summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore8
-rw-r--r--.travis.yml58
-rw-r--r--LICENSE.md2
-rw-r--r--SConstruct27
-rw-r--r--bin/tests/test_containers.cpp2
-rw-r--r--bin/tests/test_containers.h2
-rw-r--r--bin/tests/test_detailer.cpp2
-rw-r--r--bin/tests/test_detailer.h2
-rw-r--r--bin/tests/test_gdscript.cpp2
-rw-r--r--bin/tests/test_gdscript.h2
-rw-r--r--bin/tests/test_gui.cpp2
-rw-r--r--bin/tests/test_gui.h2
-rw-r--r--bin/tests/test_image.cpp2
-rw-r--r--bin/tests/test_image.h2
-rw-r--r--bin/tests/test_io.cpp2
-rw-r--r--bin/tests/test_io.h2
-rw-r--r--bin/tests/test_main.cpp2
-rw-r--r--bin/tests/test_main.h2
-rw-r--r--bin/tests/test_math.cpp2
-rw-r--r--bin/tests/test_math.h2
-rw-r--r--bin/tests/test_misc.cpp2
-rw-r--r--bin/tests/test_misc.h2
-rw-r--r--bin/tests/test_particles.cpp2
-rw-r--r--bin/tests/test_particles.h2
-rw-r--r--bin/tests/test_physics.cpp2
-rw-r--r--bin/tests/test_physics.h2
-rw-r--r--bin/tests/test_physics_2d.cpp2
-rw-r--r--bin/tests/test_physics_2d.h2
-rw-r--r--bin/tests/test_python.cpp2
-rw-r--r--bin/tests/test_python.h2
-rw-r--r--bin/tests/test_render.cpp2
-rw-r--r--bin/tests/test_render.h2
-rw-r--r--bin/tests/test_shader_lang.cpp2
-rw-r--r--bin/tests/test_shader_lang.h2
-rw-r--r--bin/tests/test_sound.cpp2
-rw-r--r--bin/tests/test_sound.h2
-rw-r--r--bin/tests/test_string.cpp2
-rw-r--r--bin/tests/test_string.h2
-rw-r--r--core/allocators.h2
-rw-r--r--core/array.cpp20
-rw-r--r--core/array.h8
-rw-r--r--core/balloon_allocator.h2
-rw-r--r--core/bind/core_bind.cpp52
-rw-r--r--core/bind/core_bind.h8
-rw-r--r--core/color.cpp2
-rw-r--r--core/color.h2
-rw-r--r--core/command_queue_mt.cpp2
-rw-r--r--core/command_queue_mt.h4
-rw-r--r--core/compressed_translation.cpp10
-rw-r--r--core/compressed_translation.h2
-rw-r--r--core/core_string_names.cpp2
-rw-r--r--core/core_string_names.h2
-rw-r--r--core/dictionary.cpp17
-rw-r--r--core/dictionary.h2
-rw-r--r--core/dvector.cpp2
-rw-r--r--core/dvector.h2
-rw-r--r--core/error_list.h2
-rw-r--r--core/error_macros.cpp2
-rw-r--r--core/error_macros.h7
-rw-r--r--core/event_queue.cpp2
-rw-r--r--core/event_queue.h2
-rw-r--r--core/fpstr.cpp2
-rw-r--r--core/fpstr.h2
-rw-r--r--core/global_constants.cpp5
-rw-r--r--core/global_constants.h2
-rw-r--r--core/globals.cpp54
-rw-r--r--core/globals.h12
-rw-r--r--core/hash_map.h2
-rw-r--r--core/hashfuncs.h2
-rw-r--r--core/image.cpp2
-rw-r--r--core/image.h2
-rw-r--r--core/image_quantize.cpp2
-rw-r--r--core/input_map.cpp60
-rw-r--r--core/input_map.h3
-rw-r--r--core/int_types.h2
-rw-r--r--core/io/aes256.cpp170
-rw-r--r--core/io/compression.cpp2
-rw-r--r--core/io/compression.h2
-rw-r--r--core/io/config_file.cpp603
-rw-r--r--core/io/config_file.h4
-rw-r--r--core/io/file_access_buffered.cpp2
-rw-r--r--core/io/file_access_buffered.h2
-rw-r--r--core/io/file_access_buffered_fa.h2
-rw-r--r--core/io/file_access_compressed.cpp2
-rw-r--r--core/io/file_access_compressed.h2
-rw-r--r--core/io/file_access_memory.cpp2
-rw-r--r--core/io/file_access_memory.h2
-rw-r--r--core/io/file_access_network.cpp6
-rw-r--r--core/io/file_access_network.h2
-rw-r--r--core/io/file_access_pack.cpp2
-rw-r--r--core/io/file_access_pack.h2
-rw-r--r--core/io/file_access_zip.cpp2
-rw-r--r--core/io/file_access_zip.h2
-rw-r--r--core/io/http_client.cpp13
-rw-r--r--core/io/http_client.h2
-rw-r--r--core/io/image_loader.cpp2
-rw-r--r--core/io/image_loader.h2
-rw-r--r--core/io/ip.cpp2
-rw-r--r--core/io/ip.h2
-rw-r--r--core/io/ip_address.cpp2
-rw-r--r--core/io/ip_address.h2
-rw-r--r--core/io/json.cpp8
-rw-r--r--core/io/json.h2
-rw-r--r--core/io/marshalls.cpp2
-rw-r--r--core/io/marshalls.h2
-rw-r--r--core/io/packet_peer.cpp4
-rw-r--r--core/io/packet_peer.h2
-rw-r--r--core/io/resource_format_binary.cpp9
-rw-r--r--core/io/resource_format_binary.h2
-rw-r--r--core/io/resource_format_xml.cpp6
-rw-r--r--core/io/resource_format_xml.h2
-rw-r--r--core/io/resource_loader.cpp2
-rw-r--r--core/io/resource_loader.h2
-rw-r--r--core/io/resource_saver.cpp2
-rw-r--r--core/io/resource_saver.h2
-rw-r--r--core/io/stream_peer.cpp301
-rw-r--r--core/io/stream_peer.h40
-rw-r--r--core/io/stream_peer_tcp.cpp2
-rw-r--r--core/io/stream_peer_tcp.h2
-rw-r--r--core/io/tcp_server.cpp2
-rw-r--r--core/io/tcp_server.h2
-rw-r--r--core/io/translation_loader_po.cpp2
-rw-r--r--core/io/translation_loader_po.h2
-rw-r--r--core/io/xml_parser.cpp14
-rw-r--r--core/io/xml_parser.h2
-rw-r--r--core/io/zip_io.h2
-rw-r--r--core/list.h2
-rw-r--r--core/map.h2
-rw-r--r--core/math/aabb.cpp2
-rw-r--r--core/math/aabb.h2
-rw-r--r--core/math/bezier_curve.cpp2
-rw-r--r--core/math/bezier_curve.h2
-rw-r--r--core/math/bsp_tree.cpp2
-rw-r--r--core/math/bsp_tree.h2
-rw-r--r--core/math/camera_matrix.cpp2
-rw-r--r--core/math/camera_matrix.h2
-rw-r--r--core/math/face3.cpp2
-rw-r--r--core/math/face3.h2
-rw-r--r--core/math/geometry.cpp2
-rw-r--r--core/math/geometry.h33
-rw-r--r--core/math/math_2d.cpp3
-rw-r--r--core/math/math_2d.h2
-rw-r--r--core/math/math_defs.cpp2
-rw-r--r--core/math/math_defs.h2
-rw-r--r--core/math/math_funcs.cpp12
-rw-r--r--core/math/math_funcs.h2
-rw-r--r--core/math/matrix3.cpp2
-rw-r--r--core/math/matrix3.h2
-rw-r--r--core/math/octree.h2
-rw-r--r--core/math/plane.cpp2
-rw-r--r--core/math/plane.h2
-rw-r--r--core/math/quat.cpp2
-rw-r--r--core/math/quat.h2
-rw-r--r--core/math/quick_hull.cpp2
-rw-r--r--core/math/quick_hull.h2
-rw-r--r--core/math/transform.cpp2
-rw-r--r--core/math/transform.h2
-rw-r--r--core/math/triangle_mesh.cpp2
-rw-r--r--core/math/triangle_mesh.h2
-rw-r--r--core/math/triangulate.cpp2
-rw-r--r--core/math/triangulate.h2
-rw-r--r--core/math/vector3.cpp2
-rw-r--r--core/math/vector3.h2
-rw-r--r--core/message_queue.cpp106
-rw-r--r--core/message_queue.h9
-rw-r--r--core/method_bind.cpp2
-rw-r--r--core/method_bind.h2
-rw-r--r--core/multi_bucket_array.h2
-rw-r--r--core/object.cpp228
-rw-r--r--core/object.h5
-rw-r--r--core/object_type_db.cpp41
-rw-r--r--core/object_type_db.h6
-rw-r--r--core/os/copymem.cpp2
-rw-r--r--core/os/copymem.h2
-rw-r--r--core/os/dir_access.cpp2
-rw-r--r--core/os/dir_access.h2
-rw-r--r--core/os/file_access.cpp2
-rw-r--r--core/os/file_access.h3
-rw-r--r--core/os/input.cpp10
-rw-r--r--core/os/input.h9
-rw-r--r--core/os/input_event.cpp3
-rw-r--r--core/os/input_event.h5
-rw-r--r--core/os/keyboard.cpp2
-rw-r--r--core/os/keyboard.h2
-rw-r--r--core/os/main_loop.cpp2
-rw-r--r--core/os/main_loop.h2
-rw-r--r--core/os/memory.cpp2
-rw-r--r--core/os/memory.h2
-rw-r--r--core/os/memory_pool_dynamic.cpp2
-rw-r--r--core/os/memory_pool_dynamic.h2
-rw-r--r--core/os/memory_pool_dynamic_prealloc.cpp2
-rw-r--r--core/os/memory_pool_dynamic_prealloc.h2
-rw-r--r--core/os/memory_pool_dynamic_static.cpp2
-rw-r--r--core/os/memory_pool_dynamic_static.h2
-rw-r--r--core/os/memory_pool_static.cpp2
-rw-r--r--core/os/memory_pool_static.h2
-rw-r--r--core/os/mutex.cpp2
-rw-r--r--core/os/mutex.h2
-rw-r--r--core/os/os.cpp20
-rw-r--r--core/os/os.h14
-rw-r--r--core/os/pc_joystick_map.h2
-rw-r--r--core/os/semaphore.cpp2
-rw-r--r--core/os/semaphore.h2
-rw-r--r--core/os/shell.cpp2
-rw-r--r--core/os/shell.h2
-rw-r--r--core/os/thread.cpp7
-rw-r--r--core/os/thread.h6
-rw-r--r--core/os/thread_dummy.cpp2
-rw-r--r--core/os/thread_dummy.h2
-rw-r--r--core/os/thread_safe.cpp2
-rw-r--r--core/os/thread_safe.h2
-rw-r--r--core/packed_data_container.cpp2
-rw-r--r--core/packed_data_container.h2
-rw-r--r--core/pair.cpp2
-rw-r--r--core/pair.h2
-rw-r--r--core/path_db.cpp2
-rw-r--r--core/path_db.h2
-rw-r--r--core/path_remap.cpp2
-rw-r--r--core/path_remap.h2
-rw-r--r--core/pool_allocator.cpp2
-rw-r--r--core/pool_allocator.h2
-rw-r--r--core/print_string.cpp4
-rw-r--r--core/print_string.h2
-rw-r--r--core/ref_ptr.cpp2
-rw-r--r--core/ref_ptr.h2
-rw-r--r--core/reference.cpp2
-rw-r--r--core/reference.h2
-rw-r--r--core/register_core_types.cpp4
-rw-r--r--core/register_core_types.h2
-rw-r--r--core/res_ptr.cpp2
-rw-r--r--core/res_ptr.h2
-rw-r--r--core/resource.cpp4
-rw-r--r--core/resource.h4
-rw-r--r--core/rid.cpp2
-rw-r--r--core/rid.h2
-rw-r--r--core/ring_buffer.h8
-rw-r--r--core/safe_refcount.cpp2
-rw-r--r--core/safe_refcount.h2
-rw-r--r--core/script_debugger_debugger.cpp2
-rw-r--r--core/script_debugger_local.cpp2
-rw-r--r--core/script_debugger_local.h2
-rw-r--r--core/script_debugger_remote.cpp11
-rw-r--r--core/script_debugger_remote.h2
-rw-r--r--core/script_language.cpp32
-rw-r--r--core/script_language.h9
-rw-r--r--core/self_list.h2
-rw-r--r--core/set.h2
-rw-r--r--core/simple_type.h2
-rw-r--r--core/sort.h2
-rw-r--r--core/string_db.cpp2
-rw-r--r--core/string_db.h2
-rw-r--r--core/translation.cpp10
-rw-r--r--core/translation.h2
-rw-r--r--core/typedefs.h14
-rw-r--r--core/undo_redo.cpp6
-rw-r--r--core/undo_redo.h2
-rw-r--r--core/ustring.cpp49
-rw-r--r--core/ustring.h5
-rw-r--r--core/variant.cpp159
-rw-r--r--core/variant.h10
-rw-r--r--core/variant_call.cpp25
-rw-r--r--core/variant_call_bind.h2
-rw-r--r--core/variant_op.cpp38
-rw-r--r--core/variant_parser.cpp738
-rw-r--r--core/variant_parser.h42
-rw-r--r--core/vector.h40
-rw-r--r--core/vmap.cpp2
-rw-r--r--core/vmap.h2
-rw-r--r--core/vset.cpp2
-rw-r--r--core/vset.h2
-rw-r--r--demos/2d/area_input/input.gd17
-rw-r--r--demos/2d/area_input/input.scnbin2886 -> 3118 bytes
-rw-r--r--demos/2d/dynamic_collision_shapes/ball.gd18
-rw-r--r--demos/2d/dynamic_collision_shapes/ball.scnbin1898 -> 1857 bytes
-rw-r--r--demos/2d/dynamic_collision_shapes/dynamic_colobjs.gd24
-rw-r--r--demos/2d/dynamic_collision_shapes/dynamic_colobjs.scnbin4348 -> 4399 bytes
-rw-r--r--demos/2d/fog_of_war/fog.gd92
-rw-r--r--demos/2d/fog_of_war/fog.scnbin3714 -> 4159 bytes
-rw-r--r--demos/2d/fog_of_war/tile_edit.scnbin1443 -> 1570 bytes
-rw-r--r--demos/2d/fog_of_war/troll.gd33
-rw-r--r--demos/2d/fog_of_war/troll.scnbin1839 -> 1979 bytes
-rw-r--r--demos/2d/hdr/beach_cave.gd29
-rw-r--r--demos/2d/hdr/beach_cave.scnbin2972 -> 4834 bytes
-rw-r--r--demos/2d/hexamap/map.scnbin2644 -> 3517 bytes
-rw-r--r--demos/2d/hexamap/tiles.scnbin2091 -> 2217 bytes
-rw-r--r--demos/2d/hexamap/troll.gd31
-rw-r--r--demos/2d/hexamap/troll.scnbin1839 -> 1983 bytes
-rw-r--r--demos/2d/isometric/dungeon.scnbin8743 -> 4708 bytes
-rw-r--r--demos/2d/isometric/tileset.scnbin2565 -> 4476 bytes
-rw-r--r--demos/2d/isometric/troll.gd31
-rw-r--r--demos/2d/isometric/troll.scnbin2100 -> 2116 bytes
-rw-r--r--demos/2d/isometric_light/column.scnbin1909 -> 2026 bytes
-rw-r--r--demos/2d/isometric_light/cubio.gd117
-rw-r--r--demos/2d/isometric_light/cubio.scnbin7006 -> 6952 bytes
-rw-r--r--demos/2d/isometric_light/map.gd15
-rw-r--r--demos/2d/isometric_light/map.scnbin8661 -> 9352 bytes
-rw-r--r--demos/2d/isometric_light/shoot.gd20
-rw-r--r--demos/2d/isometric_light/shoot.scnbin4561 -> 4111 bytes
-rw-r--r--demos/2d/isometric_light/tileset_scene.scnbin4812 -> 5339 bytes
-rw-r--r--demos/2d/isometric_light/torch.scnbin4416 -> 3861 bytes
-rw-r--r--demos/2d/kinematic_char/colworld.gd16
-rw-r--r--demos/2d/kinematic_char/colworld.scnbin7459 -> 7366 bytes
-rw-r--r--demos/2d/kinematic_char/engine.cfg2
-rw-r--r--demos/2d/kinematic_char/player.gd168
-rw-r--r--demos/2d/kinematic_char/player.scnbin1728 -> 1703 bytes
-rw-r--r--demos/2d/kinematic_col/colworld.scnbin2941 -> 4073 bytes
-rw-r--r--demos/2d/kinematic_col/player.gd23
-rw-r--r--demos/2d/kinematic_col/player.scnbin1495 -> 1625 bytes
-rw-r--r--demos/2d/light_mask/lightmask.scnbin2916 -> 3829 bytes
-rw-r--r--demos/2d/lights_shadows/light_shadows.scnbin7181 -> 4978 bytes
-rw-r--r--demos/2d/lookat/lookat.gd38
-rw-r--r--demos/2d/lookat/lookat.scnbin1622 -> 1640 bytes
-rw-r--r--demos/2d/motion/motion.gd35
-rw-r--r--demos/2d/motion/motion.scnbin2845 -> 2738 bytes
-rw-r--r--demos/2d/navpoly/navigation.gd64
-rw-r--r--demos/2d/navpoly/navigation.scnbin3456 -> 5128 bytes
-rw-r--r--demos/2d/navpoly/navigation2.scnbin3564 -> 0 bytes
-rw-r--r--demos/2d/normalmaps/normalmap.scnbin2450 -> 3168 bytes
-rw-r--r--demos/2d/particles/particles.xml265
-rw-r--r--demos/2d/platformer/bullet.gd13
-rw-r--r--demos/2d/platformer/bullet.xml273
-rw-r--r--demos/2d/platformer/coin.gd19
-rw-r--r--demos/2d/platformer/coin.xml293
-rw-r--r--demos/2d/platformer/enemy.gd91
-rw-r--r--demos/2d/platformer/enemy.xml98
-rw-r--r--demos/2d/platformer/moving_platform.gd21
-rw-r--r--demos/2d/platformer/moving_platform.xml214
-rw-r--r--demos/2d/platformer/one_way_platform.xml67
-rw-r--r--demos/2d/platformer/parallax_bg.xml258
-rw-r--r--demos/2d/platformer/player.gd237
-rw-r--r--demos/2d/platformer/player.xml202
-rw-r--r--demos/2d/platformer/seesaw.xml207
-rw-r--r--demos/2d/platformer/stage.xml843
-rw-r--r--demos/2d/platformer/tileset_edit.xml213
-rw-r--r--demos/2d/pong/pong.gd82
-rw-r--r--demos/2d/pong/pong.xml206
-rw-r--r--demos/2d/rubegoldberg/ball.xml210
-rw-r--r--demos/2d/rubegoldberg/box.xml242
-rw-r--r--demos/2d/rubegoldberg/domino.xml244
-rw-r--r--demos/2d/rubegoldberg/pendulum.xml210
-rw-r--r--demos/2d/rubegoldberg/platform.xml188
-rw-r--r--demos/2d/rubegoldberg/rubegoldberg.xml181
-rw-r--r--demos/2d/rubegoldberg/seesaw.xml266
-rw-r--r--demos/2d/screen_space_shaders/screen_shaders.gd19
-rw-r--r--demos/2d/screen_space_shaders/screen_shaders.scnbin5936 -> 7562 bytes
-rw-r--r--demos/2d/sdf_font/sdf.scnbin2415 -> 2820 bytes
-rw-r--r--demos/2d/shower_of_bullets/bullets.gd59
-rw-r--r--demos/2d/shower_of_bullets/shower.gd29
-rw-r--r--demos/2d/shower_of_bullets/shower.scnbin1836 -> 1909 bytes
-rw-r--r--demos/2d/space_shooter/asteroid.gd42
-rw-r--r--demos/2d/space_shooter/asteroid.scnbin4516 -> 3548 bytes
-rw-r--r--demos/2d/space_shooter/enemy1.gd29
-rw-r--r--demos/2d/space_shooter/enemy1.scnbin3759 -> 3369 bytes
-rw-r--r--demos/2d/space_shooter/enemy2.gd51
-rw-r--r--demos/2d/space_shooter/enemy2.scnbin3801 -> 3253 bytes
-rw-r--r--demos/2d/space_shooter/enemy_shot.gd19
-rw-r--r--demos/2d/space_shooter/enemy_shot.scnbin3944 -> 3218 bytes
-rw-r--r--demos/2d/space_shooter/explosion.scnbin1497 -> 1756 bytes
-rw-r--r--demos/2d/space_shooter/game_state.gd20
-rw-r--r--demos/2d/space_shooter/level.scnbin9185 -> 6496 bytes
-rw-r--r--demos/2d/space_shooter/level_tiles.scnbin2168 -> 1825 bytes
-rw-r--r--demos/2d/space_shooter/main_menu.gd13
-rw-r--r--demos/2d/space_shooter/main_menu.scnbin2402 -> 1903 bytes
-rw-r--r--demos/2d/space_shooter/parallax.scnbin3307 -> 2814 bytes
-rw-r--r--demos/2d/space_shooter/rail.gd18
-rw-r--r--demos/2d/space_shooter/ship.gd65
-rw-r--r--demos/2d/space_shooter/ship.scnbin6752 -> 4965 bytes
-rw-r--r--demos/2d/space_shooter/shot.gd34
-rw-r--r--demos/2d/space_shooter/shot.scnbin4079 -> 3315 bytes
-rw-r--r--demos/2d/splash/splash.xml338
-rw-r--r--demos/2d/sprite_shaders/sprite_shaders.scnbin4079 -> 5477 bytes
-rw-r--r--demos/2d/tetris/grid.gd219
-rw-r--r--demos/2d/tetris/grid.xml252
-rw-r--r--demos/2d/tetris/tetris.xml252
-rw-r--r--demos/2d/texscreen/bubbles.gd10
-rw-r--r--demos/2d/texscreen/bubbles.scnbin1551 -> 2626 bytes
-rw-r--r--demos/2d/texscreen/lens.gd45
-rw-r--r--demos/2d/texscreen/lens.scnbin1805 -> 1850 bytes
-rw-r--r--demos/3d/fixed_materials/fixed_materials.scnbin6071 -> 8271 bytes
-rw-r--r--demos/3d/kinematic_char/cubio.gd91
-rw-r--r--demos/3d/kinematic_char/follow_camera.gd62
-rw-r--r--demos/3d/kinematic_char/level.scnbin15523 -> 18847 bytes
-rw-r--r--demos/3d/kinematic_char/purplecube.scnbin9808 -> 7927 bytes
-rw-r--r--demos/3d/mousepick_test/mousepick.gd22
-rw-r--r--demos/3d/mousepick_test/mousepick.scnbin38194 -> 40434 bytes
-rw-r--r--demos/3d/navmesh/navmesh.gd103
-rw-r--r--demos/3d/navmesh/navmesh.scnbin38129 -> 40827 bytes
-rw-r--r--demos/3d/platformer/bullet.gd13
-rw-r--r--demos/3d/platformer/bullet.scnbin6157 -> 7303 bytes
-rw-r--r--demos/3d/platformer/coin.gd18
-rw-r--r--demos/3d/platformer/coin.scnbin6791 -> 7785 bytes
-rw-r--r--demos/3d/platformer/enemy.gd57
-rw-r--r--demos/3d/platformer/enemy.scnbin38594 -> 39181 bytes
-rw-r--r--demos/3d/platformer/engine.cfg4
-rw-r--r--demos/3d/platformer/follow_camera.gd89
-rw-r--r--demos/3d/platformer/player.gd210
-rw-r--r--demos/3d/platformer/player.scnbin0 -> 107922 bytes
-rw-r--r--demos/3d/platformer/player.xml1762
-rw-r--r--demos/3d/platformer/robotrigged.scnbin107962 -> 110973 bytes
-rw-r--r--demos/3d/platformer/stage.scnbin0 -> 17714 bytes
-rw-r--r--demos/3d/platformer/stage.xml697
-rw-r--r--demos/3d/platformer/tiles.scnbin47723 -> 23305 bytes
-rw-r--r--demos/3d/polygon_path_finder/engine.cfg (renamed from demos/2d/polygon_path_finder/engine.cfg)0
-rw-r--r--demos/3d/polygon_path_finder/icon.png (renamed from demos/2d/polygon_path_finder/icon.png)bin712 -> 712 bytes
-rw-r--r--demos/3d/polygon_path_finder/poly_with_holes.scn (renamed from demos/2d/polygon_path_finder/poly_with_holes.scn)bin2974 -> 2974 bytes
-rw-r--r--demos/3d/polygon_path_finder/polygonpathfinder.gd (renamed from demos/2d/polygon_path_finder/polygonpathfinder.gd)49
-rw-r--r--demos/3d/sat_test/box.scnbin23739 -> 27363 bytes
-rw-r--r--demos/3d/sat_test/capsule.scnbin21133 -> 22718 bytes
-rw-r--r--demos/3d/sat_test/convex.scnbin22828 -> 25617 bytes
-rw-r--r--demos/3d/sat_test/engine.cfg2
-rw-r--r--demos/3d/sat_test/sat_test.scnbin0 -> 3430 bytes
-rw-r--r--demos/3d/sat_test/sat_test.xml179
-rw-r--r--demos/3d/sat_test/shapes.scnbin23064 -> 25887 bytes
-rw-r--r--demos/3d/sat_test/sphere.scnbin38627 -> 41375 bytes
-rw-r--r--demos/3d/shader_materials/shader_materials.scnbin6382 -> 9892 bytes
-rw-r--r--demos/3d/truck_town/car_base.scnbin11573 -> 13459 bytes
-rw-r--r--demos/3d/truck_town/car_select.gd20
-rw-r--r--demos/3d/truck_town/car_select.scnbin1702 -> 1968 bytes
-rw-r--r--demos/3d/truck_town/crane.scnbin24164 -> 26350 bytes
-rw-r--r--demos/3d/truck_town/follow_camera.gd58
-rw-r--r--demos/3d/truck_town/trailer_truck.scnbin19934 -> 22400 bytes
-rw-r--r--demos/3d/truck_town/truck_scene.scnbin1873575 -> 1889480 bytes
-rw-r--r--demos/3d/truck_town/trucktown.scnbin161749 -> 165689 bytes
-rw-r--r--demos/3d/truck_town/vehicle.gd43
-rw-r--r--demos/gui/drag_and_drop/drag_and_drop.scnbin2594 -> 2947 bytes
-rw-r--r--demos/gui/drag_and_drop/drag_drop_script.gd18
-rw-r--r--demos/gui/input_mapping/controls.gd9
-rw-r--r--demos/gui/input_mapping/controls.scnbin2686 -> 2698 bytes
-rw-r--r--demos/gui/rich_text_bbcode/rich_text_bbcode.gd13
-rw-r--r--demos/gui/rich_text_bbcode/rich_text_bbcode.scnbin3288 -> 3217 bytes
-rw-r--r--demos/gui/translation/controls.gd11
-rw-r--r--demos/gui/translation/controls.scnbin2349 -> 2272 bytes
-rw-r--r--demos/gui/translation/main.gd18
-rw-r--r--demos/gui/translation/main.scnbin2671 -> 2939 bytes
-rw-r--r--demos/misc/autoload/global.gd41
-rw-r--r--demos/misc/autoload/scene_a.gd12
-rw-r--r--demos/misc/autoload/scene_a.scnbin1459 -> 1660 bytes
-rw-r--r--demos/misc/autoload/scene_b.gd12
-rw-r--r--demos/misc/autoload/scene_b.scnbin1448 -> 1639 bytes
-rw-r--r--demos/misc/instancing/ball.scnbin1563 -> 1885 bytes
-rw-r--r--demos/misc/instancing/container.scnbin2312 -> 3137 bytes
-rw-r--r--demos/misc/joysticks/diagram.pngbin0 -> 171519 bytes
-rw-r--r--demos/misc/joysticks/engine.cfg2
-rw-r--r--demos/misc/joysticks/indicators.pngbin0 -> 1069 bytes
-rw-r--r--demos/misc/joysticks/joysticks.gd49
-rw-r--r--demos/misc/joysticks/joysticks.scnbin3809 -> 4356 bytes
-rw-r--r--demos/misc/joysticks/jsdiagram.xscn115
-rw-r--r--demos/misc/pause/spinpause.gd2
-rw-r--r--demos/misc/pause/spinpause.scnbin3331 -> 5399 bytes
-rw-r--r--demos/misc/regex/regex.gd6
-rw-r--r--demos/misc/regex/regex.scnbin1793 -> 1775 bytes
-rw-r--r--demos/misc/scene_changer/scene_a.gd7
-rw-r--r--demos/misc/scene_changer/scene_a.scnbin1459 -> 1660 bytes
-rw-r--r--demos/misc/scene_changer/scene_b.gd7
-rw-r--r--demos/misc/scene_changer/scene_b.scnbin1448 -> 1639 bytes
-rw-r--r--demos/misc/threads/thread.gd26
-rw-r--r--demos/misc/threads/thread.scnbin1638 -> 1586 bytes
-rw-r--r--demos/misc/tween/engine.cfg2
-rw-r--r--demos/misc/tween/main.gd53
-rw-r--r--demos/misc/tween/main.scnbin0 -> 5216 bytes
-rw-r--r--demos/misc/tween/main.xml367
-rw-r--r--demos/misc/udp_chat/chat.gd46
-rw-r--r--demos/misc/udp_chat/chat.scnbin3198 -> 3359 bytes
-rw-r--r--demos/misc/window_management/control.gd85
-rw-r--r--demos/misc/window_management/observer/observer.gd31
-rw-r--r--demos/misc/window_management/observer/observer.scnbin1786 -> 3824 bytes
-rw-r--r--demos/misc/window_management/window_management.scnbin5132 -> 4384 bytes
-rw-r--r--demos/viewport/2d_in_3d/pong.gd81
-rw-r--r--demos/viewport/2d_in_3d/pong.scnbin0 -> 1417 bytes
-rw-r--r--demos/viewport/2d_in_3d/pong.xml183
-rw-r--r--demos/viewport/2d_in_3d/pong3d.gd9
-rw-r--r--demos/viewport/2d_in_3d/pong3d.scnbin3412 -> 5236 bytes
-rw-r--r--demos/viewport/3d_in_2d/main.scnbin1438 -> 1685 bytes
-rw-r--r--demos/viewport/3d_in_2d/player.scnbin105180 -> 107246 bytes
-rw-r--r--demos/viewport/3d_in_2d/player.xml1736
-rw-r--r--demos/viewport/3d_in_2d/player_2d.scnbin1576 -> 1834 bytes
-rw-r--r--demos/viewport/3d_in_2d/player_3d.scnbin1448 -> 1688 bytes
-rw-r--r--demos/viewport/gui_in_3d/gui.scnbin2270 -> 2579 bytes
-rw-r--r--demos/viewport/gui_in_3d/gui_3d.gd70
-rw-r--r--demos/viewport/gui_in_3d/gui_3d.scnbin4668 -> 6137 bytes
-rw-r--r--demos/viewport/screen_capture/screen_capture.gd23
-rw-r--r--demos/viewport/screen_capture/screen_capture.scnbin1977 -> 3482 bytes
-rw-r--r--doc/Doxyfile (renamed from Doxyfile)6
-rw-r--r--doc/Makefile47
-rw-r--r--doc/base/classes.xml1253
-rw-r--r--doc/core_classes.xml2654
-rw-r--r--doc/deferred_format.txt33
-rw-r--r--doc/demos.txt40
-rw-r--r--doc/engine_classes.xml17940
-rw-r--r--doc/examples/physics/script/test_base.sq295
-rw-r--r--doc/examples/physics/script/test_fall.sq42
-rw-r--r--doc/gdscript.lyx2531
-rw-r--r--doc/godot_splash.pngbin9801 -> 0 bytes
-rw-r--r--doc/header.txt12
-rw-r--r--doc/html/@GDScript.html93
-rw-r--r--doc/html/@Global Scope.html459
-rw-r--r--doc/html/@Squirrel.html2
-rw-r--r--doc/html/tutorial01/0_home_red_coding_godot_doc_math_position.pngbin1679 -> 0 bytes
-rw-r--r--doc/html/tutorial01/1_home_red_coding_godot_doc_math_direction.pngbin3600 -> 0 bytes
-rw-r--r--doc/html/tutorial01/2_home_red_coding_godot_doc_math_normals.pngbin2452 -> 0 bytes
-rw-r--r--doc/html/tutorial01/tutorial.css128
-rw-r--r--doc/html/tutorial01/tutorial.html902
-rw-r--r--doc/html/tutorial01/tutorial0x.pngbin2056 -> 0 bytes
-rw-r--r--doc/html/tutorial01/tutorial1x.pngbin4122 -> 0 bytes
-rw-r--r--doc/html/tutorial01/tutorial2x.pngbin618 -> 0 bytes
-rw-r--r--doc/html/tutorial01/tutorial3x.pngbin754 -> 0 bytes
-rw-r--r--doc/html/tutorial01/tutorial4x.pngbin2961 -> 0 bytes
-rw-r--r--doc/make_doc.sh17
-rw-r--r--doc/notes.txt20
-rw-r--r--doc/phys_engine.pngbin29177 -> 0 bytes
-rw-r--r--doc/squirrel.lyx984
-rw-r--r--doc/todo.txt39
-rw-r--r--doc/tools/doc_merge.py (renamed from tools/docdump/doc_merge.py)3
-rw-r--r--doc/tools/locales/es/LC_MESSAGES/makedocs.mo (renamed from tools/docdump/locales/es/LC_MESSAGES/makedocs.mo)bin2321 -> 2321 bytes
-rw-r--r--doc/tools/locales/es/LC_MESSAGES/makedocs.po (renamed from tools/docdump/locales/es/LC_MESSAGES/makedocs.po)0
-rw-r--r--doc/tools/main.css (renamed from doc/html/main.css)0
-rw-r--r--doc/tools/makedocs.pot (renamed from tools/docdump/makedocs.pot)0
-rw-r--r--doc/tools/makedocs.py (renamed from tools/docdump/makedocs.py)4
-rw-r--r--doc/tools/makedoku.py (renamed from tools/docdump/makedoku.py)5
-rw-r--r--doc/tools/makehtml.py (renamed from tools/docdump/makehtml.py)5
-rw-r--r--doc/tools/makemd.py (renamed from tools/docdump/makemd.py)3
-rw-r--r--doc/tutorial/01 Getting Started.lyx557
-rw-r--r--doc/tutorial/editor.pngbin81238 -> 0 bytes
-rw-r--r--doc/tutorial/pm.pngbin36586 -> 0 bytes
-rw-r--r--doc/tutorial/pmc.pngbin22446 -> 0 bytes
-rw-r--r--doc/tutorial/tute1_1.pngbin8719 -> 0 bytes
-rw-r--r--doc/tutorial/tute1_2.pngbin12907 -> 0 bytes
-rw-r--r--doc/tutorial/tute1_2b.pngbin3154 -> 0 bytes
-rw-r--r--doc/tutorial/tute1_3a.pngbin6660 -> 0 bytes
-rw-r--r--doc/tutorial/tute1_3b.pngbin27956 -> 0 bytes
-rw-r--r--doc/tutorial/tute1_3c.pngbin3785 -> 0 bytes
-rw-r--r--doc/tutorial/tute1_4a.pngbin17321 -> 0 bytes
-rw-r--r--doc/tutorial/tute1_4b.pngbin5421 -> 0 bytes
-rw-r--r--doc/tutorial/tute1_5a.pngbin25190 -> 0 bytes
-rw-r--r--doc/tutorial/tute1_5b.pngbin47382 -> 0 bytes
-rw-r--r--doc/tutorial/tute1_6.pngbin2555 -> 0 bytes
-rw-r--r--doc/tutorial/tute1_7.pngbin1445 -> 0 bytes
-rw-r--r--doc/undoredoapi.txt25
-rw-r--r--drivers/SCsub67
-rw-r--r--drivers/alsa/audio_driver_alsa.cpp2
-rw-r--r--drivers/alsa/audio_driver_alsa.h2
-rw-r--r--drivers/chibi/cp_config.h2
-rw-r--r--drivers/chibi/cp_envelope.cpp2
-rw-r--r--drivers/chibi/cp_envelope.h2
-rw-r--r--drivers/chibi/cp_file_access_wrapper.cpp2
-rw-r--r--drivers/chibi/cp_file_access_wrapper.h2
-rw-r--r--drivers/chibi/cp_instrument.cpp2
-rw-r--r--drivers/chibi/cp_instrument.h2
-rw-r--r--drivers/chibi/cp_loader.h2
-rw-r--r--drivers/chibi/cp_loader_it.cpp2
-rw-r--r--drivers/chibi/cp_loader_it.h2
-rw-r--r--drivers/chibi/cp_loader_it_info.cpp2
-rw-r--r--drivers/chibi/cp_loader_it_instruments.cpp2
-rw-r--r--drivers/chibi/cp_loader_it_patterns.cpp2
-rw-r--r--drivers/chibi/cp_loader_it_samples.cpp2
-rw-r--r--drivers/chibi/cp_loader_mod.cpp11
-rw-r--r--drivers/chibi/cp_loader_mod.h2
-rw-r--r--drivers/chibi/cp_loader_s3m.cpp22
-rw-r--r--drivers/chibi/cp_loader_s3m.h2
-rw-r--r--drivers/chibi/cp_loader_xm.cpp18
-rw-r--r--drivers/chibi/cp_loader_xm.h2
-rw-r--r--drivers/chibi/cp_mixer.h2
-rw-r--r--drivers/chibi/cp_note.h2
-rw-r--r--drivers/chibi/cp_order.h2
-rw-r--r--drivers/chibi/cp_pattern.cpp2
-rw-r--r--drivers/chibi/cp_pattern.h2
-rw-r--r--drivers/chibi/cp_player_data.cpp2
-rw-r--r--drivers/chibi/cp_player_data.h2
-rw-r--r--drivers/chibi/cp_player_data_control.cpp2
-rw-r--r--drivers/chibi/cp_player_data_effects.cpp2
-rw-r--r--drivers/chibi/cp_player_data_envelopes.cpp2
-rw-r--r--drivers/chibi/cp_player_data_events.cpp2
-rw-r--r--drivers/chibi/cp_player_data_filter.cpp2
-rw-r--r--drivers/chibi/cp_player_data_nna.cpp2
-rw-r--r--drivers/chibi/cp_player_data_notes.cpp2
-rw-r--r--drivers/chibi/cp_player_data_reserved.cpp2
-rw-r--r--drivers/chibi/cp_player_data_utils.cpp2
-rw-r--r--drivers/chibi/cp_sample.cpp2
-rw-r--r--drivers/chibi/cp_sample.h2
-rw-r--r--drivers/chibi/cp_sample_defs.h2
-rw-r--r--drivers/chibi/cp_sample_manager.cpp2
-rw-r--r--drivers/chibi/cp_sample_manager.h2
-rw-r--r--drivers/chibi/cp_song.cpp2
-rw-r--r--drivers/chibi/cp_song.h2
-rw-r--r--drivers/chibi/cp_tables.cpp2
-rw-r--r--drivers/chibi/cp_tables.h2
-rw-r--r--drivers/chibi/event_stream_chibi.cpp2
-rw-r--r--drivers/chibi/event_stream_chibi.h2
-rw-r--r--drivers/convex_decomp/b2Polygon.cpp4
-rw-r--r--drivers/gl_context/context_gl.cpp2
-rw-r--r--drivers/gl_context/context_gl.h2
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp129
-rw-r--r--drivers/gles2/rasterizer_gles2.h8
-rw-r--r--drivers/gles2/rasterizer_instance_gles2.cpp2
-rw-r--r--drivers/gles2/rasterizer_instance_gles2.h2
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp2
-rw-r--r--drivers/gles2/shader_compiler_gles2.h2
-rw-r--r--drivers/gles2/shader_gles2.cpp6
-rw-r--r--drivers/gles2/shader_gles2.h7
-rw-r--r--drivers/gles2/shaders/canvas.glsl25
-rw-r--r--drivers/jpegd/SCsub (renamed from drivers/jpg/SCsub)5
-rw-r--r--drivers/jpegd/image_loader_jpegd.cpp108
-rw-r--r--drivers/jpegd/image_loader_jpegd.h (renamed from drivers/jpg/image_loader_jpg.h)2
-rw-r--r--drivers/jpegd/jpgd.cpp3172
-rw-r--r--drivers/jpegd/jpgd.h319
-rw-r--r--drivers/jpg/image_loader_jpg.cpp93
-rw-r--r--drivers/jpg/jidctflt.c286
-rw-r--r--drivers/jpg/loadjpeg.c341
-rw-r--r--drivers/jpg/tinyjpeg-internal.h162
-rw-r--r--drivers/jpg/tinyjpeg.c2202
-rw-r--r--drivers/jpg/tinyjpeg.h74
-rw-r--r--drivers/nedmalloc/memory_pool_static_nedmalloc.cpp2
-rw-r--r--drivers/nedmalloc/memory_pool_static_nedmalloc.h2
-rw-r--r--drivers/nrex/README.md4
-rw-r--r--drivers/nrex/nrex.cpp101
-rw-r--r--drivers/nrex/nrex.hpp41
-rw-r--r--drivers/nrex/regex.cpp8
-rw-r--r--drivers/nrex/regex.h4
-rw-r--r--drivers/openssl/stream_peer_openssl.cpp7
-rw-r--r--drivers/openssl/stream_peer_openssl.h2
-rw-r--r--drivers/opus/audio_stream_opus.cpp2
-rw-r--r--drivers/opus/audio_stream_opus.h2
-rw-r--r--drivers/png/SCsub9
-rw-r--r--drivers/png/arm/arm_init.c232
-rw-r--r--drivers/png/arm/filter_neon.S (renamed from drivers/png/filter_neon.S)12
-rw-r--r--drivers/png/example.c85
-rw-r--r--drivers/png/image_loader_png.cpp9
-rw-r--r--drivers/png/image_loader_png.h2
-rw-r--r--drivers/png/png.c398
-rw-r--r--drivers/png/png.h490
-rw-r--r--drivers/png/pngconf.h72
-rw-r--r--drivers/png/pngdebug.h22
-rw-r--r--drivers/png/pngerror.c80
-rw-r--r--drivers/png/pngget.c64
-rw-r--r--drivers/png/pnginfo.h7
-rw-r--r--drivers/png/pnglibconf.h164
-rw-r--r--drivers/png/pngmem.c12
-rw-r--r--drivers/png/pngpread.c695
-rw-r--r--drivers/png/pngpriv.h236
-rw-r--r--drivers/png/pngread.c50
-rw-r--r--drivers/png/pngrio.c4
-rw-r--r--drivers/png/pngrtran.c228
-rw-r--r--drivers/png/pngrutil.c245
-rw-r--r--drivers/png/pngset.c283
-rw-r--r--drivers/png/pngstruct.h39
-rw-r--r--drivers/png/pngtrans.c115
-rw-r--r--drivers/png/pngwio.c6
-rw-r--r--drivers/png/pngwrite.c427
-rw-r--r--drivers/png/pngwtran.c20
-rw-r--r--drivers/png/pngwutil.c620
-rw-r--r--drivers/png/resource_saver_png.cpp2
-rw-r--r--drivers/pnm/SCsub10
-rw-r--r--drivers/pnm/bitmap_loader_pnm.cpp235
-rw-r--r--drivers/pnm/bitmap_loader_pnm.h33
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp2
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.h2
-rw-r--r--drivers/register_driver_types.cpp12
-rw-r--r--drivers/register_driver_types.h2
-rw-r--r--drivers/rtaudio/RtAudio.cpp6
-rw-r--r--drivers/rtaudio/audio_driver_rtaudio.cpp2
-rw-r--r--drivers/rtaudio/audio_driver_rtaudio.h2
-rw-r--r--drivers/theora/video_stream_theora.cpp159
-rw-r--r--drivers/theora/video_stream_theora.h35
-rw-r--r--drivers/unix/SCsub10
-rw-r--r--drivers/unix/dir_access_unix.cpp2
-rw-r--r--drivers/unix/dir_access_unix.h2
-rw-r--r--drivers/unix/file_access_unix.cpp4
-rw-r--r--drivers/unix/file_access_unix.h2
-rw-r--r--drivers/unix/ip_unix.cpp2
-rw-r--r--drivers/unix/ip_unix.h2
-rw-r--r--drivers/unix/memory_pool_static_malloc.cpp2
-rw-r--r--drivers/unix/memory_pool_static_malloc.h2
-rw-r--r--drivers/unix/mutex_posix.cpp2
-rw-r--r--drivers/unix/mutex_posix.h2
-rw-r--r--drivers/unix/os_unix.cpp22
-rw-r--r--drivers/unix/os_unix.h7
-rw-r--r--drivers/unix/semaphore_posix.cpp4
-rw-r--r--drivers/unix/semaphore_posix.h2
-rw-r--r--drivers/unix/stream_peer_tcp_posix.cpp11
-rw-r--r--drivers/unix/stream_peer_tcp_posix.h4
-rw-r--r--drivers/unix/tcp_server_posix.cpp2
-rw-r--r--drivers/unix/tcp_server_posix.h2
-rw-r--r--drivers/unix/thread_posix.cpp44
-rw-r--r--drivers/unix/thread_posix.h3
-rw-r--r--drivers/vorbis/audio_stream_ogg_vorbis.cpp2
-rw-r--r--drivers/vorbis/audio_stream_ogg_vorbis.h2
-rw-r--r--drivers/webp/SCsub158
-rw-r--r--drivers/webp/config.h145
-rw-r--r--drivers/webp/dec/alpha.c205
-rw-r--r--drivers/webp/dec/alphai.h55
-rw-r--r--drivers/webp/dec/buffer.c99
-rw-r--r--drivers/webp/dec/common.h54
-rw-r--r--drivers/webp/dec/decode_vp8.h17
-rw-r--r--drivers/webp/dec/frame.c665
-rw-r--r--drivers/webp/dec/idec.c307
-rw-r--r--drivers/webp/dec/io.c269
-rw-r--r--drivers/webp/dec/quant.c17
-rw-r--r--drivers/webp/dec/tree.c182
-rw-r--r--drivers/webp/dec/vp8.c493
-rw-r--r--drivers/webp/dec/vp8i.h218
-rw-r--r--drivers/webp/dec/vp8l.c1095
-rw-r--r--drivers/webp/dec/vp8li.h53
-rw-r--r--drivers/webp/dec/webp.c220
-rw-r--r--drivers/webp/dec/webpi.h35
-rw-r--r--drivers/webp/decode.h164
-rw-r--r--drivers/webp/demux.h364
-rw-r--r--drivers/webp/demux/anim_decode.c442
-rw-r--r--drivers/webp/demux/demux.c957
-rw-r--r--drivers/webp/dsp/alpha_processing.c383
-rw-r--r--drivers/webp/dsp/alpha_processing_mips_dsp_r2.c141
-rw-r--r--drivers/webp/dsp/alpha_processing_sse2.c298
-rw-r--r--drivers/webp/dsp/alpha_processing_sse41.c92
-rw-r--r--drivers/webp/dsp/argb.c68
-rw-r--r--drivers/webp/dsp/argb_mips_dsp_r2.c110
-rw-r--r--drivers/webp/dsp/argb_sse2.c67
-rw-r--r--drivers/webp/dsp/cost.c412
-rw-r--r--drivers/webp/dsp/cost_mips32.c154
-rw-r--r--drivers/webp/dsp/cost_mips_dsp_r2.c107
-rw-r--r--drivers/webp/dsp/cost_sse2.c119
-rw-r--r--drivers/webp/dsp/cpu.c95
-rw-r--r--drivers/webp/dsp/dec.c338
-rw-r--r--drivers/webp/dsp/dec_clip_tables.c366
-rw-r--r--drivers/webp/dsp/dec_mips32.c587
-rw-r--r--drivers/webp/dsp/dec_mips_dsp_r2.c994
-rw-r--r--drivers/webp/dsp/dec_neon.c1478
-rw-r--r--drivers/webp/dsp/dec_sse2.c1056
-rw-r--r--drivers/webp/dsp/dec_sse41.c45
-rw-r--r--drivers/webp/dsp/dsp.h368
-rw-r--r--drivers/webp/dsp/enc.c347
-rw-r--r--drivers/webp/dsp/enc_avx2.c21
-rw-r--r--drivers/webp/dsp/enc_mips32.c672
-rw-r--r--drivers/webp/dsp/enc_mips_dsp_r2.c1512
-rw-r--r--drivers/webp/dsp/enc_neon.c934
-rw-r--r--drivers/webp/dsp/enc_sse2.c1364
-rw-r--r--drivers/webp/dsp/enc_sse41.c375
-rw-r--r--drivers/webp/dsp/filters.c240
-rw-r--r--drivers/webp/dsp/filters_mips_dsp_r2.c405
-rw-r--r--drivers/webp/dsp/filters_sse2.c352
-rw-r--r--drivers/webp/dsp/lossless.c1013
-rw-r--r--drivers/webp/dsp/lossless.h292
-rw-r--r--drivers/webp/dsp/lossless_enc.c1305
-rw-r--r--drivers/webp/dsp/lossless_enc_mips32.c417
-rw-r--r--drivers/webp/dsp/lossless_enc_mips_dsp_r2.c275
-rw-r--r--drivers/webp/dsp/lossless_enc_neon.c143
-rw-r--r--drivers/webp/dsp/lossless_enc_sse2.c270
-rw-r--r--drivers/webp/dsp/lossless_enc_sse41.c51
-rw-r--r--drivers/webp/dsp/lossless_mips_dsp_r2.c680
-rw-r--r--drivers/webp/dsp/lossless_neon.c269
-rw-r--r--drivers/webp/dsp/lossless_sse2.c372
-rw-r--r--drivers/webp/dsp/mips_macro.h200
-rw-r--r--drivers/webp/dsp/neon.h82
-rw-r--r--drivers/webp/dsp/rescaler.c238
-rw-r--r--drivers/webp/dsp/rescaler_mips32.c291
-rw-r--r--drivers/webp/dsp/rescaler_mips_dsp_r2.c314
-rw-r--r--drivers/webp/dsp/rescaler_neon.c186
-rw-r--r--drivers/webp/dsp/rescaler_sse2.c373
-rw-r--r--drivers/webp/dsp/upsampling.c259
-rw-r--r--drivers/webp/dsp/upsampling_mips_dsp_r2.c282
-rw-r--r--drivers/webp/dsp/upsampling_neon.c261
-rw-r--r--drivers/webp/dsp/upsampling_sse2.c196
-rw-r--r--drivers/webp/dsp/yuv.c264
-rw-r--r--drivers/webp/dsp/yuv.h287
-rw-r--r--drivers/webp/dsp/yuv_mips32.c103
-rw-r--r--drivers/webp/dsp/yuv_mips_dsp_r2.c134
-rw-r--r--drivers/webp/dsp/yuv_sse2.c606
-rw-r--r--drivers/webp/dsp/yuv_tables_sse2.h536
-rw-r--r--drivers/webp/enc/alpha.c417
-rw-r--r--drivers/webp/enc/analysis.c361
-rw-r--r--drivers/webp/enc/backward_references.c1253
-rw-r--r--drivers/webp/enc/backward_references.h188
-rw-r--r--drivers/webp/enc/config.c69
-rw-r--r--drivers/webp/enc/cost.c672
-rw-r--r--drivers/webp/enc/cost.h36
-rw-r--r--drivers/webp/enc/delta_palettization.c455
-rw-r--r--drivers/webp/enc/delta_palettization.h25
-rw-r--r--drivers/webp/enc/filter.c332
-rw-r--r--drivers/webp/enc/frame.c987
-rw-r--r--drivers/webp/enc/histogram.c980
-rw-r--r--drivers/webp/enc/histogram.h87
-rw-r--r--drivers/webp/enc/iterator.c214
-rw-r--r--drivers/webp/enc/near_lossless.c160
-rw-r--r--drivers/webp/enc/picture.c1001
-rw-r--r--drivers/webp/enc/picture_csp.c1156
-rw-r--r--drivers/webp/enc/picture_psnr.c175
-rw-r--r--drivers/webp/enc/picture_rescale.c264
-rw-r--r--drivers/webp/enc/picture_tools.c206
-rw-r--r--drivers/webp/enc/quant.c811
-rw-r--r--drivers/webp/enc/syntax.c134
-rw-r--r--drivers/webp/enc/token.c285
-rw-r--r--drivers/webp/enc/tree.c30
-rw-r--r--drivers/webp/enc/vp8enci.h437
-rw-r--r--drivers/webp/enc/vp8l.c1367
-rw-r--r--drivers/webp/enc/vp8li.h23
-rw-r--r--drivers/webp/enc/webpenc.c266
-rw-r--r--drivers/webp/encode.h174
-rw-r--r--drivers/webp/extras.h51
-rw-r--r--drivers/webp/format_constants.h34
-rw-r--r--drivers/webp/image_loader_webp.cpp2
-rw-r--r--drivers/webp/image_loader_webp.h2
-rw-r--r--drivers/webp/mux.h760
-rw-r--r--drivers/webp/mux/anim_encode.c1404
-rw-r--r--drivers/webp/mux/muxedit.c740
-rw-r--r--drivers/webp/mux/muxi.h167
-rw-r--r--drivers/webp/mux/muxinternal.c331
-rw-r--r--drivers/webp/mux/muxread.c449
-rw-r--r--drivers/webp/mux_types.h97
-rw-r--r--drivers/webp/types.h21
-rw-r--r--drivers/webp/utils/bit_reader.c251
-rw-r--r--drivers/webp/utils/bit_reader.h238
-rw-r--r--drivers/webp/utils/bit_reader_inl.h172
-rw-r--r--drivers/webp/utils/bit_writer.c183
-rw-r--r--drivers/webp/utils/bit_writer.h106
-rw-r--r--drivers/webp/utils/color_cache.c25
-rw-r--r--drivers/webp/utils/color_cache.h30
-rw-r--r--drivers/webp/utils/endian_inl.h100
-rw-r--r--drivers/webp/utils/filters.c187
-rw-r--r--drivers/webp/utils/filters.h44
-rw-r--r--drivers/webp/utils/huffman.c337
-rw-r--r--drivers/webp/utils/huffman.h108
-rw-r--r--drivers/webp/utils/huffman_encode.c102
-rw-r--r--drivers/webp/utils/huffman_encode.h29
-rw-r--r--drivers/webp/utils/quant_levels.c24
-rw-r--r--drivers/webp/utils/quant_levels.h19
-rw-r--r--drivers/webp/utils/quant_levels_dec.c279
-rw-r--r--drivers/webp/utils/quant_levels_dec.h35
-rw-r--r--drivers/webp/utils/random.c43
-rw-r--r--drivers/webp/utils/random.h63
-rw-r--r--drivers/webp/utils/rescaler.c176
-rw-r--r--drivers/webp/utils/rescaler.h87
-rw-r--r--drivers/webp/utils/thread.c233
-rw-r--r--drivers/webp/utils/thread.h97
-rw-r--r--drivers/webp/utils/utils.c223
-rw-r--r--drivers/webp/utils/utils.h116
-rw-r--r--drivers/webpold/SCsub63
-rw-r--r--drivers/webpold/dec/alpha.c140
-rw-r--r--drivers/webpold/dec/buffer.c215
-rw-r--r--drivers/webpold/dec/decode_vp8.h182
-rw-r--r--drivers/webpold/dec/frame.c679
-rw-r--r--drivers/webpold/dec/idec.c785
-rw-r--r--drivers/webpold/dec/io.c633
-rw-r--r--drivers/webpold/dec/layer.c (renamed from drivers/webp/dec/layer.c)0
-rw-r--r--drivers/webpold/dec/quant.c113
-rw-r--r--drivers/webpold/dec/tree.c589
-rw-r--r--drivers/webpold/dec/vp8.c787
-rw-r--r--drivers/webpold/dec/vp8i.h335
-rw-r--r--drivers/webpold/dec/vp8l.c1200
-rw-r--r--drivers/webpold/dec/vp8li.h121
-rw-r--r--drivers/webpold/dec/webp.c771
-rw-r--r--drivers/webpold/dec/webpi.h114
-rw-r--r--drivers/webpold/decode.h454
-rw-r--r--drivers/webpold/dsp/cpu.c85
-rw-r--r--drivers/webpold/dsp/dec.c732
-rw-r--r--drivers/webpold/dsp/dec_neon.c329
-rw-r--r--drivers/webpold/dsp/dec_sse2.c903
-rw-r--r--drivers/webpold/dsp/dsp.h210
-rw-r--r--drivers/webpold/dsp/enc.c743
-rw-r--r--drivers/webpold/dsp/enc_sse2.c837
-rw-r--r--drivers/webpold/dsp/lossless.c1138
-rw-r--r--drivers/webpold/dsp/lossless.h82
-rw-r--r--drivers/webpold/dsp/upsampling.c357
-rw-r--r--drivers/webpold/dsp/upsampling_sse2.c209
-rw-r--r--drivers/webpold/dsp/yuv.c52
-rw-r--r--drivers/webpold/dsp/yuv.h128
-rw-r--r--drivers/webpold/enc/alpha.c330
-rw-r--r--drivers/webpold/enc/analysis.c364
-rw-r--r--drivers/webpold/enc/backward_references.c874
-rw-r--r--drivers/webpold/enc/backward_references.h212
-rw-r--r--drivers/webpold/enc/config.c132
-rw-r--r--drivers/webpold/enc/cost.c494
-rw-r--r--drivers/webpold/enc/cost.h48
-rw-r--r--drivers/webpold/enc/filter.c409
-rw-r--r--drivers/webpold/enc/frame.c939
-rw-r--r--drivers/webpold/enc/histogram.c406
-rw-r--r--drivers/webpold/enc/histogram.h115
-rw-r--r--drivers/webpold/enc/iterator.c422
-rw-r--r--drivers/webpold/enc/layer.c (renamed from drivers/webp/enc/layer.c)0
-rw-r--r--drivers/webpold/enc/picture.c1041
-rw-r--r--drivers/webpold/enc/quant.c930
-rw-r--r--drivers/webpold/enc/syntax.c437
-rw-r--r--drivers/webpold/enc/tree.c510
-rw-r--r--drivers/webpold/enc/vp8enci.h525
-rw-r--r--drivers/webpold/enc/vp8l.c1150
-rw-r--r--drivers/webpold/enc/vp8li.h68
-rw-r--r--drivers/webpold/enc/webpenc.c389
-rw-r--r--drivers/webpold/encode.h463
-rw-r--r--drivers/webpold/format_constants.h90
-rw-r--r--drivers/webpold/image_loader_webp.cpp165
-rw-r--r--drivers/webpold/image_loader_webp.h32
-rw-r--r--drivers/webpold/mux.h604
-rw-r--r--drivers/webpold/mux/demux.c (renamed from drivers/webp/mux/demux.c)0
-rw-r--r--drivers/webpold/mux/muxedit.c712
-rw-r--r--drivers/webpold/mux/muxi.h271
-rw-r--r--drivers/webpold/mux/muxinternal.c576
-rw-r--r--drivers/webpold/mux/muxread.c411
-rw-r--r--drivers/webpold/types.h45
-rw-r--r--drivers/webpold/utils/bit_reader.c229
-rw-r--r--drivers/webpold/utils/bit_reader.h198
-rw-r--r--drivers/webpold/utils/bit_writer.c284
-rw-r--r--drivers/webpold/utils/bit_writer.h123
-rw-r--r--drivers/webpold/utils/color_cache.c44
-rw-r--r--drivers/webpold/utils/color_cache.h68
-rw-r--r--drivers/webpold/utils/filters.c229
-rw-r--r--drivers/webpold/utils/filters.h54
-rw-r--r--drivers/webpold/utils/huffman.c238
-rw-r--r--drivers/webpold/utils/huffman.h78
-rw-r--r--drivers/webpold/utils/huffman_encode.c439
-rw-r--r--drivers/webpold/utils/huffman_encode.h47
-rw-r--r--drivers/webpold/utils/quant_levels.c154
-rw-r--r--drivers/webpold/utils/quant_levels.h39
-rw-r--r--drivers/webpold/utils/rescaler.c152
-rw-r--r--drivers/webpold/utils/rescaler.h76
-rw-r--r--drivers/webpold/utils/thread.c247
-rw-r--r--drivers/webpold/utils/thread.h86
-rw-r--r--drivers/webpold/utils/utils.c44
-rw-r--r--drivers/webpold/utils/utils.h44
-rw-r--r--drivers/windows/dir_access_windows.cpp2
-rw-r--r--drivers/windows/dir_access_windows.h2
-rw-r--r--drivers/windows/file_access_windows.cpp4
-rw-r--r--drivers/windows/file_access_windows.h2
-rw-r--r--drivers/windows/mutex_windows.cpp2
-rw-r--r--drivers/windows/mutex_windows.h2
-rw-r--r--drivers/windows/semaphore_windows.cpp2
-rw-r--r--drivers/windows/semaphore_windows.h2
-rw-r--r--drivers/windows/shell_windows.cpp2
-rw-r--r--drivers/windows/shell_windows.h2
-rw-r--r--drivers/windows/thread_windows.cpp2
-rw-r--r--drivers/windows/thread_windows.h2
-rw-r--r--logo_small.pngbin2025 -> 0 bytes
-rw-r--r--main/input_default.cpp543
-rw-r--r--main/input_default.h103
-rw-r--r--main/main.cpp84
-rw-r--r--main/main.h2
-rw-r--r--main/performance.cpp2
-rw-r--r--main/performance.h2
-rw-r--r--main/splash.h2
-rw-r--r--makerel.bat1
-rwxr-xr-xmethods.py41
-rw-r--r--modules/gdscript/gd_compiler.cpp42
-rw-r--r--modules/gdscript/gd_compiler.h4
-rw-r--r--modules/gdscript/gd_editor.cpp66
-rw-r--r--modules/gdscript/gd_functions.cpp129
-rw-r--r--modules/gdscript/gd_functions.h5
-rw-r--r--modules/gdscript/gd_parser.cpp202
-rw-r--r--modules/gdscript/gd_parser.h9
-rw-r--r--modules/gdscript/gd_pretty_print.cpp2
-rw-r--r--modules/gdscript/gd_pretty_print.h2
-rw-r--r--modules/gdscript/gd_script.cpp115
-rw-r--r--modules/gdscript/gd_script.h9
-rw-r--r--modules/gdscript/gd_tokenizer.cpp18
-rw-r--r--modules/gdscript/gd_tokenizer.h5
-rw-r--r--modules/gdscript/register_types.cpp2
-rw-r--r--modules/gdscript/register_types.h2
-rw-r--r--modules/gridmap/grid_map.cpp4
-rw-r--r--modules/gridmap/grid_map.h2
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp2
-rw-r--r--modules/gridmap/grid_map_editor_plugin.h2
-rw-r--r--modules/gridmap/register_types.cpp2
-rw-r--r--modules/gridmap/register_types.h2
-rw-r--r--platform/android/AndroidManifest.xml.template8
-rw-r--r--platform/android/SCsub63
-rw-r--r--platform/android/android_native_app_glue.h2
-rw-r--r--platform/android/audio_driver_jandroid.cpp6
-rw-r--r--platform/android/audio_driver_jandroid.h2
-rw-r--r--platform/android/audio_driver_opensl.cpp2
-rw-r--r--platform/android/audio_driver_opensl.h2
-rw-r--r--platform/android/build.gradle.template70
-rw-r--r--platform/android/detect.py4
-rw-r--r--platform/android/dir_access_android.cpp2
-rw-r--r--platform/android/dir_access_android.h2
-rw-r--r--platform/android/dir_access_jandroid.cpp6
-rw-r--r--platform/android/dir_access_jandroid.h2
-rw-r--r--platform/android/export/export.cpp70
-rw-r--r--platform/android/file_access_android.cpp10
-rw-r--r--platform/android/file_access_android.h2
-rw-r--r--platform/android/file_access_jandroid.cpp2
-rw-r--r--platform/android/file_access_jandroid.h2
-rw-r--r--platform/android/godot_android.cpp24
-rw-r--r--platform/android/java/aidl/com/android/vending/billing/IInAppBillingService.aidl144
-rw-r--r--platform/android/java/ant.properties17
-rw-r--r--platform/android/java/build.properties17
-rw-r--r--platform/android/java/build.xml92
-rw-r--r--platform/android/java/default.properties11
-rw-r--r--platform/android/java/gradle/wrapper/gradle-wrapper.jarbin0 -> 49896 bytes
-rw-r--r--platform/android/java/gradle/wrapper/gradle-wrapper.properties6
-rwxr-xr-xplatform/android/java/gradlew164
-rw-r--r--platform/android/java/gradlew.bat90
-rw-r--r--platform/android/java/my-release-key.keystorebin2218 -> 0 bytes
-rw-r--r--platform/android/java/proguard-project.txt20
-rw-r--r--platform/android/java/proguard.cfg36
-rw-r--r--platform/android/java/res/drawable-hdpi/notify_panel_notification_icon_bg.png (renamed from platform/android/libs/apk_expansion/res/drawable-hdpi/notify_panel_notification_icon_bg.png)bin1027 -> 1027 bytes
-rw-r--r--platform/android/java/res/drawable-mdpi/notify_panel_notification_icon_bg.png (renamed from platform/android/libs/apk_expansion/res/drawable-mdpi/notify_panel_notification_icon_bg.png)bin1125 -> 1125 bytes
-rw-r--r--platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml (renamed from platform/android/libs/apk_expansion/res/layout/status_bar_ongoing_event_progress_bar.xml)0
-rw-r--r--platform/android/java/res/values-v11/styles.xml (renamed from platform/android/libs/apk_expansion/res/values-v11/styles.xml)0
-rw-r--r--platform/android/java/res/values-v9/styles.xml (renamed from platform/android/libs/apk_expansion/res/values-v9/styles.xml)0
-rw-r--r--platform/android/java/res/values/strings.xml42
-rw-r--r--platform/android/java/res/values/styles.xml (renamed from platform/android/libs/apk_expansion/res/values/styles.xml)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/AESObfuscator.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/AESObfuscator.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/APKExpansionPolicy.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/APKExpansionPolicy.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/DeviceLimiter.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/DeviceLimiter.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/ILicenseResultListener.aidl (renamed from platform/android/libs/play_licensing/aidl/ILicenseResultListener.aidl)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/ILicenseResultListener.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ILicenseResultListener.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/ILicensingService.aidl (renamed from platform/android/libs/play_licensing/aidl/ILicensingService.aidl)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/ILicensingService.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ILicensingService.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/LicenseChecker.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/LicenseChecker.java)2
-rw-r--r--platform/android/java/src/com/android/vending/licensing/LicenseCheckerCallback.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/LicenseCheckerCallback.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/LicenseValidator.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/LicenseValidator.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/NullDeviceLimiter.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/NullDeviceLimiter.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/Obfuscator.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/Obfuscator.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/Policy.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/Policy.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/PreferenceObfuscator.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/PreferenceObfuscator.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/ResponseData.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ResponseData.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/ServerManagedPolicy.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ServerManagedPolicy.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/StrictPolicy.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/StrictPolicy.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/ValidationException.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ValidationException.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/util/Base64.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/util/Base64.java)0
-rw-r--r--platform/android/java/src/com/android/vending/licensing/util/Base64DecoderException.java (renamed from platform/android/libs/play_licensing/src/com/google/android/vending/licensing/util/Base64DecoderException.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/Constants.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/Constants.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/Helpers.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/Helpers.java)2
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/IDownloaderService.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/IDownloaderService.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/IStub.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/IStub.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/SystemFacade.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/SystemFacade.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/impl/AndroidHttpClient.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/AndroidHttpClient.java)0
-rwxr-xr-xplatform/android/java/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/impl/CustomNotificationFactory.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/CustomNotificationFactory.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java)2
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java)0
-rwxr-xr-xplatform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java (renamed from platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java)0
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/impl/V14CustomNotification.java (renamed from platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/V14CustomNotification.java)2
-rw-r--r--platform/android/java/src/com/google/android/vending/expansion/downloader/impl/V3CustomNotification.java (renamed from platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/V3CustomNotification.java)2
-rw-r--r--platform/android/java/src/org/godotengine/godot/Dictionary.java (renamed from platform/android/java/src/com/android/godot/Dictionary.java)2
-rw-r--r--platform/android/java/src/org/godotengine/godot/Godot.java (renamed from platform/android/java/src/com/android/godot/Godot.java)29
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java (renamed from platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java)2
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java (renamed from platform/android/java/src/com/android/godot/GodotDownloaderService.java)2
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotIO.java (renamed from platform/android/java/src/com/android/godot/GodotIO.java)6
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotLib.java (renamed from platform/android/java/src/com/android/godot/GodotLib.java)6
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java (renamed from platform/android/java/src/com/android/godot/GodotPaymentV3.java)4
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotView.java (renamed from platform/android/java/src/com/android/godot/GodotView.java)7
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/GodotEditText.java (renamed from platform/android/java/src/com/android/godot/input/GodotEditText.java)4
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java (renamed from platform/android/java/src/com/android/godot/input/GodotTextInputWrapper.java)4
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java (renamed from platform/android/java/src/com/android/godot/payments/ConsumeTask.java)2
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/GenericConsumeTask.java (renamed from platform/android/java/src/com/android/godot/payments/GenericConsumeTask.java)2
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java (renamed from platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java)6
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java (renamed from platform/android/java/src/com/android/godot/payments/PaymentsCache.java)2
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java (renamed from platform/android/java/src/com/android/godot/payments/PaymentsManager.java)8
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java (renamed from platform/android/java/src/com/android/godot/payments/PurchaseTask.java)6
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java (renamed from platform/android/java/src/com/android/godot/payments/ReleaseAllConsumablesTask.java)6
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java (renamed from platform/android/java/src/com/android/godot/payments/ValidateTask.java)14
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/Crypt.java (renamed from platform/android/java/src/com/android/godot/utils/Crypt.java)2
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java (renamed from platform/android/java/src/com/android/godot/utils/CustomSSLSocketFactory.java)2
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java (renamed from platform/android/java/src/com/android/godot/utils/HttpRequester.java)2
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/RequestParams.java (renamed from platform/android/java/src/com/android/godot/utils/RequestParams.java)2
-rw-r--r--platform/android/java_class_wrapper.cpp2
-rw-r--r--platform/android/java_glue.cpp74
-rw-r--r--platform/android/java_glue.h38
-rw-r--r--platform/android/libs/apk_expansion/AndroidManifest.xml9
-rw-r--r--platform/android/libs/apk_expansion/build.xml92
-rw-r--r--platform/android/libs/apk_expansion/proguard-project.txt20
-rw-r--r--platform/android/libs/apk_expansion/project.properties13
-rw-r--r--platform/android/libs/apk_expansion/res/values/strings.xml41
-rw-r--r--platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/V14CustomNotification.java101
-rw-r--r--platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/V3CustomNotification.java116
-rw-r--r--platform/android/libs/downloader_library/.classpath9
-rw-r--r--platform/android/libs/downloader_library/.settings/org.eclipse.jdt.core.prefs4
-rw-r--r--platform/android/libs/downloader_library/AndroidManifest.xml9
-rw-r--r--platform/android/libs/downloader_library/build.xml92
-rw-r--r--platform/android/libs/downloader_library/proguard-project.txt20
-rw-r--r--platform/android/libs/downloader_library/project.properties13
-rw-r--r--platform/android/libs/downloader_library/res/drawable-hdpi/notify_panel_notification_icon_bg.pngbin1027 -> 0 bytes
-rw-r--r--platform/android/libs/downloader_library/res/drawable-mdpi/notify_panel_notification_icon_bg.pngbin1125 -> 0 bytes
-rw-r--r--platform/android/libs/downloader_library/res/layout/status_bar_ongoing_event_progress_bar.xml104
-rw-r--r--platform/android/libs/downloader_library/res/values-v11/styles.xml6
-rw-r--r--platform/android/libs/downloader_library/res/values-v9/styles.xml5
-rw-r--r--platform/android/libs/downloader_library/res/values/strings.xml41
-rw-r--r--platform/android/libs/downloader_library/res/values/styles.xml25
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Constants.java236
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java80
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java277
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java181
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Helpers.java306
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java126
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderService.java83
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IStub.java41
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/SystemFacade.java123
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/AndroidHttpClient.java536
-rwxr-xr-xplatform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java112
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomNotificationFactory.java30
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java92
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java231
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java963
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java1341
-rwxr-xr-xplatform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java510
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java200
-rw-r--r--platform/android/libs/google_play_services/.classpath9
-rw-r--r--platform/android/libs/google_play_services/AndroidManifest.xml9
-rw-r--r--platform/android/libs/google_play_services/README.txt17
-rw-r--r--platform/android/libs/google_play_services/build.xml92
-rw-r--r--platform/android/libs/google_play_services/libs/google-play-services.jarbin1881748 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/libs/google-play-services.jar.properties1
-rw-r--r--platform/android/libs/google_play_services/proguard-project.txt20
-rw-r--r--platform/android/libs/google_play_services/proguard.txt20
-rw-r--r--platform/android/libs/google_play_services/project.properties15
-rw-r--r--platform/android/libs/google_play_services/res/color/common_signin_btn_text_dark.xml18
-rw-r--r--platform/android/libs/google_play_services/res/color/common_signin_btn_text_light.xml18
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_dark.9.pngbin1811 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_dark.9.pngbin1846 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_light.9.pngbin1846 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_light.9.pngbin1811 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_focus_dark.9.pngbin2100 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_focus_light.9.pngbin2075 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_normal_dark.9.pngbin2050 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_normal_light.9.pngbin2049 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_pressed_dark.9.pngbin2224 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_pressed_light.9.pngbin2331 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_dark.9.pngbin1927 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_focus_dark.9.pngbin1957 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_focus_light.9.pngbin1957 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_light.9.pngbin1927 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_focus_dark.9.pngbin2206 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_focus_light.9.pngbin2182 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_normal_dark.9.pngbin2185 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_normal_light.9.pngbin2158 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_pressed_dark.9.pngbin2374 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_pressed_light.9.pngbin2483 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_medium_off_client.pngbin1187 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_small_off_client.pngbin841 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_standard_off_client.pngbin1498 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_tall_off_client.pngbin1140 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_dark.9.pngbin1202 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_dark.9.pngbin1236 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_light.9.pngbin1236 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_light.9.pngbin1202 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_focus_dark.9.pngbin1389 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_focus_light.9.pngbin1362 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_normal_dark.9.pngbin1369 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_normal_light.9.pngbin1345 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_pressed_dark.9.pngbin1465 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_pressed_light.9.pngbin1521 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_dark.9.pngbin1309 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_focus_dark.9.pngbin1316 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_focus_light.9.pngbin1316 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_light.9.pngbin1309 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_focus_dark.9.pngbin1461 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_focus_light.9.pngbin1463 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_normal_dark.9.pngbin1463 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_normal_light.9.pngbin1455 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_pressed_dark.9.pngbin1556 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_pressed_light.9.pngbin1623 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_medium_off_client.pngbin751 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_small_off_client.pngbin581 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_standard_off_client.pngbin996 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_tall_off_client.pngbin789 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_dark.9.pngbin2438 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_dark.9.pngbin2457 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_light.9.pngbin2457 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_light.9.pngbin2438 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_focus_dark.9.pngbin2886 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_focus_light.9.pngbin2908 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_normal_dark.9.pngbin2847 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_normal_light.9.pngbin2888 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_pressed_dark.9.pngbin3133 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_pressed_light.9.pngbin3301 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_dark.9.pngbin2569 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_dark.9.pngbin2571 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_light.9.pngbin2571 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_light.9.pngbin2569 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_focus_dark.9.pngbin2939 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_focus_light.9.pngbin2947 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_normal_dark.9.pngbin2931 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_normal_light.9.pngbin2944 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_pressed_dark.9.pngbin3255 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_pressed_light.9.pngbin3384 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_medium_off_client.pngbin1598 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_small_off_client.pngbin1205 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_standard_off_client.pngbin2074 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_tall_off_client.pngbin1741 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_dark.9.pngbin4988 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_dark.9.pngbin5092 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_light.9.pngbin5092 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_light.9.pngbin4988 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_focus_dark.9.pngbin6558 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_focus_light.9.pngbin6216 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_normal_dark.9.pngbin6530 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_normal_light.9.pngbin6234 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_pressed_dark.9.pngbin7015 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_pressed_light.9.pngbin7352 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_dark.9.pngbin5637 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_dark.9.pngbin5572 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_light.9.pngbin5572 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_light.9.pngbin5637 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_focus_dark.9.pngbin6958 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_focus_light.9.pngbin6647 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_normal_dark.9.pngbin6975 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_normal_light.9.pngbin6713 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_pressed_dark.9.pngbin7569 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_pressed_light.9.pngbin7944 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_medium_off_client.pngbin5828 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_small_off_client.pngbin4279 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_standard_off_client.pngbin7439 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_tall_off_client.pngbin6204 -> 0 bytes
-rw-r--r--platform/android/libs/google_play_services/res/drawable/common_signin_btn_icon_dark.xml18
-rw-r--r--platform/android/libs/google_play_services/res/drawable/common_signin_btn_icon_light.xml18
-rw-r--r--platform/android/libs/google_play_services/res/drawable/common_signin_btn_text_dark.xml18
-rw-r--r--platform/android/libs/google_play_services/res/drawable/common_signin_btn_text_light.xml18
-rw-r--r--platform/android/libs/google_play_services/res/values-af/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-am/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-ar/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-be/strings.xml36
-rw-r--r--platform/android/libs/google_play_services/res/values-bg/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-ca/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-cs/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-da/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-de/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-el/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-en-rGB/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-en-rIN/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-es-rUS/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-es/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-et-rEE/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-fa/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-fi/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-fr-rCA/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-fr/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-hi/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-hr/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-hu/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-hy-rAM/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-in/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-it/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-iw/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-ja/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-ka-rGE/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-km-rKH/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-ko/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-lo-rLA/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-lt/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-lv/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-mn-rMN/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-ms-rMY/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-nb/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-nl/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-pl/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-pt-rBR/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-pt-rPT/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-pt/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-ro/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-ru/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-sk/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-sl/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-sr/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-sv/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-sw/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-th/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-tl/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-tr/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-uk/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-vi/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-zh-rCN/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-zh-rHK/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-zh-rTW/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values-zu/strings.xml31
-rw-r--r--platform/android/libs/google_play_services/res/values/ads_attrs.xml22
-rw-r--r--platform/android/libs/google_play_services/res/values/colors.xml14
-rw-r--r--platform/android/libs/google_play_services/res/values/maps_attrs.xml26
-rw-r--r--platform/android/libs/google_play_services/res/values/strings.xml111
-rw-r--r--platform/android/libs/google_play_services/res/values/version.xml4
-rw-r--r--platform/android/libs/google_play_services/src/android/UnusedStub.java21
-rw-r--r--platform/android/libs/play_licensing/AndroidManifest.xml24
-rw-r--r--platform/android/libs/play_licensing/build.xml92
-rw-r--r--platform/android/libs/play_licensing/proguard-project.txt20
-rw-r--r--platform/android/libs/play_licensing/project.properties12
-rw-r--r--platform/android/os_android.cpp22
-rw-r--r--platform/android/os_android.h13
-rw-r--r--platform/android/platform_config.h2
-rw-r--r--platform/android/project.properties.template15
-rw-r--r--platform/android/thread_jandroid.cpp2
-rw-r--r--platform/android/thread_jandroid.h2
-rw-r--r--platform/bb10/audio_driver_bb10.cpp2
-rw-r--r--platform/bb10/audio_driver_bb10.h2
-rw-r--r--platform/bb10/bbutil.h2
-rw-r--r--platform/bb10/export/export.cpp18
-rw-r--r--platform/bb10/godot_bb10.cpp2
-rw-r--r--platform/bb10/os_bb10.cpp2
-rw-r--r--platform/bb10/os_bb10.h2
-rw-r--r--platform/bb10/payment_service.cpp2
-rw-r--r--platform/bb10/payment_service.h2
-rw-r--r--platform/bb10/platform_config.h2
-rw-r--r--platform/flash/dir_access_flash.cpp2
-rw-r--r--platform/flash/dir_access_flash.h2
-rw-r--r--platform/flash/rasterizer_flash.cpp2
-rw-r--r--platform/flash/rasterizer_flash.h2
-rw-r--r--platform/haiku/SCsub11
-rw-r--r--platform/haiku/audio_driver_media_kit.cpp5
-rw-r--r--platform/haiku/audio_driver_media_kit.h2
-rw-r--r--platform/haiku/detect.py1
-rw-r--r--platform/haiku/godot.rdef60
-rw-r--r--platform/haiku/haiku_application.cpp2
-rw-r--r--platform/haiku/haiku_direct_window.cpp4
-rw-r--r--platform/iphone/Appirater.h2
-rw-r--r--platform/iphone/app_delegate.h2
-rw-r--r--platform/iphone/app_delegate.mm12
-rw-r--r--platform/iphone/audio_driver_iphone.cpp2
-rw-r--r--platform/iphone/audio_driver_iphone.h2
-rw-r--r--platform/iphone/detect.py14
-rw-r--r--platform/iphone/game_center.h2
-rw-r--r--platform/iphone/game_center.mm2
-rwxr-xr-xplatform/iphone/gl_view.h2
-rwxr-xr-xplatform/iphone/gl_view.mm2
-rw-r--r--platform/iphone/godot_iphone.cpp2
-rw-r--r--platform/iphone/icloud.h2
-rw-r--r--platform/iphone/icloud.mm2
-rw-r--r--platform/iphone/in_app_store.h2
-rw-r--r--platform/iphone/in_app_store.mm2
-rw-r--r--platform/iphone/os_iphone.cpp13
-rw-r--r--platform/iphone/os_iphone.h4
-rw-r--r--platform/iphone/platform_config.h4
-rw-r--r--platform/iphone/rasterizer_iphone.cpp2
-rw-r--r--platform/iphone/rasterizer_iphone.h2
-rw-r--r--platform/iphone/sem_iphone.cpp2
-rw-r--r--platform/iphone/sem_iphone.h2
-rw-r--r--platform/iphone/view_controller.h2
-rw-r--r--platform/iphone/view_controller.mm2
-rw-r--r--platform/isim/detect.py15
-rw-r--r--platform/javascript/audio_driver_javascript.cpp2
-rw-r--r--platform/javascript/audio_driver_javascript.h2
-rw-r--r--platform/javascript/audio_server_javascript.cpp2
-rw-r--r--platform/javascript/audio_server_javascript.h2
-rw-r--r--platform/javascript/detect.py9
-rw-r--r--platform/javascript/export/export.cpp101
-rw-r--r--platform/javascript/export/export.h2
-rw-r--r--platform/javascript/javascript_main.cpp2
-rw-r--r--platform/javascript/os_javascript.cpp70
-rw-r--r--platform/javascript/os_javascript.h10
-rw-r--r--platform/javascript/platform_config.h2
-rw-r--r--platform/nacl/audio_driver_nacl.cpp2
-rw-r--r--platform/nacl/audio_driver_nacl.h2
-rw-r--r--platform/nacl/context_gl_nacl.cpp2
-rw-r--r--platform/nacl/context_gl_nacl.h2
-rw-r--r--platform/nacl/geturl_handler.cpp2
-rw-r--r--platform/nacl/geturl_handler.h2
-rw-r--r--platform/nacl/godot_module.cpp2
-rw-r--r--platform/nacl/godot_nacl.cpp2
-rw-r--r--platform/nacl/nacl_keycodes.h2
-rw-r--r--platform/nacl/opengl_context.cpp2
-rw-r--r--platform/nacl/opengl_context.h2
-rw-r--r--platform/nacl/os_nacl.cpp5
-rw-r--r--platform/nacl/os_nacl.h2
-rw-r--r--platform/nacl/pepper_main.cpp2
-rw-r--r--platform/nacl/platform_config.h2
-rw-r--r--platform/osx/SCsub1
-rw-r--r--platform/osx/audio_driver_osx.cpp2
-rw-r--r--platform/osx/audio_driver_osx.h2
-rw-r--r--platform/osx/context_gl_osx.cpp2
-rw-r--r--platform/osx/context_gl_osx.h2
-rw-r--r--platform/osx/dir_access_osx.h92
-rw-r--r--platform/osx/dir_access_osx.mm350
-rw-r--r--platform/osx/export/export.cpp23
-rw-r--r--platform/osx/godot_main_osx.mm2
-rw-r--r--platform/osx/godot_osx.h2
-rw-r--r--platform/osx/godot_osx.mm2
-rw-r--r--platform/osx/os_osx.h2
-rw-r--r--platform/osx/os_osx.mm37
-rw-r--r--platform/osx/platform_config.h3
-rw-r--r--platform/osx/sem_osx.cpp2
-rw-r--r--platform/osx/sem_osx.h2
-rw-r--r--platform/server/godot_server.cpp2
-rw-r--r--platform/server/os_server.cpp2
-rw-r--r--platform/server/os_server.h2
-rw-r--r--platform/server/platform_config.h2
-rw-r--r--platform/windows/SCsub3
-rw-r--r--platform/windows/context_gl_win.cpp2
-rw-r--r--platform/windows/context_gl_win.h2
-rw-r--r--platform/windows/ctxgl_procaddr.cpp2
-rw-r--r--platform/windows/ctxgl_procaddr.h2
-rw-r--r--platform/windows/detect.py17
-rw-r--r--platform/windows/export/export.cpp2
-rw-r--r--platform/windows/godot_res.rc6
-rw-r--r--platform/windows/godot_win.cpp2
-rw-r--r--platform/windows/joystick.cpp536
-rw-r--r--platform/windows/joystick.h142
-rw-r--r--platform/windows/key_mapping_win.cpp2
-rw-r--r--platform/windows/key_mapping_win.h2
-rw-r--r--platform/windows/lang_table.h2
-rw-r--r--platform/windows/os_windows.cpp292
-rw-r--r--platform/windows/os_windows.h48
-rw-r--r--platform/windows/platform_config.h2
-rw-r--r--platform/windows/stream_peer_winsock.cpp10
-rw-r--r--platform/windows/stream_peer_winsock.h4
-rw-r--r--platform/windows/tcp_server_winsock.cpp2
-rw-r--r--platform/windows/tcp_server_winsock.h2
-rw-r--r--platform/winrt/os_winrt.cpp5
-rw-r--r--platform/winrt/os_winrt.h2
-rw-r--r--platform/x11/SCsub1
-rw-r--r--platform/x11/context_gl_x11.cpp2
-rw-r--r--platform/x11/context_gl_x11.h2
-rw-r--r--platform/x11/detect.py35
-rw-r--r--platform/x11/godot_x11.cpp2
-rw-r--r--platform/x11/joystick_linux.cpp416
-rw-r--r--platform/x11/joystick_linux.h92
-rw-r--r--platform/x11/key_mapping_x11.cpp2
-rw-r--r--platform/x11/key_mapping_x11.h2
-rw-r--r--platform/x11/os_x11.cpp230
-rw-r--r--platform/x11/os_x11.h37
-rw-r--r--platform/x11/platform_config.h5
-rw-r--r--scene/2d/animated_sprite.cpp2
-rw-r--r--scene/2d/animated_sprite.h2
-rw-r--r--scene/2d/area_2d.cpp18
-rw-r--r--scene/2d/area_2d.h6
-rw-r--r--scene/2d/camera_2d.cpp43
-rw-r--r--scene/2d/camera_2d.h8
-rw-r--r--scene/2d/canvas_item.cpp27
-rw-r--r--scene/2d/canvas_item.h7
-rw-r--r--scene/2d/canvas_modulate.cpp13
-rw-r--r--scene/2d/collision_object_2d.cpp2
-rw-r--r--scene/2d/collision_object_2d.h2
-rw-r--r--scene/2d/collision_polygon_2d.cpp66
-rw-r--r--scene/2d/collision_polygon_2d.h3
-rw-r--r--scene/2d/collision_shape_2d.cpp8
-rw-r--r--scene/2d/collision_shape_2d.h2
-rw-r--r--scene/2d/joints_2d.cpp76
-rw-r--r--scene/2d/joints_2d.h7
-rw-r--r--scene/2d/light_2d.cpp20
-rw-r--r--scene/2d/light_2d.h2
-rw-r--r--scene/2d/light_occluder_2d.cpp5
-rw-r--r--scene/2d/navigation2d.cpp42
-rw-r--r--scene/2d/navigation_polygon.cpp8
-rw-r--r--scene/2d/node_2d.cpp11
-rw-r--r--scene/2d/node_2d.h4
-rw-r--r--scene/2d/node_2d_singleton.cpp2
-rw-r--r--scene/2d/node_2d_singleton.h2
-rw-r--r--scene/2d/parallax_background.cpp4
-rw-r--r--scene/2d/parallax_background.h2
-rw-r--r--scene/2d/parallax_layer.cpp2
-rw-r--r--scene/2d/parallax_layer.h2
-rw-r--r--scene/2d/particles_2d.cpp16
-rw-r--r--scene/2d/particles_2d.h3
-rw-r--r--scene/2d/path_2d.cpp10
-rw-r--r--scene/2d/path_2d.h2
-rw-r--r--scene/2d/physics_body_2d.cpp27
-rw-r--r--scene/2d/physics_body_2d.h4
-rw-r--r--scene/2d/position_2d.cpp2
-rw-r--r--scene/2d/position_2d.h2
-rw-r--r--scene/2d/ray_cast_2d.cpp2
-rw-r--r--scene/2d/ray_cast_2d.h2
-rw-r--r--scene/2d/remote_transform_2d.cpp2
-rw-r--r--scene/2d/remote_transform_2d.h2
-rw-r--r--scene/2d/sample_player_2d.cpp2
-rw-r--r--scene/2d/sample_player_2d.h2
-rw-r--r--scene/2d/screen_button.cpp10
-rw-r--r--scene/2d/screen_button.h2
-rw-r--r--scene/2d/sound_player_2d.cpp2
-rw-r--r--scene/2d/sound_player_2d.h2
-rw-r--r--scene/2d/sprite.cpp2
-rw-r--r--scene/2d/sprite.h2
-rw-r--r--scene/2d/tile_map.cpp93
-rw-r--r--scene/2d/tile_map.h10
-rw-r--r--scene/2d/visibility_notifier_2d.cpp2
-rw-r--r--scene/2d/visibility_notifier_2d.h2
-rw-r--r--scene/3d/area.cpp4
-rw-r--r--scene/3d/area.h6
-rw-r--r--scene/3d/body_shape.cpp4
-rw-r--r--scene/3d/body_shape.h2
-rw-r--r--scene/3d/bone_attachment.cpp2
-rw-r--r--scene/3d/bone_attachment.h2
-rw-r--r--scene/3d/camera.cpp113
-rw-r--r--scene/3d/camera.h7
-rw-r--r--scene/3d/character_camera.cpp2
-rw-r--r--scene/3d/character_camera.h2
-rw-r--r--scene/3d/collision_object.cpp2
-rw-r--r--scene/3d/collision_object.h2
-rw-r--r--scene/3d/collision_polygon.cpp2
-rw-r--r--scene/3d/interpolated_camera.cpp2
-rw-r--r--scene/3d/interpolated_camera.h2
-rw-r--r--scene/3d/light.cpp6
-rw-r--r--scene/3d/light.h2
-rw-r--r--scene/3d/mesh_instance.cpp2
-rw-r--r--scene/3d/mesh_instance.h2
-rw-r--r--scene/3d/multimesh_instance.cpp2
-rw-r--r--scene/3d/multimesh_instance.h2
-rw-r--r--scene/3d/optimized_spatial_scene.cpp2
-rw-r--r--scene/3d/optimized_spatial_scene.h2
-rw-r--r--scene/3d/particles.cpp6
-rw-r--r--scene/3d/particles.h2
-rw-r--r--scene/3d/path.cpp2
-rw-r--r--scene/3d/path.h2
-rw-r--r--scene/3d/physics_body.cpp41
-rw-r--r--scene/3d/physics_body.h6
-rw-r--r--scene/3d/physics_joint.cpp35
-rw-r--r--scene/3d/physics_joint.h6
-rw-r--r--scene/3d/portal.cpp2
-rw-r--r--scene/3d/portal.h2
-rw-r--r--scene/3d/position_3d.cpp2
-rw-r--r--scene/3d/position_3d.h2
-rw-r--r--scene/3d/proximity_group.cpp2
-rw-r--r--scene/3d/proximity_group.h2
-rw-r--r--scene/3d/quad.cpp2
-rw-r--r--scene/3d/quad.h2
-rw-r--r--scene/3d/ray_cast.cpp2
-rw-r--r--scene/3d/ray_cast.h2
-rw-r--r--scene/3d/room_instance.cpp2
-rw-r--r--scene/3d/room_instance.h2
-rw-r--r--scene/3d/scenario_fx.cpp2
-rw-r--r--scene/3d/scenario_fx.h2
-rw-r--r--scene/3d/skeleton.cpp2
-rw-r--r--scene/3d/skeleton.h2
-rw-r--r--scene/3d/spatial.cpp12
-rw-r--r--scene/3d/spatial.h3
-rw-r--r--scene/3d/spatial_indexer.cpp2
-rw-r--r--scene/3d/spatial_indexer.h2
-rw-r--r--scene/3d/spatial_player.cpp2
-rw-r--r--scene/3d/spatial_player.h2
-rw-r--r--scene/3d/spatial_sample_player.cpp2
-rw-r--r--scene/3d/spatial_sample_player.h2
-rw-r--r--scene/3d/spatial_stream_player.cpp6
-rw-r--r--scene/3d/spatial_stream_player.h2
-rw-r--r--scene/3d/test_cube.cpp2
-rw-r--r--scene/3d/test_cube.h2
-rw-r--r--scene/3d/visibility_notifier.cpp2
-rw-r--r--scene/3d/visibility_notifier.h2
-rw-r--r--scene/3d/visual_instance.cpp2
-rw-r--r--scene/3d/visual_instance.h2
-rw-r--r--scene/animation/animation_cache.cpp2
-rw-r--r--scene/animation/animation_cache.h2
-rw-r--r--scene/animation/animation_player.cpp89
-rw-r--r--scene/animation/animation_player.h4
-rw-r--r--scene/animation/animation_tree_player.cpp73
-rw-r--r--scene/animation/animation_tree_player.h4
-rw-r--r--scene/animation/transitioner.cpp2
-rw-r--r--scene/animation/transitioner.h2
-rw-r--r--scene/animation/tween.cpp2
-rw-r--r--scene/animation/tween.h2
-rw-r--r--scene/animation/tween_interpolaters.cpp2
-rw-r--r--scene/audio/event_player.cpp14
-rw-r--r--scene/audio/event_player.h2
-rw-r--r--scene/audio/sample_player.cpp2
-rw-r--r--scene/audio/sample_player.h2
-rw-r--r--scene/audio/sound_room_params.cpp2
-rw-r--r--scene/audio/sound_room_params.h2
-rw-r--r--scene/audio/stream_player.cpp16
-rw-r--r--scene/audio/stream_player.h3
-rw-r--r--scene/gui/base_button.cpp2
-rw-r--r--scene/gui/base_button.h2
-rw-r--r--scene/gui/box_container.cpp2
-rw-r--r--scene/gui/box_container.h2
-rw-r--r--scene/gui/button.cpp6
-rw-r--r--scene/gui/button.h2
-rw-r--r--scene/gui/button_array.cpp2
-rw-r--r--scene/gui/button_array.h2
-rw-r--r--scene/gui/button_group.cpp2
-rw-r--r--scene/gui/button_group.h2
-rw-r--r--scene/gui/center_container.cpp2
-rw-r--r--scene/gui/center_container.h2
-rw-r--r--scene/gui/check_box.cpp2
-rw-r--r--scene/gui/check_box.h2
-rw-r--r--scene/gui/check_button.cpp2
-rw-r--r--scene/gui/check_button.h2
-rw-r--r--scene/gui/color_picker.cpp474
-rw-r--r--scene/gui/color_picker.h55
-rw-r--r--scene/gui/container.cpp4
-rw-r--r--scene/gui/container.h2
-rw-r--r--scene/gui/control.cpp1198
-rw-r--r--scene/gui/control.h86
-rw-r--r--scene/gui/custom_button.cpp2
-rw-r--r--scene/gui/custom_button.h2
-rw-r--r--scene/gui/dialogs.cpp2
-rw-r--r--scene/gui/dialogs.h2
-rw-r--r--scene/gui/file_dialog.cpp60
-rw-r--r--scene/gui/file_dialog.h7
-rw-r--r--scene/gui/graph_edit.cpp101
-rw-r--r--scene/gui/graph_edit.h14
-rw-r--r--scene/gui/graph_node.cpp11
-rw-r--r--scene/gui/graph_node.h1
-rw-r--r--scene/gui/grid_container.cpp2
-rw-r--r--scene/gui/grid_container.h2
-rw-r--r--scene/gui/label.cpp2
-rw-r--r--scene/gui/label.h2
-rw-r--r--scene/gui/line_edit.cpp67
-rw-r--r--scene/gui/line_edit.h2
-rw-r--r--scene/gui/margin_container.cpp2
-rw-r--r--scene/gui/margin_container.h2
-rw-r--r--scene/gui/menu_button.cpp2
-rw-r--r--scene/gui/menu_button.h2
-rw-r--r--scene/gui/option_button.cpp13
-rw-r--r--scene/gui/option_button.h2
-rw-r--r--scene/gui/panel.cpp2
-rw-r--r--scene/gui/panel.h2
-rw-r--r--scene/gui/panel_container.cpp2
-rw-r--r--scene/gui/panel_container.h2
-rw-r--r--scene/gui/popup.cpp24
-rw-r--r--scene/gui/popup.h2
-rw-r--r--scene/gui/popup_menu.cpp24
-rw-r--r--scene/gui/popup_menu.h3
-rw-r--r--scene/gui/progress_bar.cpp2
-rw-r--r--scene/gui/progress_bar.h2
-rw-r--r--scene/gui/range.cpp48
-rw-r--r--scene/gui/range.h15
-rw-r--r--scene/gui/reference_frame.cpp2
-rw-r--r--scene/gui/reference_frame.h2
-rw-r--r--scene/gui/rich_text_label.cpp553
-rw-r--r--scene/gui/rich_text_label.h92
-rw-r--r--scene/gui/scroll_bar.cpp2
-rw-r--r--scene/gui/scroll_bar.h2
-rw-r--r--scene/gui/scroll_container.cpp2
-rw-r--r--scene/gui/scroll_container.h2
-rw-r--r--scene/gui/separator.cpp2
-rw-r--r--scene/gui/separator.h2
-rw-r--r--scene/gui/slider.cpp6
-rw-r--r--scene/gui/slider.h2
-rw-r--r--scene/gui/spin_box.cpp32
-rw-r--r--scene/gui/spin_box.h6
-rw-r--r--scene/gui/split_container.cpp36
-rw-r--r--scene/gui/split_container.h17
-rw-r--r--scene/gui/tab_container.cpp2
-rw-r--r--scene/gui/tab_container.h2
-rw-r--r--scene/gui/tabs.cpp439
-rw-r--r--scene/gui/tabs.h31
-rw-r--r--scene/gui/text_edit.cpp133
-rw-r--r--scene/gui/text_edit.h4
-rw-r--r--scene/gui/texture_button.cpp20
-rw-r--r--scene/gui/texture_button.h6
-rw-r--r--scene/gui/texture_frame.cpp2
-rw-r--r--scene/gui/texture_frame.h2
-rw-r--r--scene/gui/texture_progress.cpp2
-rw-r--r--scene/gui/texture_progress.h2
-rw-r--r--scene/gui/tool_button.cpp2
-rw-r--r--scene/gui/tool_button.h2
-rw-r--r--scene/gui/tree.cpp107
-rw-r--r--scene/gui/tree.h10
-rw-r--r--scene/gui/video_player.cpp15
-rw-r--r--scene/gui/video_player.h8
-rw-r--r--scene/io/resource_format_image.cpp2
-rw-r--r--scene/io/resource_format_image.h2
-rw-r--r--scene/io/resource_format_wav.cpp2
-rw-r--r--scene/io/resource_format_wav.h2
-rw-r--r--scene/main/canvas_layer.cpp2
-rw-r--r--scene/main/canvas_layer.h2
-rw-r--r--scene/main/instance_placeholder.cpp13
-rw-r--r--scene/main/misc.cpp2
-rw-r--r--scene/main/misc.h2
-rw-r--r--scene/main/node.cpp54
-rw-r--r--scene/main/node.h6
-rw-r--r--scene/main/resource_preloader.cpp2
-rw-r--r--scene/main/resource_preloader.h2
-rw-r--r--scene/main/scene_main_loop.cpp20
-rw-r--r--scene/main/scene_main_loop.h6
-rw-r--r--scene/main/scene_singleton.cpp2
-rw-r--r--scene/main/scene_singleton.h2
-rw-r--r--scene/main/timer.cpp2
-rw-r--r--scene/main/timer.h2
-rw-r--r--scene/main/viewport.cpp1017
-rw-r--r--scene/main/viewport.h96
-rw-r--r--scene/register_scene_types.cpp8
-rw-r--r--scene/register_scene_types.h2
-rw-r--r--scene/resources/animation.cpp2
-rw-r--r--scene/resources/animation.h2
-rw-r--r--scene/resources/audio_stream.cpp2
-rw-r--r--scene/resources/audio_stream.h2
-rw-r--r--scene/resources/audio_stream_resampled.cpp2
-rw-r--r--scene/resources/audio_stream_resampled.h2
-rw-r--r--scene/resources/bit_mask.cpp56
-rw-r--r--scene/resources/bit_mask.h13
-rw-r--r--scene/resources/bounds.cpp2
-rw-r--r--scene/resources/bounds.h2
-rw-r--r--scene/resources/box_shape.cpp2
-rw-r--r--scene/resources/box_shape.h2
-rw-r--r--scene/resources/canvas.cpp2
-rw-r--r--scene/resources/canvas.h2
-rw-r--r--scene/resources/capsule_shape.cpp2
-rw-r--r--scene/resources/capsule_shape.h2
-rw-r--r--scene/resources/capsule_shape_2d.cpp2
-rw-r--r--scene/resources/capsule_shape_2d.h2
-rw-r--r--scene/resources/circle_shape_2d.cpp2
-rw-r--r--scene/resources/circle_shape_2d.h2
-rw-r--r--scene/resources/color_ramp.cpp34
-rw-r--r--scene/resources/color_ramp.h3
-rw-r--r--scene/resources/concave_polygon_shape.cpp2
-rw-r--r--scene/resources/concave_polygon_shape.h2
-rw-r--r--scene/resources/concave_polygon_shape_2d.cpp2
-rw-r--r--scene/resources/concave_polygon_shape_2d.h2
-rw-r--r--scene/resources/convex_polygon_shape.cpp2
-rw-r--r--scene/resources/convex_polygon_shape.h2
-rw-r--r--scene/resources/convex_polygon_shape_2d.cpp8
-rw-r--r--scene/resources/convex_polygon_shape_2d.h2
-rw-r--r--scene/resources/curve.cpp2
-rw-r--r--scene/resources/curve.h2
-rw-r--r--scene/resources/default_theme/button_focus.pngbin0 -> 2931 bytes
-rw-r--r--scene/resources/default_theme/default_theme.cpp28
-rw-r--r--scene/resources/default_theme/default_theme.h2
-rw-r--r--scene/resources/default_theme/frame_focus.pngbin0 -> 301 bytes
-rw-r--r--scene/resources/default_theme/icon_add.pngbin0 -> 351 bytes
-rw-r--r--scene/resources/default_theme/icon_color_pick.pngbin0 -> 646 bytes
-rw-r--r--scene/resources/default_theme/icon_reload.pngbin0 -> 519 bytes
-rw-r--r--scene/resources/default_theme/make_header.py (renamed from scene/resources/default_theme/make_png_header.py)55
-rw-r--r--scene/resources/default_theme/tab_close.pngbin0 -> 398 bytes
-rw-r--r--scene/resources/default_theme/theme_data.h59
-rw-r--r--scene/resources/default_theme/uv_editor.gsl19
-rw-r--r--scene/resources/default_theme/w_editor.gsl11
-rw-r--r--scene/resources/environment.cpp2
-rw-r--r--scene/resources/environment.h2
-rw-r--r--scene/resources/event_stream.cpp2
-rw-r--r--scene/resources/event_stream.h2
-rw-r--r--scene/resources/font.cpp47
-rw-r--r--scene/resources/font.h14
-rw-r--r--scene/resources/gibberish_stream.cpp2
-rw-r--r--scene/resources/gibberish_stream.h2
-rw-r--r--scene/resources/height_map_shape.cpp2
-rw-r--r--scene/resources/height_map_shape.h2
-rw-r--r--scene/resources/material.cpp8
-rw-r--r--scene/resources/material.h2
-rw-r--r--scene/resources/mesh.cpp4
-rw-r--r--scene/resources/mesh.h2
-rw-r--r--scene/resources/mesh_data_tool.cpp2
-rw-r--r--scene/resources/mesh_data_tool.h2
-rw-r--r--scene/resources/mesh_library.cpp2
-rw-r--r--scene/resources/mesh_library.h2
-rw-r--r--scene/resources/multimesh.cpp14
-rw-r--r--scene/resources/multimesh.h2
-rw-r--r--scene/resources/packed_scene.cpp101
-rw-r--r--scene/resources/packed_scene.h27
-rw-r--r--scene/resources/plane_shape.cpp2
-rw-r--r--scene/resources/plane_shape.h2
-rw-r--r--scene/resources/ray_shape.cpp2
-rw-r--r--scene/resources/ray_shape.h2
-rw-r--r--scene/resources/rectangle_shape_2d.cpp2
-rw-r--r--scene/resources/rectangle_shape_2d.h2
-rw-r--r--scene/resources/rich_text.cpp2
-rw-r--r--scene/resources/rich_text.h2
-rw-r--r--scene/resources/room.cpp2
-rw-r--r--scene/resources/room.h2
-rw-r--r--scene/resources/sample.cpp8
-rw-r--r--scene/resources/sample.h2
-rw-r--r--scene/resources/sample_library.cpp2
-rw-r--r--scene/resources/sample_library.h2
-rw-r--r--scene/resources/scene_format_text.cpp644
-rw-r--r--scene/resources/scene_format_text.h8
-rw-r--r--scene/resources/scene_preloader.cpp2
-rw-r--r--scene/resources/scene_preloader.h2
-rw-r--r--scene/resources/segment_shape_2d.cpp2
-rw-r--r--scene/resources/segment_shape_2d.h2
-rw-r--r--scene/resources/shader.cpp22
-rw-r--r--scene/resources/shader.h2
-rw-r--r--scene/resources/shader_graph.cpp21
-rw-r--r--scene/resources/shader_graph.h2
-rw-r--r--scene/resources/shape.cpp2
-rw-r--r--scene/resources/shape.h2
-rw-r--r--scene/resources/shape_2d.cpp6
-rw-r--r--scene/resources/shape_2d.h2
-rw-r--r--scene/resources/shape_line_2d.cpp2
-rw-r--r--scene/resources/shape_line_2d.h2
-rw-r--r--scene/resources/space_2d.cpp2
-rw-r--r--scene/resources/space_2d.h2
-rw-r--r--scene/resources/sphere_shape.cpp2
-rw-r--r--scene/resources/sphere_shape.h2
-rw-r--r--scene/resources/style_box.cpp10
-rw-r--r--scene/resources/style_box.h2
-rw-r--r--scene/resources/surface_tool.cpp2
-rw-r--r--scene/resources/surface_tool.h2
-rw-r--r--scene/resources/texture.cpp21
-rw-r--r--scene/resources/texture.h3
-rw-r--r--scene/resources/theme.cpp59
-rw-r--r--scene/resources/theme.h12
-rw-r--r--scene/resources/tile_set.cpp2
-rw-r--r--scene/resources/tile_set.h2
-rw-r--r--scene/resources/video_stream.cpp2
-rw-r--r--scene/resources/video_stream.h2
-rw-r--r--scene/resources/volume.cpp2
-rw-r--r--scene/resources/volume.h2
-rw-r--r--scene/resources/world.cpp2
-rw-r--r--scene/resources/world.h2
-rw-r--r--scene/resources/world_2d.cpp2
-rw-r--r--scene/resources/world_2d.h2
-rw-r--r--scene/scene_string_names.cpp2
-rw-r--r--scene/scene_string_names.h2
-rw-r--r--servers/audio/audio_driver_dummy.cpp2
-rw-r--r--servers/audio/audio_driver_dummy.h2
-rw-r--r--servers/audio/audio_filter_sw.cpp2
-rw-r--r--servers/audio/audio_filter_sw.h2
-rw-r--r--servers/audio/audio_mixer_sw.cpp2
-rw-r--r--servers/audio/audio_mixer_sw.h2
-rw-r--r--servers/audio/audio_server_sw.cpp12
-rw-r--r--servers/audio/audio_server_sw.h4
-rw-r--r--servers/audio/reverb_buffers_sw.cpp2
-rw-r--r--servers/audio/reverb_buffers_sw.h2
-rw-r--r--servers/audio/reverb_sw.cpp2
-rw-r--r--servers/audio/reverb_sw.h2
-rw-r--r--servers/audio/sample_manager_sw.cpp2
-rw-r--r--servers/audio/sample_manager_sw.h2
-rw-r--r--servers/audio/voice_rb_sw.cpp2
-rw-r--r--servers/audio/voice_rb_sw.h2
-rw-r--r--servers/audio_server.cpp57
-rw-r--r--servers/audio_server.h4
-rw-r--r--servers/physics/area_pair_sw.cpp2
-rw-r--r--servers/physics/area_pair_sw.h2
-rw-r--r--servers/physics/area_sw.cpp2
-rw-r--r--servers/physics/area_sw.h2
-rw-r--r--servers/physics/body_pair_sw.cpp2
-rw-r--r--servers/physics/body_pair_sw.h2
-rw-r--r--servers/physics/body_sw.cpp58
-rw-r--r--servers/physics/body_sw.h6
-rw-r--r--servers/physics/broad_phase_basic.cpp2
-rw-r--r--servers/physics/broad_phase_basic.h2
-rw-r--r--servers/physics/broad_phase_octree.cpp2
-rw-r--r--servers/physics/broad_phase_octree.h2
-rw-r--r--servers/physics/broad_phase_sw.cpp2
-rw-r--r--servers/physics/broad_phase_sw.h2
-rw-r--r--servers/physics/collision_object_sw.cpp2
-rw-r--r--servers/physics/collision_object_sw.h2
-rw-r--r--servers/physics/collision_solver_sat.cpp2
-rw-r--r--servers/physics/collision_solver_sat.h2
-rw-r--r--servers/physics/collision_solver_sw.cpp2
-rw-r--r--servers/physics/collision_solver_sw.h2
-rw-r--r--servers/physics/constraint_sw.cpp2
-rw-r--r--servers/physics/constraint_sw.h2
-rw-r--r--servers/physics/gjk_epa.cpp2
-rw-r--r--servers/physics/gjk_epa.h2
-rw-r--r--servers/physics/joints_sw.cpp2
-rw-r--r--servers/physics/joints_sw.h2
-rw-r--r--servers/physics/physics_server_sw.cpp4
-rw-r--r--servers/physics/physics_server_sw.h4
-rw-r--r--servers/physics/shape_sw.cpp6
-rw-r--r--servers/physics/shape_sw.h2
-rw-r--r--servers/physics/space_sw.cpp22
-rw-r--r--servers/physics/space_sw.h4
-rw-r--r--servers/physics/step_sw.cpp2
-rw-r--r--servers/physics/step_sw.h2
-rw-r--r--servers/physics_2d/area_2d_sw.cpp2
-rw-r--r--servers/physics_2d/area_2d_sw.h2
-rw-r--r--servers/physics_2d/area_pair_2d_sw.cpp2
-rw-r--r--servers/physics_2d/area_pair_2d_sw.h2
-rw-r--r--servers/physics_2d/body_2d_sw.cpp84
-rw-r--r--servers/physics_2d/body_2d_sw.h7
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp8
-rw-r--r--servers/physics_2d/body_pair_2d_sw.h2
-rw-r--r--servers/physics_2d/broad_phase_2d_basic.cpp2
-rw-r--r--servers/physics_2d/broad_phase_2d_basic.h2
-rw-r--r--servers/physics_2d/broad_phase_2d_hash_grid.cpp2
-rw-r--r--servers/physics_2d/broad_phase_2d_hash_grid.h2
-rw-r--r--servers/physics_2d/broad_phase_2d_sw.cpp2
-rw-r--r--servers/physics_2d/broad_phase_2d_sw.h2
-rw-r--r--servers/physics_2d/collision_object_2d_sw.cpp2
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h2
-rw-r--r--servers/physics_2d/collision_solver_2d_sat.cpp2
-rw-r--r--servers/physics_2d/collision_solver_2d_sat.h2
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.cpp2
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.h2
-rw-r--r--servers/physics_2d/constraint_2d_sw.cpp2
-rw-r--r--servers/physics_2d/constraint_2d_sw.h2
-rw-r--r--servers/physics_2d/joints_2d_sw.cpp2
-rw-r--r--servers/physics_2d/joints_2d_sw.h2
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp5
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h5
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp2
-rw-r--r--servers/physics_2d/shape_2d_sw.h2
-rw-r--r--servers/physics_2d/space_2d_sw.cpp10
-rw-r--r--servers/physics_2d/space_2d_sw.h2
-rw-r--r--servers/physics_2d/step_2d_sw.cpp54
-rw-r--r--servers/physics_2d/step_2d_sw.h4
-rw-r--r--servers/physics_2d_server.cpp22
-rw-r--r--servers/physics_2d_server.h4
-rw-r--r--servers/physics_server.cpp10
-rw-r--r--servers/physics_server.h8
-rw-r--r--servers/register_server_types.cpp2
-rw-r--r--servers/register_server_types.h2
-rw-r--r--servers/spatial_sound/spatial_sound_server_sw.cpp2
-rw-r--r--servers/spatial_sound/spatial_sound_server_sw.h2
-rw-r--r--servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp2
-rw-r--r--servers/spatial_sound_2d/spatial_sound_2d_server_sw.h2
-rw-r--r--servers/spatial_sound_2d_server.cpp2
-rw-r--r--servers/spatial_sound_2d_server.h2
-rw-r--r--servers/spatial_sound_server.cpp2
-rw-r--r--servers/spatial_sound_server.h2
-rw-r--r--servers/visual/particle_system_sw.cpp2
-rw-r--r--servers/visual/particle_system_sw.h2
-rw-r--r--servers/visual/rasterizer.cpp2
-rw-r--r--servers/visual/rasterizer.h11
-rw-r--r--servers/visual/rasterizer_dummy.cpp2
-rw-r--r--servers/visual/rasterizer_dummy.h2
-rw-r--r--servers/visual/shader_compiler.cpp2
-rw-r--r--servers/visual/shader_compiler.h2
-rw-r--r--servers/visual/shader_graph.cpp2
-rw-r--r--servers/visual/shader_graph.h2
-rw-r--r--servers/visual/shader_language.cpp16
-rw-r--r--servers/visual/shader_language.h2
-rw-r--r--servers/visual/visual_server_raster.cpp48
-rw-r--r--servers/visual/visual_server_raster.h6
-rw-r--r--servers/visual/visual_server_wrap_mt.cpp2
-rw-r--r--servers/visual/visual_server_wrap_mt.h2
-rw-r--r--servers/visual_server.cpp3
-rw-r--r--servers/visual_server.h3
-rwxr-xr-xtools/Godot.app/Contents/Info.plist4
-rw-r--r--tools/addheader/addheader.py2
-rw-r--r--tools/addheader/header.txt2
-rw-r--r--tools/collada/collada.cpp8
-rw-r--r--tools/collada/collada.h2
-rw-r--r--tools/doc/doc_data.cpp15
-rw-r--r--tools/doc/doc_data.h2
-rw-r--r--tools/docdump/class_list.xml13625
-rw-r--r--tools/docdump/doc_dump.cpp2
-rw-r--r--tools/docdump/doc_dump.h2
-rw-r--r--tools/docdump/main.css146
-rw-r--r--tools/editor/animation_editor.cpp230
-rw-r--r--tools/editor/animation_editor.h14
-rw-r--r--tools/editor/array_property_edit.cpp19
-rw-r--r--tools/editor/array_property_edit.h2
-rw-r--r--tools/editor/call_dialog.cpp2
-rw-r--r--tools/editor/call_dialog.h2
-rw-r--r--tools/editor/code_editor.cpp3
-rw-r--r--tools/editor/code_editor.h2
-rw-r--r--tools/editor/connections_dialog.cpp9
-rw-r--r--tools/editor/connections_dialog.h2
-rw-r--r--tools/editor/console.cpp386
-rw-r--r--tools/editor/create_dialog.cpp2
-rw-r--r--tools/editor/create_dialog.h2
-rw-r--r--tools/editor/default_saver.cpp2
-rw-r--r--tools/editor/default_saver.h2
-rw-r--r--tools/editor/doc_code_font.h2
-rw-r--r--tools/editor/doc_font.h2
-rw-r--r--tools/editor/doc_title_font.h2
-rw-r--r--tools/editor/editor_data.cpp110
-rw-r--r--tools/editor/editor_data.h7
-rw-r--r--tools/editor/editor_dir_dialog.cpp19
-rw-r--r--tools/editor/editor_dir_dialog.h2
-rw-r--r--tools/editor/editor_file_dialog.cpp90
-rw-r--r--tools/editor/editor_file_dialog.h7
-rw-r--r--tools/editor/editor_file_system.cpp950
-rw-r--r--tools/editor/editor_file_system.h89
-rw-r--r--tools/editor/editor_fonts.cpp2
-rw-r--r--tools/editor/editor_fonts.h2
-rw-r--r--tools/editor/editor_help.cpp24
-rw-r--r--tools/editor/editor_help.h2
-rw-r--r--tools/editor/editor_icons.h2
-rw-r--r--tools/editor/editor_import_export.cpp200
-rw-r--r--tools/editor/editor_import_export.h30
-rw-r--r--tools/editor/editor_log.cpp57
-rw-r--r--tools/editor/editor_log.h12
-rw-r--r--tools/editor/editor_name_dialog.cpp89
-rw-r--r--tools/editor/editor_name_dialog.h (renamed from tools/editor/console.h)93
-rw-r--r--tools/editor/editor_node.cpp948
-rw-r--r--tools/editor/editor_node.h81
-rw-r--r--tools/editor/editor_path.cpp2
-rw-r--r--tools/editor/editor_path.h2
-rw-r--r--tools/editor/editor_plugin.cpp2
-rw-r--r--tools/editor/editor_plugin.h3
-rw-r--r--tools/editor/editor_reimport_dialog.cpp2
-rw-r--r--tools/editor/editor_reimport_dialog.h2
-rw-r--r--tools/editor/editor_run.cpp2
-rw-r--r--tools/editor/editor_run.h2
-rw-r--r--tools/editor/editor_run_native.cpp2
-rw-r--r--tools/editor/editor_run_native.h2
-rw-r--r--tools/editor/editor_selection.cpp2
-rw-r--r--tools/editor/editor_selection.h2
-rw-r--r--tools/editor/editor_settings.cpp4
-rw-r--r--tools/editor/editor_settings.h3
-rw-r--r--tools/editor/editor_sub_scene.cpp14
-rw-r--r--tools/editor/editor_sub_scene.h2
-rw-r--r--tools/editor/editor_vu.cpp2
-rw-r--r--tools/editor/editor_vu.h2
-rw-r--r--tools/editor/file_type_cache.cpp2
-rw-r--r--tools/editor/file_type_cache.h2
-rw-r--r--tools/editor/groups_editor.cpp167
-rw-r--r--tools/editor/groups_editor.h38
-rw-r--r--tools/editor/icons/icon_add_track.pngbin446 -> 165 bytes
-rw-r--r--tools/editor/icons/icon_console.pngbin0 -> 640 bytes
-rw-r--r--tools/editor/icons/icon_create_new_scene_from.pngbin0 -> 588 bytes
-rw-r--r--tools/editor/icons/icon_edit_pivot.pngbin0 -> 407 bytes
-rw-r--r--tools/editor/icons/icon_key_invalid.pngbin0 -> 239 bytes
-rw-r--r--tools/editor/icons/icon_key_invalid_hover.pngbin0 -> 239 bytes
-rw-r--r--tools/editor/icons/icon_list_select.pngbin0 -> 470 bytes
-rw-r--r--tools/editor/icons/icon_pin.pngbin381 -> 428 bytes
-rw-r--r--tools/editor/import_settings.cpp2
-rw-r--r--tools/editor/import_settings.h2
-rw-r--r--tools/editor/io_plugins/editor_atlas.cpp2
-rw-r--r--tools/editor/io_plugins/editor_atlas.h2
-rw-r--r--tools/editor/io_plugins/editor_export_scene.cpp112
-rw-r--r--tools/editor/io_plugins/editor_export_scene.h16
-rw-r--r--tools/editor/io_plugins/editor_font_import_plugin.cpp28
-rw-r--r--tools/editor/io_plugins/editor_font_import_plugin.h2
-rw-r--r--tools/editor/io_plugins/editor_import_collada.cpp45
-rw-r--r--tools/editor/io_plugins/editor_import_collada.h2
-rw-r--r--tools/editor/io_plugins/editor_sample_import_plugin.cpp4
-rw-r--r--tools/editor/io_plugins/editor_sample_import_plugin.h2
-rw-r--r--tools/editor/io_plugins/editor_scene_import_plugin.cpp2
-rw-r--r--tools/editor/io_plugins/editor_scene_import_plugin.h2
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.cpp6
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.h2
-rw-r--r--tools/editor/io_plugins/editor_translation_import_plugin.cpp2
-rw-r--r--tools/editor/io_plugins/editor_translation_import_plugin.h2
-rw-r--r--tools/editor/optimized_save_dialog.cpp2
-rw-r--r--tools/editor/optimized_save_dialog.h2
-rw-r--r--tools/editor/output_strings.cpp2
-rw-r--r--tools/editor/output_strings.h2
-rw-r--r--tools/editor/pane_drag.cpp2
-rw-r--r--tools/editor/pane_drag.h2
-rw-r--r--tools/editor/plugins/animation_data_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/animation_data_editor_plugin.h2
-rw-r--r--tools/editor/plugins/animation_player_editor_plugin.cpp318
-rw-r--r--tools/editor/plugins/animation_player_editor_plugin.h21
-rw-r--r--tools/editor/plugins/animation_tree_editor_plugin.cpp25
-rw-r--r--tools/editor/plugins/animation_tree_editor_plugin.h3
-rw-r--r--tools/editor/plugins/camera_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/camera_editor_plugin.h2
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.cpp329
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.h11
-rw-r--r--tools/editor/plugins/collision_polygon_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/collision_polygon_editor_plugin.h2
-rw-r--r--tools/editor/plugins/color_ramp_editor_plugin.cpp17
-rw-r--r--tools/editor/plugins/color_ramp_editor_plugin.h3
-rw-r--r--tools/editor/plugins/control_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/control_editor_plugin.h2
-rw-r--r--tools/editor/plugins/cube_grid_theme_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/cube_grid_theme_editor_plugin.h2
-rw-r--r--tools/editor/plugins/editor_preview_plugins.cpp95
-rw-r--r--tools/editor/plugins/editor_preview_plugins.h11
-rw-r--r--tools/editor/plugins/item_list_editor_plugin.cpp367
-rw-r--r--tools/editor/plugins/item_list_editor_plugin.h140
-rw-r--r--tools/editor/plugins/mesh_editor_plugin.cpp134
-rw-r--r--tools/editor/plugins/mesh_editor_plugin.h13
-rw-r--r--tools/editor/plugins/multimesh_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/multimesh_editor_plugin.h2
-rw-r--r--tools/editor/plugins/particles_2d_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/particles_2d_editor_plugin.h2
-rw-r--r--tools/editor/plugins/particles_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/particles_editor_plugin.h2
-rw-r--r--tools/editor/plugins/path_2d_editor_plugin.cpp4
-rw-r--r--tools/editor/plugins/path_2d_editor_plugin.h2
-rw-r--r--tools/editor/plugins/path_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/path_editor_plugin.h2
-rw-r--r--tools/editor/plugins/polygon_2d_editor_plugin.cpp3
-rw-r--r--tools/editor/plugins/resource_preloader_editor_plugin.cpp20
-rw-r--r--tools/editor/plugins/resource_preloader_editor_plugin.h3
-rw-r--r--tools/editor/plugins/rich_text_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/rich_text_editor_plugin.h2
-rw-r--r--tools/editor/plugins/sample_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/sample_editor_plugin.h2
-rw-r--r--tools/editor/plugins/sample_library_editor_plugin.cpp22
-rw-r--r--tools/editor/plugins/sample_library_editor_plugin.h3
-rw-r--r--tools/editor/plugins/sample_player_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/sample_player_editor_plugin.h2
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp198
-rw-r--r--tools/editor/plugins/script_editor_plugin.h13
-rw-r--r--tools/editor/plugins/shader_editor_plugin.cpp12
-rw-r--r--tools/editor/plugins/shader_editor_plugin.h2
-rw-r--r--tools/editor/plugins/shader_graph_editor_plugin.cpp6
-rw-r--r--tools/editor/plugins/shader_graph_editor_plugin.h4
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.cpp234
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.h11
-rw-r--r--tools/editor/plugins/sprite_frames_editor_plugin.cpp21
-rw-r--r--tools/editor/plugins/sprite_frames_editor_plugin.h3
-rw-r--r--tools/editor/plugins/sprite_region_editor_plugin.cpp59
-rw-r--r--tools/editor/plugins/sprite_region_editor_plugin.h12
-rw-r--r--tools/editor/plugins/stream_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/stream_editor_plugin.h2
-rw-r--r--tools/editor/plugins/style_box_editor_plugin.cpp21
-rw-r--r--tools/editor/plugins/style_box_editor_plugin.h3
-rw-r--r--tools/editor/plugins/theme_editor_plugin.cpp17
-rw-r--r--tools/editor/plugins/theme_editor_plugin.h3
-rw-r--r--tools/editor/plugins/tile_map_editor_plugin.cpp46
-rw-r--r--tools/editor/plugins/tile_map_editor_plugin.h2
-rw-r--r--tools/editor/plugins/tile_set_editor_plugin.cpp49
-rw-r--r--tools/editor/plugins/tile_set_editor_plugin.h9
-rw-r--r--tools/editor/progress_dialog.cpp14
-rw-r--r--tools/editor/progress_dialog.h5
-rw-r--r--tools/editor/project_export.cpp52
-rw-r--r--tools/editor/project_export.h3
-rw-r--r--tools/editor/project_manager.cpp28
-rw-r--r--tools/editor/project_manager.h3
-rw-r--r--tools/editor/project_settings.cpp295
-rw-r--r--tools/editor/project_settings.h10
-rw-r--r--tools/editor/property_editor.cpp516
-rw-r--r--tools/editor/property_editor.h36
-rw-r--r--tools/editor/pvrtc_compress.cpp2
-rw-r--r--tools/editor/pvrtc_compress.h2
-rw-r--r--tools/editor/quick_open.cpp76
-rw-r--r--tools/editor/quick_open.h7
-rw-r--r--tools/editor/register_exporters.h2
-rw-r--r--tools/editor/reparent_dialog.cpp31
-rw-r--r--tools/editor/reparent_dialog.h9
-rw-r--r--tools/editor/resources_dock.cpp2
-rw-r--r--tools/editor/resources_dock.h2
-rw-r--r--tools/editor/run_settings_dialog.cpp2
-rw-r--r--tools/editor/run_settings_dialog.h2
-rw-r--r--tools/editor/scene_tree_dock.cpp190
-rw-r--r--tools/editor/scene_tree_dock.h8
-rw-r--r--tools/editor/scene_tree_editor.cpp16
-rw-r--r--tools/editor/scene_tree_editor.h2
-rw-r--r--tools/editor/scenes.cpp2
-rw-r--r--tools/editor/scenes.h2
-rw-r--r--tools/editor/scenes_dock.cpp14
-rw-r--r--tools/editor/scenes_dock.h3
-rw-r--r--tools/editor/script_create_dialog.cpp2
-rw-r--r--tools/editor/script_create_dialog.h2
-rw-r--r--tools/editor/script_editor_debugger.cpp46
-rw-r--r--tools/editor/script_editor_debugger.h10
-rw-r--r--tools/editor/settings_config_dialog.cpp14
-rw-r--r--tools/editor/settings_config_dialog.h4
-rw-r--r--tools/editor/spatial_editor_gizmos.cpp6
-rw-r--r--tools/editor/spatial_editor_gizmos.h2
-rw-r--r--tools/export/blender25/io_scene_dae/export_dae.py2
-rw-r--r--tools/html_fs/godot.html1647
-rw-r--r--tools/ios_xcode_template/godot_ios/main.m2
-rw-r--r--tools/ios_xcode_template/godot_iosTests/godot_iosTests.m2
-rw-r--r--tools/pck/pck_packer.cpp2
2108 files changed, 96488 insertions, 85994 deletions
diff --git a/.gitignore b/.gitignore
index f24d91a7ee..a6d5a2d412 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@ core/method_bind.inc
core/method_bind_ext.inc
core/script_encryption_key.cpp
core/global_defaults.cpp
+drivers/unix/os_unix_global_settings_path.cpp
tools/editor/register_exporters.cpp
tools/editor/doc_data_compressed.h
tools/editor/editor_icons.cpp
@@ -23,8 +24,8 @@ tools/editor/editor_icons.cpp
make.bat
log.txt
-# Doxygen generated documentation
-doc/doxygen/*
+# Documentation generated by doxygen or from classes.xml
+doc/_build/
# Javascript specific
*.bc
@@ -188,9 +189,6 @@ AutoTest.Net/
# Installshield output folder
[Ee]xpress/
-# dumpdoc generated files
-doc/html/class_list
-
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
diff --git a/.travis.yml b/.travis.yml
index 6dd21dae0b..13f91b99e8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,14 +1,48 @@
language: cpp
-compiler:
+
+sudo: required
+dist: trusty
+
+compiler:
- gcc
-before_install:
-
-
-before_script:
- - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
- - sudo apt-get update -qq
- - sudo apt-get install -qq scons pkg-config libx11-dev libxcursor-dev build-essential libasound2-dev libfreetype6-dev libgl1-mesa-dev libglu-dev
- - if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.8; fi
- - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
-
-script: scons platform=x11
+ - clang
+
+os:
+ - linux
+ - osx
+
+env:
+ - GODOT_TARGET=iphone
+ - GODOT_TARGET=osx
+ - GODOT_TARGET=x11
+ - GODOT_TARGET=android
+ - GODOT_TARGET=windows
+
+matrix:
+ exclude:
+ - os: linux
+ env: GODOT_TARGET=iphone
+ - os: linux
+ env: GODOT_TARGET=osx
+ - os: linux
+ env: GODOT_TARGET=android
+ - os: osx
+ env: GODOT_TARGET=x11
+ - os: osx
+ env: GODOT_TARGET=windows
+ - compiler: gcc
+ env: GODOT_TARGET=iphone
+ - compiler: clang
+ env: GODOT_TARGET=android
+ - compiler: clang
+ env: GODOT_TARGET=windows
+
+
+before_script:
+ - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq; sudo apt-get install -y scons pkg-config libx11-dev libxcursor-dev build-essential libasound2-dev libfreetype6-dev libgl1-mesa-dev libglu-dev libssl-dev libxinerama-dev libevdev-dev libudev-dev; fi
+ - if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$GODOT_TARGET" = "windows" ]; then sudo apt-get update -qq; sudo apt-get install -y mingw32 mingw-w64; fi
+ - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; brew install scons; fi
+ - if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$GODOT_TARGET" = "android" ]; then brew update; brew install android-sdk android-ndk; export ANDROID_HOME=/usr/local/opt/android-sdk; export ANDROID_NDK_ROOT=/usr/local/opt/android-ndk; fi
+
+script:
+ - scons platform=$GODOT_TARGET CXX=$CXX
diff --git a/LICENSE.md b/LICENSE.md
index ca0a9702f7..2f78f0e37d 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,7 +1,7 @@
GODOT ENGINE
http://www.godotengine.org
**********************************************************************
- Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.
+ Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/SConstruct b/SConstruct
index 46edf06a42..b047e961f2 100644
--- a/SConstruct
+++ b/SConstruct
@@ -66,26 +66,34 @@ env_base=Environment(tools=custom_tools,ENV = {'PATH' : os.environ['PATH']});
#env_base=Environment(tools=custom_tools);
env_base.global_defaults=global_defaults
-env_base.android_source_modules=[]
-env_base.android_source_files=[]
-env_base.android_module_libraries=[]
+env_base.android_maven_repos=[]
+env_base.android_dependencies=[]
+env_base.android_java_dirs=[]
+env_base.android_res_dirs=[]
+env_base.android_aidl_dirs=[]
+env_base.android_jni_dirs=[]
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__.android_add_maven_repository=methods.android_add_maven_repository
+env_base.__class__.android_add_dependency=methods.android_add_dependency
+env_base.__class__.android_add_java_dir=methods.android_add_java_dir
+env_base.__class__.android_add_res_dir=methods.android_add_res_dir
+env_base.__class__.android_add_aidl_dir=methods.android_add_aidl_dir
+env_base.__class__.android_add_jni_dir=methods.android_add_jni_dir
+env_base.__class__.android_add_to_manifest = methods.android_add_to_manifest
+env_base.__class__.android_add_to_permissions = methods.android_add_to_permissions
+env_base.__class__.android_add_to_attributes = methods.android_add_to_attributes
env_base.__class__.disable_module = methods.disable_module
env_base.__class__.add_source_files = methods.add_source_files
env_base["x86_opt_gcc"]=False
env_base["x86_opt_vc"]=False
+env_base["armv7_opt_gcc"]=False
customs = ['custom.py']
@@ -126,6 +134,7 @@ opts.Add("CXX", "Compiler");
opts.Add("CCFLAGS", "Custom flags for the C++ compiler");
opts.Add("CFLAGS", "Custom flags for the C compiler");
opts.Add("LINKFLAGS", "Custom flags for the linker");
+opts.Add('unix_global_settings_path', 'unix-specific path to system-wide settings. Currently only used by templates.','')
opts.Add('disable_3d', 'Disable 3D nodes for smaller executable (yes/no)', "no")
opts.Add('disable_advanced_gui', 'Disable advance 3D gui nodes and behaviors (yes/no)', "no")
opts.Add('colored', 'Enable colored output for the compilation (yes/no)', 'no')
diff --git a/bin/tests/test_containers.cpp b/bin/tests/test_containers.cpp
index db877fcc1c..f8cc8ccd41 100644
--- a/bin/tests/test_containers.cpp
+++ b/bin/tests/test_containers.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_containers.h b/bin/tests/test_containers.h
index 3bfdef301b..72d5c0ff7a 100644
--- a/bin/tests/test_containers.h
+++ b/bin/tests/test_containers.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_detailer.cpp b/bin/tests/test_detailer.cpp
index ce318632dd..616356077e 100644
--- a/bin/tests/test_detailer.cpp
+++ b/bin/tests/test_detailer.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_detailer.h b/bin/tests/test_detailer.h
index a410f6a67a..597e088caf 100644
--- a/bin/tests/test_detailer.h
+++ b/bin/tests/test_detailer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_gdscript.cpp b/bin/tests/test_gdscript.cpp
index 68209ecb54..683191fba2 100644
--- a/bin/tests/test_gdscript.cpp
+++ b/bin/tests/test_gdscript.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_gdscript.h b/bin/tests/test_gdscript.h
index f599b9c9e1..225654e2a8 100644
--- a/bin/tests/test_gdscript.h
+++ b/bin/tests/test_gdscript.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_gui.cpp b/bin/tests/test_gui.cpp
index c404623872..cba488a3da 100644
--- a/bin/tests/test_gui.cpp
+++ b/bin/tests/test_gui.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_gui.h b/bin/tests/test_gui.h
index 556b45462a..5526320b0c 100644
--- a/bin/tests/test_gui.h
+++ b/bin/tests/test_gui.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_image.cpp b/bin/tests/test_image.cpp
index b378755dfe..bf9851cf01 100644
--- a/bin/tests/test_image.cpp
+++ b/bin/tests/test_image.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_image.h b/bin/tests/test_image.h
index 8812658464..09b33e799e 100644
--- a/bin/tests/test_image.h
+++ b/bin/tests/test_image.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_io.cpp b/bin/tests/test_io.cpp
index 4c211a1b0d..a1eb2be19b 100644
--- a/bin/tests/test_io.cpp
+++ b/bin/tests/test_io.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_io.h b/bin/tests/test_io.h
index 27a5118cf0..c839590ab9 100644
--- a/bin/tests/test_io.h
+++ b/bin/tests/test_io.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_main.cpp b/bin/tests/test_main.cpp
index 5567145aa0..8143a95d66 100644
--- a/bin/tests/test_main.cpp
+++ b/bin/tests/test_main.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_main.h b/bin/tests/test_main.h
index d1898387eb..c8d571a7dd 100644
--- a/bin/tests/test_main.h
+++ b/bin/tests/test_main.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_math.cpp b/bin/tests/test_math.cpp
index d340515c65..b5041b265f 100644
--- a/bin/tests/test_math.cpp
+++ b/bin/tests/test_math.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_math.h b/bin/tests/test_math.h
index 3209ebcef6..492c3a1837 100644
--- a/bin/tests/test_math.h
+++ b/bin/tests/test_math.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_misc.cpp b/bin/tests/test_misc.cpp
index d6ea193853..68564c62b0 100644
--- a/bin/tests/test_misc.cpp
+++ b/bin/tests/test_misc.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_misc.h b/bin/tests/test_misc.h
index ac751e5cc9..55608f6a0e 100644
--- a/bin/tests/test_misc.h
+++ b/bin/tests/test_misc.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_particles.cpp b/bin/tests/test_particles.cpp
index 18b52444d8..bafd78eda0 100644
--- a/bin/tests/test_particles.cpp
+++ b/bin/tests/test_particles.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_particles.h b/bin/tests/test_particles.h
index e5e3cfab15..e95637a4e6 100644
--- a/bin/tests/test_particles.h
+++ b/bin/tests/test_particles.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_physics.cpp b/bin/tests/test_physics.cpp
index e3fd96ff9d..ce96f37f3f 100644
--- a/bin/tests/test_physics.cpp
+++ b/bin/tests/test_physics.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_physics.h b/bin/tests/test_physics.h
index f62806bf5e..5b6a54f2d4 100644
--- a/bin/tests/test_physics.h
+++ b/bin/tests/test_physics.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_physics_2d.cpp b/bin/tests/test_physics_2d.cpp
index 70a7d868be..c5fb734999 100644
--- a/bin/tests/test_physics_2d.cpp
+++ b/bin/tests/test_physics_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_physics_2d.h b/bin/tests/test_physics_2d.h
index eadd5ebcb4..e2eb1f4023 100644
--- a/bin/tests/test_physics_2d.h
+++ b/bin/tests/test_physics_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_python.cpp b/bin/tests/test_python.cpp
index a89e4a7eee..575caf2513 100644
--- a/bin/tests/test_python.cpp
+++ b/bin/tests/test_python.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_python.h b/bin/tests/test_python.h
index 9dafbd545d..77e9603fe2 100644
--- a/bin/tests/test_python.h
+++ b/bin/tests/test_python.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_render.cpp b/bin/tests/test_render.cpp
index 97a52b16c1..568699e5e6 100644
--- a/bin/tests/test_render.cpp
+++ b/bin/tests/test_render.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_render.h b/bin/tests/test_render.h
index dc71a32978..6993e75b9f 100644
--- a/bin/tests/test_render.h
+++ b/bin/tests/test_render.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_shader_lang.cpp b/bin/tests/test_shader_lang.cpp
index df826e489d..e55ad3074f 100644
--- a/bin/tests/test_shader_lang.cpp
+++ b/bin/tests/test_shader_lang.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_shader_lang.h b/bin/tests/test_shader_lang.h
index 85d379bc43..f129fb224a 100644
--- a/bin/tests/test_shader_lang.h
+++ b/bin/tests/test_shader_lang.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_sound.cpp b/bin/tests/test_sound.cpp
index 63c6edd9c9..44cc117e02 100644
--- a/bin/tests/test_sound.cpp
+++ b/bin/tests/test_sound.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_sound.h b/bin/tests/test_sound.h
index 32b66c8bba..91b87a2261 100644
--- a/bin/tests/test_sound.h
+++ b/bin/tests/test_sound.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_string.cpp b/bin/tests/test_string.cpp
index 93b1835b78..fe7bf4d9cf 100644
--- a/bin/tests/test_string.cpp
+++ b/bin/tests/test_string.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/bin/tests/test_string.h b/bin/tests/test_string.h
index b04eccb005..7b3cd9a019 100644
--- a/bin/tests/test_string.h
+++ b/bin/tests/test_string.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/allocators.h b/core/allocators.h
index 16e516e87b..4a5fd7a119 100644
--- a/core/allocators.h
+++ b/core/allocators.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/array.cpp b/core/array.cpp
index ab9f19d6a0..fef0fcbb40 100644
--- a/core/array.cpp
+++ b/core/array.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -222,6 +222,24 @@ void Array::invert(){
}
+void Array::push_front(const Variant& p_value) {
+
+ _p->array.insert(0,p_value);
+}
+
+void Array::pop_back(){
+
+ if (!_p->array.empty())
+ _p->array.resize( _p->array.size() -1 );
+
+}
+void Array::pop_front(){
+
+ if (!_p->array.empty())
+ _p->array.remove(0);
+
+}
+
Array::Array(const Array& p_from) {
diff --git a/core/array.h b/core/array.h
index 904309b257..ecb91b69dc 100644
--- a/core/array.h
+++ b/core/array.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -53,7 +53,7 @@ public:
bool empty() const;
void clear();
- bool is_shared() const;
+ bool is_shared() const;
bool operator==(const Array& p_array) const;
@@ -75,6 +75,10 @@ public:
void erase(const Variant& p_value);
+ void push_front(const Variant& p_value);
+ void pop_back();
+ void pop_front();
+
Array(const Array& p_from);
Array(bool p_shared=false);
~Array();
diff --git a/core/balloon_allocator.h b/core/balloon_allocator.h
index 177c744669..eb6632bb37 100644
--- a/core/balloon_allocator.h
+++ b/core/balloon_allocator.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 94557d149d..94d9e22a1e 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -62,8 +62,8 @@ void _ResourceLoader::_bind_methods() {
ObjectTypeDB::bind_method(_MD("load:Resource","path","type_hint", "p_no_cache"),&_ResourceLoader::load,DEFVAL(""), DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_recognized_extensions_for_type","type"),&_ResourceLoader::get_recognized_extensions_for_type);
ObjectTypeDB::bind_method(_MD("set_abort_on_missing_resources","abort"),&_ResourceLoader::set_abort_on_missing_resources);
- ObjectTypeDB::bind_method(_MD("get_dependencies"),&_ResourceLoader::get_dependencies);
- ObjectTypeDB::bind_method(_MD("has"),&_ResourceLoader::has);
+ ObjectTypeDB::bind_method(_MD("get_dependencies","path"),&_ResourceLoader::get_dependencies);
+ ObjectTypeDB::bind_method(_MD("has","path"),&_ResourceLoader::has);
}
_ResourceLoader::_ResourceLoader() {
@@ -96,7 +96,7 @@ _ResourceSaver *_ResourceSaver::singleton=NULL;
void _ResourceSaver::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("save","path","resource:Resource"),&_ResourceSaver::save, DEFVAL(0));
+ ObjectTypeDB::bind_method(_MD("save","path","resource:Resource","flags"),&_ResourceSaver::save,DEFVAL(0));
ObjectTypeDB::bind_method(_MD("get_recognized_extensions","type"),&_ResourceSaver::get_recognized_extensions);
BIND_CONSTANT(FLAG_RELATIVE_PATHS);
@@ -494,8 +494,8 @@ uint64_t _OS::get_unix_time() const {
return OS::get_singleton()->get_unix_time();
};
-uint64_t _OS::get_system_time_msec() const {
- return OS::get_singleton()->get_system_time_msec();
+uint64_t _OS::get_system_time_secs() const {
+ return OS::get_singleton()->get_system_time_secs();
}
void _OS::delay_usec(uint32_t p_usec) const {
@@ -708,6 +708,15 @@ _OS::ScreenOrientation _OS::get_screen_orientation() const {
return ScreenOrientation(OS::get_singleton()->get_screen_orientation());
}
+void _OS::set_keep_screen_on(bool p_enabled) {
+
+ OS::get_singleton()->set_keep_screen_on(p_enabled);
+}
+
+bool _OS::is_keep_screen_on() const {
+
+ return OS::get_singleton()->is_keep_screen_on();
+}
String _OS::get_system_dir(SystemDir p_dir) const {
@@ -775,6 +784,8 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_screen_orientation","orientation"),&_OS::set_screen_orientation);
ObjectTypeDB::bind_method(_MD("get_screen_orientation"),&_OS::get_screen_orientation);
+ ObjectTypeDB::bind_method(_MD("set_keep_screen_on","enabled"),&_OS::set_keep_screen_on);
+ ObjectTypeDB::bind_method(_MD("is_keep_screen_on"),&_OS::is_keep_screen_on);
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);
@@ -810,9 +821,9 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_time","utc"),&_OS::get_time,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_time_zone_info"),&_OS::get_time_zone_info);
ObjectTypeDB::bind_method(_MD("get_unix_time"),&_OS::get_unix_time);
- ObjectTypeDB::bind_method(_MD("get_system_time_msec"), &_OS::get_system_time_msec);
+ ObjectTypeDB::bind_method(_MD("get_system_time_secs"), &_OS::get_system_time_secs);
- ObjectTypeDB::bind_method(_MD("set_icon"),&_OS::set_icon);
+ ObjectTypeDB::bind_method(_MD("set_icon","icon"),&_OS::set_icon);
ObjectTypeDB::bind_method(_MD("delay_usec","usec"),&_OS::delay_usec);
ObjectTypeDB::bind_method(_MD("delay_msec","msec"),&_OS::delay_msec);
@@ -851,9 +862,9 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_frames_per_second"),&_OS::get_frames_per_second);
ObjectTypeDB::bind_method(_MD("print_all_textures_by_size"),&_OS::print_all_textures_by_size);
- ObjectTypeDB::bind_method(_MD("print_resources_by_type"),&_OS::print_resources_by_type);
+ ObjectTypeDB::bind_method(_MD("print_resources_by_type","types"),&_OS::print_resources_by_type);
- ObjectTypeDB::bind_method(_MD("native_video_play"),&_OS::native_video_play);
+ ObjectTypeDB::bind_method(_MD("native_video_play","path","volume","audio_track","subtitle_track"),&_OS::native_video_play);
ObjectTypeDB::bind_method(_MD("native_video_is_playing"),&_OS::native_video_is_playing);
ObjectTypeDB::bind_method(_MD("native_video_stop"),&_OS::native_video_stop);
ObjectTypeDB::bind_method(_MD("native_video_pause"),&_OS::native_video_pause);
@@ -1509,6 +1520,7 @@ void _File::_bind_methods() {
BIND_CONSTANT( READ );
BIND_CONSTANT( WRITE );
BIND_CONSTANT( READ_WRITE );
+ BIND_CONSTANT( WRITE_READ );
}
_File::_File(){
@@ -1883,6 +1895,14 @@ void _Thread::_start_func(void *ud) {
Variant::CallError ce;
const Variant* arg[1]={&t->userdata};
+ // we don't know our thread pointer yet :(
+ if (t->name == "") {
+ // come up with a better name using maybe the filename on the Script?
+ //t->thread->set_name(t->target_method);
+ } else {
+ //t->thread->set_name(t->name);
+ };
+
t->ret=t->target_instance->call(t->target_method,arg,1,ce);
if (ce.error!=Variant::CallError::CALL_OK) {
@@ -1972,12 +1992,24 @@ Variant _Thread::wait_to_finish() {
return r;
}
+Error _Thread::set_name(const String &p_name) {
+
+ name = p_name;
+
+ if (thread) {
+ return thread->set_name(p_name);
+ };
+
+ return OK;
+};
+
void _Thread::_bind_methods() {
ObjectTypeDB::bind_method(_MD("start:Error","instance","method","userdata","priority"),&_Thread::start,DEFVAL(Variant()),DEFVAL(PRIORITY_NORMAL));
ObjectTypeDB::bind_method(_MD("get_id"),&_Thread::get_id);
ObjectTypeDB::bind_method(_MD("is_active"),&_Thread::is_active);
- ObjectTypeDB::bind_method(_MD("wait_to_finish:var"),&_Thread::wait_to_finish);
+ ObjectTypeDB::bind_method(_MD("wait_to_finish:Variant"),&_Thread::wait_to_finish);
+ ObjectTypeDB::bind_method(_MD("set_name:Error", "name"),&_Thread::set_name);
BIND_CONSTANT( PRIORITY_LOW );
BIND_CONSTANT( PRIORITY_NORMAL );
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 24ea810767..e03657f3a0 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -208,7 +208,7 @@ public:
Dictionary get_time(bool utc) const;
Dictionary get_time_zone_info() const;
uint64_t get_unix_time() const;
- uint64_t get_system_time_msec() const;
+ uint64_t get_system_time_secs() const;
int get_static_memory_usage() const;
int get_static_memory_peak_usage() const;
@@ -262,6 +262,9 @@ public:
void set_screen_orientation(ScreenOrientation p_orientation);
ScreenOrientation get_screen_orientation() const;
+ void set_keep_screen_on(bool p_enabled);
+ bool is_keep_screen_on() const;
+
void set_time_scale(float p_scale);
float get_time_scale();
@@ -329,6 +332,7 @@ public:
READ=1,
WRITE=2,
READ_WRITE=3,
+ WRITE_READ=7,
};
Error open_encrypted(const String& p_path, int p_mode_flags,const Vector<uint8_t>& p_key);
@@ -508,6 +512,7 @@ protected:
Object *target_instance;
StringName target_method;
Thread *thread;
+ String name;
static void _bind_methods();
static void _start_func(void *ud);
public:
@@ -523,6 +528,7 @@ public:
String get_id() const;
bool is_active() const;
Variant wait_to_finish();
+ Error set_name(const String& p_name);
_Thread();
~_Thread();
diff --git a/core/color.cpp b/core/color.cpp
index 32f3df6d4b..c53de360bc 100644
--- a/core/color.cpp
+++ b/core/color.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/color.h b/core/color.h
index d5d5a4ea09..d0a1e8835c 100644
--- a/core/color.h
+++ b/core/color.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/command_queue_mt.cpp b/core/command_queue_mt.cpp
index f28617b33c..a2507b1378 100644
--- a/core/command_queue_mt.cpp
+++ b/core/command_queue_mt.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h
index 113199869b..4fd33e3a55 100644
--- a/core/command_queue_mt.h
+++ b/core/command_queue_mt.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -983,7 +983,7 @@ public:
void flush_all() {
- ERR_FAIL_COND(sync);
+ //ERR_FAIL_COND(sync);
lock();
while (true) {
bool exit = !flush_one();
diff --git a/core/compressed_translation.cpp b/core/compressed_translation.cpp
index 45fd4b5080..b104b8062a 100644
--- a/core/compressed_translation.cpp
+++ b/core/compressed_translation.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -410,15 +410,15 @@ bool PHashTranslation::_set(const StringName& p_name, const Variant& p_value) {
String name = p_name.operator String();
if (name=="hash_table") {
hash_table=p_value;
- print_line("translation: loaded hash table of size: "+itos(hash_table.size()));
+ //print_line("translation: loaded hash table of size: "+itos(hash_table.size()));
} else if (name=="bucket_table") {
bucket_table=p_value;
- print_line("translation: loaded bucket table of size: "+itos(bucket_table.size()));
+ //print_line("translation: loaded bucket table of size: "+itos(bucket_table.size()));
} else if (name=="strings") {
strings=p_value;
- print_line("translation: loaded string table of size: "+itos(strings.size()));
+ //print_line("translation: loaded string table of size: "+itos(strings.size()));
} else if (name=="load_from") {
- print_line("generating");
+ //print_line("generating");
generate(p_value);
} else
return false;
diff --git a/core/compressed_translation.h b/core/compressed_translation.h
index c41e2afb53..a1406ce1b2 100644
--- a/core/compressed_translation.h
+++ b/core/compressed_translation.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/core_string_names.cpp b/core/core_string_names.cpp
index d0cd19768f..8605b9131b 100644
--- a/core/core_string_names.cpp
+++ b/core/core_string_names.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/core_string_names.h b/core/core_string_names.h
index 8bda1f3f79..ef9e846c47 100644
--- a/core/core_string_names.h
+++ b/core/core_string_names.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/dictionary.cpp b/core/dictionary.cpp
index b2d31f230d..a013c21b29 100644
--- a/core/dictionary.cpp
+++ b/core/dictionary.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -160,7 +160,20 @@ void Dictionary::_unref() const {
}
uint32_t Dictionary::hash() const {
- return hash_djb2_one_64(make_uint64_t(_p));
+ uint32_t h=hash_djb2_one_32(Variant::DICTIONARY);
+
+ List<Variant> keys;
+ get_key_list(&keys);
+
+ for (List<Variant>::Element *E=keys.front();E;E=E->next()) {
+
+ h = hash_djb2_one_32( E->get().hash(), h);
+ h = hash_djb2_one_32( operator[](E->get()).hash(), h);
+
+ }
+
+
+ return h;
}
Array Dictionary::keys() const {
diff --git a/core/dictionary.h b/core/dictionary.h
index 8cbabfc65d..145e7e5c84 100644
--- a/core/dictionary.h
+++ b/core/dictionary.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/dvector.cpp b/core/dvector.cpp
index 60aa2e079f..fa06399139 100644
--- a/core/dvector.cpp
+++ b/core/dvector.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/dvector.h b/core/dvector.h
index 2c75bbf9eb..17431b33a6 100644
--- a/core/dvector.h
+++ b/core/dvector.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/error_list.h b/core/error_list.h
index 92c417154c..cb531f527f 100644
--- a/core/error_list.h
+++ b/core/error_list.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/error_macros.cpp b/core/error_macros.cpp
index 53bce56626..03e5ba37da 100644
--- a/core/error_macros.cpp
+++ b/core/error_macros.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/error_macros.h b/core/error_macros.h
index 76da88287b..cafbf0c16e 100644
--- a/core/error_macros.h
+++ b/core/error_macros.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -207,6 +207,11 @@ extern bool _err_error_exists;
_err_error_exists=false;\
} \
+#define ERR_PRINTS(m_string) \
+ { \
+ _err_print_error(FUNCTION_STR,__FILE__,__LINE__,String(m_string).utf8().get_data()); \
+ _err_error_exists=false;\
+ } \
/** Print a warning string.
*/
diff --git a/core/event_queue.cpp b/core/event_queue.cpp
index 1afd686f86..088e80b266 100644
--- a/core/event_queue.cpp
+++ b/core/event_queue.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/event_queue.h b/core/event_queue.h
index 51ed7373eb..af0a4df2b8 100644
--- a/core/event_queue.h
+++ b/core/event_queue.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/fpstr.cpp b/core/fpstr.cpp
index 20b527d88b..76046d0b99 100644
--- a/core/fpstr.cpp
+++ b/core/fpstr.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/fpstr.h b/core/fpstr.h
index c8ff80806e..d3d02733b3 100644
--- a/core/fpstr.h
+++ b/core/fpstr.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/global_constants.cpp b/core/global_constants.cpp
index 9fb45c672a..92e50a8b96 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -402,6 +402,9 @@ static _GlobalConstant _global_constants[]={
BIND_GLOBAL_CONSTANT( JOY_ANALOG_2_X ),
BIND_GLOBAL_CONSTANT( JOY_ANALOG_2_Y ),
+ BIND_GLOBAL_CONSTANT( JOY_ANALOG_L2 ),
+ BIND_GLOBAL_CONSTANT( JOY_ANALOG_R2 ),
+
// error list
diff --git a/core/global_constants.h b/core/global_constants.h
index 77cd3724c6..f7f6677482 100644
--- a/core/global_constants.h
+++ b/core/global_constants.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/globals.cpp b/core/globals.cpp
index aee708d0cd..1e60854f28 100644
--- a/core/globals.cpp
+++ b/core/globals.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -132,8 +132,12 @@ bool Globals::_set(const StringName& p_name, const Variant& p_value) {
if (props.has(p_name)) {
if (!props[p_name].overrided)
props[p_name].variant=p_value;
+
+ if (props[p_name].order>=NO_ORDER_BASE && registering_order) {
+ props[p_name].order=last_order++;
+ }
} else {
- props[p_name]=VariantContainer(p_value,last_order++);
+ props[p_name]=VariantContainer(p_value,last_order++ + (registering_order?0:NO_ORDER_BASE));
}
}
@@ -300,6 +304,7 @@ Error Globals::setup(const String& p_path,const String & p_main_pack) {
return OK;
}
+
if (OS::get_singleton()->get_resource_dir()!="") {
//OS will call Globals->get_resource_path which will be empty if not overriden!
//if the OS would rather use somewhere else, then it will not be empty.
@@ -309,7 +314,7 @@ Error Globals::setup(const String& p_path,const String & p_main_pack) {
print_line("has res dir: "+resource_path);
if (!_load_resource_pack("res://data.pck"))
- _load_resource_pack("res://data.pcz");
+ _load_resource_pack("res://data.zip");
// make sure this is load from the resource path
print_line("exists engine cfg? "+itos(FileAccess::exists("/engine.cfg")));
if (_load_settings("res://engine.cfg")==OK || _load_settings_binary("res://engine.cfb")==OK) {
@@ -340,7 +345,7 @@ Error Globals::setup(const String& p_path,const String & p_main_pack) {
//try to load settings in ascending through dirs shape!
//tries to open pack, but only first time
- if (first_time && (_load_resource_pack(current_dir+"/"+exec_name+".pck") || _load_resource_pack(current_dir+"/"+exec_name+".pcz") )) {
+ if (first_time && (_load_resource_pack(current_dir+"/"+exec_name+".pck") || _load_resource_pack(current_dir+"/"+exec_name+".zip") )) {
if (_load_settings("res://engine.cfg")==OK || _load_settings_binary("res://engine.cfb")==OK) {
_load_settings("res://override.cfg");
@@ -349,7 +354,7 @@ Error Globals::setup(const String& p_path,const String & p_main_pack) {
}
break;
- } else if (first_time && (_load_resource_pack(current_dir+"/data.pck") || _load_resource_pack(current_dir+"/data.pcz") )) {
+ } else if (first_time && (_load_resource_pack(current_dir+"/data.pck") || _load_resource_pack(current_dir+"/data.zip") )) {
if (_load_settings("res://engine.cfg")==OK || _load_settings_binary("res://engine.cfb")==OK) {
_load_settings("res://override.cfg");
@@ -633,7 +638,9 @@ static Variant _decode_variant(const String& p_string) {
InputEvent ie;
ie.type=InputEvent::JOYSTICK_MOTION;
ie.device=params[0].to_int();
- ie.joy_motion.axis=params[1].to_int();
+ int axis = params[1].to_int();;
+ ie.joy_motion.axis=axis>>1;
+ ie.joy_motion.axis_value=axis&1?1:-1;
return ie;
}
@@ -741,6 +748,10 @@ static Variant _decode_variant(const String& p_string) {
return Variant();
}
+void Globals::set_registering_order(bool p_enable) {
+
+ registering_order=p_enable;
+}
Error Globals::_load_settings_binary(const String p_path) {
@@ -760,6 +771,8 @@ Error Globals::_load_settings_binary(const String p_path) {
ERR_FAIL_V(ERR_FILE_CORRUPT;)
}
+ set_registering_order(false);
+
uint32_t count=f->get_32();
for(int i=0;i<count;i++) {
@@ -784,6 +797,9 @@ Error Globals::_load_settings_binary(const String p_path) {
set_persisting(key,true);
}
+ set_registering_order(true);
+
+
return OK;
}
Error Globals::_load_settings(const String p_path) {
@@ -802,6 +818,8 @@ Error Globals::_load_settings(const String p_path) {
String section;
String subpath;
+ set_registering_order(false);
+
int line_count = 0;
while(!f->eof_reached()) {
@@ -877,6 +895,7 @@ Error Globals::_load_settings(const String p_path) {
memdelete(f);
+ set_registering_order(true);
return OK;
}
@@ -1012,7 +1031,7 @@ static String _encode_variant(const Variant& p_variant) {
} break;
case InputEvent::JOYSTICK_MOTION: {
- return "jaxis("+itos(ev.device)+", "+itos(ev.joy_motion.axis)+")";
+ return "jaxis("+itos(ev.device)+", "+itos(ev.joy_motion.axis * 2 + (ev.joy_motion.axis_value<0?0:1))+")";
} break;
default: {
@@ -1374,11 +1393,11 @@ void Globals::_bind_methods() {
ObjectTypeDB::bind_method(_MD("localize_path","path"),&Globals::localize_path);
ObjectTypeDB::bind_method(_MD("globalize_path","path"),&Globals::globalize_path);
ObjectTypeDB::bind_method(_MD("save"),&Globals::save);
- ObjectTypeDB::bind_method(_MD("has_singleton"),&Globals::has_singleton);
- ObjectTypeDB::bind_method(_MD("get_singleton"),&Globals::get_singleton_object);
- ObjectTypeDB::bind_method(_MD("load_resource_pack"),&Globals::_load_resource_pack);
+ ObjectTypeDB::bind_method(_MD("has_singleton","name"),&Globals::has_singleton);
+ ObjectTypeDB::bind_method(_MD("get_singleton","name"),&Globals::get_singleton_object);
+ ObjectTypeDB::bind_method(_MD("load_resource_pack","pack"),&Globals::_load_resource_pack);
- ObjectTypeDB::bind_method(_MD("save_custom"),&Globals::_save_custom_bnd);
+ ObjectTypeDB::bind_method(_MD("save_custom","file"),&Globals::_save_custom_bnd);
}
@@ -1388,7 +1407,7 @@ Globals::Globals() {
singleton=this;
last_order=0;
disable_platform_override=false;
-
+ registering_order=true;
Array va;
@@ -1414,6 +1433,7 @@ Globals::Globals() {
joyb.joy_button.button_index=JOY_BUTTON_0;
va.push_back(joyb);
set("input/ui_accept",va);
+ input_presets.push_back("input/ui_accept");
va=Array();
key.key.scancode=KEY_SPACE;
@@ -1421,6 +1441,7 @@ Globals::Globals() {
joyb.joy_button.button_index=JOY_BUTTON_3;
va.push_back(joyb);
set("input/ui_select",va);
+ input_presets.push_back("input/ui_select");
va=Array();
key.key.scancode=KEY_ESCAPE;
@@ -1428,17 +1449,20 @@ Globals::Globals() {
joyb.joy_button.button_index=JOY_BUTTON_1;
va.push_back(joyb);
set("input/ui_cancel",va);
+ input_presets.push_back("input/ui_cancel");
va=Array();
key.key.scancode=KEY_TAB;
va.push_back(key);
set("input/ui_focus_next",va);
+ input_presets.push_back("input/ui_focus_next");
va=Array();
key.key.scancode=KEY_TAB;
key.key.mod.shift=true;
va.push_back(key);
set("input/ui_focus_prev",va);
+ input_presets.push_back("input/ui_focus_prev");
key.key.mod.shift=false;
va=Array();
@@ -1447,6 +1471,7 @@ Globals::Globals() {
joyb.joy_button.button_index=JOY_DPAD_LEFT;
va.push_back(joyb);
set("input/ui_left",va);
+ input_presets.push_back("input/ui_left");
va=Array();
key.key.scancode=KEY_RIGHT;
@@ -1454,6 +1479,7 @@ Globals::Globals() {
joyb.joy_button.button_index=JOY_DPAD_RIGHT;
va.push_back(joyb);
set("input/ui_right",va);
+ input_presets.push_back("input/ui_right");
va=Array();
key.key.scancode=KEY_UP;
@@ -1461,6 +1487,7 @@ Globals::Globals() {
joyb.joy_button.button_index=JOY_DPAD_UP;
va.push_back(joyb);
set("input/ui_up",va);
+ input_presets.push_back("input/ui_up");
va=Array();
key.key.scancode=KEY_DOWN;
@@ -1468,17 +1495,20 @@ Globals::Globals() {
joyb.joy_button.button_index=JOY_DPAD_DOWN;
va.push_back(joyb);
set("input/ui_down",va);
+ input_presets.push_back("input/ui_down");
va=Array();
key.key.scancode=KEY_PAGEUP;
va.push_back(key);
set("input/ui_page_up",va);
+ input_presets.push_back("input/ui_page_up");
va=Array();
key.key.scancode=KEY_PAGEDOWN;
va.push_back(key);
set("input/ui_page_down",va);
+ input_presets.push_back("input/ui_page_down");
// set("display/orientation", "landscape");
diff --git a/core/globals.h b/core/globals.h
index 2ec56966f6..8951f5fbd2 100644
--- a/core/globals.h
+++ b/core/globals.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -54,6 +54,10 @@ public:
protected:
+ enum {
+ NO_ORDER_BASE=1<<18
+ };
+
struct VariantContainer {
int order;
bool persist;
@@ -64,12 +68,14 @@ protected:
VariantContainer(const Variant& p_variant, int p_order, bool p_persist=false) { variant=p_variant; order=p_order; hide_from_editor=false; persist=p_persist; overrided=false; }
};
+ bool registering_order;
int last_order;
Map<StringName,VariantContainer> props;
String resource_path;
Map<StringName,PropertyInfo> custom_prop_info;
bool disable_platform_override;
bool using_datapack;
+ List<String> input_presets;
bool _set(const StringName& p_name, const Variant& p_value);
@@ -124,6 +130,8 @@ public:
Vector<String> get_optimizer_presets() const;
+ List<String> get_input_presets() const { return input_presets; }
+
void set_disable_platform_override(bool p_disable);
Object* get_singleton_object(const String& p_name) const;
@@ -131,6 +139,8 @@ public:
bool is_using_datapack() const;
+ void set_registering_order(bool p_registering);
+
Globals();
~Globals();
diff --git a/core/hash_map.h b/core/hash_map.h
index eea6d1a153..33eb25652c 100644
--- a/core/hash_map.h
+++ b/core/hash_map.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/hashfuncs.h b/core/hashfuncs.h
index b12950f160..c2ed5bd679 100644
--- a/core/hashfuncs.h
+++ b/core/hashfuncs.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/image.cpp b/core/image.cpp
index eadb7ecc8b..798fc41f40 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/image.h b/core/image.h
index a155823af7..aea5dc6438 100644
--- a/core/image.h
+++ b/core/image.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/image_quantize.cpp b/core/image_quantize.cpp
index a14e0ab72e..b8d4658fda 100644
--- a/core/image_quantize.cpp
+++ b/core/image_quantize.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/input_map.cpp b/core/input_map.cpp
index 24151c59c9..d4560a1e1b 100644
--- a/core/input_map.cpp
+++ b/core/input_map.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -204,6 +204,64 @@ bool InputMap::event_is_action(const InputEvent& p_event, const StringName& p_ac
return _find_event(E->get().inputs,p_event)!=NULL;
}
+bool InputMap::event_is_joy_motion_action_pressed(const InputEvent& p_event) const {
+
+ ERR_FAIL_COND_V(p_event.type!=InputEvent::JOYSTICK_MOTION,false);
+ bool pressed=false;
+
+ //this could be optimized by having a separate list of joymotions?
+
+ for (Map<StringName, Action>::Element *A=input_map.front();A;A=A->next()) {
+
+ for (List<InputEvent>::Element *E=A->get().inputs.front();E;E=E->next()) {
+
+ const InputEvent& e=E->get();
+ if(e.type!=p_event.type)
+ continue;
+ if (e.type!=InputEvent::KEY && e.device!=p_event.device)
+ continue;
+
+ switch(p_event.type) {
+
+ case InputEvent::KEY: {
+
+ if (e.key.scancode==p_event.key.scancode && e.key.mod == p_event.key.mod)
+ return e.key.pressed;
+
+ } break;
+ case InputEvent::JOYSTICK_BUTTON: {
+
+ if (e.joy_button.button_index==p_event.joy_button.button_index) {
+ return e.joy_button.pressed;
+ }
+
+ } break;
+ case InputEvent::MOUSE_BUTTON: {
+
+ if (e.mouse_button.button_index==p_event.mouse_button.button_index) {
+ return e.mouse_button.pressed;
+ }
+
+ } break;
+ case InputEvent::JOYSTICK_MOTION: {
+
+ if (e.joy_motion.axis==p_event.joy_motion.axis) {
+ if (
+ (e.joy_motion.axis_value * p_event.joy_motion.axis_value >0) && //same axis
+ ABS(e.joy_motion.axis_value)>0.5 && ABS(p_event.joy_motion.axis_value)>0.5 )
+ pressed=true;
+ }
+
+ } break;
+ }
+
+ }
+ }
+
+ return pressed;
+
+}
+
void InputMap::load_from_globals() {
input_map.clear();;
diff --git a/core/input_map.h b/core/input_map.h
index c5b21b1457..5cd1e41922 100644
--- a/core/input_map.h
+++ b/core/input_map.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -68,6 +68,7 @@ public:
const List<InputEvent> *get_action_list(const StringName& p_action);
bool event_is_action(const InputEvent& p_event, const StringName& p_action) const;
+ bool event_is_joy_motion_action_pressed(const InputEvent& p_event) const;
void load_from_globals();
diff --git a/core/int_types.h b/core/int_types.h
index 231196b808..7d7c4b16b0 100644
--- a/core/int_types.h
+++ b/core/int_types.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/aes256.cpp b/core/io/aes256.cpp
index e7f465dcc6..cfdac0214d 100644
--- a/core/io/aes256.cpp
+++ b/core/io/aes256.cpp
@@ -1,8 +1,8 @@
-/*
+/*
* Byte-oriented AES-256 implementation.
-* All lookup tables replaced with 'on the fly' calculations.
+* All lookup tables replaced with 'on the fly' calculations.
*
-* Copyright (c) 2007-2009 Ilya O. Levin, http://www.literatecode.com
+* Copyright (c) 2007-2011 Ilya O. Levin, http://www.literatecode.com
* Other contributors: Hal Finney
*
* Permission to use, copy, modify, and distribute this software for any
@@ -19,13 +19,33 @@
*/
#include "aes256.h"
-#define F(x) (((x)<<1) ^ ((((x)>>7) & 1) * 0x1b))
#define FD(x) (((x) >> 1) ^ (((x) & 1) ? 0x8d : 0))
-// #define BACK_TO_TABLES
+#define BACK_TO_TABLES
+
+static uint8_t rj_xtime(uint8_t);
+static void aes_subBytes(uint8_t *);
+static void aes_subBytes_inv(uint8_t *);
+static void aes_addRoundKey(uint8_t *, uint8_t *);
+static void aes_addRoundKey_cpy(uint8_t *, uint8_t *, uint8_t *);
+static void aes_shiftRows(uint8_t *);
+static void aes_shiftRows_inv(uint8_t *);
+static void aes_mixColumns(uint8_t *);
+static void aes_mixColumns_inv(uint8_t *);
+static void aes_expandEncKey(uint8_t *, uint8_t *);
+static void aes_expandDecKey(uint8_t *, uint8_t *);
+#ifndef BACK_TO_TABLES
+static uint8_t gf_alog(uint8_t);
+static uint8_t gf_log(uint8_t);
+static uint8_t gf_mulinv(uint8_t);
+static uint8_t rj_sbox(uint8_t);
+static uint8_t rj_sbox_inv(uint8_t);
+#endif
+
#ifdef BACK_TO_TABLES
-const uint8_t sbox[256] = {
+static const uint8_t sbox[256] =
+{
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
@@ -59,7 +79,8 @@ const uint8_t sbox[256] = {
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
-const uint8_t sboxinv[256] = {
+static const uint8_t sboxinv[256] =
+{
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
@@ -100,55 +121,62 @@ const uint8_t sboxinv[256] = {
#else /* tableless subroutines */
/* -------------------------------------------------------------------------- */
-uint8_t gf_alog(uint8_t x) // calculate anti-logarithm gen 3
+static uint8_t gf_alog(uint8_t x) // calculate anti-logarithm gen 3
{
- uint8_t atb = 1, z;
+ uint8_t y = 1, i;
- while (x--) {z = atb; atb <<= 1; if (z & 0x80) atb^= 0x1b; atb ^= z;}
+ for (i = 0; i < x; i++) y ^= rj_xtime(y);
- return atb;
+ return y;
} /* gf_alog */
/* -------------------------------------------------------------------------- */
-uint8_t gf_log(uint8_t x) // calculate logarithm gen 3
+static uint8_t gf_log(uint8_t x) // calculate logarithm gen 3
{
- uint8_t atb = 1, i = 0, z;
+ uint8_t y, i = 0;
- do {
- if (atb == x) break;
- z = atb; atb <<= 1; if (z & 0x80) atb^= 0x1b; atb ^= z;
- } while (++i > 0);
+ if (x)
+ for (i = 1, y = 1; i > 0; i++ )
+ {
+ y ^= rj_xtime(y);
+ if (y == x) break;
+ }
return i;
} /* gf_log */
/* -------------------------------------------------------------------------- */
-uint8_t gf_mulinv(uint8_t x) // calculate multiplicative inverse
+static uint8_t gf_mulinv(uint8_t x) // calculate multiplicative inverse
{
return (x) ? gf_alog(255 - gf_log(x)) : 0;
} /* gf_mulinv */
/* -------------------------------------------------------------------------- */
-uint8_t rj_sbox(uint8_t x)
+static uint8_t rj_sbox(uint8_t x)
{
uint8_t y, sb;
sb = y = gf_mulinv(x);
- y = (y<<1)|(y>>7); sb ^= y; y = (y<<1)|(y>>7); sb ^= y;
- y = (y<<1)|(y>>7); sb ^= y; y = (y<<1)|(y>>7); sb ^= y;
+ y = (uint8_t)(y << 1) | (y >> 7), sb ^= y;
+ y = (uint8_t)(y << 1) | (y >> 7), sb ^= y;
+ y = (uint8_t)(y << 1) | (y >> 7), sb ^= y;
+ y = (uint8_t)(y << 1) | (y >> 7), sb ^= y;
return (sb ^ 0x63);
} /* rj_sbox */
/* -------------------------------------------------------------------------- */
-uint8_t rj_sbox_inv(uint8_t x)
+static uint8_t rj_sbox_inv(uint8_t x)
{
uint8_t y, sb;
y = x ^ 0x63;
- sb = y = (y<<1)|(y>>7);
- y = (y<<2)|(y>>6); sb ^= y; y = (y<<3)|(y>>5); sb ^= y;
+ sb = y = (uint8_t)(y << 1) | (y >> 7);
+ y = (uint8_t)(y << 2) | (y >> 6);
+ sb ^= y;
+ y = (uint8_t)(y << 3) | (y >> 5);
+ sb ^= y;
return gf_mulinv(sb);
} /* rj_sbox_inv */
@@ -156,13 +184,14 @@ uint8_t rj_sbox_inv(uint8_t x)
#endif
/* -------------------------------------------------------------------------- */
-uint8_t rj_xtime(uint8_t x)
+static uint8_t rj_xtime(uint8_t x)
{
- return (x & 0x80) ? ((x << 1) ^ 0x1b) : (x << 1);
+ uint8_t y = (uint8_t)(x << 1);
+ return (x & 0x80) ? (y ^ 0x1b) : y;
} /* rj_xtime */
/* -------------------------------------------------------------------------- */
-void aes_subBytes(uint8_t *buf)
+static void aes_subBytes(uint8_t *buf)
{
register uint8_t i = 16;
@@ -170,7 +199,7 @@ void aes_subBytes(uint8_t *buf)
} /* aes_subBytes */
/* -------------------------------------------------------------------------- */
-void aes_subBytes_inv(uint8_t *buf)
+static void aes_subBytes_inv(uint8_t *buf)
{
register uint8_t i = 16;
@@ -178,7 +207,7 @@ void aes_subBytes_inv(uint8_t *buf)
} /* aes_subBytes_inv */
/* -------------------------------------------------------------------------- */
-void aes_addRoundKey(uint8_t *buf, uint8_t *key)
+static void aes_addRoundKey(uint8_t *buf, uint8_t *key)
{
register uint8_t i = 16;
@@ -186,49 +215,54 @@ void aes_addRoundKey(uint8_t *buf, uint8_t *key)
} /* aes_addRoundKey */
/* -------------------------------------------------------------------------- */
-void aes_addRoundKey_cpy(uint8_t *buf, uint8_t *key, uint8_t *cpk)
+static void aes_addRoundKey_cpy(uint8_t *buf, uint8_t *key, uint8_t *cpk)
{
register uint8_t i = 16;
- while (i--) buf[i] ^= (cpk[i] = key[i]), cpk[16+i] = key[16 + i];
+ while (i--) buf[i] ^= (cpk[i] = key[i]), cpk[16 + i] = key[16 + i];
} /* aes_addRoundKey_cpy */
/* -------------------------------------------------------------------------- */
-void aes_shiftRows(uint8_t *buf)
+static void aes_shiftRows(uint8_t *buf)
{
register uint8_t i, j; /* to make it potentially parallelable :) */
- i = buf[1]; buf[1] = buf[5]; buf[5] = buf[9]; buf[9] = buf[13]; buf[13] = i;
- i = buf[10]; buf[10] = buf[2]; buf[2] = i;
- j = buf[3]; buf[3] = buf[15]; buf[15] = buf[11]; buf[11] = buf[7]; buf[7] = j;
- j = buf[14]; buf[14] = buf[6]; buf[6] = j;
+ i = buf[1], buf[1] = buf[5], buf[5] = buf[9], buf[9] = buf[13], buf[13] = i;
+ i = buf[10], buf[10] = buf[2], buf[2] = i;
+ j = buf[3], buf[3] = buf[15], buf[15] = buf[11], buf[11] = buf[7], buf[7] = j;
+ j = buf[14], buf[14] = buf[6], buf[6] = j;
} /* aes_shiftRows */
/* -------------------------------------------------------------------------- */
-void aes_shiftRows_inv(uint8_t *buf)
+static void aes_shiftRows_inv(uint8_t *buf)
{
register uint8_t i, j; /* same as above :) */
- i = buf[1]; buf[1] = buf[13]; buf[13] = buf[9]; buf[9] = buf[5]; buf[5] = i;
- i = buf[2]; buf[2] = buf[10]; buf[10] = i;
- j = buf[3]; buf[3] = buf[7]; buf[7] = buf[11]; buf[11] = buf[15]; buf[15] = j;
- j = buf[6]; buf[6] = buf[14]; buf[14] = j;
+ i = buf[1], buf[1] = buf[13], buf[13] = buf[9], buf[9] = buf[5], buf[5] = i;
+ i = buf[2], buf[2] = buf[10], buf[10] = i;
+ j = buf[3], buf[3] = buf[7], buf[7] = buf[11], buf[11] = buf[15], buf[15] = j;
+ j = buf[6], buf[6] = buf[14], buf[14] = j;
} /* aes_shiftRows_inv */
/* -------------------------------------------------------------------------- */
-void aes_mixColumns(uint8_t *buf)
+static void aes_mixColumns(uint8_t *buf)
{
register uint8_t i, a, b, c, d, e;
for (i = 0; i < 16; i += 4)
{
- a = buf[i]; b = buf[i + 1]; c = buf[i + 2]; d = buf[i + 3];
+ a = buf[i];
+ b = buf[i + 1];
+ c = buf[i + 2];
+ d = buf[i + 3];
e = a ^ b ^ c ^ d;
- buf[i] ^= e ^ rj_xtime(a^b); buf[i+1] ^= e ^ rj_xtime(b^c);
- buf[i+2] ^= e ^ rj_xtime(c^d); buf[i+3] ^= e ^ rj_xtime(d^a);
+ buf[i] ^= e ^ rj_xtime(a ^ b);
+ buf[i + 1] ^= e ^ rj_xtime(b ^ c);
+ buf[i + 2] ^= e ^ rj_xtime(c ^ d);
+ buf[i + 3] ^= e ^ rj_xtime(d ^ a);
}
} /* aes_mixColumns */
@@ -239,17 +273,23 @@ void aes_mixColumns_inv(uint8_t *buf)
for (i = 0; i < 16; i += 4)
{
- a = buf[i]; b = buf[i + 1]; c = buf[i + 2]; d = buf[i + 3];
+ a = buf[i];
+ b = buf[i + 1];
+ c = buf[i + 2];
+ d = buf[i + 3];
e = a ^ b ^ c ^ d;
z = rj_xtime(e);
- x = e ^ rj_xtime(rj_xtime(z^a^c)); y = e ^ rj_xtime(rj_xtime(z^b^d));
- buf[i] ^= x ^ rj_xtime(a^b); buf[i+1] ^= y ^ rj_xtime(b^c);
- buf[i+2] ^= x ^ rj_xtime(c^d); buf[i+3] ^= y ^ rj_xtime(d^a);
+ x = e ^ rj_xtime(rj_xtime(z ^ a ^ c));
+ y = e ^ rj_xtime(rj_xtime(z ^ b ^ d));
+ buf[i] ^= x ^ rj_xtime(a ^ b);
+ buf[i + 1] ^= y ^ rj_xtime(b ^ c);
+ buf[i + 2] ^= x ^ rj_xtime(c ^ d);
+ buf[i + 3] ^= y ^ rj_xtime(d ^ a);
}
} /* aes_mixColumns_inv */
/* -------------------------------------------------------------------------- */
-void aes_expandEncKey(uint8_t *k, uint8_t *rc)
+static void aes_expandEncKey(uint8_t *k, uint8_t *rc)
{
register uint8_t i;
@@ -257,35 +297,35 @@ void aes_expandEncKey(uint8_t *k, uint8_t *rc)
k[1] ^= rj_sbox(k[30]);
k[2] ^= rj_sbox(k[31]);
k[3] ^= rj_sbox(k[28]);
- *rc = F( *rc);
+ *rc = rj_xtime( *rc);
- for(i = 4; i < 16; i += 4) k[i] ^= k[i-4], k[i+1] ^= k[i-3],
- k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];
+ for(i = 4; i < 16; i += 4) k[i] ^= k[i - 4], k[i + 1] ^= k[i - 3],
+ k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1];
k[16] ^= rj_sbox(k[12]);
k[17] ^= rj_sbox(k[13]);
k[18] ^= rj_sbox(k[14]);
k[19] ^= rj_sbox(k[15]);
- for(i = 20; i < 32; i += 4) k[i] ^= k[i-4], k[i+1] ^= k[i-3],
- k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];
+ for(i = 20; i < 32; i += 4) k[i] ^= k[i - 4], k[i + 1] ^= k[i - 3],
+ k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1];
} /* aes_expandEncKey */
/* -------------------------------------------------------------------------- */
-void aes_expandDecKey(uint8_t *k, uint8_t *rc)
+void aes_expandDecKey(uint8_t *k, uint8_t *rc)
{
uint8_t i;
- for(i = 28; i > 16; i -= 4) k[i+0] ^= k[i-4], k[i+1] ^= k[i-3],
- k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];
+ for(i = 28; i > 16; i -= 4) k[i + 0] ^= k[i - 4], k[i + 1] ^= k[i - 3],
+ k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1];
k[16] ^= rj_sbox(k[12]);
k[17] ^= rj_sbox(k[13]);
k[18] ^= rj_sbox(k[14]);
k[19] ^= rj_sbox(k[15]);
- for(i = 12; i > 0; i -= 4) k[i+0] ^= k[i-4], k[i+1] ^= k[i-3],
- k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];
+ for(i = 12; i > 0; i -= 4) k[i + 0] ^= k[i - 4], k[i + 1] ^= k[i - 3],
+ k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1];
*rc = FD(*rc);
k[0] ^= rj_sbox(k[29]) ^ (*rc);
@@ -302,7 +342,7 @@ void aes256_init(aes256_context *ctx, uint8_t *k)
register uint8_t i;
for (i = 0; i < sizeof(ctx->key); i++) ctx->enckey[i] = ctx->deckey[i] = k[i];
- for (i = 8;--i;) aes_expandEncKey(ctx->deckey, &rcon);
+ for (i = 8; --i;) aes_expandEncKey(ctx->deckey, &rcon);
} /* aes256_init */
/* -------------------------------------------------------------------------- */
@@ -310,7 +350,7 @@ void aes256_done(aes256_context *ctx)
{
register uint8_t i;
- for (i = 0; i < sizeof(ctx->key); i++)
+ for (i = 0; i < sizeof(ctx->key); i++)
ctx->key[i] = ctx->enckey[i] = ctx->deckey[i] = 0;
} /* aes256_done */
@@ -330,7 +370,7 @@ void aes256_encrypt_ecb(aes256_context *ctx, uint8_t *buf)
}
aes_subBytes(buf);
aes_shiftRows(buf);
- aes_expandEncKey(ctx->key, &rcon);
+ aes_expandEncKey(ctx->key, &rcon);
aes_addRoundKey(buf, ctx->key);
} /* aes256_encrypt */
@@ -345,7 +385,7 @@ void aes256_decrypt_ecb(aes256_context *ctx, uint8_t *buf)
for (i = 14, rcon = 0x80; --i;)
{
- if( ( i & 1 ) )
+ if( ( i & 1 ) )
{
aes_expandDecKey(ctx->key, &rcon);
aes_addRoundKey(buf, &ctx->key[16]);
@@ -355,5 +395,5 @@ void aes256_decrypt_ecb(aes256_context *ctx, uint8_t *buf)
aes_shiftRows_inv(buf);
aes_subBytes_inv(buf);
}
- aes_addRoundKey( buf, ctx->key);
+ aes_addRoundKey( buf, ctx->key);
} /* aes256_decrypt */
diff --git a/core/io/compression.cpp b/core/io/compression.cpp
index 729b7bec52..a17e358cbb 100644
--- a/core/io/compression.cpp
+++ b/core/io/compression.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/compression.h b/core/io/compression.h
index 106a3f0201..07a293c940 100644
--- a/core/io/compression.h
+++ b/core/io/compression.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index 75388f514a..fd20ec9404 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,6 +29,7 @@
#include "config_file.h"
#include "os/keyboard.h"
#include "os/file_access.h"
+#include "variant_parser.h"
StringArray ConfigFile::_get_sections() const {
@@ -83,10 +84,10 @@ void ConfigFile::set_value(const String& p_section, const String& p_key, const V
}
}
-Variant ConfigFile::get_value(const String& p_section, const String& p_key) const{
+Variant ConfigFile::get_value(const String& p_section, const String& p_key, Variant p_default) const {
- ERR_FAIL_COND_V(!values.has(p_section),Variant());
- ERR_FAIL_COND_V(!values[p_section].has(p_key),Variant());
+ ERR_FAIL_COND_V(!values.has(p_section),p_default);
+ ERR_FAIL_COND_V(!values[p_section].has(p_key),p_default);
return values[p_section][p_key];
}
@@ -118,151 +119,6 @@ void ConfigFile::get_section_keys(const String& p_section,List<String> *r_keys)
}
-static String _encode_variant(const Variant& p_variant) {
-
- switch(p_variant.get_type()) {
-
- case Variant::BOOL: {
- bool val = p_variant;
- return (val?"true":"false");
- } break;
- case Variant::INT: {
- int val = p_variant;
- return itos(val);
- } break;
- case Variant::REAL: {
- float val = p_variant;
- return rtos(val)+(val==int(val)?".0":"");
- } break;
- case Variant::STRING: {
- String val = p_variant;
- return "\""+val.xml_escape()+"\"";
- } break;
- case Variant::COLOR: {
-
- Color val = p_variant;
- return "#"+val.to_html();
- } break;
- case Variant::STRING_ARRAY:
- case Variant::INT_ARRAY:
- case Variant::REAL_ARRAY:
- case Variant::ARRAY: {
- Array arr = p_variant;
- String str="[";
- for(int i=0;i<arr.size();i++) {
-
- if (i>0)
- str+=", ";
- str+=_encode_variant(arr[i]);
- }
- str+="]";
- return str;
- } break;
- case Variant::DICTIONARY: {
- Dictionary d = p_variant;
- String str="{";
- List<Variant> keys;
- d.get_key_list(&keys);
- for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
-
- if (E!=keys.front())
- str+=", ";
- str+=_encode_variant(E->get());
- str+=":";
- str+=_encode_variant(d[E->get()]);
-
- }
- str+="}";
- return str;
- } break;
- case Variant::IMAGE: {
- String str="img(";
-
- Image img=p_variant;
- if (!img.empty()) {
-
- String format;
- switch(img.get_format()) {
-
- case Image::FORMAT_GRAYSCALE: format="grayscale"; break;
- case Image::FORMAT_INTENSITY: format="intensity"; break;
- case Image::FORMAT_GRAYSCALE_ALPHA: format="grayscale_alpha"; break;
- case Image::FORMAT_RGB: format="rgb"; break;
- case Image::FORMAT_RGBA: format="rgba"; break;
- case Image::FORMAT_INDEXED : format="indexed"; break;
- case Image::FORMAT_INDEXED_ALPHA: format="indexed_alpha"; break;
- case Image::FORMAT_BC1: format="bc1"; break;
- case Image::FORMAT_BC2: format="bc2"; break;
- case Image::FORMAT_BC3: format="bc3"; break;
- case Image::FORMAT_BC4: format="bc4"; break;
- case Image::FORMAT_BC5: format="bc5"; break;
- case Image::FORMAT_CUSTOM: format="custom custom_size="+itos(img.get_data().size())+""; break;
- default: {}
- }
-
- str+=format+", ";
- str+=itos(img.get_mipmaps())+", ";
- str+=itos(img.get_width())+", ";
- str+=itos(img.get_height())+", ";
- DVector<uint8_t> data = img.get_data();
- int ds=data.size();
- DVector<uint8_t>::Read r = data.read();
- for(int i=0;i<ds;i++) {
- uint8_t byte = r[i];
- const char hex[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
- char bstr[3]={ hex[byte>>4], hex[byte&0xF], 0};
- str+=bstr;
- }
- }
- str+=")";
- return str;
- } break;
- case Variant::INPUT_EVENT: {
-
- InputEvent ev = p_variant;
-
- switch(ev.type) {
-
- case InputEvent::KEY: {
-
- String mods;
- if (ev.key.mod.control)
- mods+="C";
- if (ev.key.mod.shift)
- mods+="S";
- if (ev.key.mod.alt)
- mods+="A";
- if (ev.key.mod.meta)
- mods+="M";
- if (mods!="")
- mods=", "+mods;
-
- return "key("+keycode_get_string(ev.key.scancode)+mods+")";
- } break;
- case InputEvent::MOUSE_BUTTON: {
-
- return "mbutton("+itos(ev.device)+", "+itos(ev.mouse_button.button_index)+")";
- } break;
- case InputEvent::JOYSTICK_BUTTON: {
-
- return "jbutton("+itos(ev.device)+", "+itos(ev.joy_button.button_index)+")";
- } break;
- case InputEvent::JOYSTICK_MOTION: {
-
- return "jaxis("+itos(ev.device)+", "+itos(ev.joy_motion.axis)+")";
- } break;
- default: {
-
- return "nil";
- } break;
-
- }
- } break;
- default: {}
- }
-
- return "nil"; //don't know wha to do with this
-}
Error ConfigFile::save(const String& p_path){
@@ -271,6 +127,8 @@ Error ConfigFile::save(const String& p_path){
FileAccess *file = FileAccess::open(p_path,FileAccess::WRITE,&err);
if (err) {
+ if (file)
+ memdelete(file);
return err;
}
@@ -283,7 +141,9 @@ Error ConfigFile::save(const String& p_path){
for(Map<String, Variant>::Element *F=E->get().front();F;F=F->next()) {
- file->store_string(F->key()+"="+_encode_variant(F->get())+"\n");
+ String vstr;
+ VariantWriter::write_to_string(F->get(),vstr);
+ file->store_string(F->key()+"="+vstr+"\n");
}
}
@@ -292,432 +152,49 @@ Error ConfigFile::save(const String& p_path){
return OK;
}
-static Vector<String> _decode_params(const String& p_string) {
-
- int begin=p_string.find("(");
- ERR_FAIL_COND_V(begin==-1,Vector<String>());
- begin++;
- int end=p_string.find(")");
- ERR_FAIL_COND_V(end<begin,Vector<String>());
- return p_string.substr(begin,end-begin).split(",");
-}
-
-static String _get_chunk(const String& str,int &pos, int close_pos) {
-
-
- enum {
- MIN_COMMA,
- MIN_COLON,
- MIN_CLOSE,
- MIN_QUOTE,
- MIN_PARENTHESIS,
- MIN_CURLY_OPEN,
- MIN_OPEN
- };
-
- int min_pos=close_pos;
- int min_what=MIN_CLOSE;
-
-#define TEST_MIN(m_how,m_what) \
-{\
-int res = str.find(m_how,pos);\
-if (res!=-1 && res < min_pos) {\
- min_pos=res;\
- min_what=m_what;\
-}\
-}\
-
-
- TEST_MIN(",",MIN_COMMA);
- TEST_MIN("[",MIN_OPEN);
- TEST_MIN("{",MIN_CURLY_OPEN);
- TEST_MIN("(",MIN_PARENTHESIS);
- TEST_MIN("\"",MIN_QUOTE);
-
- int end=min_pos;
-
-
- switch(min_what) {
-
- case MIN_COMMA: {
- } break;
- case MIN_CLOSE: {
- //end because it's done
- } break;
- case MIN_QUOTE: {
- end=str.find("\"",min_pos+1)+1;
- ERR_FAIL_COND_V(end==-1,Variant());
-
- } break;
- case MIN_PARENTHESIS: {
-
- end=str.find(")",min_pos+1)+1;
- ERR_FAIL_COND_V(end==-1,Variant());
-
- } break;
- case MIN_OPEN: {
- int level=1;
- end++;
- while(end<close_pos) {
-
- if (str[end]=='[')
- level++;
- if (str[end]==']') {
- level--;
- if (level==0)
- break;
- }
- end++;
- }
- ERR_FAIL_COND_V(level!=0,Variant());
- end++;
- } break;
- case MIN_CURLY_OPEN: {
- int level=1;
- end++;
- while(end<close_pos) {
-
- if (str[end]=='{')
- level++;
- if (str[end]=='}') {
- level--;
- if (level==0)
- break;
- }
- end++;
- }
- ERR_FAIL_COND_V(level!=0,Variant());
- end++;
- } break;
-
- }
-
- String ret = str.substr(pos,end-pos);
-
- pos=end;
- while(pos<close_pos) {
- if (str[pos]!=',' && str[pos]!=' ' && str[pos]!=':')
- break;
- pos++;
- }
-
- return ret;
-
-}
-
-
-static Variant _decode_variant(const String& p_string) {
-
-
- String str = p_string.strip_edges();
-
- if (str.nocasecmp_to("true")==0)
- return Variant(true);
- if (str.nocasecmp_to("false")==0)
- return Variant(false);
- if (str.nocasecmp_to("nil")==0)
- return Variant();
- if (str.is_valid_float()) {
- if (str.find(".")==-1)
- return str.to_int();
- else
- return str.to_double();
-
- }
- if (str.begins_with("#")) { //string
- return Color::html(str);
- }
- if (str.begins_with("\"")) { //string
- int end = str.find_last("\"");
- ERR_FAIL_COND_V(end==0,Variant());
- return str.substr(1,end-1).xml_unescape();
-
- }
-
- if (str.begins_with("[")) { //array
-
- int close_pos = str.find_last("]");
- ERR_FAIL_COND_V(close_pos==-1,Variant());
- Array array;
-
- int pos=1;
-
- while(pos<close_pos) {
-
- String s = _get_chunk(str,pos,close_pos);
- array.push_back(_decode_variant(s));
- }
- return array;
-
- }
-
- if (str.begins_with("{")) { //array
-
- int close_pos = str.find_last("}");
- ERR_FAIL_COND_V(close_pos==-1,Variant());
- Dictionary d;
-
- int pos=1;
-
- while(pos<close_pos) {
-
- String key = _get_chunk(str,pos,close_pos);
- String data = _get_chunk(str,pos,close_pos);
- d[_decode_variant(key)]=_decode_variant(data);
- }
- return d;
-
- }
- if (str.begins_with("key")) {
- Vector<String> params = _decode_params(p_string);
- ERR_FAIL_COND_V(params.size()!=1 && params.size()!=2,Variant());
- int scode=0;
-
- if (params[0].is_numeric()) {
- scode=params[0].to_int();
- if (scode < 10) {
- scode=KEY_0+scode;
- }
- } else
- scode=find_keycode(params[0]);
-
- InputEvent ie;
- ie.type=InputEvent::KEY;
- ie.key.scancode=scode;
-
- if (params.size()==2) {
- String mods=params[1];
- if (mods.findn("C")!=-1)
- ie.key.mod.control=true;
- if (mods.findn("A")!=-1)
- ie.key.mod.alt=true;
- if (mods.findn("S")!=-1)
- ie.key.mod.shift=true;
- if (mods.findn("M")!=-1)
- ie.key.mod.meta=true;
- }
- return ie;
-
- }
-
- if (str.begins_with("mbutton")) {
- Vector<String> params = _decode_params(p_string);
- ERR_FAIL_COND_V(params.size()!=2,Variant());
-
- InputEvent ie;
- ie.type=InputEvent::MOUSE_BUTTON;
- ie.device=params[0].to_int();
- ie.mouse_button.button_index=params[1].to_int();
-
- return ie;
- }
-
- if (str.begins_with("jbutton")) {
- Vector<String> params = _decode_params(p_string);
- ERR_FAIL_COND_V(params.size()!=2,Variant());
-
- InputEvent ie;
- ie.type=InputEvent::JOYSTICK_BUTTON;
- ie.device=params[0].to_int();
- ie.joy_button.button_index=params[1].to_int();
-
- return ie;
- }
-
- if (str.begins_with("jaxis")) {
- Vector<String> params = _decode_params(p_string);
- ERR_FAIL_COND_V(params.size()!=2,Variant());
-
- InputEvent ie;
- ie.type=InputEvent::JOYSTICK_MOTION;
- ie.device=params[0].to_int();
- ie.joy_motion.axis=params[1].to_int();
-
- return ie;
- }
- if (str.begins_with("img")) {
- Vector<String> params = _decode_params(p_string);
- if (params.size()==0) {
- return Image();
- }
-
- ERR_FAIL_COND_V(params.size()!=5,Image());
-
- String format=params[0].strip_edges();
-
- Image::Format imgformat;
-
- if (format=="grayscale") {
- imgformat=Image::FORMAT_GRAYSCALE;
- } else if (format=="intensity") {
- imgformat=Image::FORMAT_INTENSITY;
- } else if (format=="grayscale_alpha") {
- imgformat=Image::FORMAT_GRAYSCALE_ALPHA;
- } else if (format=="rgb") {
- imgformat=Image::FORMAT_RGB;
- } else if (format=="rgba") {
- imgformat=Image::FORMAT_RGBA;
- } else if (format=="indexed") {
- imgformat=Image::FORMAT_INDEXED;
- } else if (format=="indexed_alpha") {
- imgformat=Image::FORMAT_INDEXED_ALPHA;
- } else if (format=="bc1") {
- imgformat=Image::FORMAT_BC1;
- } else if (format=="bc2") {
- imgformat=Image::FORMAT_BC2;
- } else if (format=="bc3") {
- imgformat=Image::FORMAT_BC3;
- } else if (format=="bc4") {
- imgformat=Image::FORMAT_BC4;
- } else if (format=="bc5") {
- imgformat=Image::FORMAT_BC5;
- } else if (format=="custom") {
- imgformat=Image::FORMAT_CUSTOM;
- } else {
-
- ERR_FAIL_V( Image() );
- }
-
- int mipmaps=params[1].to_int();
- int w=params[2].to_int();
- int h=params[3].to_int();
-
- if (w == 0 && h == 0) {
- //r_v = Image(w, h, imgformat);
- return Image();
- };
-
-
- String data=params[4];
- int datasize=data.length()/2;
- DVector<uint8_t> pixels;
- pixels.resize(datasize);
- DVector<uint8_t>::Write wb = pixels.write();
- const CharType *cptr=data.c_str();
-
- int idx=0;
- uint8_t byte;
- while( idx<datasize*2) {
-
- CharType c=*(cptr++);
-
- ERR_FAIL_COND_V(c=='<',ERR_FILE_CORRUPT);
-
- if ( (c>='0' && c<='9') || (c>='A' && c<='F') || (c>='a' && c<='f') ) {
-
- if (idx&1) {
-
- byte|=HEX2CHR(c);
- wb[idx>>1]=byte;
- } else {
-
- byte=HEX2CHR(c)<<4;
- }
-
- idx++;
- }
-
- }
-
- wb = DVector<uint8_t>::Write();
-
- return Image(w,h,mipmaps,imgformat,pixels);
- }
-
- if (str.find(",")!=-1) { //vector2 or vector3
- Vector<float> farr = str.split_floats(",",true);
- if (farr.size()==2) {
- return Point2(farr[0],farr[1]);
- }
- if (farr.size()==3) {
- return Vector3(farr[0],farr[1],farr[2]);
- }
- ERR_FAIL_V(Variant());
- }
-
-
- return Variant();
-}
Error ConfigFile::load(const String& p_path) {
Error err;
FileAccess *f= FileAccess::open(p_path,FileAccess::READ,&err);
- if (err!=OK) {
-
- return err;
- }
-
-
- String line;
- String section;
- String subpath;
-
- int line_count = 0;
-
- while(!f->eof_reached()) {
-
- String line = f->get_line().strip_edges();
- line_count++;
-
- if (line=="")
- continue;
-
- // find comments
-
- {
+ if (!f)
+ return ERR_CANT_OPEN;
- int pos=0;
- while (true) {
- int ret = line.find(";",pos);
- if (ret==-1)
- break;
+ VariantParser::StreamFile stream;
+ stream.f=f;
- int qc=0;
- for(int i=0;i<ret;i++) {
+ String assign;
+ Variant value;
+ VariantParser::Tag next_tag;
- if (line[i]=='"')
- qc++;
- }
+ int lines=0;
+ String error_text;
- if ( !(qc&1) ) {
- //not inside string, real comment
- line=line.substr(0,ret);
- break;
-
- }
+ String section;
- pos=ret+1;
+ while(true) {
+ assign=Variant();
+ next_tag.fields.clear();
+ next_tag.name=String();
- }
+ err = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,NULL,true);
+ if (err==ERR_FILE_EOF) {
+ memdelete(f);
+ return OK;
+ }
+ else if (err!=OK) {
+ ERR_PRINTS("ConfgFile::load - "+p_path+":"+itos(lines)+" error: "+error_text);
+ memdelete(f);
+ return err;
}
- if (line.begins_with("[")) {
-
- int end = line.find_last("]");
- ERR_CONTINUE(end!=line.length()-1);
-
- section=line.substr(1,line.length()-2);
-
- } else if (line.find("=")!=-1) {
-
-
- int eqpos = line.find("=");
- String var=line.substr(0,eqpos).strip_edges();
- String value=line.substr(eqpos+1,line.length()).strip_edges();
-
- Variant val = _decode_variant(value);
-
- set_value(section,var,val);
-
- } else {
-
- if (line.length() > 0) {
- ERR_PRINT(String("Syntax error on line "+itos(line_count)+" of file "+p_path).ascii().get_data());
- };
- };
+ if (assign!=String()) {
+ set_value(section,assign,value);
+ } else if (next_tag.name!=String()) {
+ section=next_tag.name;
+ }
}
memdelete(f);
@@ -730,13 +207,13 @@ Error ConfigFile::load(const String& p_path) {
void ConfigFile::_bind_methods(){
ObjectTypeDB::bind_method(_MD("set_value","section","key","value"),&ConfigFile::set_value);
- ObjectTypeDB::bind_method(_MD("get_value","section","key"),&ConfigFile::get_value);
+ ObjectTypeDB::bind_method(_MD("get_value","section","key","default"),&ConfigFile::get_value,DEFVAL(Variant()));
ObjectTypeDB::bind_method(_MD("has_section","section"),&ConfigFile::has_section);
ObjectTypeDB::bind_method(_MD("has_section_key","section","key"),&ConfigFile::has_section_key);
ObjectTypeDB::bind_method(_MD("get_sections"),&ConfigFile::_get_sections);
- ObjectTypeDB::bind_method(_MD("get_section_keys"),&ConfigFile::_get_section_keys);
+ ObjectTypeDB::bind_method(_MD("get_section_keys","section"),&ConfigFile::_get_section_keys);
ObjectTypeDB::bind_method(_MD("load:Error","path"),&ConfigFile::load);
ObjectTypeDB::bind_method(_MD("save:Error","path"),&ConfigFile::save);
diff --git a/core/io/config_file.h b/core/io/config_file.h
index 608f143fb1..4708fefeaa 100644
--- a/core/io/config_file.h
+++ b/core/io/config_file.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -46,7 +46,7 @@ protected:
public:
void set_value(const String& p_section, const String& p_key, const Variant& p_value);
- Variant get_value(const String& p_section, const String& p_key) const;
+ Variant get_value(const String& p_section, const String& p_key, Variant p_default=Variant()) const;
bool has_section(const String& p_section) const;
bool has_section_key(const String& p_section,const String& p_key) const;
diff --git a/core/io/file_access_buffered.cpp b/core/io/file_access_buffered.cpp
index ab17cb8118..b38fda3686 100644
--- a/core/io/file_access_buffered.cpp
+++ b/core/io/file_access_buffered.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_buffered.h b/core/io/file_access_buffered.h
index e6de203cda..9d405e15f7 100644
--- a/core/io/file_access_buffered.h
+++ b/core/io/file_access_buffered.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h
index d36c4843e4..afa79db06f 100644
--- a/core/io/file_access_buffered_fa.h
+++ b/core/io/file_access_buffered_fa.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index 1d06dc8c4b..2547d2d065 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index 69a03fa14f..f9e7cd98bd 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index 83da55fc61..2cc52a9e2d 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h
index 8c58a8a8ce..287f3dfe04 100644
--- a/core/io/file_access_memory.h
+++ b/core/io/file_access_memory.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 850e055129..e63b57533f 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,9 +34,9 @@
-#define DEBUG_PRINT(m_p) print_line(m_p)
+//#define DEBUG_PRINT(m_p) print_line(m_p)
//#define DEBUG_TIME(m_what) printf("MS: %s - %lli\n",m_what,OS::get_singleton()->get_ticks_usec());
-//#define DEBUG_PRINT(m_p)
+#define DEBUG_PRINT(m_p)
#define DEBUG_TIME(m_what)
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index 2190cdb0ea..0073209ab8 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 339a6d0528..5c8c741f28 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 5bf5ad012c..f5dae6d51d 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index ab2eb3b3f2..41f43bf54d 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index 88272e6cfc..0a927b72f2 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index 58092efd4b..19a7286dcf 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -248,7 +248,7 @@ Error HTTPClient::poll(){
status=STATUS_SSL_HANDSHAKE_ERROR;
return ERR_CANT_CONNECT;
}
- print_line("SSL! TURNED ON!");
+ //print_line("SSL! TURNED ON!");
connection=ssl;
}
status=STATUS_CONNECTED;
@@ -295,7 +295,7 @@ Error HTTPClient::poll(){
response_str.push_back(0);
String response;
response.parse_utf8((const char*)response_str.ptr());
- print_line("END OF RESPONSE? :\n"+response+"\n------");
+ //print_line("END OF RESPONSE? :\n"+response+"\n------");
Vector<String> responses = response.split("\n");
body_size=0;
chunked=false;
@@ -307,16 +307,17 @@ Error HTTPClient::poll(){
for(int i=0;i<responses.size();i++) {
String s = responses[i].strip_edges();
+ s = s.to_lower();
if (s.length()==0)
continue;
- if (s.begins_with("Content-Length:")) {
+ if (s.begins_with("content-length:")) {
body_size = s.substr(s.find(":")+1,s.length()).strip_edges().to_int();
body_left=body_size;
}
- if (s.begins_with("Transfer-Encoding:")) {
+ if (s.begins_with("transfer-encoding:")) {
String encoding = s.substr(s.find(":")+1,s.length()).strip_edges();
- print_line("TRANSFER ENCODING: "+encoding);
+ //print_line("TRANSFER ENCODING: "+encoding);
if (encoding=="chunked") {
chunked=true;
}
diff --git a/core/io/http_client.h b/core/io/http_client.h
index b103dc43fc..e138681396 100644
--- a/core/io/http_client.h
+++ b/core/io/http_client.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index 2db6e00f0a..aa641f00b4 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/image_loader.h b/core/io/image_loader.h
index ff972696ea..3cc6c6cf43 100644
--- a/core/io/image_loader.h
+++ b/core/io/image_loader.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index 523f9f472b..b8bd00c2fb 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/ip.h b/core/io/ip.h
index 6f50a190e6..38c86e7ba3 100644
--- a/core/io/ip.h
+++ b/core/io/ip.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp
index ed5a45c9ef..7a51bce7c6 100644
--- a/core/io/ip_address.cpp
+++ b/core/io/ip_address.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/ip_address.h b/core/io/ip_address.h
index e55f45a2d7..1292311729 100644
--- a/core/io/ip_address.h
+++ b/core/io/ip_address.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/json.cpp b/core/io/json.cpp
index 22c99d0465..f9a8638d06 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -86,7 +86,7 @@ String JSON::_print_var(const Variant& p_var) {
s+="}";
return s;
};
- default: return "\""+String(p_var).c_escape()+"\"";
+ default: return "\""+String(p_var).json_escape()+"\"";
}
@@ -288,7 +288,7 @@ Error JSON::_parse_value(Variant &value,Token& token,const CharType *p_str,int &
if (token.type==TK_CURLY_BRACKET_OPEN) {
- Dictionary d;
+ Dictionary d(true);
Error err = _parse_object(d,p_str,index,p_len,line,r_err_str);
if (err)
return err;
@@ -296,7 +296,7 @@ Error JSON::_parse_value(Variant &value,Token& token,const CharType *p_str,int &
return OK;
} else if (token.type==TK_BRACKET_OPEN) {
- Array a;
+ Array a(true);
Error err = _parse_array(a,p_str,index,p_len,line,r_err_str);
if (err)
return err;
diff --git a/core/io/json.h b/core/io/json.h
index 78b6303451..a2803269cb 100644
--- a/core/io/json.h
+++ b/core/io/json.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index 62ccd81489..4dccf21d2d 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/marshalls.h b/core/io/marshalls.h
index df673debf5..7a5b16e8af 100644
--- a/core/io/marshalls.h
+++ b/core/io/marshalls.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp
index f6d526b512..6cb3daa7ac 100644
--- a/core/io/packet_peer.cpp
+++ b/core/io/packet_peer.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -127,7 +127,7 @@ Error PacketPeer::_get_packet_error() const {
void PacketPeer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_var"),&PacketPeer::_bnd_get_var);
- ObjectTypeDB::bind_method(_MD("put_var", "var:var"),&PacketPeer::put_var);
+ ObjectTypeDB::bind_method(_MD("put_var", "var:Variant"),&PacketPeer::put_var);
ObjectTypeDB::bind_method(_MD("get_packet"),&PacketPeer::_get_packet);
ObjectTypeDB::bind_method(_MD("put_packet:Error", "buffer"),&PacketPeer::_put_packet);
ObjectTypeDB::bind_method(_MD("get_packet_error:Error"),&PacketPeer::_get_packet_error);
diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h
index 76d1eb22b5..b29fc22af0 100644
--- a/core/io/packet_peer.h
+++ b/core/io/packet_peer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 1a0552e8d1..c008c3f9a4 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -725,7 +725,8 @@ Error ResourceInteractiveLoaderBinary::poll(){
}
} else {
- path=res_path;
+ if (!ResourceCache::has(res_path))
+ path=res_path;
}
uint64_t offset = internal_resources[s].offset;
@@ -853,6 +854,8 @@ String ResourceInteractiveLoaderBinary::get_unicode_string() {
if (len>str_buf.size()) {
str_buf.resize(len);
}
+ if (len==0)
+ return String();
f->get_buffer((uint8_t*)&str_buf[0],len);
String s;
s.parse_utf8(&str_buf[0]);
@@ -905,7 +908,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
error=ERR_FILE_UNRECOGNIZED;
ERR_EXPLAIN("Unrecognized binary resource file: "+local_path);
- ERR_FAIL_V();
+ ERR_FAIL();
}
bool big_endian = f->get_32();
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index 8bf20bc574..b8be3080b8 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp
index 48917a19ea..8c8d79948a 100644
--- a/core/io/resource_format_xml.cpp
+++ b/core/io/resource_format_xml.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1570,7 +1570,9 @@ Error ResourceInteractiveLoaderXML::poll() {
if (main) {
f->close();
resource=res;
- resource->set_path(res_path);
+ if (!ResourceCache::has(res_path)) {
+ resource->set_path(res_path);
+ }
error=ERR_FILE_EOF;
return error;
diff --git a/core/io/resource_format_xml.h b/core/io/resource_format_xml.h
index 77987c6a5b..94c81a4111 100644
--- a/core/io/resource_format_xml.h
+++ b/core/io/resource_format_xml.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 3862790b02..67208b5960 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index 00a05dcb43..fe58303066 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp
index fdb9a53f0d..51020a0285 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h
index 8382b65290..7bc96c1087 100644
--- a/core/io/resource_saver.h
+++ b/core/io/resource_saver.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp
index b00b462eb6..2a9dff86f8 100644
--- a/core/io/stream_peer.cpp
+++ b/core/io/stream_peer.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "stream_peer.h"
-
+#include "io/marshalls.h"
Error StreamPeer::_put_data(const DVector<uint8_t>& p_data) {
@@ -115,6 +115,271 @@ Array StreamPeer::_get_partial_data(int p_bytes) {
}
+void StreamPeer::set_big_endian(bool p_enable) {
+
+ big_endian=p_enable;
+}
+
+bool StreamPeer::is_big_endian_enabled() const {
+
+ return big_endian;
+}
+
+
+void StreamPeer::put_u8(uint8_t p_val) {
+ put_data((const uint8_t*)&p_val,1);
+
+}
+
+void StreamPeer::put_8(int8_t p_val){
+
+ put_data((const uint8_t*)&p_val,1);
+}
+void StreamPeer::put_u16(uint16_t p_val){
+
+ if (big_endian) {
+ p_val=BSWAP16(p_val);
+ }
+ uint8_t buf[2];
+ encode_uint16(p_val,buf);
+ put_data(buf,2);
+
+}
+void StreamPeer::put_16(int16_t p_val){
+
+ if (big_endian) {
+ p_val=BSWAP16(p_val);
+ }
+ uint8_t buf[2];
+ encode_uint16(p_val,buf);
+ put_data(buf,2);
+
+}
+void StreamPeer::put_u32(uint32_t p_val){
+
+ if (big_endian) {
+ p_val=BSWAP32(p_val);
+ }
+ uint8_t buf[4];
+ encode_uint32(p_val,buf);
+ put_data(buf,4);
+
+}
+void StreamPeer::put_32(int32_t p_val){
+
+ if (big_endian) {
+ p_val=BSWAP32(p_val);
+ }
+ uint8_t buf[4];
+ encode_uint32(p_val,buf);
+ put_data(buf,4);
+
+}
+void StreamPeer::put_u64(uint64_t p_val){
+
+ if (big_endian) {
+ p_val=BSWAP64(p_val);
+ }
+ uint8_t buf[8];
+ encode_uint64(p_val,buf);
+ put_data(buf,8);
+
+}
+void StreamPeer::put_64(int64_t p_val){
+
+ if (big_endian) {
+ p_val=BSWAP64(p_val);
+ }
+ uint8_t buf[8];
+ encode_uint64(p_val,buf);
+ put_data(buf,8);
+
+}
+void StreamPeer::put_float(float p_val){
+
+ uint8_t buf[4];
+
+ encode_float(p_val,buf);
+ if (big_endian) {
+ uint32_t *p32=(uint32_t *)buf;
+ *p32=BSWAP32(*p32);
+ }
+
+ put_data(buf,4);
+
+}
+void StreamPeer::put_double(double p_val){
+
+ uint8_t buf[8];
+ encode_double(p_val,buf);
+ if (big_endian) {
+ uint64_t *p64=(uint64_t *)buf;
+ *p64=BSWAP64(*p64);
+ }
+ put_data(buf,8);
+
+}
+void StreamPeer::put_utf8_string(const String& p_string) {
+
+ CharString cs=p_string.utf8();
+ put_data((const uint8_t*)cs.get_data(),cs.length());
+
+}
+void StreamPeer::put_var(const Variant& p_variant){
+
+ int len=0;
+ Vector<uint8_t> buf;
+ encode_variant(p_variant,NULL,len);
+ buf.resize(len);
+ put_32(len);
+ encode_variant(p_variant,buf.ptr(),len);
+ put_data(buf.ptr(),buf.size());
+
+
+}
+
+uint8_t StreamPeer::get_u8(){
+
+ uint8_t buf[1];
+ get_data(buf,1);
+ return buf[0];
+}
+int8_t StreamPeer::get_8(){
+
+ uint8_t buf[1];
+ get_data(buf,1);
+ return buf[0];
+
+}
+uint16_t StreamPeer::get_u16(){
+
+ uint8_t buf[2];
+ get_data(buf,2);
+ uint16_t r = decode_uint16(buf);
+ if (big_endian) {
+ r=BSWAP16(r);
+ }
+ return r;
+
+}
+int16_t StreamPeer::get_16(){
+
+ uint8_t buf[2];
+ get_data(buf,2);
+ uint16_t r = decode_uint16(buf);
+ if (big_endian) {
+ r=BSWAP16(r);
+ }
+ return r;
+
+}
+uint32_t StreamPeer::get_u32(){
+
+ uint8_t buf[4];
+ get_data(buf,4);
+ uint32_t r = decode_uint32(buf);
+ if (big_endian) {
+ r=BSWAP32(r);
+ }
+ return r;
+
+}
+int32_t StreamPeer::get_32(){
+
+ uint8_t buf[4];
+ get_data(buf,4);
+ uint32_t r = decode_uint32(buf);
+ if (big_endian) {
+ r=BSWAP32(r);
+ }
+ return r;
+
+}
+uint64_t StreamPeer::get_u64(){
+
+ uint8_t buf[8];
+ get_data(buf,8);
+ uint64_t r = decode_uint64(buf);
+ if (big_endian) {
+ r=BSWAP64(r);
+ }
+ return r;
+
+}
+int64_t StreamPeer::get_64(){
+
+ uint8_t buf[8];
+ get_data(buf,8);
+ uint64_t r = decode_uint64(buf);
+ if (big_endian) {
+ r=BSWAP64(r);
+ }
+ return r;
+
+}
+float StreamPeer::get_float(){
+
+ uint8_t buf[4];
+ get_data(buf,4);
+
+ if (big_endian) {
+ uint32_t *p32=(uint32_t *)buf;
+ *p32=BSWAP32(*p32);
+ }
+
+ return decode_float(buf);
+}
+
+float StreamPeer::get_double(){
+
+ uint8_t buf[8];
+ get_data(buf,8);
+
+ if (big_endian) {
+ uint64_t *p64=(uint64_t *)buf;
+ *p64=BSWAP64(*p64);
+ }
+
+ return decode_double(buf);
+
+}
+String StreamPeer::get_string(int p_bytes){
+
+ ERR_FAIL_COND_V(p_bytes<0,String());
+
+ Vector<char> buf;
+ buf.resize(p_bytes+1);
+ get_data((uint8_t*)&buf[0],p_bytes);
+ buf[p_bytes]=0;
+ return buf.ptr();
+
+}
+String StreamPeer::get_utf8_string(int p_bytes){
+
+ ERR_FAIL_COND_V(p_bytes<0,String());
+ ERR_FAIL_COND_V(p_bytes<0,String());
+
+ Vector<uint8_t> buf;
+ buf.resize(p_bytes);
+ get_data(buf.ptr(),p_bytes);
+
+ String ret;
+ ret.parse_utf8((const char*)buf.ptr(),buf.size());
+ return ret;
+
+}
+Variant StreamPeer::get_var(){
+
+ int len = get_32();
+ Vector<uint8_t> var;
+ var.resize(len);
+ get_data(var.ptr(),len);
+
+ Variant ret;
+ decode_variant(ret,var.ptr(),len);
+ return ret;
+}
+
void StreamPeer::_bind_methods() {
@@ -123,4 +388,36 @@ void StreamPeer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_data","bytes"),&StreamPeer::_get_data);
ObjectTypeDB::bind_method(_MD("get_partial_data","bytes"),&StreamPeer::_get_partial_data);
+
+ ObjectTypeDB::bind_method(_MD("get_available_bytes"),&StreamPeer::get_available_bytes);
+
+ ObjectTypeDB::bind_method(_MD("set_big_endian","enable"),&StreamPeer::set_big_endian);
+ ObjectTypeDB::bind_method(_MD("is_big_endian_enabled"),&StreamPeer::is_big_endian_enabled);
+
+ ObjectTypeDB::bind_method(_MD("put_8","val"),&StreamPeer::put_8);
+ ObjectTypeDB::bind_method(_MD("put_u8","val"),&StreamPeer::put_u8);
+ ObjectTypeDB::bind_method(_MD("put_16","val"),&StreamPeer::put_16);
+ ObjectTypeDB::bind_method(_MD("put_u16","val"),&StreamPeer::put_u16);
+ ObjectTypeDB::bind_method(_MD("put_32","val"),&StreamPeer::put_32);
+ ObjectTypeDB::bind_method(_MD("put_u32","val"),&StreamPeer::put_u32);
+ ObjectTypeDB::bind_method(_MD("put_64","val"),&StreamPeer::put_64);
+ ObjectTypeDB::bind_method(_MD("put_u64","val"),&StreamPeer::put_u64);
+ ObjectTypeDB::bind_method(_MD("put_float","val"),&StreamPeer::put_float);
+ ObjectTypeDB::bind_method(_MD("put_double","val"),&StreamPeer::put_double);
+ ObjectTypeDB::bind_method(_MD("put_utf8_string","val"),&StreamPeer::put_utf8_string);
+ ObjectTypeDB::bind_method(_MD("put_var","val:Variant"),&StreamPeer::put_var);
+
+ ObjectTypeDB::bind_method(_MD("get_8"),&StreamPeer::get_8);
+ ObjectTypeDB::bind_method(_MD("get_u8"),&StreamPeer::get_u8);
+ ObjectTypeDB::bind_method(_MD("get_16"),&StreamPeer::get_16);
+ ObjectTypeDB::bind_method(_MD("get_u16"),&StreamPeer::get_u16);
+ ObjectTypeDB::bind_method(_MD("get_32"),&StreamPeer::get_32);
+ ObjectTypeDB::bind_method(_MD("get_u32"),&StreamPeer::get_u32);
+ ObjectTypeDB::bind_method(_MD("get_64"),&StreamPeer::get_64);
+ ObjectTypeDB::bind_method(_MD("get_u64"),&StreamPeer::get_u64);
+ ObjectTypeDB::bind_method(_MD("get_float"),&StreamPeer::get_float);
+ ObjectTypeDB::bind_method(_MD("get_double"),&StreamPeer::get_double);
+ ObjectTypeDB::bind_method(_MD("get_string","bytes"),&StreamPeer::get_string);
+ ObjectTypeDB::bind_method(_MD("get_utf8_string","bytes"),&StreamPeer::get_utf8_string);
+ ObjectTypeDB::bind_method(_MD("get_var:Variant"),&StreamPeer::get_var);
}
diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h
index e83fc71b93..970e6695a5 100644
--- a/core/io/stream_peer.h
+++ b/core/io/stream_peer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -44,6 +44,8 @@ protected:
Array _get_data(int p_bytes);
Array _get_partial_data(int p_bytes);
+ bool big_endian;
+
public:
virtual Error put_data(const uint8_t* p_data,int p_bytes)=0; ///< put a whole chunk of data, blocking until it sent
@@ -52,7 +54,41 @@ public:
virtual Error get_data(uint8_t* p_buffer, int p_bytes)=0; ///< read p_bytes of data, if p_bytes > available, it will block
virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received)=0; ///< read as much data as p_bytes into buffer, if less was read, return in r_received
- StreamPeer() {}
+ virtual int get_available_bytes() const=0;
+
+ void set_big_endian(bool p_enable);
+ bool is_big_endian_enabled() const;
+
+ void put_8(int8_t p_val);
+ void put_u8(uint8_t p_val);
+ void put_16(int16_t p_val);
+ void put_u16(uint16_t p_val);
+ void put_32(int32_t p_val);
+ void put_u32(uint32_t p_val);
+ void put_64(int64_t p_val);
+ void put_u64(uint64_t p_val);
+ void put_float(float p_val);
+ void put_double(double p_val);
+ void put_utf8_string(const String& p_string);
+ void put_var(const Variant& p_variant);
+
+ uint8_t get_u8();
+ int8_t get_8();
+ uint16_t get_u16();
+ int16_t get_16();
+ uint32_t get_u32();
+ int32_t get_32();
+ uint64_t get_u64();
+ int64_t get_64();
+ float get_float();
+ float get_double();
+ String get_string(int p_bytes);
+ String get_utf8_string(int p_bytes);
+ Variant get_var();
+
+
+
+ StreamPeer() { big_endian=false; }
};
#endif // STREAM_PEER_H
diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp
index c2343790ea..fbb0c69cb7 100644
--- a/core/io/stream_peer_tcp.cpp
+++ b/core/io/stream_peer_tcp.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h
index 0e37303516..4c58e7e149 100644
--- a/core/io/stream_peer_tcp.h
+++ b/core/io/stream_peer_tcp.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp
index 803df87086..274d20a48a 100644
--- a/core/io/tcp_server.cpp
+++ b/core/io/tcp_server.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h
index b59f3293d7..512a7e640a 100644
--- a/core/io/tcp_server.h
+++ b/core/io/tcp_server.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index 020d168208..fe101a8676 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h
index e07ae15e28..a569674d80 100644
--- a/core/io/translation_loader_po.h
+++ b/core/io/translation_loader_po.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 1ff458f325..e6a90412c1 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -385,15 +385,15 @@ void XMLParser::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_node_data"),&XMLParser::get_node_data);
ObjectTypeDB::bind_method(_MD("get_node_offset"),&XMLParser::get_node_offset);
ObjectTypeDB::bind_method(_MD("get_attribute_count"),&XMLParser::get_attribute_count);
- ObjectTypeDB::bind_method(_MD("get_attribute_name"),&XMLParser::get_attribute_name);
- ObjectTypeDB::bind_method(_MD("get_attribute_value"),(String (XMLParser::*)(int) const) &XMLParser::get_attribute_value);
- ObjectTypeDB::bind_method(_MD("has_attribute"),&XMLParser::has_attribute);
- ObjectTypeDB::bind_method(_MD("get_named_attribute_value"), (String (XMLParser::*)(const String&) const) &XMLParser::get_attribute_value);
- ObjectTypeDB::bind_method(_MD("get_named_attribute_value_safe"), &XMLParser::get_attribute_value_safe);
+ ObjectTypeDB::bind_method(_MD("get_attribute_name","idx"),&XMLParser::get_attribute_name);
+ ObjectTypeDB::bind_method(_MD("get_attribute_value","idx"),(String (XMLParser::*)(int) const) &XMLParser::get_attribute_value);
+ ObjectTypeDB::bind_method(_MD("has_attribute","name"),&XMLParser::has_attribute);
+ ObjectTypeDB::bind_method(_MD("get_named_attribute_value","name"), (String (XMLParser::*)(const String&) const) &XMLParser::get_attribute_value);
+ ObjectTypeDB::bind_method(_MD("get_named_attribute_value_safe","name"), &XMLParser::get_attribute_value_safe);
ObjectTypeDB::bind_method(_MD("is_empty"),&XMLParser::is_empty);
ObjectTypeDB::bind_method(_MD("get_current_line"),&XMLParser::get_current_line);
ObjectTypeDB::bind_method(_MD("skip_section"),&XMLParser::skip_section);
- ObjectTypeDB::bind_method(_MD("seek"),&XMLParser::seek);
+ ObjectTypeDB::bind_method(_MD("seek","pos"),&XMLParser::seek);
ObjectTypeDB::bind_method(_MD("open","file"),&XMLParser::open);
ObjectTypeDB::bind_method(_MD("open_buffer","buffer"),&XMLParser::open_buffer);
diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h
index 418a8efa70..e0ec3ec770 100644
--- a/core/io/xml_parser.h
+++ b/core/io/xml_parser.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/zip_io.h b/core/io/zip_io.h
index dd3c371a4a..355003d947 100644
--- a/core/io/zip_io.h
+++ b/core/io/zip_io.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/list.h b/core/list.h
index 018abca940..fbeb653da4 100644
--- a/core/list.h
+++ b/core/list.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/map.h b/core/map.h
index e45c833bcb..35dc73df48 100644
--- a/core/map.h
+++ b/core/map.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/aabb.cpp b/core/math/aabb.cpp
index 435df66aab..6d8a5a72f0 100644
--- a/core/math/aabb.cpp
+++ b/core/math/aabb.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/aabb.h b/core/math/aabb.h
index 4781e5c263..7c9c3081ac 100644
--- a/core/math/aabb.h
+++ b/core/math/aabb.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/bezier_curve.cpp b/core/math/bezier_curve.cpp
index c9467a77e4..37cf16504c 100644
--- a/core/math/bezier_curve.cpp
+++ b/core/math/bezier_curve.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/bezier_curve.h b/core/math/bezier_curve.h
index de14d68987..25df9dfda8 100644
--- a/core/math/bezier_curve.h
+++ b/core/math/bezier_curve.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/bsp_tree.cpp b/core/math/bsp_tree.cpp
index d71b7551d9..0c07b733f0 100644
--- a/core/math/bsp_tree.cpp
+++ b/core/math/bsp_tree.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/bsp_tree.h b/core/math/bsp_tree.h
index b980d9590b..a7145f9ff1 100644
--- a/core/math/bsp_tree.h
+++ b/core/math/bsp_tree.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index f1afa33a4b..61c8b78e0a 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/camera_matrix.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h
index 52b84f4870..27500a545e 100644
--- a/core/math/camera_matrix.h
+++ b/core/math/camera_matrix.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/face3.cpp b/core/math/face3.cpp
index 354372df74..e1af91f28e 100644
--- a/core/math/face3.cpp
+++ b/core/math/face3.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/face3.h b/core/math/face3.h
index eccbc78122..c36fdd1332 100644
--- a/core/math/face3.h
+++ b/core/math/face3.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp
index 14adde74e7..2905d26fe5 100644
--- a/core/math/geometry.cpp
+++ b/core/math/geometry.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/geometry.h b/core/math/geometry.h
index b438b41d61..8370990d6e 100644
--- a/core/math/geometry.h
+++ b/core/math/geometry.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -886,7 +886,38 @@ public:
}
+ static double vec2_cross(const Point2 &O, const Point2 &A, const Point2 &B)
+ {
+ return (double)(A.x - O.x) * (B.y - O.y) - (double)(A.y - O.y) * (B.x - O.x);
+ }
+
+ // Returns a list of points on the convex hull in counter-clockwise order.
+ // Note: the last point in the returned list is the same as the first one.
+ static Vector<Point2> convex_hull_2d(Vector<Point2> P)
+ {
+ int n = P.size(), k = 0;
+ Vector<Point2> H;
+ H.resize(2*n);
+
+ // Sort points lexicographically
+ P.sort();
+
+ // Build lower hull
+ for (int i = 0; i < n; ++i) {
+ while (k >= 2 && vec2_cross(H[k-2], H[k-1], P[i]) <= 0) k--;
+ H[k++] = P[i];
+ }
+
+ // Build upper hull
+ for (int i = n-2, t = k+1; i >= 0; i--) {
+ while (k >= t && vec2_cross(H[k-2], H[k-1], P[i]) <= 0) k--;
+ H[k++] = P[i];
+ }
+
+ H.resize(k);
+ return H;
+ }
static MeshData build_convex_mesh(const DVector<Plane> &p_planes);
static DVector<Plane> build_sphere_planes(float p_radius, int p_lats, int p_lons, Vector3::Axis p_axis=Vector3::AXIS_Z);
diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp
index ce03f089e5..a485125cb4 100644
--- a/core/math/math_2d.cpp
+++ b/core/math/math_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -187,7 +187,6 @@ Vector2 Vector2::snapped(const Vector2& p_by) const {
Vector2 Vector2::clamped(real_t p_len) const {
- return *this;
real_t l = length();
Vector2 v = *this;
if (l>0 && p_len<l) {
diff --git a/core/math/math_2d.h b/core/math/math_2d.h
index 3d40e24091..1171364671 100644
--- a/core/math/math_2d.h
+++ b/core/math/math_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/math_defs.cpp b/core/math/math_defs.cpp
index 51aaa6800e..70963bd71d 100644
--- a/core/math/math_defs.cpp
+++ b/core/math/math_defs.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/math_defs.h b/core/math/math_defs.h
index 7cb6c7f499..eb85039ca3 100644
--- a/core/math/math_defs.h
+++ b/core/math/math_defs.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp
index 3c94ac5bc7..20d9db3375 100644
--- a/core/math/math_funcs.cpp
+++ b/core/math/math_funcs.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -207,9 +207,15 @@ double Math::ceil(double p_x) {
int Math::decimals(double p_step) {
int max=4;
+ double llimit = Math::pow(0.1,max);
+ double ulimit = 1.0-llimit;
int i=0;
- while( (p_step - Math::floor(p_step)) != 0.0 && max) {
-
+ while( max) {
+
+ float d = absf(p_step) - Math::floor(absf(p_step));
+
+ if (d<llimit || d>ulimit)
+ break;
p_step*=10.0;
max--;
i++;
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index ec089ebc8b..62890b0371 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/matrix3.cpp b/core/math/matrix3.cpp
index 10f1461fdc..f51da80a83 100644
--- a/core/math/matrix3.cpp
+++ b/core/math/matrix3.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/matrix3.h b/core/math/matrix3.h
index 98feb2dbbd..291934b8eb 100644
--- a/core/math/matrix3.h
+++ b/core/math/matrix3.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/octree.h b/core/math/octree.h
index 84de388178..b51c4bcba7 100644
--- a/core/math/octree.h
+++ b/core/math/octree.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/plane.cpp b/core/math/plane.cpp
index f9395a002a..d17ce01bec 100644
--- a/core/math/plane.cpp
+++ b/core/math/plane.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/plane.h b/core/math/plane.h
index 604b880266..d20e63dc47 100644
--- a/core/math/plane.h
+++ b/core/math/plane.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/quat.cpp b/core/math/quat.cpp
index e0c4b0793c..ebc5ec4e65 100644
--- a/core/math/quat.cpp
+++ b/core/math/quat.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/quat.h b/core/math/quat.h
index f161e35074..738b6946c7 100644
--- a/core/math/quat.h
+++ b/core/math/quat.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index 80ae0f04e1..956824d3d0 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/quick_hull.h b/core/math/quick_hull.h
index cb486a0b6f..8c009b907d 100644
--- a/core/math/quick_hull.h
+++ b/core/math/quick_hull.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/transform.cpp b/core/math/transform.cpp
index a6f4f626cc..8371f7e34b 100644
--- a/core/math/transform.cpp
+++ b/core/math/transform.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/transform.h b/core/math/transform.h
index a992843d70..bd1247084d 100644
--- a/core/math/transform.h
+++ b/core/math/transform.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp
index 70cb639fc2..adb9861092 100644
--- a/core/math/triangle_mesh.cpp
+++ b/core/math/triangle_mesh.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/triangle_mesh.h b/core/math/triangle_mesh.h
index 87d8ce8e6c..b5e8f79cde 100644
--- a/core/math/triangle_mesh.h
+++ b/core/math/triangle_mesh.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp
index b13e13c47d..27b7c86675 100644
--- a/core/math/triangulate.cpp
+++ b/core/math/triangulate.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/triangulate.h b/core/math/triangulate.h
index 927b7efb8d..7dcc91b2fd 100644
--- a/core/math/triangulate.h
+++ b/core/math/triangulate.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp
index a3877eb9ff..8afd73f482 100644
--- a/core/math/vector3.cpp
+++ b/core/math/vector3.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/vector3.h b/core/math/vector3.h
index 8a3cca8f33..528c4d37b3 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/message_queue.cpp b/core/message_queue.cpp
index 489939ee65..c69021f4f0 100644
--- a/core/message_queue.cpp
+++ b/core/message_queue.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "message_queue.h"
#include "globals.h"
-
+#include "script_language.h"
MessageQueue *MessageQueue::singleton=NULL;
MessageQueue *MessageQueue::get_singleton() {
@@ -36,26 +36,11 @@ MessageQueue *MessageQueue::get_singleton() {
return singleton;
}
-Error MessageQueue::push_call(ObjectID p_id, const StringName& p_method, VARIANT_ARG_DECLARE) {
+Error MessageQueue::push_call(ObjectID p_id,const StringName& p_method,const Variant** p_args,int p_argcount,bool p_show_error) {
_THREAD_SAFE_METHOD_
- uint8_t room_needed=sizeof(Message);
- int args=0;
- if (p_arg5.get_type()!=Variant::NIL)
- args=5;
- else if (p_arg4.get_type()!=Variant::NIL)
- args=4;
- else if (p_arg3.get_type()!=Variant::NIL)
- args=3;
- else if (p_arg2.get_type()!=Variant::NIL)
- args=2;
- else if (p_arg1.get_type()!=Variant::NIL)
- args=1;
- else
- args=0;
-
- room_needed+=sizeof(Variant)*args;
+ int room_needed=sizeof(Message)+sizeof(Variant)*p_argcount;
if ((buffer_end+room_needed) >= buffer_size) {
String type;
@@ -65,53 +50,43 @@ Error MessageQueue::push_call(ObjectID p_id, const StringName& p_method, VARIANT
statistics();
}
+
ERR_FAIL_COND_V( (buffer_end+room_needed) >= buffer_size , ERR_OUT_OF_MEMORY );
Message * msg = memnew_placement( &buffer[ buffer_end ], Message );
- msg->args=args;
+ msg->args=p_argcount;
msg->instance_ID=p_id;
msg->target=p_method;
msg->type=TYPE_CALL;
- buffer_end+=sizeof(Message);
+ if (p_show_error)
+ msg->type|=FLAG_SHOW_ERROR;
+ buffer_end+=sizeof(Message);
- if (args>=1) {
+ for(int i=0;i<p_argcount;i++) {
Variant * v = memnew_placement( &buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
- *v=p_arg1;
- }
-
- if (args>=2) {
+ *v=*p_args[i];
- Variant * v = memnew_placement( &buffer[ buffer_end ], Variant );
- buffer_end+=sizeof(Variant);
- *v=p_arg2;
}
- if (args>=3) {
+ return OK;
+}
- Variant * v = memnew_placement( &buffer[ buffer_end ], Variant );
- buffer_end+=sizeof(Variant);
- *v=p_arg3;
+Error MessageQueue::push_call(ObjectID p_id, const StringName& p_method, VARIANT_ARG_DECLARE) {
- }
+ VARIANT_ARGPTRS;
- if (args>=4) {
+ int argc=0;
- Variant * v = memnew_placement( &buffer[ buffer_end ], Variant );
- buffer_end+=sizeof(Variant);
- *v=p_arg4;
+ for(int i=0;i<VARIANT_ARG_MAX;i++) {
+ if (argptr[i]->get_type()==Variant::NIL)
+ break;
+ argc++;
}
- if (args>=5) {
+ return push_call(p_id,p_method,argptr,argc,false);
- Variant * v = memnew_placement( &buffer[ buffer_end ], Variant );
- buffer_end+=sizeof(Variant);
- *v=p_arg5;
- }
-
-
- return OK;
}
Error MessageQueue::push_set(ObjectID p_id, const StringName& p_prop, const Variant& p_value) {
@@ -212,7 +187,7 @@ void MessageQueue::statistics() {
if (target!=NULL) {
- switch(message->type) {
+ switch(message->type&FLAG_MASK) {
case TYPE_CALL: {
@@ -251,7 +226,7 @@ void MessageQueue::statistics() {
read_pos+=sizeof(Message);
- if (message->type!=TYPE_NOTIFICATION)
+ if ((message->type&FLAG_MASK)!=TYPE_NOTIFICATION)
read_pos+=sizeof(Variant)*message->args;
}
@@ -322,6 +297,26 @@ int MessageQueue::get_max_buffer_usage() const {
return buffer_max_used;
}
+
+void MessageQueue::_call_function(Object* p_target, const StringName& p_func, const Variant *p_args, int p_argcount,bool p_show_error) {
+
+ const Variant **argptrs=NULL;
+ if (p_argcount) {
+ argptrs = (const Variant**)alloca(sizeof(Variant*)*p_argcount);
+ for(int i=0;i<p_argcount;i++) {
+ argptrs[i]=&p_args[i];
+ }
+ }
+
+ Variant::CallError ce;
+ p_target->call(p_func,argptrs,p_argcount,ce);
+ if (p_show_error && ce.error!=Variant::CallError::CALL_OK) {
+
+ ERR_PRINTS("Error calling deferred method: "+Variant::get_call_error_text(p_target,p_func,argptrs,p_argcount,ce));
+
+ }
+}
+
void MessageQueue::flush() {
@@ -347,7 +342,7 @@ void MessageQueue::flush() {
if (target!=NULL) {
- switch(message->type) {
+ switch(message->type&FLAG_MASK) {
case TYPE_CALL: {
Variant *args= (Variant*)(message+1);
@@ -355,12 +350,7 @@ void MessageQueue::flush() {
// messages don't expect a return value
- target->call( message->target,
- (message->args>=1) ? args[0] : Variant(),
- (message->args>=2) ? args[1] : Variant(),
- (message->args>=3) ? args[2] : Variant(),
- (message->args>=4) ? args[3] : Variant(),
- (message->args>=5) ? args[4] : Variant() );
+ _call_function(target,message->target,args,message->args,message->type&FLAG_SHOW_ERROR);
for(int i=0;i<message->args;i++) {
args[i].~Variant();
@@ -386,7 +376,7 @@ void MessageQueue::flush() {
}
uint32_t advance = sizeof(Message);
- if (message->type!=TYPE_NOTIFICATION)
+ if ((message->type&FLAG_MASK)!=TYPE_NOTIFICATION)
advance+=sizeof(Variant)*message->args;
message->~Message();
@@ -423,14 +413,14 @@ MessageQueue::~MessageQueue() {
Message *message = (Message*)&buffer[ read_pos ];
Variant *args= (Variant*)(message+1);
int argc = message->args;
- if (message->type!=TYPE_NOTIFICATION) {
+ if ((message->type&FLAG_MASK)!=TYPE_NOTIFICATION) {
for (int i=0;i<argc;i++)
args[i].~Variant();
}
message->~Message();
read_pos+=sizeof(Message);
- if (message->type!=TYPE_NOTIFICATION)
+ if ((message->type&FLAG_MASK)!=TYPE_NOTIFICATION)
read_pos+=sizeof(Variant)*message->args;
}
diff --git a/core/message_queue.h b/core/message_queue.h
index 5cee21847b..6a3ec79732 100644
--- a/core/message_queue.h
+++ b/core/message_queue.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -46,7 +46,10 @@ class MessageQueue {
enum {
TYPE_CALL,
TYPE_NOTIFICATION,
- TYPE_SET
+ TYPE_SET,
+ FLAG_SHOW_ERROR=1<<14,
+ FLAG_MASK=FLAG_SHOW_ERROR-1
+
};
struct Message {
@@ -65,12 +68,14 @@ class MessageQueue {
uint32_t buffer_max_used;
uint32_t buffer_size;
+ void _call_function(Object* p_target,const StringName& p_func,const Variant *p_args,int p_argcount,bool p_show_error);
static MessageQueue *singleton;
public:
static MessageQueue *get_singleton();
+ Error push_call(ObjectID p_id,const StringName& p_method,const Variant** p_args,int p_argcount,bool p_show_error=false);
Error push_call(ObjectID p_id, const StringName& p_method, VARIANT_ARG_LIST);
Error push_notification(ObjectID p_id, int p_notification);
Error push_set(ObjectID p_id, const StringName& p_prop, const Variant& p_value);
diff --git a/core/method_bind.cpp b/core/method_bind.cpp
index ce57380434..b41fa33887 100644
--- a/core/method_bind.cpp
+++ b/core/method_bind.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/method_bind.h b/core/method_bind.h
index 85c1084f80..4c2598e50c 100644
--- a/core/method_bind.h
+++ b/core/method_bind.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/multi_bucket_array.h b/core/multi_bucket_array.h
index d85c9de583..98033e40f6 100644
--- a/core/multi_bucket_array.h
+++ b/core/multi_bucket_array.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/object.cpp b/core/object.cpp
index 3a4c06e7e7..c92fc35b24 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -314,6 +314,7 @@ void Object::set(const StringName& p_name, const Variant& p_value, bool *r_valid
_edited=true;
#endif
+
if (script_instance) {
if (script_instance->set(p_name,p_value)) {
@@ -326,9 +327,9 @@ void Object::set(const StringName& p_name, const Variant& p_value, bool *r_valid
//try built-in setgetter
{
- if (ObjectTypeDB::set_property(this,p_name,p_value)) {
- if (r_valid)
- *r_valid=true;
+ if (ObjectTypeDB::set_property(this,p_name,p_value,r_valid)) {
+ //if (r_valid)
+ // *r_valid=true;
return;
}
}
@@ -511,17 +512,10 @@ Variant Object::_call_deferred_bind(const Variant** p_args, int p_argcount, Vari
r_error.error=Variant::CallError::CALL_OK;
- StringName signal = *p_args[0];
-
- Variant v[VARIANT_ARG_MAX];
-
-
- for(int i=0;i<MIN(5,p_argcount-1);i++) {
+ StringName method = *p_args[0];
- v[i]=*p_args[i+1];
- }
+ MessageQueue::get_singleton()->push_call(get_instance_ID(),method,&p_args[1],p_argcount-1);
- call_deferred(signal,v[0],v[1],v[2],v[3],v[4]);
return Variant();
}
@@ -838,6 +832,8 @@ void Object::call_multilevel(const StringName& p_name, VARIANT_ARG_DECLARE) {
Variant Object::call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error) {
+ r_error.error=Variant::CallError::CALL_OK;
+
if (p_method==CoreStringNames::get_singleton()->_free) {
//free must be here, before anything, always ready
#ifdef DEBUG_ENABLED
@@ -1010,6 +1006,27 @@ Array Object::_get_property_list_bind() const {
return convert_property_list(&lpi);
}
+
+static Dictionary _get_dict_from_method(const MethodInfo &mi) {
+
+ Dictionary d;
+ d["name"]=mi.name;
+ d["args"]=convert_property_list(&mi.arguments);
+ Array da;
+ for(int i=0;i<mi.default_arguments.size();i++)
+ da.push_back(mi.default_arguments[i]);
+ d["default_args"]=da;
+ d["flags"]=mi.flags;
+ d["id"]=mi.id;
+ Dictionary r;
+ r["type"]=mi.return_val.type;
+ r["hint"]=mi.return_val.hint;
+ r["hint_string"]=mi.return_val.hint_string;
+ d["return_type"]=r;
+ return d;
+
+}
+
Array Object::_get_method_list_bind() const {
List<MethodInfo> ml;
@@ -1018,20 +1035,7 @@ Array Object::_get_method_list_bind() const {
for(List<MethodInfo>::Element *E=ml.front();E;E=E->next()) {
- Dictionary d;
- d["name"]=E->get().name;
- d["args"]=convert_property_list(&E->get().arguments);
- Array da;
- for(int i=0;i<E->get().default_arguments.size();i++)
- da.push_back(E->get().default_arguments[i]);
- d["default_args"]=da;
- d["flags"]=E->get().flags;
- d["id"]=E->get().id;
- Dictionary r;
- r["type"]=E->get().return_val.type;
- r["hint"]=E->get().return_val.hint;
- r["hint_string"]=E->get().return_val.hint_string;
- d["return_type"]=r;
+ Dictionary d = _get_dict_from_method(E->get());
//va.push_back(d);
ret.push_back(d);
}
@@ -1121,21 +1125,22 @@ Variant Object::_emit_signal(const Variant** p_args, int p_argcount, Variant::Ca
StringName signal = *p_args[0];
- Variant v[VARIANT_ARG_MAX];
-
- for(int i=0;i<MIN(5,p_argcount-1);i++) {
+ const Variant**args=NULL;
- v[i]=*p_args[i+1];
+ int argc=p_argcount-1;
+ if (argc) {
+ args=&p_args[1];
}
- emit_signal(signal,v[0],v[1],v[2],v[3],v[4]);
+ emit_signal(signal,args,argc);
+
return Variant();
-}
+}
-void Object::emit_signal(const StringName& p_name,VARIANT_ARG_DECLARE) {
+void Object::emit_signal(const StringName& p_name,const Variant** p_args,int p_argcount) {
if (_block_signals)
return; //no emit, signals blocked
@@ -1158,10 +1163,12 @@ void Object::emit_signal(const StringName& p_name,VARIANT_ARG_DECLARE) {
OBJ_DEBUG_LOCK
+ Vector<const Variant*> bind_mem;
+
+
for(int i=0;i<ssize;i++) {
const Connection &c = slot_map.getv(i).conn;
- VARIANT_ARGPTRS
Object *target;
#ifdef DEBUG_ENABLED
@@ -1172,21 +1179,37 @@ void Object::emit_signal(const StringName& p_name,VARIANT_ARG_DECLARE) {
#endif
- int bind_count=c.binds.size();
- int bind=0;
+ const Variant **args=p_args;
+ int argc=p_argcount;
- for(int i=0;bind < bind_count && i<VARIANT_ARG_MAX;i++) {
+ if (c.binds.size()) {
+ //handle binds
+ bind_mem.resize(p_argcount+c.binds.size());
- if (argptr[i]->get_type()==Variant::NIL) {
- argptr[i]=&c.binds[bind];
- bind++;
+ for(int j=0;j<p_argcount;j++) {
+ bind_mem[j]=p_args[j];
+ }
+ for(int j=0;j<c.binds.size();j++) {
+ bind_mem[p_argcount+j]=&c.binds[j];
}
+
+ args=bind_mem.ptr();
+ argc=bind_mem.size();
}
if (c.flags&CONNECT_DEFERRED) {
- MessageQueue::get_singleton()->push_call(target->get_instance_ID(),c.method,VARIANT_ARGPTRS_PASS);
+ MessageQueue::get_singleton()->push_call(target->get_instance_ID(),c.method,args,argc,true);
} else {
- target->call( c.method, VARIANT_ARGPTRS_PASS );
+ Variant::CallError ce;
+ target->call( c.method, args, argc,ce );
+ if (ce.error!=Variant::CallError::CALL_OK) {
+
+ if (ce.error==Variant::CallError::CALL_ERROR_INVALID_METHOD && !ObjectTypeDB::type_exists( target->get_type_name() ) ) {
+ //most likely object is not initialized yet, do not throw error.
+ } else {
+ ERR_PRINTS("Error calling method from signal '"+String(p_name)+"': "+Variant::get_call_error_text(target,c.method,args,argc,ce));
+ }
+ }
}
if (c.flags&CONNECT_ONESHOT) {
@@ -1199,57 +1222,29 @@ void Object::emit_signal(const StringName& p_name,VARIANT_ARG_DECLARE) {
}
-#if 0
-
- //old (deprecated and dangerous code)
- s->lock++;
- for( Map<Signal::Target,Signal::Slot>::Element *E = s->slot_map.front();E;E=E->next() ) {
-
- const Signal::Target& t = E->key();
- const Signal::Slot& s = E->get();
- const Connection &c = s.cE->get();
- VARIANT_ARGPTRS
+ while (!disconnect_data.empty()) {
- int bind_count=c.binds.size();
- int bind=0;
+ const _ObjectSignalDisconnectData &dd = disconnect_data.front()->get();
+ disconnect(dd.signal,dd.target,dd.method);
+ disconnect_data.pop_front();
+ }
- for(int i=0;bind < bind_count && i<VARIANT_ARG_MAX;i++) {
+}
- if (argptr[i]->get_type()==Variant::NIL) {
- argptr[i]=&c.binds[bind];
- bind++;
- }
- }
+void Object::emit_signal(const StringName& p_name,VARIANT_ARG_DECLARE) {
- if (c.flags&CONNECT_DEFERRED) {
- MessageQueue::get_singleton()->push_call(t._id,t.method,VARIANT_ARGPTRS_PASS);
- } else {
- Object *obj = ObjectDB::get_instance(t._id);
- ERR_CONTINUE(!obj); //yeah this should always be here
- obj->call( t.method, VARIANT_ARGPTRS_PASS );
- }
+ VARIANT_ARGPTRS;
- if (c.flags&CONNECT_ONESHOT) {
- _ObjectSignalDisconnectData dd;
- dd.signal=p_name;
- dd.target=ObjectDB::get_instance(t._id);
- dd.method=t.method;
- disconnect_data.push_back(dd);
- }
+ int argc=0;
+ for(int i=0;i<VARIANT_ARG_MAX;i++) {
+ if (argptr[i]->get_type()==Variant::NIL)
+ break;
+ argc++;
}
-
-
- s->lock--;
-#endif
- while (!disconnect_data.empty()) {
-
- const _ObjectSignalDisconnectData &dd = disconnect_data.front()->get();
- disconnect(dd.signal,dd.target,dd.method);
- disconnect_data.pop_front();
- }
+ emit_signal(p_name,argptr,argc);
}
@@ -1298,11 +1293,39 @@ void Object::_emit_signal(const StringName& p_name,const Array& p_pargs){
#endif
Array Object::_get_signal_list() const{
- return Array();
+ List<MethodInfo> signal_list;
+ get_signal_list(&signal_list);
+
+ Array ret;
+ for (List<MethodInfo>::Element *E=signal_list.front();E;E=E->next()) {
+
+ ret.push_back(_get_dict_from_method(E->get()));
+ }
+
+ return ret;
}
Array Object::_get_signal_connection_list(const String& p_signal) const{
- return Array();
+ List<Connection> conns;
+ get_all_signal_connections(&conns);
+
+ Array ret;
+
+ for (List<Connection>::Element *E=conns.front();E;E=E->next()) {
+
+ Connection &c=E->get();
+ Dictionary rc;
+ rc["signal"]=c.signal;
+ rc["method"]=c.method;
+ rc["source"]=c.source;
+ rc["target"]=c.target;
+ rc["binds"]=c.binds;
+ rc["flags"]=c.flags;
+ ret.push_back(rc);
+ }
+
+ return ret;
+
}
@@ -1404,6 +1427,10 @@ bool Object::is_connected(const StringName& p_signal, Object *p_to_object, const
bool signal_is_valid = ObjectTypeDB::has_signal(get_type_name(),p_signal);
if (signal_is_valid)
return false;
+
+ if (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal))
+ return false;
+
ERR_EXPLAIN("Nonexistent signal: "+p_signal);
ERR_FAIL_COND_V(!s,false);
}
@@ -1545,7 +1572,7 @@ void Object::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get","property"),&Object::_get_bind);
ObjectTypeDB::bind_method(_MD("get_property_list"),&Object::_get_property_list_bind);
ObjectTypeDB::bind_method(_MD("get_method_list"),&Object::_get_method_list_bind);
- ObjectTypeDB::bind_method(_MD("notification","what"),&Object::notification,DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("notification","what","reversed"),&Object::notification,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_instance_ID"),&Object::get_instance_ID);
ObjectTypeDB::bind_method(_MD("set_script","script:Script"),&Object::set_script);
@@ -1608,11 +1635,12 @@ void Object::_bind_methods() {
ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_deferred",&Object::_call_deferred_bind,mi,defargs);
}
- ObjectTypeDB::bind_method(_MD("callv:var","method","arg_array"),&Object::callv);
+ ObjectTypeDB::bind_method(_MD("callv:Variant","method","arg_array"),&Object::callv);
- ObjectTypeDB::bind_method(_MD("has_method"),&Object::has_method);
+ ObjectTypeDB::bind_method(_MD("has_method","method"),&Object::has_method);
ObjectTypeDB::bind_method(_MD("get_signal_list"),&Object::_get_signal_list);
+ ObjectTypeDB::bind_method(_MD("get_signal_connection_list","signal"),&Object::_get_signal_connection_list);
ObjectTypeDB::bind_method(_MD("connect","signal","target:Object","method","binds","flags"),&Object::connect,DEFVAL(Array()),DEFVAL(0));
ObjectTypeDB::bind_method(_MD("disconnect","signal","target:Object","method"),&Object::disconnect);
@@ -1694,6 +1722,26 @@ void Object::get_translatable_strings(List<String> *p_strings) const {
}
+Variant::Type Object::get_static_property_type(const StringName& p_property, bool *r_valid) const {
+
+ bool valid;
+ Variant::Type t = ObjectTypeDB::get_property_type(get_type_name(),p_property,&valid);
+ if (valid) {
+ if (r_valid)
+ *r_valid=true;
+ return t;
+ }
+
+ if (get_script_instance()) {
+ return get_script_instance()->get_property_type(p_property,r_valid);
+ }
+ if (r_valid)
+ *r_valid=false;
+
+ return Variant::NIL;
+
+}
+
bool Object::is_queued_for_deletion() const {
return _is_queued_for_deletion;
}
diff --git a/core/object.h b/core/object.h
index 981a83958c..dcebf9b2a2 100644
--- a/core/object.h
+++ b/core/object.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -593,6 +593,7 @@ public:
void add_user_signal(const MethodInfo& p_signal);
void emit_signal(const StringName& p_name,VARIANT_ARG_LIST);
+ void emit_signal(const StringName& p_name, const Variant** p_args, int p_argcount);
void get_signal_list(List<MethodInfo> *p_signals ) const;
void get_signal_connection_list(const StringName& p_signal,List<Connection> *p_connections) const;
void get_all_signal_connections(List<Connection> *p_connections) const;
@@ -606,6 +607,8 @@ public:
void set_block_signals(bool p_block);
bool is_blocking_signals() const;
+ Variant::Type get_static_property_type(const StringName& p_property,bool *r_valid=NULL) const;
+
virtual void get_translatable_strings(List<String> *p_strings) const;
virtual void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp
index a64b3d2715..dd9304f1f9 100644
--- a/core/object_type_db.cpp
+++ b/core/object_type_db.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -612,6 +612,7 @@ void ObjectTypeDB::add_property(StringName p_type,const PropertyInfo& p_pinfo, c
psg._setptr=mb_set;
psg._getptr=mb_get;
psg.index=p_index;
+ psg.type=p_pinfo.type;
type->property_setget[p_pinfo.name]=psg;
@@ -634,7 +635,7 @@ void ObjectTypeDB::get_property_list(StringName p_type,List<PropertyInfo> *p_lis
}
}
-bool ObjectTypeDB::set_property(Object* p_object,const StringName& p_property, const Variant& p_value) {
+bool ObjectTypeDB::set_property(Object* p_object,const StringName& p_property, const Variant& p_value,bool *r_valid) {
TypeInfo *type=types.getptr(p_object->get_type_name());
@@ -643,13 +644,17 @@ bool ObjectTypeDB::set_property(Object* p_object,const StringName& p_property, c
const PropertySetGet *psg = check->property_setget.getptr(p_property);
if (psg) {
- if (!psg->setter)
+ if (!psg->setter) {
+ if (r_valid)
+ *r_valid=false;
return true; //return true but do nothing
+ }
+
+ Variant::CallError ce;
if (psg->index>=0) {
Variant index=psg->index;
const Variant* arg[2]={&index,&p_value};
- Variant::CallError ce;
// p_object->call(psg->setter,arg,2,ce);
if (psg->_setptr) {
psg->_setptr->call(p_object,arg,2,ce);
@@ -660,13 +665,16 @@ bool ObjectTypeDB::set_property(Object* p_object,const StringName& p_property, c
} else {
const Variant* arg[1]={&p_value};
- Variant::CallError ce;
if (psg->_setptr) {
psg->_setptr->call(p_object,arg,1,ce);
} else {
p_object->call(psg->setter,arg,1,ce);
}
}
+
+ if (r_valid)
+ *r_valid=ce.error==Variant::CallError::CALL_OK;
+
return true;
}
@@ -718,6 +726,29 @@ bool ObjectTypeDB::get_property(Object* p_object,const StringName& p_property, V
return false;
}
+Variant::Type ObjectTypeDB::get_property_type(const StringName& p_type, const StringName& p_property,bool *r_is_valid) {
+
+ TypeInfo *type=types.getptr(p_type);
+ TypeInfo *check=type;
+ while(check) {
+ const PropertySetGet *psg = check->property_setget.getptr(p_property);
+ if (psg) {
+
+ if (r_is_valid)
+ *r_is_valid=true;
+
+ return psg->type;
+ }
+
+ check=check->inherits_ptr;
+ }
+ if (r_is_valid)
+ *r_is_valid=false;
+
+ return Variant::NIL;
+
+}
+
void ObjectTypeDB::set_method_flags(StringName p_type,StringName p_method,int p_flags) {
diff --git a/core/object_type_db.h b/core/object_type_db.h
index bfa0f921e5..f6caf14be5 100644
--- a/core/object_type_db.h
+++ b/core/object_type_db.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -117,6 +117,7 @@ class ObjectTypeDB {
StringName getter;
MethodBind *_setptr;
MethodBind *_getptr;
+ Variant::Type type;
};
struct TypeInfo {
@@ -456,8 +457,9 @@ public:
static void add_property(StringName p_type,const PropertyInfo& p_pinfo, const StringName& p_setter, const StringName& p_getter, int p_index=-1);
static void get_property_list(StringName p_type,List<PropertyInfo> *p_list,bool p_no_inheritance=false);
- static bool set_property(Object* p_object,const StringName& p_property, const Variant& p_value);
+ static bool set_property(Object* p_object, const StringName& p_property, const Variant& p_value, bool *r_valid=NULL);
static bool get_property(Object* p_object,const StringName& p_property, Variant& r_value);
+ static Variant::Type get_property_type(const StringName& p_type, const StringName& p_property,bool *r_is_valid=NULL);
diff --git a/core/os/copymem.cpp b/core/os/copymem.cpp
index 54baf1e232..234ca50b45 100644
--- a/core/os/copymem.cpp
+++ b/core/os/copymem.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/copymem.h b/core/os/copymem.h
index a5d640edbf..d7fc46aae4 100644
--- a/core/os/copymem.h
+++ b/core/os/copymem.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index d0baae5872..32d66a7408 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/dir_access.h b/core/os/dir_access.h
index 8bacc96c60..e97a065998 100644
--- a/core/os/dir_access.h
+++ b/core/os/dir_access.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index ef7efd27e1..d82d0b63c5 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/file_access.h b/core/os/file_access.h
index 8e34013796..51cf839117 100644
--- a/core/os/file_access.h
+++ b/core/os/file_access.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -78,6 +78,7 @@ public:
READ=1,
WRITE=2,
READ_WRITE=3,
+ WRITE_READ=7,
};
virtual void close()=0; ///< close a file
diff --git a/core/os/input.cpp b/core/os/input.cpp
index 15872d02fd..6e1e618d9a 100644
--- a/core/os/input.cpp
+++ b/core/os/input.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -53,8 +53,12 @@ void Input::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_mouse_button_pressed","button"),&Input::is_mouse_button_pressed);
ObjectTypeDB::bind_method(_MD("is_joy_button_pressed","device","button"),&Input::is_joy_button_pressed);
ObjectTypeDB::bind_method(_MD("is_action_pressed","action"),&Input::is_action_pressed);
+ ObjectTypeDB::bind_method(_MD("add_joy_mapping","mapping", "update_existing"),&Input::add_joy_mapping, DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("remove_joy_mapping","guid"),&Input::remove_joy_mapping);
+ ObjectTypeDB::bind_method(_MD("is_joy_known","device"),&Input::is_joy_known);
ObjectTypeDB::bind_method(_MD("get_joy_axis","device","axis"),&Input::get_joy_axis);
ObjectTypeDB::bind_method(_MD("get_joy_name","device"),&Input::get_joy_name);
+ ObjectTypeDB::bind_method(_MD("get_joy_guid","device"),&Input::get_joy_guid);
ObjectTypeDB::bind_method(_MD("get_accelerometer"),&Input::get_accelerometer);
//ObjectTypeDB::bind_method(_MD("get_mouse_pos"),&Input::get_mouse_pos); - this is not the function you want
ObjectTypeDB::bind_method(_MD("get_mouse_speed"),&Input::get_mouse_speed);
@@ -62,8 +66,8 @@ void Input::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_mouse_mode","mode"),&Input::set_mouse_mode);
ObjectTypeDB::bind_method(_MD("get_mouse_mode"),&Input::get_mouse_mode);
ObjectTypeDB::bind_method(_MD("warp_mouse_pos","to"),&Input::warp_mouse_pos);
- ObjectTypeDB::bind_method(_MD("action_press"),&Input::action_press);
- ObjectTypeDB::bind_method(_MD("action_release"),&Input::action_release);
+ ObjectTypeDB::bind_method(_MD("action_press","action"),&Input::action_press);
+ ObjectTypeDB::bind_method(_MD("action_release","action"),&Input::action_release);
ObjectTypeDB::bind_method(_MD("set_custom_mouse_cursor","image:Texture","hotspot"),&Input::set_custom_mouse_cursor,DEFVAL(Vector2()));
BIND_CONSTANT( MOUSE_MODE_VISIBLE );
diff --git a/core/os/input.h b/core/os/input.h
index 8aa0e6b18a..2dd4496f26 100644
--- a/core/os/input.h
+++ b/core/os/input.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -62,8 +62,11 @@ public:
virtual float get_joy_axis(int p_device,int p_axis)=0;
virtual String get_joy_name(int p_idx)=0;
- virtual void joy_connection_changed(int p_idx, bool p_connected, String p_name)=0;
-
+ virtual void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid)=0;
+ virtual void add_joy_mapping(String p_mapping, bool p_update_existing=false)=0;
+ virtual void remove_joy_mapping(String p_guid)=0;
+ virtual bool is_joy_known(int p_device)=0;
+ virtual String get_joy_guid(int p_device) const=0;
virtual Point2 get_mouse_pos() const=0;
virtual Point2 get_mouse_speed() const=0;
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index 2bd62927b0..2f39567a7e 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -156,6 +156,7 @@ bool InputEvent::is_pressed() const {
case MOUSE_BUTTON: return mouse_button.pressed;
case JOYSTICK_BUTTON: return joy_button.pressed;
case SCREEN_TOUCH: return screen_touch.pressed;
+ case JOYSTICK_MOTION: return InputMap::get_singleton()->event_is_joy_motion_action_pressed(*this);
case ACTION: return action.pressed;
default: {}
}
diff --git a/core/os/input_event.h b/core/os/input_event.h
index 4bb122ebc1..b601adc875 100644
--- a/core/os/input_event.h
+++ b/core/os/input_event.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -143,6 +143,9 @@ enum {
JOY_ANALOG_2_X = JOY_AXIS_4,
JOY_ANALOG_2_Y = JOY_AXIS_5,
+
+ JOY_ANALOG_L2 = JOY_AXIS_6,
+ JOY_ANALOG_R2 = JOY_AXIS_7,
};
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp
index 10e64c3961..633aa06a9a 100644
--- a/core/os/keyboard.cpp
+++ b/core/os/keyboard.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
index eaf656dd4d..69e74d1252 100644
--- a/core/os/keyboard.h
+++ b/core/os/keyboard.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
index c37c281fb9..310bbaa3b8 100644
--- a/core/os/main_loop.cpp
+++ b/core/os/main_loop.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/main_loop.h b/core/os/main_loop.h
index c5d58120c5..059624dbe4 100644
--- a/core/os/main_loop.h
+++ b/core/os/main_loop.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory.cpp b/core/os/memory.cpp
index 1d9ac4e302..f7f8fef2b7 100644
--- a/core/os/memory.cpp
+++ b/core/os/memory.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory.h b/core/os/memory.h
index 0a35c93fdb..98b973bc06 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory_pool_dynamic.cpp b/core/os/memory_pool_dynamic.cpp
index d1c41aff84..6be8d0a36d 100644
--- a/core/os/memory_pool_dynamic.cpp
+++ b/core/os/memory_pool_dynamic.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory_pool_dynamic.h b/core/os/memory_pool_dynamic.h
index 00999ee24d..82149bcf5d 100644
--- a/core/os/memory_pool_dynamic.h
+++ b/core/os/memory_pool_dynamic.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory_pool_dynamic_prealloc.cpp b/core/os/memory_pool_dynamic_prealloc.cpp
index c7c25f32d1..f76c2a12b4 100644
--- a/core/os/memory_pool_dynamic_prealloc.cpp
+++ b/core/os/memory_pool_dynamic_prealloc.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory_pool_dynamic_prealloc.h b/core/os/memory_pool_dynamic_prealloc.h
index 3523079bac..d2256c0c98 100644
--- a/core/os/memory_pool_dynamic_prealloc.h
+++ b/core/os/memory_pool_dynamic_prealloc.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory_pool_dynamic_static.cpp b/core/os/memory_pool_dynamic_static.cpp
index 029ef450cd..894066708e 100644
--- a/core/os/memory_pool_dynamic_static.cpp
+++ b/core/os/memory_pool_dynamic_static.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory_pool_dynamic_static.h b/core/os/memory_pool_dynamic_static.h
index a870f3070c..6177c78de7 100644
--- a/core/os/memory_pool_dynamic_static.h
+++ b/core/os/memory_pool_dynamic_static.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory_pool_static.cpp b/core/os/memory_pool_static.cpp
index d3617eac73..321f4d989e 100644
--- a/core/os/memory_pool_static.cpp
+++ b/core/os/memory_pool_static.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory_pool_static.h b/core/os/memory_pool_static.h
index 40bd1aaf0e..2e11b7ded4 100644
--- a/core/os/memory_pool_static.h
+++ b/core/os/memory_pool_static.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/mutex.cpp b/core/os/mutex.cpp
index be984c080b..9b379009b9 100644
--- a/core/os/mutex.cpp
+++ b/core/os/mutex.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/mutex.h b/core/os/mutex.h
index ac6d36d635..f16375aa26 100644
--- a/core/os/mutex.h
+++ b/core/os/mutex.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 8caf95e4d1..e93038f854 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -50,7 +50,7 @@ uint64_t OS::get_unix_time() const {
return 0;
};
-uint64_t OS::get_system_time_msec() const {
+uint64_t OS::get_system_time_secs() const {
return 0;
}
void OS::debug_break() {
@@ -112,6 +112,14 @@ float OS::get_target_fps() const {
return _target_fps;
}
+void OS::set_keep_screen_on(bool p_enabled) {
+ _keep_screen_on=p_enabled;
+}
+
+bool OS::is_keep_screen_on() const {
+ return _keep_screen_on;
+}
+
void OS::set_low_processor_usage_mode(bool p_enabled) {
low_processor_usage_mode=p_enabled;
@@ -507,12 +515,20 @@ float OS::get_time_scale() const {
return _time_scale;
}
+bool OS::is_joy_known(int p_device) {
+ return true;
+}
+
+String OS::get_joy_guid(int p_device) const {
+ return "Default Joystick";
+}
OS::OS() {
last_error=NULL;
frames_drawn=0;
singleton=this;
ips=60;
+ _keep_screen_on=true; // set default value to true, because this had been true before godot 2.0.
low_processor_usage_mode=false;
_verbose_stdout=false;
_frame_delay=0;
diff --git a/core/os/os.h b/core/os/os.h
index e5338b4a02..bc3fad302a 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -46,6 +46,7 @@ class OS {
String _custom_level;
List<String> _cmdline;
int ips;
+ bool _keep_screen_on;
bool low_processor_usage_mode;
bool _verbose_stdout;
String _local_clipboard;
@@ -75,7 +76,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=1280,int p_height=720,bool p_fullscreen=false, bool p_resizable = true) {width=p_width; height=p_height; fullscreen=p_fullscreen; resizable = p_resizable; }
};
protected:
friend class Main;
@@ -180,10 +181,12 @@ public:
virtual float get_frames_per_second() const { return _fps; };
-
+ virtual void set_keep_screen_on(bool p_enabled);
+ virtual bool is_keep_screen_on() const;
virtual void set_low_processor_usage_mode(bool p_enabled);
virtual bool is_in_low_processor_usage_mode() const;
+ virtual String get_installed_templates_path() const { return ""; };
virtual String get_executable_path() const;
virtual Error execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL)=0;
virtual Error kill(const ProcessID& p_pid)=0;
@@ -255,7 +258,7 @@ public:
virtual Time get_time(bool local=false) const=0;
virtual TimeZoneInfo get_time_zone_info() const=0;
virtual uint64_t get_unix_time() const;
- virtual uint64_t get_system_time_msec() const;
+ virtual uint64_t get_system_time_secs() const;
virtual void delay_usec(uint32_t p_usec) const=0;
virtual uint64_t get_ticks_usec() const=0;
@@ -396,6 +399,9 @@ public:
_FORCE_INLINE_ bool get_use_pixel_snap() const { return _pixel_snap; }
+ virtual bool is_joy_known(int p_device);
+ virtual String get_joy_guid(int p_device)const;
+
OS();
virtual ~OS();
diff --git a/core/os/pc_joystick_map.h b/core/os/pc_joystick_map.h
index 111dc9b3a8..df123c5c1b 100644
--- a/core/os/pc_joystick_map.h
+++ b/core/os/pc_joystick_map.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/semaphore.cpp b/core/os/semaphore.cpp
index 8cb431d2cc..5fa2d339dc 100644
--- a/core/os/semaphore.cpp
+++ b/core/os/semaphore.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/semaphore.h b/core/os/semaphore.h
index e8ad9d3c3a..b65542ce35 100644
--- a/core/os/semaphore.h
+++ b/core/os/semaphore.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/shell.cpp b/core/os/shell.cpp
index 3746dc6804..8737d97fa0 100644
--- a/core/os/shell.cpp
+++ b/core/os/shell.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/shell.h b/core/os/shell.h
index 7ef5abbdef..805dd70301 100644
--- a/core/os/shell.h
+++ b/core/os/shell.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/thread.cpp b/core/os/thread.cpp
index 96b0f561ca..7fb1e969d4 100644
--- a/core/os/thread.cpp
+++ b/core/os/thread.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -58,6 +58,11 @@ void Thread::wait_to_finish(Thread *p_thread) {
}
+Error Thread::set_name(const String &p_name) {
+
+ return ERR_UNAVAILABLE;
+};
+
Thread::Thread()
{
}
diff --git a/core/os/thread.h b/core/os/thread.h
index 590fee1fc6..5711561809 100644
--- a/core/os/thread.h
+++ b/core/os/thread.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,6 +35,7 @@
@author Juan Linietsky <reduzio@gmail.com>
*/
+#include "ustring.h"
typedef void (*ThreadCreateCallback)(void *p_userdata);
@@ -71,7 +72,8 @@ protected:
Thread();
public:
-
+
+ virtual Error set_name(const String& p_name);
virtual ID get_ID() const=0;
diff --git a/core/os/thread_dummy.cpp b/core/os/thread_dummy.cpp
index 4e139f6379..30a0e2696c 100644
--- a/core/os/thread_dummy.cpp
+++ b/core/os/thread_dummy.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/thread_dummy.h b/core/os/thread_dummy.h
index a83e42ff98..800eef9ef9 100644
--- a/core/os/thread_dummy.h
+++ b/core/os/thread_dummy.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/thread_safe.cpp b/core/os/thread_safe.cpp
index 9a20db6a9d..f252190504 100644
--- a/core/os/thread_safe.cpp
+++ b/core/os/thread_safe.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/thread_safe.h b/core/os/thread_safe.h
index 62d2181279..793dd88543 100644
--- a/core/os/thread_safe.h
+++ b/core/os/thread_safe.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp
index fa17e93aa8..dd736502a3 100644
--- a/core/packed_data_container.cpp
+++ b/core/packed_data_container.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/packed_data_container.h b/core/packed_data_container.h
index f4152bbb4d..9183dcb90e 100644
--- a/core/packed_data_container.h
+++ b/core/packed_data_container.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/pair.cpp b/core/pair.cpp
index 17076bb379..14bb2d7775 100644
--- a/core/pair.cpp
+++ b/core/pair.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/pair.h b/core/pair.h
index 83fc837fff..9bffc37f49 100644
--- a/core/pair.h
+++ b/core/pair.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/path_db.cpp b/core/path_db.cpp
index c6ea25d966..d3521fcb23 100644
--- a/core/path_db.cpp
+++ b/core/path_db.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/path_db.h b/core/path_db.h
index de84216006..9c9be65d28 100644
--- a/core/path_db.h
+++ b/core/path_db.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/path_remap.cpp b/core/path_remap.cpp
index 2ef39470a0..d4cb883f41 100644
--- a/core/path_remap.cpp
+++ b/core/path_remap.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/path_remap.h b/core/path_remap.h
index cb2a045668..66ebe7987b 100644
--- a/core/path_remap.h
+++ b/core/path_remap.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/pool_allocator.cpp b/core/pool_allocator.cpp
index d7dca45836..23be650fda 100644
--- a/core/pool_allocator.cpp
+++ b/core/pool_allocator.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/pool_allocator.h b/core/pool_allocator.h
index 4b0f931eb3..2c5920149b 100644
--- a/core/pool_allocator.h
+++ b/core/pool_allocator.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/print_string.cpp b/core/print_string.cpp
index 42e018f303..e364388b7b 100644
--- a/core/print_string.cpp
+++ b/core/print_string.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -66,7 +66,7 @@ void remove_print_handler(PrintHandlerList *p_handler) {
l=l->next;
}
- OS::get_singleton()->print("print hanlder list is %p\n",print_handler_list);
+ OS::get_singleton()->print("print handler list is %p\n",print_handler_list);
ERR_FAIL_COND(l==NULL);
_global_unlock();
diff --git a/core/print_string.h b/core/print_string.h
index 4ea389b3a1..0aa5b4c8e9 100644
--- a/core/print_string.h
+++ b/core/print_string.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/ref_ptr.cpp b/core/ref_ptr.cpp
index ddb8054e3b..dee2b9a164 100644
--- a/core/ref_ptr.cpp
+++ b/core/ref_ptr.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/ref_ptr.h b/core/ref_ptr.h
index d1ee6a3a7d..68788b73cd 100644
--- a/core/ref_ptr.h
+++ b/core/ref_ptr.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/reference.cpp b/core/reference.cpp
index 509e132b5a..90bafd0a9c 100644
--- a/core/reference.cpp
+++ b/core/reference.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/reference.h b/core/reference.h
index 65f31f78f3..8bfbf19ab6 100644
--- a/core/reference.h
+++ b/core/reference.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 8754946bb1..d977ea3e18 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -101,10 +101,12 @@ void register_core_types() {
resource_loader_binary = memnew( ResourceFormatLoaderBinary );
ResourceLoader::add_resource_format_loader(resource_loader_binary);
+#ifdef XML_ENABLED
resource_saver_xml = memnew( ResourceFormatSaverXML );
ResourceSaver::add_resource_format_saver(resource_saver_xml);
resource_loader_xml = memnew( ResourceFormatLoaderXML );
ResourceLoader::add_resource_format_loader(resource_loader_xml);
+#endif
ObjectTypeDB::register_type<Object>();
diff --git a/core/register_core_types.h b/core/register_core_types.h
index a84849c969..239d67f1ec 100644
--- a/core/register_core_types.h
+++ b/core/register_core_types.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/res_ptr.cpp b/core/res_ptr.cpp
index fcff285e8f..11312b8021 100644
--- a/core/res_ptr.cpp
+++ b/core/res_ptr.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/res_ptr.h b/core/res_ptr.h
index 21f7fb6a2c..e1dc66b290 100644
--- a/core/res_ptr.h
+++ b/core/res_ptr.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/resource.cpp b/core/resource.cpp
index 6967599f96..e0706cf541 100644
--- a/core/resource.cpp
+++ b/core/resource.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -278,7 +278,7 @@ void Resource::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_import_metadata","metadata"),&Resource::set_import_metadata);
ObjectTypeDB::bind_method(_MD("get_import_metadata"),&Resource::get_import_metadata);
- ObjectTypeDB::bind_method(_MD("duplicate"),&Resource::duplicate,DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("duplicate","subresources"),&Resource::duplicate,DEFVAL(false));
ADD_SIGNAL( MethodInfo("changed") );
ADD_PROPERTY( PropertyInfo(Variant::STRING,"resource/path",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR ), _SCS("set_path"),_SCS("get_path"));
ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"resource/name"), _SCS("set_name"),_SCS("get_name"));
diff --git a/core/resource.h b/core/resource.h
index 3596abe673..f0c86631cc 100644
--- a/core/resource.h
+++ b/core/resource.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -144,7 +144,7 @@ public:
#ifdef TOOLS_ENABLED
- void set_last_modified_time(uint64_t p_time) { last_modified_time=p_time; }
+ virtual void set_last_modified_time(uint64_t p_time) { last_modified_time=p_time; }
uint64_t get_last_modified_time() const { return last_modified_time; }
#endif
diff --git a/core/rid.cpp b/core/rid.cpp
index 0870e6ab2d..219c2f0e69 100644
--- a/core/rid.cpp
+++ b/core/rid.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/rid.h b/core/rid.h
index e6582757ee..85ae1b15d3 100644
--- a/core/rid.h
+++ b/core/rid.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/ring_buffer.h b/core/ring_buffer.h
index 3cf9cf9064..4658ec5e51 100644
--- a/core/ring_buffer.h
+++ b/core/ring_buffer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -155,6 +155,12 @@ public:
inline int size() {
return data.size();
};
+
+ inline void clear() {
+ read_pos = 0;
+ write_pos = 0;
+
+ }
void resize(int p_power) {
int old_size = size();
diff --git a/core/safe_refcount.cpp b/core/safe_refcount.cpp
index afe2a4eb33..7718e466f2 100644
--- a/core/safe_refcount.cpp
+++ b/core/safe_refcount.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/safe_refcount.h b/core/safe_refcount.h
index 481b9fa7e9..e5dc854c23 100644
--- a/core/safe_refcount.h
+++ b/core/safe_refcount.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/script_debugger_debugger.cpp b/core/script_debugger_debugger.cpp
index 5c592a130c..71ad33f5ed 100644
--- a/core/script_debugger_debugger.cpp
+++ b/core/script_debugger_debugger.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/script_debugger_local.cpp b/core/script_debugger_local.cpp
index 649bbe89f0..3e442f7f59 100644
--- a/core/script_debugger_local.cpp
+++ b/core/script_debugger_local.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/script_debugger_local.h b/core/script_debugger_local.h
index 45ff1d4466..4abacfc519 100644
--- a/core/script_debugger_local.h
+++ b/core/script_debugger_local.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index d72c9f7532..b56ff4c0e1 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,7 +30,7 @@
#include "os/os.h"
#include "io/ip.h"
#include "globals.h"
-
+#include "os/input.h"
void ScriptDebuggerRemote::_send_video_memory() {
List<ResourceUsage> usage;
@@ -135,6 +135,10 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) {
packet_peer_stream->put_var(p_can_continue);
packet_peer_stream->put_var(p_script->debug_get_error());
+ Input::MouseMode mouse_mode=Input::get_singleton()->get_mouse_mode();
+ if (mouse_mode!=Input::MOUSE_MODE_VISIBLE)
+ Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
+
while(true) {
@@ -296,6 +300,9 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) {
packet_peer_stream->put_var("debug_exit");
packet_peer_stream->put_var(0);
+ if (mouse_mode!=Input::MOUSE_MODE_VISIBLE)
+ Input::get_singleton()->set_mouse_mode(mouse_mode);
+
}
diff --git a/core/script_debugger_remote.h b/core/script_debugger_remote.h
index 973fa23212..f18e212236 100644
--- a/core/script_debugger_remote.h
+++ b/core/script_debugger_remote.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/script_language.cpp b/core/script_language.cpp
index 35c50b1022..0eac39e7d1 100644
--- a/core/script_language.cpp
+++ b/core/script_language.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -92,6 +92,22 @@ void ScriptServer::init_languages() {
}
}
+void ScriptInstance::get_property_state(List<Pair<StringName, Variant> > &state) {
+
+ List<PropertyInfo> pinfo;
+ get_property_list(&pinfo);
+ for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+
+ if (E->get().usage&PROPERTY_USAGE_STORAGE) {
+ Pair<StringName,Variant> p;
+ p.first=E->get().name;
+ if (get(p.first,p.second))
+ state.push_back(p);
+ }
+ }
+}
+
+
Variant ScriptInstance::call(const StringName& p_method,VARIANT_ARG_DECLARE) {
VARIANT_ARGPTRS;
@@ -267,6 +283,20 @@ void PlaceHolderScriptInstance::get_property_list(List<PropertyInfo> *p_properti
}
}
+Variant::Type PlaceHolderScriptInstance::get_property_type(const StringName& p_name,bool *r_is_valid) const {
+
+ if (values.has(p_name)) {
+ if (r_is_valid)
+ *r_is_valid=true;
+ return values[p_name].get_type();
+ }
+ if (r_is_valid)
+ *r_is_valid=false;
+
+ return Variant::NIL;
+}
+
+
void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties,const Map<StringName,Variant>& p_values) {
diff --git a/core/script_language.h b/core/script_language.h
index 5a0f673b94..7e278b8555 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -82,6 +82,7 @@ public:
virtual StringName get_instance_base_type() const=0; // this may not work in all scripts, will return empty if so
virtual ScriptInstance* instance_create(Object *p_this)=0;
virtual bool instance_has(const Object *p_this) const=0;
+
virtual bool has_source_code() const=0;
virtual String get_source_code() const=0;
@@ -97,6 +98,7 @@ public:
virtual bool has_script_signal(const StringName& p_signal) const=0;
virtual void get_script_signal_list(List<MethodInfo> *r_signals) const=0;
+ virtual bool get_property_default_value(const StringName& p_property,Variant& r_value) const=0;
virtual void update_exports() {} //editor tool
@@ -109,6 +111,9 @@ public:
virtual bool set(const StringName& p_name, const Variant& p_value)=0;
virtual bool get(const StringName& p_name, Variant &r_ret) const=0;
virtual void get_property_list(List<PropertyInfo> *p_properties) const=0;
+ virtual Variant::Type get_property_type(const StringName& p_name,bool *r_is_valid=NULL) const=0;
+
+ virtual void get_property_state(List<Pair<StringName,Variant> > &state);
virtual void get_method_list(List<MethodInfo> *p_list) const=0;
virtual bool has_method(const StringName& p_method) const=0;
@@ -163,6 +168,7 @@ public:
virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const=0;
virtual Error complete_code(const String& p_code, const String& p_base_path, Object*p_owner,List<String>* r_options,String& r_call_hint) { return ERR_UNAVAILABLE; }
virtual void auto_indent_code(String& p_code,int p_from_line,int p_to_line) const=0;
+ virtual void add_global_constant(const StringName& p_variable,const Variant& p_value)=0;
/* DEBUGGER FUNCTIONS */
@@ -208,6 +214,7 @@ public:
virtual bool set(const StringName& p_name, const Variant& p_value);
virtual bool get(const StringName& p_name, Variant &r_ret) const;
virtual void get_property_list(List<PropertyInfo> *p_properties) const;
+ virtual Variant::Type get_property_type(const StringName& p_name,bool *r_is_valid=NULL) const;
virtual void get_method_list(List<MethodInfo> *p_list) const {}
virtual bool has_method(const StringName& p_method) const { return false; }
diff --git a/core/self_list.h b/core/self_list.h
index b414baaba6..bfdcfbfbc2 100644
--- a/core/self_list.h
+++ b/core/self_list.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/set.h b/core/set.h
index 91c4e3f9c4..808ffe5b36 100644
--- a/core/set.h
+++ b/core/set.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/simple_type.h b/core/simple_type.h
index 84e08bf0b4..1cc597146e 100644
--- a/core/simple_type.h
+++ b/core/simple_type.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/sort.h b/core/sort.h
index 65664d0ed8..bd61921c8a 100644
--- a/core/sort.h
+++ b/core/sort.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/string_db.cpp b/core/string_db.cpp
index b48d9f37d4..0e953cc326 100644
--- a/core/string_db.cpp
+++ b/core/string_db.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/string_db.h b/core/string_db.h
index 3b3249bf5e..f6c6ecefec 100644
--- a/core/string_db.h
+++ b/core/string_db.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/translation.cpp b/core/translation.cpp
index 8247cd1201..e4dad8d8de 100644
--- a/core/translation.cpp
+++ b/core/translation.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -626,7 +626,7 @@ bool TranslationServer::_load_translations(const String& p_from) {
for(int i=0;i<tcount;i++) {
- print_line( "Loading translation from " + r[i] );
+ //print_line( "Loading translation from " + r[i] );
Ref<Translation> tr = ResourceLoader::load(r[i]);
if (tr.is_valid())
add_translation(tr);
@@ -670,10 +670,10 @@ void TranslationServer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_locale","locale"),&TranslationServer::set_locale);
ObjectTypeDB::bind_method(_MD("get_locale"),&TranslationServer::get_locale);
- ObjectTypeDB::bind_method(_MD("translate"),&TranslationServer::translate);
+ ObjectTypeDB::bind_method(_MD("translate","message"),&TranslationServer::translate);
- ObjectTypeDB::bind_method(_MD("add_translation"),&TranslationServer::add_translation);
- ObjectTypeDB::bind_method(_MD("remove_translation"),&TranslationServer::remove_translation);
+ ObjectTypeDB::bind_method(_MD("add_translation","translation:Translation"),&TranslationServer::add_translation);
+ ObjectTypeDB::bind_method(_MD("remove_translation","translation:Translation"),&TranslationServer::remove_translation);
ObjectTypeDB::bind_method(_MD("clear"),&TranslationServer::clear);
diff --git a/core/translation.h b/core/translation.h
index 54118cd3b5..5be6b8913a 100644
--- a/core/translation.h
+++ b/core/translation.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/typedefs.h b/core/typedefs.h
index 6ca31fd137..1ca7a4f66d 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -197,10 +197,22 @@ static inline int get_shift_from_power_of_2( unsigned int p_pixel ) {
return -1;
}
+/** Swap 16 bits value for endianness */
+static inline uint16_t BSWAP16(uint16_t x) {
+ return (x>>8)|(x<<8);
+}
/** Swap 32 bits value for endianness */
static inline uint32_t BSWAP32(uint32_t x) {
return((x<<24)|((x<<8)&0x00FF0000)|((x>>8)&0x0000FF00)|(x>>24));
}
+/** Swap 64 bits value for endianness */
+
+static inline uint64_t BSWAP64(uint64_t x) {
+ x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32;
+ x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
+ x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8;
+ return x;
+}
/** When compiling with RTTI, we can add an "extra"
* layer of safeness in many operations, so dynamic_cast
diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp
index 85cc2bbc7f..ecbda1d3fd 100644
--- a/core/undo_redo.cpp
+++ b/core/undo_redo.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -482,8 +482,8 @@ void UndoRedo::_bind_methods() {
ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"add_undo_method",&UndoRedo::_add_undo_method,mi,defargs);
}
- ObjectTypeDB::bind_method(_MD("add_do_property","object", "property", "value:var"),&UndoRedo::add_do_property);
- ObjectTypeDB::bind_method(_MD("add_undo_property","object", "property", "value:var"),&UndoRedo::add_undo_property);
+ ObjectTypeDB::bind_method(_MD("add_do_property","object", "property", "value:Variant"),&UndoRedo::add_do_property);
+ ObjectTypeDB::bind_method(_MD("add_undo_property","object", "property", "value:Variant"),&UndoRedo::add_undo_property);
ObjectTypeDB::bind_method(_MD("add_do_reference","object"),&UndoRedo::add_do_reference);
ObjectTypeDB::bind_method(_MD("add_undo_reference","object"),&UndoRedo::add_undo_reference);
ObjectTypeDB::bind_method(_MD("clear_history"),&UndoRedo::clear_history);
diff --git a/core/undo_redo.h b/core/undo_redo.h
index 141a413c2a..7f63ba9ed6 100644
--- a/core/undo_redo.h
+++ b/core/undo_redo.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/ustring.cpp b/core/ustring.cpp
index f3c89a7908..ee750c39e5 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -897,17 +897,8 @@ String String::num(double p_num,int p_decimals) {
}
char buf[256];
-#if defined(__GNUC__)
-#ifdef MINGW_ENABLED
- //snprintf is inexplicably broken in mingw
- //sprintf(buf,fmt,p_num);
- _snprintf(buf,256,fmt,p_num);
-#else
+#if defined(__GNUC__) || defined(_MSC_VER)
snprintf(buf,256,fmt,p_num);
-#endif
-
-#elif defined(_MSC_VER)
- _snprintf(buf,256,fmt,p_num);
#else
sprintf(buf,fmt,p_num);
#endif
@@ -1178,10 +1169,7 @@ String String::num_scientific(double p_num) {
char buf[256];
-#if defined(_MSC_VER) || defined(MINGW_ENABLED)
-
- _snprintf(buf,256,"%lg",p_num);
-#elif defined(__GNUC__)
+#if defined(__GNUC__) || defined(_MSC_VER)
snprintf(buf,256,"%lg",p_num);
#else
sprintf(buf,"%.16lg",p_num);
@@ -1648,12 +1636,16 @@ int64_t String::to_int64() const {
return integer*sign;
}
-int String::to_int(const char* p_str) {
+int String::to_int(const char* p_str,int p_len) {
int to=0;
- while(p_str[to]!=0 && p_str[to]!='.')
- to++;
+ if (p_len>=0)
+ to=p_len;
+ else {
+ while(p_str[to]!=0 && p_str[to]!='.')
+ to++;
+ }
int integer=0;
@@ -3096,7 +3088,11 @@ String String::http_escape() const {
res += ord;
} else {
char h_Val[3];
- snprintf(h_Val, 3, "%.2X", ord);
+#if defined(__GNUC__) || defined(_MSC_VER)
+ snprintf(h_Val, 3, "%.2X", ord);
+#else
+ sprintf(h_Val, "%.2X", ord);
+#endif
res += "%";
res += h_Val;
}
@@ -3162,6 +3158,21 @@ String String::c_escape() const {
return escaped;
}
+String String::json_escape() const {
+
+ String escaped=*this;
+ escaped=escaped.replace("\\","\\\\");
+ escaped=escaped.replace("\b","\\b");
+ escaped=escaped.replace("\f","\\f");
+ escaped=escaped.replace("\n","\\n");
+ escaped=escaped.replace("\r","\\r");
+ escaped=escaped.replace("\t","\\t");
+ escaped=escaped.replace("\v","\\v");
+ escaped=escaped.replace("\"","\\\"");
+
+ return escaped;
+}
+
String String::xml_escape(bool p_escape_quotes) const {
String str=*this;
diff --git a/core/ustring.h b/core/ustring.h
index 2f3c4bff4d..9276afa0f7 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -144,7 +144,7 @@ public:
int to_int() const;
int64_t to_int64() const;
- static int to_int(const char* p_str);
+ static int to_int(const char* p_str, int p_len=-1);
static double to_double(const char* p_str);
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);
@@ -211,6 +211,7 @@ public:
String http_unescape() const;
String c_escape() const;
String c_unescape() const;
+ String json_escape() const;
String world_wrap(int p_chars_per_line) const;
String percent_encode() const;
diff --git a/core/variant.cpp b/core/variant.cpp
index c6a55b10e6..3bd8d80528 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,7 +33,7 @@
#include "scene/gui/control.h"
#include "io/marshalls.h"
#include "core_string_names.h"
-
+#include "variant_parser.h"
String Variant::get_type_name(Variant::Type p_type) {
@@ -706,6 +706,17 @@ bool Variant::operator==(const Variant& p_variant) const {
}
+bool Variant::operator!=(const Variant& p_variant) const {
+
+ if (type!=p_variant.type) //evaluation of operator== needs to be more strict
+ return true;
+ bool v;
+ Variant r;
+ evaluate(OP_NOT_EQUAL,*this,p_variant,r,v);
+ return r;
+
+}
+
bool Variant::operator<(const Variant& p_variant) const {
if (type!=p_variant.type) //if types differ, then order by type first
return type<p_variant.type;
@@ -2973,132 +2984,40 @@ void Variant::construct_from_string(const String& p_string,Variant& r_value,Obje
}
-String Variant::get_construct_string(ObjectDeConstruct p_obj_deconstruct,void *p_deconstruct_ud) const {
-
- switch( type ) {
-
- case NIL: return "null";
- case BOOL: return _data._bool ? "true" : "false";
- case INT: return String::num(_data._int);
- case REAL: return String::num(_data._real);
- case STRING: return "\""+reinterpret_cast<const String*>(_data._mem)->c_escape()+"\"";
- case VECTOR2: return "Vector2("+operator Vector2()+")";
- case RECT2: return "Rect2("+operator Rect2()+")";
- case MATRIX32: return "Matrix32("+operator Matrix32()+")";
- case VECTOR3: return "Vector3("+operator Vector3()+")";
- case PLANE: return "Plane("+operator Plane()+")";
- //case QUAT:
- case _AABB: return "AABB("+operator AABB()+")";
- case QUAT: return "Quat("+operator Quat()+")";
- case MATRIX3: return "Matrix3("+operator Matrix3()+")";
- case TRANSFORM: return "Transform("+operator Transform()+")";
- case NODE_PATH: return "@\""+String(operator NodePath()).c_escape()+"\"";
- case INPUT_EVENT: return "InputEvent()";
- case COLOR: return "Color("+String::num( operator Color().r)+","+String::num( operator Color().g)+","+String::num( operator Color().b)+","+String::num( operator Color().a)+")" ;
- case DICTIONARY: {
-
- const Dictionary &d =*reinterpret_cast<const Dictionary*>(_data._mem);
- //const String *K=NULL;
- String str="{";
- List<Variant> keys;
- d.get_key_list(&keys);
-
- Vector<_VariantStrPair> pairs;
-
- for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
-
- _VariantStrPair sp;
- sp.key=E->get().get_construct_string(p_obj_deconstruct,p_deconstruct_ud);
- sp.value=d[E->get()].get_construct_string(p_obj_deconstruct,p_deconstruct_ud);
- pairs.push_back(sp);
- }
+String Variant::get_construct_string() const {
- pairs.sort();
+ String vars;
+ VariantWriter::write_to_string(*this,vars);
- for(int i=0;i<pairs.size();i++) {
- if (i>0)
- str+=", ";
- str+="("+pairs[i].key+":"+pairs[i].value+")";
- }
- str+="}";
+ return vars;
- return str;
- } break;
- case VECTOR3_ARRAY: {
-
- DVector<Vector3> vec = operator DVector<Vector3>();
- String str="Vector3Array([";
- for(int i=0;i<vec.size();i++) {
-
- if (i>0)
- str+=", ";
- str+=Variant( vec[i] ).get_construct_string();
- }
- return str+"])";
- } break;
- case STRING_ARRAY: {
+}
- DVector<String> vec = operator DVector<String>();
- String str="StringArray([";
- for(int i=0;i<vec.size();i++) {
+String Variant::get_call_error_text(Object* p_base, const StringName& p_method,const Variant** p_argptrs,int p_argcount,const Variant::CallError &ce) {
- if (i>0)
- str+=", ";
- str=str+=Variant( vec[i] ).get_construct_string();
- }
- return str+"])";
- } break;
- case INT_ARRAY: {
- DVector<int> vec = operator DVector<int>();
- String str="IntArray([";
- for(int i=0;i<vec.size();i++) {
+ String err_text;
- if (i>0)
- str+=", ";
- str=str+itos(vec[i]);
- }
- return str+"])";
- } break;
- case REAL_ARRAY: {
-
- DVector<real_t> vec = operator DVector<real_t>();
- String str="FloatArray([";
- for(int i=0;i<vec.size();i++) {
-
- if (i>0)
- str+=", ";
- str=str+rtos(vec[i]);
- }
- return str+"])";
- } break;
- case ARRAY: {
-
- Array arr = operator Array();
- String str="[";
- for (int i=0; i<arr.size(); i++) {
- if (i)
- str+=", ";
- str += arr[i].get_construct_string(p_obj_deconstruct,p_deconstruct_ud);
- };
- return str+"]";
-
- } break;
- case OBJECT: {
+ if (ce.error==Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) {
+ int errorarg=ce.argument;
+ err_text="Cannot convert argument "+itos(errorarg+1)+" from "+Variant::get_type_name(p_argptrs[errorarg]->get_type())+" to "+Variant::get_type_name(ce.expected)+".";
+ } else if (ce.error==Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {
+ err_text="Expected "+itos(ce.argument)+" arguments.";
+ } else if (ce.error==Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {
+ err_text="Expected "+itos(ce.argument)+" arguments.";
+ } else if (ce.error==Variant::CallError::CALL_ERROR_INVALID_METHOD) {
+ err_text="Method not found.";
+ } else if (ce.error==Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL) {
+ err_text="Instance is null";
+ } else if (ce.error==Variant::CallError::CALL_OK){
+ return "Call OK";
+ }
- if (_get_obj().obj) {
- if (p_obj_deconstruct) {
- return "Object(\""+p_obj_deconstruct(Variant(*this),p_deconstruct_ud).c_escape()+")";
- } else {
- return _get_obj().obj->get_type()+".new()";
- }
- } else
- return "null";
+ String class_name = p_base->get_type();
+ Ref<Script> script = p_base->get_script();
+ if (script.is_valid() && script->get_path().is_resource_file()) {
- } break;
- default: {
- return "["+get_type_name(type)+"]";
- }
+ class_name+="("+script->get_path().get_file()+")";
}
-
+ return "'"+class_name+"::"+String(p_method)+"': "+err_text;
}
diff --git a/core/variant.h b/core/variant.h
index 8fd9662c36..b58c781bdd 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -390,7 +390,10 @@ public:
Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,CallError &r_error);
Variant call(const StringName& p_method,const Variant& p_arg1=Variant(),const Variant& p_arg2=Variant(),const Variant& p_arg3=Variant(),const Variant& p_arg4=Variant(),const Variant& p_arg5=Variant());
- static Variant construct(const Variant::Type,const Variant** p_args,int p_argcount,CallError &r_error);
+
+ static String get_call_error_text(Object* p_base, const StringName& p_method,const Variant** p_argptrs,int p_argcount,const Variant::CallError &ce);
+
+ static Variant construct(const Variant::Type,const Variant** p_args,int p_argcount,CallError &r_error,bool p_strict=true);
void get_method_list(List<MethodInfo> *p_list) const;
bool has_method(const StringName& p_method) const;
@@ -411,6 +414,7 @@ public:
//argsVariant call()
bool operator==(const Variant& p_variant) const;
+ bool operator!=(const Variant& p_variant) const;
bool operator<(const Variant& p_variant) const;
uint32_t hash() const;
@@ -425,7 +429,7 @@ public:
typedef String (*ObjectDeConstruct)(const Variant& p_object,void *ud);
typedef void (*ObjectConstruct)(const String& p_text,void *ud,Variant& r_value);
- String get_construct_string(ObjectDeConstruct p_obj_deconstruct=NULL,void *p_deconstruct_ud=NULL) const;
+ String get_construct_string() const;
static void construct_from_string(const String& p_string,Variant& r_value,ObjectConstruct p_obj_construct=NULL,void *p_construct_ud=NULL);
void operator=(const Variant& p_variant); // only this is enough for all the other types
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 48c38f05f9..90f868c866 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -272,6 +272,9 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM0R(String,get_file);
VCALL_LOCALMEM0R(String,xml_escape);
VCALL_LOCALMEM0R(String,xml_unescape);
+ VCALL_LOCALMEM0R(String,c_escape);
+ VCALL_LOCALMEM0R(String,c_unescape);
+ VCALL_LOCALMEM0R(String,json_escape);
VCALL_LOCALMEM0R(String,percent_encode);
VCALL_LOCALMEM0R(String,percent_decode);
VCALL_LOCALMEM0R(String,is_valid_identifier);
@@ -450,6 +453,9 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM0(Array,clear);
VCALL_LOCALMEM0R(Array,hash);
VCALL_LOCALMEM1(Array,push_back);
+ VCALL_LOCALMEM1(Array,push_front);
+ VCALL_LOCALMEM0(Array,pop_back);
+ VCALL_LOCALMEM0(Array,pop_front);
VCALL_LOCALMEM1(Array,append);
VCALL_LOCALMEM1(Array,resize);
VCALL_LOCALMEM2(Array,insert);
@@ -858,6 +864,11 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
r_ret=Transform(p_args[0]->operator Matrix3(),p_args[1]->operator Vector3());
}
+ static void Image_init1(Variant& r_ret, const Variant** p_args) {
+
+ r_ret=Image(*p_args[0],*p_args[1],*p_args[2],Image::Format(p_args[3]->operator int()));
+ }
+
static void add_constructor(VariantConstructFunc p_func,const Variant::Type p_type,
const String& p_name1="", const Variant::Type p_type1=Variant::NIL,
const String& p_name2="", const Variant::Type p_type2=Variant::NIL,
@@ -959,7 +970,7 @@ Variant Variant::call(const StringName& p_method,const Variant** p_args,int p_ar
#define VCALL(m_type,m_method) _VariantCall::_call_##m_type##_##m_method
-Variant Variant::construct(const Variant::Type p_type,const Variant** p_args,int p_argcount,CallError &r_error) {
+Variant Variant::construct(const Variant::Type p_type, const Variant** p_args, int p_argcount, CallError &r_error, bool p_strict) {
r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
ERR_FAIL_INDEX_V(p_type,VARIANT_MAX,Variant());
@@ -1035,7 +1046,7 @@ Variant Variant::construct(const Variant::Type p_type,const Variant** p_args,int
} else if (p_argcount==1 && p_args[0]->type==p_type) {
return *p_args[0]; //copy construct
- } else if (p_argcount==1 && Variant::can_convert(p_args[0]->type,p_type)) {
+ } else if (p_argcount==1 && (!p_strict || Variant::can_convert(p_args[0]->type,p_type))) {
//near match construct
switch(p_type) {
@@ -1278,6 +1289,9 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC0(STRING,STRING,String,get_file,varray());
ADDFUNC0(STRING,STRING,String,xml_escape,varray());
ADDFUNC0(STRING,STRING,String,xml_unescape,varray());
+ ADDFUNC0(STRING,STRING,String,c_escape,varray());
+ ADDFUNC0(STRING,STRING,String,c_unescape,varray());
+ ADDFUNC0(STRING,STRING,String,json_escape,varray());
ADDFUNC0(STRING,STRING,String,percent_encode,varray());
ADDFUNC0(STRING,STRING,String,percent_decode,varray());
ADDFUNC0(STRING,BOOL,String,is_valid_identifier,varray());
@@ -1421,12 +1435,15 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC0(ARRAY,NIL,Array,clear,varray());
ADDFUNC0(ARRAY,INT,Array,hash,varray());
ADDFUNC1(ARRAY,NIL,Array,push_back,NIL,"value",varray());
+ ADDFUNC1(ARRAY,NIL,Array,push_front,NIL,"value",varray());
ADDFUNC1(ARRAY,NIL,Array,append,NIL,"value",varray());
ADDFUNC1(ARRAY,NIL,Array,resize,INT,"pos",varray());
ADDFUNC2(ARRAY,NIL,Array,insert,INT,"pos",NIL,"value",varray());
ADDFUNC1(ARRAY,NIL,Array,remove,INT,"pos",varray());
ADDFUNC1(ARRAY,NIL,Array,erase,NIL,"value",varray());
ADDFUNC1(ARRAY,INT,Array,find,NIL,"value",varray());
+ ADDFUNC0(ARRAY,NIL,Array,pop_back,varray());
+ ADDFUNC0(ARRAY,NIL,Array,pop_front,varray());
ADDFUNC0(ARRAY,NIL,Array,sort,varray());
ADDFUNC2(ARRAY,NIL,Array,sort_custom,OBJECT,"obj",STRING,"func",varray());
ADDFUNC0(ARRAY,NIL,Array,invert,varray());
@@ -1583,6 +1600,8 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
_VariantCall::add_constructor(_VariantCall::Transform_init1,Variant::TRANSFORM,"x_axis",Variant::VECTOR3,"y_axis",Variant::VECTOR3,"z_axis",Variant::VECTOR3,"origin",Variant::VECTOR3);
_VariantCall::add_constructor(_VariantCall::Transform_init2,Variant::TRANSFORM,"basis",Variant::MATRIX3,"origin",Variant::VECTOR3);
+ _VariantCall::add_constructor(_VariantCall::Image_init1,Variant::IMAGE,"width",Variant::INT,"height",Variant::INT,"mipmaps",Variant::BOOL,"format",Variant::INT);
+
/* REGISTER CONSTANTS */
_VariantCall::constant_data[Variant::VECTOR3].value["AXIS_X"]=Vector3::AXIS_X;
diff --git a/core/variant_call_bind.h b/core/variant_call_bind.h
index 613669203d..54954540b0 100644
--- a/core/variant_call_bind.h
+++ b/core/variant_call_bind.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 1bcfa7d2ae..204a00e1d5 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1003,7 +1003,7 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
return;
}
- *str = str->substr(0,idx-1)+chr+str->substr(idx+1,str->length());
+ *str = str->substr(0,idx)+chr+str->substr(idx+1,str->length());
valid=true;
return;
@@ -1352,6 +1352,22 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
valid=true;
v->set_hsv(v->get_h(),v->get_s(),p_value);
return;
+ } else if (*str=="r8" ) {
+ valid=true;
+ v->g=float(p_value)/255.0;
+ return;
+ } else if (*str=="g8" ) {
+ valid=true;
+ v->g=float(p_value)/255.0;
+ return;
+ } else if (*str=="b8" ) {
+ valid=true;
+ v->b=float(p_value)/255.0;
+ return;
+ } else if (*str=="a8" ) {\
+ valid=true;
+ v->a=float(p_value)/255.0;
+ return;
}
} else if (p_index.get_type()==Variant::INT) {
@@ -2195,6 +2211,18 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const {
} else if (*str=="v" ) {
valid=true;
return v->get_v();
+ } else if (*str=="r8") {
+ valid=true;
+ return v->r*255.0;
+ } else if (*str=="g8" ) {
+ valid=true;
+ return v->g*255.0;
+ } else if (*str=="b8" ) {
+ valid=true;
+ return v->b*255.0;
+ } else if (*str=="a8" ) {
+ valid=true;
+ return v->a*255.0;
}
} else if (p_index.get_type()==Variant::INT) {
@@ -2635,7 +2663,7 @@ bool Variant::in(const Variant& p_index, bool *r_valid) const {
if (l) {
for(int i=0;i<l;i++) {
- if ((*arr)[i]==p_index)
+ if (evaluate(OP_EQUAL,(*arr)[i],p_index))
return true;
}
@@ -2866,6 +2894,10 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back( PropertyInfo(Variant::REAL,"h"));
p_list->push_back( PropertyInfo(Variant::REAL,"s"));
p_list->push_back( PropertyInfo(Variant::REAL,"v"));
+ p_list->push_back( PropertyInfo(Variant::INT,"r8"));
+ p_list->push_back( PropertyInfo(Variant::INT,"g8"));
+ p_list->push_back( PropertyInfo(Variant::INT,"b8"));
+ p_list->push_back( PropertyInfo(Variant::INT,"a8"));
} break;
case IMAGE: { } break;
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index fed8c28740..3efa87de80 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -19,6 +19,20 @@ bool VariantParser::StreamFile::is_eof() const {
}
+CharType VariantParser::StreamString::get_char() {
+
+ if (pos>=s.length())
+ return 0;
+ else
+ return s[pos++];
+}
+
+bool VariantParser::StreamString::is_utf8() const {
+ return false;
+}
+bool VariantParser::StreamString::is_eof() const {
+ return pos>s.length();
+}
/////////////////////////////////////////////////////////////////////////////////////////////////
@@ -35,8 +49,10 @@ const char * VariantParser::tk_name[TK_MAX] = {
"identifier",
"string",
"number",
+ "color",
"':'",
"','",
+ "'.'",
"'='",
"EOF",
"ERROR"
@@ -106,16 +122,58 @@ Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, Stri
r_token.type=TK_COLON;
return OK;
};
+ case ';': {
+
+ while(true) {
+ CharType ch=p_stream->get_char();
+ if (p_stream->is_eof()) {
+ r_token.type=TK_EOF;
+ return OK;
+ }
+ if (ch=='\n')
+ break;
+ }
+
+ break;
+ };
case ',': {
r_token.type=TK_COMMA;
return OK;
};
+ case '.': {
+
+ r_token.type=TK_PERIOD;
+ return OK;
+ };
case '=': {
r_token.type=TK_EQUAL;
return OK;
};
+ case '#': {
+
+
+ String color_str="#";
+ while(true) {
+ CharType ch=p_stream->get_char();
+ if (p_stream->is_eof()) {
+ r_token.type=TK_EOF;
+ return OK;
+ } else if ( (ch>='0' && ch<='9') || (ch>='a' && ch<='f') || (ch>='A' && ch<='F') ) {
+ color_str+=String::chr(ch);
+
+ } else {
+ p_stream->saved=ch;
+ break;
+ }
+ }
+
+ r_token.value=Color::html(color_str);
+ r_token.type=TK_COLOR;
+ return OK;
+
+ };
case '"': {
@@ -336,6 +394,42 @@ Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, Stri
return ERR_PARSE_ERROR;
}
+Error VariantParser::_parse_enginecfg(Stream *p_stream, Vector<String>& strings, int &line, String &r_err_str) {
+
+ Token token;
+ get_token(p_stream,token,line,r_err_str);
+ if (token.type!=TK_PARENTHESIS_OPEN) {
+ r_err_str="Expected '(' in old-style engine.cfg construct";
+ return ERR_PARSE_ERROR;
+ }
+
+
+ String accum;
+
+ while(true) {
+
+ CharType c=p_stream->get_char();
+
+ if (p_stream->is_eof()) {
+ r_err_str="Unexpected EOF while parsing old-style engine.cfg construct";
+ return ERR_PARSE_ERROR;
+ }
+
+ if (c==',') {
+ strings.push_back(accum.strip_edges());
+ accum=String();
+ } else if (c==')') {
+ strings.push_back(accum.strip_edges());
+ return OK;
+ } else if (c=='\n') {
+ line++;
+ }
+
+ }
+
+ return OK;
+}
+
template<class T>
Error VariantParser::_parse_construct(Stream *p_stream,Vector<T>& r_construct,int &line,String &r_err_str) {
@@ -354,7 +448,7 @@ Error VariantParser::_parse_construct(Stream *p_stream,Vector<T>& r_construct,in
if (!first) {
get_token(p_stream,token,line,r_err_str);
if (token.type==TK_COMMA) {
- //do none
+ //do none
} else if (token.type==TK_PARENTHESIS_CLOSE) {
break;
} else {
@@ -364,7 +458,10 @@ Error VariantParser::_parse_construct(Stream *p_stream,Vector<T>& r_construct,in
}
}
get_token(p_stream,token,line,r_err_str);
- if (token.type!=TK_NUMBER) {
+
+ if (first && token.type==TK_PARENTHESIS_CLOSE) {
+ break;
+ } else if (token.type!=TK_NUMBER) {
r_err_str="Expected float in constructor";
return ERR_PARSE_ERROR;
}
@@ -460,6 +557,19 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
value=Vector2(args[0],args[1]);
return OK;
+ } else if (id=="Rect2"){
+
+ Vector<float> args;
+ Error err = _parse_construct<float>(p_stream,args,line,r_err_str);
+ if (err)
+ return err;
+
+ if (args.size()!=4) {
+ r_err_str="Expected 4 arguments for constructor";
+ }
+
+ value=Rect2(args[0],args[1],args[2],args[3]);
+ return OK;
} else if (id=="Vector3"){
Vector<float> args;
@@ -971,8 +1081,24 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
ie.joy_motion.axis = token.value;
get_token(p_stream,token,line,r_err_str);
+
+ if (token.type!=TK_COMMA) {
+ r_err_str="Expected ',' after axis index";
+ return ERR_PARSE_ERROR;
+ }
+
+ get_token(p_stream,token,line,r_err_str);
+ if (token.type!=TK_NUMBER) {
+ r_err_str="Expected axis sign";
+ return ERR_PARSE_ERROR;
+ }
+
+ ie.joy_motion.axis_value = token.value;
+
+ get_token(p_stream,token,line,r_err_str);
+
if (token.type!=TK_PARENTHESIS_CLOSE) {
- r_err_str="Expected ')'";
+ r_err_str="Expected ')' for jaxis";
return ERR_PARSE_ERROR;
}
@@ -1066,7 +1192,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
get_token(p_stream,token,line,r_err_str);
if (token.type==TK_COMMA) {
//do none
- } else if (token.type!=TK_PARENTHESIS_CLOSE) {
+ } else if (token.type==TK_PARENTHESIS_CLOSE) {
break;
} else {
r_err_str="Expected ',' or ')'";
@@ -1075,11 +1201,13 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
}
}
get_token(p_stream,token,line,r_err_str);
+
if (token.type!=TK_STRING) {
- r_err_str="Expected string";
+ r_err_str="Expected string";
return ERR_PARSE_ERROR;
}
+ first=false;
cs.push_back(token.value);
}
@@ -1161,6 +1289,112 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
value=arr;
return OK;
+ } else if (id=="key") { // compatibility with engine.cfg
+
+ Vector<String> params;
+ Error err = _parse_enginecfg(p_stream,params,line,r_err_str);
+ if (err)
+ return err;
+ ERR_FAIL_COND_V(params.size()!=1 && params.size()!=2,ERR_PARSE_ERROR);
+
+ int scode=0;
+
+ if (params[0].is_numeric()) {
+ scode=params[0].to_int();
+ if (scode < 10) {
+ scode=KEY_0+scode;
+ }
+ } else
+ scode=find_keycode(params[0]);
+
+ InputEvent ie;
+ ie.type=InputEvent::KEY;
+ ie.key.scancode=scode;
+
+ if (params.size()==2) {
+ String mods=params[1];
+ if (mods.findn("C")!=-1)
+ ie.key.mod.control=true;
+ if (mods.findn("A")!=-1)
+ ie.key.mod.alt=true;
+ if (mods.findn("S")!=-1)
+ ie.key.mod.shift=true;
+ if (mods.findn("M")!=-1)
+ ie.key.mod.meta=true;
+ }
+ value=ie;
+ return OK;
+
+ } else if (id=="mbutton") { // compatibility with engine.cfg
+
+ Vector<String> params;
+ Error err = _parse_enginecfg(p_stream,params,line,r_err_str);
+ if (err)
+ return err;
+ ERR_FAIL_COND_V(params.size()!=2,ERR_PARSE_ERROR);
+
+ InputEvent ie;
+ ie.type=InputEvent::MOUSE_BUTTON;
+ ie.device=params[0].to_int();
+ ie.mouse_button.button_index=params[1].to_int();
+
+ value=ie;
+ return OK;
+ } else if (id=="jbutton") { // compatibility with engine.cfg
+
+ Vector<String> params;
+ Error err = _parse_enginecfg(p_stream,params,line,r_err_str);
+ if (err)
+ return err;
+ ERR_FAIL_COND_V(params.size()!=2,ERR_PARSE_ERROR);
+ InputEvent ie;
+ ie.type=InputEvent::JOYSTICK_BUTTON;
+ ie.device=params[0].to_int();
+ ie.joy_button.button_index=params[1].to_int();
+
+ value=ie;
+
+ return OK;
+ } else if (id=="jaxis") { // compatibility with engine.cfg
+
+ Vector<String> params;
+ Error err = _parse_enginecfg(p_stream,params,line,r_err_str);
+ if (err)
+ return err;
+ ERR_FAIL_COND_V(params.size()!=2,ERR_PARSE_ERROR);
+
+ InputEvent ie;
+ ie.type=InputEvent::JOYSTICK_MOTION;
+ ie.device=params[0].to_int();
+ int axis=params[1].to_int();
+ ie.joy_motion.axis=axis>>1;
+ ie.joy_motion.axis_value=axis&1?1:-1;
+
+ value= ie;
+
+ return OK;
+ } else if (id=="img") { // compatibility with engine.cfg
+
+ Token token;
+ get_token(p_stream,token,line,r_err_str);
+ if (token.type!=TK_PARENTHESIS_OPEN) {
+ r_err_str="Expected '(' in old-style engine.cfg construct";
+ return ERR_PARSE_ERROR;
+ }
+
+ while(true) {
+ CharType c = p_stream->get_char();
+ if (p_stream->is_eof()) {
+ r_err_str="Unexpected EOF in old style engine.cfg img()";
+ return ERR_PARSE_ERROR;
+ }
+ if (c==')')
+ break;
+ }
+
+ value=Image();
+
+ return OK;
} else {
r_err_str="Unexpected identifier: '"+id+"'.";
@@ -1212,6 +1446,10 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
value=token.value;
return OK;
+ } else if (token.type==TK_COLOR) {
+
+ value=token.value;
+ return OK;
} else {
r_err_str="Expected value, got "+String(tk_name[token.type])+".";
return ERR_PARSE_ERROR;
@@ -1347,7 +1585,7 @@ Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int
}
-Error VariantParser::_parse_tag(Token& token, Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, ResourceParser *p_res_parser) {
+Error VariantParser::_parse_tag(Token& token, Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, ResourceParser *p_res_parser,bool p_simple_tag) {
r_tag.fields.clear();
@@ -1357,6 +1595,29 @@ Error VariantParser::_parse_tag(Token& token, Stream *p_stream, int &line, Strin
}
+ if (p_simple_tag) {
+
+ r_tag.name="";
+ r_tag.fields.clear();
+
+ while(true) {
+
+ CharType c = p_stream->get_char();
+ if (p_stream->is_eof()) {
+ r_err_str="Unexpected EOF while parsing simple tag";
+ return ERR_PARSE_ERROR;
+ }
+ if (c==']')
+ break;
+ r_tag.name+=String::chr(c);
+ }
+
+ r_tag.name = r_tag.name.strip_edges();
+
+ return OK;
+
+ }
+
get_token(p_stream,token,line,r_err_str);
@@ -1366,6 +1627,7 @@ Error VariantParser::_parse_tag(Token& token, Stream *p_stream, int &line, Strin
}
r_tag.name=token.value;
+ bool parsing_tag=true;
while(true) {
@@ -1378,6 +1640,16 @@ Error VariantParser::_parse_tag(Token& token, Stream *p_stream, int &line, Strin
if (token.type==TK_BRACKET_CLOSE)
break;
+ if (parsing_tag && token.type==TK_PERIOD) {
+ r_tag.name+="."; //support tags such as [someprop.Anroid] for specific platforms
+ get_token(p_stream,token,line,r_err_str);
+ } else if (parsing_tag && token.type==TK_COLON) {
+ r_tag.name+=":"; //support tags such as [someprop.Anroid] for specific platforms
+ get_token(p_stream,token,line,r_err_str);
+ } else {
+ parsing_tag=false;
+ }
+
if (token.type!=TK_IDENTIFIER) {
r_err_str="Expected Identifier";
return ERR_PARSE_ERROR;
@@ -1385,10 +1657,13 @@ Error VariantParser::_parse_tag(Token& token, Stream *p_stream, int &line, Strin
String id=token.value;
+ if (parsing_tag) {
+ r_tag.name+=id;
+ continue;
+ }
get_token(p_stream,token,line,r_err_str);
if (token.type!=TK_EQUAL) {
- r_err_str="Expected '='";
return ERR_PARSE_ERROR;
}
@@ -1407,7 +1682,7 @@ Error VariantParser::_parse_tag(Token& token, Stream *p_stream, int &line, Strin
}
-Error VariantParser::parse_tag(Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, ResourceParser *p_res_parser) {
+Error VariantParser::parse_tag(Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, ResourceParser *p_res_parser, bool p_simple_tag) {
Token token;
get_token(p_stream,token,line,r_err_str);
@@ -1421,14 +1696,15 @@ Error VariantParser::parse_tag(Stream *p_stream, int &line, String &r_err_str, T
return ERR_PARSE_ERROR;
}
- return _parse_tag(token,p_stream,line,r_err_str,r_tag,p_res_parser);
+ return _parse_tag(token,p_stream,line,r_err_str,r_tag,p_res_parser,p_simple_tag);
}
-Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, String &r_assign, Variant &r_value, ResourceParser *p_res_parser) {
+Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, String &r_assign, Variant &r_value, ResourceParser *p_res_parser, bool p_simple_tag) {
//assign..
+ r_assign="";
String what;
while(true) {
@@ -1446,11 +1722,23 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r
if (p_stream->is_eof())
return ERR_FILE_EOF;
+ if (c==';') { //comment
+ while(true) {
+ CharType ch=p_stream->get_char();
+ if (p_stream->is_eof()) {
+ return ERR_FILE_EOF;
+ }
+ if (ch=='\n')
+ break;
+ }
+ continue;
+ }
+
if (c=='[' && what.length()==0) {
//it's a tag!
p_stream->saved='['; //go back one
- Error err = parse_tag(p_stream,line,r_err_str,r_tag,p_res_parser);
+ Error err = parse_tag(p_stream,line,r_err_str,r_tag,p_res_parser,p_simple_tag);
return err;
}
@@ -1493,3 +1781,431 @@ Error VariantParser::parse(Stream *p_stream, Variant& r_ret, String &r_err_str,
}
+
+//////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+
+Error VariantWriter::write(const Variant& p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud,EncodeResourceFunc p_encode_res_func,void* p_encode_res_ud) {
+
+ switch( p_variant.get_type() ) {
+
+ case Variant::NIL: {
+ p_store_string_func(p_store_string_ud,"null");
+ } break;
+ case Variant::BOOL: {
+
+ p_store_string_func(p_store_string_ud,p_variant.operator bool() ? "true":"false" );
+ } break;
+ case Variant::INT: {
+
+ p_store_string_func(p_store_string_ud, itos(p_variant.operator int()) );
+ } break;
+ case Variant::REAL: {
+
+ String s = rtoss(p_variant.operator real_t());
+ if (s.find(".")==-1 && s.find("e")==-1)
+ s+=".0";
+ p_store_string_func(p_store_string_ud, s );
+ } break;
+ case Variant::STRING: {
+
+ String str=p_variant;
+
+ str="\""+str.c_escape()+"\"";
+ p_store_string_func(p_store_string_ud, str );
+ } break;
+ case Variant::VECTOR2: {
+
+ Vector2 v = p_variant;
+ p_store_string_func(p_store_string_ud,"Vector2( "+rtoss(v.x) +", "+rtoss(v.y)+" )" );
+ } break;
+ case Variant::RECT2: {
+
+ Rect2 aabb = p_variant;
+ p_store_string_func(p_store_string_ud,"Rect2( "+rtoss(aabb.pos.x) +", "+rtoss(aabb.pos.y) +", "+rtoss(aabb.size.x) +", "+rtoss(aabb.size.y)+" )" );
+
+ } break;
+ case Variant::VECTOR3: {
+
+ Vector3 v = p_variant;
+ p_store_string_func(p_store_string_ud,"Vector3( "+rtoss(v.x) +", "+rtoss(v.y)+", "+rtoss(v.z)+" )");
+ } break;
+ case Variant::PLANE: {
+
+ Plane p = p_variant;
+ p_store_string_func(p_store_string_ud,"Plane( "+rtoss(p.normal.x) +", "+rtoss(p.normal.y)+", "+rtoss(p.normal.z)+", "+rtoss(p.d)+" )" );
+
+ } break;
+ case Variant::_AABB: {
+
+ AABB aabb = p_variant;
+ p_store_string_func(p_store_string_ud,"AABB( "+rtoss(aabb.pos.x) +", "+rtoss(aabb.pos.y) +", "+rtoss(aabb.pos.z) +", "+rtoss(aabb.size.x) +", "+rtoss(aabb.size.y) +", "+rtoss(aabb.size.z)+" )" );
+
+ } break;
+ case Variant::QUAT: {
+
+ Quat quat = p_variant;
+ p_store_string_func(p_store_string_ud,"Quat( "+rtoss(quat.x)+", "+rtoss(quat.y)+", "+rtoss(quat.z)+", "+rtoss(quat.w)+" )");
+
+ } break;
+ case Variant::MATRIX32: {
+
+ String s="Matrix32( ";
+ Matrix32 m3 = p_variant;
+ for (int i=0;i<3;i++) {
+ for (int j=0;j<2;j++) {
+
+ if (i!=0 || j!=0)
+ s+=", ";
+ s+=rtoss( m3.elements[i][j] );
+ }
+ }
+
+ p_store_string_func(p_store_string_ud,s+" )");
+
+ } break;
+ case Variant::MATRIX3: {
+
+ String s="Matrix3( ";
+ Matrix3 m3 = p_variant;
+ for (int i=0;i<3;i++) {
+ for (int j=0;j<3;j++) {
+
+ if (i!=0 || j!=0)
+ s+=", ";
+ s+=rtoss( m3.elements[i][j] );
+ }
+ }
+
+ p_store_string_func(p_store_string_ud,s+" )");
+
+ } break;
+ case Variant::TRANSFORM: {
+
+ String s="Transform( ";
+ Transform t = p_variant;
+ Matrix3 &m3 = t.basis;
+ for (int i=0;i<3;i++) {
+ for (int j=0;j<3;j++) {
+
+ if (i!=0 || j!=0)
+ s+=", ";
+ s+=rtoss( m3.elements[i][j] );
+ }
+ }
+
+ s=s+", "+rtoss(t.origin.x) +", "+rtoss(t.origin.y)+", "+rtoss(t.origin.z);
+
+ p_store_string_func(p_store_string_ud,s+" )");
+ } break;
+
+ // misc types
+ case Variant::COLOR: {
+
+ Color c = p_variant;
+ p_store_string_func(p_store_string_ud,"Color( "+rtoss(c.r) +", "+rtoss(c.g)+", "+rtoss(c.b)+", "+rtoss(c.a)+" )");
+
+ } break;
+ case Variant::IMAGE: {
+
+
+ Image img=p_variant;
+
+ if (img.empty()) {
+ p_store_string_func(p_store_string_ud,"Image()");
+ break;
+ }
+
+ String imgstr="Image( ";
+ imgstr+=itos(img.get_width());
+ imgstr+=", "+itos(img.get_height());
+ imgstr+=", "+itos(img.get_mipmaps());
+ imgstr+=", ";
+
+ switch(img.get_format()) {
+
+ case Image::FORMAT_GRAYSCALE: imgstr+="GRAYSCALE"; break;
+ case Image::FORMAT_INTENSITY: imgstr+="INTENSITY"; break;
+ case Image::FORMAT_GRAYSCALE_ALPHA: imgstr+="GRAYSCALE_ALPHA"; break;
+ case Image::FORMAT_RGB: imgstr+="RGB"; break;
+ case Image::FORMAT_RGBA: imgstr+="RGBA"; break;
+ case Image::FORMAT_INDEXED : imgstr+="INDEXED"; break;
+ case Image::FORMAT_INDEXED_ALPHA: imgstr+="INDEXED_ALPHA"; break;
+ case Image::FORMAT_BC1: imgstr+="BC1"; break;
+ case Image::FORMAT_BC2: imgstr+="BC2"; break;
+ case Image::FORMAT_BC3: imgstr+="BC3"; break;
+ case Image::FORMAT_BC4: imgstr+="BC4"; break;
+ case Image::FORMAT_BC5: imgstr+="BC5"; break;
+ case Image::FORMAT_PVRTC2: imgstr+="PVRTC2"; break;
+ case Image::FORMAT_PVRTC2_ALPHA: imgstr+="PVRTC2_ALPHA"; break;
+ case Image::FORMAT_PVRTC4: imgstr+="PVRTC4"; break;
+ case Image::FORMAT_PVRTC4_ALPHA: imgstr+="PVRTC4_ALPHA"; break;
+ case Image::FORMAT_ETC: imgstr+="ETC"; break;
+ case Image::FORMAT_ATC: imgstr+="ATC"; break;
+ case Image::FORMAT_ATC_ALPHA_EXPLICIT: imgstr+="ATC_ALPHA_EXPLICIT"; break;
+ case Image::FORMAT_ATC_ALPHA_INTERPOLATED: imgstr+="ATC_ALPHA_INTERPOLATED"; break;
+ case Image::FORMAT_CUSTOM: imgstr+="CUSTOM"; break;
+ default: {}
+ }
+
+
+ String s;
+
+ DVector<uint8_t> data = img.get_data();
+ int len = data.size();
+ DVector<uint8_t>::Read r = data.read();
+ const uint8_t *ptr=r.ptr();;
+ for (int i=0;i<len;i++) {
+
+ if (i>0)
+ s+=", ";
+ s+=itos(ptr[i]);
+ }
+
+ imgstr+=", ";
+ p_store_string_func(p_store_string_ud,imgstr);
+ p_store_string_func(p_store_string_ud,s);
+ p_store_string_func(p_store_string_ud," )");
+ } break;
+ case Variant::NODE_PATH: {
+
+ String str=p_variant;
+
+ str="NodePath(\""+str.c_escape()+"\")";
+ p_store_string_func(p_store_string_ud,str);
+
+ } break;
+
+ case Variant::OBJECT: {
+
+ RES res = p_variant;
+ if (res.is_null()) {
+ p_store_string_func(p_store_string_ud,"null");
+ break; // don't save it
+ }
+
+ String res_text;
+
+ if (p_encode_res_func) {
+
+ res_text=p_encode_res_func(p_encode_res_ud,res);
+ }
+
+ if (res_text==String() && res->get_path().is_resource_file()) {
+
+ //external resource
+ String path=res->get_path();
+ res_text="Resource( \""+path+"\")";
+ }
+
+ if (res_text==String())
+ res_text="null";
+
+ p_store_string_func(p_store_string_ud,res_text);
+
+ } break;
+ case Variant::INPUT_EVENT: {
+
+ p_store_string_func(p_store_string_ud,"InputEvent()"); //will be added later
+ } break;
+ case Variant::DICTIONARY: {
+
+ Dictionary dict = p_variant;
+
+ List<Variant> keys;
+ dict.get_key_list(&keys);
+ keys.sort();
+
+ p_store_string_func(p_store_string_ud,"{ ");
+ for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
+
+ //if (!_check_type(dict[E->get()]))
+ // continue;
+ write(E->get(),p_store_string_func,p_store_string_ud,p_encode_res_func,p_encode_res_ud);
+ p_store_string_func(p_store_string_ud,":");
+ write(dict[E->get()],p_store_string_func,p_store_string_ud,p_encode_res_func,p_encode_res_ud);
+ if (E->next())
+ p_store_string_func(p_store_string_ud,", ");
+ }
+
+
+ p_store_string_func(p_store_string_ud," }");
+
+
+ } break;
+ case Variant::ARRAY: {
+
+ p_store_string_func(p_store_string_ud,"[ ");
+ Array array = p_variant;
+ int len=array.size();
+ for (int i=0;i<len;i++) {
+
+ if (i>0)
+ p_store_string_func(p_store_string_ud,", ");
+ write(array[i],p_store_string_func,p_store_string_ud,p_encode_res_func,p_encode_res_ud);
+
+ }
+ p_store_string_func(p_store_string_ud," ]");
+
+ } break;
+
+ case Variant::RAW_ARRAY: {
+
+ p_store_string_func(p_store_string_ud,"ByteArray( ");
+ String s;
+ DVector<uint8_t> data = p_variant;
+ int len = data.size();
+ DVector<uint8_t>::Read r = data.read();
+ const uint8_t *ptr=r.ptr();;
+ for (int i=0;i<len;i++) {
+
+ if (i>0)
+ p_store_string_func(p_store_string_ud,", ");
+
+ p_store_string_func(p_store_string_ud,itos(ptr[i]));
+
+ }
+
+ p_store_string_func(p_store_string_ud," )");
+
+ } break;
+ case Variant::INT_ARRAY: {
+
+ p_store_string_func(p_store_string_ud,"IntArray( ");
+ DVector<int> data = p_variant;
+ int len = data.size();
+ DVector<int>::Read r = data.read();
+ const int *ptr=r.ptr();;
+
+ for (int i=0;i<len;i++) {
+
+ if (i>0)
+ p_store_string_func(p_store_string_ud,", ");
+
+ p_store_string_func(p_store_string_ud,itos(ptr[i]));
+ }
+
+
+ p_store_string_func(p_store_string_ud," )");
+
+ } break;
+ case Variant::REAL_ARRAY: {
+
+ p_store_string_func(p_store_string_ud,"FloatArray( ");
+ DVector<real_t> data = p_variant;
+ int len = data.size();
+ DVector<real_t>::Read r = data.read();
+ const real_t *ptr=r.ptr();;
+
+ for (int i=0;i<len;i++) {
+
+ if (i>0)
+ p_store_string_func(p_store_string_ud,", ");
+ p_store_string_func(p_store_string_ud,rtoss(ptr[i]));
+ }
+
+ p_store_string_func(p_store_string_ud," )");
+
+ } break;
+ case Variant::STRING_ARRAY: {
+
+ p_store_string_func(p_store_string_ud,"StringArray( ");
+ DVector<String> data = p_variant;
+ int len = data.size();
+ DVector<String>::Read r = data.read();
+ const String *ptr=r.ptr();;
+ String s;
+ //write_string("\n");
+
+
+
+ for (int i=0;i<len;i++) {
+
+ if (i>0)
+ p_store_string_func(p_store_string_ud,", ");
+ String str=ptr[i];
+ p_store_string_func(p_store_string_ud,"\""+str.c_escape()+"\"");
+ }
+
+ p_store_string_func(p_store_string_ud," )");
+
+ } break;
+ case Variant::VECTOR2_ARRAY: {
+
+ p_store_string_func(p_store_string_ud,"Vector2Array( ");
+ DVector<Vector2> data = p_variant;
+ int len = data.size();
+ DVector<Vector2>::Read r = data.read();
+ const Vector2 *ptr=r.ptr();;
+
+ for (int i=0;i<len;i++) {
+
+ if (i>0)
+ p_store_string_func(p_store_string_ud,", ");
+ p_store_string_func(p_store_string_ud,rtoss(ptr[i].x)+", "+rtoss(ptr[i].y) );
+ }
+
+ p_store_string_func(p_store_string_ud," )");
+
+ } break;
+ case Variant::VECTOR3_ARRAY: {
+
+ p_store_string_func(p_store_string_ud,"Vector3Array( ");
+ DVector<Vector3> data = p_variant;
+ int len = data.size();
+ DVector<Vector3>::Read r = data.read();
+ const Vector3 *ptr=r.ptr();;
+
+ for (int i=0;i<len;i++) {
+
+ if (i>0)
+ p_store_string_func(p_store_string_ud,", ");
+ p_store_string_func(p_store_string_ud,rtoss(ptr[i].x)+", "+rtoss(ptr[i].y)+", "+rtoss(ptr[i].z) );
+ }
+
+ p_store_string_func(p_store_string_ud," )");
+
+ } break;
+ case Variant::COLOR_ARRAY: {
+
+ p_store_string_func(p_store_string_ud,"ColorArray( ");
+
+ DVector<Color> data = p_variant;
+ int len = data.size();
+ DVector<Color>::Read r = data.read();
+ const Color *ptr=r.ptr();;
+
+ for (int i=0;i<len;i++) {
+
+ if (i>0)
+ p_store_string_func(p_store_string_ud,", ");
+
+ p_store_string_func(p_store_string_ud,rtoss(ptr[i].r)+", "+rtoss(ptr[i].g)+", "+rtoss(ptr[i].b)+", "+rtoss(ptr[i].a) );
+
+ }
+ p_store_string_func(p_store_string_ud," )");
+
+ } break;
+ default: {}
+
+ }
+
+ return OK;
+}
+
+static Error _write_to_str(void *ud,const String& p_string) {
+
+ String *str=(String*)ud;
+ (*str)+=p_string;
+ return OK;
+}
+
+Error VariantWriter::write_to_string(const Variant& p_variant, String& r_string, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud) {
+
+ r_string=String();
+
+ return write(p_variant,_write_to_str,&r_string,p_encode_res_func,p_encode_res_ud);
+
+}
diff --git a/core/variant_parser.h b/core/variant_parser.h
index e1d25f7512..00f6910b29 100644
--- a/core/variant_parser.h
+++ b/core/variant_parser.h
@@ -32,6 +32,19 @@ public:
};
+ struct StreamString : public Stream {
+
+ String s;
+ int pos;
+
+ virtual CharType get_char();
+ virtual bool is_utf8() const;
+ virtual bool is_eof() const;
+
+ StreamString() { pos=0; }
+
+ };
+
typedef Error (*ParseResourceFunc)(void* p_self, Stream* p_stream,Ref<Resource>& r_res,int &line,String &r_err_str);
struct ResourceParser {
@@ -53,8 +66,10 @@ public:
TK_IDENTIFIER,
TK_STRING,
TK_NUMBER,
+ TK_COLOR,
TK_COLON,
TK_COMMA,
+ TK_PERIOD,
TK_EQUAL,
TK_EOF,
TK_ERROR,
@@ -86,18 +101,39 @@ private:
template<class T>
static Error _parse_construct(Stream *p_stream, Vector<T>& r_construct, int &line, String &r_err_str);
+ static Error _parse_enginecfg(Stream *p_stream, Vector<String>& strings, int &line, String &r_err_str);
static Error _parse_dictionary(Dictionary &object, Stream *p_stream, int &line, String &r_err_str,ResourceParser *p_res_parser=NULL);
static Error _parse_array(Array &array, Stream *p_stream, int &line, String &r_err_str,ResourceParser *p_res_parser=NULL);
- static Error _parse_tag(Token& token,Stream *p_stream, int &line, String &r_err_str,Tag& r_tag,ResourceParser *p_res_parser=NULL);
+ static Error _parse_tag(Token& token,Stream *p_stream, int &line, String &r_err_str,Tag& r_tag,ResourceParser *p_res_parser=NULL,bool p_simple_tag=false);
public:
- static Error parse_tag(Stream *p_stream, int &line, String &r_err_str,Tag& r_tag,ResourceParser *p_res_parser=NULL);
- static Error parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, String &r_assign, Variant &r_value,ResourceParser *p_res_parser=NULL);
+ static Error parse_tag(Stream *p_stream, int &line, String &r_err_str,Tag& r_tag,ResourceParser *p_res_parser=NULL,bool p_simple_tag=false);
+ static Error parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, String &r_assign, Variant &r_value,ResourceParser *p_res_parser=NULL,bool p_simple_tag=false);
static Error parse_value(Token& token,Variant &value, Stream *p_stream, int &line, String &r_err_str,ResourceParser *p_res_parser=NULL);
static Error get_token(Stream *p_stream,Token& r_token,int &line,String &r_err_str);
static Error parse(Stream *p_stream, Variant &r_ret, String &r_err_str, int &r_err_line,ResourceParser *p_res_parser=NULL);
};
+
+
+
+class VariantWriter {
+public:
+
+ typedef Error (*StoreStringFunc)(void *ud,const String& p_string);
+ typedef String (*EncodeResourceFunc)(void *ud,const RES& p_resource);
+
+ static Error write(const Variant& p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud,EncodeResourceFunc p_encode_res_func,void* p_encode_res_ud);
+ static Error write_to_string(const Variant& p_variant, String& r_string, EncodeResourceFunc p_encode_res_func=NULL,void* p_encode_res_ud=NULL);
+
+
+};
+
+
+
+
+
+
#endif // VARIANT_PARSER_H
diff --git a/core/vector.h b/core/vector.h
index d103400622..641721f401 100644
--- a/core/vector.h
+++ b/core/vector.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,7 +42,7 @@
template<class T>
class Vector {
- mutable void* _ptr;
+ mutable T* _ptr;
// internal helpers
@@ -51,21 +51,21 @@ class Vector {
if (!_ptr)
return NULL;
- return reinterpret_cast<SafeRefCount*>(_ptr);
+ return reinterpret_cast<SafeRefCount*>((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount));
}
_FORCE_INLINE_ int* _get_size() const {
if (!_ptr)
return NULL;
- return reinterpret_cast<int*>(((uint8_t*)(_ptr))+sizeof(SafeRefCount));
+ return reinterpret_cast<int*>((uint8_t*)_ptr-sizeof(int));
}
_FORCE_INLINE_ T* _get_data() const {
if (!_ptr)
return NULL;
- return reinterpret_cast<T*>(((uint8_t*)(_ptr))+sizeof(SafeRefCount)+sizeof(int));
+ return reinterpret_cast<T*>(_ptr);
}
@@ -88,11 +88,11 @@ public:
_FORCE_INLINE_ void clear() { resize(0); }
_FORCE_INLINE_ int size() const {
-
- if (!_ptr)
- return 0;
+ int* size = _get_size();
+ if (size)
+ return *size;
else
- return *reinterpret_cast<int*>(((uint8_t*)(_ptr))+sizeof(SafeRefCount));
+ return 0;
}
_FORCE_INLINE_ bool empty() const { return _ptr == 0; }
Error resize(int p_size);
@@ -174,7 +174,7 @@ void Vector<T>::_unref(void *p_data) {
if (!p_data)
return;
- SafeRefCount *src = reinterpret_cast<SafeRefCount*>(p_data);
+ SafeRefCount *src = reinterpret_cast<SafeRefCount*>((uint8_t*)p_data-sizeof(int)-sizeof(SafeRefCount));
if (!src->unref())
return; // still in use
@@ -189,7 +189,7 @@ void Vector<T>::_unref(void *p_data) {
}
// free mem
- memfree(p_data);
+ memfree((uint8_t*)p_data-sizeof(int)-sizeof(SafeRefCount));
}
@@ -201,7 +201,8 @@ void Vector<T>::_copy_on_write() {
if (_get_refcount()->get() > 1 ) {
/* in use by more than me */
- SafeRefCount *src_new=(SafeRefCount *)memalloc(_get_alloc_size(*_get_size()));
+ void* mem_new = memalloc(_get_alloc_size(*_get_size()));
+ SafeRefCount *src_new=(SafeRefCount *)mem_new;
src_new->init();
int * _size = (int*)(src_new+1);
*_size=*_get_size();
@@ -215,7 +216,7 @@ void Vector<T>::_copy_on_write() {
}
_unref(_ptr);
- _ptr=src_new;
+ _ptr=_data;
}
}
@@ -260,16 +261,17 @@ Error Vector<T>::resize(int p_size) {
if (size()==0) {
// alloc from scratch
- _ptr = (T*)memalloc(_get_alloc_size(p_size));
- ERR_FAIL_COND_V( !_ptr ,ERR_OUT_OF_MEMORY);
+ void* ptr=memalloc(_get_alloc_size(p_size));
+ ERR_FAIL_COND_V( !ptr ,ERR_OUT_OF_MEMORY);
+ _ptr=(T*)((uint8_t*)ptr+sizeof(int)+sizeof(SafeRefCount));
_get_refcount()->init(); // init refcount
*_get_size()=0; // init size (currently, none)
} else {
- void *_ptrnew = (T*)memrealloc(_ptr,_get_alloc_size(p_size));
+ void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount),_get_alloc_size(p_size));
ERR_FAIL_COND_V( !_ptrnew ,ERR_OUT_OF_MEMORY);
- _ptr=_ptrnew;
+ _ptr=(T*)((uint8_t*)_ptrnew+sizeof(int)+sizeof(SafeRefCount));
}
// construct the newly created elements
@@ -291,10 +293,10 @@ Error Vector<T>::resize(int p_size) {
t->~T();
}
- void *_ptrnew = (T*)memrealloc(_ptr,_get_alloc_size(p_size));
+ void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount),_get_alloc_size(p_size));
ERR_FAIL_COND_V( !_ptrnew ,ERR_OUT_OF_MEMORY);
- _ptr=_ptrnew;
+ _ptr=(T*)((uint8_t*)_ptrnew+sizeof(int)+sizeof(SafeRefCount));
*_get_size()=p_size;
diff --git a/core/vmap.cpp b/core/vmap.cpp
index 32481eb9eb..e94198257a 100644
--- a/core/vmap.cpp
+++ b/core/vmap.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/vmap.h b/core/vmap.h
index 5ff8f73978..6880abf260 100644
--- a/core/vmap.h
+++ b/core/vmap.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/vset.cpp b/core/vset.cpp
index c849bf3367..cefafeb073 100644
--- a/core/vset.cpp
+++ b/core/vset.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/vset.h b/core/vset.h
index e1e02ab435..cafcb0bb2f 100644
--- a/core/vset.h
+++ b/core/vset.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/demos/2d/area_input/input.gd b/demos/2d/area_input/input.gd
index 3f719fc853..e9cc9f3c1d 100644
--- a/demos/2d/area_input/input.gd
+++ b/demos/2d/area_input/input.gd
@@ -1,16 +1,15 @@
extends Area2D
-#virtual from CollisionObject2D (also available as signal)
+
+# 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 )
+ # 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("")
-
+# 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
index 1a2dcbc5f4..f3a19f64da 100644
--- a/demos/2d/area_input/input.scn
+++ b/demos/2d/area_input/input.scn
Binary files differ
diff --git a/demos/2d/dynamic_collision_shapes/ball.gd b/demos/2d/dynamic_collision_shapes/ball.gd
index c17b20f9c8..169079ea46 100644
--- a/demos/2d/dynamic_collision_shapes/ball.gd
+++ b/demos/2d/dynamic_collision_shapes/ball.gd
@@ -1,21 +1,17 @@
extends RigidBody2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
+# Member variables
+var timeout = 5
-var timeout=5
func _process(delta):
- timeout-=delta
- if (timeout<1):
+ timeout -= delta
+ if (timeout < 1):
set_opacity(timeout)
- if (timeout<0):
+ if (timeout < 0):
queue_free()
-func _ready():
- set_process(true)
- # Initialization here
- pass
+func _ready():
+ set_process(true)
diff --git a/demos/2d/dynamic_collision_shapes/ball.scn b/demos/2d/dynamic_collision_shapes/ball.scn
index e332de276d..51a91d5bc0 100644
--- a/demos/2d/dynamic_collision_shapes/ball.scn
+++ b/demos/2d/dynamic_collision_shapes/ball.scn
Binary files differ
diff --git a/demos/2d/dynamic_collision_shapes/dynamic_colobjs.gd b/demos/2d/dynamic_collision_shapes/dynamic_colobjs.gd
index a6a42a1914..25db51642b 100644
--- a/demos/2d/dynamic_collision_shapes/dynamic_colobjs.gd
+++ b/demos/2d/dynamic_collision_shapes/dynamic_colobjs.gd
@@ -1,23 +1,19 @@
extends Node2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
-const EMIT_INTERVAL=0.1
-var timeout=EMIT_INTERVAL
+# Member variables
+const EMIT_INTERVAL = 0.1
+var timeout = EMIT_INTERVAL
+
func _process(delta):
- timeout-=delta
- if (timeout<0):
- timeout=EMIT_INTERVAL
+ timeout -= delta
+ if (timeout < 0):
+ timeout = EMIT_INTERVAL
var ball = preload("res://ball.scn").instance()
- ball.set_pos( Vector2(randf() * get_viewport_rect().size.x, 0) )
+ ball.set_pos(Vector2(randf()*get_viewport_rect().size.x, 0))
add_child(ball)
-
-func _ready():
- set_process(true)
- # Initialization here
- pass
+func _ready():
+ set_process(true)
diff --git a/demos/2d/dynamic_collision_shapes/dynamic_colobjs.scn b/demos/2d/dynamic_collision_shapes/dynamic_colobjs.scn
index e6d1ebf9cf..6d17e2209f 100644
--- a/demos/2d/dynamic_collision_shapes/dynamic_colobjs.scn
+++ b/demos/2d/dynamic_collision_shapes/dynamic_colobjs.scn
Binary files differ
diff --git a/demos/2d/fog_of_war/fog.gd b/demos/2d/fog_of_war/fog.gd
index 9da5680e4d..3ac8df0e17 100644
--- a/demos/2d/fog_of_war/fog.gd
+++ b/demos/2d/fog_of_war/fog.gd
@@ -1,86 +1,78 @@
extends TileMap
-# member variables here, example:
-# var a=2
-# var b="textvar"
+# Member variables
-# 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
+# Boundaries 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
+var position # Player's position
-# iteration variables
+# Iteration variables
var x
var y
-# variable to check if player moved
+# Variables to check if the 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)
+# 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
+
+# Process that runs in realtime
func _fixed_process(delta):
position = get_node("../troll").get_pos()
- # calculate the corresponding tile
+ # Calculate the corresponding tile
# from the players position
x = int(position.x/get_cell_size().x)
- # switching from positive to negative tile positions
+ # Switching from positive to negative tile positions
# causes problems because of rounding problems
if position.x < 0:
- x -= 1 # correct negative values
+ x -= 1 # Correct negative values
y = int(position.y/get_cell_size().y)
- if position.y < 0:
+ 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
+
+ # 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)
+ 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
+
+ # 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)
+ 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)
+ # 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.scn b/demos/2d/fog_of_war/fog.scn
index 4987f1ead5..cf19601567 100644
--- a/demos/2d/fog_of_war/fog.scn
+++ b/demos/2d/fog_of_war/fog.scn
Binary files differ
diff --git a/demos/2d/fog_of_war/tile_edit.scn b/demos/2d/fog_of_war/tile_edit.scn
index aaca19d370..3eddf38e48 100644
--- a/demos/2d/fog_of_war/tile_edit.scn
+++ 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
index d118d3a2ba..6f40072e84 100644
--- a/demos/2d/fog_of_war/troll.gd
+++ b/demos/2d/fog_of_war/troll.gd
@@ -2,42 +2,37 @@
extends KinematicBody2D
# This is a simple collision demo showing how
-# the kinematic cotroller works.
+# the kinematic controller works.
# move() will allow to move the node, and will
-# always move it to a non-colliding spot,
+# always move it to a non-colliding spot,
# as long as it starts from a non-colliding spot too.
+# Member variables
+const MOTION_SPEED = 160 # Pixels/second
-#pixels / second
-const MOTION_SPEED=160
func _fixed_process(delta):
-
var motion = Vector2()
if (Input.is_action_pressed("move_up")):
- motion+=Vector2(0,-1)
+ motion += Vector2(0, -1)
if (Input.is_action_pressed("move_bottom")):
- motion+=Vector2(0,1)
+ motion += Vector2(0, 1)
if (Input.is_action_pressed("move_left")):
- motion+=Vector2(-1,0)
+ motion += Vector2(-1, 0)
if (Input.is_action_pressed("move_right")):
- motion+=Vector2(1,0)
+ motion += Vector2(1, 0)
- motion = motion.normalized() * MOTION_SPEED * delta
+ motion = motion.normalized()*MOTION_SPEED*delta
motion = move(motion)
- #make character slide nicely through the world
+ # Make character slide nicely through the world
var slide_attempts = 4
- while(is_colliding() and slide_attempts>0):
+ while(is_colliding() and slide_attempts > 0):
motion = get_collision_normal().slide(motion)
- motion=move(motion)
- slide_attempts-=1
-
+ motion = move(motion)
+ slide_attempts -= 1
+
func _ready():
- # Initalization here
set_fixed_process(true)
- pass
-
-
diff --git a/demos/2d/fog_of_war/troll.scn b/demos/2d/fog_of_war/troll.scn
index f5d87c3631..ab9af17221 100644
--- a/demos/2d/fog_of_war/troll.scn
+++ 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
index 9dffbc4662..fcc878e565 100644
--- a/demos/2d/hdr/beach_cave.gd
+++ b/demos/2d/hdr/beach_cave.gd
@@ -1,26 +1,21 @@
extends Node2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
-const CAVE_LIMIT=1000
+# Member variables
+const CAVE_LIMIT = 1000
-func _input(ev):
- if (ev.type==InputEvent.MOUSE_MOTION and ev.button_mask&1):
- var rel_x = ev.relative_x
+
+func _input(event):
+ if (event.type == InputEvent.MOUSE_MOTION and event.button_mask&1):
+ var rel_x = event.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
+ 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
index 4147a130ad..6a4108e7a5 100644
--- a/demos/2d/hdr/beach_cave.scn
+++ b/demos/2d/hdr/beach_cave.scn
Binary files differ
diff --git a/demos/2d/hexamap/map.scn b/demos/2d/hexamap/map.scn
index 5798aab850..de49527003 100644
--- a/demos/2d/hexamap/map.scn
+++ b/demos/2d/hexamap/map.scn
Binary files differ
diff --git a/demos/2d/hexamap/tiles.scn b/demos/2d/hexamap/tiles.scn
index 265aedac2b..a019bbb92d 100644
--- a/demos/2d/hexamap/tiles.scn
+++ b/demos/2d/hexamap/tiles.scn
Binary files differ
diff --git a/demos/2d/hexamap/troll.gd b/demos/2d/hexamap/troll.gd
index d118d3a2ba..82938fdf10 100644
--- a/demos/2d/hexamap/troll.gd
+++ b/demos/2d/hexamap/troll.gd
@@ -2,42 +2,37 @@
extends KinematicBody2D
# This is a simple collision demo showing how
-# the kinematic cotroller works.
+# the kinematic controller 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.
+# Member variables
+const MOTION_SPEED = 160 # Pixels/second
-#pixels / second
-const MOTION_SPEED=160
func _fixed_process(delta):
-
var motion = Vector2()
if (Input.is_action_pressed("move_up")):
- motion+=Vector2(0,-1)
+ motion += Vector2(0, -1)
if (Input.is_action_pressed("move_bottom")):
- motion+=Vector2(0,1)
+ motion += Vector2(0, 1)
if (Input.is_action_pressed("move_left")):
- motion+=Vector2(-1,0)
+ motion += Vector2(-1, 0)
if (Input.is_action_pressed("move_right")):
- motion+=Vector2(1,0)
+ motion += Vector2(1, 0)
- motion = motion.normalized() * MOTION_SPEED * delta
+ motion = motion.normalized()*MOTION_SPEED*delta
motion = move(motion)
- #make character slide nicely through the world
+ # Make character slide nicely through the world
var slide_attempts = 4
- while(is_colliding() and slide_attempts>0):
+ while(is_colliding() and slide_attempts > 0):
motion = get_collision_normal().slide(motion)
- motion=move(motion)
- slide_attempts-=1
-
+ motion = move(motion)
+ slide_attempts -= 1
+
func _ready():
- # Initalization here
set_fixed_process(true)
- pass
-
-
diff --git a/demos/2d/hexamap/troll.scn b/demos/2d/hexamap/troll.scn
index f5d87c3631..1f33dabf8e 100644
--- a/demos/2d/hexamap/troll.scn
+++ b/demos/2d/hexamap/troll.scn
Binary files differ
diff --git a/demos/2d/isometric/dungeon.scn b/demos/2d/isometric/dungeon.scn
index e03a3bd3dd..8f0f316d73 100644
--- a/demos/2d/isometric/dungeon.scn
+++ b/demos/2d/isometric/dungeon.scn
Binary files differ
diff --git a/demos/2d/isometric/tileset.scn b/demos/2d/isometric/tileset.scn
index c04ea5382c..e487285f83 100644
--- a/demos/2d/isometric/tileset.scn
+++ b/demos/2d/isometric/tileset.scn
Binary files differ
diff --git a/demos/2d/isometric/troll.gd b/demos/2d/isometric/troll.gd
index d118d3a2ba..d8d4880df1 100644
--- a/demos/2d/isometric/troll.gd
+++ b/demos/2d/isometric/troll.gd
@@ -2,42 +2,37 @@
extends KinematicBody2D
# This is a simple collision demo showing how
-# the kinematic cotroller works.
+# the kinematic controller 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.
+# Member variables
+const MOTION_SPEED = 160 # Pixels/seconds
-#pixels / second
-const MOTION_SPEED=160
func _fixed_process(delta):
-
var motion = Vector2()
if (Input.is_action_pressed("move_up")):
- motion+=Vector2(0,-1)
+ motion += Vector2(0, -1)
if (Input.is_action_pressed("move_bottom")):
- motion+=Vector2(0,1)
+ motion += Vector2(0, 1)
if (Input.is_action_pressed("move_left")):
- motion+=Vector2(-1,0)
+ motion += Vector2(-1, 0)
if (Input.is_action_pressed("move_right")):
- motion+=Vector2(1,0)
+ motion += Vector2(1, 0)
- motion = motion.normalized() * MOTION_SPEED * delta
+ motion = motion.normalized()*MOTION_SPEED*delta
motion = move(motion)
- #make character slide nicely through the world
+ # Make character slide nicely through the world
var slide_attempts = 4
- while(is_colliding() and slide_attempts>0):
+ while(is_colliding() and slide_attempts > 0):
motion = get_collision_normal().slide(motion)
- motion=move(motion)
- slide_attempts-=1
-
+ motion = move(motion)
+ slide_attempts -= 1
+
func _ready():
- # Initalization here
set_fixed_process(true)
- pass
-
-
diff --git a/demos/2d/isometric/troll.scn b/demos/2d/isometric/troll.scn
index 19b566fe05..d53aac4fbf 100644
--- a/demos/2d/isometric/troll.scn
+++ b/demos/2d/isometric/troll.scn
Binary files differ
diff --git a/demos/2d/isometric_light/column.scn b/demos/2d/isometric_light/column.scn
index f0b7683885..03f3c2c976 100644
--- a/demos/2d/isometric_light/column.scn
+++ 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
index 30c766936c..508cd3728c 100644
--- a/demos/2d/isometric_light/cubio.gd
+++ b/demos/2d/isometric_light/cubio.gd
@@ -1,96 +1,85 @@
extends KinematicBody2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
+# Member variables
const MAX_SPEED = 300.0
const IDLE_SPEED = 10.0
-const ACCEL=5.0
-const VSCALE=0.5
-const SHOOT_INTERVAL=0.3
+const ACCEL = 5.0
+const VSCALE = 0.5
+const SHOOT_INTERVAL = 0.3
+
+var speed = Vector2()
+var current_anim = ""
+var current_mirror = false
-var speed=Vector2()
-var current_anim=""
-var current_mirror=false
+var shoot_countdown = 0
-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()
+func _input(event):
+ if (event.type == InputEvent.MOUSE_BUTTON and event.button_index == 1 and event.pressed and shoot_countdown <= 0):
+ var pos = get_canvas_transform().affine_inverse()*event.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 )
+ bullet.advance_dir = dir
+ bullet.set_pos(get_global_pos() + dir*60)
get_parent().add_child(bullet)
- shoot_countdown=SHOOT_INTERVAL
-
-
-
+ shoot_countdown = SHOOT_INTERVAL
+
func _fixed_process(delta):
-
- shoot_countdown-=delta
+ shoot_countdown -= delta
var dir = Vector2()
if (Input.is_action_pressed("up")):
- dir+=Vector2(0,-1)
+ dir += Vector2(0, -1)
if (Input.is_action_pressed("down")):
- dir+=Vector2(0,1)
+ dir += Vector2(0, 1)
if (Input.is_action_pressed("left")):
- dir+=Vector2(-1,0)
+ 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)
+ 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)
+ motion = n.slide(motion)
move(motion)
- var next_anim=""
- var next_mirror=false
+ 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)
+ 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"
+ 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):
+ 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
-
+ 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
index fc931b0c8d..55e2185247 100644
--- a/demos/2d/isometric_light/cubio.scn
+++ b/demos/2d/isometric_light/cubio.scn
Binary files differ
diff --git a/demos/2d/isometric_light/map.gd b/demos/2d/isometric_light/map.gd
index f712aeeaec..6b790ddf1c 100644
--- a/demos/2d/isometric_light/map.gd
+++ b/demos/2d/isometric_light/map.gd
@@ -1,18 +1,7 @@
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"):
+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
index 89002f991f..da3fc5654f 100644
--- a/demos/2d/isometric_light/map.scn
+++ b/demos/2d/isometric_light/map.scn
Binary files differ
diff --git a/demos/2d/isometric_light/shoot.gd b/demos/2d/isometric_light/shoot.gd
index 0486bbb658..b48d4ad34b 100644
--- a/demos/2d/isometric_light/shoot.gd
+++ b/demos/2d/isometric_light/shoot.gd
@@ -1,27 +1,21 @@
extends KinematicBody2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-var advance_dir=Vector2(1,0)
+# Member variables
const ADVANCE_SPEED = 500.0
-var hit=false
+var advance_dir = Vector2(1, 0)
+var hit = false
+
func _fixed_process(delta):
-
if (hit):
return
- move(advance_dir*delta*ADVANCE_SPEED)
+ move(advance_dir*delta*ADVANCE_SPEED)
if (is_colliding()):
get_node("anim").play("explode")
- hit=true
+ 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
index 672608810f..6909ae0c71 100644
--- a/demos/2d/isometric_light/shoot.scn
+++ b/demos/2d/isometric_light/shoot.scn
Binary files differ
diff --git a/demos/2d/isometric_light/tileset_scene.scn b/demos/2d/isometric_light/tileset_scene.scn
index 3d0773c9c5..4841cc18a7 100644
--- a/demos/2d/isometric_light/tileset_scene.scn
+++ 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
index 3f08b33311..9d6a8e2eae 100644
--- a/demos/2d/isometric_light/torch.scn
+++ b/demos/2d/isometric_light/torch.scn
Binary files differ
diff --git a/demos/2d/kinematic_char/colworld.gd b/demos/2d/kinematic_char/colworld.gd
index fe2dc30bb6..7926ef9d54 100644
--- a/demos/2d/kinematic_char/colworld.gd
+++ b/demos/2d/kinematic_char/colworld.gd
@@ -1,18 +1,8 @@
extends Node2D
-#member variables here, example:
-#var a=2
-#var b="textvar"
-func _ready():
- #Initalization here
- pass
-
-
-
-
-func _on_princess_body_enter( body ):
- #the name of this editor-generated callback is unfortunate
- if (body.get_name()=="player"):
+func _on_princess_body_enter(body):
+ # The name of this editor-generated callback is unfortunate
+ if (body.get_name() == "player"):
get_node("youwin").show()
diff --git a/demos/2d/kinematic_char/colworld.scn b/demos/2d/kinematic_char/colworld.scn
index e66705368d..ff10826563 100644
--- a/demos/2d/kinematic_char/colworld.scn
+++ b/demos/2d/kinematic_char/colworld.scn
Binary files differ
diff --git a/demos/2d/kinematic_char/engine.cfg b/demos/2d/kinematic_char/engine.cfg
index 4ce8f836ae..8bdd5e2fc5 100644
--- a/demos/2d/kinematic_char/engine.cfg
+++ b/demos/2d/kinematic_char/engine.cfg
@@ -1,6 +1,6 @@
[application]
-name="Kinematic Collision"
+name="Kinematic Character"
main_scene="res://colworld.scn"
icon="res://icon.png"
diff --git a/demos/2d/kinematic_char/player.gd b/demos/2d/kinematic_char/player.gd
index 329382408b..2890cc2ce3 100644
--- a/demos/2d/kinematic_char/player.gd
+++ b/demos/2d/kinematic_char/player.gd
@@ -1,137 +1,123 @@
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.
+# This is a simple collision demo showing how
+# the kinematic controller 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.
+# Member variables
+const GRAVITY = 500.0 # Pixels/second
-#pixels / second
-const GRAVITY = 500.0
-
-#Angle in degrees towards either side that the player can
-#consider "floor".
+# Angle in degrees towards either side that the player can consider "floor"
const FLOOR_ANGLE_TOLERANCE = 40
const WALK_FORCE = 600
-const WALK_MIN_SPEED=10
+const WALK_MIN_SPEED = 10
const WALK_MAX_SPEED = 200
const STOP_FORCE = 1300
const JUMP_SPEED = 200
-const JUMP_MAX_AIRBORNE_TIME=0.2
+const JUMP_MAX_AIRBORNE_TIME = 0.2
-const SLIDE_STOP_VELOCITY=1.0 #one pixel per second
-const SLIDE_STOP_MIN_TRAVEL=1.0 #one pixel
+const SLIDE_STOP_VELOCITY = 1.0 # One pixel per second
+const SLIDE_STOP_MIN_TRAVEL = 1.0 # One pixel
var velocity = Vector2()
-var on_air_time=100
-var jumping=false
+var on_air_time = 100
+var jumping = false
-var prev_jump_pressed=false
+var prev_jump_pressed = false
-func _fixed_process(delta):
- #create forces
- var force = Vector2(0,GRAVITY)
+func _fixed_process(delta):
+ # Create forces
+ var force = Vector2(0, GRAVITY)
var walk_left = Input.is_action_pressed("move_left")
var walk_right = Input.is_action_pressed("move_right")
var jump = Input.is_action_pressed("jump")
-
- var stop=true
+
+ var stop = true
if (walk_left):
- if (velocity.x<=WALK_MIN_SPEED and velocity.x > -WALK_MAX_SPEED):
- force.x-=WALK_FORCE
- stop=false
-
+ if (velocity.x <= WALK_MIN_SPEED and velocity.x > -WALK_MAX_SPEED):
+ force.x -= WALK_FORCE
+ stop = false
elif (walk_right):
- if (velocity.x>=-WALK_MIN_SPEED and velocity.x < WALK_MAX_SPEED):
- force.x+=WALK_FORCE
- stop=false
+ if (velocity.x >= -WALK_MIN_SPEED and velocity.x < WALK_MAX_SPEED):
+ force.x += WALK_FORCE
+ stop = false
if (stop):
var vsign = sign(velocity.x)
var vlen = abs(velocity.x)
- vlen -= STOP_FORCE * delta
- if (vlen<0):
- vlen=0
-
- velocity.x=vlen*vsign
+ vlen -= STOP_FORCE*delta
+ if (vlen < 0):
+ vlen = 0
-
-
- #integrate forces to velocity
- velocity += force * delta
+ velocity.x = vlen*vsign
- #integrate velocity into motion and move
- var motion = velocity * delta
-
- #move and consume motion
+ # Integrate forces to velocity
+ velocity += force*delta
+
+ # Integrate velocity into motion and move
+ var motion = velocity*delta
+
+ # Move and consume motion
motion = move(motion)
-
-
- var floor_velocity=Vector2()
-
+
+ var floor_velocity = Vector2()
+
if (is_colliding()):
- # you can check which tile was collision against with this
+ # You can check which tile was collision against with this
# print(get_collider_metadata())
-
- #ran against something, is it the floor? get normal
+
+ # Ran against something, is it the floor? Get normal
var n = get_collision_normal()
-
- if ( rad2deg(acos(n.dot( Vector2(0,-1)))) < FLOOR_ANGLE_TOLERANCE ):
- #if angle to the "up" vectors is < angle tolerance
- #char is on floor
- on_air_time=0
- floor_velocity=get_collider_velocity()
-
-
- if (on_air_time==0 and force.x==0 and get_travel().length() < SLIDE_STOP_MIN_TRAVEL and abs(velocity.x) < SLIDE_STOP_VELOCITY and get_collider_velocity()==Vector2()):
- #Since this formula will always slide the character around,
- #a special case must be considered to to stop it from moving
- #if standing on an inclined floor. Conditions are:
- # 1) Standing on floor (on_air_time==0)
+
+ if (rad2deg(acos(n.dot(Vector2(0, -1)))) < FLOOR_ANGLE_TOLERANCE):
+ # If angle to the "up" vectors is < angle tolerance
+ # char is on floor
+ on_air_time = 0
+ floor_velocity = get_collider_velocity()
+
+ if (on_air_time == 0 and force.x == 0 and get_travel().length() < SLIDE_STOP_MIN_TRAVEL and abs(velocity.x) < SLIDE_STOP_VELOCITY and get_collider_velocity() == Vector2()):
+ # Since this formula will always slide the character around,
+ # a special case must be considered to to stop it from moving
+ # if standing on an inclined floor. Conditions are:
+ # 1) Standing on floor (on_air_time == 0)
# 2) Did not move more than one pixel (get_travel().length() < SLIDE_STOP_MIN_TRAVEL)
# 3) Not moving horizontally (abs(velocity.x) < SLIDE_STOP_VELOCITY)
# 4) Collider is not moving
-
+
revert_motion()
- velocity.y=0.0
-
+ velocity.y = 0.0
else:
- #For every other case of motion,our motion was interrupted.
- #Try to complete the motion by "sliding"
- #by the normal
-
+ # For every other case of motion, our motion was interrupted.
+ # Try to complete the motion by "sliding" by the normal
motion = n.slide(motion)
- velocity = n.slide(velocity)
- #then move again
+ velocity = n.slide(velocity)
+ # Then move again
move(motion)
-
- if (floor_velocity!=Vector2()):
- #if floor moves, move with floor
+
+ if (floor_velocity != Vector2()):
+ # If floor moves, move with floor
move(floor_velocity*delta)
-
- if (jumping and velocity.y>0):
- #if falling, no longer jumping
- jumping=false
-
- if (on_air_time<JUMP_MAX_AIRBORNE_TIME and jump and not prev_jump_pressed and not jumping):
- # Jump must also be allowed to happen if the
- # character left the floor a little bit ago.
+
+ if (jumping and velocity.y > 0):
+ # If falling, no longer jumping
+ jumping = false
+
+ if (on_air_time < JUMP_MAX_AIRBORNE_TIME and jump and not prev_jump_pressed and not jumping):
+ # Jump must also be allowed to happen if the character left the floor a little bit ago.
# Makes controls more snappy.
- velocity.y=-JUMP_SPEED
- jumping=true
-
- on_air_time+=delta
- prev_jump_pressed=jump
+ velocity.y = -JUMP_SPEED
+ jumping = true
+
+ on_air_time += delta
+ prev_jump_pressed = jump
+
func _ready():
- #Initalization here
set_fixed_process(true)
- pass
-
-
diff --git a/demos/2d/kinematic_char/player.scn b/demos/2d/kinematic_char/player.scn
index 5809c0e98a..5ee86ce85d 100644
--- a/demos/2d/kinematic_char/player.scn
+++ b/demos/2d/kinematic_char/player.scn
Binary files differ
diff --git a/demos/2d/kinematic_col/colworld.scn b/demos/2d/kinematic_col/colworld.scn
index 064ff12075..06607b7efd 100644
--- a/demos/2d/kinematic_col/colworld.scn
+++ b/demos/2d/kinematic_col/colworld.scn
Binary files differ
diff --git a/demos/2d/kinematic_col/player.gd b/demos/2d/kinematic_col/player.gd
index 36784a9d9f..ce09e1509e 100644
--- a/demos/2d/kinematic_col/player.gd
+++ b/demos/2d/kinematic_col/player.gd
@@ -2,35 +2,30 @@
extends KinematicBody2D
# This is a simple collision demo showing how
-# the kinematic cotroller works.
+# the kinematic controller 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.
+# Member variables
+const MOTION_SPEED = 160 # Pixels/second
-#pixels / second
-const MOTION_SPEED=160
func _fixed_process(delta):
-
var motion = Vector2()
if (Input.is_action_pressed("move_up")):
- motion+=Vector2(0,-1)
+ motion += Vector2(0, -1)
if (Input.is_action_pressed("move_bottom")):
- motion+=Vector2(0,1)
+ motion += Vector2(0, 1)
if (Input.is_action_pressed("move_left")):
- motion+=Vector2(-1,0)
+ motion += Vector2(-1, 0)
if (Input.is_action_pressed("move_right")):
- motion+=Vector2(1,0)
+ motion += Vector2(1, 0)
- motion = motion.normalized() * MOTION_SPEED * delta
+ motion = motion.normalized()*MOTION_SPEED*delta
move(motion)
-
+
func _ready():
- # Initalization here
set_fixed_process(true)
- pass
-
-
diff --git a/demos/2d/kinematic_col/player.scn b/demos/2d/kinematic_col/player.scn
index e558bffe8e..28ad204472 100644
--- a/demos/2d/kinematic_col/player.scn
+++ b/demos/2d/kinematic_col/player.scn
Binary files differ
diff --git a/demos/2d/light_mask/lightmask.scn b/demos/2d/light_mask/lightmask.scn
index 08805f44c6..fcf56b5b84 100644
--- a/demos/2d/light_mask/lightmask.scn
+++ b/demos/2d/light_mask/lightmask.scn
Binary files differ
diff --git a/demos/2d/lights_shadows/light_shadows.scn b/demos/2d/lights_shadows/light_shadows.scn
index 152f68a407..24ccd1e0be 100644
--- a/demos/2d/lights_shadows/light_shadows.scn
+++ b/demos/2d/lights_shadows/light_shadows.scn
Binary files differ
diff --git a/demos/2d/lookat/lookat.gd b/demos/2d/lookat/lookat.gd
index 742c5b0671..c45c3ad622 100644
--- a/demos/2d/lookat/lookat.gd
+++ b/demos/2d/lookat/lookat.gd
@@ -1,43 +1,33 @@
extends Sprite
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-const MODE_DIRECT=0
-const MODE_CONSTANT=1
-const MODE_SMOOTH=2
+# Member variables
+const MODE_DIRECT = 0
+const MODE_CONSTANT = 1
+const MODE_SMOOTH = 2
const ROTATION_SPEED = 1
const SMOOTH_SPEED = 2.0
-export(int,"Direct","Constant","Smooth") var mode=MODE_DIRECT
+export(int, "Direct", "Constant", "Smooth") var mode = MODE_DIRECT
+
func _process(delta):
var mpos = get_viewport().get_mouse_pos()
- if (mode==MODE_DIRECT):
-
+ if (mode == MODE_DIRECT):
look_at(mpos)
-
- elif (mode==MODE_CONSTANT):
-
+ elif (mode == MODE_CONSTANT):
var ang = get_angle_to(mpos)
var s = sign(ang)
- ang=abs(ang)
-
- rotate( min(ang,ROTATION_SPEED*delta)*s )
+ ang = abs(ang)
- elif (mode==MODE_SMOOTH):
-
- var ang = get_angle_to(mpos)
+ rotate(min(ang, ROTATION_SPEED*delta)*s)
+ elif (mode == MODE_SMOOTH):
+ var ang = get_angle_to(mpos)
- rotate( ang*delta*SMOOTH_SPEED )
+ rotate(ang*delta*SMOOTH_SPEED)
+
func _ready():
- # Initialization here
set_process(true)
- pass
-
-
diff --git a/demos/2d/lookat/lookat.scn b/demos/2d/lookat/lookat.scn
index 880070b4c7..66be060c06 100644
--- a/demos/2d/lookat/lookat.scn
+++ b/demos/2d/lookat/lookat.scn
Binary files differ
diff --git a/demos/2d/motion/motion.gd b/demos/2d/motion/motion.gd
index 8f8f56a889..f9bbd6f90d 100644
--- a/demos/2d/motion/motion.gd
+++ b/demos/2d/motion/motion.gd
@@ -1,38 +1,33 @@
extends Sprite
-
-export var use_idle=true
-
-# member variables here, example:
-# var a=2
-# var b="textvar"
+# Member variables
const BEGIN = -113
const END = 907
-const TIME = 5.0 # seconds
-const SPEED = (END-BEGIN)/TIME
+const TIME = 5.0 # Seconds
+const SPEED = (END - BEGIN)/TIME
+
+export var use_idle = true
+
func _process(delta):
var ofs = get_pos()
- ofs.x+=delta*SPEED
- if (ofs.x>END):
- ofs.x=BEGIN
+ ofs.x += delta*SPEED
+ if (ofs.x > END):
+ ofs.x = BEGIN
set_pos(ofs)
-
+
+
func _fixed_process(delta):
var ofs = get_pos()
- ofs.x+=delta*SPEED
- if (ofs.x>END):
- ofs.x=BEGIN
+ ofs.x += delta*SPEED
+ if (ofs.x > END):
+ ofs.x = BEGIN
set_pos(ofs)
-
+
func _ready():
- # Initialization here
if (use_idle):
set_process(true)
else:
set_fixed_process(true)
- pass
-
-
diff --git a/demos/2d/motion/motion.scn b/demos/2d/motion/motion.scn
index 6c5b5307ac..6e19356674 100644
--- a/demos/2d/motion/motion.scn
+++ b/demos/2d/motion/motion.scn
Binary files differ
diff --git a/demos/2d/navpoly/navigation.gd b/demos/2d/navpoly/navigation.gd
index 9c3dc2921d..4cfa2ad733 100644
--- a/demos/2d/navpoly/navigation.gd
+++ b/demos/2d/navpoly/navigation.gd
@@ -1,63 +1,53 @@
extends Navigation2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
-var begin=Vector2()
-var end=Vector2()
-var path=[]
+# Member variables
+const SPEED = 200.0
-const SPEED=200.0
-
-func _process(delta):
+var begin = Vector2()
+var end = Vector2()
+var path = []
- if (path.size()>1):
-
+func _process(delta):
+ if (path.size() > 1):
var to_walk = delta*SPEED
- while(to_walk>0 and path.size()>=2):
- var pfrom = path[path.size()-1]
- var pto = path[path.size()-2]
+ while(to_walk > 0 and path.size() >= 2):
+ var pfrom = path[path.size() - 1]
+ var pto = path[path.size() - 2]
var d = pfrom.distance_to(pto)
- if (d<=to_walk):
- path.remove(path.size()-1)
- to_walk-=d
+ if (d <= to_walk):
+ path.remove(path.size() - 1)
+ to_walk -= d
else:
- path[path.size()-1] = pfrom.linear_interpolate(pto,to_walk/d)
- to_walk=0
-
- var atpos = path[path.size()-1]
+ path[path.size() - 1] = pfrom.linear_interpolate(pto, to_walk/d)
+ to_walk = 0
+
+ var atpos = path[path.size() - 1]
get_node("agent").set_pos(atpos)
- if (path.size()<2):
- path=[]
+ if (path.size() < 2):
+ path = []
set_process(false)
-
else:
set_process(false)
-
func _update_path():
-
- var p = get_simple_path(begin,end,true)
- path=Array(p) # Vector2array to complex to use, convert to regular array
+ var p = get_simple_path(begin, end, true)
+ path = Array(p) # Vector2array too complex to use, convert to regular array
path.invert()
set_process(true)
-func _input(ev):
- if (ev.type==InputEvent.MOUSE_BUTTON and ev.pressed and ev.button_index==1):
- begin=get_node("agent").get_pos()
- #mouse to local navigatio cooards
- end=ev.pos - get_pos()
+func _input(event):
+ if (event.type == InputEvent.MOUSE_BUTTON and event.pressed and event.button_index == 1):
+ begin = get_node("agent").get_pos()
+ # Mouse to local navigation coordinates
+ end = event.pos - get_pos()
_update_path()
+
func _ready():
- # Initialization here
set_process_input(true)
- pass
-
-
diff --git a/demos/2d/navpoly/navigation.scn b/demos/2d/navpoly/navigation.scn
index 1bb7de391b..c56270bfd3 100644
--- a/demos/2d/navpoly/navigation.scn
+++ b/demos/2d/navpoly/navigation.scn
Binary files differ
diff --git a/demos/2d/navpoly/navigation2.scn b/demos/2d/navpoly/navigation2.scn
deleted file mode 100644
index 224aed73f5..0000000000
--- a/demos/2d/navpoly/navigation2.scn
+++ /dev/null
Binary files differ
diff --git a/demos/2d/normalmaps/normalmap.scn b/demos/2d/normalmaps/normalmap.scn
index ab737e83f3..cf5fc05ce1 100644
--- a/demos/2d/normalmaps/normalmap.scn
+++ b/demos/2d/normalmaps/normalmap.scn
Binary files differ
diff --git a/demos/2d/particles/particles.xml b/demos/2d/particles/particles.xml
index c8f7596b86..c21ccb1f55 100644
--- a/demos/2d/particles/particles.xml
+++ b/demos/2d/particles/particles.xml
@@ -1,37 +1,49 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="4" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
- <ext_resource path="res://fire_particle.png" type="Texture"></ext_resource>
- <ext_resource path="res://smoke_particle.png" type="Texture"></ext_resource>
- <ext_resource path="res://spark_particle2.png" type="Texture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="8" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://fire_particle.png" type="Texture" index="0"></ext_resource>
+ <ext_resource path="res://smoke_particle.png" type="Texture" index="1"></ext_resource>
+ <ext_resource path="res://spark_particle2.png" type="Texture" index="2"></ext_resource>
+ <resource type="ColorRamp" path="local://1">
+ <real_array name="offsets" len="3"> 0, 0.1, 1 </real_array>
+ <color_array name="colors" len="3"> 1, 1, 1, 0, 0.886275, 0.371681, 0, 1, 1, 0.99115, 1, 0 </color_array>
+
+ </resource>
+ <resource type="ColorRamp" path="local://2">
+ <real_array name="offsets" len="3"> 0, 0.2, 1 </real_array>
+ <color_array name="colors" len="3"> 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0 </color_array>
+
+ </resource>
+ <resource type="ColorRamp" path="local://3">
+ <real_array name="offsets" len="4"> 0, 0.1, 0.5, 1 </real_array>
+ <color_array name="colors" len="4"> 1, 1, 1, 0.870518, 1, 0.47451, 0.6, 1, 0.529412, 0.74902, 1, 1, 0, 1, 0.698039, 0 </color_array>
+
+ </resource>
+ <resource type="ColorRamp" path="local://4">
+ <real_array name="offsets" len="4"> 0, 0.1, 0.7, 1 </real_array>
+ <color_array name="colors" len="4"> 1, 1, 1, 0, 0.886275, 0.401015, 0, 1, 1, 0.679866, 0.432123, 0.12654, 0, 0, 0, 0 </color_array>
+
+ </resource>
<main_resource>
<dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="68">
+ <string_array len="41">
<string> "Node" </string>
- <string> "_import_path" </string>
<string> "__meta__" </string>
<string> "Fire" </string>
- <string> "Particles2D" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/behind_parent" </string>
<string> "visibility/blend_mode" </string>
<string> "transform/pos" </string>
<string> "transform/rot" </string>
- <string> "transform/scale" </string>
<string> "config/amount" </string>
<string> "config/lifetime" </string>
- <string> "config/time_scale" </string>
- <string> "config/preprocess" </string>
- <string> "config/emit_timeout" </string>
- <string> "config/emitting" </string>
- <string> "config/offset" </string>
<string> "config/half_extents" </string>
<string> "config/local_space" </string>
- <string> "config/explosiveness" </string>
- <string> "config/flip_h" </string>
- <string> "config/flip_v" </string>
<string> "config/texture" </string>
<string> "params/direction" </string>
<string> "params/spread" </string>
@@ -47,136 +59,159 @@
<string> "params/initial_size" </string>
<string> "params/final_size" </string>
<string> "params/hue_variation" </string>
- <string> "randomness/direction" </string>
- <string> "randomness/spread" </string>
- <string> "randomness/linear_velocity" </string>
- <string> "randomness/spin_velocity" </string>
- <string> "randomness/orbit_velocity" </string>
- <string> "randomness/gravity_direction" </string>
- <string> "randomness/gravity_strength" </string>
- <string> "randomness/radial_accel" </string>
- <string> "randomness/tangential_accel" </string>
- <string> "randomness/damping" </string>
+ <string> "params/anim_speed_scale" </string>
+ <string> "params/anim_initial_pos" </string>
<string> "randomness/initial_angle" </string>
- <string> "randomness/initial_size" </string>
- <string> "randomness/final_size" </string>
- <string> "randomness/hue_variation" </string>
- <string> "color_phases/count" </string>
- <string> "phase_0/pos" </string>
- <string> "phase_0/color" </string>
- <string> "phase_1/pos" </string>
- <string> "phase_1/color" </string>
- <string> "phase_2/pos" </string>
- <string> "phase_2/color" </string>
- <string> "phase_3/pos" </string>
- <string> "phase_3/color" </string>
- <string> "emission_points" </string>
+ <string> "color/color_ramp" </string>
+ <string> "Particles2D" </string>
<string> "Smoke" </string>
+ <string> "randomness/spin_velocity" </string>
<string> "Magic" </string>
+ <string> "randomness/orbit_velocity" </string>
<string> "Explosion" </string>
+ <string> "visibility/behind_parent" </string>
+ <string> "config/time_scale" </string>
+ <string> "config/explosiveness" </string>
<string> "Mask" </string>
+ <string> "color/color" </string>
+ <string> "emission_points" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
<string> "node_count" </string>
<int> 6 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="304"> -1, -1, 0, 0, -1, 1, 1, 0, 0, 0, 0, 29, 2, -1, 26, 3, 1, 4, 2, 5, 3, 6, 4, 7, 5, 8, 6, 9, 7, 10, 8, 11, 9, 12, 9, 13, 10, 14, 9, 15, 9, 16, 11, 17, 12, 18, 9, 19, 9, 20, 9, 21, 11, 22, 13, 23, 14, 24, 9, 25, 5, 26, 9, 27, 15, 28, 16, 0, 0, 0, 29, 30, -1, 25, 4, 17, 5, 18, 6, 4, 7, 19, 9, 7, 10, 20, 11, 9, 12, 21, 13, 22, 14, 5, 15, 9, 16, 9, 17, 9, 18, 9, 19, 9, 20, 9, 21, 11, 22, 5, 23, 23, 24, 9, 25, 5, 26, 9, 31, 5, 27, 5, 28, 24, 0, 0, 0, 29, 32, -1, 26, 4, 25, 6, 4, 7, 15, 8, 26, 9, 7, 10, 27, 11, 9, 12, 11, 13, 10, 14, 14, 15, 28, 16, 9, 17, 29, 18, 9, 19, 30, 20, 9, 21, 31, 22, 23, 23, 5, 24, 9, 25, 5, 26, 9, 31, 5, 33, 32, 27, 5, 28, 33, 0, 0, 0, 29, 34, -1, 28, 35, 34, 3, 1, 4, 35, 5, 3, 6, 4, 7, 15, 36, 15, 8, 6, 9, 7, 37, 36, 10, 20, 11, 9, 12, 11, 13, 37, 14, 9, 15, 9, 16, 11, 17, 12, 18, 9, 19, 9, 20, 38, 21, 5, 22, 13, 23, 23, 24, 9, 25, 5, 26, 9, 28, 39, 0, 0, 0, 29, 38, -1, 25, 4, 40, 6, 41, 7, 42, 8, 43, 9, 7, 10, 27, 11, 9, 12, 11, 13, 9, 14, 15, 15, 9, 16, 9, 17, 9, 18, 9, 19, 9, 20, 9, 21, 5, 22, 5, 23, 5, 24, 9, 25, 5, 26, 9, 31, 5, 39, 44, 40, 45, 0 </int_array>
<string> "variants" </string>
- <array len="65" shared="false">
- <node_path> "" </node_path>
+ <array len="46" shared="false">
<dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
<dictionary shared="false">
<string> "2D" </string>
<dictionary shared="false">
- <string> "pixel_snap" </string>
+ <string> "ofs" </string>
+ <vector2> -193.367, -465.428 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
<bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
<string> "zoom" </string>
<real> 0.440127 </real>
- <string> "use_snap" </string>
- <bool> False </bool>
- <string> "ofs" </string>
- <vector2> -193.367, -173.288 </vector2>
- <string> "snap" </string>
- <int> 10 </int>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
<string> "viewports" </string>
<array len="4" shared="false">
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
</array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -185,77 +220,55 @@
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
- <bool> True </bool>
- <real> 1 </real>
- <bool> False </bool>
<int> 1 </int>
<vector2> 165.787, 527.801 </vector2>
<real> -179.790649 </real>
- <vector2> 1, 1 </vector2>
<int> 32 </int>
- <real> 0 </real>
- <vector2> 0, 0 </vector2>
+ <real> 1 </real>
<vector2> 15, 15 </vector2>
- <resource resource_type="Texture" path="res://fire_particle.png"> </resource>
+ <bool> False </bool>
+ <resource external="0"> </resource>
+ <real> 0 </real>
<real> 20 </real>
<real> 180 </real>
<real> 80 </real>
<real> 0.7 </real>
<real> 0.3 </real>
<real> 2 </real>
- <int> 3 </int>
- <color> 1, 1, 1, 0 </color>
- <real> 0.1 </real>
- <color> 0.886275, 0.371681, 0, 1 </color>
- <color> 1, 0.99115, 1, 0 </color>
- <color> 0, 0, 0, 1 </color>
- <vector2_array len="0"> </vector2_array>
+ <resource resource_type="ColorRamp" path="local://1"> </resource>
<vector2> 377.396, 543.147 </vector2>
<real> 176.575912 </real>
<real> 4 </real>
- <resource resource_type="Texture" path="res://smoke_particle.png"> </resource>
+ <resource external="1"> </resource>
<real> 20.907272 </real>
<real> 47.151516 </real>
<real> 3 </real>
- <real> 0.2 </real>
- <color> 1, 1, 1, 1 </color>
- <color> 0, 0, 0, 0 </color>
+ <resource resource_type="ColorRamp" path="local://2"> </resource>
<vector2> 593.848, 531.064 </vector2>
<vector2> 40, 40 </vector2>
- <resource resource_type="Texture" path="res://spark_particle2.png"> </resource>
+ <resource external="2"> </resource>
<real> 0.01 </real>
<real> 9.8 </real>
<real> 15.515152 </real>
<real> 45 </real>
<real> 100 </real>
- <int> 4 </int>
- <color> 1, 1, 1, 0.870518 </color>
- <color> 1, 0.47451, 0.6, 1 </color>
- <real> 0.5 </real>
- <color> 0.529412, 0.74902, 1, 1 </color>
- <color> 0, 1, 0.698039, 0 </color>
+ <resource resource_type="ColorRamp" path="local://3"> </resource>
+ <bool> True </bool>
<vector2> 613.467, 182.62 </vector2>
<real> 0.05 </real>
<real> 184.546997 </real>
<real> 366.300415 </real>
- <color> 0.886275, 0.401015, 0, 1 </color>
- <color> 1, 0.679866, 0.432123, 0.12654 </color>
+ <resource resource_type="ColorRamp" path="local://4"> </resource>
<vector2> 192.975, 141.598 </vector2>
<int> 170 </int>
+ <real> 0.1 </real>
<vector2> 128, 128 </vector2>
- <int> 0 </int>
<color> 1, 0.477876, 0.60177, 1 </color>
- <color> 0.533333, 0.752212, 1, 1 </color>
- <color> 0, 1, 0.699115, 0 </color>
<vector2_array len="512"> -0.125, -0.03125, 0.65625, -0.148438, 0.609375, 0.0234375, -0.757812, 0.375, 0.265625, 0.078125, 0.632812, 0.382812, 0.671875, 0.414062, 0.367188, -0.226562, 0.75, -0.125, 0.4375, 0.421875, 0.335938, -0.148438, -0.125, 0.257812, -0.171875, 0.359375, -0.601562, -0.265625, 0.375, 0.382812, -0.296875, 0.09375, -0.664062, -0.21875, -0.554688, -0.226562, -0.320312, 0.367188, -0.320312, -0.257812, 0, -0.257812, 0.578125, -0.25, -0.164062, 0.109375, -0.578125, -0.015625, -0.445312, 0, 0.273438, 0.101562, 0.320312, 0.03125, -0.125, 0.0703125, -0.570312, 0.289062, 0.257812, -0.09375, -0.585938, 0.179688, -0.664062, 0.0234375, -0.25, -0.0859375, 0.6875, -0.109375, 0.234375, 0, -0.5, -0.265625, 0.710938, 0.335938, 0.609375, -0.046875, 0.664062, -0.210938, -0.242188, -0.21875, -0.484375, -0.257812, -0.453125, 0.414062, 0.609375, -0.203125, 0.289062, 0.132812, -0.03125, -0.257812, -0.492188, -0.1875, 0.5625, -0.140625, -0.5625, 0.148438, -0.257812, -0.234375, -0.140625, 0.15625, -0.5625, 0.109375, 0.132812, 0.398438, -0.640625, -0.25, -0.585938, 0.304688, -0.328125, -0.257812, 0.226562, 0.148438, -0.546875, 0.210938, 0.625, 0.179688, 0.648438, -0.0078125, 0.367188, 0.328125, 0.265625, 0.0546875, -0.59375, -0.273438, -0.203125, 0.21875, 0.570312, -0.21875, -0.695312, 0.078125, -0.375, 0.03125, -0.164062, 0.0390625, 0.265625, 0.226562, -0.625, -0.109375, 0.203125, -0.132812, -0.671875, 0.328125, 0.625, -0.179688, -0.640625, 0.0859375, 0.65625, 0, -0.242188, 0.414062, 0.242188, 0.25, -0.148438, -0.0625, 0.390625, -0.25, 0.664062, 0.351562, 0.320312, 0.203125, -0.546875, 0.335938, 0.328125, -0.148438, 0.609375, -0.0625, -0.171875, 0.046875, -0.578125, 0.0546875, -0.304688, -0.28125, 0.734375, -0.0546875, 0.679688, 0.390625, -0.460938, 0.0859375, -0.703125, 0.101562, -0.140625, 0.234375, -0.507812, 0.078125, -0.25, 0.304688, -0.046875, 0.359375, 0.1875, 0.0703125, -0.570312, 0.242188, 0.65625, 0.0859375, -0.203125, -0.265625, -0.164062, -0.179688, 0.367188, -0.1875, -0.601562, -0.101562, -0.117188, -0.210938, -0.546875, 0.109375, -0.585938, -0.28125, -0.59375, -0.03125, 0.3125, -0.179688, 0.414062, 0.429688, -0.476562, -0.195312, -0.0703125, -0.21875, -0.5625, 0.304688, -0.609375, 0.226562, 0.429688, 0.429688, 0.203125, 0.242188, 0.078125, 0.367188, 0.242188, 0.03125, 0.601562, -0.0390625, 0.328125, 0.03125, -0.53125, -0.195312, -0.53125, -0.210938, 0.3125, -0.257812, 0.445312, -0.273438, 0.273438, -0.273438, -0.695312, -0.179688, 0.234375, -0.15625, -0.546875, -0.242188, -0.234375, -0.125, 0.734375, -0.226562, 0.367188, -0.234375, -0.15625, 0.046875, -0.445312, -0.226562, 0.625, 0.03125, -0.0859375, 0.210938, -0.648438, 0.296875, 0.335938, -0.109375, 0.625, -0.078125, 0.601562, 0.351562, 0.242188, 0.140625, 0.0234375, -0.273438, -0.679688, -0.109375, 0.640625, 0.15625, 0.171875, 0.0859375, -0.273438, -0.273438, -0.242188, 0.34375, 0.179688, 0.15625, -0.179688, -0.117188, 0.671875, 0.03125, -0.640625, 0.304688, 0.109375, -0.242188, -0.210938, 0.382812, -0.0859375, 0.0078125, -0.695312, 0.078125, 0.296875, 0.320312, 0.304688, -0.226562, 0.257812, -0.0234375, -0.203125, -0.015625, -0.648438, 0.335938, -0.703125, -0.132812, -0.273438, -0.210938, -0.15625, -0.273438, -0.0390625, 0.335938, 0.617188, 0.179688, 0.34375, 0.390625, -0.210938, -0.132812, -0.226562, -0.117188, 0.617188, -0.289062, 0.125, -0.21875, 0.71875, -0.164062, -0.570312, 0.1875, -0.1875, 0.382812, 0.640625, -0.296875, -0.125, 0.109375, 0.671875, 0.289062, -0.515625, 0.382812, 0.359375, -0.179688, 0.726562, -0.226562, 0.25, 0.320312, -0.328125, 0, -0.117188, -0.234375, -0.210938, -0.148438, -0.546875, -0.117188, 0.359375, 0.429688, -0.15625, -0.226562, 0.632812, -0.257812, -0.28125, -0.273438, 0.265625, 0.015625, -0.765625, 0.351562, 0.703125, 0.421875, -0.585938, 0.0078125, 0.28125, 0.109375, 0.304688, 0.171875, 0.65625, 0.421875, 0.078125, 0.382812, 0.179688, 0.25, -0.382812, 0.0703125, 0.585938, -0.140625, -0.109375, 0.382812, -0.59375, -0.09375, 0.4375, 0.398438, -0.132812, 0.0234375, -0.625, 0.0078125, -0.210938, -0.21875, -0.25, 0.257812, 0.257812, 0.398438, 0.625, 0.195312, 0.148438, -0.234375, -0.476562, 0.398438, -0.210938, 0.046875, 0.695312, -0.101562, 0.695312, 0.140625, -0.492188, -0.1875, 0.25, -0.09375, -0.195312, -0.195312, -0.328125, 0.0703125, -0.242188, -0.0625, 0.296875, 0.34375, -0.632812, 0.0078125, -0.265625, 0.09375, 0.421875, -0.203125, 0.171875, 0.03125, -0.09375, -0.0703125, 0.289062, 0.0859375, -0.609375, 0.390625, -0.554688, 0.257812, -0.6875, 0.0078125, 0.304688, 0.414062, 0.226562, 0.390625, -0.21875, -0.28125, 0.265625, 0.320312, -0.671875, 0.234375, -0.210938, 0.03125, 0.679688, -0.0234375, 0.359375, -0.203125, 0.3125, 0.289062, 0.671875, 0.140625, -0.78125, 0.414062, -0.546875, 0.40625, 0.625, 0.367188, 0.0859375, 0.421875, 0.1875, -0.09375, 0.617188, 0.40625, -0.078125, -0.0390625, 0.695312, 0.0859375, -0.6875, -0.265625, 0.421875, -0.265625, 0.601562, -0.0234375, -0.3125, -0.265625, -0.078125, 0.046875, 0.617188, 0.164062, 0.273438, -0.03125, -0.695312, -0.015625, -0.5625, 0.164062, -0.578125, 0.265625, -0.726562, 0.421875, -0.078125, -0.25, -0.171875, 0.171875, -0.234375, -0.0390625, 0.257812, 0.429688, -0.179688, -0.117188, 0.351562, -0.03125, -0.78125, -0.234375, -0.546875, -0.171875, -0.460938, -0.234375, -0.164062, 0.09375, -0.65625, 0.398438, -0.445312, 0.0859375, -0.71875, -0.226562, 0.671875, 0.101562, -0.46875, -0.195312, -0.71875, -0.265625, 0.617188, 0.125, -0.78125, -0.21875, -0.226562, -0.15625, 0.21875, 0.0234375, 0.289062, 0.101562, 0.648438, -0.171875, 0.390625, -0.273438, -0.257812, 0.078125, -0.21875, 0, 0.65625, -0.203125, -0.679688, 0.171875, -0.1875, 0.328125, -0.46875, -0.28125, 0.273438, 0, 0.664062, 0.296875, -0.140625, 0.335938, -0.625, 0.382812, -0.34375, -0.21875, -0.171875, -0.25, -0.546875, -0.117188, -0.117188, -0.203125, -0.1875, 0.351562, -0.585938, -0.109375, -0.203125, -0.0625, -0.570312, 0.03125, -0.5625, -0.109375, 0.601562, -0.195312, 0.3125, 0.140625, -0.101562, 0.25, 0.25, 0.3125, 0.125, -0.203125, -0.09375, -0.140625, -0.242188, 0.414062, 0.664062, -0.0625, -0.21875, -0.078125, 0.6875, -0.210938, -0.140625, 0.015625, -0.632812, -0.25, -0.109375, 0.234375, -0.695312, 0.015625, -0.3125, -0.28125, 0.296875, -0.0234375, 0.296875, 0.203125, -0.125, 0.234375, 0.570312, 0.390625, -0.554688, 0.203125, -0.5625, 0.351562, -0.15625, 0.21875, -0.375, 0.0390625, -0.226562, -0.140625, 0.695312, 0.164062, 0.632812, 0.367188, -0.328125, -0.210938, -0.59375, 0.34375, 0.304688, -0.242188, -0.34375, 0.0703125, -0.679688, -0.179688, 0.664062, 0.101562, 0.34375, 0.171875, -0.695312, -0.078125, -0.242188, -0.0546875, 0.304688, -0.234375, -0.0078125, -0.21875, -0.632812, 0.203125, 0.625, 0.03125, -0.414062, 0.015625, 0.273438, -0.078125, 0.695312, 0.28125, 0.34375, 0.101562, -0.164062, 0.289062, -0.1875, 0.273438, -0.203125, 0.0703125, 0.734375, -0.171875, -0.59375, 0.34375, -0.15625, 0.210938, 0.429688, 0.375, -0.234375, 0.34375, 0.617188, 0.101562, 0.703125, 0, -0.578125, 0.148438, 0.21875, -0.171875, -0.304688, 0.375, -0.65625, -0.09375, -0.101562, 0.25, -0.4375, 0.03125, -0.242188, 0.421875, -0.546875, 0.0625, -0.632812, -0.148438, -0.125, 0.179688, 0.179688, 0.304688, -0.265625, 0.078125, -0.289062, 0.421875, -0.585938, 0.1875, -0.289062, 0.34375, 0.273438, 0.367188, -0.109375, 0.117188, 0.34375, 0.046875, -0.0625, 0.320312, 0.6875, -0.234375, -0.523438, 0.320312, -0.09375, -0.242188, -0.65625, 0.25, -0.609375, -0.117188, -0.140625, 0.140625, 0.28125, -0.09375, -0.625, -0.28125, 0.34375, 0.328125, 0.265625, 0.109375, -0.609375, 0.0078125, -0.078125, -0.234375, -0.289062, -0.203125, 0.289062, 0.289062, -0.0859375, 0.0078125, -0.101562, -0.28125, -0.625, -0.101562, -0.546875, 0.382812, -0.539062, -0.195312, -0.210938, 0.046875, -0.492188, 0.390625, -0.664062, -0.0703125, 0.71875, -0.101562, -0.140625, -0.046875, 0.695312, 0.289062, -0.710938, 0.429688, -0.703125, 0.3125, -0.203125, 0.109375, 0.421875, -0.273438, 0.304688, 0.21875, 0.328125, 0.257812, -0.632812, -0.0703125, 0.320312, -0.140625, 0.265625, -0.203125, -0.109375, -0.179688, 0.25, -0.210938, 0.65625, 0.109375, -0.648438, -0.0625, -0.0859375, 0.375, -0.429688, 0.398438, 0.320312, 0.3125, -0.0703125, 0.265625, 0.648438, 0.0078125, 0.320312, 0.335938, 0.398438, 0.421875, -0.101562, -0.0625, -0.296875, 0.40625, 0.695312, -0.0390625, 0.335938, 0.21875, -0.546875, 0.117188, -0.476562, 0.390625, -0.648438, 0.117188, -0.078125, -0.28125, 0.328125, 0.289062, -0.226562, 0.179688, 0.226562, 0.375, -0.429688, 0.382812, -0.0546875, 0.34375, 0.59375, -0.125, 0.632812, 0.265625, 0.226562, 0.3125, -0.523438, -0.140625, -0.546875, 0.046875, 0.242188, -0.148438, -0.648438, 0.0234375, -0.289062, 0, -0.546875, 0.101562, -0.125, -0.0625, -0.492188, 0.367188, 0.328125, 0.15625, -0.351562, 0.0546875, -0.609375, 0.414062, -0.296875, 0.09375, 0.671875, -0.203125, -0.257812, -0.273438, -0.335938, 0.414062, 0.65625, -0.195312, -0.601562, -0.101562, -0.203125, -0.078125, 0.210938, 0.242188, 0.296875, 0.335938, -0.578125, 0.40625, -0.664062, -0.078125, -0.0859375, 0.390625, 0.171875, 0.304688, -0.6875, 0.390625, -0.554688, 0.0078125, -0.570312, -0.179688, -0.210938, -0.09375, 0.726562, -0.03125, -0.546875, -0.0859375, -0.265625, -0.171875, -0.65625, 0.179688, -0.171875, 0.257812, -0.164062, -0.171875, 0.203125, 0.335938, -0.640625, 0.21875, 0.390625, 0.375, 0.6875, -0.234375, 0.742188, 0.34375, -0.0546875, 0.351562, -0.632812, 0.195312, 0.671875, -0.21875, 0.195312, 0.015625, 0.226562, 0.117188, -0.507812, 0.078125, -0.140625, -0.15625, 0.703125, -0.28125, 0.226562, -0.140625, 0.328125, 0.421875, 0.3125, 0.1875, 0.703125, 0.078125, 0.351562, 0.289062, 0.21875, -0.242188, -0.328125, 0, 0.171875, 0.101562, -0.304688, -0.242188, -0.210938, 0.078125, 0.625, -0.0078125, 0.25, 0.242188, -0.664062, 0.117188, 0.203125, -0.140625, 0.226562, 0.429688, 0.328125, -0.203125, -0.679688, 0.0703125, -0.195312, -0.148438, -0.523438, 0.328125, 0.382812, -0.257812, 0.578125, -0.171875, 0.65625, 0.320312, -0.632812, -0.148438, 0.703125, 0.0703125, -0.53125, 0.398438, -0.414062, 0.03125, -0.0859375, 0.0546875, -0.53125, 0.335938, 0.304688, 0.429688, -0.234375, -0.148438, -0.375, 0.046875, -0.148438, 0.289062, -0.0390625, 0.421875, 0.226562, -0.125, -0.570312, 0.398438, -0.0703125, -0.0234375, 0.257812, -0.132812 </vector2_array>
</array>
- <string> "nodes" </string>
- <int_array len="640"> -1, -1, 0, 0, -1, 2, 1, 0, 2, 1, 0, 0, 0, 4, 3, -1, 60, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 8, 13, 9, 14, 3, 15, 3, 16, 10, 17, 10, 18, 2, 19, 11, 20, 12, 21, 4, 22, 3, 23, 4, 24, 4, 25, 13, 26, 10, 27, 10, 28, 14, 29, 10, 30, 10, 31, 15, 32, 16, 33, 10, 34, 10, 35, 10, 36, 15, 37, 17, 38, 18, 39, 10, 40, 10, 41, 10, 42, 10, 43, 10, 44, 10, 45, 10, 46, 10, 47, 10, 48, 10, 49, 10, 50, 19, 51, 10, 52, 10, 53, 10, 54, 20, 55, 10, 56, 21, 57, 22, 58, 23, 59, 3, 60, 24, 61, 3, 62, 25, 63, 26, 0, 0, 0, 4, 64, -1, 59, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 10, 27, 11, 28, 12, 8, 13, 9, 14, 29, 15, 3, 16, 10, 17, 10, 18, 2, 19, 11, 20, 11, 21, 4, 22, 3, 23, 4, 24, 4, 25, 30, 26, 10, 27, 31, 28, 32, 29, 3, 30, 10, 31, 10, 32, 10, 33, 10, 34, 10, 35, 10, 36, 15, 37, 3, 38, 33, 39, 10, 40, 10, 41, 10, 42, 10, 43, 3, 44, 10, 45, 10, 46, 10, 47, 10, 48, 10, 49, 10, 50, 3, 51, 10, 52, 10, 53, 10, 54, 20, 55, 10, 56, 21, 57, 34, 58, 35, 59, 3, 60, 36, 61, 3, 62, 25, 63, 26, 0, 0, 0, 4, 65, -1, 59, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 10, 37, 11, 10, 12, 8, 13, 9, 14, 19, 15, 3, 16, 10, 17, 10, 18, 2, 19, 11, 20, 38, 21, 4, 22, 3, 23, 4, 24, 4, 25, 39, 26, 10, 27, 15, 28, 14, 29, 18, 30, 40, 31, 10, 32, 41, 33, 10, 34, 42, 35, 10, 36, 43, 37, 33, 38, 3, 39, 10, 40, 10, 41, 10, 42, 10, 43, 3, 44, 44, 45, 10, 46, 10, 47, 10, 48, 10, 49, 10, 50, 3, 51, 10, 52, 10, 53, 10, 54, 45, 55, 10, 56, 46, 57, 22, 58, 47, 59, 48, 60, 49, 61, 3, 62, 50, 63, 26, 0, 0, 0, 4, 66, -1, 60, 1, 0, 5, 2, 6, 3, 7, 3, 8, 2, 9, 5, 10, 51, 11, 7, 12, 8, 13, 9, 14, 19, 15, 19, 16, 10, 17, 10, 18, 2, 19, 11, 20, 12, 21, 4, 22, 52, 23, 4, 24, 4, 25, 30, 26, 10, 27, 15, 28, 53, 29, 10, 30, 10, 31, 15, 32, 16, 33, 10, 34, 10, 35, 54, 36, 3, 37, 17, 38, 33, 39, 10, 40, 10, 41, 10, 42, 10, 43, 10, 44, 10, 45, 10, 46, 10, 47, 10, 48, 10, 49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 45, 55, 10, 56, 21, 57, 22, 58, 55, 59, 17, 60, 56, 61, 3, 62, 36, 63, 26, 0, 0, 0, 4, 67, -1, 59, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 10, 57, 11, 10, 12, 8, 13, 58, 14, 22, 15, 3, 16, 10, 17, 10, 18, 2, 19, 11, 20, 59, 21, 4, 22, 3, 23, 4, 24, 4, 25, 39, 26, 10, 27, 15, 28, 10, 29, 19, 30, 10, 31, 10, 32, 10, 33, 10, 34, 10, 35, 10, 36, 3, 37, 3, 38, 3, 39, 10, 40, 10, 41, 10, 42, 10, 43, 3, 44, 10, 45, 10, 46, 10, 47, 10, 48, 10, 49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 60, 55, 10, 56, 61, 57, 48, 58, 62, 59, 3, 60, 63, 61, 3, 62, 25, 63, 64, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/platformer/bullet.gd b/demos/2d/platformer/bullet.gd
index 9aacc9809d..3aee69714e 100644
--- a/demos/2d/platformer/bullet.gd
+++ b/demos/2d/platformer/bullet.gd
@@ -1,21 +1,16 @@
extends RigidBody2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
+# Member variables
+var disabled = false
-var disabled=false
func disable():
if (disabled):
return
get_node("anim").play("shutdown")
- disabled=true
+ disabled = true
+
func _ready():
- # Initalization here
get_node("Timer").start()
- pass
-
-
diff --git a/demos/2d/platformer/bullet.xml b/demos/2d/platformer/bullet.xml
index 84c903803f..63938581ad 100644
--- a/demos/2d/platformer/bullet.xml
+++ b/demos/2d/platformer/bullet.xml
@@ -1,12 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="5" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
- <ext_resource path="res://bullet.*" type="Texture"></ext_resource>
- <ext_resource path="res://bullet.*" type="Script"></ext_resource>
+<resource_file type="PackedScene" subresource_count="6" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://bullet.png" type="Texture" index="1"></ext_resource>
+ <ext_resource path="res://bullet.gd" type="Script" index="0"></ext_resource>
<resource type="CircleShape2D" path="local://1">
<real name="custom_solver_bias"> 0 </real>
<real name="radius"> 10 </real>
</resource>
+ <resource type="ColorRamp" path="local://3">
+ <real_array name="offsets" len="2"> 0, 1 </real_array>
+ <color_array name="colors" len="2"> 1, 1, 1, 1, 1, 0, 0, 0 </color_array>
+
+ </resource>
<resource type="Animation" path="local://2">
<string name="resource/name"> "shutdown" </string>
<real name="length"> 1.5 </real>
@@ -18,14 +23,14 @@
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
+ <string> "times" </string>
+ <real_array len="1"> 0 </real_array>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<bool> False </bool>
</array>
- <string> "times" </string>
- <real_array len="1"> 0 </real_array>
</dictionary>
<string name="tracks/1/type"> "value" </string>
<node_path name="tracks/1/path"> "sprite:visibility/self_opacity" </node_path>
@@ -33,6 +38,8 @@
<dictionary name="tracks/1/keys" shared="false">
<string> "cont" </string>
<bool> True </bool>
+ <string> "times" </string>
+ <real_array len="2"> 0, 1.00394 </real_array>
<string> "transitions" </string>
<real_array len="2"> 1, 1 </real_array>
<string> "values" </string>
@@ -40,13 +47,13 @@
<real> 1 </real>
<real> 0 </real>
</array>
- <string> "times" </string>
- <real_array len="2"> 0, 1.00394 </real_array>
</dictionary>
<string name="tracks/2/type"> "method" </string>
<node_path name="tracks/2/path"> "." </node_path>
<int name="tracks/2/interp"> 1 </int>
<dictionary name="tracks/2/keys" shared="false">
+ <string> "times" </string>
+ <real_array len="1"> 1.31 </real_array>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
@@ -59,57 +66,51 @@
<string> "queue_free" </string>
</dictionary>
</array>
- <string> "times" </string>
- <real_array len="1"> 1.31 </real_array>
</dictionary>
</resource>
<main_resource>
<dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 1 </int>
+ <string> "conns" </string>
+ <int_array len="6"> 4, 0, 73, 72, 2, 0 </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="111">
+ <string_array len="74">
<string> "bullet" </string>
- <string> "RigidBody2D" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
- <string> "shape_count" </string>
+ <string> "input/pickable" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
<string> "shapes/0/trigger" </string>
+ <string> "collision/layers" </string>
+ <string> "collision/mask" </string>
<string> "mode" </string>
<string> "mass" </string>
<string> "friction" </string>
<string> "bounce" </string>
+ <string> "gravity_scale" </string>
<string> "custom_integrator" </string>
<string> "continuous_cd" </string>
<string> "contacts_reported" </string>
<string> "contact_monitor" </string>
- <string> "active" </string>
+ <string> "sleeping" </string>
<string> "can_sleep" </string>
<string> "velocity/linear" </string>
<string> "velocity/angular" </string>
+ <string> "damp_override/linear" </string>
+ <string> "damp_override/angular" </string>
<string> "script/script" </string>
<string> "__meta__" </string>
+ <string> "RigidBody2D" </string>
<string> "particles" </string>
- <string> "Particles2D" </string>
+ <string> "visibility/opacity" </string>
<string> "visibility/blend_mode" </string>
<string> "config/amount" </string>
<string> "config/lifetime" </string>
- <string> "config/time_scale" </string>
- <string> "config/preprocess" </string>
- <string> "config/emit_timeout" </string>
- <string> "config/emitting" </string>
- <string> "config/offset" </string>
- <string> "config/half_extents" </string>
<string> "config/local_space" </string>
- <string> "config/explosiveness" </string>
- <string> "config/flip_h" </string>
- <string> "config/flip_v" </string>
<string> "config/texture" </string>
<string> "params/direction" </string>
<string> "params/spread" </string>
@@ -121,54 +122,27 @@
<string> "params/radial_accel" </string>
<string> "params/tangential_accel" </string>
<string> "params/damping" </string>
+ <string> "params/initial_angle" </string>
<string> "params/initial_size" </string>
<string> "params/final_size" </string>
<string> "params/hue_variation" </string>
- <string> "randomness/direction" </string>
- <string> "randomness/spread" </string>
- <string> "randomness/linear_velocity" </string>
- <string> "randomness/spin_velocity" </string>
- <string> "randomness/orbit_velocity" </string>
- <string> "randomness/gravity_direction" </string>
- <string> "randomness/gravity_strength" </string>
- <string> "randomness/radial_accel" </string>
- <string> "randomness/tangential_accel" </string>
- <string> "randomness/damping" </string>
- <string> "randomness/initial_size" </string>
- <string> "randomness/final_size" </string>
- <string> "randomness/hue_variation" </string>
- <string> "color_phases/count" </string>
- <string> "phase_0/pos" </string>
- <string> "phase_0/color" </string>
- <string> "phase_1/pos" </string>
- <string> "phase_1/color" </string>
- <string> "phase_2/pos" </string>
- <string> "phase_2/color" </string>
- <string> "phase_3/pos" </string>
- <string> "phase_3/color" </string>
- <string> "emission_points" </string>
+ <string> "params/anim_speed_scale" </string>
+ <string> "params/anim_initial_pos" </string>
+ <string> "color/color_ramp" </string>
+ <string> "Particles2D" </string>
<string> "sprite" </string>
- <string> "Sprite" </string>
<string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
+ <string> "Sprite" </string>
<string> "CollisionShape2D" </string>
<string> "shape" </string>
<string> "trigger" </string>
+ <string> "_update_shape_index" </string>
<string> "Timer" </string>
+ <string> "process_mode" </string>
<string> "wait_time" </string>
<string> "one_shot" </string>
<string> "autostart" </string>
<string> "anim" </string>
- <string> "AnimationPlayer" </string>
<string> "playback/process_mode" </string>
<string> "playback/default_blend_time" </string>
<string> "root/root" </string>
@@ -177,128 +151,158 @@
<string> "playback/speed" </string>
<string> "blend_times" </string>
<string> "autoplay" </string>
+ <string> "AnimationPlayer" </string>
<string> "disable" </string>
<string> "timeout" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 1 </int>
<string> "node_count" </string>
<int> 6 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="166"> -1, -1, 24, 0, -1, 23, 1, 0, 2, 1, 3, 2, 4, 0, 5, 3, 6, 3, 7, 4, 8, 5, 9, 5, 10, 6, 11, 5, 12, 0, 13, 7, 14, 4, 15, 0, 16, 0, 17, 8, 18, 9, 19, 6, 20, 10, 21, 10, 22, 11, 23, 12, 0, 0, 0, 49, 25, -1, 23, 26, 13, 27, 3, 28, 14, 29, 15, 30, 0, 31, 16, 32, 6, 33, 17, 34, 6, 35, 6, 36, 6, 37, 6, 38, 6, 39, 6, 40, 6, 41, 6, 42, 6, 43, 5, 44, 6, 45, 6, 46, 5, 47, 6, 48, 18, 0, 0, 0, 52, 50, -1, 1, 51, 16, 0, 0, 0, 53, 53, -1, 3, 54, 1, 55, 0, 56, 19, 0, 0, 0, 57, 57, -1, 4, 58, 3, 59, 5, 60, 8, 61, 0, 0, 0, 0, 71, 62, -1, 8, 63, 3, 64, 6, 65, 20, 66, 21, 67, 8, 68, 5, 69, 22, 70, 23, 0 </int_array>
<string> "variants" </string>
- <array len="27" shared="false">
- <bool> True </bool>
- <real> 1 </real>
- <vector2> 0, 0 </vector2>
- <real> 0 </real>
- <vector2> 1, 1 </vector2>
- <int> 1 </int>
+ <array len="24" shared="false">
+ <bool> False </bool>
<resource resource_type="Shape2D" path="local://1"> </resource>
<matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
- <bool> False </bool>
+ <int> 1 </int>
<int> 0 </int>
+ <real> 1 </real>
+ <real> 0 </real>
<int> 2 </int>
- <resource resource_type="Script" path="res://bullet.*"> </resource>
+ <bool> True </bool>
+ <vector2> 0, 0 </vector2>
+ <real> -1 </real>
+ <resource external="0"> </resource>
<dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
<dictionary shared="false">
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 2 </int>
- <string> "sources" </string>
- <array len="3" shared="false">
- <string> "res://enemy.gd" </string>
- <string> "res://player.gd" </string>
- <string> "res://bullet.gd" </string>
- </array>
- </dictionary>
<string> "2D" </string>
<dictionary shared="false">
- <string> "pixel_snap" </string>
+ <string> "ofs" </string>
+ <vector2> -74.7573, -35.9676 </vector2>
+ <string> "snap_grid" </string>
<bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
<string> "zoom" </string>
<real> 3.424785 </real>
- <string> "ofs" </string>
- <vector2> -74.7573, -35.9676 </vector2>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
<string> "viewports" </string>
<array len="4" shared="false">
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
</array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -307,29 +311,22 @@
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
<real> 0.559322 </real>
<int> 24 </int>
<real> 0.1 </real>
- <resource resource_type="Texture" path="res://bullet.*"> </resource>
+ <resource external="1"> </resource>
<real> 10 </real>
- <color> 1, 1, 1, 1 </color>
- <color> 1, 0, 0, 0 </color>
- <color> 0, 0, 0, 1 </color>
- <vector2_array len="0"> </vector2_array>
- <rect2> 0, 0, 0, 0 </rect2>
+ <resource resource_type="ColorRamp" path="local://3"> </resource>
+ <int> -1 </int>
<node_path> ".." </node_path>
<resource resource_type="Animation" path="local://2"> </resource>
<array len="0" shared="false">
</array>
<string> "" </string>
</array>
- <string> "nodes" </string>
- <int_array len="282"> -1, -1, 1, 0, -1, 25, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 8, 13, 9, 14, 1, 15, 1, 16, 3, 17, 8, 18, 10, 19, 9, 20, 8, 21, 0, 22, 0, 23, 2, 24, 3, 25, 11, 26, 12, 0, 0, 0, 28, 27, -1, 57, 2, 0, 3, 13, 4, 1, 5, 0, 29, 5, 6, 2, 7, 3, 8, 4, 30, 14, 31, 15, 32, 1, 33, 3, 34, 3, 35, 0, 36, 2, 37, 2, 38, 8, 39, 1, 40, 8, 41, 8, 42, 16, 43, 3, 44, 17, 45, 3, 46, 3, 47, 3, 48, 3, 49, 3, 50, 3, 51, 3, 52, 3, 53, 1, 54, 3, 55, 3, 56, 3, 57, 3, 58, 3, 59, 3, 60, 3, 61, 3, 62, 3, 63, 3, 64, 3, 65, 3, 66, 3, 67, 3, 68, 3, 69, 10, 70, 3, 71, 18, 72, 1, 73, 19, 74, 1, 75, 20, 76, 1, 77, 20, 78, 21, 0, 0, 0, 80, 79, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 81, 16, 82, 0, 83, 2, 84, 8, 85, 8, 86, 5, 87, 5, 88, 9, 89, 18, 90, 8, 91, 22, 0, 0, 0, 92, 92, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 93, 6, 94, 8, 0, 0, 0, 95, 95, -1, 3, 96, 1, 97, 0, 98, 8, 0, 0, 0, 100, 99, -1, 8, 101, 5, 102, 3, 103, 23, 104, 24, 105, 0, 106, 1, 107, 25, 108, 26, 0 </int_array>
- <string> "conns" </string>
- <int_array len="6"> 4, 0, 110, 109, 2, 0 </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/platformer/coin.gd b/demos/2d/platformer/coin.gd
index 983cd46d88..1118732707 100644
--- a/demos/2d/platformer/coin.gd
+++ b/demos/2d/platformer/coin.gd
@@ -1,28 +1,19 @@
extends Area2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-var taken=false
+# Member variables
+var taken = false
func _on_body_enter( body ):
if (not taken and body extends preload("res://player.gd")):
get_node("anim").play("taken")
- taken=true
-
-
-func _ready():
- # Initalization here
- pass
-
+ taken = true
-func _on_coin_area_enter( area ):
+func _on_coin_area_enter(area):
pass # replace with function body
-func _on_coin_area_enter_shape( area_id, area, area_shape, area_shape ):
+func _on_coin_area_enter_shape(area_id, area, area_shape, area_shape):
pass # replace with function body
diff --git a/demos/2d/platformer/coin.xml b/demos/2d/platformer/coin.xml
index 194ea711b0..f33a63bd57 100644
--- a/demos/2d/platformer/coin.xml
+++ b/demos/2d/platformer/coin.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="9" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
- <ext_resource path="res://bullet.*" type="Texture"></ext_resource>
- <ext_resource path="res://coin.*" type="Texture"></ext_resource>
- <ext_resource path="res://sound_coin.*" type="Sample"></ext_resource>
- <ext_resource path="res://coin.*" type="Script"></ext_resource>
+<resource_file type="PackedScene" subresource_count="10" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://bullet.png" type="Texture" index="3"></ext_resource>
+ <ext_resource path="res://coin.png" type="Texture" index="1"></ext_resource>
+ <ext_resource path="res://sound_coin.wav" type="Sample" index="2"></ext_resource>
+ <ext_resource path="res://coin.gd" type="Script" index="0"></ext_resource>
<resource type="CircleShape2D" path="local://1">
<real name="custom_solver_bias"> 0 </real>
<real name="radius"> 10 </real>
@@ -20,14 +20,14 @@
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> True </bool>
+ <string> "times" </string>
+ <real_array len="1"> 0 </real_array>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 0 </int>
</array>
- <string> "times" </string>
- <real_array len="1"> 0 </real_array>
</dictionary>
<string name="tracks/1/type"> "value" </string>
<node_path name="tracks/1/path"> "sound:play/play" </node_path>
@@ -35,14 +35,14 @@
<dictionary name="tracks/1/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
+ <string> "times" </string>
+ <real_array len="1"> 0 </real_array>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<string> "coin" </string>
</array>
- <string> "times" </string>
- <real_array len="1"> 0 </real_array>
</dictionary>
<string name="tracks/2/type"> "value" </string>
<node_path name="tracks/2/path"> "particles:visibility/self_opacity" </node_path>
@@ -50,6 +50,8 @@
<dictionary name="tracks/2/keys" shared="false">
<string> "cont" </string>
<bool> True </bool>
+ <string> "times" </string>
+ <real_array len="2"> 0, 1.66 </real_array>
<string> "transitions" </string>
<real_array len="2"> 1, 1 </real_array>
<string> "values" </string>
@@ -57,8 +59,6 @@
<real> 1 </real>
<real> 0 </real>
</array>
- <string> "times" </string>
- <real_array len="2"> 0, 1.66 </real_array>
</dictionary>
<string name="tracks/3/type"> "value" </string>
<node_path name="tracks/3/path"> "sprite:visibility/self_opacity" </node_path>
@@ -66,6 +66,8 @@
<dictionary name="tracks/3/keys" shared="false">
<string> "cont" </string>
<bool> True </bool>
+ <string> "times" </string>
+ <real_array len="2"> 0, 0.4 </real_array>
<string> "transitions" </string>
<real_array len="2"> 1, 1 </real_array>
<string> "values" </string>
@@ -73,8 +75,6 @@
<real> 1 </real>
<real> 0 </real>
</array>
- <string> "times" </string>
- <real_array len="2"> 0, 0.4 </real_array>
</dictionary>
<string name="tracks/4/type"> "value" </string>
<node_path name="tracks/4/path"> "particles:config/emitting" </node_path>
@@ -82,19 +82,21 @@
<dictionary name="tracks/4/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
+ <string> "times" </string>
+ <real_array len="1"> 0 </real_array>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<bool> True </bool>
</array>
- <string> "times" </string>
- <real_array len="1"> 0 </real_array>
</dictionary>
<string name="tracks/5/type"> "method" </string>
<node_path name="tracks/5/path"> "." </node_path>
<int name="tracks/5/interp"> 1 </int>
<dictionary name="tracks/5/keys" shared="false">
+ <string> "times" </string>
+ <real_array len="1"> 2.7 </real_array>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
@@ -107,8 +109,6 @@
<string> "queue_free" </string>
</dictionary>
</array>
- <string> "times" </string>
- <real_array len="1"> 2.7 </real_array>
</dictionary>
</resource>
@@ -123,6 +123,8 @@
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
+ <string> "times" </string>
+ <real_array len="7"> 0, 0.25, 0.5, 0.75, 1, 1.25, 1.5 </real_array>
<string> "transitions" </string>
<real_array len="7"> 1, 1, 1, 1, 1, 1, 1 </real_array>
<string> "values" </string>
@@ -135,8 +137,6 @@
<int> 1 </int>
<int> 0 </int>
</array>
- <string> "times" </string>
- <real_array len="7"> 0, 0.25, 0.5, 0.75, 1, 1.25, 1.5 </real_array>
</dictionary>
</resource>
@@ -147,49 +147,43 @@
<string> "pitch" </string>
<real> 1 </real>
<string> "sample" </string>
- <resource resource_type="Sample" path="res://sound_coin.*"> </resource>
+ <resource external="2"> </resource>
</dictionary>
</resource>
+ <resource type="ColorRamp" path="local://5">
+ <real_array name="offsets" len="2"> 0, 1 </real_array>
+ <color_array name="colors" len="2"> 1, 1, 1, 1, 0, 0, 0, 1 </color_array>
+
+ </resource>
<main_resource>
<dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 1 </int>
+ <string> "conns" </string>
+ <int_array len="6"> 0, 0, 76, 75, 2, 0 </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="115">
+ <string_array len="77">
<string> "coin" </string>
- <string> "Area2D" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
- <string> "shape_count" </string>
+ <string> "input/pickable" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
<string> "shapes/0/trigger" </string>
- <string> "gravity_point" </string>
<string> "gravity_vec" </string>
<string> "gravity" </string>
- <string> "density" </string>
- <string> "monitoring" </string>
+ <string> "linear_damp" </string>
+ <string> "angular_damp" </string>
<string> "script/script" </string>
<string> "__meta__" </string>
+ <string> "Area2D" </string>
<string> "sprite" </string>
- <string> "Sprite" </string>
<string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
<string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
+ <string> "Sprite" </string>
<string> "anim" </string>
- <string> "AnimationPlayer" </string>
<string> "playback/process_mode" </string>
<string> "playback/default_blend_time" </string>
<string> "root/root" </string>
@@ -199,12 +193,13 @@
<string> "playback/speed" </string>
<string> "blend_times" </string>
<string> "autoplay" </string>
+ <string> "AnimationPlayer" </string>
<string> "collision" </string>
- <string> "CollisionShape2D" </string>
<string> "shape" </string>
<string> "trigger" </string>
+ <string> "_update_shape_index" </string>
+ <string> "CollisionShape2D" </string>
<string> "sound" </string>
- <string> "SamplePlayer2D" </string>
<string> "params/volume_db" </string>
<string> "params/pitch_scale" </string>
<string> "params/attenuation/min_distance" </string>
@@ -213,19 +208,13 @@
<string> "config/polyphony" </string>
<string> "config/samples" </string>
<string> "config/pitch_random" </string>
+ <string> "SamplePlayer2D" </string>
<string> "particles" </string>
- <string> "Particles2D" </string>
<string> "visibility/blend_mode" </string>
<string> "config/amount" </string>
<string> "config/lifetime" </string>
- <string> "config/time_scale" </string>
- <string> "config/preprocess" </string>
- <string> "config/emit_timeout" </string>
<string> "config/emitting" </string>
- <string> "config/offset" </string>
<string> "config/half_extents" </string>
- <string> "config/local_space" </string>
- <string> "config/explosiveness" </string>
<string> "config/texture" </string>
<string> "params/direction" </string>
<string> "params/spread" </string>
@@ -237,160 +226,170 @@
<string> "params/radial_accel" </string>
<string> "params/tangential_accel" </string>
<string> "params/damping" </string>
+ <string> "params/initial_angle" </string>
<string> "params/initial_size" </string>
<string> "params/final_size" </string>
<string> "params/hue_variation" </string>
- <string> "randomness/direction" </string>
- <string> "randomness/spread" </string>
- <string> "randomness/linear_velocity" </string>
- <string> "randomness/spin_velocity" </string>
- <string> "randomness/orbit_velocity" </string>
- <string> "randomness/gravity_direction" </string>
- <string> "randomness/gravity_strength" </string>
- <string> "randomness/radial_accel" </string>
- <string> "randomness/tangential_accel" </string>
- <string> "randomness/damping" </string>
- <string> "randomness/initial_size" </string>
- <string> "randomness/final_size" </string>
- <string> "randomness/hue_variation" </string>
- <string> "color_phases/count" </string>
- <string> "phase_0/pos" </string>
- <string> "phase_0/color" </string>
- <string> "phase_1/pos" </string>
- <string> "phase_1/color" </string>
- <string> "phase_2/pos" </string>
- <string> "phase_2/color" </string>
- <string> "phase_3/pos" </string>
- <string> "phase_3/color" </string>
- <string> "emission_points" </string>
+ <string> "params/anim_speed_scale" </string>
+ <string> "params/anim_initial_pos" </string>
+ <string> "color/color_ramp" </string>
+ <string> "Particles2D" </string>
<string> "enabler" </string>
- <string> "VisibilityEnabler2D" </string>
<string> "rect" </string>
<string> "enabler/pause_animations" </string>
<string> "enabler/freeze_bodies" </string>
+ <string> "enabler/pause_particles" </string>
+ <string> "enabler/process_parent" </string>
+ <string> "enabler/fixed_process_parent" </string>
+ <string> "VisibilityEnabler2D" </string>
<string> "_on_body_enter" </string>
<string> "body_enter" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 1 </int>
<string> "node_count" </string>
<int> 7 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="171"> -1, -1, 11, 0, -1, 10, 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7, 9, 8, 10, 9, 0, 0, 0, 15, 12, -1, 2, 13, 10, 14, 11, 0, 0, 0, 26, 16, -1, 9, 17, 12, 18, 13, 19, 14, 20, 15, 21, 16, 22, 0, 23, 17, 24, 18, 25, 19, 0, 0, 0, 31, 27, -1, 3, 28, 1, 29, 3, 30, 20, 0, 0, 0, 41, 32, -1, 8, 33, 13, 34, 7, 35, 7, 36, 21, 37, 7, 38, 12, 39, 22, 40, 13, 0, 0, 0, 66, 42, -1, 23, 43, 12, 44, 23, 45, 24, 46, 3, 47, 25, 48, 26, 49, 13, 50, 27, 51, 13, 52, 13, 53, 13, 54, 13, 55, 13, 56, 13, 57, 13, 58, 13, 59, 13, 60, 28, 61, 28, 62, 13, 63, 7, 64, 13, 65, 29, 0, 0, 0, 74, 67, -1, 6, 68, 30, 69, 0, 70, 0, 71, 0, 72, 3, 73, 3, 0 </int_array>
<string> "variants" </string>
- <array len="37" shared="false">
+ <array len="31" shared="false">
<bool> True </bool>
- <real> 1 </real>
- <vector2> 0, 0 </vector2>
- <real> 0 </real>
- <vector2> 1, 1 </vector2>
- <int> 1 </int>
<resource resource_type="Shape2D" path="local://1"> </resource>
<matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
<bool> False </bool>
<vector2> 0, 1 </vector2>
<real> 98 </real>
<real> 0.1 </real>
- <resource resource_type="Script" path="res://coin.*"> </resource>
+ <real> 1 </real>
+ <resource external="0"> </resource>
<dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
<dictionary shared="false">
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 2 </int>
- <string> "sources" </string>
- <array len="3" shared="false">
- <string> "res://enemy.gd" </string>
- <string> "res://player.gd" </string>
- <string> "res://coin.gd" </string>
- </array>
- </dictionary>
<string> "2D" </string>
<dictionary shared="false">
- <string> "pixel_snap" </string>
+ <string> "ofs" </string>
+ <vector2> -34.3697, -21.6562 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
<bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
<string> "zoom" </string>
<real> 3.794776 </real>
- <string> "ofs" </string>
- <vector2> -34.3697, -21.6562 </vector2>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
<string> "viewports" </string>
<array len="4" shared="false">
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
</array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -399,14 +398,11 @@
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
- <resource resource_type="Texture" path="res://coin.*"> </resource>
+ <resource external="1"> </resource>
<int> 4 </int>
- <int> 0 </int>
- <color> 1, 1, 1, 1 </color>
- <rect2> 0, 0, 0, 0 </rect2>
+ <int> 1 </int>
+ <real> 0 </real>
<node_path> ".." </node_path>
<resource resource_type="Animation" path="local://2"> </resource>
<resource resource_type="Animation" path="local://3"> </resource>
@@ -414,23 +410,20 @@
<array len="0" shared="false">
</array>
<string> "spin" </string>
+ <int> -1 </int>
<real> 2048 </real>
<resource resource_type="SampleLibrary" path="local://4"> </resource>
<int> 8 </int>
<real> 0.4 </real>
<vector2> 5, 5 </vector2>
- <resource resource_type="Texture" path="res://bullet.*"> </resource>
+ <resource external="3"> </resource>
<real> 10 </real>
<real> 0.2 </real>
- <int> 2 </int>
- <color> 0, 0, 0, 1 </color>
- <vector2_array len="0"> </vector2_array>
+ <resource resource_type="ColorRamp" path="local://5"> </resource>
<rect2> -10, -10, 20, 20 </rect2>
</array>
- <string> "nodes" </string>
- <int_array len="317"> -1, -1, 1, 0, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 8, 13, 8, 14, 9, 15, 10, 16, 11, 17, 0, 18, 12, 19, 13, 0, 0, 0, 21, 20, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 22, 14, 23, 0, 24, 2, 25, 8, 26, 8, 27, 5, 28, 15, 29, 16, 30, 17, 31, 8, 32, 18, 0, 0, 0, 34, 33, -1, 9, 35, 5, 36, 3, 37, 19, 38, 20, 39, 21, 40, 0, 41, 22, 42, 23, 43, 24, 0, 0, 0, 45, 44, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 46, 6, 47, 8, 0, 0, 0, 49, 48, -1, 15, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 50, 3, 51, 1, 52, 1, 53, 25, 54, 1, 55, 5, 56, 26, 57, 3, 0, 0, 0, 59, 58, -1, 55, 2, 0, 3, 1, 4, 1, 5, 0, 60, 5, 6, 2, 7, 3, 8, 4, 61, 27, 62, 28, 63, 1, 64, 3, 65, 3, 66, 8, 67, 2, 68, 29, 69, 0, 70, 1, 71, 30, 72, 3, 73, 31, 74, 3, 75, 3, 76, 3, 77, 3, 78, 3, 79, 3, 80, 3, 81, 3, 82, 32, 83, 32, 84, 3, 85, 3, 86, 3, 87, 3, 88, 3, 89, 3, 90, 3, 91, 3, 92, 3, 93, 3, 94, 3, 95, 3, 96, 3, 97, 3, 98, 33, 99, 3, 100, 17, 101, 1, 102, 34, 103, 1, 104, 34, 105, 1, 106, 34, 107, 35, 0, 0, 0, 109, 108, -1, 10, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 110, 36, 111, 0, 112, 0, 0 </int_array>
- <string> "conns" </string>
- <int_array len="6"> 0, 0, 114, 113, 2, 0 </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/platformer/enemy.gd b/demos/2d/platformer/enemy.gd
index a264cd0cff..5a4d8af579 100644
--- a/demos/2d/platformer/enemy.gd
+++ b/demos/2d/platformer/enemy.gd
@@ -1,98 +1,83 @@
extends RigidBody2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
+# Member variables
const STATE_WALKING = 0
const STATE_DYING = 1
-
var state = STATE_WALKING
-
var direction = -1
-var anim=""
+var anim = ""
-var rc_left=null
-var rc_right=null
+var rc_left = null
+var rc_right = null
var WALK_SPEED = 50
var bullet_class = preload("res://bullet.gd")
+
func _die():
queue_free()
+
func _pre_explode():
- #stay there
+ # Stay there
clear_shapes()
set_mode(MODE_STATIC)
get_node("sound").play("explode")
-
-func _integrate_forces(s):
+func _integrate_forces(s):
var lv = s.get_linear_velocity()
- var new_anim=anim
+ var new_anim = anim
- if (state==STATE_DYING):
- new_anim="explode"
- elif (state==STATE_WALKING):
-
- new_anim="walk"
+ if (state == STATE_DYING):
+ new_anim = "explode"
+ elif (state == STATE_WALKING):
+ new_anim = "walk"
- var wall_side=0.0
+ var wall_side = 0.0
for i in range(s.get_contact_count()):
var cc = s.get_contact_collider_object(i)
var dp = s.get_contact_local_normal(i)
if (cc):
-
-
if (cc extends bullet_class and not cc.disabled):
set_mode(MODE_RIGID)
- state=STATE_DYING
- #lv=s.get_contact_local_normal(i)*400
+ state = STATE_DYING
+ #lv = s.get_contact_local_normal(i)*400
s.set_angular_velocity(sign(dp.x)*33.0)
set_friction(1)
cc.disable()
get_node("sound").play("hit")
-
break
-
-
- if (dp.x>0.9):
- wall_side=1.0
- elif (dp.x<-0.9):
- wall_side=-1.0
-
- if (wall_side!=0 and wall_side!=direction):
-
- direction=-direction
- get_node("sprite").set_scale( Vector2(-direction,1) )
- if (direction<0 and not rc_left.is_colliding() and rc_right.is_colliding()):
- direction=-direction
- get_node("sprite").set_scale( Vector2(-direction,1) )
- elif (direction>0 and not rc_right.is_colliding() and rc_left.is_colliding()):
- direction=-direction
- get_node("sprite").set_scale( Vector2(-direction,1) )
-
-
- lv.x = direction * WALK_SPEED
- if( anim!=new_anim ):
- anim=new_anim
+ if (dp.x > 0.9):
+ wall_side = 1.0
+ elif (dp.x < -0.9):
+ wall_side = -1.0
+
+ if (wall_side != 0 and wall_side != direction):
+ direction = -direction
+ get_node("sprite").set_scale(Vector2(-direction, 1))
+ if (direction < 0 and not rc_left.is_colliding() and rc_right.is_colliding()):
+ direction = -direction
+ get_node("sprite").set_scale(Vector2(-direction, 1))
+ elif (direction > 0 and not rc_right.is_colliding() and rc_left.is_colliding()):
+ direction = -direction
+ get_node("sprite").set_scale(Vector2(-direction, 1))
+
+ lv.x = direction*WALK_SPEED
+
+ if(anim != new_anim):
+ anim = new_anim
get_node("anim").play(anim)
-
+
s.set_linear_velocity(lv)
func _ready():
- # Initalization here
- rc_left=get_node("raycast_left")
- rc_right=get_node("raycast_right")
-
-
-
+ rc_left = get_node("raycast_left")
+ rc_right = get_node("raycast_right")
diff --git a/demos/2d/platformer/enemy.xml b/demos/2d/platformer/enemy.xml
index ad3a70931d..72d2ff068e 100644
--- a/demos/2d/platformer/enemy.xml
+++ b/demos/2d/platformer/enemy.xml
@@ -2,9 +2,9 @@
<resource_file type="PackedScene" subresource_count="12" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
<ext_resource path="res://bullet.png" type="Texture" index="2"></ext_resource>
<ext_resource path="res://enemy.gd" type="Script" index="0"></ext_resource>
- <ext_resource path="res://enemy.png" type="Texture" index="1"></ext_resource>
- <ext_resource path="res://sound_hit.wav" type="Sample" index="4"></ext_resource>
<ext_resource path="res://sound_explode.wav" type="Sample" index="3"></ext_resource>
+ <ext_resource path="res://sound_hit.wav" type="Sample" index="4"></ext_resource>
+ <ext_resource path="res://enemy.png" type="Texture" index="1"></ext_resource>
<resource type="CircleShape2D" path="local://1">
<real name="custom_solver_bias"> 0 </real>
<real name="radius"> 14 </real>
@@ -41,33 +41,6 @@
</dictionary>
</resource>
- <resource type="Animation" path="local://4">
- <string name="resource/name"> "walk" </string>
- <real name="length"> 1.25 </real>
- <bool name="loop"> True </bool>
- <real name="step"> 0.25 </real>
- <string name="tracks/0/type"> "value" </string>
- <node_path name="tracks/0/path"> "sprite:frame" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <dictionary name="tracks/0/keys" shared="false">
- <string> "cont" </string>
- <bool> False </bool>
- <string> "times" </string>
- <real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
- <string> "transitions" </string>
- <real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array>
- <string> "values" </string>
- <array len="6" shared="false">
- <int> 0 </int>
- <int> 1 </int>
- <int> 2 </int>
- <int> 3 </int>
- <int> 4 </int>
- <int> 0 </int>
- </array>
- </dictionary>
-
- </resource>
<resource type="Animation" path="local://3">
<string name="resource/name"> "explode" </string>
<real name="length"> 6 </real>
@@ -147,27 +120,54 @@
</dictionary>
</resource>
+ <resource type="Animation" path="local://4">
+ <string name="resource/name"> "walk" </string>
+ <real name="length"> 1.25 </real>
+ <bool name="loop"> True </bool>
+ <real name="step"> 0.25 </real>
+ <string name="tracks/0/type"> "value" </string>
+ <node_path name="tracks/0/path"> "sprite:frame" </node_path>
+ <int name="tracks/0/interp"> 1 </int>
+ <dictionary name="tracks/0/keys" shared="false">
+ <string> "cont" </string>
+ <bool> False </bool>
+ <string> "times" </string>
+ <real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
+ <string> "transitions" </string>
+ <real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array>
+ <string> "values" </string>
+ <array len="6" shared="false">
+ <int> 0 </int>
+ <int> 1 </int>
+ <int> 2 </int>
+ <int> 3 </int>
+ <int> 4 </int>
+ <int> 0 </int>
+ </array>
+ </dictionary>
+
+ </resource>
<resource type="ColorRamp" path="local://6">
<real_array name="offsets" len="2"> 0, 1 </real_array>
<color_array name="colors" len="2"> 1, 0.884956, 0.823009, 1, 0.768627, 0.389381, 0, 0 </color_array>
</resource>
<resource type="SampleLibrary" path="local://5">
- <dictionary name="samples/explode" shared="false">
+ <dictionary name="samples/hit" shared="false">
<string> "db" </string>
<real> 0 </real>
<string> "pitch" </string>
<real> 1 </real>
<string> "sample" </string>
- <resource external="3"> </resource>
+ <resource external="4"> </resource>
</dictionary>
- <dictionary name="samples/hit" shared="false">
+ <dictionary name="samples/explode" shared="false">
<string> "db" </string>
<real> 0 </real>
<string> "pitch" </string>
<real> 1 </real>
<string> "sample" </string>
- <resource external="4"> </resource>
+ <resource external="3"> </resource>
</dictionary>
</resource>
@@ -177,10 +177,12 @@
<int> 0 </int>
<string> "conns" </string>
<int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="107">
+ <string_array len="108">
<string> "enemy" </string>
- <string> "RigidBody2D" </string>
<string> "input/pickable" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
@@ -210,8 +212,8 @@
<string> "damp_override/angular" </string>
<string> "script/script" </string>
<string> "__meta__" </string>
+ <string> "RigidBody2D" </string>
<string> "enabler" </string>
- <string> "VisibilityEnabler2D" </string>
<string> "transform/pos" </string>
<string> "transform/scale" </string>
<string> "rect" </string>
@@ -220,23 +222,24 @@
<string> "enabler/pause_particles" </string>
<string> "enabler/process_parent" </string>
<string> "enabler/fixed_process_parent" </string>
+ <string> "VisibilityEnabler2D" </string>
<string> "anim" </string>
- <string> "AnimationPlayer" </string>
<string> "playback/process_mode" </string>
<string> "playback/default_blend_time" </string>
<string> "root/root" </string>
<string> "anims/idle" </string>
- <string> "anims/walk" </string>
<string> "anims/explode" </string>
+ <string> "anims/walk" </string>
<string> "playback/active" </string>
<string> "playback/speed" </string>
<string> "blend_times" </string>
<string> "autoplay" </string>
+ <string> "AnimationPlayer" </string>
<string> "sprite" </string>
- <string> "Sprite" </string>
<string> "texture" </string>
<string> "hframes" </string>
<string> "frame" </string>
+ <string> "Sprite" </string>
<string> "CollisionShape2D" </string>
<string> "shape" </string>
<string> "trigger" </string>
@@ -244,10 +247,11 @@
<string> "CollisionShape2D 2" </string>
<string> "CollisionShape2D 3" </string>
<string> "raycast_left" </string>
- <string> "RayCast2D" </string>
<string> "enabled" </string>
<string> "cast_to" </string>
<string> "layer_mask" </string>
+ <string> "type_mask" </string>
+ <string> "RayCast2D" </string>
<string> "raycast_right" </string>
<string> "Particles2D" </string>
<string> "visibility/self_opacity" </string>
@@ -277,7 +281,6 @@
<string> "randomness/spin_velocity" </string>
<string> "color/color_ramp" </string>
<string> "sound" </string>
- <string> "SamplePlayer2D" </string>
<string> "params/volume_db" </string>
<string> "params/pitch_scale" </string>
<string> "params/attenuation/min_distance" </string>
@@ -286,13 +289,17 @@
<string> "config/polyphony" </string>
<string> "config/samples" </string>
<string> "config/pitch_random" </string>
+ <string> "SamplePlayer2D" </string>
</string_array>
<string> "node_count" </string>
<int> 11 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
<string> "nodes" </string>
- <int_array len="285"> -1, -1, 1, 0, -1, 29, 2, 0, 3, 1, 4, 2, 5, 0, 6, 1, 7, 3, 8, 0, 9, 1, 10, 4, 11, 0, 12, 5, 13, 5, 14, 6, 15, 7, 16, 8, 17, 8, 18, 7, 19, 0, 20, 9, 21, 10, 22, 0, 23, 0, 24, 11, 25, 12, 26, 8, 27, 13, 28, 13, 29, 14, 30, 15, 0, 0, 0, 32, 31, -1, 8, 33, 16, 34, 17, 35, 18, 36, 11, 37, 11, 38, 11, 39, 0, 40, 0, 0, 0, 0, 42, 41, -1, 10, 43, 5, 44, 8, 45, 19, 46, 20, 47, 21, 48, 22, 49, 11, 50, 23, 51, 24, 52, 25, 0, 0, 0, 54, 53, -1, 3, 55, 26, 56, 27, 57, 10, 0, 0, 0, 58, 58, -1, 4, 33, 28, 59, 1, 60, 0, 61, 29, 0, 0, 0, 58, 62, -1, 4, 33, 30, 59, 1, 60, 0, 61, 29, 0, 0, 0, 58, 63, -1, 4, 33, 31, 59, 1, 60, 0, 61, 29, 0, 0, 0, 65, 64, -1, 4, 33, 32, 66, 11, 67, 33, 68, 5, 0, 0, 0, 65, 69, -1, 4, 33, 34, 66, 11, 67, 33, 68, 5, 0, 0, 0, 70, 70, -1, 26, 71, 35, 72, 5, 73, 36, 74, 37, 75, 37, 76, 0, 77, 38, 78, 39, 79, 8, 80, 40, 81, 41, 82, 42, 83, 8, 84, 8, 85, 43, 86, 8, 87, 8, 88, 8, 89, 8, 90, 42, 91, 23, 92, 8, 93, 7, 94, 8, 95, 7, 96, 44, 0, 0, 0, 98, 97, -1, 8, 99, 8, 100, 7, 101, 7, 102, 45, 103, 7, 104, 46, 105, 47, 106, 8, 0 </int_array>
+ <int_array len="289"> -1, -1, 30, 0, -1, 29, 1, 0, 2, 1, 3, 2, 4, 0, 5, 1, 6, 3, 7, 0, 8, 1, 9, 4, 10, 0, 11, 5, 12, 5, 13, 6, 14, 7, 15, 8, 16, 8, 17, 7, 18, 0, 19, 9, 20, 10, 21, 0, 22, 0, 23, 11, 24, 12, 25, 8, 26, 13, 27, 13, 28, 14, 29, 15, 0, 0, 0, 40, 31, -1, 8, 32, 16, 33, 17, 34, 18, 35, 11, 36, 11, 37, 11, 38, 0, 39, 0, 0, 0, 0, 52, 41, -1, 10, 42, 5, 43, 8, 44, 19, 45, 20, 46, 21, 47, 22, 48, 11, 49, 23, 50, 24, 51, 25, 0, 0, 0, 57, 53, -1, 3, 54, 26, 55, 27, 56, 10, 0, 0, 0, 58, 58, -1, 4, 32, 28, 59, 1, 60, 0, 61, 29, 0, 0, 0, 58, 62, -1, 4, 32, 30, 59, 1, 60, 0, 61, 29, 0, 0, 0, 58, 63, -1, 4, 32, 31, 59, 1, 60, 0, 61, 29, 0, 0, 0, 69, 64, -1, 5, 32, 32, 65, 11, 66, 33, 67, 5, 68, 34, 0, 0, 0, 69, 70, -1, 5, 32, 35, 65, 11, 66, 33, 67, 5, 68, 34, 0, 0, 0, 71, 71, -1, 26, 72, 36, 73, 5, 74, 37, 75, 38, 76, 38, 77, 0, 78, 39, 79, 40, 80, 8, 81, 41, 82, 42, 83, 43, 84, 8, 85, 8, 86, 44, 87, 8, 88, 8, 89, 8, 90, 8, 91, 43, 92, 23, 93, 8, 94, 7, 95, 8, 96, 7, 97, 45, 0, 0, 0, 107, 98, -1, 8, 99, 8, 100, 7, 101, 7, 102, 46, 103, 7, 104, 47, 105, 48, 106, 8, 0 </int_array>
<string> "variants" </string>
- <array len="48" shared="false">
+ <array len="49" shared="false">
<bool> False </bool>
<resource resource_type="Shape2D" path="local://1"> </resource>
<matrix32> 1, -0, 0, 1, -1.08072, -2.16144 </matrix32>
@@ -449,8 +456,8 @@
<rect2> -10, -10, 20, 20 </rect2>
<node_path> ".." </node_path>
<resource resource_type="Animation" path="local://2"> </resource>
- <resource resource_type="Animation" path="local://4"> </resource>
<resource resource_type="Animation" path="local://3"> </resource>
+ <resource resource_type="Animation" path="local://4"> </resource>
<real> 3 </real>
<array len="0" shared="false">
</array>
@@ -463,6 +470,7 @@
<vector2> -12.495, 3.53415 </vector2>
<vector2> -33.2868, -9.34363 </vector2>
<vector2> 0, 45 </vector2>
+ <int> 15 </int>
<vector2> 29.1987, -9.34363 </vector2>
<real> 0.121212 </real>
<int> 32 </int>
@@ -479,7 +487,7 @@
<resource resource_type="SampleLibrary" path="local://5"> </resource>
</array>
<string> "version" </string>
- <int> 1 </int>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/platformer/moving_platform.gd b/demos/2d/platformer/moving_platform.gd
index 719d9e460e..21c312d5c3 100644
--- a/demos/2d/platformer/moving_platform.gd
+++ b/demos/2d/platformer/moving_platform.gd
@@ -1,27 +1,20 @@
extends Node2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
+# Member variables
export var motion = Vector2()
export var cycle = 1.0
-var accum=0.0
+var accum = 0.0
-func _fixed_process(delta):
- accum += delta * (1.0/cycle) * PI * 2.0
- accum = fmod(accum,PI*2.0)
+func _fixed_process(delta):
+ accum += delta*(1.0/cycle)*PI*2.0
+ accum = fmod(accum, PI*2.0)
var d = sin(accum)
var xf = Matrix32()
- xf[2]= motion * d
+ xf[2]= motion*d
get_node("platform").set_transform(xf)
-
+
func _ready():
- # Initalization here
set_fixed_process(true)
- pass
-
-
diff --git a/demos/2d/platformer/moving_platform.xml b/demos/2d/platformer/moving_platform.xml
index 4d54d6d11c..4b94a7af48 100644
--- a/demos/2d/platformer/moving_platform.xml
+++ b/demos/2d/platformer/moving_platform.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="4" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
- <ext_resource path="res://moving_platform.*" type="Texture"></ext_resource>
- <ext_resource path="res://moving_platform.*" type="Script"></ext_resource>
+<resource_file type="PackedScene" subresource_count="4" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://moving_platform.png" type="Texture" index="1"></ext_resource>
+ <ext_resource path="res://moving_platform.gd" type="Script" index="0"></ext_resource>
<resource type="ConvexPolygonShape2D" path="local://1">
<real name="custom_solver_bias"> 0 </real>
<vector2_array name="points" len="4"> -88, 24, -88, -24, 88, -24, 88, 24 </vector2_array>
@@ -9,169 +9,189 @@
</resource>
<main_resource>
<dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="46">
+ <string_array len="36">
<string> "moving_platform" </string>
- <string> "Node2D" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
<string> "script/script" </string>
<string> "__meta__" </string>
<string> "motion" </string>
<string> "cycle" </string>
+ <string> "Node2D" </string>
<string> "platform" </string>
- <string> "RigidBody2D" </string>
- <string> "shape_count" </string>
+ <string> "input/pickable" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
<string> "shapes/0/trigger" </string>
+ <string> "collision/layers" </string>
+ <string> "collision/mask" </string>
<string> "mode" </string>
<string> "mass" </string>
<string> "friction" </string>
<string> "bounce" </string>
+ <string> "gravity_scale" </string>
<string> "custom_integrator" </string>
<string> "continuous_cd" </string>
<string> "contacts_reported" </string>
<string> "contact_monitor" </string>
- <string> "active" </string>
+ <string> "sleeping" </string>
<string> "can_sleep" </string>
<string> "velocity/linear" </string>
<string> "velocity/angular" </string>
+ <string> "damp_override/linear" </string>
+ <string> "damp_override/angular" </string>
+ <string> "RigidBody2D" </string>
<string> "Sprite" </string>
<string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
<string> "CollisionPolygon2D" </string>
<string> "build_mode" </string>
<string> "polygon" </string>
+ <string> "shape_range" </string>
+ <string> "trigger" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
<string> "node_count" </string>
<int> 4 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="88"> -1, -1, 5, 0, -1, 4, 1, 0, 2, 1, 3, 2, 4, 3, 0, 0, 0, 28, 6, -1, 21, 7, 4, 8, 5, 9, 6, 10, 4, 11, 7, 12, 7, 13, 8, 14, 3, 15, 3, 16, 9, 17, 3, 18, 4, 19, 10, 20, 10, 21, 4, 22, 4, 23, 11, 24, 2, 25, 9, 26, 12, 27, 12, 0, 1, 0, 29, 29, -1, 1, 30, 13, 0, 1, 0, 31, 31, -1, 4, 32, 10, 33, 14, 34, 15, 35, 4, 0 </int_array>
<string> "variants" </string>
- <array len="17" shared="false">
- <bool> True </bool>
- <real> 1 </real>
- <vector2> 0, 0 </vector2>
- <real> 0 </real>
- <vector2> 1, 1 </vector2>
- <resource resource_type="Script" path="res://moving_platform.*"> </resource>
+ <array len="16" shared="false">
+ <resource external="0"> </resource>
<dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
<dictionary shared="false">
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 0 </int>
- <string> "sources" </string>
- <array len="4" shared="false">
- <string> "res://moving_platform.gd" </string>
- <string> "res://enemy.gd" </string>
- <string> "res://player.gd" </string>
- <string> "res://coin.gd" </string>
- </array>
- </dictionary>
<string> "2D" </string>
<dictionary shared="false">
- <string> "pixel_snap" </string>
+ <string> "ofs" </string>
+ <vector2> -210.652, -172.81 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
<bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
<string> "zoom" </string>
<real> 1.360373 </real>
- <string> "ofs" </string>
- <vector2> -210.652, -172.81 </vector2>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
- <real> 400 </real>
+ <real> 179 </real>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
<string> "viewports" </string>
<array len="4" shared="false">
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
</array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -180,24 +200,24 @@
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
- <int> 1 </int>
+ <vector2> 0, 0 </vector2>
+ <real> 1 </real>
+ <bool> False </bool>
<resource resource_type="Shape2D" path="local://1"> </resource>
<matrix32> 1, -0, 0, 1, 0, 0 </matrix32>
- <bool> False </bool>
+ <int> 1 </int>
<int> 3 </int>
+ <real> 0 </real>
<int> 0 </int>
- <resource resource_type="Texture" path="res://moving_platform.*"> </resource>
- <color> 1, 1, 1, 1 </color>
- <rect2> 0, 0, 0, 0 </rect2>
+ <bool> True </bool>
+ <real> -1 </real>
+ <resource external="1"> </resource>
<vector2_array len="4"> -88, -24, 88, -24, 88, 24, -88, 24 </vector2_array>
+ <vector2> -1, -1 </vector2>
</array>
- <string> "nodes" </string>
- <int_array len="150"> -1, -1, 1, 0, -1, 11, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 2, 12, 1, 0, 0, 0, 14, 13, -1, 23, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 15, 7, 16, 8, 17, 9, 18, 10, 19, 11, 20, 1, 21, 1, 22, 3, 23, 10, 24, 10, 25, 12, 26, 10, 27, 0, 28, 0, 29, 2, 30, 3, 0, 1, 0, 31, 31, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 32, 13, 33, 0, 34, 2, 35, 10, 36, 10, 37, 7, 38, 7, 39, 12, 40, 14, 41, 10, 42, 15, 0, 1, 0, 43, 43, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 44, 12, 45, 16, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/platformer/one_way_platform.xml b/demos/2d/platformer/one_way_platform.xml
index 491dd32b17..85b2322711 100644
--- a/demos/2d/platformer/one_way_platform.xml
+++ b/demos/2d/platformer/one_way_platform.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="3" version="1.1" version_name="Godot Engine v1.1.rc1.custom_build">
- <ext_resource path="res://one_way_platform.png" type="Texture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="3" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://one_way_platform.png" type="Texture" index="0"></ext_resource>
<resource type="RectangleShape2D" path="local://1">
<real name="custom_solver_bias"> 0 </real>
<vector2 name="extents"> 100, 10 </vector2>
@@ -12,22 +12,13 @@
<int> 0 </int>
<string> "conns" </string>
<int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="42">
+ <string_array len="23">
<string> "one_way_platform" </string>
- <string> "StaticBody2D" </string>
- <string> "_import_path" </string>
- <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>
- <string> "z/z" </string>
- <string> "z/relative" </string>
<string> "input/pickable" </string>
- <string> "shape_count" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
<string> "shapes/0/trigger" </string>
@@ -40,42 +31,34 @@
<string> "friction" </string>
<string> "bounce" </string>
<string> "__meta__" </string>
+ <string> "StaticBody2D" </string>
<string> "sprite" </string>
- <string> "Sprite" </string>
<string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
+ <string> "Sprite" </string>
<string> "CollisionShape2D" </string>
+ <string> "transform/pos" </string>
<string> "shape" </string>
<string> "trigger" </string>
+ <string> "_update_shape_index" </string>
</string_array>
<string> "node_count" </string>
<int> 3 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
<string> "nodes" </string>
- <int_array len="135"> -1, -1, 1, 0, -1, 24, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11, 1, 12, 8, 13, 3, 14, 9, 15, 10, 16, 8, 17, 3, 18, 3, 19, 11, 20, 12, 21, 4, 22, 5, 23, 2, 24, 5, 25, 13, 0, 0, 0, 27, 26, -1, 21, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11, 1, 28, 14, 29, 1, 30, 4, 31, 8, 32, 8, 33, 3, 34, 3, 35, 7, 36, 15, 37, 8, 38, 16, 0, 0, 0, 39, 39, -1, 12, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 17, 8, 5, 9, 6, 10, 7, 11, 1, 40, 9, 41, 8, 0 </int_array>
+ <int_array len="57"> -1, -1, 14, 0, -1, 13, 1, 0, 2, 1, 3, 2, 4, 0, 5, 3, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11, 8, 12, 7, 13, 9, 0, 0, 0, 17, 15, -1, 1, 16, 10, 0, 0, 0, 18, 18, -1, 4, 19, 11, 20, 1, 21, 0, 22, 12, 0 </int_array>
<string> "variants" </string>
- <array len="18" shared="false">
- <node_path> "" </node_path>
- <bool> True </bool>
- <real> 1 </real>
- <int> 1 </int>
- <vector2> 0, 0 </vector2>
- <real> 0 </real>
- <vector2> 1, 1 </vector2>
- <int> 0 </int>
+ <array len="13" shared="false">
<bool> False </bool>
<resource resource_type="Shape2D" path="local://1"> </resource>
<matrix32> 1, -0, 0, 1, 1.46304, -13.1672 </matrix32>
+ <int> 1 </int>
<vector2> 0, 1 </vector2>
<real> 20 </real>
+ <vector2> 0, 0 </vector2>
+ <real> 0 </real>
+ <real> 1 </real>
<dictionary shared="false">
<string> "__editor_plugin_screen__" </string>
<string> "2D" </string>
@@ -198,6 +181,11 @@
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -207,13 +195,12 @@
<int> 0 </int>
</dictionary>
</dictionary>
- <resource resource_type="Texture" path="res://one_way_platform.png"> </resource>
- <color> 1, 1, 1, 1 </color>
- <rect2> 0, 0, 0, 0 </rect2>
+ <resource external="0"> </resource>
<vector2> 1.46304, -13.1672 </vector2>
+ <int> -1 </int>
</array>
<string> "version" </string>
- <int> 1 </int>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/platformer/parallax_bg.xml b/demos/2d/platformer/parallax_bg.xml
index cc8cfe5de0..3b306aecab 100644
--- a/demos/2d/platformer/parallax_bg.xml
+++ b/demos/2d/platformer/parallax_bg.xml
@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="7" version="0.99" version_name="Godot Engine v0.99.3046-pre-beta">
- <ext_resource path="res://scroll_bg_sky.png" type="Texture"></ext_resource>
- <ext_resource path="res://scroll_bg_cloud_1.png" type="Texture"></ext_resource>
- <ext_resource path="res://scroll_bg_cloud_3.png" type="Texture"></ext_resource>
- <ext_resource path="res://scroll_bg_cloud_2.png" type="Texture"></ext_resource>
- <ext_resource path="res://scroll_bg_fg_1.png" type="Texture"></ext_resource>
- <ext_resource path="res://scroll_bg_fg_2.png" type="Texture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="7" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://scroll_bg_cloud_1.png" type="Texture" index="1"></ext_resource>
+ <ext_resource path="res://scroll_bg_sky.png" type="Texture" index="0"></ext_resource>
+ <ext_resource path="res://scroll_bg_fg_2.png" type="Texture" index="4"></ext_resource>
+ <ext_resource path="res://scroll_bg_cloud_3.png" type="Texture" index="3"></ext_resource>
+ <ext_resource path="res://scroll_bg_cloud_2.png" type="Texture" index="2"></ext_resource>
+ <ext_resource path="res://scroll_bg_fg_1.png" type="Texture" index="5"></ext_resource>
<main_resource>
- <string name="resource/name"> "" </string>
- <dictionary name="_bundled">
+ <dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="51">
+ <string_array len="32">
<string> "parallax_bg" </string>
- <string> "ParallaxBackground" </string>
- <string> "process/process" </string>
- <string> "process/fixed_process" </string>
- <string> "process/input" </string>
- <string> "process/unhandled_input" </string>
- <string> "process/mode" </string>
<string> "layer" </string>
<string> "offset" </string>
<string> "rotation" </string>
@@ -27,148 +27,204 @@
<string> "scroll/base_scale" </string>
<string> "scroll/limit_begin" </string>
<string> "scroll/limit_end" </string>
- <string> "script/script" </string>
+ <string> "scroll/ignore_camera_zoom" </string>
<string> "__meta__" </string>
+ <string> "ParallaxBackground" </string>
<string> "sky" </string>
- <string> "ParallaxLayer" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/toplevel" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "visibility/blend_mode" </string>
- <string> "transform/notify" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
<string> "motion/scale" </string>
<string> "motion/mirroring" </string>
+ <string> "ParallaxLayer" </string>
<string> "Sprite" </string>
+ <string> "transform/scale" </string>
<string> "texture" </string>
<string> "centered" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
<string> "clouds" </string>
+ <string> "transform/pos" </string>
<string> "Sprite 2" </string>
<string> "Sprite 3" </string>
<string> "Sprite 4" </string>
<string> "Sprite 5" </string>
<string> "Sprite 6" </string>
<string> "mount_ 2" </string>
+ <string> "region" </string>
+ <string> "region_rect" </string>
<string> "mount_1" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
<string> "node_count" </string>
<int> 14 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="198"> -1, -1, 12, 0, -1, 11, 1, 0, 2, 1, 3, 2, 4, 3, 5, 1, 6, 1, 7, 4, 8, 1, 9, 1, 10, 5, 11, 6, 0, 0, 0, 16, 13, -1, 2, 14, 3, 15, 7, 0, 1, 0, 17, 17, -1, 3, 18, 8, 19, 9, 20, 5, 0, 0, 0, 16, 21, -1, 2, 14, 10, 15, 7, 0, 3, 0, 17, 17, -1, 3, 22, 11, 19, 12, 20, 5, 0, 3, 0, 17, 23, -1, 3, 22, 13, 19, 12, 20, 5, 0, 3, 0, 17, 24, -1, 3, 22, 14, 19, 15, 20, 5, 0, 3, 0, 17, 25, -1, 3, 22, 16, 19, 15, 20, 5, 0, 3, 0, 17, 26, -1, 3, 22, 17, 19, 18, 20, 5, 0, 3, 0, 17, 27, -1, 3, 22, 19, 19, 18, 20, 5, 0, 0, 0, 16, 28, -1, 2, 14, 20, 15, 7, 0, 10, 0, 17, 17, -1, 5, 22, 21, 19, 22, 20, 5, 29, 23, 30, 24, 0, 0, 0, 16, 31, -1, 2, 14, 25, 15, 7, 0, 12, 0, 17, 17, -1, 5, 22, 21, 19, 26, 20, 5, 29, 23, 30, 24, 0 </int_array>
<string> "variants" </string>
- <array len="33">
- <bool> False </bool>
- <int> 0 </int>
+ <array len="27" shared="false">
<int> -1 </int>
<vector2> 0, 0 </vector2>
<real> 0 </real>
<vector2> 1, 1 </vector2>
<vector2> 0.7, 0 </vector2>
- <resource name=""></resource> <dictionary>
+ <bool> False </bool>
+ <dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
- <dictionary>
- <string> "Script" </string>
- <dictionary>
- <string> "current" </string>
- <int> 0 </int>
- <string> "sources" </string>
- <array len="4">
- <string> "res://moving_platform.gd" </string>
- <string> "res://enemy.gd" </string>
- <string> "res://player.gd" </string>
- <string> "res://coin.gd" </string>
- </array>
- </dictionary>
+ <dictionary shared="false">
<string> "2D" </string>
- <dictionary>
- <string> "zoom" </string>
- <real> 1 </real>
+ <dictionary shared="false">
<string> "ofs" </string>
<vector2> -5, -25 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
+ <string> "zoom" </string>
+ <real> 1 </real>
</dictionary>
<string> "3D" </string>
- <dictionary>
- <string> "zfar" </string>
- <real> 500 </real>
+ <dictionary shared="false">
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
- <string> "window_mode" </string>
- <int> 0 </int>
- <string> "window_0" </string>
- <dictionary>
- <string> "distance" </string>
- <real> 4 </real>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "x_rot" </string>
- <real> 0.337 </real>
- <string> "y_rot" </string>
- <real> -0.575 </real>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
+ <string> "viewports" </string>
+ <array len="4" shared="false">
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ </array>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
- <dictionary>
+ <dictionary shared="false">
<string> "custom_args" </string>
<string> "-l $scene" </string>
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
- <bool> True </bool>
- <real> 1 </real>
<vector2> 800, 0 </vector2>
<vector2> 32, 0.94 </vector2>
- <resource resource_type="Texture" path="res://scroll_bg_sky.png"> </resource>
- <int> 1 </int>
- <color> 1, 1, 1, 1 </color>
- <rect2> 0, 0, 0, 0 </rect2>
+ <resource external="0"> </resource>
<vector2> 0.1, 1 </vector2>
<vector2> 28, 127 </vector2>
- <resource resource_type="Texture" path="res://scroll_bg_cloud_1.png"> </resource>
+ <resource external="1"> </resource>
<vector2> 404, 24 </vector2>
<vector2> 154, 46 </vector2>
- <resource resource_type="Texture" path="res://scroll_bg_cloud_2.png"> </resource>
+ <resource external="2"> </resource>
<vector2> 525, 130 </vector2>
<vector2> 255, 158 </vector2>
- <resource resource_type="Texture" path="res://scroll_bg_cloud_3.png"> </resource>
+ <resource external="3"> </resource>
<vector2> 674, 70 </vector2>
<vector2> 0.2, 1 </vector2>
<vector2> 0, 225 </vector2>
- <resource resource_type="Texture" path="res://scroll_bg_fg_2.png"> </resource>
+ <resource external="4"> </resource>
+ <bool> True </bool>
<rect2> 0, 0, 800, 256 </rect2>
<vector2> 0.4, 1 </vector2>
- <resource resource_type="Texture" path="res://scroll_bg_fg_1.png"> </resource>
+ <resource external="5"> </resource>
</array>
- <string> "nodes" </string>
- <int_array len="760"> -1, -1, 1, 0, -1, 16, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 3, 9, 4, 10, 5, 11, 3, 12, 3, 13, 6, 14, 3, 15, 3, 16, 7, 17, 8, 0, 0, 0, 19, 18, -1, 18, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 20, 9, 21, 0, 22, 10, 23, 10, 24, 9, 25, 1, 26, 0, 27, 3, 28, 4, 29, 5, 30, 5, 31, 11, 16, 7, 0, 1, 0, 32, 32, -1, 27, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 20, 9, 21, 0, 22, 10, 23, 10, 24, 9, 25, 1, 26, 0, 27, 3, 28, 4, 29, 12, 33, 13, 34, 0, 8, 3, 35, 0, 36, 0, 37, 14, 38, 14, 39, 1, 40, 15, 41, 0, 42, 16, 16, 7, 0, 0, 0, 19, 43, -1, 18, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 20, 9, 21, 0, 22, 10, 23, 10, 24, 9, 25, 1, 26, 0, 27, 3, 28, 4, 29, 5, 30, 17, 31, 11, 16, 7, 0, 3, 0, 32, 32, -1, 27, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 20, 9, 21, 0, 22, 10, 23, 10, 24, 9, 25, 1, 26, 0, 27, 18, 28, 4, 29, 5, 33, 19, 34, 0, 8, 3, 35, 0, 36, 0, 37, 14, 38, 14, 39, 1, 40, 15, 41, 0, 42, 16, 16, 7, 0, 3, 0, 32, 44, -1, 27, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 20, 9, 21, 0, 22, 10, 23, 10, 24, 9, 25, 1, 26, 0, 27, 20, 28, 4, 29, 5, 33, 19, 34, 0, 8, 3, 35, 0, 36, 0, 37, 14, 38, 14, 39, 1, 40, 15, 41, 0, 42, 16, 16, 7, 0, 3, 0, 32, 45, -1, 27, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 20, 9, 21, 0, 22, 10, 23, 10, 24, 9, 25, 1, 26, 0, 27, 21, 28, 4, 29, 5, 33, 22, 34, 0, 8, 3, 35, 0, 36, 0, 37, 14, 38, 14, 39, 1, 40, 15, 41, 0, 42, 16, 16, 7, 0, 3, 0, 32, 46, -1, 27, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 20, 9, 21, 0, 22, 10, 23, 10, 24, 9, 25, 1, 26, 0, 27, 23, 28, 4, 29, 5, 33, 22, 34, 0, 8, 3, 35, 0, 36, 0, 37, 14, 38, 14, 39, 1, 40, 15, 41, 0, 42, 16, 16, 7, 0, 3, 0, 32, 47, -1, 27, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 20, 9, 21, 0, 22, 10, 23, 10, 24, 9, 25, 1, 26, 0, 27, 24, 28, 4, 29, 5, 33, 25, 34, 0, 8, 3, 35, 0, 36, 0, 37, 14, 38, 14, 39, 1, 40, 15, 41, 0, 42, 16, 16, 7, 0, 3, 0, 32, 48, -1, 27, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 20, 9, 21, 0, 22, 10, 23, 10, 24, 9, 25, 1, 26, 0, 27, 26, 28, 4, 29, 5, 33, 25, 34, 0, 8, 3, 35, 0, 36, 0, 37, 14, 38, 14, 39, 1, 40, 15, 41, 0, 42, 16, 16, 7, 0, 0, 0, 19, 49, -1, 18, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 20, 9, 21, 0, 22, 10, 23, 10, 24, 9, 25, 1, 26, 0, 27, 3, 28, 4, 29, 5, 30, 27, 31, 11, 16, 7, 0, 10, 0, 32, 32, -1, 27, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 20, 9, 21, 0, 22, 10, 23, 10, 24, 9, 25, 1, 26, 0, 27, 28, 28, 4, 29, 5, 33, 29, 34, 0, 8, 3, 35, 0, 36, 0, 37, 14, 38, 14, 39, 1, 40, 15, 41, 9, 42, 30, 16, 7, 0, 0, 0, 19, 50, -1, 18, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 20, 9, 21, 0, 22, 10, 23, 10, 24, 9, 25, 1, 26, 0, 27, 3, 28, 4, 29, 5, 30, 31, 31, 11, 16, 7, 0, 12, 0, 32, 32, -1, 27, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 20, 9, 21, 0, 22, 10, 23, 10, 24, 9, 25, 1, 26, 0, 27, 28, 28, 4, 29, 5, 33, 32, 34, 0, 8, 3, 35, 0, 36, 0, 37, 14, 38, 14, 39, 1, 40, 15, 41, 9, 42, 30, 16, 7, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
- <resource name="script/script"></resource>
+
</main_resource>
</resource_file> \ No newline at end of file
diff --git a/demos/2d/platformer/player.gd b/demos/2d/platformer/player.gd
index 9ee189df21..7ed99df9bd 100644
--- a/demos/2d/platformer/player.gd
+++ b/demos/2d/platformer/player.gd
@@ -1,3 +1,4 @@
+
extends RigidBody2D
# Character Demo, written by Juan Linietsky.
@@ -24,42 +25,40 @@ extends RigidBody2D
# -Friction cant be used, so floor velocity must be considered
# for moving platforms.
-var anim=""
-var siding_left=false
-var jumping=false
-var stopping_jump=false
-var shooting=false
+# Member variables
+var anim = ""
+var siding_left = false
+var jumping = false
+var stopping_jump = false
+var shooting = false
var WALK_ACCEL = 800.0
-var WALK_DEACCEL= 800.0
-var WALK_MAX_VELOCITY= 200.0
+var WALK_DEACCEL = 800.0
+var WALK_MAX_VELOCITY = 200.0
var AIR_ACCEL = 200.0
-var AIR_DEACCEL= 200.0
-var JUMP_VELOCITY=460
-var STOP_JUMP_FORCE=900.0
+var AIR_DEACCEL = 200.0
+var JUMP_VELOCITY = 460
+var STOP_JUMP_FORCE = 900.0
var MAX_FLOOR_AIRBORNE_TIME = 0.15
-var airborne_time=1e20
-var shoot_time=1e20
+var airborne_time = 1e20
+var shoot_time = 1e20
var MAX_SHOOT_POSE_TIME = 0.3
var bullet = preload("res://bullet.xml")
-var floor_h_velocity=0.0
+var floor_h_velocity = 0.0
var enemy
-func _integrate_forces(s):
-
-
+func _integrate_forces(s):
var lv = s.get_linear_velocity()
var step = s.get_step()
- var new_anim=anim
- var new_siding_left=siding_left
-
+ var new_anim = anim
+ var new_siding_left = siding_left
# Get the controls
var move_left = Input.is_action_pressed("move_left")
@@ -74,188 +73,160 @@ func _integrate_forces(s):
p.y = p.y - 100
e.set_pos(p)
get_parent().add_child(e)
-
-
- #deapply prev floor velocity
- lv.x-=floor_h_velocity
- floor_h_velocity=0.0
+ # Deapply prev floor velocity
+ lv.x -= floor_h_velocity
+ floor_h_velocity = 0.0
# Find the floor (a contact with upwards facing collision normal)
- var found_floor=false
- var floor_index=-1
+ var found_floor = false
+ var floor_index = -1
for x in range(s.get_contact_count()):
-
var ci = s.get_contact_local_normal(x)
- if (ci.dot(Vector2(0,-1))>0.6):
- found_floor=true
- floor_index=x
+ if (ci.dot(Vector2(0, -1)) > 0.6):
+ found_floor = true
+ floor_index = x
# A good idea when impementing characters of all kinds,
- # Compensates for physics imprecission, as well as human
- # reaction delay.
-
+ # compensates for physics imprecission, as well as human reaction delay.
if (shoot and not shooting):
- shoot_time=0
+ shoot_time = 0
var bi = bullet.instance()
var ss
if (siding_left):
- ss=-1.0
+ ss = -1.0
else:
- ss=1.0
- var pos = get_pos() + get_node("bullet_shoot").get_pos()*Vector2(ss,1.0)
-
+ ss = 1.0
+ var pos = get_pos() + get_node("bullet_shoot").get_pos()*Vector2(ss, 1.0)
+
bi.set_pos(pos)
get_parent().add_child(bi)
-
- bi.set_linear_velocity( Vector2(800.0*ss,-80) )
- get_node("sprite/smoke").set_emitting(true)
+
+ bi.set_linear_velocity(Vector2(800.0*ss, -80))
+ get_node("sprite/smoke").set_emitting(true)
get_node("sound").play("shoot")
- PS2D.body_add_collision_exception(bi.get_rid(),get_rid()) # make bullet and this not collide
-
-
+ PS2D.body_add_collision_exception(bi.get_rid(), get_rid()) # Make bullet and this not collide
else:
- shoot_time+=step
-
+ shoot_time += step
if (found_floor):
- airborne_time=0.0
+ airborne_time = 0.0
else:
- airborne_time+=step #time it spent in the air
-
+ airborne_time += step # Time it spent in the air
+
var on_floor = airborne_time < MAX_FLOOR_AIRBORNE_TIME
- # Process jump
+ # Process jump
if (jumping):
- if (lv.y>0):
- #set off the jumping flag if going down
- jumping=false
+ if (lv.y > 0):
+ # Set off the jumping flag if going down
+ jumping = false
elif (not jump):
- stopping_jump=true
-
- if (stopping_jump):
- lv.y+=STOP_JUMP_FORCE*step
+ stopping_jump = true
+ if (stopping_jump):
+ lv.y += STOP_JUMP_FORCE*step
+
if (on_floor):
-
# Process logic when character is on floor
-
if (move_left and not move_right):
if (lv.x > -WALK_MAX_VELOCITY):
- lv.x-=WALK_ACCEL*step
+ lv.x -= WALK_ACCEL*step
elif (move_right and not move_left):
if (lv.x < WALK_MAX_VELOCITY):
- lv.x+=WALK_ACCEL*step
+ lv.x += WALK_ACCEL*step
else:
var xv = abs(lv.x)
- xv-=WALK_DEACCEL*step
- if (xv<0):
- xv=0
- lv.x=sign(lv.x)*xv
-
- #Check jump
+ xv -= WALK_DEACCEL*step
+ if (xv < 0):
+ xv = 0
+ lv.x = sign(lv.x)*xv
+
+ # Check jump
if (not jumping and jump):
- lv.y=-JUMP_VELOCITY
- jumping=true
- stopping_jump=false
+ lv.y = -JUMP_VELOCITY
+ jumping = true
+ stopping_jump = false
get_node("sound").play("jump")
-
- #check siding
+ # Check siding
if (lv.x < 0 and move_left):
- new_siding_left=true
+ new_siding_left = true
elif (lv.x > 0 and move_right):
- new_siding_left=false
+ new_siding_left = false
if (jumping):
- new_anim="jumping"
- elif (abs(lv.x)<0.1):
- if (shoot_time<MAX_SHOOT_POSE_TIME):
- new_anim="idle_weapon"
+ new_anim = "jumping"
+ elif (abs(lv.x) < 0.1):
+ if (shoot_time < MAX_SHOOT_POSE_TIME):
+ new_anim = "idle_weapon"
else:
- new_anim="idle"
+ new_anim = "idle"
else:
- if (shoot_time<MAX_SHOOT_POSE_TIME):
- new_anim="run_weapon"
+ if (shoot_time < MAX_SHOOT_POSE_TIME):
+ new_anim = "run_weapon"
else:
- new_anim="run"
+ new_anim = "run"
else:
-
# Process logic when the character is in the air
-
if (move_left and not move_right):
if (lv.x > -WALK_MAX_VELOCITY):
- lv.x-=AIR_ACCEL*step
+ lv.x -= AIR_ACCEL*step
elif (move_right and not move_left):
if (lv.x < WALK_MAX_VELOCITY):
- lv.x+=AIR_ACCEL*step
+ lv.x += AIR_ACCEL*step
else:
var xv = abs(lv.x)
- xv-=AIR_DEACCEL*step
- if (xv<0):
- xv=0
- lv.x=sign(lv.x)*xv
-
- if (lv.y<0):
- if (shoot_time<MAX_SHOOT_POSE_TIME):
- new_anim="jumping_weapon"
+ xv -= AIR_DEACCEL*step
+ if (xv < 0):
+ xv = 0
+ lv.x = sign(lv.x)*xv
+
+ if (lv.y < 0):
+ if (shoot_time < MAX_SHOOT_POSE_TIME):
+ new_anim = "jumping_weapon"
else:
- new_anim="jumping"
+ new_anim = "jumping"
else:
- if (shoot_time<MAX_SHOOT_POSE_TIME):
- new_anim="falling_weapon"
+ if (shoot_time < MAX_SHOOT_POSE_TIME):
+ new_anim = "falling_weapon"
else:
- new_anim="falling"
-
-
- #Update siding
+ new_anim = "falling"
- if (new_siding_left!=siding_left):
+ # Update siding
+ if (new_siding_left != siding_left):
if (new_siding_left):
- get_node("sprite").set_scale( Vector2(-1,1) )
+ get_node("sprite").set_scale(Vector2(-1, 1))
else:
- get_node("sprite").set_scale( Vector2(1,1) )
-
- siding_left=new_siding_left
-
- #Change animation
- if (new_anim!=anim):
- anim=new_anim
- get_node("anim").play(anim)
-
- shooting=shoot
-
- # Apply floor velocity
- if (found_floor):
- floor_h_velocity=s.get_contact_collider_velocity_at_pos(floor_index).x
- lv.x+=floor_h_velocity
+ get_node("sprite").set_scale(Vector2(1, 1))
+ siding_left = new_siding_left
-
-
- #Finally, apply gravity and set back the linear velocity
- lv+=s.get_total_gravity()*step
- s.set_linear_velocity(lv)
-
+ # Change animation
+ if (new_anim != anim):
+ anim = new_anim
+ get_node("anim").play(anim)
-
+ shooting = shoot
+ # Apply floor velocity
+ if (found_floor):
+ floor_h_velocity = s.get_contact_collider_velocity_at_pos(floor_index).x
+ lv.x += floor_h_velocity
+ # Finally, apply gravity and set back the linear velocity
+ lv += s.get_total_gravity()*step
+ s.set_linear_velocity(lv)
func _ready():
- # Initalization here
-
+ enemy = ResourceLoader.load("res://enemy.xml")
+
# if !Globals.has_singleton("Facebook"):
-# return
+# return
# var Facebook = Globals.get_singleton("Facebook")
# var link = Globals.get("facebook/link")
# var icon = Globals.get("facebook/icon")
# var msg = "I just sneezed on your wall! Beat my score and Stop the Running nose!"
# var title = "I just sneezed on your wall!"
# Facebook.post("feed", msg, title, link, icon)
- enemy = ResourceLoader.load("res://enemy.xml")
- pass
-
-
-
diff --git a/demos/2d/platformer/player.xml b/demos/2d/platformer/player.xml
index 8c7b74ceae..493279672f 100644
--- a/demos/2d/platformer/player.xml
+++ b/demos/2d/platformer/player.xml
@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="25" version="1.1" version_name="Godot Engine v1.1.stable.custom_build">
- <ext_resource path="res://player.gd" type="Script"></ext_resource>
- <ext_resource path="res://robot_demo.png" type="Texture"></ext_resource>
- <ext_resource path="res://bullet.png" type="Texture"></ext_resource>
- <ext_resource path="res://sound_coin.wav" type="Sample"></ext_resource>
- <ext_resource path="res://sound_jump.wav" type="Sample"></ext_resource>
- <ext_resource path="res://sound_shoot.wav" type="Sample"></ext_resource>
- <ext_resource path="res://osb_left.png" type="Texture"></ext_resource>
- <ext_resource path="res://osb_right.png" type="Texture"></ext_resource>
- <ext_resource path="res://osb_jump.png" type="Texture"></ext_resource>
- <ext_resource path="res://osb_fire.png" type="Texture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="25" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://bullet.png" type="Texture" index="2"></ext_resource>
+ <ext_resource path="res://sound_coin.wav" type="Sample" index="3"></ext_resource>
+ <ext_resource path="res://player.gd" type="Script" index="0"></ext_resource>
+ <ext_resource path="res://robot_demo.png" type="Texture" index="1"></ext_resource>
+ <ext_resource path="res://sound_shoot.wav" type="Sample" index="5"></ext_resource>
+ <ext_resource path="res://sound_jump.wav" type="Sample" index="4"></ext_resource>
+ <ext_resource path="res://osb_left.png" type="Texture" index="6"></ext_resource>
+ <ext_resource path="res://osb_right.png" type="Texture" index="7"></ext_resource>
+ <ext_resource path="res://osb_jump.png" type="Texture" index="8"></ext_resource>
+ <ext_resource path="res://osb_fire.png" type="Texture" index="9"></ext_resource>
<resource type="RayShape2D" path="local://1">
<real name="custom_solver_bias"> 0.5 </real>
<real name="length"> 20 </real>
@@ -78,8 +78,8 @@
</dictionary>
</resource>
- <resource type="Animation" path="local://5">
- <string name="resource/name"> "idle_weapon" </string>
+ <resource type="Animation" path="local://10">
+ <string name="resource/name"> "falling_weapon" </string>
<real name="length"> 0.5 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
@@ -95,13 +95,14 @@
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
- <int> 25 </int>
+ <int> 26 </int>
</array>
</dictionary>
</resource>
- <resource type="Animation" path="local://6">
- <real name="length"> 1.25 </real>
+ <resource type="Animation" path="local://5">
+ <string name="resource/name"> "idle_weapon" </string>
+ <real name="length"> 0.5 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
@@ -111,23 +112,19 @@
<string> "cont" </string>
<bool> False </bool>
<string> "times" </string>
- <real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
+ <real_array len="1"> 0 </real_array>
<string> "transitions" </string>
- <real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array>
+ <real_array len="1"> 1 </real_array>
<string> "values" </string>
- <array len="6" shared="false">
- <int> 0 </int>
- <int> 1 </int>
- <int> 2 </int>
- <int> 3 </int>
- <int> 4 </int>
- <int> 0 </int>
+ <array len="1" shared="false">
+ <int> 25 </int>
</array>
</dictionary>
</resource>
- <resource type="Animation" path="local://11">
- <real name="length"> 1.25 </real>
+ <resource type="Animation" path="local://7">
+ <string name="resource/name"> "crouch" </string>
+ <real name="length"> 0.01 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
@@ -137,24 +134,19 @@
<string> "cont" </string>
<bool> False </bool>
<string> "times" </string>
- <real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
+ <real_array len="1"> 0 </real_array>
<string> "transitions" </string>
- <real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array>
+ <real_array len="1"> 1 </real_array>
<string> "values" </string>
- <array len="6" shared="false">
- <int> 5 </int>
- <int> 6 </int>
- <int> 7 </int>
- <int> 8 </int>
- <int> 9 </int>
- <int> 5 </int>
+ <array len="1" shared="false">
+ <int> 22 </int>
</array>
</dictionary>
</resource>
- <resource type="Animation" path="local://10">
- <string name="resource/name"> "falling_weapon" </string>
- <real name="length"> 0.5 </real>
+ <resource type="Animation" path="local://8">
+ <string name="resource/name"> "falling" </string>
+ <real name="length"> 0.01 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
@@ -169,14 +161,13 @@
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
- <int> 26 </int>
+ <int> 21 </int>
</array>
</dictionary>
</resource>
- <resource type="Animation" path="local://7">
- <string name="resource/name"> "crouch" </string>
- <real name="length"> 0.01 </real>
+ <resource type="Animation" path="local://9">
+ <real name="length"> 1.25 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
@@ -186,19 +177,23 @@
<string> "cont" </string>
<bool> False </bool>
<string> "times" </string>
- <real_array len="1"> 0 </real_array>
+ <real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
<string> "transitions" </string>
- <real_array len="1"> 1 </real_array>
+ <real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array>
<string> "values" </string>
- <array len="1" shared="false">
- <int> 22 </int>
+ <array len="6" shared="false">
+ <int> 10 </int>
+ <int> 11 </int>
+ <int> 12 </int>
+ <int> 13 </int>
+ <int> 14 </int>
+ <int> 5 </int>
</array>
</dictionary>
</resource>
- <resource type="Animation" path="local://8">
- <string name="resource/name"> "falling" </string>
- <real name="length"> 0.01 </real>
+ <resource type="Animation" path="local://12">
+ <real name="length"> 0.5 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
@@ -213,12 +208,12 @@
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
- <int> 21 </int>
+ <int> 26 </int>
</array>
</dictionary>
</resource>
- <resource type="Animation" path="local://9">
+ <resource type="Animation" path="local://6">
<real name="length"> 1.25 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
@@ -234,18 +229,18 @@
<real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array>
<string> "values" </string>
<array len="6" shared="false">
- <int> 10 </int>
- <int> 11 </int>
- <int> 12 </int>
- <int> 13 </int>
- <int> 14 </int>
- <int> 5 </int>
+ <int> 0 </int>
+ <int> 1 </int>
+ <int> 2 </int>
+ <int> 3 </int>
+ <int> 4 </int>
+ <int> 0 </int>
</array>
</dictionary>
</resource>
- <resource type="Animation" path="local://12">
- <real name="length"> 0.5 </real>
+ <resource type="Animation" path="local://11">
+ <real name="length"> 1.25 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
@@ -255,12 +250,17 @@
<string> "cont" </string>
<bool> False </bool>
<string> "times" </string>
- <real_array len="1"> 0 </real_array>
+ <real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
<string> "transitions" </string>
- <real_array len="1"> 1 </real_array>
+ <real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array>
<string> "values" </string>
- <array len="1" shared="false">
- <int> 26 </int>
+ <array len="6" shared="false">
+ <int> 5 </int>
+ <int> 6 </int>
+ <int> 7 </int>
+ <int> 8 </int>
+ <int> 9 </int>
+ <int> 5 </int>
</array>
</dictionary>
@@ -272,7 +272,7 @@
<string> "pitch" </string>
<real> 1 </real>
<string> "sample" </string>
- <resource resource_type="Sample" path="res://sound_jump.wav"> </resource>
+ <resource external="4"> </resource>
</dictionary>
<dictionary name="samples/shoot" shared="false">
<string> "db" </string>
@@ -280,7 +280,7 @@
<string> "pitch" </string>
<real> 1 </real>
<string> "sample" </string>
- <resource resource_type="Sample" path="res://sound_shoot.wav"> </resource>
+ <resource external="5"> </resource>
</dictionary>
<dictionary name="samples/coin" shared="false">
<string> "db" </string>
@@ -288,7 +288,7 @@
<string> "pitch" </string>
<real> 1 </real>
<string> "sample" </string>
- <resource resource_type="Sample" path="res://sound_coin.wav"> </resource>
+ <resource external="3"> </resource>
</dictionary>
</resource>
@@ -298,10 +298,12 @@
<int> 0 </int>
<string> "conns" </string>
<int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="142">
+ <string_array len="144">
<string> "player" </string>
- <string> "RigidBody2D" </string>
<string> "input/pickable" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
@@ -328,13 +330,13 @@
<string> "damp_override/angular" </string>
<string> "script/script" </string>
<string> "__meta__" </string>
+ <string> "RigidBody2D" </string>
<string> "sprite" </string>
- <string> "Sprite" </string>
<string> "texture" </string>
<string> "vframes" </string>
<string> "hframes" </string>
+ <string> "Sprite" </string>
<string> "smoke" </string>
- <string> "Particles2D" </string>
<string> "visibility/self_opacity" </string>
<string> "visibility/blend_mode" </string>
<string> "transform/pos" </string>
@@ -364,27 +366,27 @@
<string> "params/anim_initial_pos" </string>
<string> "randomness/spin_velocity" </string>
<string> "color/color_ramp" </string>
+ <string> "Particles2D" </string>
<string> "anim" </string>
- <string> "AnimationPlayer" </string>
<string> "playback/process_mode" </string>
<string> "playback/default_blend_time" </string>
<string> "root/root" </string>
<string> "anims/idle" </string>
<string> "anims/jumping" </string>
- <string> "anims/idle_weapon" </string>
- <string> "anims/run" </string>
- <string> "anims/run_weapon" </string>
<string> "anims/falling_weapon" </string>
+ <string> "anims/idle_weapon" </string>
<string> "anims/crouch" </string>
<string> "anims/falling" </string>
<string> "anims/standing_weapon_ready" </string>
<string> "anims/jumping_weapon" </string>
+ <string> "anims/run" </string>
+ <string> "anims/run_weapon" </string>
<string> "playback/active" </string>
<string> "playback/speed" </string>
<string> "blend_times" </string>
<string> "autoplay" </string>
+ <string> "AnimationPlayer" </string>
<string> "camera" </string>
- <string> "Camera2D" </string>
<string> "anchor_mode" </string>
<string> "rotating" </string>
<string> "current" </string>
@@ -400,15 +402,16 @@
<string> "drag_margin/top" </string>
<string> "drag_margin/right" </string>
<string> "drag_margin/bottom" </string>
+ <string> "Camera2D" </string>
<string> "bullet_shoot" </string>
<string> "Position2D" </string>
<string> "CollisionShape2D" </string>
<string> "transform/scale" </string>
<string> "shape" </string>
<string> "trigger" </string>
+ <string> "_update_shape_index" </string>
<string> "sound" </string>
- <string> "SamplePlayer" </string>
- <string> "config/voices" </string>
+ <string> "config/polyphony" </string>
<string> "config/samples" </string>
<string> "default/volume_db" </string>
<string> "default/pitch_scale" </string>
@@ -422,33 +425,38 @@
<string> "default/reverb_room" </string>
<string> "default/reverb_send" </string>
<string> "default/chorus_send" </string>
+ <string> "SamplePlayer" </string>
<string> "CollisionPolygon2D" </string>
<string> "build_mode" </string>
<string> "polygon" </string>
+ <string> "shape_range" </string>
<string> "ui" </string>
- <string> "CanvasLayer" </string>
<string> "layer" </string>
<string> "offset" </string>
<string> "rotation" </string>
<string> "scale" </string>
+ <string> "CanvasLayer" </string>
<string> "left" </string>
- <string> "TouchScreenButton" </string>
<string> "normal" </string>
<string> "pressed" </string>
<string> "bitmask" </string>
<string> "passby_press" </string>
<string> "action" </string>
<string> "visibility_mode" </string>
+ <string> "TouchScreenButton" </string>
<string> "right" </string>
<string> "jump" </string>
<string> "fire" </string>
</string_array>
<string> "node_count" </string>
<int> 14 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
<string> "nodes" </string>
- <int_array len="394"> -1, -1, 1, 0, -1, 26, 2, 0, 3, 1, 4, 2, 5, 0, 6, 3, 7, 4, 8, 0, 9, 5, 10, 5, 11, 6, 12, 7, 13, 8, 14, 8, 15, 9, 16, 10, 17, 11, 18, 12, 19, 0, 20, 0, 21, 10, 22, 13, 23, 8, 24, 14, 25, 14, 26, 15, 27, 16, 0, 0, 0, 29, 28, -1, 3, 30, 17, 31, 6, 32, 18, 0, 1, 0, 34, 33, -1, 29, 35, 19, 36, 5, 37, 20, 38, 21, 39, 22, 40, 23, 41, 23, 42, 0, 43, 0, 44, 24, 45, 25, 46, 8, 47, 26, 48, 27, 49, 9, 50, 8, 51, 8, 52, 28, 53, 8, 54, 8, 55, 8, 56, 8, 57, 29, 58, 29, 59, 8, 60, 9, 61, 8, 62, 29, 63, 30, 0, 0, 0, 65, 64, -1, 17, 66, 5, 67, 8, 68, 31, 69, 32, 70, 33, 71, 34, 72, 35, 73, 36, 74, 37, 75, 38, 76, 39, 77, 40, 78, 41, 79, 10, 80, 29, 81, 42, 82, 43, 0, 0, 0, 84, 83, -1, 15, 85, 5, 86, 0, 87, 10, 88, 8, 89, 44, 90, 11, 91, 11, 92, 45, 93, 45, 94, 10, 95, 10, 96, 46, 97, 46, 98, 46, 99, 46, 0, 0, 0, 101, 100, -1, 1, 37, 47, 0, 0, 0, 102, 102, -1, 4, 37, 48, 103, 49, 104, 1, 105, 0, 0, 0, 0, 107, 106, -1, 14, 108, 12, 109, 50, 110, 8, 111, 9, 112, 8, 113, 8, 114, 8, 115, 51, 116, 51, 117, 51, 118, 51, 119, 6, 120, 8, 121, 8, 0, 0, 0, 122, 122, -1, 3, 123, 11, 124, 52, 105, 0, 0, 0, 0, 126, 125, -1, 4, 127, 11, 128, 13, 129, 8, 130, 44, 0, 9, 0, 132, 131, -1, 8, 37, 53, 103, 54, 133, 55, 134, 56, 135, 56, 136, 10, 137, 57, 138, 5, 0, 9, 0, 132, 139, -1, 8, 37, 58, 103, 54, 133, 59, 134, 56, 135, 56, 136, 10, 137, 60, 138, 5, 0, 9, 0, 132, 140, -1, 8, 37, 61, 103, 54, 133, 62, 134, 56, 135, 56, 136, 0, 137, 63, 138, 5, 0, 9, 0, 132, 141, -1, 8, 37, 64, 103, 54, 133, 65, 134, 56, 135, 56, 136, 0, 137, 66, 138, 5, 0 </int_array>
+ <int_array len="398"> -1, -1, 27, 0, -1, 26, 1, 0, 2, 1, 3, 2, 4, 0, 5, 3, 6, 4, 7, 0, 8, 5, 9, 5, 10, 6, 11, 7, 12, 8, 13, 8, 14, 9, 15, 10, 16, 11, 17, 12, 18, 0, 19, 0, 20, 10, 21, 13, 22, 8, 23, 14, 24, 14, 25, 15, 26, 16, 0, 0, 0, 32, 28, -1, 3, 29, 17, 30, 6, 31, 18, 0, 1, 0, 63, 33, -1, 29, 34, 19, 35, 5, 36, 20, 37, 21, 38, 22, 39, 23, 40, 23, 41, 0, 42, 0, 43, 24, 44, 25, 45, 8, 46, 26, 47, 27, 48, 9, 49, 8, 50, 8, 51, 28, 52, 8, 53, 8, 54, 8, 55, 8, 56, 29, 57, 29, 58, 8, 59, 9, 60, 8, 61, 29, 62, 30, 0, 0, 0, 82, 64, -1, 17, 65, 5, 66, 8, 67, 31, 68, 32, 69, 33, 70, 34, 71, 35, 72, 36, 73, 37, 74, 38, 75, 39, 76, 40, 77, 41, 78, 10, 79, 29, 80, 42, 81, 43, 0, 0, 0, 99, 83, -1, 15, 84, 5, 85, 0, 86, 10, 87, 8, 88, 44, 89, 11, 90, 11, 91, 45, 92, 45, 93, 10, 94, 10, 95, 46, 96, 46, 97, 46, 98, 46, 0, 0, 0, 101, 100, -1, 1, 36, 47, 0, 0, 0, 102, 102, -1, 5, 36, 48, 103, 49, 104, 1, 105, 0, 106, 50, 0, 0, 0, 122, 107, -1, 14, 108, 5, 109, 51, 110, 8, 111, 9, 112, 8, 113, 8, 114, 8, 115, 11, 116, 8, 117, 8, 118, 8, 119, 6, 120, 8, 121, 8, 0, 0, 0, 123, 123, -1, 4, 124, 11, 125, 52, 126, 53, 105, 0, 0, 0, 0, 132, 127, -1, 4, 128, 11, 129, 13, 130, 8, 131, 44, 0, 9, 0, 140, 133, -1, 8, 36, 54, 103, 55, 134, 56, 135, 57, 136, 57, 137, 10, 138, 58, 139, 5, 0, 9, 0, 140, 141, -1, 8, 36, 59, 103, 55, 134, 60, 135, 57, 136, 57, 137, 10, 138, 61, 139, 5, 0, 9, 0, 140, 142, -1, 8, 36, 62, 103, 55, 134, 63, 135, 57, 136, 57, 137, 0, 138, 64, 139, 5, 0, 9, 0, 140, 143, -1, 8, 36, 65, 103, 55, 134, 66, 135, 57, 136, 57, 137, 0, 138, 67, 139, 5, 0 </int_array>
<string> "variants" </string>
- <array len="67" shared="false">
+ <array len="68" shared="false">
<bool> False </bool>
<resource resource_type="Shape2D" path="local://1"> </resource>
<matrix32> 1, -0, 0, 1.76469, 0.291992, -12.1587 </matrix32>
@@ -464,7 +472,7 @@
<int> 3 </int>
<vector2> 0, 0 </vector2>
<real> -1 </real>
- <resource resource_type="Script" path="res://player.gd"> </resource>
+ <resource external="0"> </resource>
<dictionary shared="false">
<string> "__editor_plugin_screen__" </string>
<string> "2D" </string>
@@ -587,6 +595,11 @@
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -596,7 +609,7 @@
<int> 0 </int>
</dictionary>
</dictionary>
- <resource resource_type="Texture" path="res://robot_demo.png"> </resource>
+ <resource external="1"> </resource>
<int> 16 </int>
<real> 0.363636 </real>
<vector2> 20.7312, 3.21187 </vector2>
@@ -604,7 +617,7 @@
<int> 4 </int>
<real> 0.3 </real>
<real> 0.1 </real>
- <resource resource_type="Texture" path="res://bullet.png"> </resource>
+ <resource external="2"> </resource>
<real> 180 </real>
<real> 20 </real>
<real> 9.8 </real>
@@ -613,14 +626,14 @@
<node_path> ".." </node_path>
<resource resource_type="Animation" path="local://3"> </resource>
<resource resource_type="Animation" path="local://4"> </resource>
- <resource resource_type="Animation" path="local://5"> </resource>
- <resource resource_type="Animation" path="local://6"> </resource>
- <resource resource_type="Animation" path="local://11"> </resource>
<resource resource_type="Animation" path="local://10"> </resource>
+ <resource resource_type="Animation" path="local://5"> </resource>
<resource resource_type="Animation" path="local://7"> </resource>
<resource resource_type="Animation" path="local://8"> </resource>
<resource resource_type="Animation" path="local://9"> </resource>
<resource resource_type="Animation" path="local://12"> </resource>
+ <resource resource_type="Animation" path="local://6"> </resource>
+ <resource resource_type="Animation" path="local://11"> </resource>
<array len="0" shared="false">
</array>
<string> "" </string>
@@ -630,25 +643,26 @@
<vector2> 31.2428, 4.08784 </vector2>
<vector2> 0.291992, -12.1587 </vector2>
<vector2> 1, 1.76469 </vector2>
+ <int> -1 </int>
<resource resource_type="SampleLibrary" path="local://13"> </resource>
- <nil> </nil>
<vector2_array len="3"> -0.138023, 16.5036, -19.902, -24.8691, 19.3625, -24.6056 </vector2_array>
+ <vector2> -1, -1 </vector2>
<vector2> 27.7593, 360.87 </vector2>
<vector2> 1.49157, 1.46265 </vector2>
- <resource resource_type="Texture" path="res://osb_left.png"> </resource>
+ <resource external="6"> </resource>
<resource name=""></resource> <string> "move_left" </string>
<vector2> 121.542, 361.415 </vector2>
- <resource resource_type="Texture" path="res://osb_right.png"> </resource>
+ <resource external="7"> </resource>
<string> "move_right" </string>
<vector2> 666.224, 359.02 </vector2>
- <resource resource_type="Texture" path="res://osb_jump.png"> </resource>
+ <resource external="8"> </resource>
<string> "jump" </string>
<vector2> 668.073, 262.788 </vector2>
- <resource resource_type="Texture" path="res://osb_fire.png"> </resource>
+ <resource external="9"> </resource>
<string> "shoot" </string>
</array>
<string> "version" </string>
- <int> 1 </int>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/platformer/seesaw.xml b/demos/2d/platformer/seesaw.xml
index ed879a9319..760423167f 100644
--- a/demos/2d/platformer/seesaw.xml
+++ b/demos/2d/platformer/seesaw.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="4" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
- <ext_resource path="res://plank.*" type="Texture"></ext_resource>
- <ext_resource path="res://plankpin.*" type="Texture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="4" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://plank.png" type="Texture" index="0"></ext_resource>
+ <ext_resource path="res://plankpin.png" type="Texture" index="1"></ext_resource>
<resource type="RectangleShape2D" path="local://1">
<real name="custom_solver_bias"> 0 </real>
<vector2 name="extents"> 128, 8 </vector2>
@@ -9,159 +9,192 @@
</resource>
<main_resource>
<dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="49">
+ <string_array len="40">
<string> "seesaw" </string>
- <string> "Node2D" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
<string> "__meta__" </string>
+ <string> "Node2D" </string>
<string> "plank" </string>
- <string> "RigidBody2D" </string>
- <string> "shape_count" </string>
+ <string> "input/pickable" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
<string> "shapes/0/trigger" </string>
+ <string> "collision/layers" </string>
+ <string> "collision/mask" </string>
<string> "mode" </string>
<string> "mass" </string>
<string> "friction" </string>
<string> "bounce" </string>
+ <string> "gravity_scale" </string>
<string> "custom_integrator" </string>
<string> "continuous_cd" </string>
<string> "contacts_reported" </string>
<string> "contact_monitor" </string>
- <string> "active" </string>
+ <string> "sleeping" </string>
<string> "can_sleep" </string>
<string> "velocity/linear" </string>
<string> "velocity/angular" </string>
+ <string> "damp_override/linear" </string>
+ <string> "damp_override/angular" </string>
+ <string> "RigidBody2D" </string>
<string> "sprite" </string>
- <string> "Sprite" </string>
<string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
+ <string> "Sprite" </string>
<string> "CollisionShape2D" </string>
<string> "shape" </string>
<string> "trigger" </string>
+ <string> "_update_shape_index" </string>
<string> "pin" </string>
- <string> "PinJoint2D" </string>
<string> "node_a" </string>
<string> "node_b" </string>
<string> "bias/bias" </string>
+ <string> "softness" </string>
+ <string> "PinJoint2D" </string>
+ <string> "transform/pos" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
<string> "node_count" </string>
<int> 6 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="106"> -1, -1, 2, 0, -1, 1, 1, 0, 0, 0, 0, 25, 3, -1, 21, 4, 1, 5, 2, 6, 3, 7, 1, 8, 4, 9, 4, 10, 5, 11, 6, 12, 7, 13, 8, 14, 7, 15, 1, 16, 5, 17, 5, 18, 1, 19, 1, 20, 9, 21, 10, 22, 8, 23, 11, 24, 11, 0, 1, 0, 28, 26, -1, 1, 27, 12, 0, 1, 0, 29, 29, -1, 3, 30, 2, 31, 1, 32, 13, 0, 0, 0, 38, 33, -1, 4, 34, 14, 35, 15, 36, 8, 37, 8, 0, 0, 0, 28, 28, -1, 2, 39, 16, 27, 17, 0 </int_array>
<string> "variants" </string>
- <array len="19" shared="false">
- <bool> True </bool>
- <real> 1 </real>
- <vector2> 0, 0 </vector2>
- <real> 0 </real>
- <vector2> 1, 1 </vector2>
+ <array len="18" shared="false">
<dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
<dictionary shared="false">
<string> "2D" </string>
<dictionary shared="false">
- <string> "pixel_snap" </string>
+ <string> "ofs" </string>
+ <vector2> -116.979, -109.897 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
<bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
<string> "zoom" </string>
<real> 2.050547 </real>
- <string> "ofs" </string>
- <vector2> -116.979, -109.897 </vector2>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
- <real> 400 </real>
+ <real> 179 </real>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
<string> "viewports" </string>
<array len="4" shared="false">
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
</array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -170,27 +203,27 @@
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
- <int> 1 </int>
+ <bool> False </bool>
<resource resource_type="Shape2D" path="local://1"> </resource>
<matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
- <bool> False </bool>
+ <int> 1 </int>
<int> 0 </int>
<real> 5.102041 </real>
- <resource resource_type="Texture" path="res://plank.*"> </resource>
- <color> 1, 1, 1, 1 </color>
- <rect2> 0, 0, 0, 0 </rect2>
+ <real> 1 </real>
+ <real> 0 </real>
+ <bool> True </bool>
+ <vector2> 0, 0 </vector2>
+ <real> -1 </real>
+ <resource external="0"> </resource>
+ <int> -1 </int>
<node_path> "../plank" </node_path>
<node_path> "" </node_path>
<vector2> -0.290825, 20.2425 </vector2>
- <resource resource_type="Texture" path="res://plankpin.*"> </resource>
+ <resource external="1"> </resource>
</array>
- <string> "nodes" </string>
- <int_array len="214"> -1, -1, 1, 0, -1, 8, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 0, 0, 0, 11, 10, -1, 23, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 12, 6, 13, 7, 14, 8, 15, 9, 16, 10, 17, 11, 18, 1, 19, 3, 20, 9, 21, 9, 22, 10, 23, 9, 24, 0, 25, 0, 26, 2, 27, 3, 0, 1, 0, 29, 28, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 30, 12, 31, 0, 32, 2, 33, 9, 34, 9, 35, 6, 36, 6, 37, 10, 38, 13, 39, 9, 40, 14, 0, 1, 0, 41, 41, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 42, 7, 43, 9, 0, 0, 0, 45, 44, -1, 10, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 46, 15, 47, 16, 48, 3, 0, 0, 0, 29, 29, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 17, 7, 3, 8, 4, 30, 18, 31, 0, 32, 2, 33, 9, 34, 9, 35, 6, 36, 6, 37, 10, 38, 13, 39, 9, 40, 14, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/platformer/stage.xml b/demos/2d/platformer/stage.xml
index d081a1be38..3b5d281551 100644
--- a/demos/2d/platformer/stage.xml
+++ b/demos/2d/platformer/stage.xml
@@ -1,27 +1,29 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="10" version="1.1" version_name="Godot Engine v1.1.stable.custom_build">
- <ext_resource path="res://tileset.xml" type="TileSet"></ext_resource>
- <ext_resource path="res://coin.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://one_way_platform.xml" type="PackedScene"></ext_resource>
- <ext_resource path="res://player.xml" type="PackedScene"></ext_resource>
- <ext_resource path="res://music.ogg" type="AudioStream"></ext_resource>
- <ext_resource path="res://enemy.xml" type="PackedScene"></ext_resource>
- <ext_resource path="res://parallax_bg.xml" type="PackedScene"></ext_resource>
+<resource_file type="PackedScene" subresource_count="10" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://tileset.xml" type="TileSet" index="0"></ext_resource>
+ <ext_resource path="res://music.ogg" type="AudioStream" index="6"></ext_resource>
+ <ext_resource path="res://coin.xml" type="PackedScene" index="1"></ext_resource>
+ <ext_resource path="res://one_way_platform.xml" type="PackedScene" index="4"></ext_resource>
+ <ext_resource path="res://moving_platform.xml" type="PackedScene" index="2"></ext_resource>
+ <ext_resource path="res://enemy.xml" type="PackedScene" index="7"></ext_resource>
+ <ext_resource path="res://seesaw.xml" type="PackedScene" index="3"></ext_resource>
+ <ext_resource path="res://player.xml" type="PackedScene" index="5"></ext_resource>
+ <ext_resource path="res://parallax_bg.xml" type="PackedScene" index="8"></ext_resource>
<main_resource>
<dictionary name="_bundled" shared="false">
<string> "conn_count" </string>
<int> 0 </int>
<string> "conns" </string>
<int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="117">
+ <string_array len="112">
<string> "stage" </string>
- <string> "Node" </string>
<string> "__meta__" </string>
+ <string> "Node" </string>
<string> "tile_map" </string>
- <string> "TileMap" </string>
<string> "mode" </string>
<string> "tile_set" </string>
<string> "cell/size" </string>
@@ -36,11 +38,13 @@
<string> "collision/layers" </string>
<string> "collision/mask" </string>
<string> "tile_data" </string>
+ <string> "TileMap" </string>
<string> "coins" </string>
<string> "coin" </string>
- <string> "Area2D" </string>
- <string> "_import_path" </string>
<string> "transform/pos" </string>
+ <string> "input/pickable" </string>
+ <string> "linear_damp" </string>
+ <string> "angular_damp" </string>
<string> "coin 2" </string>
<string> "coin 3" </string>
<string> "coin 4" </string>
@@ -84,24 +88,23 @@
<string> "coin 31 7 5" </string>
<string> "props" </string>
<string> "moving_platform" </string>
- <string> "Node2D" </string>
<string> "motion" </string>
<string> "cycle" </string>
<string> "moving_platform 2" </string>
<string> "moving_platform 3" </string>
<string> "seesaw" </string>
<string> "one_way_platform" </string>
- <string> "StaticBody2D" </string>
<string> "player" </string>
- <string> "RigidBody2D" </string>
<string> "music" </string>
- <string> "StreamPlayer" </string>
<string> "stream/stream" </string>
<string> "stream/play" </string>
<string> "stream/loop" </string>
<string> "stream/volume_db" </string>
<string> "stream/autoplay" </string>
<string> "stream/paused" </string>
+ <string> "stream/loop_restart_time" </string>
+ <string> "stream/buffering_ms" </string>
+ <string> "StreamPlayer" </string>
<string> "enemies" </string>
<string> "enemy 5" </string>
<string> "enemy 6" </string>
@@ -115,7 +118,7 @@
<string> "enemy 14" </string>
<string> "enemy 15" </string>
<string> "parallax_bg" </string>
- <string> "ParallaxBackground" </string>
+ <string> "scroll/ignore_camera_zoom" </string>
<string> "Label" </string>
<string> "margin/left" </string>
<string> "margin/top" </string>
@@ -124,26 +127,24 @@
<string> "focus/ignore_mouse" </string>
<string> "focus/stop_mouse" </string>
<string> "size_flags/horizontal" </string>
- <string> "range/min" </string>
- <string> "range/max" </string>
- <string> "range/step" </string>
- <string> "range/page" </string>
- <string> "range/value" </string>
- <string> "range/exp_edit" </string>
- <string> "rounded_values" </string>
<string> "text" </string>
<string> "autowrap" </string>
<string> "percent_visible" </string>
+ <string> "lines_skipped" </string>
+ <string> "max_lines_visible" </string>
</string_array>
<string> "node_count" </string>
<int> 67 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
<string> "nodes" </string>
- <int_array len="917"> -1, -1, 1, 0, -1, 1, 2, 0, 0, 0, 0, 4, 3, -1, 15, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 1, 12, 7, 13, 7, 14, 8, 15, 9, 16, 10, 17, 10, 18, 11, 2, 12, 0, 0, 0, 1, 19, -1, 0, 0, 2, 0, 21, 20, 13, 3, 22, 14, 23, 15, 2, 16, 0, 2, 0, 21, 24, 13, 3, 22, 14, 23, 17, 2, 16, 0, 2, 0, 21, 25, 13, 3, 22, 14, 23, 18, 2, 16, 0, 2, 0, 21, 26, 13, 3, 22, 14, 23, 19, 2, 16, 0, 2, 0, 21, 27, 13, 3, 22, 14, 23, 20, 2, 16, 0, 2, 0, 21, 28, 13, 3, 22, 14, 23, 21, 2, 16, 0, 2, 0, 21, 29, 13, 3, 22, 14, 23, 22, 2, 16, 0, 2, 0, 21, 30, 13, 3, 22, 14, 23, 23, 2, 16, 0, 2, 0, 21, 31, 13, 3, 22, 14, 23, 24, 2, 16, 0, 2, 0, 21, 32, 13, 3, 22, 14, 23, 25, 2, 16, 0, 2, 0, 21, 33, 13, 3, 22, 14, 23, 26, 2, 16, 0, 2, 0, 21, 34, 13, 3, 22, 14, 23, 27, 2, 16, 0, 2, 0, 21, 35, 13, 3, 22, 14, 23, 28, 2, 16, 0, 2, 0, 21, 36, 13, 3, 22, 14, 23, 29, 2, 16, 0, 2, 0, 21, 37, 13, 3, 22, 14, 23, 30, 2, 16, 0, 2, 0, 21, 38, 13, 3, 22, 14, 23, 31, 2, 16, 0, 2, 0, 21, 39, 13, 3, 22, 14, 23, 32, 2, 16, 0, 2, 0, 21, 40, 13, 3, 22, 14, 23, 33, 2, 16, 0, 2, 0, 21, 41, 13, 3, 22, 14, 23, 34, 2, 16, 0, 2, 0, 21, 42, 13, 3, 22, 14, 23, 35, 2, 16, 0, 2, 0, 21, 43, 13, 3, 22, 14, 23, 36, 2, 16, 0, 2, 0, 21, 44, 13, 3, 22, 14, 23, 37, 2, 16, 0, 2, 0, 21, 45, 13, 3, 22, 14, 23, 38, 2, 16, 0, 2, 0, 21, 46, 13, 3, 22, 14, 23, 39, 2, 16, 0, 2, 0, 21, 47, 13, 3, 22, 14, 23, 40, 2, 16, 0, 2, 0, 21, 48, 13, 3, 22, 14, 23, 41, 2, 16, 0, 2, 0, 21, 49, 13, 3, 22, 14, 23, 42, 2, 16, 0, 2, 0, 21, 50, 13, 3, 22, 14, 23, 43, 2, 16, 0, 2, 0, 21, 51, 13, 3, 22, 14, 23, 44, 2, 16, 0, 2, 0, 21, 52, 13, 3, 22, 14, 23, 45, 2, 16, 0, 2, 0, 21, 53, 13, 3, 22, 14, 23, 46, 2, 16, 0, 2, 0, 21, 54, 13, 3, 22, 14, 23, 47, 2, 16, 0, 2, 0, 21, 55, 13, 3, 22, 14, 23, 48, 2, 16, 0, 2, 0, 21, 56, 13, 3, 22, 14, 23, 49, 2, 16, 0, 2, 0, 21, 57, 13, 3, 22, 14, 23, 50, 2, 16, 0, 2, 0, 21, 58, 13, 3, 22, 14, 23, 51, 2, 16, 0, 2, 0, 21, 59, 13, 3, 22, 14, 23, 52, 2, 16, 0, 2, 0, 21, 60, 13, 3, 22, 14, 23, 53, 2, 16, 0, 2, 0, 21, 61, 13, 3, 22, 14, 23, 54, 2, 16, 0, 2, 0, 21, 62, 13, 3, 22, 14, 23, 55, 2, 16, 0, 2, 0, 21, 63, 13, 3, 22, 14, 23, 56, 2, 16, 0, 2, 0, 21, 64, 13, 3, 22, 14, 23, 57, 2, 16, 0, 0, 0, 1, 65, -1, 0, 0, 45, 0, 67, 66, 58, 5, 22, 14, 23, 59, 2, 60, 68, 61, 69, 62, 0, 45, 0, 67, 70, 58, 5, 22, 14, 23, 63, 2, 60, 68, 64, 69, 65, 0, 45, 0, 67, 71, 58, 5, 22, 14, 23, 66, 2, 60, 68, 67, 69, 65, 0, 45, 0, 67, 72, 68, 3, 22, 14, 23, 69, 2, 70, 0, 45, 0, 74, 73, 71, 3, 22, 14, 23, 72, 2, 73, 0, 0, 0, 76, 75, 74, 3, 22, 14, 23, 75, 2, 76, 0, 0, 0, 78, 77, -1, 6, 79, 77, 80, 7, 81, 78, 82, 79, 83, 78, 84, 7, 0, 0, 0, 1, 85, -1, 0, 0, 53, 0, 76, 86, 80, 3, 22, 14, 23, 81, 2, 82, 0, 53, 0, 76, 87, 80, 3, 22, 14, 23, 83, 2, 82, 0, 53, 0, 76, 88, 80, 3, 22, 14, 23, 84, 2, 82, 0, 53, 0, 76, 89, 80, 3, 22, 14, 23, 85, 2, 82, 0, 53, 0, 76, 90, 80, 3, 22, 14, 23, 86, 2, 82, 0, 53, 0, 76, 91, 80, 3, 22, 14, 23, 87, 2, 82, 0, 53, 0, 76, 92, 80, 3, 22, 14, 23, 88, 2, 82, 0, 53, 0, 76, 93, 80, 3, 22, 14, 23, 89, 2, 82, 0, 53, 0, 76, 94, 80, 3, 22, 14, 23, 90, 2, 82, 0, 53, 0, 76, 95, 80, 3, 22, 14, 23, 91, 2, 82, 0, 53, 0, 76, 96, 80, 3, 22, 14, 23, 92, 2, 82, 0, 0, 0, 98, 97, 93, 2, 22, 14, 2, 94, 0, 0, 0, 99, 99, -1, 17, 100, 95, 101, 96, 102, 97, 103, 98, 104, 78, 105, 78, 106, 6, 107, 9, 108, 99, 109, 8, 110, 100, 111, 9, 112, 7, 113, 7, 114, 101, 115, 78, 116, 102, 0 </int_array>
+ <int_array len="925"> -1, -1, 2, 0, -1, 1, 1, 0, 0, 0, 0, 18, 3, -1, 15, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 1, 11, 7, 12, 7, 13, 8, 14, 9, 15, 10, 16, 10, 17, 11, 1, 12, 0, 0, 0, 2, 19, -1, 0, 0, 2, 0, 2147483647, 20, 13, 4, 21, 14, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 25, 13, 4, 21, 17, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 26, 13, 4, 21, 18, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 27, 13, 4, 21, 19, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 28, 13, 4, 21, 20, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 29, 13, 4, 21, 21, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 30, 13, 4, 21, 22, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 31, 13, 4, 21, 23, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 32, 13, 4, 21, 24, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 33, 13, 4, 21, 25, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 34, 13, 4, 21, 26, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 35, 13, 4, 21, 27, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 36, 13, 4, 21, 28, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 37, 13, 4, 21, 29, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 38, 13, 4, 21, 30, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 39, 13, 4, 21, 31, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 40, 13, 4, 21, 32, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 41, 13, 4, 21, 33, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 42, 13, 4, 21, 34, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 43, 13, 4, 21, 35, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 44, 13, 4, 21, 36, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 45, 13, 4, 21, 37, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 46, 13, 4, 21, 38, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 47, 13, 4, 21, 39, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 48, 13, 4, 21, 40, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 49, 13, 4, 21, 41, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 50, 13, 4, 21, 42, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 51, 13, 4, 21, 43, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 52, 13, 4, 21, 44, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 53, 13, 4, 21, 45, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 54, 13, 4, 21, 46, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 55, 13, 4, 21, 47, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 56, 13, 4, 21, 48, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 57, 13, 4, 21, 49, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 58, 13, 4, 21, 50, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 59, 13, 4, 21, 51, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 60, 13, 4, 21, 52, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 61, 13, 4, 21, 53, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 62, 13, 4, 21, 54, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 63, 13, 4, 21, 55, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 64, 13, 4, 21, 56, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 65, 13, 4, 21, 57, 22, 15, 23, 16, 24, 8, 0, 0, 0, 2, 66, -1, 0, 0, 45, 0, 2147483647, 67, 58, 3, 21, 59, 68, 60, 69, 61, 0, 45, 0, 2147483647, 70, 58, 3, 21, 62, 68, 63, 69, 64, 0, 45, 0, 2147483647, 71, 58, 3, 21, 65, 68, 66, 69, 64, 0, 45, 0, 2147483647, 72, 67, 1, 21, 68, 0, 45, 0, 2147483647, 73, 69, 1, 21, 70, 0, 0, 0, 2147483647, 74, 71, 1, 21, 72, 0, 0, 0, 84, 75, -1, 8, 76, 73, 77, 7, 78, 15, 79, 74, 80, 15, 81, 7, 82, 9, 83, 75, 0, 0, 0, 2, 85, -1, 0, 0, 53, 0, 2147483647, 86, 76, 1, 21, 77, 0, 53, 0, 2147483647, 87, 76, 1, 21, 78, 0, 53, 0, 2147483647, 88, 76, 1, 21, 79, 0, 53, 0, 2147483647, 89, 76, 1, 21, 80, 0, 53, 0, 2147483647, 90, 76, 1, 21, 81, 0, 53, 0, 2147483647, 91, 76, 1, 21, 82, 0, 53, 0, 2147483647, 92, 76, 1, 21, 83, 0, 53, 0, 2147483647, 93, 76, 1, 21, 84, 0, 53, 0, 2147483647, 94, 76, 1, 21, 85, 0, 53, 0, 2147483647, 95, 76, 1, 21, 86, 0, 53, 0, 2147483647, 96, 76, 1, 21, 87, 0, 0, 0, 2147483647, 97, 88, 1, 98, 7, 0, 0, 0, 99, 99, -1, 12, 100, 89, 101, 90, 102, 91, 103, 92, 104, 15, 105, 15, 106, 6, 107, 93, 108, 15, 109, 8, 110, 1, 111, 94, 0 </int_array>
<string> "variants" </string>
- <array len="103" shared="false">
+ <array len="95" shared="false">
<dictionary shared="false">
<string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
+ <string> "Script" </string>
<string> "__editor_plugin_states__" </string>
<dictionary shared="false">
<string> "2D" </string>
@@ -263,6 +264,11 @@
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -273,7 +279,7 @@
</dictionary>
</dictionary>
<int> 0 </int>
- <resource resource_type="TileSet" path="res://tileset.xml"> </resource>
+ <resource external="0"> </resource>
<vector2> 64, 64 </vector2>
<int> 8 </int>
<matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
@@ -287,119 +293,10 @@
<string> "_edit_lock_" </string>
<bool> True </bool>
</dictionary>
- <resource resource_type="PackedScene" path="res://coin.xml"> </resource>
- <node_path> "" </node_path>
+ <resource external="1"> </resource>
<vector2> 672, 1179 </vector2>
- <dictionary shared="false">
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "ofs" </string>
- <vector2> -34.3697, -21.6562 </vector2>
- <string> "pixel_snap" </string>
- <bool> False </bool>
- <string> "zoom" </string>
- <real> 3.794776 </real>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "fov" </string>
- <real> 45 </real>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- </array>
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "znear" </string>
- <real> 0.1 </real>
- </dictionary>
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 2 </int>
- <string> "sources" </string>
- <array len="3" shared="false">
- <string> "res://enemy.gd" </string>
- <string> "res://player.gd" </string>
- <string> "res://coin.gd" </string>
- </array>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- </dictionary>
+ <bool> True </bool>
+ <real> 0.1 </real>
<vector2> 704, 1179 </vector2>
<vector2> 736, 1179 </vector2>
<vector2> 1120, 992 </vector2>
@@ -441,119 +338,8 @@
<vector2> 4300.75, 541.058 </vector2>
<vector2> 4236.75, 541.058 </vector2>
<vector2> 4172.75, 541.058 </vector2>
- <resource resource_type="PackedScene" path="res://moving_platform.xml"> </resource>
+ <resource external="2"> </resource>
<vector2> 1451.86, 742.969 </vector2>
- <dictionary shared="false">
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "ofs" </string>
- <vector2> -210.652, -172.81 </vector2>
- <string> "pixel_snap" </string>
- <bool> False </bool>
- <string> "zoom" </string>
- <real> 1.360373 </real>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "fov" </string>
- <real> 400 </real>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- </array>
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "znear" </string>
- <real> 0.1 </real>
- </dictionary>
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 0 </int>
- <string> "sources" </string>
- <array len="4" shared="false">
- <string> "res://moving_platform.gd" </string>
- <string> "res://enemy.gd" </string>
- <string> "res://player.gd" </string>
- <string> "res://coin.gd" </string>
- </array>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- </dictionary>
<vector2> 0, 140 </vector2>
<real> 5 </real>
<vector2> 624.824, 545.544 </vector2>
@@ -561,483 +347,17 @@
<real> 10 </real>
<vector2> 3419.86, 739.662 </vector2>
<vector2> 450, 0 </vector2>
- <resource resource_type="PackedScene" path="res://seesaw.xml"> </resource>
+ <resource external="3"> </resource>
<vector2> 2402.79, 849.52 </vector2>
- <dictionary shared="false">
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "ofs" </string>
- <vector2> -116.979, -109.897 </vector2>
- <string> "pixel_snap" </string>
- <bool> False </bool>
- <string> "zoom" </string>
- <real> 2.050547 </real>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "fov" </string>
- <real> 400 </real>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- </array>
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "znear" </string>
- <real> 0.1 </real>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- </dictionary>
- <resource resource_type="PackedScene" path="res://one_way_platform.xml"> </resource>
+ <resource external="4"> </resource>
<vector2> 927.698, 1120.81 </vector2>
- <dictionary shared="false">
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "ofs" </string>
- <vector2> -133.699, -110.553 </vector2>
- <string> "snap_grid" </string>
- <bool> False </bool>
- <string> "snap_offset" </string>
- <vector2> 0, 0 </vector2>
- <string> "snap_pixel" </string>
- <bool> False </bool>
- <string> "snap_relative" </string>
- <bool> False </bool>
- <string> "snap_rotation" </string>
- <bool> False </bool>
- <string> "snap_rotation_offset" </string>
- <real> 0 </real>
- <string> "snap_rotation_step" </string>
- <real> 0.261799 </real>
- <string> "snap_show_grid" </string>
- <bool> False </bool>
- <string> "snap_step" </string>
- <vector2> 10, 10 </vector2>
- <string> "zoom" </string>
- <real> 2.050546 </real>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "ambient_light_color" </string>
- <color> 0.15, 0.15, 0.15, 1 </color>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "default_srgb" </string>
- <bool> False </bool>
- <string> "deflight_rot_x" </string>
- <real> 0.942478 </real>
- <string> "deflight_rot_y" </string>
- <real> 0.628319 </real>
- <string> "fov" </string>
- <real> 45 </real>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "listener" </string>
- <bool> True </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "listener" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "listener" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "listener" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- </array>
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "znear" </string>
- <real> 0.1 </real>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- </dictionary>
- <resource resource_type="PackedScene" path="res://player.xml"> </resource>
+ <resource external="5"> </resource>
<vector2> 251.684, 1045.6 </vector2>
- <dictionary shared="false">
- <string> "__editor_plugin_screen__" </string>
- <string> "Script" </string>
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "ofs" </string>
- <vector2> -181.946, -86.2812 </vector2>
- <string> "pixel_snap" </string>
- <bool> False </bool>
- <string> "snap" </string>
- <int> 10 </int>
- <string> "use_snap" </string>
- <bool> False </bool>
- <string> "zoom" </string>
- <real> 2.272073 </real>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "ambient_light_color" </string>
- <color> 0.15, 0.15, 0.15, 1 </color>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "default_srgb" </string>
- <bool> False </bool>
- <string> "deflight_rot_x" </string>
- <real> 0.942478 </real>
- <string> "deflight_rot_y" </string>
- <real> 0.628319 </real>
- <string> "fov" </string>
- <real> 45 </real>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "listener" </string>
- <bool> True </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "listener" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "listener" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "listener" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- </array>
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "znear" </string>
- <real> 0.1 </real>
- </dictionary>
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 0 </int>
- <string> "sources" </string>
- <array len="1" shared="false">
- <string> "res://player.gd" </string>
- </array>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- </dictionary>
- <resource resource_type="AudioStream" path="res://music.ogg"> </resource>
- <bool> True </bool>
+ <resource external="6"> </resource>
<real> 2 </real>
- <resource resource_type="PackedScene" path="res://enemy.xml"> </resource>
+ <int> 500 </int>
+ <resource external="7"> </resource>
<vector2> 834.664, 1309.6 </vector2>
- <dictionary shared="false">
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "ofs" </string>
- <vector2> -227.625, -197.9 </vector2>
- <string> "pixel_snap" </string>
- <bool> False </bool>
- <string> "zoom" </string>
- <real> 1.108033 </real>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "fov" </string>
- <real> 45 </real>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- </array>
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "znear" </string>
- <real> 0.1 </real>
- </dictionary>
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 0 </int>
- <string> "sources" </string>
- <array len="1" shared="false">
- <string> "res://enemy.gd" </string>
- </array>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- </dictionary>
<vector2> 707.665, 1225.05 </vector2>
<vector2> 1125.21, 1053.06 </vector2>
<vector2> 1292.11, 1059.24 </vector2>
@@ -1048,79 +368,16 @@
<vector2> 3429.73, 540.865 </vector2>
<vector2> 3546.2, 1356.19 </vector2>
<vector2> 2406.63, 815.115 </vector2>
- <resource resource_type="PackedScene" path="res://parallax_bg.xml"> </resource>
- <dictionary shared="false">
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "ofs" </string>
- <vector2> -5, -25 </vector2>
- <string> "zoom" </string>
- <real> 1 </real>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "fov" </string>
- <real> 45 </real>
- <string> "window_0" </string>
- <dictionary shared="false">
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "distance" </string>
- <real> 4 </real>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "x_rot" </string>
- <real> 0.337 </real>
- <string> "y_rot" </string>
- <real> -0.575 </real>
- </dictionary>
- <string> "window_mode" </string>
- <int> 0 </int>
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "znear" </string>
- <real> 0.1 </real>
- </dictionary>
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 0 </int>
- <string> "sources" </string>
- <array len="4" shared="false">
- <string> "res://moving_platform.gd" </string>
- <string> "res://enemy.gd" </string>
- <string> "res://player.gd" </string>
- <string> "res://coin.gd" </string>
- </array>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- </dictionary>
+ <resource external="8"> </resource>
<real> 12 </real>
<real> -202 </real>
<real> 358 </real>
<real> -10 </real>
- <real> 7 </real>
- <real> 14.769231 </real>
<string> "This is a simple demo on how to make a platformer game with Godot.&quot;This version uses physics and the 2D physics engine for motion and collision.&quot;&quot;The demo also shows the benefits of using the scene system, where coins,&quot;enemies and the player are edited separatedly and instanced in the stage.&quot;&quot;To edit the base tiles for the tileset, open the tileset_edit.xml file and follow &quot;instructions.&quot;" </string>
- <real> -1 </real>
+ <int> -1 </int>
</array>
<string> "version" </string>
- <int> 1 </int>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/platformer/tileset_edit.xml b/demos/2d/platformer/tileset_edit.xml
index db289433ab..3ae9f1bd2a 100644
--- a/demos/2d/platformer/tileset_edit.xml
+++ b/demos/2d/platformer/tileset_edit.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="14" version="1.0" version_name="Godot Engine v1.0.stable.custom_build">
- <ext_resource path="res://tiles_demo.png" type="Texture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="14" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://tiles_demo.png" type="Texture" index="0"></ext_resource>
<resource type="ConvexPolygonShape2D" path="local://1">
<real name="custom_solver_bias"> 0 </real>
<vector2_array name="points" len="4"> -32, -24, 32, -24, 32, 32, -32, 32 </vector2_array>
@@ -63,48 +63,41 @@
</resource>
<main_resource>
<dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="77">
+ <string_array len="49">
<string> "Node" </string>
- <string> "_import_path" </string>
<string> "__meta__" </string>
<string> "floor" </string>
- <string> "Sprite" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
- <string> "z/z" </string>
- <string> "z/relative" </string>
<string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
<string> "region" </string>
<string> "region_rect" </string>
+ <string> "Sprite" </string>
<string> "collision" </string>
- <string> "StaticBody2D" </string>
- <string> "shape_count" </string>
+ <string> "input/pickable" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
<string> "shapes/0/trigger" </string>
- <string> "layers" </string>
+ <string> "collision/layers" </string>
+ <string> "collision/mask" </string>
<string> "constant_linear_velocity" </string>
<string> "constant_angular_velocity" </string>
<string> "friction" </string>
<string> "bounce" </string>
+ <string> "StaticBody2D" </string>
<string> "CollisionPolygon2D" </string>
<string> "build_mode" </string>
<string> "polygon" </string>
+ <string> "shape_range" </string>
<string> "trigger" </string>
<string> "edge" </string>
+ <string> "transform/pos" </string>
<string> "wall" </string>
<string> "wall_deco" </string>
<string> "corner" </string>
@@ -118,147 +111,152 @@
<string> "ramp" </string>
<string> "ceiling2wall" </string>
<string> "help" </string>
- <string> "Label" </string>
- <string> "focus_neighbour/left" </string>
- <string> "focus_neighbour/top" </string>
- <string> "focus_neighbour/right" </string>
- <string> "focus_neighbour/bottom" </string>
<string> "focus/ignore_mouse" </string>
<string> "focus/stop_mouse" </string>
<string> "size_flags/horizontal" </string>
- <string> "size_flags/stretch_ratio" </string>
- <string> "range/min" </string>
- <string> "range/max" </string>
- <string> "range/step" </string>
- <string> "range/page" </string>
- <string> "range/value" </string>
- <string> "range/exp_edit" </string>
- <string> "rounded_values" </string>
<string> "text" </string>
- <string> "align" </string>
- <string> "valign" </string>
- <string> "autowrap" </string>
- <string> "uppercase" </string>
<string> "percent_visible" </string>
+ <string> "lines_skipped" </string>
+ <string> "max_lines_visible" </string>
+ <string> "Label" </string>
<string> "platform_floor" </string>
<string> "platform_edge" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
<string> "node_count" </string>
<int> 42 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="772"> -1, -1, 0, 0, -1, 1, 1, 0, 0, 0, 0, 6, 2, -1, 3, 3, 1, 4, 2, 5, 3, 0, 1, 0, 18, 7, -1, 10, 8, 4, 9, 5, 10, 6, 11, 4, 12, 7, 13, 7, 14, 8, 15, 9, 16, 10, 17, 9, 0, 2, 0, 19, 19, -1, 4, 20, 11, 21, 12, 22, 13, 23, 4, 0, 0, 0, 6, 24, -1, 4, 25, 14, 3, 1, 4, 2, 5, 15, 0, 4, 0, 18, 7, -1, 10, 8, 4, 9, 16, 10, 6, 11, 4, 12, 7, 13, 7, 14, 8, 15, 9, 16, 10, 17, 9, 0, 5, 0, 19, 19, -1, 4, 20, 11, 21, 17, 22, 13, 23, 4, 0, 0, 0, 6, 26, -1, 4, 25, 18, 3, 1, 4, 2, 5, 19, 0, 7, 0, 18, 7, -1, 10, 8, 4, 9, 20, 10, 6, 11, 4, 12, 7, 13, 7, 14, 8, 15, 9, 16, 10, 17, 9, 0, 8, 0, 19, 19, -1, 4, 20, 11, 21, 21, 22, 13, 23, 4, 0, 0, 0, 6, 27, -1, 4, 25, 22, 3, 1, 4, 2, 5, 23, 0, 10, 0, 18, 7, -1, 10, 8, 4, 9, 24, 10, 6, 11, 4, 12, 7, 13, 7, 14, 8, 15, 9, 16, 10, 17, 9, 0, 11, 0, 19, 19, -1, 4, 20, 11, 21, 25, 22, 13, 23, 4, 0, 0, 0, 6, 28, -1, 4, 25, 26, 3, 1, 4, 2, 5, 27, 0, 13, 0, 18, 7, -1, 10, 8, 4, 9, 28, 10, 6, 11, 4, 12, 7, 13, 7, 14, 8, 15, 9, 16, 10, 17, 9, 0, 14, 0, 19, 19, -1, 4, 20, 11, 21, 29, 22, 13, 23, 4, 0, 0, 0, 6, 29, -1, 4, 25, 30, 3, 1, 4, 2, 5, 31, 0, 16, 0, 18, 7, -1, 10, 8, 4, 9, 32, 10, 6, 11, 4, 12, 7, 13, 7, 14, 8, 15, 9, 16, 10, 17, 9, 0, 17, 0, 19, 19, -1, 4, 20, 11, 21, 33, 22, 13, 23, 4, 0, 0, 0, 6, 30, -1, 4, 25, 34, 3, 1, 4, 2, 5, 35, 0, 19, 0, 18, 7, -1, 10, 8, 4, 9, 36, 10, 6, 11, 4, 12, 7, 13, 7, 14, 8, 15, 9, 16, 10, 17, 9, 0, 20, 0, 19, 19, -1, 4, 20, 11, 21, 33, 22, 13, 23, 4, 0, 0, 0, 6, 31, -1, 4, 25, 37, 3, 1, 4, 2, 5, 38, 0, 0, 0, 6, 32, -1, 4, 25, 39, 3, 1, 4, 2, 5, 40, 0, 0, 0, 6, 33, -1, 4, 25, 41, 3, 1, 4, 2, 5, 42, 0, 0, 0, 6, 34, -1, 4, 25, 43, 3, 1, 4, 2, 5, 44, 0, 0, 0, 6, 35, -1, 4, 25, 45, 3, 1, 4, 2, 5, 46, 0, 26, 0, 18, 7, -1, 10, 8, 4, 9, 47, 10, 6, 11, 4, 12, 7, 13, 7, 14, 8, 15, 9, 16, 10, 17, 9, 0, 27, 0, 19, 19, -1, 4, 20, 11, 21, 48, 22, 13, 23, 4, 0, 0, 0, 6, 36, -1, 4, 25, 49, 3, 1, 4, 2, 5, 50, 0, 29, 0, 18, 7, -1, 10, 8, 4, 9, 51, 10, 6, 11, 4, 12, 7, 13, 7, 14, 8, 15, 9, 16, 10, 17, 9, 0, 30, 0, 19, 19, -1, 4, 20, 11, 21, 52, 22, 13, 23, 4, 0, 0, 0, 6, 37, -1, 4, 25, 53, 3, 1, 4, 2, 5, 54, 0, 32, 0, 18, 7, -1, 10, 8, 4, 9, 55, 10, 6, 11, 4, 12, 7, 13, 7, 14, 8, 15, 9, 16, 10, 17, 9, 0, 33, 0, 19, 19, -1, 4, 20, 11, 21, 21, 22, 13, 23, 4, 0, 0, 0, 46, 38, -1, 7, 39, 2, 40, 2, 41, 56, 42, 57, 43, 10, 44, 11, 45, 58, 0, 0, 0, 6, 47, -1, 4, 25, 59, 3, 1, 4, 2, 5, 60, 0, 36, 0, 18, 7, -1, 10, 8, 4, 9, 61, 10, 6, 11, 4, 12, 7, 13, 7, 14, 8, 15, 9, 16, 10, 17, 9, 0, 37, 0, 19, 19, -1, 4, 20, 11, 21, 62, 22, 13, 23, 4, 0, 0, 0, 6, 48, -1, 4, 25, 63, 3, 1, 4, 2, 5, 64, 0, 39, 0, 18, 7, -1, 10, 8, 4, 9, 65, 10, 6, 11, 4, 12, 7, 13, 7, 14, 8, 15, 9, 16, 10, 17, 9, 0, 40, 0, 19, 19, -1, 4, 20, 11, 21, 66, 22, 13, 23, 4, 0 </int_array>
<string> "variants" </string>
- <array len="69" shared="false">
- <node_path> "" </node_path>
+ <array len="67" shared="false">
<dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "Script" </string>
<string> "__editor_plugin_states__" </string>
<dictionary shared="false">
<string> "2D" </string>
<dictionary shared="false">
- <string> "pixel_snap" </string>
- <bool> True </bool>
- <string> "zoom" </string>
- <real> 1.670183 </real>
- <string> "use_snap" </string>
- <bool> True </bool>
<string> "ofs" </string>
<vector2> -446.534, -87.6905 </vector2>
- <string> "snap" </string>
- <int> 8 </int>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
+ <string> "zoom" </string>
+ <real> 1.670183 </real>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
<string> "deflight_rot_y" </string>
<real> 0.628319 </real>
- <string> "zfar" </string>
- <real> 500 </real>
<string> "fov" </string>
<real> 45 </real>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
<string> "viewports" </string>
<array len="4" shared="false">
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
<string> "listener" </string>
<bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
<string> "use_environment" </string>
<bool> False </bool>
<string> "use_orthogonal" </string>
<bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
<string> "listener" </string>
<bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
<string> "use_environment" </string>
<bool> False </bool>
<string> "use_orthogonal" </string>
<bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
<string> "listener" </string>
<bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
<string> "use_environment" </string>
<bool> False </bool>
<string> "use_orthogonal" </string>
<bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
<string> "listener" </string>
<bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
<string> "use_environment" </string>
<bool> False </bool>
<string> "use_orthogonal" </string>
<bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
</dictionary>
</array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "ambient_light_color" </string>
- <color> 0.15, 0.15, 0.15, 1 </color>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
- <string> "default_srgb" </string>
+ </dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
<bool> False </bool>
- <string> "deflight_rot_x" </string>
- <real> 0.942478 </real>
</dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
@@ -268,23 +266,20 @@
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
+ <resource external="0"> </resource>
<bool> True </bool>
- <real> 1 </real>
- <vector2> 0, 0 </vector2>
- <real> 0 </real>
- <vector2> 1, 1 </vector2>
- <int> 0 </int>
- <resource resource_type="Texture" path="res://tiles_demo.png"> </resource>
- <bool> False </bool>
- <int> 1 </int>
- <color> 1, 1, 1, 1 </color>
<rect2> 0, 0, 64, 64 </rect2>
+ <bool> False </bool>
<resource resource_type="Shape2D" path="local://1"> </resource>
<matrix32> 1, -0, 0, 1, 0, 0 </matrix32>
+ <int> 1 </int>
+ <vector2> 0, 0 </vector2>
+ <real> 0 </real>
+ <real> 1 </real>
+ <int> 0 </int>
<vector2_array len="4"> 32, -24, 32, 32, -32, 32, -32, -24 </vector2_array>
+ <vector2> -1, -1 </vector2>
<vector2> 64, 0 </vector2>
<rect2> 64, 0, 64, 64 </rect2>
<resource resource_type="Shape2D" path="local://2"> </resource>
@@ -329,7 +324,7 @@
<resource resource_type="Shape2D" path="local://10"> </resource>
<int> 2 </int>
<string> "This scene serves as a tool for editing the tileset.&#0010;Nodes (sprites) and their respective collisions&#0010;are edited here. &#0010;&#0010;To create a tileset from this, a &quot;TileSet&quot; resoucre &#0010;must be created. Use the helper in:&#0010;&#0010; Scene -&lt; Convert To -&lt; TileSet&#0010;&#0010;This will save a tileset. Saving over it will merge your changes.&#0010;&#0010;Finally, the saved tileset resource (tileset.xml in this&#0010; case), can be opened to be used into a TileMap node&#0010; for editing a tile map.&#0010;" </string>
- <real> -1 </real>
+ <int> -1 </int>
<vector2> 0, 256 </vector2>
<rect2> 128, 0, 64, 64 </rect2>
<resource resource_type="Shape2D" path="local://11"> </resource>
@@ -339,10 +334,8 @@
<resource resource_type="Shape2D" path="local://12"> </resource>
<vector2_array len="4"> 24, -24, 24, 24, -32, 24, -32, -24 </vector2_array>
</array>
- <string> "nodes" </string>
- <int_array len="1708"> -1, -1, 0, 0, -1, 2, 1, 0, 2, 1, 0, 0, 0, 4, 3, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 12, 0, 1, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 13, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 2, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 15, 38, 9, 0, 0, 0, 4, 39, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 16, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 17, 0, 4, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 18, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 5, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 19, 38, 9, 0, 0, 0, 4, 40, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 20, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 21, 0, 7, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 22, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 8, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 23, 38, 9, 0, 0, 0, 4, 41, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 24, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 25, 0, 10, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 26, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 11, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 27, 38, 9, 0, 0, 0, 4, 42, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 28, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 29, 0, 13, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 30, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 14, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 31, 38, 9, 0, 0, 0, 4, 43, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 32, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 33, 0, 16, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 34, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 17, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 35, 38, 9, 0, 0, 0, 4, 44, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 36, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 37, 0, 19, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 38, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 20, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 35, 38, 9, 0, 0, 0, 4, 45, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 39, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 40, 0, 0, 0, 4, 46, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 41, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 42, 0, 0, 0, 4, 47, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 43, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 44, 0, 0, 0, 4, 48, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 45, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 46, 0, 0, 0, 4, 49, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 47, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 48, 0, 26, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 49, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 27, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 50, 38, 9, 0, 0, 0, 4, 50, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 51, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 52, 0, 29, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 53, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 30, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 54, 38, 9, 0, 0, 0, 4, 51, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 55, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 56, 0, 32, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 57, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 33, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 23, 38, 9, 0, 0, 0, 53, 52, -1, 25, 1, 0, 5, 2, 6, 3, 7, 3, 54, 0, 55, 0, 56, 0, 57, 0, 58, 2, 59, 2, 60, 58, 61, 3, 62, 5, 63, 3, 64, 3, 65, 3, 66, 5, 67, 9, 68, 9, 69, 59, 70, 7, 71, 7, 72, 9, 73, 9, 74, 60, 0, 0, 0, 4, 75, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 61, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 62, 0, 36, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 63, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 37, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 64, 38, 9, 0, 0, 0, 4, 76, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 65, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 66, 0, 39, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 67, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 40, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 68, 38, 9, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/pong/pong.gd b/demos/2d/pong/pong.gd
index cf6003c659..81afbd9961 100644
--- a/demos/2d/pong/pong.gd
+++ b/demos/2d/pong/pong.gd
@@ -1,73 +1,67 @@
extends Node2D
-#member variables here, example:
-#var a=2
-#var b="textvar"
+# Member variables
const INITIAL_BALL_SPEED = 80
var ball_speed = INITIAL_BALL_SPEED
-var screen_size = Vector2(640,400)
-#default ball direction
-var direction = Vector2(-1,0)
-var pad_size = Vector2(8,32)
+var screen_size = Vector2(640, 400)
+
+# Default ball direction
+var direction = Vector2(-1, 0)
+var pad_size = Vector2(8, 32)
const PAD_SPEED = 150
func _process(delta):
-
-
- #get ball position and pad rectangles
+ # Get ball position and pad rectangles
var ball_pos = get_node("ball").get_pos()
- var left_rect = Rect2( get_node("left").get_pos() - pad_size*0.5, pad_size )
- var right_rect = Rect2( get_node("right").get_pos() - pad_size*0.5, pad_size )
+ var left_rect = Rect2(get_node("left").get_pos() - pad_size*0.5, pad_size)
+ var right_rect = Rect2(get_node("right").get_pos() - pad_size*0.5, pad_size)
- #integrate new ball postion
- ball_pos+=direction*ball_speed*delta
+ # Integrate new ball postion
+ ball_pos += direction*ball_speed*delta
- #flip when touching roof or floor
- if ( (ball_pos.y<0 and direction.y <0) or (ball_pos.y>screen_size.y and direction.y>0)):
+ # Flip when touching roof or floor
+ if ((ball_pos.y < 0 and direction.y < 0) or (ball_pos.y > screen_size.y and direction.y > 0)):
direction.y = -direction.y
-
- #flip, change direction and increase speed when touching pads
- if ( (left_rect.has_point(ball_pos) and direction.x < 0) or (right_rect.has_point(ball_pos) and direction.x > 0)):
- direction.x=-direction.x
- ball_speed*=1.1
- direction.y=randf()*2.0-1
+
+ # Flip, change direction and increase speed when touching pads
+ if ((left_rect.has_point(ball_pos) and direction.x < 0) or (right_rect.has_point(ball_pos) and direction.x > 0)):
+ direction.x = -direction.x
+ ball_speed *= 1.1
+ direction.y = randf()*2.0 - 1
direction = direction.normalized()
-
- #check gameover
- if (ball_pos.x<0 or ball_pos.x>screen_size.x):
- ball_pos=screen_size*0.5
- ball_speed=INITIAL_BALL_SPEED
- direction=Vector2(-1,0)
-
-
+
+ # Check gameover
+ if (ball_pos.x < 0 or ball_pos.x > screen_size.x):
+ ball_pos = screen_size*0.5
+ ball_speed = INITIAL_BALL_SPEED
+ direction = Vector2(-1, 0)
+
get_node("ball").set_pos(ball_pos)
-
- #move left pad
+
+ # Move left pad
var left_pos = get_node("left").get_pos()
if (left_pos.y > 0 and Input.is_action_pressed("left_move_up")):
- left_pos.y+=-PAD_SPEED*delta
+ left_pos.y += -PAD_SPEED*delta
if (left_pos.y < screen_size.y and Input.is_action_pressed("left_move_down")):
- left_pos.y+=PAD_SPEED*delta
-
+ left_pos.y += PAD_SPEED*delta
+
get_node("left").set_pos(left_pos)
-
- #move right pad
+
+ # Move right pad
var right_pos = get_node("right").get_pos()
if (right_pos.y > 0 and Input.is_action_pressed("right_move_up")):
- right_pos.y+=-PAD_SPEED*delta
+ right_pos.y += -PAD_SPEED*delta
if (right_pos.y < screen_size.y and Input.is_action_pressed("right_move_down")):
- right_pos.y+=PAD_SPEED*delta
-
- get_node("right").set_pos(right_pos)
+ right_pos.y += PAD_SPEED*delta
-
+ get_node("right").set_pos(right_pos)
+
func _ready():
- screen_size = get_viewport_rect().size #get actual size
+ screen_size = get_viewport_rect().size # Get actual size
pad_size = get_node("left").get_texture().get_size()
set_process(true)
-
diff --git a/demos/2d/pong/pong.xml b/demos/2d/pong/pong.xml
index cf47a8db9f..2189be7c62 100644
--- a/demos/2d/pong/pong.xml
+++ b/demos/2d/pong/pong.xml
@@ -1,153 +1,170 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="6" version="0.99" version_name="Godot Engine v0.99.3735-pre-beta">
- <ext_resource path="res://pong.*" type="GDScript"></ext_resource>
- <ext_resource path="res://separator.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://left_pallete.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://right_pallete.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://ball.*" type="ImageTexture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="6" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://pong.gd" type="Script" index="0"></ext_resource>
+ <ext_resource path="res://left_pallete.png" type="Texture" index="1"></ext_resource>
+ <ext_resource path="res://separator.png" type="Texture" index="3"></ext_resource>
+ <ext_resource path="res://right_pallete.png" type="Texture" index="2"></ext_resource>
+ <ext_resource path="res://ball.png" type="Texture" index="4"></ext_resource>
<main_resource>
<dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="27">
+ <string_array len="11">
<string> "game" </string>
- <string> "Node2D" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
<string> "script/script" </string>
<string> "__meta__" </string>
+ <string> "Node2D" </string>
<string> "left" </string>
- <string> "Sprite" </string>
+ <string> "transform/pos" </string>
<string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
+ <string> "Sprite" </string>
<string> "right" </string>
<string> "separator" </string>
<string> "ball" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
<string> "node_count" </string>
<int> 5 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="55"> -1, -1, 3, 0, -1, 2, 1, 0, 2, 1, 0, 0, 0, 7, 4, -1, 2, 5, 2, 6, 3, 0, 0, 0, 7, 8, -1, 2, 5, 4, 6, 5, 0, 0, 0, 7, 9, -1, 2, 5, 6, 6, 7, 0, 0, 0, 7, 10, -1, 2, 5, 8, 6, 9, 0 </int_array>
<string> "variants" </string>
- <array len="20" shared="false">
- <bool> True </bool>
- <real> 1 </real>
- <vector2> 0, 0 </vector2>
- <real> 0 </real>
- <vector2> 1, 1 </vector2>
- <resource resource_type="GDScript" path="res://pong.*"> </resource>
+ <array len="10" shared="false">
+ <resource external="0"> </resource>
<dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "Script" </string>
<string> "__editor_plugin_states__" </string>
<dictionary shared="false">
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 0 </int>
- <string> "sources" </string>
- <array len="1" shared="false">
- <string> "res://pong.gd" </string>
- </array>
- </dictionary>
<string> "2D" </string>
<dictionary shared="false">
- <string> "pixel_snap" </string>
- <bool> True </bool>
- <string> "zoom" </string>
- <real> 1.108033 </real>
<string> "ofs" </string>
<vector2> -54.59, -36.0052 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
+ <string> "zoom" </string>
+ <real> 1.108033 </real>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
<string> "viewports" </string>
<array len="4" shared="false">
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
</array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -156,27 +173,18 @@
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "Script" </string>
</dictionary>
<vector2> 67.6875, 183.208 </vector2>
- <resource resource_type="ImageTexture" path="res://left_pallete.*"> </resource>
- <bool> False </bool>
- <int> 1 </int>
- <int> 0 </int>
- <color> 1, 1, 1, 1 </color>
- <rect2> 0, 0, 0, 0 </rect2>
+ <resource external="1"> </resource>
<vector2> 577, 187 </vector2>
- <resource resource_type="ImageTexture" path="res://right_pallete.*"> </resource>
+ <resource external="2"> </resource>
<vector2> 320, 200 </vector2>
- <resource resource_type="ImageTexture" path="res://separator.*"> </resource>
+ <resource external="3"> </resource>
<vector2> 320.283, 188 </vector2>
- <resource resource_type="ImageTexture" path="res://ball.*"> </resource>
+ <resource external="4"> </resource>
</array>
- <string> "nodes" </string>
- <int_array len="197"> -1, -1, 1, 0, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 0, 0, 0, 12, 11, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 7, 7, 3, 8, 4, 13, 8, 14, 0, 15, 2, 16, 9, 17, 9, 18, 10, 19, 10, 20, 11, 21, 12, 22, 9, 23, 13, 0, 0, 0, 12, 24, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 14, 7, 3, 8, 4, 13, 15, 14, 0, 15, 2, 16, 9, 17, 9, 18, 10, 19, 10, 20, 11, 21, 12, 22, 9, 23, 13, 0, 0, 0, 12, 25, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 16, 7, 3, 8, 4, 13, 17, 14, 0, 15, 2, 16, 9, 17, 9, 18, 10, 19, 10, 20, 11, 21, 12, 22, 9, 23, 13, 0, 0, 0, 12, 26, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 18, 7, 3, 8, 4, 13, 19, 14, 0, 15, 2, 16, 9, 17, 9, 18, 10, 19, 10, 20, 11, 21, 12, 22, 9, 23, 13, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/rubegoldberg/ball.xml b/demos/2d/rubegoldberg/ball.xml
index 625438eb75..73b699514c 100644
--- a/demos/2d/rubegoldberg/ball.xml
+++ b/demos/2d/rubegoldberg/ball.xml
@@ -1,171 +1,200 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="3" version="0.99" version_name="Godot Engine v0.99.3656-pre-beta">
- <ext_resource path="res://art/bowling_ball.*" type="ImageTexture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="3" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://art/bowling_ball.png" type="Texture" index="0"></ext_resource>
<resource type="CircleShape2D" path="local://1">
- <string name="resource/name"> "" </string>
<real name="custom_solver_bias"> 0 </real>
<real name="radius"> 32 </real>
- <resource name="script/script"></resource>
+
</resource>
<main_resource>
- <string name="resource/name"> "" </string>
<dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="48">
+ <string_array len="30">
<string> "Ball" </string>
- <string> "RigidBody2D" </string>
- <string> "process/process" </string>
- <string> "process/fixed_process" </string>
- <string> "process/input" </string>
- <string> "process/unhandled_input" </string>
- <string> "process/pause_mode" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "visibility/blend_mode" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
- <string> "shape_count" </string>
+ <string> "input/pickable" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
<string> "shapes/0/trigger" </string>
+ <string> "collision/layers" </string>
+ <string> "collision/mask" </string>
<string> "mode" </string>
<string> "mass" </string>
<string> "friction" </string>
<string> "bounce" </string>
+ <string> "gravity_scale" </string>
<string> "custom_integrator" </string>
<string> "continuous_cd" </string>
<string> "contacts_reported" </string>
<string> "contact_monitor" </string>
- <string> "active" </string>
+ <string> "sleeping" </string>
<string> "can_sleep" </string>
<string> "velocity/linear" </string>
<string> "velocity/angular" </string>
- <string> "script/script" </string>
+ <string> "damp_override/linear" </string>
+ <string> "damp_override/angular" </string>
<string> "__meta__" </string>
+ <string> "RigidBody2D" </string>
<string> "Sprite" </string>
<string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
<string> "CollisionShape2D" </string>
<string> "shape" </string>
<string> "trigger" </string>
+ <string> "_update_shape_index" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
<string> "node_count" </string>
<int> 3 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="73"> -1, -1, 23, 0, -1, 22, 1, 0, 2, 1, 3, 2, 4, 0, 5, 3, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11, 6, 12, 0, 13, 4, 14, 4, 15, 0, 16, 0, 17, 8, 18, 9, 19, 7, 20, 10, 21, 10, 22, 11, 0, 0, 0, 24, 24, -1, 1, 25, 12, 0, 0, 0, 26, 26, -1, 3, 27, 1, 28, 0, 29, 13, 0 </int_array>
<string> "variants" </string>
- <array len="16" shared="true">
+ <array len="14" shared="false">
<bool> False </bool>
+ <resource resource_type="Shape2D" path="local://1"> </resource>
+ <matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
+ <int> 1 </int>
<int> 0 </int>
- <bool> True </bool>
+ <real> 3 </real>
<real> 1 </real>
- <vector2> 0, 0 </vector2>
<real> 0 </real>
- <vector2> 1, 1 </vector2>
- <int> 1 </int>
- <resource resource_type="CircleShape2D" path="local://1"> </resource>
- <matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
- <real> 3 </real>
- <resource name=""></resource> <dictionary shared="false">
+ <bool> True </bool>
+ <vector2> 0, 0 </vector2>
+ <real> -1 </real>
+ <dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
<dictionary shared="false">
<string> "2D" </string>
<dictionary shared="false">
- <string> "zoom" </string>
- <real> 1.50734 </real>
<string> "ofs" </string>
<vector2> -80.5995, -149.825 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
+ <string> "zoom" </string>
+ <real> 1.50734 </real>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
<string> "viewports" </string>
- <array len="4" shared="true">
+ <array len="4" shared="false">
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
</array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -174,18 +203,13 @@
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "Script" </string>
</dictionary>
- <resource resource_type="ImageTexture" path="res://art/bowling_ball.*"> </resource>
- <color> 1, 1, 1, 1 </color>
- <rect2> 0, 0, 0, 0 </rect2>
+ <resource external="0"> </resource>
+ <int> -1 </int>
</array>
- <string> "nodes" </string>
- <int_array len="165"> -1, -1, 1, 0, -1, 31, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 3, 9, 3, 10, 2, 11, 1, 12, 4, 13, 5, 14, 6, 15, 7, 16, 8, 17, 9, 18, 0, 19, 1, 20, 10, 21, 3, 22, 5, 23, 0, 24, 0, 25, 1, 26, 0, 27, 2, 28, 2, 29, 4, 30, 5, 31, 11, 32, 12, 0, 0, 0, 33, 33, -1, 25, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 3, 9, 3, 10, 2, 11, 1, 12, 4, 13, 5, 14, 6, 34, 13, 35, 2, 36, 4, 37, 0, 38, 0, 39, 7, 40, 7, 41, 1, 42, 14, 43, 0, 44, 15, 31, 11, 0, 0, 0, 45, 45, -1, 16, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 3, 9, 3, 10, 2, 11, 1, 12, 4, 13, 5, 14, 6, 46, 8, 47, 0, 31, 11, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
- <resource name="script/script"></resource>
+
</main_resource>
</resource_file> \ No newline at end of file
diff --git a/demos/2d/rubegoldberg/box.xml b/demos/2d/rubegoldberg/box.xml
index c715326ae0..c30d30e9f9 100644
--- a/demos/2d/rubegoldberg/box.xml
+++ b/demos/2d/rubegoldberg/box.xml
@@ -1,142 +1,214 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="3" version="0.99" version_name="Godot Engine v0.99.2864-pre-beta">
- <ext_resource path="res://art/box.png" type="Texture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="3" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://art/box.png" type="Texture" index="0"></ext_resource>
<resource type="RectangleShape2D" path="local://1">
- <string name="resource/name"> "" </string>
<real name="custom_solver_bias"> 0 </real>
<vector2 name="extents"> 32, 32 </vector2>
- <resource name="script/script"></resource>
+
</resource>
<main_resource>
- <string name="resource/name"> "" </string>
- <dictionary name="_bundled">
+ <dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="48">
+ <string_array len="30">
<string> "box" </string>
- <string> "RigidBody2D" </string>
- <string> "process/process" </string>
- <string> "process/fixed_process" </string>
- <string> "process/input" </string>
- <string> "process/unhandled_input" </string>
- <string> "process/mode" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/toplevel" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "visibility/blend_mode" </string>
- <string> "transform/notify" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
- <string> "shape_count" </string>
+ <string> "input/pickable" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
+ <string> "shapes/0/trigger" </string>
+ <string> "collision/layers" </string>
+ <string> "collision/mask" </string>
<string> "mode" </string>
<string> "mass" </string>
<string> "friction" </string>
<string> "bounce" </string>
+ <string> "gravity_scale" </string>
<string> "custom_integrator" </string>
<string> "continuous_cd" </string>
<string> "contacts_reported" </string>
<string> "contact_monitor" </string>
- <string> "active" </string>
+ <string> "sleeping" </string>
<string> "can_sleep" </string>
<string> "velocity/linear" </string>
<string> "velocity/angular" </string>
- <string> "script/script" </string>
+ <string> "damp_override/linear" </string>
+ <string> "damp_override/angular" </string>
<string> "__meta__" </string>
+ <string> "RigidBody2D" </string>
<string> "Sprite" </string>
<string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
<string> "CollisionShape2D" </string>
<string> "shape" </string>
+ <string> "trigger" </string>
+ <string> "_update_shape_index" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
<string> "node_count" </string>
<int> 3 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="73"> -1, -1, 23, 0, -1, 22, 1, 0, 2, 1, 3, 2, 4, 0, 5, 3, 6, 3, 7, 4, 8, 5, 9, 5, 10, 6, 11, 5, 12, 0, 13, 4, 14, 4, 15, 0, 16, 0, 17, 7, 18, 8, 19, 6, 20, 9, 21, 9, 22, 10, 0, 0, 0, 24, 24, -1, 1, 25, 11, 0, 0, 0, 26, 26, -1, 3, 27, 1, 28, 0, 29, 12, 0 </int_array>
<string> "variants" </string>
- <array len="15">
+ <array len="13" shared="false">
<bool> False </bool>
+ <resource resource_type="Shape2D" path="local://1"> </resource>
+ <matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
+ <int> 1 </int>
<int> 0 </int>
- <bool> True </bool>
<real> 1 </real>
- <vector2> 0, 0 </vector2>
<real> 0 </real>
- <vector2> 1, 1 </vector2>
- <int> 1 </int>
- <resource resource_type="RectangleShape2D" path="local://1"> </resource>
- <matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
- <resource name=""></resource> <dictionary>
+ <bool> True </bool>
+ <vector2> 0, 0 </vector2>
+ <real> -1 </real>
+ <dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
- <dictionary>
+ <dictionary shared="false">
<string> "2D" </string>
- <dictionary>
- <string> "zoom" </string>
- <real> 1 </real>
+ <dictionary shared="false">
<string> "ofs" </string>
<vector2> -125, -163 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
+ <string> "zoom" </string>
+ <real> 1 </real>
</dictionary>
<string> "3D" </string>
- <dictionary>
- <string> "zfar" </string>
- <real> 500 </real>
+ <dictionary shared="false">
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
- <string> "window_mode" </string>
- <int> 0 </int>
- <string> "window_0" </string>
- <dictionary>
- <string> "distance" </string>
- <real> 4 </real>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "x_rot" </string>
- <real> 0.337 </real>
- <string> "y_rot" </string>
- <real> -0.575 </real>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
+ <string> "viewports" </string>
+ <array len="4" shared="false">
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ </array>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
- <dictionary>
+ <dictionary shared="false">
<string> "custom_args" </string>
<string> "-l $scene" </string>
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
- <resource resource_type="Texture" path="res://art/box.png"> </resource>
- <color> 1, 1, 1, 1 </color>
- <rect2> 0, 0, 0, 0 </rect2>
+ <resource external="0"> </resource>
+ <int> -1 </int>
</array>
- <string> "nodes" </string>
- <int_array len="173"> -1, -1, 1, 0, -1, 32, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 2, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 1, 21, 3, 22, 3, 23, 5, 24, 0, 25, 0, 26, 1, 27, 0, 28, 2, 29, 2, 30, 4, 31, 5, 32, 10, 33, 11, 0, 0, 0, 34, 34, -1, 27, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 0, 14, 4, 15, 5, 16, 6, 35, 12, 36, 2, 37, 4, 38, 0, 39, 0, 40, 7, 41, 7, 42, 1, 43, 13, 44, 0, 45, 14, 32, 10, 0, 0, 0, 46, 46, -1, 17, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 2, 14, 4, 15, 5, 16, 6, 47, 8, 32, 10, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
- <resource name="script/script"></resource>
+
</main_resource>
</resource_file> \ No newline at end of file
diff --git a/demos/2d/rubegoldberg/domino.xml b/demos/2d/rubegoldberg/domino.xml
index 324bf57e66..ec86c833df 100644
--- a/demos/2d/rubegoldberg/domino.xml
+++ b/demos/2d/rubegoldberg/domino.xml
@@ -1,143 +1,215 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="3" version="0.99" version_name="Godot Engine v0.99.2864-pre-beta">
- <ext_resource path="res://art/domino.png" type="Texture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="3" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://art/domino.png" type="Texture" index="0"></ext_resource>
<resource type="RectangleShape2D" path="local://1">
- <string name="resource/name"> "" </string>
<real name="custom_solver_bias"> 0 </real>
<vector2 name="extents"> 16, 64 </vector2>
- <resource name="script/script"></resource>
+
</resource>
<main_resource>
- <string name="resource/name"> "" </string>
- <dictionary name="_bundled">
+ <dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="48">
+ <string_array len="30">
<string> "domino" </string>
- <string> "RigidBody2D" </string>
- <string> "process/process" </string>
- <string> "process/fixed_process" </string>
- <string> "process/input" </string>
- <string> "process/unhandled_input" </string>
- <string> "process/mode" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/toplevel" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "visibility/blend_mode" </string>
- <string> "transform/notify" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
- <string> "shape_count" </string>
+ <string> "input/pickable" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
+ <string> "shapes/0/trigger" </string>
+ <string> "collision/layers" </string>
+ <string> "collision/mask" </string>
<string> "mode" </string>
<string> "mass" </string>
<string> "friction" </string>
<string> "bounce" </string>
+ <string> "gravity_scale" </string>
<string> "custom_integrator" </string>
<string> "continuous_cd" </string>
<string> "contacts_reported" </string>
<string> "contact_monitor" </string>
- <string> "active" </string>
+ <string> "sleeping" </string>
<string> "can_sleep" </string>
<string> "velocity/linear" </string>
<string> "velocity/angular" </string>
- <string> "script/script" </string>
+ <string> "damp_override/linear" </string>
+ <string> "damp_override/angular" </string>
<string> "__meta__" </string>
+ <string> "RigidBody2D" </string>
<string> "Sprite" </string>
<string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
<string> "CollisionShape2D" </string>
<string> "shape" </string>
+ <string> "trigger" </string>
+ <string> "_update_shape_index" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
<string> "node_count" </string>
<int> 3 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="73"> -1, -1, 23, 0, -1, 22, 1, 0, 2, 1, 3, 2, 4, 0, 5, 3, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11, 5, 12, 0, 13, 4, 14, 4, 15, 0, 16, 0, 17, 8, 18, 9, 19, 7, 20, 10, 21, 10, 22, 11, 0, 0, 0, 24, 24, -1, 1, 25, 12, 0, 0, 0, 26, 26, -1, 3, 27, 1, 28, 0, 29, 13, 0 </int_array>
<string> "variants" </string>
- <array len="16">
+ <array len="14" shared="false">
<bool> False </bool>
+ <resource resource_type="Shape2D" path="local://1"> </resource>
+ <matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
+ <int> 1 </int>
<int> 0 </int>
- <bool> True </bool>
<real> 1 </real>
- <vector2> 0, 0 </vector2>
- <real> 0 </real>
- <vector2> 1, 1 </vector2>
- <int> 1 </int>
- <resource resource_type="RectangleShape2D" path="local://1"> </resource>
- <matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
<real> 0.5 </real>
- <resource name=""></resource> <dictionary>
+ <real> 0 </real>
+ <bool> True </bool>
+ <vector2> 0, 0 </vector2>
+ <real> -1 </real>
+ <dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
- <dictionary>
+ <dictionary shared="false">
<string> "2D" </string>
- <dictionary>
- <string> "zoom" </string>
- <real> 1 </real>
+ <dictionary shared="false">
<string> "ofs" </string>
<vector2> -135, -114 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
+ <string> "zoom" </string>
+ <real> 1 </real>
</dictionary>
<string> "3D" </string>
- <dictionary>
- <string> "zfar" </string>
- <real> 500 </real>
+ <dictionary shared="false">
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
- <string> "window_mode" </string>
- <int> 0 </int>
- <string> "window_0" </string>
- <dictionary>
- <string> "distance" </string>
- <real> 4 </real>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "x_rot" </string>
- <real> 0.337 </real>
- <string> "y_rot" </string>
- <real> -0.575 </real>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
+ <string> "viewports" </string>
+ <array len="4" shared="false">
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ </array>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
- <dictionary>
+ <dictionary shared="false">
<string> "custom_args" </string>
<string> "-l $scene" </string>
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
- <resource resource_type="Texture" path="res://art/domino.png"> </resource>
- <color> 1, 1, 1, 1 </color>
- <rect2> 0, 0, 0, 0 </rect2>
+ <resource external="0"> </resource>
+ <int> -1 </int>
</array>
- <string> "nodes" </string>
- <int_array len="173"> -1, -1, 1, 0, -1, 32, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 2, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 1, 21, 3, 22, 10, 23, 5, 24, 0, 25, 0, 26, 1, 27, 0, 28, 2, 29, 2, 30, 4, 31, 5, 32, 11, 33, 12, 0, 0, 0, 34, 34, -1, 27, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 0, 14, 4, 15, 5, 16, 6, 35, 13, 36, 2, 37, 4, 38, 0, 39, 0, 40, 7, 41, 7, 42, 1, 43, 14, 44, 0, 45, 15, 32, 11, 0, 0, 0, 46, 46, -1, 17, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 2, 14, 4, 15, 5, 16, 6, 47, 8, 32, 11, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
- <resource name="script/script"></resource>
+
</main_resource>
</resource_file> \ No newline at end of file
diff --git a/demos/2d/rubegoldberg/pendulum.xml b/demos/2d/rubegoldberg/pendulum.xml
index 2a5378ff2f..90ad45f287 100644
--- a/demos/2d/rubegoldberg/pendulum.xml
+++ b/demos/2d/rubegoldberg/pendulum.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="5" version="0.99" version_name="Godot Engine v0.99.3735-pre-beta">
- <ext_resource path="res://art/bowling_ball.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://art/box.*" type="ImageTexture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="5" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://art/bowling_ball.png" type="Texture" index="1"></ext_resource>
+ <ext_resource path="res://art/box.png" type="Texture" index="0"></ext_resource>
<resource type="RectangleShape2D" path="local://1">
<real name="custom_solver_bias"> 0 </real>
<vector2 name="extents"> 3, 12 </vector2>
@@ -14,165 +14,201 @@
</resource>
<main_resource>
<dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="57">
+ <string_array len="49">
<string> "pendulum" </string>
- <string> "Node2D" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
<string> "__meta__" </string>
+ <string> "Node2D" </string>
<string> "union_0" </string>
- <string> "RigidBody2D" </string>
- <string> "shape_count" </string>
+ <string> "input/pickable" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
<string> "shapes/0/trigger" </string>
+ <string> "collision/layers" </string>
+ <string> "collision/mask" </string>
<string> "mode" </string>
<string> "mass" </string>
<string> "friction" </string>
<string> "bounce" </string>
+ <string> "gravity_scale" </string>
<string> "custom_integrator" </string>
<string> "continuous_cd" </string>
<string> "contacts_reported" </string>
<string> "contact_monitor" </string>
- <string> "active" </string>
+ <string> "sleeping" </string>
<string> "can_sleep" </string>
<string> "velocity/linear" </string>
<string> "velocity/angular" </string>
+ <string> "damp_override/linear" </string>
+ <string> "damp_override/angular" </string>
+ <string> "RigidBody2D" </string>
<string> "Sprite" </string>
+ <string> "transform/scale" </string>
<string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
<string> "collision" </string>
- <string> "CollisionShape2D" </string>
<string> "shape" </string>
<string> "trigger" </string>
+ <string> "_update_shape_index" </string>
+ <string> "CollisionShape2D" </string>
<string> "union_ 2" </string>
+ <string> "transform/pos" </string>
<string> "union_ 3" </string>
<string> "union_ 4" </string>
<string> "joint1" </string>
- <string> "PinJoint2D" </string>
<string> "node_a" </string>
<string> "node_b" </string>
<string> "bias/bias" </string>
+ <string> "softness" </string>
+ <string> "PinJoint2D" </string>
<string> "joint 2_3" </string>
<string> "joint 3_4" </string>
<string> "ball" </string>
<string> "joint 4_ball" </string>
<string> "joint wall" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
<string> "node_count" </string>
<int> 21 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="479"> -1, -1, 2, 0, -1, 1, 1, 0, 0, 0, 0, 25, 3, -1, 22, 4, 1, 5, 2, 6, 3, 7, 1, 8, 4, 9, 4, 10, 5, 11, 6, 12, 7, 13, 8, 14, 7, 15, 1, 16, 5, 17, 5, 18, 1, 19, 1, 20, 9, 21, 10, 22, 8, 23, 11, 24, 11, 1, 12, 0, 1, 0, 26, 26, -1, 2, 27, 13, 28, 14, 0, 1, 0, 33, 29, -1, 3, 30, 2, 31, 1, 32, 15, 0, 0, 0, 25, 34, -1, 23, 35, 16, 4, 1, 5, 2, 6, 17, 7, 1, 8, 4, 9, 4, 10, 5, 11, 6, 12, 7, 13, 8, 14, 7, 15, 1, 16, 5, 17, 5, 18, 1, 19, 1, 20, 9, 21, 10, 22, 8, 23, 11, 24, 11, 1, 18, 0, 4, 0, 26, 26, -1, 2, 27, 13, 28, 14, 0, 4, 0, 33, 29, -1, 3, 30, 2, 31, 1, 32, 15, 0, 0, 0, 25, 36, -1, 23, 35, 19, 4, 1, 5, 2, 6, 17, 7, 1, 8, 4, 9, 4, 10, 5, 11, 6, 12, 7, 13, 8, 14, 7, 15, 1, 16, 5, 17, 5, 18, 1, 19, 1, 20, 9, 21, 10, 22, 8, 23, 11, 24, 11, 1, 18, 0, 7, 0, 26, 26, -1, 2, 27, 13, 28, 14, 0, 7, 0, 33, 29, -1, 3, 30, 2, 31, 1, 32, 15, 0, 0, 0, 25, 37, -1, 23, 35, 20, 4, 1, 5, 2, 6, 17, 7, 1, 8, 4, 9, 4, 10, 5, 11, 6, 12, 7, 13, 8, 14, 7, 15, 1, 16, 5, 17, 5, 18, 1, 19, 1, 20, 9, 21, 10, 22, 8, 23, 11, 24, 11, 1, 18, 0, 10, 0, 26, 26, -1, 2, 27, 13, 28, 14, 0, 10, 0, 33, 29, -1, 3, 30, 2, 31, 1, 32, 15, 0, 0, 0, 43, 38, -1, 5, 35, 21, 39, 22, 40, 23, 41, 8, 42, 8, 0, 0, 0, 43, 44, -1, 5, 35, 24, 39, 23, 40, 25, 41, 8, 42, 8, 0, 0, 0, 43, 45, -1, 5, 35, 26, 39, 25, 40, 27, 41, 6, 42, 8, 0, 0, 0, 25, 46, -1, 24, 35, 28, 27, 29, 4, 1, 5, 30, 6, 17, 7, 1, 8, 4, 9, 4, 10, 5, 11, 6, 12, 7, 13, 8, 14, 7, 15, 1, 16, 5, 17, 5, 18, 1, 19, 1, 20, 9, 21, 10, 22, 8, 23, 11, 24, 11, 1, 18, 0, 16, 0, 26, 26, -1, 2, 27, 31, 28, 32, 0, 16, 0, 33, 29, -1, 3, 30, 30, 31, 1, 32, 15, 0, 0, 0, 43, 47, -1, 5, 35, 33, 39, 27, 40, 34, 41, 8, 42, 8, 0, 0, 0, 43, 48, -1, 5, 35, 35, 39, 22, 40, 36, 41, 8, 42, 8, 0 </int_array>
<string> "variants" </string>
- <array len="38" shared="false">
- <bool> True </bool>
- <real> 1 </real>
- <vector2> 0, 0 </vector2>
- <real> 0 </real>
- <vector2> 1, 1 </vector2>
+ <array len="37" shared="false">
<dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
<dictionary shared="false">
<string> "2D" </string>
<dictionary shared="false">
- <string> "zoom" </string>
- <real> 2.78951 </real>
<string> "ofs" </string>
<vector2> -121.028, 0.923909 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
+ <string> "zoom" </string>
+ <real> 2.78951 </real>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
<string> "viewports" </string>
<array len="4" shared="false">
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
</array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -181,23 +217,25 @@
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
- <int> 1 </int>
- <resource resource_type="RectangleShape2D" path="local://1"> </resource>
- <matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
<bool> False </bool>
+ <resource resource_type="Shape2D" path="local://1"> </resource>
+ <matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
+ <int> 1 </int>
<int> 0 </int>
<real> 0.2 </real>
+ <real> 1 </real>
+ <real> 0 </real>
+ <bool> True </bool>
+ <vector2> 0, 0 </vector2>
+ <real> -1 </real>
<dictionary shared="false">
<string> "_edit_group_" </string>
<bool> True </bool>
</dictionary>
<vector2> 0.1, 0.4 </vector2>
- <resource resource_type="ImageTexture" path="res://art/box.*"> </resource>
- <color> 1, 1, 1, 1 </color>
- <rect2> 0, 0, 0, 0 </rect2>
+ <resource external="0"> </resource>
+ <int> -1 </int>
<vector2> 0, 26.9432 </vector2>
<matrix32> 1, -0, 0, 1, 0, 0 </matrix32>
<dictionary shared="false">
@@ -215,18 +253,16 @@
<node_path> "../union_ 4" </node_path>
<vector2> 0, 106.787 </vector2>
<vector2> 0.98476, 1 </vector2>
- <resource resource_type="CircleShape2D" path="local://2"> </resource>
+ <resource resource_type="Shape2D" path="local://2"> </resource>
<vector2> 0.5, 0.5 </vector2>
- <resource resource_type="ImageTexture" path="res://art/bowling_ball.*"> </resource>
+ <resource external="1"> </resource>
<vector2> 0, 92.5287 </vector2>
<node_path> "../ball" </node_path>
<vector2> 0, -12.1024 </vector2>
<node_path> "" </node_path>
</array>
- <string> "nodes" </string>
- <int_array len="773"> -1, -1, 1, 0, -1, 8, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 0, 0, 0, 11, 10, -1, 24, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 12, 6, 13, 7, 14, 8, 15, 9, 16, 10, 17, 11, 18, 1, 19, 3, 20, 9, 21, 9, 22, 10, 23, 9, 24, 0, 25, 0, 26, 2, 27, 3, 9, 12, 0, 1, 0, 28, 28, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 13, 29, 14, 30, 0, 31, 2, 32, 9, 33, 9, 34, 6, 35, 6, 36, 10, 37, 15, 38, 9, 39, 16, 0, 1, 0, 41, 40, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 42, 7, 43, 9, 0, 0, 0, 11, 44, -1, 24, 2, 0, 3, 1, 4, 1, 5, 0, 6, 17, 7, 3, 8, 4, 12, 6, 13, 7, 14, 18, 15, 9, 16, 10, 17, 11, 18, 1, 19, 3, 20, 9, 21, 9, 22, 10, 23, 9, 24, 0, 25, 0, 26, 2, 27, 3, 9, 19, 0, 4, 0, 28, 28, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 13, 29, 14, 30, 0, 31, 2, 32, 9, 33, 9, 34, 6, 35, 6, 36, 10, 37, 15, 38, 9, 39, 16, 0, 4, 0, 41, 40, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 42, 7, 43, 9, 0, 0, 0, 11, 45, -1, 24, 2, 0, 3, 1, 4, 1, 5, 0, 6, 20, 7, 3, 8, 4, 12, 6, 13, 7, 14, 18, 15, 9, 16, 10, 17, 11, 18, 1, 19, 3, 20, 9, 21, 9, 22, 10, 23, 9, 24, 0, 25, 0, 26, 2, 27, 3, 9, 19, 0, 7, 0, 28, 28, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 13, 29, 14, 30, 0, 31, 2, 32, 9, 33, 9, 34, 6, 35, 6, 36, 10, 37, 15, 38, 9, 39, 16, 0, 7, 0, 41, 40, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 42, 7, 43, 9, 0, 0, 0, 11, 46, -1, 24, 2, 0, 3, 1, 4, 1, 5, 0, 6, 21, 7, 3, 8, 4, 12, 6, 13, 7, 14, 18, 15, 9, 16, 10, 17, 11, 18, 1, 19, 3, 20, 9, 21, 9, 22, 10, 23, 9, 24, 0, 25, 0, 26, 2, 27, 3, 9, 19, 0, 10, 0, 28, 28, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 13, 29, 14, 30, 0, 31, 2, 32, 9, 33, 9, 34, 6, 35, 6, 36, 10, 37, 15, 38, 9, 39, 16, 0, 10, 0, 41, 40, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 42, 7, 43, 9, 0, 0, 0, 48, 47, -1, 10, 2, 0, 3, 1, 4, 1, 5, 0, 6, 22, 7, 3, 8, 4, 49, 23, 50, 24, 51, 3, 0, 0, 0, 48, 52, -1, 10, 2, 0, 3, 1, 4, 1, 5, 0, 6, 25, 7, 3, 8, 4, 49, 24, 50, 26, 51, 3, 0, 0, 0, 48, 53, -1, 10, 2, 0, 3, 1, 4, 1, 5, 0, 6, 27, 7, 3, 8, 4, 49, 26, 50, 28, 51, 11, 0, 0, 0, 11, 54, -1, 24, 2, 0, 3, 1, 4, 1, 5, 0, 6, 29, 7, 3, 8, 30, 12, 6, 13, 31, 14, 18, 15, 9, 16, 10, 17, 11, 18, 1, 19, 3, 20, 9, 21, 9, 22, 10, 23, 9, 24, 0, 25, 0, 26, 2, 27, 3, 9, 19, 0, 16, 0, 28, 28, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 32, 29, 33, 30, 0, 31, 2, 32, 9, 33, 9, 34, 6, 35, 6, 36, 10, 37, 15, 38, 9, 39, 16, 0, 16, 0, 41, 40, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 42, 31, 43, 9, 0, 0, 0, 48, 55, -1, 10, 2, 0, 3, 1, 4, 1, 5, 0, 6, 34, 7, 3, 8, 4, 49, 28, 50, 35, 51, 3, 0, 0, 0, 48, 56, -1, 10, 2, 0, 3, 1, 4, 1, 5, 0, 6, 36, 7, 3, 8, 4, 49, 23, 50, 37, 51, 3, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/rubegoldberg/platform.xml b/demos/2d/rubegoldberg/platform.xml
index 0cc8f4b137..09cd0fdda6 100644
--- a/demos/2d/rubegoldberg/platform.xml
+++ b/demos/2d/rubegoldberg/platform.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="3" version="0.99" version_name="Godot Engine v0.99.3735-pre-beta">
- <ext_resource path="res://art/platform.*" type="ImageTexture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="3" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://art/platform.png" type="Texture" index="0"></ext_resource>
<resource type="RectangleShape2D" path="local://1">
<real name="custom_solver_bias"> 0 </real>
<vector2 name="extents"> 128, 16 </vector2>
@@ -8,148 +8,178 @@
</resource>
<main_resource>
<dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="34">
+ <string_array len="19">
<string> "platform" </string>
- <string> "StaticBody2D" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
- <string> "shape_count" </string>
+ <string> "input/pickable" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
<string> "shapes/0/trigger" </string>
- <string> "simulate_motion" </string>
+ <string> "collision/layers" </string>
+ <string> "collision/mask" </string>
<string> "constant_linear_velocity" </string>
<string> "constant_angular_velocity" </string>
<string> "friction" </string>
<string> "bounce" </string>
<string> "__meta__" </string>
+ <string> "StaticBody2D" </string>
<string> "Sprite" </string>
<string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
<string> "CollisionShape2D" </string>
<string> "shape" </string>
<string> "trigger" </string>
+ <string> "_update_shape_index" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
<string> "node_count" </string>
<int> 3 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="51"> -1, -1, 12, 0, -1, 11, 1, 0, 2, 1, 3, 2, 4, 0, 5, 3, 6, 3, 7, 4, 8, 5, 9, 6, 10, 5, 11, 7, 0, 0, 0, 13, 13, -1, 1, 14, 8, 0, 0, 0, 15, 15, -1, 3, 16, 1, 17, 0, 18, 9, 0 </int_array>
<string> "variants" </string>
- <array len="14" shared="false">
- <bool> True </bool>
- <real> 1 </real>
+ <array len="10" shared="false">
+ <bool> False </bool>
+ <resource resource_type="Shape2D" path="local://1"> </resource>
+ <matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
+ <int> 1 </int>
<vector2> 0, 0 </vector2>
<real> 0 </real>
- <vector2> 1, 1 </vector2>
- <int> 1 </int>
- <resource resource_type="RectangleShape2D" path="local://1"> </resource>
- <matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
- <bool> False </bool>
+ <real> 1 </real>
<dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
<dictionary shared="false">
<string> "2D" </string>
<dictionary shared="false">
- <string> "pixel_snap" </string>
+ <string> "ofs" </string>
+ <vector2> -135, -114 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
<bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
<string> "zoom" </string>
<real> 1 </real>
- <string> "ofs" </string>
- <vector2> -135, -114 </vector2>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
<string> "viewports" </string>
<array len="4" shared="false">
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
</array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -158,18 +188,12 @@
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
- <resource resource_type="ImageTexture" path="res://art/platform.*"> </resource>
- <int> 0 </int>
- <color> 1, 1, 1, 1 </color>
- <rect2> 0, 0, 0, 0 </rect2>
+ <resource external="0"> </resource>
+ <int> -1 </int>
</array>
- <string> "nodes" </string>
- <int_array len="109"> -1, -1, 1, 0, -1, 17, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 8, 13, 8, 14, 2, 15, 3, 16, 1, 17, 3, 18, 9, 0, 0, 0, 19, 19, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 20, 10, 21, 0, 22, 2, 23, 8, 24, 8, 25, 5, 26, 5, 27, 11, 28, 12, 29, 8, 30, 13, 0, 0, 0, 31, 31, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 32, 6, 33, 8, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/rubegoldberg/rubegoldberg.xml b/demos/2d/rubegoldberg/rubegoldberg.xml
index edb6dda0e1..490b0f9d34 100644
--- a/demos/2d/rubegoldberg/rubegoldberg.xml
+++ b/demos/2d/rubegoldberg/rubegoldberg.xml
@@ -1,25 +1,37 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="7" version="0.99" version_name="Godot Engine v0.99.3735-pre-beta">
- <ext_resource path="res://platform.*" type="PackedScene"></ext_resource>
- <ext_resource path="res://ball.*" type="PackedScene"></ext_resource>
- <ext_resource path="res://domino.*" type="PackedScene"></ext_resource>
- <ext_resource path="res://seesaw.*" type="PackedScene"></ext_resource>
- <ext_resource path="res://box.*" type="PackedScene"></ext_resource>
- <ext_resource path="res://pendulum.*" type="PackedScene"></ext_resource>
+<resource_file type="PackedScene" subresource_count="7" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://platform.xml" type="PackedScene" index="0"></ext_resource>
+ <ext_resource path="res://seesaw.xml" type="PackedScene" index="3"></ext_resource>
+ <ext_resource path="res://pendulum.xml" type="PackedScene" index="5"></ext_resource>
+ <ext_resource path="res://box.xml" type="PackedScene" index="4"></ext_resource>
+ <ext_resource path="res://ball.xml" type="PackedScene" index="1"></ext_resource>
+ <ext_resource path="res://domino.xml" type="PackedScene" index="2"></ext_resource>
<main_resource>
<dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="29">
+ <string_array len="33">
<string> "Node" </string>
<string> "__meta__" </string>
<string> "platform" </string>
- <string> "StaticBody2D" </string>
<string> "transform/pos" </string>
<string> "transform/rot" </string>
+ <string> "input/pickable" </string>
+ <string> "collision/layers" </string>
+ <string> "collision/mask" </string>
<string> "platform 2" </string>
<string> "platform 3" </string>
<string> "Ball" </string>
- <string> "RigidBody2D" </string>
+ <string> "gravity_scale" </string>
+ <string> "sleeping" </string>
+ <string> "damp_override/linear" </string>
+ <string> "damp_override/angular" </string>
<string> "domino" </string>
<string> "domino 2" </string>
<string> "domino 4" </string>
@@ -31,7 +43,6 @@
<string> "platform 7" </string>
<string> "platform 8" </string>
<string> "SeeSaw" </string>
- <string> "Node2D" </string>
<string> "box" </string>
<string> "pendulum" </string>
<string> "pendulum 2" </string>
@@ -40,102 +51,142 @@
<string> "Ball 5" </string>
<string> "velocity/linear" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
<string> "node_count" </string>
<int> 21 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="347"> -1, -1, 0, 0, -1, 1, 1, 0, 0, 0, 0, 2147483647, 2, 1, 5, 3, 2, 4, 3, 5, 4, 6, 5, 7, 5, 0, 0, 0, 2147483647, 8, 1, 4, 3, 6, 5, 4, 6, 5, 7, 5, 0, 0, 0, 2147483647, 9, 1, 4, 3, 7, 5, 4, 6, 5, 7, 5, 0, 0, 0, 2147483647, 10, 8, 8, 3, 9, 5, 4, 6, 5, 7, 5, 11, 10, 12, 4, 13, 11, 14, 11, 0, 0, 0, 2147483647, 15, 12, 8, 3, 13, 5, 4, 6, 5, 7, 5, 11, 10, 12, 4, 13, 11, 14, 11, 0, 0, 0, 2147483647, 16, 12, 8, 3, 14, 5, 4, 6, 5, 7, 5, 11, 10, 12, 4, 13, 11, 14, 11, 0, 0, 0, 2147483647, 17, 12, 8, 3, 15, 5, 4, 6, 5, 7, 5, 11, 10, 12, 4, 13, 11, 14, 11, 0, 0, 0, 2147483647, 18, 1, 5, 3, 16, 4, 17, 5, 4, 6, 5, 7, 5, 0, 0, 0, 2147483647, 19, 1, 6, 3, 18, 4, 19, 20, 20, 5, 4, 6, 5, 7, 5, 0, 0, 0, 2147483647, 21, 8, 8, 3, 21, 5, 4, 6, 5, 7, 5, 11, 10, 12, 4, 13, 11, 14, 11, 0, 0, 0, 2147483647, 22, 1, 4, 3, 22, 5, 4, 6, 5, 7, 5, 0, 0, 0, 2147483647, 23, 1, 4, 3, 23, 5, 4, 6, 5, 7, 5, 0, 0, 0, 2147483647, 24, 1, 4, 3, 24, 5, 4, 6, 5, 7, 5, 0, 0, 0, 2147483647, 25, 25, 1, 3, 26, 0, 0, 0, 2147483647, 26, 27, 9, 3, 28, 4, 29, 5, 4, 6, 5, 7, 5, 11, 10, 12, 4, 13, 11, 14, 11, 0, 0, 0, 2147483647, 27, 30, 1, 3, 31, 0, 0, 0, 2147483647, 28, 30, 1, 3, 32, 0, 0, 0, 2147483647, 29, 30, 1, 3, 33, 0, 0, 0, 2147483647, 30, 30, 1, 3, 34, 0, 0, 0, 2147483647, 31, 8, 9, 3, 35, 5, 4, 6, 5, 7, 5, 11, 10, 12, 4, 32, 36, 13, 11, 14, 11, 0 </int_array>
<string> "variants" </string>
- <array len="33" shared="false">
+ <array len="37" shared="false">
<dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
<dictionary shared="false">
<string> "2D" </string>
<dictionary shared="false">
- <string> "pixel_snap" </string>
+ <string> "ofs" </string>
+ <vector2> -717.096, -249.162 </vector2>
+ <string> "snap_grid" </string>
<bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
<string> "zoom" </string>
<real> 0.598737 </real>
- <string> "ofs" </string>
- <vector2> -15.4883, -75.0379 </vector2>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
<string> "viewports" </string>
<array len="4" shared="false">
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
</array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -144,17 +195,19 @@
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
- <resource resource_type="PackedScene" path="res://platform.*"> </resource>
+ <resource external="0"> </resource>
<vector2> 116.881, 145.589 </vector2>
<real> -20.87962 </real>
+ <bool> False </bool>
+ <int> 1 </int>
<vector2> 336.29, 264.52 </vector2>
<vector2> 526.99, 264.52 </vector2>
- <resource resource_type="PackedScene" path="res://ball.*"> </resource>
+ <resource external="1"> </resource>
<vector2> 76.0801, 67.2141 </vector2>
- <resource resource_type="PackedScene" path="res://domino.*"> </resource>
+ <real> 1 </real>
+ <real> -1 </real>
+ <resource external="2"> </resource>
<vector2> 262.764, 182.008 </vector2>
<vector2> 356.951, 182.008 </vector2>
<vector2> 448.834, 179.291 </vector2>
@@ -167,12 +220,12 @@
<vector2> 679.231, 588.598 </vector2>
<vector2> 424.491, 588.598 </vector2>
<vector2> 185.655, 588.598 </vector2>
- <resource resource_type="PackedScene" path="res://seesaw.*"> </resource>
+ <resource external="3"> </resource>
<vector2> 602.935, 554.501 </vector2>
- <resource resource_type="PackedScene" path="res://box.*"> </resource>
+ <resource external="4"> </resource>
<vector2> 476.002, 509.406 </vector2>
<real> 21.737282 </real>
- <resource resource_type="PackedScene" path="res://pendulum.*"> </resource>
+ <resource external="5"> </resource>
<vector2> 391.607, 305.444 </vector2>
<vector2> 343.172, 303.774 </vector2>
<vector2> 288.056, 303.774 </vector2>
@@ -180,10 +233,8 @@
<vector2> 116.165, 526.515 </vector2>
<vector2> 0, -200 </vector2>
</array>
- <string> "nodes" </string>
- <int_array len="201"> -1, -1, 0, 0, -1, 1, 1, 0, 0, 0, 0, 3, 2, 1, 2, 4, 2, 5, 3, 0, 0, 0, 3, 6, 1, 1, 4, 4, 0, 0, 0, 3, 7, 1, 1, 4, 5, 0, 0, 0, 9, 8, 6, 1, 4, 7, 0, 0, 0, 9, 10, 8, 1, 4, 9, 0, 0, 0, 9, 11, 8, 1, 4, 10, 0, 0, 0, 9, 12, 8, 1, 4, 11, 0, 0, 0, 3, 13, 1, 2, 4, 12, 5, 13, 0, 0, 0, 3, 14, 1, 3, 4, 14, 5, 15, 15, 16, 0, 0, 0, 9, 16, 6, 1, 4, 17, 0, 0, 0, 3, 17, 1, 1, 4, 18, 0, 0, 0, 3, 18, 1, 1, 4, 19, 0, 0, 0, 3, 19, 1, 1, 4, 20, 0, 0, 0, 21, 20, 21, 1, 4, 22, 0, 0, 0, 9, 22, 23, 2, 4, 24, 5, 25, 0, 0, 0, 21, 23, 26, 1, 4, 27, 0, 0, 0, 21, 24, 26, 1, 4, 28, 0, 0, 0, 21, 25, 26, 1, 4, 29, 0, 0, 0, 21, 26, 26, 1, 4, 30, 0, 0, 0, 9, 27, 6, 2, 4, 31, 28, 32, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/rubegoldberg/seesaw.xml b/demos/2d/rubegoldberg/seesaw.xml
index 30edbe9162..281e4e7c0d 100644
--- a/demos/2d/rubegoldberg/seesaw.xml
+++ b/demos/2d/rubegoldberg/seesaw.xml
@@ -1,169 +1,243 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="5" version="0.99" version_name="Godot Engine v0.99.2864-pre-beta">
- <ext_resource path="res://art/seesaw_top.png" type="Texture"></ext_resource>
- <ext_resource path="res://art/seesaw_base.png" type="Texture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="5" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://art/seesaw_top.png" type="Texture" index="1"></ext_resource>
+ <ext_resource path="res://art/seesaw_base.png" type="Texture" index="0"></ext_resource>
<resource type="ConcavePolygonShape2D" path="local://1">
- <string name="resource/name"> "" </string>
<real name="custom_solver_bias"> 0 </real>
<vector2_array name="segments" len="6"> -32.6231, 32.0838, -1.28218, -31.1383, -1.28218, -31.1383, 33.8412, 33.1645, 33.8412, 33.1645, -32.6231, 32.0838 </vector2_array>
- <resource name="script/script"></resource>
+
</resource>
<resource type="ConvexPolygonShape2D" path="local://2">
- <string name="resource/name"> "" </string>
<real name="custom_solver_bias"> 0 </real>
<vector2_array name="points" len="4"> -99.0874, 7.76759, -125.025, -8.98358, 125.162, -8.44321, 99.2248, 7.22723 </vector2_array>
- <resource name="script/script"></resource>
+
</resource>
<main_resource>
- <string name="resource/name"> "" </string>
- <dictionary name="_bundled">
+ <dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="58">
+ <string_array len="43">
<string> "SeeSaw" </string>
- <string> "Node2D" </string>
- <string> "process/process" </string>
- <string> "process/fixed_process" </string>
- <string> "process/input" </string>
- <string> "process/unhandled_input" </string>
- <string> "process/mode" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/toplevel" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "visibility/blend_mode" </string>
- <string> "transform/notify" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
- <string> "script/script" </string>
<string> "__meta__" </string>
+ <string> "Node2D" </string>
<string> "Sprite" </string>
<string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
<string> "StaticBody2D" </string>
- <string> "shape_count" </string>
+ <string> "input/pickable" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
- <string> "simulate_motion" </string>
+ <string> "shapes/0/trigger" </string>
+ <string> "collision/layers" </string>
+ <string> "collision/mask" </string>
<string> "constant_linear_velocity" </string>
<string> "constant_angular_velocity" </string>
+ <string> "friction" </string>
+ <string> "bounce" </string>
<string> "CollisionPolygon2D" </string>
<string> "build_mode" </string>
<string> "polygon" </string>
+ <string> "shape_range" </string>
+ <string> "trigger" </string>
<string> "RigidBody2D" </string>
+ <string> "transform/pos" </string>
+ <string> "transform/rot" </string>
<string> "mode" </string>
<string> "mass" </string>
- <string> "friction" </string>
- <string> "bounce" </string>
+ <string> "gravity_scale" </string>
<string> "custom_integrator" </string>
<string> "continuous_cd" </string>
<string> "contacts_reported" </string>
<string> "contact_monitor" </string>
- <string> "active" </string>
+ <string> "sleeping" </string>
<string> "can_sleep" </string>
<string> "velocity/linear" </string>
<string> "velocity/angular" </string>
+ <string> "damp_override/linear" </string>
+ <string> "damp_override/angular" </string>
+ <string> "transform/scale" </string>
<string> "PinJoint2D" </string>
<string> "node_a" </string>
<string> "node_b" </string>
<string> "bias/bias" </string>
+ <string> "softness" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
<string> "node_count" </string>
<int> 8 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="156"> -1, -1, 2, 0, -1, 1, 1, 0, 0, 0, 0, 3, 3, -1, 1, 4, 1, 0, 1, 0, 5, 5, -1, 10, 6, 2, 7, 3, 8, 4, 9, 2, 10, 5, 11, 5, 12, 6, 13, 7, 14, 8, 15, 7, 0, 2, 0, 16, 16, -1, 4, 17, 9, 18, 10, 19, 11, 20, 2, 0, 0, 0, 21, 21, -1, 23, 22, 12, 23, 13, 6, 2, 7, 14, 8, 4, 9, 2, 10, 5, 11, 5, 24, 9, 25, 8, 14, 8, 15, 7, 26, 8, 27, 2, 28, 9, 29, 9, 30, 2, 31, 2, 32, 15, 33, 6, 34, 7, 35, 16, 36, 16, 0, 4, 0, 3, 3, -1, 2, 37, 17, 4, 18, 0, 4, 0, 16, 16, -1, 4, 17, 9, 18, 19, 19, 11, 20, 2, 0, 0, 0, 38, 38, -1, 5, 22, 20, 39, 21, 40, 22, 41, 7, 42, 7, 0 </int_array>
<string> "variants" </string>
- <array len="25">
- <bool> False </bool>
- <int> 0 </int>
- <bool> True </bool>
- <real> 1 </real>
- <vector2> 0, 0 </vector2>
- <real> 0 </real>
- <vector2> 1, 1 </vector2>
- <resource name=""></resource> <dictionary>
+ <array len="23" shared="false">
+ <dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
- <dictionary>
+ <dictionary shared="false">
<string> "2D" </string>
- <dictionary>
- <string> "zoom" </string>
- <real> 1.670183 </real>
+ <dictionary shared="false">
<string> "ofs" </string>
<vector2> -277.779, -292.484 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
+ <string> "zoom" </string>
+ <real> 1.670183 </real>
</dictionary>
<string> "3D" </string>
- <dictionary>
- <string> "zfar" </string>
- <real> 500 </real>
+ <dictionary shared="false">
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
- <string> "window_mode" </string>
- <int> 0 </int>
- <string> "window_0" </string>
- <dictionary>
- <string> "distance" </string>
- <real> 4 </real>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "x_rot" </string>
- <real> 0.337 </real>
- <string> "y_rot" </string>
- <real> -0.575 </real>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
+ <string> "viewports" </string>
+ <array len="4" shared="false">
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ </array>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
- <dictionary>
+ <dictionary shared="false">
<string> "custom_args" </string>
<string> "-l $scene" </string>
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
- <resource resource_type="Texture" path="res://art/seesaw_base.png"> </resource>
- <int> 1 </int>
- <color> 1, 1, 1, 1 </color>
- <rect2> 0, 0, 0, 0 </rect2>
- <resource resource_type="ConcavePolygonShape2D" path="local://1"> </resource>
+ <resource external="0"> </resource>
+ <bool> False </bool>
+ <resource resource_type="Shape2D" path="local://1"> </resource>
<matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
+ <int> 1 </int>
+ <vector2> 0, 0 </vector2>
+ <real> 0 </real>
+ <real> 1 </real>
+ <int> 0 </int>
<vector2_array len="3"> -32.6231, 32.0838, -1.28218, -31.1383, 33.8412, 33.1645 </vector2_array>
+ <vector2> -1, -1 </vector2>
<vector2> 1.19748, -29.9368 </vector2>
<real> 16.223282 </real>
- <resource resource_type="ConvexPolygonShape2D" path="local://2"> </resource>
+ <resource resource_type="Shape2D" path="local://2"> </resource>
+ <bool> True </bool>
+ <real> -1 </real>
<vector2> 1, 0.5 </vector2>
- <resource resource_type="Texture" path="res://art/seesaw_top.png"> </resource>
+ <resource external="1"> </resource>
<vector2_array len="4"> -125.025, -8.98358, 125.162, -8.44321, 99.2248, 7.22723, -99.0874, 7.76759 </vector2_array>
<vector2> 0, -31.1343 </vector2>
<node_path> "../RigidBody2D" </node_path>
<node_path> "../Sprite/StaticBody2D" </node_path>
</array>
- <string> "nodes" </string>
- <int_array len="414"> -1, -1, 1, 0, -1, 17, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 0, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 0, 0, 0, 19, 19, -1, 27, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 0, 14, 4, 15, 5, 16, 6, 20, 9, 21, 2, 22, 4, 23, 0, 24, 0, 25, 10, 26, 10, 27, 1, 28, 11, 29, 0, 30, 12, 17, 7, 0, 1, 0, 31, 31, -1, 22, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 2, 14, 4, 15, 5, 16, 6, 32, 10, 33, 13, 34, 14, 35, 0, 36, 4, 37, 5, 17, 7, 0, 2, 0, 38, 38, -1, 18, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 2, 14, 4, 15, 5, 16, 6, 39, 1, 40, 15, 17, 7, 0, 0, 0, 41, 41, -1, 31, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 2, 14, 16, 15, 17, 16, 6, 32, 10, 33, 18, 34, 14, 42, 1, 43, 3, 44, 3, 45, 5, 46, 0, 47, 0, 48, 1, 49, 0, 50, 2, 51, 2, 52, 4, 53, 5, 17, 7, 0, 4, 0, 19, 19, -1, 27, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 0, 14, 4, 15, 5, 16, 19, 20, 20, 21, 2, 22, 4, 23, 0, 24, 0, 25, 10, 26, 10, 27, 1, 28, 11, 29, 0, 30, 12, 17, 7, 0, 4, 0, 38, 38, -1, 18, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 2, 14, 4, 15, 5, 16, 6, 39, 1, 40, 21, 17, 7, 0, 0, 0, 54, 54, -1, 19, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 0, 14, 22, 15, 5, 16, 6, 55, 23, 56, 24, 57, 5, 17, 7, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
- <resource name="script/script"></resource>
+
</main_resource>
</resource_file> \ No newline at end of file
diff --git a/demos/2d/screen_space_shaders/screen_shaders.gd b/demos/2d/screen_space_shaders/screen_shaders.gd
index 4e8a548539..b847a9c923 100644
--- a/demos/2d/screen_space_shaders/screen_shaders.gd
+++ b/demos/2d/screen_space_shaders/screen_shaders.gd
@@ -1,32 +1,25 @@
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())
+ 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
+ get_node("effect").add_item("FX: " + c.get_name())
-
-
-func _on_picture_item_selected( ID ):
+func _on_picture_item_selected(ID):
for c in range(get_node("pictures").get_child_count()):
- if (ID==c):
+ if (ID == c):
get_node("pictures").get_child(c).show()
else:
get_node("pictures").get_child(c).hide()
-func _on_effect_item_selected( ID ):
+func _on_effect_item_selected(ID):
for c in range(get_node("effects").get_child_count()):
- if (ID==c):
+ 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
index fc2be96fc9..be12cef02d 100644
--- a/demos/2d/screen_space_shaders/screen_shaders.scn
+++ b/demos/2d/screen_space_shaders/screen_shaders.scn
Binary files differ
diff --git a/demos/2d/sdf_font/sdf.scn b/demos/2d/sdf_font/sdf.scn
index 89d6245bf0..4880500d6d 100644
--- a/demos/2d/sdf_font/sdf.scn
+++ b/demos/2d/sdf_font/sdf.scn
Binary files differ
diff --git a/demos/2d/shower_of_bullets/bullets.gd b/demos/2d/shower_of_bullets/bullets.gd
index 79f4faaae6..e0eba2682a 100644
--- a/demos/2d/shower_of_bullets/bullets.gd
+++ b/demos/2d/shower_of_bullets/bullets.gd
@@ -4,73 +4,68 @@ extends Node2D
# This demo is an example of controling a high number of 2D objects with logic and collision without using scene nodes.
# This technique is a lot more efficient than using instancing and nodes, but requires more programming and is less visual
+# Member variables
const BULLET_COUNT = 500
const SPEED_MIN = 20
const SPEED_MAX = 50
-var bullets=[]
+var bullets = []
var shape
+
+# Inner classes
class Bullet:
var pos = Vector2()
var speed = 1.0
var body = RID()
-
-func _draw():
+func _draw():
var t = preload("res://bullet.png")
var tofs = -t.get_size()*0.5
for b in bullets:
- draw_texture(t,b.pos+tofs)
-
-
+ draw_texture(t, b.pos + tofs)
+
+
func _process(delta):
var width = get_viewport_rect().size.x*2.0
var mat = Matrix32()
for b in bullets:
- b.pos.x-=b.speed*delta
+ b.pos.x -= b.speed*delta
if (b.pos.x < -30):
- b.pos.x+=width
- mat.o=b.pos
-
- Physics2DServer.body_set_state(b.body,Physics2DServer.BODY_STATE_TRANSFORM,mat)
+ b.pos.x += width
+ mat.o = b.pos
+ Physics2DServer.body_set_state(b.body, Physics2DServer.BODY_STATE_TRANSFORM, mat)
+
update()
-
-
-func _ready():
- shape = Physics2DServer.shape_create(Physics2DServer.SHAPE_CIRCLE)
- Physics2DServer.shape_set_data(shape,8) #radius
+func _ready():
+ shape = Physics2DServer.shape_create(Physics2DServer.SHAPE_CIRCLE)
+ Physics2DServer.shape_set_data(shape, 8) # Radius
+
for i in range(BULLET_COUNT):
var b = Bullet.new()
- b.speed=rand_range(SPEED_MIN,SPEED_MAX)
+ b.speed = rand_range(SPEED_MIN, SPEED_MAX)
b.body = Physics2DServer.body_create(Physics2DServer.BODY_MODE_KINEMATIC)
- Physics2DServer.body_set_space(b.body,get_world_2d().get_space())
- Physics2DServer.body_add_shape(b.body,shape)
+ Physics2DServer.body_set_space(b.body, get_world_2d().get_space())
+ Physics2DServer.body_add_shape(b.body, shape)
- b.pos = Vector2( get_viewport_rect().size * Vector2(randf()*2.0,randf()) ) #twice as long
- b.pos.x += get_viewport_rect().size.x # start outside
+ b.pos = Vector2(get_viewport_rect().size * Vector2(randf()*2.0, randf())) # Twice as long
+ b.pos.x += get_viewport_rect().size.x # Start outside
var mat = Matrix32()
- mat.o=b.pos
- Physics2DServer.body_set_state(b.body,Physics2DServer.BODY_STATE_TRANSFORM,mat)
+ mat.o = b.pos
+ Physics2DServer.body_set_state(b.body, Physics2DServer.BODY_STATE_TRANSFORM, mat)
bullets.append(b)
-
-
- set_process(true)
-
+ set_process(true)
+
+
func _exit_tree():
for b in bullets:
Physics2DServer.free_rid(b.body)
Physics2DServer.free_rid(shape)
- # Initalization here
bullets.clear()
-
- pass
-
-
diff --git a/demos/2d/shower_of_bullets/shower.gd b/demos/2d/shower_of_bullets/shower.gd
index bba8431764..50c1109489 100644
--- a/demos/2d/shower_of_bullets/shower.gd
+++ b/demos/2d/shower_of_bullets/shower.gd
@@ -1,32 +1,25 @@
extends Node2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
+# Member variables
+var touching = 0
-var touching=0
+func _input(event):
+ if (event.type == InputEvent.MOUSE_MOTION):
+ get_node("player").set_pos(event.pos - Vector2(0, 16))
-func _input(ev):
- if (ev.type==InputEvent.MOUSE_MOTION):
- get_node("player").set_pos(ev.pos-Vector2(0,16))
-
-
-func _on_player_body_enter_shape( body_id, body, body_shape, area_shape ):
-
- touching+=1
- if (touching==1):
+func _on_player_body_enter_shape(body_id, body, body_shape, area_shape):
+ touching += 1
+ if (touching == 1):
get_node("player/sprite").set_frame(1)
-func _on_player_body_exit_shape( body_id, body, body_shape, area_shape ):
-
- touching-=1
- if (touching==0):
+func _on_player_body_exit_shape(body_id, body, body_shape, area_shape):
+ touching -= 1
+ if (touching == 0):
get_node("player/sprite").set_frame(0)
func _ready():
set_process_input(true)
- pass
diff --git a/demos/2d/shower_of_bullets/shower.scn b/demos/2d/shower_of_bullets/shower.scn
index 648888d099..9e2181e9c6 100644
--- a/demos/2d/shower_of_bullets/shower.scn
+++ b/demos/2d/shower_of_bullets/shower.scn
Binary files differ
diff --git a/demos/2d/space_shooter/asteroid.gd b/demos/2d/space_shooter/asteroid.gd
index f21b9777bb..9f6734e122 100644
--- a/demos/2d/space_shooter/asteroid.gd
+++ b/demos/2d/space_shooter/asteroid.gd
@@ -1,49 +1,43 @@
extends Area2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
+# Member variables
+const SPEED = -200
+const Y_RANDOM = 10
-const SPEED=-200
-const Y_RANDOM=10
+var points = 1
+var speed_y = 0.0
+var destroyed = false
-var points=1
-
-
-var speed_y=0.0
func _process(delta):
+ translate(Vector2(SPEED, speed_y)*delta)
- translate( Vector2(SPEED,speed_y) * delta )
func _ready():
- # Initialization here
- speed_y=rand_range(-Y_RANDOM,Y_RANDOM)
- pass
+ speed_y = rand_range(-Y_RANDOM, Y_RANDOM)
-var destroyed=false
func destroy():
if (destroyed):
- return
- destroyed=true
+ return
+ destroyed = true
get_node("anim").play("explode")
set_process(false)
get_node("sfx").play("sound_explode")
- #accum points
- get_node("/root/game_state").points+=1
-
+ # Accumulate points
+ get_node("/root/game_state").points += 1
+
+
func is_enemy():
- return not destroyed
-
+ return not destroyed
+
func _on_visibility_enter_screen():
set_process(true)
- #make it spin!
+ # Make it spin!
get_node("anim").play("spin")
-
+
func _on_visibility_exit_screen():
queue_free()
- pass # replace with function body
diff --git a/demos/2d/space_shooter/asteroid.scn b/demos/2d/space_shooter/asteroid.scn
index b881725ea4..6bca98cd30 100644
--- a/demos/2d/space_shooter/asteroid.scn
+++ b/demos/2d/space_shooter/asteroid.scn
Binary files differ
diff --git a/demos/2d/space_shooter/enemy1.gd b/demos/2d/space_shooter/enemy1.gd
index 051798742a..204995c05d 100644
--- a/demos/2d/space_shooter/enemy1.gd
+++ b/demos/2d/space_shooter/enemy1.gd
@@ -1,17 +1,15 @@
extends Area2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
+# Member variables
+const SPEED = -200
+
+var destroyed=false
-const SPEED=-200
func _process(delta):
- get_parent().translate(Vector2(SPEED*delta,0))
+ get_parent().translate(Vector2(SPEED*delta, 0))
-
-var destroyed=false
func is_enemy():
return not destroyed
@@ -19,19 +17,20 @@ func is_enemy():
func destroy():
if (destroyed):
- return
- destroyed=true
+ return
+ destroyed = true
get_node("anim").play("explode")
- set_process(false)
+ set_process(false)
get_node("sfx").play("sound_explode")
- #accum points
- get_node("/root/game_state").points+=5
+ # Accumulate points
+ get_node("/root/game_state").points += 5
+
func _on_visibility_enter_screen():
set_process(true)
- get_node("anim").play("zigzag")
- get_node("anim").seek(randf()*2.0) #make it start from any pos
+ get_node("anim").play("zigzag")
+ get_node("anim").seek(randf()*2.0) # Make it start from any pos
+
func _on_visibility_exit_screen():
queue_free()
-
diff --git a/demos/2d/space_shooter/enemy1.scn b/demos/2d/space_shooter/enemy1.scn
index 14298f0a59..805071b772 100644
--- a/demos/2d/space_shooter/enemy1.scn
+++ b/demos/2d/space_shooter/enemy1.scn
Binary files differ
diff --git a/demos/2d/space_shooter/enemy2.gd b/demos/2d/space_shooter/enemy2.gd
index 4f632a053d..bfdb743103 100644
--- a/demos/2d/space_shooter/enemy2.gd
+++ b/demos/2d/space_shooter/enemy2.gd
@@ -1,56 +1,51 @@
extends Area2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
-const SPEED=-220
-const SHOOT_INTERVAL=1
-var shoot_timeout=0
+# Member variables
+const SPEED = -220
+const SHOOT_INTERVAL = 1
+
+var shoot_timeout = 0
+var destroyed=false
+
func _process(delta):
- translate( Vector2(SPEED*delta,0) )
- shoot_timeout-=delta
+ translate(Vector2(SPEED*delta, 0))
+ shoot_timeout -= delta
- if (shoot_timeout<0):
-
- shoot_timeout=SHOOT_INTERVAL
+ if (shoot_timeout < 0):
+ shoot_timeout = SHOOT_INTERVAL
- #instance a shot
+ # Instance a shot
var shot = preload("res://enemy_shot.scn").instance()
- #set pos as "shoot_from" Position2D node
- shot.set_pos( get_node("shoot_from").get_global_pos() )
- #add it to parent, so it has world coordinates
+ # Set pos as "shoot_from" Position2D node
+ shot.set_pos(get_node("shoot_from").get_global_pos())
+ # Add it to parent, so it has world coordinates
get_parent().add_child(shot)
-
-var destroyed=false
+
func is_enemy():
return not destroyed
+
func destroy():
if (destroyed):
- return
- destroyed=true
+ return
+ destroyed = true
get_node("anim").play("explode")
- set_process(false)
+ set_process(false)
get_node("sfx").play("sound_explode")
- #accum points
- get_node("/root/game_state").points+=10
+ # Accumulate points
+ get_node("/root/game_state").points += 10
+
func _ready():
set_fixed_process(true)
- # Initialization here
- pass
-
-
func _on_visibility_enter_screen():
set_process(true)
- pass # replace with function body
func _on_visibility_exit_screen():
queue_free()
- pass # replace with function body
diff --git a/demos/2d/space_shooter/enemy2.scn b/demos/2d/space_shooter/enemy2.scn
index 1d31f9c30e..644add77aa 100644
--- a/demos/2d/space_shooter/enemy2.scn
+++ b/demos/2d/space_shooter/enemy2.scn
Binary files differ
diff --git a/demos/2d/space_shooter/enemy_shot.gd b/demos/2d/space_shooter/enemy_shot.gd
index 238d24e4a2..6c782b69f1 100644
--- a/demos/2d/space_shooter/enemy_shot.gd
+++ b/demos/2d/space_shooter/enemy_shot.gd
@@ -1,32 +1,31 @@
extends Area2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
+# Member variables
const SPEED = -800
+var hit = false
+
+
func _process(delta):
- translate(Vector2(delta*SPEED,0))
+ translate(Vector2(delta*SPEED, 0))
+
func _ready():
- # Initialization here
set_process(true)
-var hit=false
-
func is_enemy():
return true
+
func _hit_something():
if (hit):
return
- hit=true
+ hit = true
set_process(false)
get_node("anim").play("splash")
+
func _on_visibility_exit_screen():
queue_free()
-
diff --git a/demos/2d/space_shooter/enemy_shot.scn b/demos/2d/space_shooter/enemy_shot.scn
index 13f5ae89e5..353c9058f7 100644
--- a/demos/2d/space_shooter/enemy_shot.scn
+++ b/demos/2d/space_shooter/enemy_shot.scn
Binary files differ
diff --git a/demos/2d/space_shooter/explosion.scn b/demos/2d/space_shooter/explosion.scn
index 4edcf709cb..6fc105fac3 100644
--- a/demos/2d/space_shooter/explosion.scn
+++ b/demos/2d/space_shooter/explosion.scn
Binary files differ
diff --git a/demos/2d/space_shooter/game_state.gd b/demos/2d/space_shooter/game_state.gd
index f66d0fa8fa..0aa5e1f42b 100644
--- a/demos/2d/space_shooter/game_state.gd
+++ b/demos/2d/space_shooter/game_state.gd
@@ -1,24 +1,22 @@
-extends Node
+extends Node
+# Member variables
var points = 0
var max_points = 0
func _ready():
var f = File.new()
- #load high score
-
- if (f.open("user://highscore",File.READ)==OK):
-
- max_points=f.get_var()
+ # Load high score
+ if (f.open("user://highscore", File.READ) == OK):
+ max_points = f.get_var()
func game_over():
- if (points>max_points):
- max_points=points
- #save high score
+ if (points > max_points):
+ max_points = points
+ # Save high score
var f = File.new()
- f.open("user://highscore",File.WRITE)
+ f.open("user://highscore", File.WRITE)
f.store_var(max_points)
- \ No newline at end of file
diff --git a/demos/2d/space_shooter/level.scn b/demos/2d/space_shooter/level.scn
index 12a679f8b6..6d5f8005f5 100644
--- a/demos/2d/space_shooter/level.scn
+++ b/demos/2d/space_shooter/level.scn
Binary files differ
diff --git a/demos/2d/space_shooter/level_tiles.scn b/demos/2d/space_shooter/level_tiles.scn
index 4d1feea70f..932be39a29 100644
--- a/demos/2d/space_shooter/level_tiles.scn
+++ b/demos/2d/space_shooter/level_tiles.scn
Binary files differ
diff --git a/demos/2d/space_shooter/main_menu.gd b/demos/2d/space_shooter/main_menu.gd
index 52221aba1b..a7f242da7b 100644
--- a/demos/2d/space_shooter/main_menu.gd
+++ b/demos/2d/space_shooter/main_menu.gd
@@ -1,20 +1,11 @@
extends Control
-# member variables here, example:
-# var a=2
-# var b="textvar"
func _ready():
-
- get_node("score").set_text( "HIGH SCORE: "+str( get_node("/root/game_state").max_points ) )
- # Initialization here
- pass
-
-
+ get_node("score").set_text("HIGH SCORE: " + str(get_node("/root/game_state").max_points))
func _on_play_pressed():
- get_node("/root/game_state").points=0
+ get_node("/root/game_state").points = 0
get_tree().change_scene("res://level.scn")
- pass # replace with function body
diff --git a/demos/2d/space_shooter/main_menu.scn b/demos/2d/space_shooter/main_menu.scn
index b87cc5d3a8..91b0b37b14 100644
--- a/demos/2d/space_shooter/main_menu.scn
+++ b/demos/2d/space_shooter/main_menu.scn
Binary files differ
diff --git a/demos/2d/space_shooter/parallax.scn b/demos/2d/space_shooter/parallax.scn
index f67277dc01..2753d16e84 100644
--- a/demos/2d/space_shooter/parallax.scn
+++ b/demos/2d/space_shooter/parallax.scn
Binary files differ
diff --git a/demos/2d/space_shooter/rail.gd b/demos/2d/space_shooter/rail.gd
index 22ebd02670..7362dff97d 100644
--- a/demos/2d/space_shooter/rail.gd
+++ b/demos/2d/space_shooter/rail.gd
@@ -1,25 +1,19 @@
extends Node2D
+# Member variables
+const SPEED = 200
+var offset = 0
-const SPEED=200
-# member variables here, example:
-# var a=2
-# var b="textvar"
func stop():
set_process(false)
-var offset=0
-
func _process(delta):
- offset+=delta*SPEED
- set_pos(Vector2(offset,0))
+ offset += delta*SPEED
+ set_pos(Vector2(offset, 0))
+
func _ready():
set_process(true)
- # Initialization here
-
-
-
diff --git a/demos/2d/space_shooter/ship.gd b/demos/2d/space_shooter/ship.gd
index fa444868a4..b6c1200632 100644
--- a/demos/2d/space_shooter/ship.gd
+++ b/demos/2d/space_shooter/ship.gd
@@ -1,71 +1,65 @@
extends Area2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
+# Member variables
const SPEED = 200
var screen_size
+var prev_shooting = false
+var killed = false
-var prev_shooting=false
func _process(delta):
-
var motion = Vector2()
if Input.is_action_pressed("move_up"):
- motion+=Vector2(0,-1)
+ motion += Vector2(0, -1)
if Input.is_action_pressed("move_down"):
- motion+=Vector2(0,1)
+ motion += Vector2(0, 1)
if Input.is_action_pressed("move_left"):
- motion+=Vector2(-1,0)
+ motion += Vector2(-1, 0)
if Input.is_action_pressed("move_right"):
- motion+=Vector2(1,0)
+ motion += Vector2(1, 0)
var shooting = Input.is_action_pressed("shoot")
-
+
var pos = get_pos()
- pos+=motion*delta*SPEED
- if (pos.x<0):
- pos.x=0
- if (pos.x>screen_size.x):
- pos.x=screen_size.x
- if (pos.y<0):
- pos.y=0
- if (pos.y>screen_size.y):
- pos.y=screen_size.y
-
+ pos += motion*delta*SPEED
+ if (pos.x < 0):
+ pos.x = 0
+ if (pos.x > screen_size.x):
+ pos.x = screen_size.x
+ if (pos.y < 0):
+ pos.y = 0
+ if (pos.y > screen_size.y):
+ pos.y = screen_size.y
+
set_pos(pos)
if (shooting and not prev_shooting):
- # just pressed
+ # Just pressed
var shot = preload("res://shot.scn").instance()
- #use the position3d as reference
- shot.set_pos( get_node("shootfrom").get_global_pos() )
- #put it two parents above, so it is not moved by us
+ # Use the Position2D as reference
+ shot.set_pos(get_node("shootfrom").get_global_pos())
+ # Put it two parents above, so it is not moved by us
get_node("../..").add_child(shot)
- #play sound
+ # Play sound
get_node("sfx").play("shoot")
-
prev_shooting = shooting
+
+ # Update points counter
+ get_node("../hud/score_points").set_text(str(get_node("/root/game_state").points))
- #update points counter
- get_node("../hud/score_points").set_text( str(get_node("/root/game_state").points) )
func _ready():
- # Initialization here
screen_size = get_viewport().get_rect().size
set_process(true)
- pass
-var killed=false
func _hit_something():
if (killed):
return
- killed=true
+ killed = true
get_node("anim").play("explode")
get_node("sfx").play("sound_explode")
get_node("../hud/game_over").show()
@@ -74,15 +68,14 @@ func _hit_something():
set_process(false)
-func _on_ship_body_enter( body ):
+func _on_ship_body_enter(body):
_hit_something()
-func _on_ship_area_enter( area ):
+func _on_ship_area_enter(area):
if (area.has_method("is_enemy") and area.is_enemy()):
_hit_something()
func _on_back_to_menu_pressed():
get_tree().change_scene("res://main_menu.scn")
- pass # replace with function body
diff --git a/demos/2d/space_shooter/ship.scn b/demos/2d/space_shooter/ship.scn
index 82c710eda7..c60e2e3e3b 100644
--- a/demos/2d/space_shooter/ship.scn
+++ b/demos/2d/space_shooter/ship.scn
Binary files differ
diff --git a/demos/2d/space_shooter/shot.gd b/demos/2d/space_shooter/shot.gd
index 28b67bd26d..936dde73d1 100644
--- a/demos/2d/space_shooter/shot.gd
+++ b/demos/2d/space_shooter/shot.gd
@@ -1,48 +1,40 @@
extends Area2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
+# Member variables
const SPEED = 800
+var hit = false
+
+
func _process(delta):
- translate(Vector2(delta*SPEED,0))
+ translate(Vector2(delta*SPEED, 0))
+
func _ready():
- # Initialization here
set_process(true)
- pass
-var hit=false
func _hit_something():
if (hit):
return
- hit=true
+ hit = true
set_process(false)
get_node("anim").play("splash")
+
func _on_visibility_exit_screen():
queue_free()
- pass # replace with function body
-
-func _on_shot_area_enter( area ):
- #hit an enemy or asteroid
+func _on_shot_area_enter(area):
+ # Hit an enemy or asteroid
if (area.has_method("destroy")):
- #duck typing at it's best
+ # Duck typing at it's best
area.destroy()
_hit_something()
-
-
- pass
-func _on_shot_body_enter( body ):
- #hit the tilemap
+func _on_shot_body_enter(body):
+ # Hit the tilemap
_hit_something()
- pass # replace with function body
-
diff --git a/demos/2d/space_shooter/shot.scn b/demos/2d/space_shooter/shot.scn
index 86a20ffa47..9daf4ebe82 100644
--- a/demos/2d/space_shooter/shot.scn
+++ b/demos/2d/space_shooter/shot.scn
Binary files differ
diff --git a/demos/2d/splash/splash.xml b/demos/2d/splash/splash.xml
index ecfcb0f5b5..4a36619b09 100644
--- a/demos/2d/splash/splash.xml
+++ b/demos/2d/splash/splash.xml
@@ -1,20 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="20" version="0.99" version_name="Godot Engine v0.99.3735-pre-beta">
- <ext_resource path="res://splash_01.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://splash_02.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://splash_03.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://splash_04.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://splash_05.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://splash_06.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://splash_07.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://splash_08.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://splash_09.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://bg.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://bg_layer_2.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://bg_layer_1.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://button_pressed.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://freesans.*" type="Font"></ext_resource>
- <ext_resource path="res://button.*" type="ImageTexture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="20" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://splash_02.png" type="Texture" index="4"></ext_resource>
+ <ext_resource path="res://splash_01.png" type="Texture" index="3"></ext_resource>
+ <ext_resource path="res://splash_05.png" type="Texture" index="7"></ext_resource>
+ <ext_resource path="res://splash_06.png" type="Texture" index="8"></ext_resource>
+ <ext_resource path="res://splash_03.png" type="Texture" index="5"></ext_resource>
+ <ext_resource path="res://splash_04.png" type="Texture" index="6"></ext_resource>
+ <ext_resource path="res://splash_07.png" type="Texture" index="9"></ext_resource>
+ <ext_resource path="res://splash_08.png" type="Texture" index="10"></ext_resource>
+ <ext_resource path="res://splash_09.png" type="Texture" index="11"></ext_resource>
+ <ext_resource path="res://bg.png" type="Texture" index="0"></ext_resource>
+ <ext_resource path="res://bg_layer_2.png" type="Texture" index="1"></ext_resource>
+ <ext_resource path="res://bg_layer_1.png" type="Texture" index="2"></ext_resource>
+ <ext_resource path="res://button_pressed.png" type="Texture" index="13"></ext_resource>
+ <ext_resource path="res://button.png" type="Texture" index="12"></ext_resource>
+ <ext_resource path="res://freesans.fnt" type="Font" index="14"></ext_resource>
<resource type="Animation" path="local://1">
<string name="resource/name"> "scroll" </string>
<real name="length"> 1 </real>
@@ -26,6 +26,8 @@
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> True </bool>
+ <string> "times" </string>
+ <real_array len="2"> 0, 1 </real_array>
<string> "transitions" </string>
<real_array len="2"> 1, 1 </real_array>
<string> "values" </string>
@@ -33,48 +35,23 @@
<vector2> 0, 0 </vector2>
<vector2> -800, 0 </vector2>
</array>
- <string> "times" </string>
- <real_array len="2"> 0, 1 </real_array>
</dictionary>
</resource>
<resource type="SpriteFrames" path="local://2">
<array name="frames" len="9" shared="false">
- <resource resource_type="ImageTexture" path="res://splash_01.*"> </resource>
- <resource resource_type="ImageTexture" path="res://splash_02.*"> </resource>
- <resource resource_type="ImageTexture" path="res://splash_03.*"> </resource>
- <resource resource_type="ImageTexture" path="res://splash_04.*"> </resource>
- <resource resource_type="ImageTexture" path="res://splash_05.*"> </resource>
- <resource resource_type="ImageTexture" path="res://splash_06.*"> </resource>
- <resource resource_type="ImageTexture" path="res://splash_07.*"> </resource>
- <resource resource_type="ImageTexture" path="res://splash_08.*"> </resource>
- <resource resource_type="ImageTexture" path="res://splash_09.*"> </resource>
+ <resource external="3"> </resource>
+ <resource external="4"> </resource>
+ <resource external="5"> </resource>
+ <resource external="6"> </resource>
+ <resource external="7"> </resource>
+ <resource external="8"> </resource>
+ <resource external="9"> </resource>
+ <resource external="10"> </resource>
+ <resource external="11"> </resource>
</array>
</resource>
- <resource type="Animation" path="local://3">
- <string name="resource/name"> "loop" </string>
- <real name="length"> 0.6 </real>
- <bool name="loop"> True </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "value" </string>
- <node_path name="tracks/0/path"> "logo:frame" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <dictionary name="tracks/0/keys" shared="false">
- <string> "cont" </string>
- <bool> False </bool>
- <string> "transitions" </string>
- <real_array len="2"> 1, 1 </real_array>
- <string> "values" </string>
- <array len="2" shared="false">
- <int> 8 </int>
- <int> 7 </int>
- </array>
- <string> "times" </string>
- <real_array len="2"> 0, 0.3 </real_array>
- </dictionary>
-
- </resource>
<resource type="Animation" path="local://4">
<string name="resource/name"> "intro" </string>
<real name="length"> 3 </real>
@@ -86,6 +63,8 @@
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> True </bool>
+ <string> "times" </string>
+ <real_array len="2"> 1, 1.5 </real_array>
<string> "transitions" </string>
<real_array len="2"> 2, 1 </real_array>
<string> "values" </string>
@@ -93,8 +72,6 @@
<vector2> 412, -212.981 </vector2>
<vector2> 412, 171 </vector2>
</array>
- <string> "times" </string>
- <real_array len="2"> 1, 1.5 </real_array>
</dictionary>
<string name="tracks/1/type"> "value" </string>
<node_path name="tracks/1/path"> "logo:frame" </node_path>
@@ -102,6 +79,8 @@
<dictionary name="tracks/1/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
+ <string> "times" </string>
+ <real_array len="10"> 0, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3 </real_array>
<string> "transitions" </string>
<real_array len="10"> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 </real_array>
<string> "values" </string>
@@ -117,8 +96,6 @@
<int> 7 </int>
<int> 8 </int>
</array>
- <string> "times" </string>
- <real_array len="10"> 0, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3 </real_array>
</dictionary>
<string name="tracks/2/type"> "value" </string>
<node_path name="tracks/2/path"> "start:visibility/opacity" </node_path>
@@ -126,6 +103,8 @@
<dictionary name="tracks/2/keys" shared="false">
<string> "cont" </string>
<bool> True </bool>
+ <string> "times" </string>
+ <real_array len="2"> 2.5, 2.8 </real_array>
<string> "transitions" </string>
<real_array len="2"> 1, 1 </real_array>
<string> "values" </string>
@@ -133,8 +112,6 @@
<real> 0 </real>
<real> 1 </real>
</array>
- <string> "times" </string>
- <real_array len="2"> 2.5, 2.8 </real_array>
</dictionary>
<string name="tracks/3/type"> "value" </string>
<node_path name="tracks/3/path"> "start:visibility/visible" </node_path>
@@ -142,6 +119,8 @@
<dictionary name="tracks/3/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
+ <string> "times" </string>
+ <real_array len="2"> 0, 2.5 </real_array>
<string> "transitions" </string>
<real_array len="2"> 1, 1 </real_array>
<string> "values" </string>
@@ -149,8 +128,6 @@
<bool> False </bool>
<bool> True </bool>
</array>
- <string> "times" </string>
- <real_array len="2"> 0, 2.5 </real_array>
</dictionary>
<string name="tracks/4/type"> "value" </string>
<node_path name="tracks/4/path"> "copyright:visibility/visible" </node_path>
@@ -158,6 +135,8 @@
<dictionary name="tracks/4/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
+ <string> "times" </string>
+ <real_array len="2"> 0, 2.5 </real_array>
<string> "transitions" </string>
<real_array len="2"> 1, 1 </real_array>
<string> "values" </string>
@@ -165,8 +144,6 @@
<bool> False </bool>
<bool> True </bool>
</array>
- <string> "times" </string>
- <real_array len="2"> 0, 2.5 </real_array>
</dictionary>
<string name="tracks/5/type"> "value" </string>
<node_path name="tracks/5/path"> "copyright:visibility/opacity" </node_path>
@@ -174,6 +151,8 @@
<dictionary name="tracks/5/keys" shared="false">
<string> "cont" </string>
<bool> True </bool>
+ <string> "times" </string>
+ <real_array len="2"> 2.5, 2.8 </real_array>
<string> "transitions" </string>
<real_array len="2"> 1, 1 </real_array>
<string> "values" </string>
@@ -181,45 +160,61 @@
<real> 0 </real>
<real> 1 </real>
</array>
+ </dictionary>
+
+ </resource>
+ <resource type="Animation" path="local://3">
+ <string name="resource/name"> "loop" </string>
+ <real name="length"> 0.6 </real>
+ <bool name="loop"> True </bool>
+ <real name="step"> 0.1 </real>
+ <string name="tracks/0/type"> "value" </string>
+ <node_path name="tracks/0/path"> "logo:frame" </node_path>
+ <int name="tracks/0/interp"> 1 </int>
+ <dictionary name="tracks/0/keys" shared="false">
+ <string> "cont" </string>
+ <bool> False </bool>
<string> "times" </string>
- <real_array len="2"> 2.5, 2.8 </real_array>
+ <real_array len="2"> 0, 0.3 </real_array>
+ <string> "transitions" </string>
+ <real_array len="2"> 1, 1 </real_array>
+ <string> "values" </string>
+ <array len="2" shared="false">
+ <int> 8 </int>
+ <int> 7 </int>
+ </array>
</dictionary>
</resource>
<main_resource>
<dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="81">
+ <string_array len="51">
<string> "splash" </string>
- <string> "Control" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
<string> "anchor/right" </string>
<string> "anchor/bottom" </string>
- <string> "focus_neighbour/left" </string>
- <string> "focus_neighbour/top" </string>
- <string> "focus_neighbour/right" </string>
- <string> "focus_neighbour/bottom" </string>
<string> "focus/ignore_mouse" </string>
<string> "focus/stop_mouse" </string>
<string> "size_flags/horizontal" </string>
<string> "size_flags/vertical" </string>
- <string> "size_flags/stretch_ratio" </string>
<string> "__meta__" </string>
+ <string> "Control" </string>
<string> "bg" </string>
<string> "margin/right" </string>
<string> "margin/bottom" </string>
<string> "1" </string>
- <string> "TextureFrame" </string>
<string> "texture" </string>
- <string> "modulate" </string>
- <string> "expand" </string>
+ <string> "TextureFrame" </string>
<string> "2" </string>
<string> "margin/left" </string>
<string> "scroll" </string>
- <string> "AnimationPlayer" </string>
<string> "playback/process_mode" </string>
<string> "playback/default_blend_time" </string>
<string> "root/root" </string>
@@ -228,152 +223,172 @@
<string> "playback/speed" </string>
<string> "blend_times" </string>
<string> "autoplay" </string>
+ <string> "AnimationPlayer" </string>
<string> "layer2" </string>
<string> "margin/top" </string>
<string> "layer1" </string>
<string> "logo" </string>
- <string> "AnimatedSprite" </string>
<string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
<string> "frames" </string>
<string> "frame" </string>
- <string> "centered" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
+ <string> "AnimatedSprite" </string>
<string> "start" </string>
- <string> "TextureButton" </string>
- <string> "disabled" </string>
<string> "toggle_mode" </string>
- <string> "click_on_press" </string>
<string> "textures/normal" </string>
<string> "textures/pressed" </string>
- <string> "textures/hover" </string>
- <string> "textures/disabled" </string>
- <string> "textures/focused" </string>
- <string> "textures/click_mask" </string>
+ <string> "TextureButton" </string>
<string> "copyright" </string>
- <string> "Label" </string>
<string> "custom_fonts/font" </string>
- <string> "range/min" </string>
- <string> "range/max" </string>
- <string> "range/step" </string>
- <string> "range/page" </string>
- <string> "range/value" </string>
- <string> "range/exp_edit" </string>
- <string> "rounded_values" </string>
<string> "text" </string>
- <string> "align" </string>
- <string> "valign" </string>
- <string> "autowrap" </string>
<string> "percent_visible" </string>
+ <string> "lines_skipped" </string>
+ <string> "max_lines_visible" </string>
+ <string> "Label" </string>
<string> "intro" </string>
- <string> "anims/loop" </string>
<string> "anims/intro" </string>
<string> "next/intro" </string>
+ <string> "anims/loop" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
<string> "node_count" </string>
<int> 17 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="387"> -1, -1, 8, 0, -1, 7, 1, 0, 2, 0, 3, 1, 4, 2, 5, 3, 6, 3, 7, 4, 0, 0, 0, 8, 9, -1, 6, 10, 5, 11, 5, 3, 1, 4, 2, 5, 3, 6, 3, 0, 1, 0, 14, 12, -1, 7, 10, 5, 11, 5, 3, 2, 4, 2, 5, 3, 6, 3, 13, 6, 0, 1, 0, 14, 15, -1, 8, 16, 7, 10, 8, 11, 9, 3, 2, 4, 2, 5, 3, 6, 3, 13, 6, 0, 1, 0, 26, 17, -1, 8, 18, 0, 19, 10, 20, 11, 21, 12, 22, 2, 23, 13, 24, 14, 25, 15, 0, 0, 0, 8, 27, -1, 6, 10, 5, 11, 5, 3, 1, 4, 2, 5, 3, 6, 3, 0, 5, 0, 14, 12, -1, 8, 28, 16, 10, 7, 11, 17, 3, 2, 4, 2, 5, 3, 6, 3, 13, 18, 0, 5, 0, 14, 15, -1, 9, 16, 7, 28, 16, 10, 8, 11, 17, 3, 2, 4, 2, 5, 3, 6, 3, 13, 18, 0, 5, 0, 26, 17, -1, 8, 18, 0, 19, 10, 20, 11, 21, 12, 22, 2, 23, 19, 24, 14, 25, 15, 0, 0, 0, 8, 29, -1, 6, 10, 5, 11, 5, 3, 1, 4, 2, 5, 3, 6, 3, 0, 9, 0, 14, 12, -1, 8, 28, 20, 10, 7, 11, 17, 3, 2, 4, 2, 5, 3, 6, 3, 13, 21, 0, 9, 0, 14, 15, -1, 9, 16, 7, 28, 20, 10, 8, 11, 17, 3, 2, 4, 2, 5, 3, 6, 3, 13, 21, 0, 9, 0, 26, 17, -1, 8, 18, 0, 19, 10, 20, 11, 21, 12, 22, 2, 23, 22, 24, 14, 25, 15, 0, 0, 0, 34, 30, -1, 3, 31, 23, 32, 24, 33, 25, 0, 0, 0, 39, 35, -1, 11, 16, 26, 28, 27, 10, 28, 11, 29, 3, 1, 4, 2, 5, 3, 6, 3, 36, 1, 37, 30, 38, 31, 0, 0, 0, 46, 40, -1, 12, 16, 32, 28, 33, 10, 34, 11, 35, 3, 2, 4, 2, 5, 3, 41, 36, 42, 37, 43, 38, 44, 39, 45, 40, 0, 0, 0, 26, 47, -1, 10, 18, 0, 19, 10, 20, 11, 48, 41, 49, 42, 50, 43, 22, 2, 23, 38, 24, 14, 25, 44, 0 </int_array>
<string> "variants" </string>
- <array len="49" shared="false">
- <bool> True </bool>
- <real> 1 </real>
+ <array len="45" shared="false">
<int> 1 </int>
- <node_path> "" </node_path>
<bool> False </bool>
+ <bool> True </bool>
<int> 2 </int>
<dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
<dictionary shared="false">
<string> "2D" </string>
<dictionary shared="false">
- <string> "pixel_snap" </string>
- <bool> True </bool>
+ <string> "ofs" </string>
+ <vector2> -301.424, -450.503 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
<string> "zoom" </string>
<real> 0.54036 </real>
- <string> "ofs" </string>
- <vector2> -301.424, 3.30361 </vector2>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
<string> "viewports" </string>
<array len="4" shared="false">
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
</dictionary>
</array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -382,12 +397,9 @@
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
<real> 40 </real>
- <resource resource_type="ImageTexture" path="res://bg.*"> </resource>
- <color> 1, 1, 1, 1 </color>
+ <resource external="0"> </resource>
<real> 800 </real>
<real> 1600 </real>
<real> 450 </real>
@@ -400,38 +412,36 @@
<string> "scroll" </string>
<real> 194 </real>
<real> 456 </real>
- <resource resource_type="ImageTexture" path="res://bg_layer_2.*"> </resource>
+ <resource external="1"> </resource>
<real> 0.1 </real>
<real> 212 </real>
- <resource resource_type="ImageTexture" path="res://bg_layer_1.*"> </resource>
+ <resource external="2"> </resource>
<real> 0.2 </real>
<vector2> 412, 171 </vector2>
- <vector2> 1, 1 </vector2>
<resource resource_type="SpriteFrames" path="local://2"> </resource>
<int> 8 </int>
<real> 345 </real>
<real> 369 </real>
<real> 494 </real>
<real> 443 </real>
- <resource resource_type="ImageTexture" path="res://button.*"> </resource>
- <resource resource_type="ImageTexture" path="res://button_pressed.*"> </resource>
- <resource name=""></resource> <real> 658 </real>
+ <resource external="12"> </resource>
+ <resource external="13"> </resource>
+ <real> 658 </real>
<real> 417 </real>
<real> 776 </real>
<real> 434 </real>
- <resource resource_type="Font" path="res://freesans.*"> </resource>
+ <resource external="14"> </resource>
<string> "(c) 1994 SOGA" </string>
+ <real> 1 </real>
<int> 0 </int>
- <real> -1 </real>
- <resource resource_type="Animation" path="local://3"> </resource>
+ <int> -1 </int>
<resource resource_type="Animation" path="local://4"> </resource>
<string> "loop" </string>
+ <resource resource_type="Animation" path="local://3"> </resource>
<string> "intro" </string>
</array>
- <string> "nodes" </string>
- <int_array len="675"> -1, -1, 1, 0, -1, 16, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 2, 8, 3, 9, 3, 10, 3, 11, 3, 12, 4, 13, 0, 14, 5, 15, 5, 16, 1, 17, 6, 0, 0, 0, 1, 18, -1, 15, 2, 0, 3, 1, 4, 1, 5, 0, 19, 7, 20, 7, 8, 3, 9, 3, 10, 3, 11, 3, 12, 4, 13, 0, 14, 5, 15, 5, 16, 1, 0, 1, 0, 22, 21, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 19, 7, 20, 7, 8, 3, 9, 3, 10, 3, 11, 3, 12, 0, 13, 0, 14, 5, 15, 5, 16, 1, 23, 8, 24, 9, 25, 4, 0, 1, 0, 22, 26, -1, 19, 2, 0, 3, 1, 4, 1, 5, 0, 27, 10, 19, 11, 20, 12, 8, 3, 9, 3, 10, 3, 11, 3, 12, 0, 13, 0, 14, 5, 15, 5, 16, 1, 23, 8, 24, 9, 25, 4, 0, 1, 0, 29, 28, -1, 8, 30, 2, 31, 13, 32, 14, 33, 15, 34, 0, 35, 16, 36, 17, 37, 18, 0, 0, 0, 1, 38, -1, 15, 2, 0, 3, 1, 4, 1, 5, 0, 19, 7, 20, 7, 8, 3, 9, 3, 10, 3, 11, 3, 12, 4, 13, 0, 14, 5, 15, 5, 16, 1, 0, 5, 0, 22, 21, -1, 19, 2, 0, 3, 1, 4, 1, 5, 0, 39, 19, 19, 10, 20, 20, 8, 3, 9, 3, 10, 3, 11, 3, 12, 0, 13, 0, 14, 5, 15, 5, 16, 1, 23, 21, 24, 9, 25, 4, 0, 5, 0, 22, 26, -1, 20, 2, 0, 3, 1, 4, 1, 5, 0, 27, 10, 39, 19, 19, 11, 20, 20, 8, 3, 9, 3, 10, 3, 11, 3, 12, 0, 13, 0, 14, 5, 15, 5, 16, 1, 23, 21, 24, 9, 25, 4, 0, 5, 0, 29, 28, -1, 8, 30, 2, 31, 13, 32, 14, 33, 15, 34, 0, 35, 22, 36, 17, 37, 18, 0, 0, 0, 1, 40, -1, 15, 2, 0, 3, 1, 4, 1, 5, 0, 19, 7, 20, 7, 8, 3, 9, 3, 10, 3, 11, 3, 12, 4, 13, 0, 14, 5, 15, 5, 16, 1, 0, 9, 0, 22, 21, -1, 19, 2, 0, 3, 1, 4, 1, 5, 0, 39, 23, 19, 10, 20, 20, 8, 3, 9, 3, 10, 3, 11, 3, 12, 0, 13, 0, 14, 5, 15, 5, 16, 1, 23, 24, 24, 9, 25, 4, 0, 9, 0, 22, 26, -1, 20, 2, 0, 3, 1, 4, 1, 5, 0, 27, 10, 39, 23, 19, 11, 20, 20, 8, 3, 9, 3, 10, 3, 11, 3, 12, 0, 13, 0, 14, 5, 15, 5, 16, 1, 23, 24, 24, 9, 25, 4, 0, 9, 0, 29, 28, -1, 8, 30, 2, 31, 13, 32, 14, 33, 15, 34, 0, 35, 25, 36, 17, 37, 18, 0, 0, 0, 42, 41, -1, 13, 2, 0, 3, 1, 4, 1, 5, 0, 43, 26, 44, 13, 45, 27, 46, 28, 47, 29, 48, 0, 49, 4, 50, 4, 24, 9, 0, 0, 0, 52, 51, -1, 26, 2, 0, 3, 1, 4, 1, 5, 0, 27, 30, 39, 31, 19, 32, 20, 33, 8, 3, 9, 3, 10, 3, 11, 3, 12, 4, 13, 0, 14, 5, 15, 5, 16, 1, 53, 4, 54, 4, 55, 4, 56, 34, 57, 35, 58, 36, 59, 36, 60, 36, 61, 36, 0, 0, 0, 63, 62, -1, 29, 2, 0, 3, 1, 4, 1, 5, 0, 27, 37, 39, 38, 19, 39, 20, 40, 8, 3, 9, 3, 10, 3, 11, 3, 12, 0, 13, 0, 14, 5, 16, 1, 64, 41, 65, 13, 66, 1, 67, 1, 68, 1, 69, 13, 70, 4, 71, 4, 72, 42, 73, 43, 74, 43, 75, 4, 76, 44, 0, 0, 0, 29, 77, -1, 10, 30, 2, 31, 13, 32, 14, 78, 45, 79, 46, 80, 47, 34, 0, 35, 1, 36, 17, 37, 48, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
</main_resource>
diff --git a/demos/2d/sprite_shaders/sprite_shaders.scn b/demos/2d/sprite_shaders/sprite_shaders.scn
index 7c36f2137c..b6060f8eaa 100644
--- a/demos/2d/sprite_shaders/sprite_shaders.scn
+++ b/demos/2d/sprite_shaders/sprite_shaders.scn
Binary files differ
diff --git a/demos/2d/tetris/grid.gd b/demos/2d/tetris/grid.gd
index 8708d168e4..75fabb4210 100644
--- a/demos/2d/tetris/grid.gd
+++ b/demos/2d/tetris/grid.gd
@@ -1,82 +1,76 @@
-
extends Control
# Simple Tetris-like demo, (c) 2012 Juan Linietsky
# Implemented by using a regular Control and drawing on it during the _draw() callback.
# The drawing surface is updated only when changes happen (by calling update())
-
+# Member variables
var score = 0
-var score_label=null
+var score_label = null
const MAX_SHAPES = 7
var block = preload("block.png")
-var block_colors=[
- Color(1,0.5,0.5),
- Color(0.5,1,0.5),
- Color(0.5,0.5,1),
- Color(0.8,0.4,0.8),
- Color(0.8,0.8,0.4),
- Color(0.4,0.8,0.8),
- Color(0.7,0.7,0.7)]
-
-var block_shapes=[
- [ Vector2(0,-1),Vector2(0,0),Vector2(0,1),Vector2(0,2) ], # I
- [ Vector2(0,0),Vector2(1,0),Vector2(1,1),Vector2(0,1) ], # O
- [ Vector2(-1,1),Vector2(0,1),Vector2(0,0),Vector2(1,0) ], # S
- [ Vector2(1,1),Vector2(0,1),Vector2(0,0),Vector2(-1,0) ], # Z
- [ Vector2(-1,1),Vector2(-1,0),Vector2(0,0),Vector2(1,0) ], # L
- [ Vector2(1,1),Vector2(1,0),Vector2(0,0),Vector2(-1,0) ], # J
- [ Vector2(0,1),Vector2(1,0),Vector2(0,0),Vector2(-1,0) ]] # T
-
+var block_colors = [
+ Color(1, 0.5, 0.5),
+ Color(0.5, 1, 0.5),
+ Color(0.5, 0.5, 1),
+ Color(0.8, 0.4, 0.8),
+ Color(0.8, 0.8, 0.4),
+ Color(0.4, 0.8, 0.8),
+ Color(0.7, 0.7, 0.7)]
-var block_rotations=[
- Matrix32( Vector2(1,0),Vector2(0,1), Vector2() ),
- Matrix32( Vector2(0,1),Vector2(-1,0), Vector2() ),
- Matrix32( Vector2(-1,0),Vector2(0,-1), Vector2() ),
- Matrix32( Vector2(0,-1),Vector2(1,0), Vector2() )
-]
-
+var block_shapes = [
+ [ Vector2(0, -1), Vector2(0, 0), Vector2(0, 1), Vector2(0, 2) ], # I
+ [ Vector2(0, 0), Vector2(1, 0), Vector2(1, 1), Vector2(0, 1) ], # O
+ [ Vector2(-1, 1), Vector2(0, 1), Vector2(0, 0), Vector2(1, 0) ], # S
+ [ Vector2(1, 1), Vector2(0, 1), Vector2(0, 0), Vector2(-1, 0) ], # Z
+ [ Vector2(-1, 1), Vector2(-1, 0), Vector2(0, 0), Vector2(1, 0) ], # L
+ [ Vector2(1, 1), Vector2(1, 0), Vector2(0, 0), Vector2(-1, 0) ], # J
+ [ Vector2(0, 1), Vector2(1, 0), Vector2(0, 0), Vector2(-1, 0) ]] # T
-var width=0
-var height=0
+var block_rotations = [
+ Matrix32(Vector2(1, 0), Vector2(0, 1), Vector2()),
+ Matrix32(Vector2(0, 1), Vector2(-1, 0), Vector2()),
+ Matrix32(Vector2(-1, 0), Vector2(0, -1), Vector2()),
+ Matrix32(Vector2(0, -1), Vector2(1, 0), Vector2())]
-var cells={}
+var width = 0
+var height = 0
-var piece_active=false
-var piece_shape=0
-var piece_pos=Vector2()
-var piece_rot=0
+var cells = {}
+var piece_active = false
+var piece_shape = 0
+var piece_pos = Vector2()
+var piece_rot = 0
-func piece_cell_xform(p,er=0):
- var r = (4+er+piece_rot)%4
- return piece_pos+block_rotations[r].xform(p)
-func _draw():
+func piece_cell_xform(p, er = 0):
+ var r = (4 + er + piece_rot) % 4
+ return piece_pos + block_rotations[r].xform(p)
+
- var sb = get_stylebox("bg","Tree") # use line edit bg
- draw_style_box(sb,Rect2(Vector2(),get_size()).grow(3))
+func _draw():
+ var sb = get_stylebox("bg", "Tree") # Use line edit bg
+ draw_style_box(sb, Rect2(Vector2(), get_size()).grow(3))
var bs = block.get_size()
for y in range(height):
for x in range(width):
- if (Vector2(x,y) in cells):
- draw_texture_rect(block,Rect2(Vector2(x,y)*bs,bs),false,block_colors[cells[Vector2(x,y)]])
-
+ if (Vector2(x, y) in cells):
+ draw_texture_rect(block, Rect2(Vector2(x, y)*bs, bs), false, block_colors[cells[Vector2(x, y)]])
+
if (piece_active):
-
for c in block_shapes[piece_shape]:
- draw_texture_rect(block,Rect2(piece_cell_xform(c)*bs,bs),false,block_colors[piece_shape])
-
+ draw_texture_rect(block, Rect2(piece_cell_xform(c)*bs, bs), false, block_colors[piece_shape])
-func piece_check_fit(ofs,er=0):
+func piece_check_fit(ofs, er = 0):
for c in block_shapes[piece_shape]:
- var pos = piece_cell_xform(c,er)+ofs
+ var pos = piece_cell_xform(c, er) + ofs
if (pos.x < 0):
return false
if (pos.y < 0):
@@ -88,130 +82,113 @@ func piece_check_fit(ofs,er=0):
if (pos in cells):
return false
- return true
+ return true
-func new_piece():
- piece_shape = randi() % MAX_SHAPES
- piece_pos = Vector2(width/2,0)
- piece_active=true
- piece_rot=0
- if (piece_shape==0):
- piece_pos.y+=1
-
+func new_piece():
+ piece_shape = randi() % MAX_SHAPES
+ piece_pos = Vector2(width/2, 0)
+ piece_active = true
+ piece_rot = 0
+ if (piece_shape == 0):
+ piece_pos.y += 1
+
if (not piece_check_fit(Vector2())):
- #game over
- #print("GAME OVER!")
+ # Game over
game_over()
-
- update()
-
+ update()
+
+
func test_collapse_rows():
- var accum_down=0
+ var accum_down = 0
for i in range(height):
var y = height - i - 1
var collapse = true
for x in range(width):
- if (Vector2(x,y) in cells):
+ if (Vector2(x, y) in cells):
if (accum_down):
- cells[ Vector2(x,y+accum_down) ] = cells[Vector2(x,y)]
+ cells[Vector2(x, y + accum_down)] = cells[Vector2(x, y)]
else:
- collapse=false
+ collapse = false
if (accum_down):
- cells.erase( Vector2(x,y+accum_down) )
-
- if (collapse):
- accum_down+=1
+ cells.erase(Vector2(x, y + accum_down))
-
- score+=accum_down*100
+ if (collapse):
+ accum_down += 1
+
+ score += accum_down*100
score_label.set_text(str(score))
-
-
+
+
func game_over():
+ piece_active = false
+ get_node("gameover").set_text("Game over!")
+ update()
+
- piece_active=false
- get_node("gameover").set_text("Game Over")
- update()
-
-
func restart_pressed():
+ score = 0
+ score_label.set_text("0")
+ cells.clear()
+ get_node("gameover").set_text("")
+ piece_active = true
+ get_node("../restart").release_focus()
+ update()
- score=0
- score_label.set_text("0")
- cells.clear()
- get_node("gameover").set_text("")
- piece_active=true
- get_node("../restart").release_focus()
- update()
-
-
func piece_move_down():
-
if (!piece_active):
return
- if (piece_check_fit(Vector2(0,1))):
- piece_pos.y+=1
- update()
+ if (piece_check_fit(Vector2(0, 1))):
+ piece_pos.y += 1
+ update()
else:
-
for c in block_shapes[piece_shape]:
var pos = piece_cell_xform(c)
- cells[pos]=piece_shape
+ cells[pos] = piece_shape
test_collapse_rows()
new_piece()
-
-func piece_rotate():
+func piece_rotate():
var adv = 1
- if (not piece_check_fit(Vector2(),1)):
+ if (not piece_check_fit(Vector2(), 1)):
return
piece_rot = (piece_rot + adv) % 4
update()
-
-
-
-func _input(ie):
+func _input(ie):
if (not piece_active):
return
if (!ie.is_pressed()):
return
if (ie.is_action("move_left")):
- if (piece_check_fit(Vector2(-1,0))):
- piece_pos.x-=1
+ if (piece_check_fit(Vector2(-1, 0))):
+ piece_pos.x -= 1
update()
elif (ie.is_action("move_right")):
- if (piece_check_fit(Vector2(1,0))):
- piece_pos.x+=1
+ if (piece_check_fit(Vector2(1, 0))):
+ piece_pos.x += 1
update()
elif (ie.is_action("move_down")):
piece_move_down()
elif (ie.is_action("rotate")):
piece_rotate()
-
-
-func setup(w,h):
- width=w
- height=h
- set_size( Vector2(w,h)*block.get_size() )
+
+
+func setup(w, h):
+ width = w
+ height = h
+ set_size(Vector2(w, h)*block.get_size())
new_piece()
get_node("timer").start()
-
-func _ready():
- # Initalization here
- setup(10,20)
+func _ready():
+ setup(10, 20)
score_label = get_node("../score")
-
+
set_process_input(true)
-
-
-
-
diff --git a/demos/2d/tetris/grid.xml b/demos/2d/tetris/grid.xml
index 072ffb5e75..49ad4ccc41 100644
--- a/demos/2d/tetris/grid.xml
+++ b/demos/2d/tetris/grid.xml
@@ -1,153 +1,209 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="2" version="0.99" version_name="Godot Engine v0.99.3037-pre-beta">
- <ext_resource path="res://grid.gd" type="GDScript"></ext_resource>
+<resource_file type="PackedScene" subresource_count="2" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://grid.gd" type="Script" index="0"></ext_resource>
<main_resource>
- <string name="resource/name"> "" </string>
- <dictionary name="_bundled">
+ <dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 1 </int>
+ <string> "conns" </string>
+ <int_array len="6"> 1, 0, 30, 29, 2, 0 </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="57">
+ <string_array len="31">
<string> "Grid" </string>
- <string> "Control" </string>
- <string> "process/process" </string>
- <string> "process/fixed_process" </string>
- <string> "process/input" </string>
- <string> "process/unhandled_input" </string>
- <string> "process/mode" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/toplevel" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "visibility/blend_mode" </string>
- <string> "transform/notify" </string>
- <string> "anchor/left" </string>
- <string> "anchor/top" </string>
- <string> "anchor/right" </string>
- <string> "anchor/bottom" </string>
- <string> "margin/left" </string>
- <string> "margin/top" </string>
<string> "margin/right" </string>
<string> "margin/bottom" </string>
- <string> "hint/tooltip" </string>
- <string> "focus_neighbour/left" </string>
- <string> "focus_neighbour/top" </string>
- <string> "focus_neighbour/right" </string>
- <string> "focus_neighbour/bottom" </string>
<string> "focus/ignore_mouse" </string>
<string> "focus/stop_mouse" </string>
<string> "size_flags/horizontal" </string>
<string> "size_flags/vertical" </string>
- <string> "size_flags/stretch_ratio" </string>
<string> "script/script" </string>
<string> "__meta__" </string>
+ <string> "Control" </string>
<string> "timer" </string>
- <string> "Timer" </string>
+ <string> "process_mode" </string>
<string> "wait_time" </string>
<string> "one_shot" </string>
<string> "autostart" </string>
+ <string> "Timer" </string>
<string> "gameover" </string>
- <string> "Label" </string>
+ <string> "anchor/right" </string>
+ <string> "anchor/bottom" </string>
<string> "custom_colors/font_color" </string>
+ <string> "custom_colors/font_color_shadow" </string>
<string> "custom_constants/shadow_offset_x" </string>
<string> "custom_constants/shadow_offset_y" </string>
- <string> "range/min" </string>
- <string> "range/max" </string>
- <string> "range/step" </string>
- <string> "range/page" </string>
- <string> "range/value" </string>
- <string> "range/exp_edit" </string>
- <string> "rounded_values" </string>
- <string> "text" </string>
<string> "align" </string>
<string> "valign" </string>
- <string> "autowrap" </string>
+ <string> "percent_visible" </string>
+ <string> "lines_skipped" </string>
+ <string> "max_lines_visible" </string>
+ <string> "Label" </string>
<string> "piece_move_down" </string>
<string> "timeout" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 1 </int>
<string> "node_count" </string>
<int> 3 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="73"> -1, -1, 9, 0, -1, 8, 1, 0, 2, 0, 3, 1, 4, 2, 5, 3, 6, 3, 7, 4, 8, 5, 0, 0, 0, 15, 10, -1, 4, 11, 6, 12, 7, 13, 1, 14, 1, 0, 0, 0, 28, 16, -1, 14, 17, 6, 18, 6, 3, 2, 4, 2, 5, 3, 19, 8, 20, 9, 21, 6, 22, 6, 23, 6, 24, 6, 25, 7, 26, 10, 27, 11, 0 </int_array>
<string> "variants" </string>
- <array len="14">
+ <array len="12" shared="false">
+ <real> 40 </real>
<bool> False </bool>
- <int> 0 </int>
<bool> True </bool>
- <real> 1 </real>
- <real> 0 </real>
- <real> 40 </real>
- <string> "" </string>
- <node_path> "" </node_path>
<int> 2 </int>
- <resource resource_type="GDScript" path="res://grid.gd"> </resource>
- <dictionary>
+ <resource external="0"> </resource>
+ <dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
- <dictionary>
- <string> "Script" </string>
- <dictionary>
- <string> "current" </string>
- <int> 0 </int>
- <string> "sources" </string>
- <array len="1">
- <string> "res://grid.gd" </string>
- </array>
- </dictionary>
+ <dictionary shared="false">
<string> "2D" </string>
- <dictionary>
+ <dictionary shared="false">
+ <string> "ofs" </string>
+ <vector2> -229.129, -80 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
<string> "zoom" </string>
<real> 1 </real>
- <string> "ofs" </string>
- <vector2> -69, -22 </vector2>
</dictionary>
<string> "3D" </string>
- <dictionary>
- <string> "zfar" </string>
- <real> 500 </real>
+ <dictionary shared="false">
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
- <string> "window_mode" </string>
- <int> 0 </int>
- <string> "window_0" </string>
- <dictionary>
- <string> "distance" </string>
- <real> 4 </real>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "x_rot" </string>
- <real> 0.337 </real>
- <string> "y_rot" </string>
- <real> -0.575 </real>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
+ <string> "viewports" </string>
+ <array len="4" shared="false">
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ </array>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
- <dictionary>
+ <dictionary shared="false">
<string> "custom_args" </string>
<string> "-l $scene" </string>
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "Script" </string>
</dictionary>
- <resource name=""></resource> <int> 1 </int>
+ <int> 1 </int>
+ <real> 1 </real>
+ <color> 1, 1, 1, 1 </color>
<color> 0, 0, 0, 1 </color>
+ <int> 0 </int>
+ <int> -1 </int>
</array>
- <string> "nodes" </string>
- <int_array len="193"> -1, -1, 1, 0, -1, 32, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 0, 14, 1, 15, 1, 16, 1, 17, 1, 18, 4, 19, 4, 20, 5, 21, 5, 22, 6, 23, 7, 24, 7, 25, 7, 26, 7, 27, 0, 28, 2, 29, 8, 30, 8, 31, 3, 32, 9, 33, 10, 0, 0, 0, 35, 34, -1, 9, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 36, 3, 37, 0, 38, 0, 32, 11, 0, 0, 0, 40, 39, -1, 45, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 0, 14, 1, 15, 1, 16, 12, 17, 12, 18, 4, 19, 4, 20, 4, 21, 4, 22, 6, 23, 7, 24, 7, 25, 7, 26, 7, 27, 2, 28, 2, 29, 8, 30, 1, 31, 3, 41, 13, 42, 12, 43, 12, 44, 4, 45, 3, 46, 3, 47, 3, 48, 4, 49, 0, 50, 0, 51, 6, 52, 12, 53, 12, 54, 0, 32, 11, 0 </int_array>
- <string> "conns" </string>
- <int_array len="6"> 1, 0, 56, 55, 2, 0 </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
- <resource name="script/script"></resource>
+
</main_resource>
</resource_file> \ No newline at end of file
diff --git a/demos/2d/tetris/tetris.xml b/demos/2d/tetris/tetris.xml
index 1b5e5afeb0..a8e47a8ae4 100644
--- a/demos/2d/tetris/tetris.xml
+++ b/demos/2d/tetris/tetris.xml
@@ -1,147 +1,192 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="2" version="0.99" version_name="Godot Engine v0.99.3037-pre-beta">
- <ext_resource path="res://grid.xml" type="PackedScene"></ext_resource>
+<resource_file type="PackedScene" subresource_count="2" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://grid.xml" type="PackedScene" index="0"></ext_resource>
<main_resource>
- <string name="resource/name"> "" </string>
- <dictionary name="_bundled">
+ <dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 1 </int>
+ <string> "conns" </string>
+ <int_array len="6"> 4, 1, 23, 22, 2, 0 </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
<string> "names" </string>
- <string_array len="59">
+ <string_array len="24">
<string> "Tetris" </string>
- <string> "Panel" </string>
- <string> "process/process" </string>
- <string> "process/fixed_process" </string>
- <string> "process/input" </string>
- <string> "process/unhandled_input" </string>
- <string> "process/mode" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/toplevel" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "visibility/blend_mode" </string>
- <string> "transform/notify" </string>
- <string> "anchor/left" </string>
- <string> "anchor/top" </string>
- <string> "anchor/right" </string>
- <string> "anchor/bottom" </string>
- <string> "margin/left" </string>
- <string> "margin/top" </string>
<string> "margin/right" </string>
<string> "margin/bottom" </string>
- <string> "hint/tooltip" </string>
- <string> "focus_neighbour/left" </string>
- <string> "focus_neighbour/top" </string>
- <string> "focus_neighbour/right" </string>
- <string> "focus_neighbour/bottom" </string>
<string> "focus/ignore_mouse" </string>
<string> "focus/stop_mouse" </string>
<string> "size_flags/horizontal" </string>
<string> "size_flags/vertical" </string>
- <string> "size_flags/stretch_ratio" </string>
- <string> "script/script" </string>
<string> "__meta__" </string>
+ <string> "Panel" </string>
<string> "Grid" </string>
- <string> "Control" </string>
+ <string> "margin/left" </string>
+ <string> "margin/top" </string>
<string> "Label" </string>
- <string> "range/min" </string>
- <string> "range/max" </string>
- <string> "range/step" </string>
- <string> "range/page" </string>
- <string> "range/value" </string>
- <string> "range/exp_edit" </string>
- <string> "rounded_values" </string>
<string> "text" </string>
- <string> "align" </string>
- <string> "valign" </string>
- <string> "autowrap" </string>
+ <string> "percent_visible" </string>
+ <string> "lines_skipped" </string>
+ <string> "max_lines_visible" </string>
<string> "score" </string>
<string> "restart" </string>
- <string> "Button" </string>
- <string> "disabled" </string>
<string> "toggle_mode" </string>
- <string> "click_on_press" </string>
- <string> "icon" </string>
<string> "flat" </string>
- <string> "clip_text" </string>
+ <string> "Button" </string>
<string> "restart_pressed" </string>
<string> "pressed" </string>
</string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 1 </int>
<string> "node_count" </string>
<int> 5 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="123"> -1, -1, 8, 0, -1, 7, 1, 0, 2, 0, 3, 1, 4, 2, 5, 3, 6, 3, 7, 4, 0, 0, 0, 2147483647, 9, 5, 4, 10, 6, 11, 7, 1, 8, 2, 9, 0, 0, 0, 12, 12, -1, 11, 10, 10, 11, 11, 1, 12, 2, 13, 3, 2, 4, 2, 5, 3, 13, 14, 14, 15, 15, 16, 16, 17, 0, 0, 0, 12, 17, -1, 11, 10, 18, 11, 19, 1, 20, 2, 21, 3, 2, 4, 2, 5, 3, 13, 22, 14, 15, 15, 16, 16, 17, 0, 0, 0, 21, 18, -1, 11, 10, 10, 11, 23, 1, 24, 2, 25, 3, 1, 4, 2, 5, 3, 6, 3, 19, 1, 13, 26, 20, 1, 0 </int_array>
<string> "variants" </string>
- <array len="30">
+ <array len="27" shared="false">
+ <real> 400 </real>
<bool> False </bool>
- <int> 0 </int>
<bool> True </bool>
- <real> 1 </real>
- <real> 0 </real>
- <real> 400 </real>
- <string> "" </string>
- <node_path> "" </node_path>
<int> 2 </int>
- <resource name=""></resource> <dictionary>
+ <dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
<string> "__editor_plugin_states__" </string>
- <dictionary>
- <string> "Script" </string>
- <dictionary>
- <string> "current" </string>
- <int> 0 </int>
- <string> "sources" </string>
- <array len="1">
- <string> "res://grid.gd" </string>
- </array>
- </dictionary>
+ <dictionary shared="false">
<string> "2D" </string>
- <dictionary>
+ <dictionary shared="false">
+ <string> "ofs" </string>
+ <vector2> -229.129, -54.344 </vector2>
+ <string> "snap_grid" </string>
+ <bool> False </bool>
+ <string> "snap_offset" </string>
+ <vector2> 0, 0 </vector2>
+ <string> "snap_pixel" </string>
+ <bool> False </bool>
+ <string> "snap_relative" </string>
+ <bool> False </bool>
+ <string> "snap_rotation" </string>
+ <bool> False </bool>
+ <string> "snap_rotation_offset" </string>
+ <real> 0 </real>
+ <string> "snap_rotation_step" </string>
+ <real> 0.261799 </real>
+ <string> "snap_show_grid" </string>
+ <bool> False </bool>
+ <string> "snap_step" </string>
+ <vector2> 10, 10 </vector2>
<string> "zoom" </string>
<real> 1.360374 </real>
- <string> "ofs" </string>
- <vector2> -44.5757, -54.344 </vector2>
</dictionary>
<string> "3D" </string>
- <dictionary>
- <string> "zfar" </string>
- <real> 500 </real>
+ <dictionary shared="false">
+ <string> "ambient_light_color" </string>
+ <color> 0.15, 0.15, 0.15, 1 </color>
+ <string> "default_light" </string>
+ <bool> True </bool>
+ <string> "default_srgb" </string>
+ <bool> False </bool>
+ <string> "deflight_rot_x" </string>
+ <real> 0.942478 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "fov" </string>
<real> 45 </real>
- <string> "window_mode" </string>
- <int> 0 </int>
- <string> "window_0" </string>
- <dictionary>
- <string> "distance" </string>
- <real> 4 </real>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "x_rot" </string>
- <real> 0.337 </real>
- <string> "y_rot" </string>
- <real> -0.575 </real>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
+ <string> "show_grid" </string>
+ <bool> True </bool>
+ <string> "show_origin" </string>
+ <bool> True </bool>
+ <string> "viewport_mode" </string>
+ <int> 1 </int>
+ <string> "viewports" </string>
+ <array len="4" shared="false">
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> True </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "distance" </string>
+ <real> 4 </real>
+ <string> "listener" </string>
+ <bool> False </bool>
+ <string> "pos" </string>
+ <vector3> 0, 0, 0 </vector3>
+ <string> "use_environment" </string>
+ <bool> False </bool>
+ <string> "use_orthogonal" </string>
+ <bool> False </bool>
+ <string> "x_rot" </string>
+ <real> 0 </real>
+ <string> "y_rot" </string>
+ <real> 0 </real>
+ </dictionary>
+ </array>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
+ <string> "Anim" </string>
+ <dictionary shared="false">
+ <string> "visible" </string>
+ <bool> False </bool>
+ </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
- <dictionary>
+ <dictionary shared="false">
<string> "custom_args" </string>
<string> "-l $scene" </string>
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
</dictionary>
- <resource resource_type="PackedScene" path="res://grid.xml"> </resource>
+ <resource external="0"> </resource>
<real> 40 </real>
<real> 35 </real>
<real> 80 </real>
@@ -151,6 +196,9 @@
<real> 283 </real>
<real> 49 </real>
<string> "Score:" </string>
+ <real> 1 </real>
+ <int> 0 </int>
+ <int> -1 </int>
<real> 252 </real>
<real> 55 </real>
<real> 293 </real>
@@ -161,11 +209,9 @@
<real> 311 </real>
<string> "Restart" </string>
</array>
- <string> "nodes" </string>
- <int_array len="351"> -1, -1, 1, 0, -1, 32, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 0, 14, 1, 15, 1, 16, 1, 17, 1, 18, 4, 19, 4, 20, 5, 21, 5, 22, 6, 23, 7, 24, 7, 25, 7, 26, 7, 27, 0, 28, 2, 29, 8, 30, 8, 31, 3, 32, 9, 33, 10, 0, 0, 0, 35, 34, 11, 4, 18, 12, 19, 13, 20, 14, 21, 15, 0, 0, 0, 36, 36, -1, 42, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 0, 14, 1, 15, 1, 16, 1, 17, 1, 18, 16, 19, 17, 20, 18, 21, 19, 22, 6, 23, 7, 24, 7, 25, 7, 26, 7, 27, 2, 28, 2, 29, 8, 30, 1, 31, 3, 37, 4, 38, 3, 39, 3, 40, 3, 41, 4, 42, 0, 43, 0, 44, 20, 45, 1, 46, 1, 47, 0, 32, 9, 0, 0, 0, 36, 48, -1, 42, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 0, 14, 1, 15, 1, 16, 1, 17, 1, 18, 21, 19, 22, 20, 23, 21, 24, 22, 6, 23, 7, 24, 7, 25, 7, 26, 7, 27, 2, 28, 2, 29, 8, 30, 1, 31, 3, 37, 4, 38, 3, 39, 3, 40, 3, 41, 4, 42, 0, 43, 0, 44, 25, 45, 1, 46, 1, 47, 0, 32, 9, 0, 0, 0, 50, 49, -1, 38, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 0, 14, 1, 15, 1, 16, 1, 17, 1, 18, 16, 19, 26, 20, 27, 21, 28, 22, 6, 23, 7, 24, 7, 25, 7, 26, 7, 27, 0, 28, 2, 29, 8, 30, 8, 31, 3, 51, 0, 52, 0, 53, 0, 44, 29, 54, 9, 55, 0, 56, 0, 32, 9, 0 </int_array>
- <string> "conns" </string>
- <int_array len="6"> 4, 1, 58, 57, 2, 0 </int_array>
+ <string> "version" </string>
+ <int> 2 </int>
</dictionary>
- <resource name="script/script"></resource>
+
</main_resource>
</resource_file> \ No newline at end of file
diff --git a/demos/2d/texscreen/bubbles.gd b/demos/2d/texscreen/bubbles.gd
index 2ee227a928..400da1a205 100644
--- a/demos/2d/texscreen/bubbles.gd
+++ b/demos/2d/texscreen/bubbles.gd
@@ -1,17 +1,11 @@
extends Control
-# member variables here, example:
-# var a=2
-# var b="textvar"
+# Member variables
+const MAX_BUBBLES = 10
-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
index 41026aceed..8509b3811c 100644
--- a/demos/2d/texscreen/bubbles.scn
+++ b/demos/2d/texscreen/bubbles.scn
Binary files differ
diff --git a/demos/2d/texscreen/lens.gd b/demos/2d/texscreen/lens.gd
index 2ccbfba497..d1007553b0 100644
--- a/demos/2d/texscreen/lens.gd
+++ b/demos/2d/texscreen/lens.gd
@@ -1,37 +1,32 @@
extends BackBufferCopy
-# member variables here, example:
-# var a=2
-# var b="textvar"
-const MOTION_SPEED=150
+# Member variables
+const MOTION_SPEED = 150
+
+var vsize
+var dir
-var vsize;
-var dir;
func _process(delta):
- var pos = get_pos() + dir * delta * MOTION_SPEED
+ 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)
- 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()
+ 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
index 5c6f8b7af8..530a0b1eb0 100644
--- a/demos/2d/texscreen/lens.scn
+++ b/demos/2d/texscreen/lens.scn
Binary files differ
diff --git a/demos/3d/fixed_materials/fixed_materials.scn b/demos/3d/fixed_materials/fixed_materials.scn
index de14ccdb15..94809b9a5e 100644
--- a/demos/3d/fixed_materials/fixed_materials.scn
+++ b/demos/3d/fixed_materials/fixed_materials.scn
Binary files differ
diff --git a/demos/3d/kinematic_char/cubio.gd b/demos/3d/kinematic_char/cubio.gd
index 058b919d05..769ada3bca 100644
--- a/demos/3d/kinematic_char/cubio.gd
+++ b/demos/3d/kinematic_char/cubio.gd
@@ -1,10 +1,7 @@
extends KinematicBody
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
+# Member variables
var g = -9.8
var vel = Vector3()
const MAX_SPEED = 5
@@ -13,83 +10,77 @@ const ACCEL= 2
const DEACCEL= 4
const MAX_SLOPE_ANGLE = 30
-func _fixed_process(delta):
- var dir = Vector3() #where does the player intend to walk to
+func _fixed_process(delta):
+ var dir = Vector3() # Where does the player intend to walk to
var cam_xform = get_node("target/camera").get_global_transform()
if (Input.is_action_pressed("move_forward")):
- dir+=-cam_xform.basis[2]
+ dir += -cam_xform.basis[2]
if (Input.is_action_pressed("move_backwards")):
- dir+=cam_xform.basis[2]
+ dir += cam_xform.basis[2]
if (Input.is_action_pressed("move_left")):
- dir+=-cam_xform.basis[0]
+ dir += -cam_xform.basis[0]
if (Input.is_action_pressed("move_right")):
- dir+=cam_xform.basis[0]
-
- dir.y=0
- dir=dir.normalized()
-
- vel.y+=delta*g
+ dir += cam_xform.basis[0]
+
+ dir.y = 0
+ dir = dir.normalized()
+
+ vel.y += delta*g
var hvel = vel
- hvel.y=0
+ hvel.y = 0
var target = dir*MAX_SPEED
var accel
- if (dir.dot(hvel) >0):
- accel=ACCEL
+ if (dir.dot(hvel) > 0):
+ accel = ACCEL
else:
- accel=DEACCEL
-
- hvel = hvel.linear_interpolate(target,accel*delta)
+ accel = DEACCEL
+
+ hvel = hvel.linear_interpolate(target, accel*delta)
+
+ vel.x = hvel.x
+ vel.z = hvel.z
- vel.x=hvel.x;
- vel.z=hvel.z
-
var motion = move(vel*delta)
-
+
var on_floor = false
var original_vel = vel
-
-
- var floor_velocity=Vector3()
-
- var attempts=4
+ var floor_velocity = Vector3()
+ var attempts = 4
while(is_colliding() and attempts):
- var n=get_collision_normal()
-
- if ( rad2deg(acos(n.dot( Vector3(0,1,0)))) < MAX_SLOPE_ANGLE ):
- #if angle to the "up" vectors is < angle tolerance
- #char is on floor
- floor_velocity=get_collider_velocity()
- on_floor=true
+ var n = get_collision_normal()
+
+ if (rad2deg(acos(n.dot(Vector3(0, 1, 0)))) < MAX_SLOPE_ANGLE):
+ # If angle to the "up" vectors is < angle tolerance,
+ # char is on floor
+ floor_velocity = get_collider_velocity()
+ on_floor = true
motion = n.slide(motion)
vel = n.slide(vel)
if (original_vel.dot(vel) > 0):
- #do not allow to slide towads the opposite direction we were coming from
+ # Do not allow to slide towads the opposite direction we were coming from
motion=move(motion)
- if (motion.length()<0.001):
+ if (motion.length() < 0.001):
break
- attempts-=1
-
- if (on_floor and floor_velocity!=Vector3()):
- move(floor_velocity*delta)
+ attempts -= 1
+
+ if (on_floor and floor_velocity != Vector3()):
+ move(floor_velocity*delta)
if (on_floor and Input.is_action_pressed("jump")):
- vel.y=JUMP_SPEED
-
+ vel.y = JUMP_SPEED
+
var crid = get_node("../elevator1").get_rid()
-# print(crid," : ",PS.body_get_state(crid,PS.BODY_STATE_TRANSFORM))
+
func _ready():
- # Initalization here
set_fixed_process(true)
- pass
-func _on_tcube_body_enter( body ):
+func _on_tcube_body_enter(body):
get_node("../ty").show()
- pass # replace with function body
diff --git a/demos/3d/kinematic_char/follow_camera.gd b/demos/3d/kinematic_char/follow_camera.gd
index cf7172d7bb..37a1402053 100644
--- a/demos/3d/kinematic_char/follow_camera.gd
+++ b/demos/3d/kinematic_char/follow_camera.gd
@@ -1,69 +1,57 @@
extends Camera
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-var collision_exception=[]
-export var min_distance=0.5
-export var max_distance=4.0
-export var angle_v_adjust=0.0
-export var autoturn_ray_aperture=25
-export var autoturn_speed=50
+# Member variables
+var collision_exception = []
+export var min_distance = 0.5
+export var max_distance = 4.0
+export var angle_v_adjust = 0.0
+export var autoturn_ray_aperture = 25
+export var autoturn_speed = 50
var max_height = 2.0
var min_height = 0
+
func _fixed_process(dt):
- var target = get_parent().get_global_transform().origin
+ var target = get_parent().get_global_transform().origin
var pos = get_global_transform().origin
- var up = Vector3(0,1,0)
+ var up = Vector3(0, 1, 0)
var delta = pos - target
- #regular delta follow
+ # Regular delta follow
- #check ranges
-
+ # Check ranges
if (delta.length() < min_distance):
- delta = delta.normalized() * min_distance
+ delta = delta.normalized()*min_distance
elif (delta.length() > max_distance):
- delta = delta.normalized() * max_distance
+ delta = delta.normalized()*max_distance
- #check upper and lower height
- if ( delta.y > max_height):
+ # Check upper and lower height
+ if (delta.y > max_height):
delta.y = max_height
- if ( delta.y < min_height):
+ if (delta.y < min_height):
delta.y = min_height
-
+
pos = target + delta
- look_at_from_pos(pos,target,up)
+ look_at_from_pos(pos, target, up)
- #turn a little up or down
+ # Turn a little up or down
var t = get_transform()
- t.basis = Matrix3(t.basis[0],deg2rad(angle_v_adjust)) * t.basis
+ t.basis = Matrix3(t.basis[0], deg2rad(angle_v_adjust))*t.basis
set_transform(t)
-
-
-func _ready():
-#find collision exceptions for ray
+func _ready():
+ # Find collision exceptions for ray
var node = self
while(node):
if (node extends RigidBody):
collision_exception.append(node.get_rid())
break
else:
- node=node.get_parent()
- # Initalization here
+ node = node.get_parent()
set_fixed_process(true)
- #this detaches the camera transform from the parent spatial node
+ # This detaches the camera transform from the parent spatial node
set_as_toplevel(true)
-
-
-
-
-
-
diff --git a/demos/3d/kinematic_char/level.scn b/demos/3d/kinematic_char/level.scn
index 8be64c61c0..0082f55f43 100644
--- a/demos/3d/kinematic_char/level.scn
+++ b/demos/3d/kinematic_char/level.scn
Binary files differ
diff --git a/demos/3d/kinematic_char/purplecube.scn b/demos/3d/kinematic_char/purplecube.scn
index ab758366fd..e3ed1bf84b 100644
--- a/demos/3d/kinematic_char/purplecube.scn
+++ b/demos/3d/kinematic_char/purplecube.scn
Binary files differ
diff --git a/demos/3d/mousepick_test/mousepick.gd b/demos/3d/mousepick_test/mousepick.gd
index c96091b650..674ec7ff6f 100644
--- a/demos/3d/mousepick_test/mousepick.gd
+++ b/demos/3d/mousepick_test/mousepick.gd
@@ -1,15 +1,12 @@
extends RigidBody
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
+# Member variables
var gray_mat = FixedMaterial.new()
+var selected = false
-var selected=false
-func _input_event(camera,event,pos,normal,shape):
+func _input_event(camera, event, pos, normal, shape):
if (event.type==InputEvent.MOUSE_BUTTON and event.pressed):
if (not selected):
get_node("mesh").set_material_override(gray_mat)
@@ -17,16 +14,11 @@ func _input_event(camera,event,pos,normal,shape):
get_node("mesh").set_material_override(null)
selected = not selected
-
-func _mouse_enter():
- get_node("mesh").set_scale( Vector3(1.1,1.1,1.1) )
-func _mouse_exit():
- get_node("mesh").set_scale( Vector3(1,1,1) )
-
-func _ready():
- # Initalization here
- pass
+func _mouse_enter():
+ get_node("mesh").set_scale(Vector3(1.1, 1.1, 1.1))
+func _mouse_exit():
+ get_node("mesh").set_scale(Vector3(1, 1, 1))
diff --git a/demos/3d/mousepick_test/mousepick.scn b/demos/3d/mousepick_test/mousepick.scn
index 7ecac46a86..0b6c33c119 100644
--- a/demos/3d/mousepick_test/mousepick.scn
+++ b/demos/3d/mousepick_test/mousepick.scn
Binary files differ
diff --git a/demos/3d/navmesh/navmesh.gd b/demos/3d/navmesh/navmesh.gd
index b5dc488ec3..30b8cfb32a 100644
--- a/demos/3d/navmesh/navmesh.gd
+++ b/demos/3d/navmesh/navmesh.gd
@@ -1,61 +1,54 @@
extends Navigation
-# member variables here, example:
-# var a=2
-# var b="textvar"
+# Member variables
+const SPEED = 4.0
-const SPEED=4.0
+var camrot = 0.0
-var camrot=0.0
-
-var begin=Vector3()
-var end=Vector3()
+var begin = Vector3()
+var end = Vector3()
var m = FixedMaterial.new()
-var path=[]
-
-func _process(delta):
+var path = []
+var draw_path = false
- if (path.size()>1):
-
+func _process(delta):
+ if (path.size() > 1):
var to_walk = delta*SPEED
- var to_watch = Vector3(0,1,0)
- while(to_walk>0 and path.size()>=2):
- var pfrom = path[path.size()-1]
- var pto = path[path.size()-2]
+ var to_watch = Vector3(0, 1, 0)
+ while(to_walk > 0 and path.size() >= 2):
+ var pfrom = path[path.size() - 1]
+ var pto = path[path.size() - 2]
to_watch = (pto - pfrom).normalized()
var d = pfrom.distance_to(pto)
- if (d<=to_walk):
- path.remove(path.size()-1)
- to_walk-=d
+ if (d <= to_walk):
+ path.remove(path.size() - 1)
+ to_walk -= d
else:
- path[path.size()-1] = pfrom.linear_interpolate(pto,to_walk/d)
- to_walk=0
-
- var atpos = path[path.size()-1]
+ path[path.size() - 1] = pfrom.linear_interpolate(pto, to_walk/d)
+ to_walk = 0
+
+ var atpos = path[path.size() - 1]
var atdir = to_watch
- atdir.y=0
+ atdir.y = 0
var t = Transform()
- t.origin=atpos
- t=t.looking_at(atpos+atdir,Vector3(0,1,0))
+ t.origin = atpos
+ t=t.looking_at(atpos + atdir, Vector3(0, 1, 0))
get_node("robot_base").set_transform(t)
- if (path.size()<2):
- path=[]
+ if (path.size() < 2):
+ path = []
set_process(false)
-
else:
set_process(false)
-var draw_path=false
func _update_path():
-
- var p = get_simple_path(begin,end,true)
- path=Array(p) # Vector3array to complex to use, convert to regular array
+ var p = get_simple_path(begin, end, true)
+ path = Array(p) # Vector3array too complex to use, convert to regular array
path.invert()
set_process(true)
@@ -63,48 +56,40 @@ func _update_path():
var im = get_node("draw")
im.set_material_override(m)
im.clear()
- im.begin(Mesh.PRIMITIVE_POINTS,null)
+ im.begin(Mesh.PRIMITIVE_POINTS, null)
im.add_vertex(begin)
im.add_vertex(end)
im.end()
- im.begin(Mesh.PRIMITIVE_LINE_STRIP,null)
+ im.begin(Mesh.PRIMITIVE_LINE_STRIP, null)
for x in p:
im.add_vertex(x)
im.end()
-func _input(ev):
- if (ev.type==InputEvent.MOUSE_BUTTON and ev.button_index==BUTTON_LEFT and ev.pressed):
-
- var from = get_node("cambase/Camera").project_ray_origin(ev.pos)
- var to = from+get_node("cambase/Camera").project_ray_normal(ev.pos)*100
- var p = get_closest_point_to_segment(from,to)
-
- begin=get_closest_point(get_node("robot_base").get_translation())
- end=p
+func _input(event):
+ if (event.type == InputEvent.MOUSE_BUTTON and event.button_index == BUTTON_LEFT and event.pressed):
+ var from = get_node("cambase/Camera").project_ray_origin(event.pos)
+ var to = from + get_node("cambase/Camera").project_ray_normal(event.pos)*100
+ var p = get_closest_point_to_segment(from, to)
+
+ begin = get_closest_point(get_node("robot_base").get_translation())
+ end = p
_update_path()
-
- if (ev.type==InputEvent.MOUSE_MOTION):
- if (ev.button_mask&BUTTON_MASK_MIDDLE):
-
- camrot+=ev.relative_x*0.005
- get_node("cambase").set_rotation(Vector3(0,camrot,0))
+
+ if (event.type == InputEvent.MOUSE_MOTION):
+ if (event.button_mask&BUTTON_MASK_MIDDLE):
+ camrot += event.relative_x*0.005
+ get_node("cambase").set_rotation(Vector3(0, camrot, 0))
print("camrot ", camrot)
-
func _ready():
- # Initalization here
set_process_input(true)
m.set_line_width(3)
m.set_point_size(3)
- m.set_fixed_flag(FixedMaterial.FLAG_USE_POINT_SIZE,true)
- m.set_flag(Material.FLAG_UNSHADED,true)
+ m.set_fixed_flag(FixedMaterial.FLAG_USE_POINT_SIZE, true)
+ m.set_flag(Material.FLAG_UNSHADED, true)
#begin = get_closest_point(get_node("start").get_translation())
#end = get_closest_point(get_node("end").get_translation())
#call_deferred("_update_path")
-
- pass
-
-
diff --git a/demos/3d/navmesh/navmesh.scn b/demos/3d/navmesh/navmesh.scn
index 1202985dec..33183781ad 100644
--- a/demos/3d/navmesh/navmesh.scn
+++ b/demos/3d/navmesh/navmesh.scn
Binary files differ
diff --git a/demos/3d/platformer/bullet.gd b/demos/3d/platformer/bullet.gd
index 842e6874e9..29219403bd 100644
--- a/demos/3d/platformer/bullet.gd
+++ b/demos/3d/platformer/bullet.gd
@@ -1,14 +1,5 @@
extends RigidBody
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-var disabled=false
-
-func _ready():
- # Initalization here
- pass
-
-
+# Member variables
+var disabled = false
diff --git a/demos/3d/platformer/bullet.scn b/demos/3d/platformer/bullet.scn
index da90dba1a5..54ceb50488 100644
--- a/demos/3d/platformer/bullet.scn
+++ b/demos/3d/platformer/bullet.scn
Binary files differ
diff --git a/demos/3d/platformer/coin.gd b/demos/3d/platformer/coin.gd
index 8bf1a3460d..bd2eea81e2 100644
--- a/demos/3d/platformer/coin.gd
+++ b/demos/3d/platformer/coin.gd
@@ -1,23 +1,11 @@
extends Area
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-
+# Member variables
var taken = false
-func _on_coin_body_enter( body ):
+func _on_coin_body_enter(body):
if (not taken and body extends preload("res://player.gd")):
get_node("anim").play("take")
- taken=true
-
-
-func _ready():
- # Initalization here
- pass
-
-
-
+ taken = true
diff --git a/demos/3d/platformer/coin.scn b/demos/3d/platformer/coin.scn
index a4148b4060..238150788b 100644
--- a/demos/3d/platformer/coin.scn
+++ b/demos/3d/platformer/coin.scn
Binary files differ
diff --git a/demos/3d/platformer/enemy.gd b/demos/3d/platformer/enemy.gd
index 9b2e95a96d..55c79e4858 100644
--- a/demos/3d/platformer/enemy.gd
+++ b/demos/3d/platformer/enemy.gd
@@ -1,14 +1,10 @@
extends RigidBody
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
+# Member variables
const STATE_WALKING = 0
const STATE_DYING = 1
-
var prev_advance = false
var deaccel = 20.0
var accel = 5
@@ -16,80 +12,67 @@ var max_speed = 2
var rot_dir = 4
var rot_speed = 1
-var dying=false
-
-func _integrate_forces(state):
+var dying = false
-
+func _integrate_forces(state):
var delta = state.get_step()
var lv = state.get_linear_velocity()
var g = state.get_total_gravity()
- lv += g * delta #apply gravity
+ lv += g*delta # Apply gravity
var up = -g.normalized()
-
+
if (dying):
state.set_linear_velocity(lv)
return
-
+
for i in range(state.get_contact_count()):
var cc = state.get_contact_collider_object(i)
var dp = state.get_contact_local_normal(i)
-
+
if (cc):
if (cc extends preload("res://bullet.gd") and not cc.disabled):
set_mode(MODE_RIGID)
- dying=true
- #lv=s.get_contact_local_normal(i)*400
- state.set_angular_velocity( -dp.cross(up).normalized() *33.0)
+ dying = true
+ #lv = s.get_contact_local_normal(i)*400
+ state.set_angular_velocity(-dp.cross(up).normalized()*33.0)
get_node("AnimationPlayer").play("impact")
get_node("AnimationPlayer").queue("explode")
set_friction(1)
- cc.disabled=true
+ cc.disabled = true
get_node("sound").play("hit")
return
-
-
-
-
var col_floor = get_node("Armature/ray_floor").is_colliding()
var col_wall = get_node("Armature/ray_wall").is_colliding()
var advance = not col_wall and col_floor
var dir = get_node("Armature").get_transform().basis[2].normalized()
-
-
var deaccel_dir = dir
if (advance):
if (dir.dot(lv) < max_speed):
- lv+=dir * accel * delta
+ lv += dir*accel*delta
deaccel_dir = dir.cross(g).normalized()
else:
if (prev_advance):
- rot_dir = 1 #randf() * 2.0 -1.0
-
- dir = Matrix3(up,rot_dir * rot_speed * delta).xform(dir)
- get_node("Armature").set_transform( Transform().looking_at(-dir,up) )
-
+ rot_dir = 1 # randf()*2.0 - 1.0
+ dir = Matrix3(up, rot_dir*rot_speed*delta).xform(dir)
+ get_node("Armature").set_transform(Transform().looking_at(-dir, up))
+
var dspeed = deaccel_dir.dot(lv)
- dspeed -= deaccel * delta
- if (dspeed<0):
- dspeed=0
+ dspeed -= deaccel*delta
+ if (dspeed < 0):
+ dspeed = 0
lv = lv - deaccel_dir*deaccel_dir.dot(lv) + deaccel_dir*dspeed
-
state.set_linear_velocity(lv)
- prev_advance=advance
+ prev_advance = advance
-func _ready():
- # Initalization here
- pass
func _die():
queue_free()
diff --git a/demos/3d/platformer/enemy.scn b/demos/3d/platformer/enemy.scn
index 083582a85a..dd62692b7f 100644
--- a/demos/3d/platformer/enemy.scn
+++ b/demos/3d/platformer/enemy.scn
Binary files differ
diff --git a/demos/3d/platformer/engine.cfg b/demos/3d/platformer/engine.cfg
index 793ac36364..84a7e8f597 100644
--- a/demos/3d/platformer/engine.cfg
+++ b/demos/3d/platformer/engine.cfg
@@ -1,12 +1,12 @@
[application]
name="Platformer 3D"
-main_scene="res://stage.xml"
+main_scene="res://stage.scn"
icon="res://icon.png"
[display]
-height=450
+height=720
stretch_2d=true
[input]
diff --git a/demos/3d/platformer/follow_camera.gd b/demos/3d/platformer/follow_camera.gd
index 3d18327df0..d0d531b9a5 100644
--- a/demos/3d/platformer/follow_camera.gd
+++ b/demos/3d/platformer/follow_camera.gd
@@ -1,95 +1,80 @@
extends Camera
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-var collision_exception=[]
-export var min_distance=0.5
-export var max_distance=4.0
-export var angle_v_adjust=0.0
-export var autoturn_ray_aperture=25
-export var autoturn_speed=50
+# Member variables
+var collision_exception = []
+export var min_distance = 0.5
+export var max_distance = 4.0
+export var angle_v_adjust = 0.0
+export var autoturn_ray_aperture = 25
+export var autoturn_speed = 50
var max_height = 2.0
var min_height = 0
func _fixed_process(dt):
- var target = get_parent().get_global_transform().origin
+ var target = get_parent().get_global_transform().origin
var pos = get_global_transform().origin
- var up = Vector3(0,1,0)
+ var up = Vector3(0, 1, 0)
var delta = pos - target
- #regular delta follow
-
- #check ranges
+ # Regular delta follow
+ # Check ranges
if (delta.length() < min_distance):
- delta = delta.normalized() * min_distance
+ delta = delta.normalized()*min_distance
elif (delta.length() > max_distance):
- delta = delta.normalized() * max_distance
+ delta = delta.normalized()*max_distance
- #check upper and lower height
- if ( delta.y > max_height):
+ # Check upper and lower height
+ if (delta.y > max_height):
delta.y = max_height
- if ( delta.y < min_height):
+ if (delta.y < min_height):
delta.y = min_height
- #check autoturn
-
- var ds = PhysicsServer.space_get_direct_state( get_world().get_space() )
-
+ # Check autoturn
+ var ds = PhysicsServer.space_get_direct_state(get_world().get_space())
- var col_left = ds.intersect_ray(target,target+Matrix3(up,deg2rad(autoturn_ray_aperture)).xform(delta),collision_exception)
- var col = ds.intersect_ray(target,target+delta,collision_exception)
- var col_right = ds.intersect_ray(target,target+Matrix3(up,deg2rad(-autoturn_ray_aperture)).xform(delta),collision_exception)
+ var col_left = ds.intersect_ray(target, target + Matrix3(up, deg2rad(autoturn_ray_aperture)).xform(delta), collision_exception)
+ var col = ds.intersect_ray(target, target + delta, collision_exception)
+ var col_right = ds.intersect_ray(target, target + Matrix3(up, deg2rad(-autoturn_ray_aperture)).xform(delta), collision_exception)
if (!col.empty()):
- #if main ray was occluded, get camera closer, this is the worst case scenario
+ # If main ray was occluded, get camera closer, this is the worst case scenario
delta = col.position - target
elif (!col_left.empty() and col_right.empty()):
- #if only left ray is occluded, turn the camera around to the right
- delta = Matrix3(up,deg2rad(-dt*autoturn_speed)).xform(delta)
+ # If only left ray is occluded, turn the camera around to the right
+ delta = Matrix3(up, deg2rad(-dt*autoturn_speed)).xform(delta)
elif (col_left.empty() and !col_right.empty()):
- #if only right ray is occluded, turn the camera around to the left
- delta = Matrix3(up,deg2rad(dt*autoturn_speed)).xform(delta)
+ # If only right ray is occluded, turn the camera around to the left
+ delta = Matrix3(up, deg2rad(dt*autoturn_speed)).xform(delta)
else:
- #do nothing otherwise, left and right are occluded but center is not, so do not autoturn
+ # Do nothing otherwise, left and right are occluded but center is not, so do not autoturn
pass
- #apply lookat
- if (delta==Vector3()):
- delta = (pos - target).normalized() * 0.0001
+ # Apply lookat
+ if (delta == Vector3()):
+ delta = (pos - target).normalized()*0.0001
pos = target + delta
- look_at_from_pos(pos,target,up)
+ look_at_from_pos(pos, target, up)
- #turn a little up or down
+ # Turn a little up or down
var t = get_transform()
- t.basis = Matrix3(t.basis[0],deg2rad(angle_v_adjust)) * t.basis
+ t.basis = Matrix3(t.basis[0], deg2rad(angle_v_adjust))*t.basis
set_transform(t)
-
-
-func _ready():
-#find collision exceptions for ray
+func _ready():
+ # Find collision exceptions for ray
var node = self
while(node):
if (node extends RigidBody):
collision_exception.append(node.get_rid())
break
else:
- node=node.get_parent()
- # Initalization here
+ node = node.get_parent()
set_fixed_process(true)
- #this detaches the camera transform from the parent spatial node
+ # This detaches the camera transform from the parent spatial node
set_as_toplevel(true)
-
-
-
-
-
-
diff --git a/demos/3d/platformer/player.gd b/demos/3d/platformer/player.gd
index 76cf2861bf..7471460538 100644
--- a/demos/3d/platformer/player.gd
+++ b/demos/3d/platformer/player.gd
@@ -1,12 +1,7 @@
extends RigidBody
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-#var dir=Vector3()
-
+# Member variables
const ANIM_FLOOR = 0
const ANIM_AIR_UP = 1
const ANIM_AIR_DOWN = 2
@@ -14,21 +9,21 @@ const ANIM_AIR_DOWN = 2
const SHOOT_TIME = 1.5
const SHOOT_SCALE = 2
-const CHAR_SCALE = Vector3(0.3,0.3,0.3)
+const CHAR_SCALE = Vector3(0.3, 0.3, 0.3)
var facing_dir = Vector3(1, 0, 0)
var movement_dir = Vector3()
-var jumping=false
+var jumping = false
-var turn_speed=40
+var turn_speed = 40
var keep_jump_inertia = true
var air_idle_deaccel = false
-var accel=19.0
-var deaccel=14.0
-var sharp_turn_threshhold = 140
+var accel = 19.0
+var deaccel = 14.0
+var sharp_turn_threshold = 140
-var max_speed=3.1
+var max_speed = 3.1
var on_floor = false
var prev_shoot = false
@@ -37,9 +32,9 @@ var last_floor_velocity = Vector3()
var shoot_blend = 0
-func adjust_facing(p_facing, p_target,p_step, p_adjust_rate,current_gn):
- var n = p_target # normal
+func adjust_facing(p_facing, p_target, p_step, p_adjust_rate, current_gn):
+ var n = p_target # Normal
var t = n.cross(current_gn).normalized()
var x = n.dot(p_facing)
@@ -47,47 +42,43 @@ func adjust_facing(p_facing, p_target,p_step, p_adjust_rate,current_gn):
var ang = atan2(y,x)
- if (abs(ang)<0.001): # too small
+ if (abs(ang) < 0.001): # Too small
return p_facing
var s = sign(ang)
- ang = ang * s
- var turn = ang * p_adjust_rate * p_step
+ ang = ang*s
+ var turn = ang*p_adjust_rate*p_step
var a
- if (ang<turn):
- a=ang
+ if (ang < turn):
+ a = ang
else:
- a=turn
- ang = (ang - a) * s
+ a = turn
+ ang = (ang - a)*s
- return ((n * cos(ang)) + (t * sin(ang))) * p_facing.length()
-
-
+ return (n*cos(ang) + t*sin(ang))*p_facing.length()
-func _integrate_forces( state ):
- var lv = state.get_linear_velocity() # linear velocity
+func _integrate_forces(state):
+ var lv = state.get_linear_velocity() # Linear velocity
var g = state.get_total_gravity()
var delta = state.get_step()
# var d = 1.0 - delta*state.get_total_density()
-# if (d<0):
-# d=0
- lv += g * delta #apply gravity
-
+# if (d < 0):
+# d = 0
+ lv += g*delta # Apply gravity
+
var anim = ANIM_FLOOR
-
+
var up = -g.normalized() # (up is against gravity)
- var vv = up.dot(lv) # vertical velocity
- var hv = lv - (up*vv) # horizontal velocity
-
-
-
- var hdir = hv.normalized() # horizontal direction
- var hspeed = hv.length() #horizontal speed
-
+ var vv = up.dot(lv) # Vertical velocity
+ var hv = lv - up*vv # Horizontal velocity
+
+ var hdir = hv.normalized() # Horizontal direction
+ var hspeed = hv.length() # Horizontal speed
+
var floor_velocity
var onfloor = false
-
+
if (state.get_contact_count() == 0):
floor_velocity = last_floor_velocity
else:
@@ -98,104 +89,89 @@ func _integrate_forces( state ):
onfloor = true
floor_velocity = state.get_contact_collider_velocity_at_pos(i)
break
-
-
- var dir = Vector3() #where does the player intend to walk to
+
+ var dir = Vector3() # Where does the player intend to walk to
var cam_xform = get_node("target/camera").get_global_transform()
if (Input.is_action_pressed("move_forward")):
- dir+=-cam_xform.basis[2]
+ dir += -cam_xform.basis[2]
if (Input.is_action_pressed("move_backwards")):
- dir+=cam_xform.basis[2]
+ dir += cam_xform.basis[2]
if (Input.is_action_pressed("move_left")):
- dir+=-cam_xform.basis[0]
+ dir += -cam_xform.basis[0]
if (Input.is_action_pressed("move_right")):
- dir+=cam_xform.basis[0]
-
+ dir += cam_xform.basis[0]
+
var jump_attempt = Input.is_action_pressed("jump")
var shoot_attempt = Input.is_action_pressed("shoot")
-
+
var target_dir = (dir - up*dir.dot(up)).normalized()
if (onfloor):
-
- var sharp_turn = hspeed > 0.1 and rad2deg(acos(target_dir.dot(hdir))) > sharp_turn_threshhold
-
- if (dir.length()>0.1 and !sharp_turn) :
- if (hspeed > 0.001) :
-
+ var sharp_turn = hspeed > 0.1 and rad2deg(acos(target_dir.dot(hdir))) > sharp_turn_threshold
+
+ if (dir.length() > 0.1 and !sharp_turn):
+ if (hspeed > 0.001):
#linear_dir = linear_h_velocity/linear_vel
- #if (linear_vel > brake_velocity_limit and linear_dir.dot(ctarget_dir)<-cos(Math::deg2rad(brake_angular_limit)))
- # brake=true
+ #if (linear_vel > brake_velocity_limit and linear_dir.dot(ctarget_dir) < -cos(Math::deg2rad(brake_angular_limit)))
+ # brake = true
#else
- hdir = adjust_facing(hdir,target_dir,delta,1.0/hspeed*turn_speed,up)
+ hdir = adjust_facing(hdir, target_dir, delta, 1.0/hspeed*turn_speed, up)
facing_dir = hdir
else:
-
hdir = target_dir
- if (hspeed<max_speed):
- hspeed+=accel*delta
-
+ if (hspeed < max_speed):
+ hspeed += accel*delta
else:
- hspeed-=deaccel*delta
- if (hspeed<0):
- hspeed=0
+ hspeed -= deaccel*delta
+ if (hspeed < 0):
+ hspeed = 0
hv = hdir*hspeed
- var mesh_xform = get_node("Armature").get_transform()
- var facing_mesh=-mesh_xform.basis[0].normalized()
+ var mesh_xform = get_node("Armature").get_transform()
+ var facing_mesh = -mesh_xform.basis[0].normalized()
facing_mesh = (facing_mesh - up*facing_mesh.dot(up)).normalized()
- facing_mesh = adjust_facing(facing_mesh,target_dir,delta,1.0/hspeed*turn_speed,up)
- var m3 = Matrix3(-facing_mesh,up,-facing_mesh.cross(up).normalized()).scaled( CHAR_SCALE )
+ facing_mesh = adjust_facing(facing_mesh, target_dir, delta, 1.0/hspeed*turn_speed, up)
+ var m3 = Matrix3(-facing_mesh, up, -facing_mesh.cross(up).normalized()).scaled(CHAR_SCALE)
+
+ get_node("Armature").set_transform(Transform(m3, mesh_xform.origin))
- get_node("Armature").set_transform(Transform(m3,mesh_xform.origin))
-
if (not jumping and jump_attempt):
vv = 7.0
- jumping = true
+ jumping = true
get_node("sfx").play("jump")
else:
-
- if (vv>0):
- anim=ANIM_AIR_UP
+ if (vv > 0):
+ anim = ANIM_AIR_UP
else:
- anim=ANIM_AIR_DOWN
-
+ anim = ANIM_AIR_DOWN
+
var hs
- if (dir.length()>0.1):
-
- hv += target_dir * (accel * 0.2) * delta
+ if (dir.length() > 0.1):
+ hv += target_dir*(accel*0.2)*delta
if (hv.length() > max_speed):
- hv = hv.normalized() * max_speed
-
+ hv = hv.normalized()*max_speed
else:
-
if (air_idle_deaccel):
- hspeed = hspeed - (deaccel * 0.2) * delta
- if (hspeed<0):
- hspeed=0
-
+ hspeed = hspeed - (deaccel*0.2)*delta
+ if (hspeed < 0):
+ hspeed = 0
+
hv = hdir*hspeed
-
-
+
if (jumping and vv < 0):
- jumping=false
-
- lv = hv+up*vv
+ jumping = false
+ lv = hv + up*vv
-
if (onfloor):
-
movement_dir = lv
#lv += floor_velocity
last_floor_velocity = floor_velocity
else:
-
- if (on_floor) :
-
+ if (on_floor):
#if (keep_jump_inertia):
# lv += last_floor_velocity
pass
@@ -204,40 +180,32 @@ func _integrate_forces( state ):
movement_dir = lv
on_floor = onfloor
-
+
state.set_linear_velocity(lv)
- if (shoot_blend>0):
- shoot_blend -= delta * SHOOT_SCALE
- if (shoot_blend<0):
- shoot_blend=0
+ if (shoot_blend > 0):
+ shoot_blend -= delta*SHOOT_SCALE
+ if (shoot_blend < 0):
+ shoot_blend = 0
if (shoot_attempt and not prev_shoot):
- shoot_blend = SHOOT_TIME
+ shoot_blend = SHOOT_TIME
var bullet = preload("res://bullet.scn").instance()
- bullet.set_transform( get_node("Armature/bullet").get_global_transform().orthonormalized() )
- get_parent().add_child( bullet )
- bullet.set_linear_velocity( get_node("Armature/bullet").get_global_transform().basis[2].normalized() * 20 )
- PS.body_add_collision_exception( bullet.get_rid(), get_rid() ) #add it to bullet
+ bullet.set_transform(get_node("Armature/bullet").get_global_transform().orthonormalized())
+ get_parent().add_child(bullet)
+ bullet.set_linear_velocity(get_node("Armature/bullet").get_global_transform().basis[2].normalized()*20)
+ PS.body_add_collision_exception(bullet.get_rid(), get_rid()) # Add it to bullet
get_node("sfx").play("shoot")
-
+
prev_shoot = shoot_attempt
if (onfloor):
- get_node("AnimationTreePlayer").blend2_node_set_amount("walk",hspeed / max_speed)
-
- get_node("AnimationTreePlayer").transition_node_set_current("state",anim)
- get_node("AnimationTreePlayer").blend2_node_set_amount("gun",min(shoot_blend,1.0))
-# state.set_angular_velocity(Vector3())
-
+ get_node("AnimationTreePlayer").blend2_node_set_amount("walk", hspeed/max_speed)
+ get_node("AnimationTreePlayer").transition_node_set_current("state", anim)
+ get_node("AnimationTreePlayer").blend2_node_set_amount("gun", min(shoot_blend, 1.0))
+# state.set_angular_velocity(Vector3())
func _ready():
-
-
- # Initalization here
get_node("AnimationTreePlayer").set_active(true)
- pass
-
-
diff --git a/demos/3d/platformer/player.scn b/demos/3d/platformer/player.scn
new file mode 100644
index 0000000000..3b24da94ec
--- /dev/null
+++ b/demos/3d/platformer/player.scn
Binary files differ
diff --git a/demos/3d/platformer/player.xml b/demos/3d/platformer/player.xml
deleted file mode 100644
index c008d21675..0000000000
--- a/demos/3d/platformer/player.xml
+++ /dev/null
@@ -1,1762 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="23" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
- <ext_resource path="res://osb_left.png" type="Texture"></ext_resource>
- <ext_resource path="res://osb_up.png" type="Texture"></ext_resource>
- <ext_resource path="res://player.gd" type="Script"></ext_resource>
- <ext_resource path="res://sound_jump.wav" type="Sample"></ext_resource>
- <ext_resource path="res://follow_camera.gd" type="Script"></ext_resource>
- <ext_resource path="res://osb_down.png" type="Texture"></ext_resource>
- <ext_resource path="res://osb_right.png" type="Texture"></ext_resource>
- <ext_resource path="res://sound_shoot.wav" type="Sample"></ext_resource>
- <resource type="CapsuleShape" path="local://1">
- <real name="radius"> 0.4 </real>
- <real name="height"> 0.4 </real>
-
- </resource>
- <resource type="RayShape" path="local://2">
- <real name="length"> 1 </real>
-
- </resource>
- <resource type="FixedMaterial" path="local://3">
- <bool name="flags/visible"> True </bool>
- <bool name="flags/double_sided"> True </bool>
- <bool name="flags/invert_faces"> False </bool>
- <bool name="flags/unshaded"> False </bool>
- <bool name="flags/on_top"> False </bool>
- <bool name="flags/wireframe"> False </bool>
- <bool name="flags/billboard_sw"> False </bool>
- <bool name="hints/decal"> False </bool>
- <bool name="hints/opaque_pre_zpass"> False </bool>
- <bool name="hints/no_shadow"> False </bool>
- <bool name="hints/no_depth_draw"> False </bool>
- <int name="params/blend_mode"> 0 </int>
- <real name="params/line_width"> 0 </real>
- <bool name="fixed_flags/use_alpha"> False </bool>
- <bool name="fixed_flags/use_color_array"> False </bool>
- <bool name="fixed_flags/use_point_size"> False </bool>
- <color name="params/diffuse"> 0.702475, 0.707942, 0.727015, 1 </color>
- <color name="params/specular"> 0.351321, 0.35466, 0.377071, 1 </color>
- <color name="params/emission"> 0, 0, 0, 1 </color>
- <real name="params/specular_exp"> 34.20256 </real>
- <int name="params/detail_blend"> 0 </int>
- <real name="params/detail_mix"> 1 </real>
- <int name="params/normal_depth"> 1 </int>
- <real name="params/shade_param"> 0.5 </real>
- <int name="params/glow"> 0 </int>
- <real name="params/point_size"> 1 </real>
- <transform name="uv_xform"> 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 </transform>
- <resource name="textures/diffuse"></resource> <int name="textures/diffuse_tc"> 0 </int>
- <resource name="textures/detail"></resource> <int name="textures/detail_tc"> 0 </int>
- <resource name="textures/specular"></resource> <int name="textures/specular_tc"> 0 </int>
- <resource name="textures/emission"></resource> <int name="textures/emission_tc"> 0 </int>
- <resource name="textures/specular_exp"></resource> <int name="textures/specular_exp_tc"> 0 </int>
- <resource name="textures/glow"></resource> <int name="textures/glow_tc"> 0 </int>
- <resource name="textures/normal"></resource> <int name="textures/normal_tc"> 0 </int>
- <resource name="textures/shade_param"></resource> <int name="textures/shade_param_tc"> 0 </int>
-
- </resource>
- <resource type="FixedMaterial" path="local://4">
- <bool name="flags/visible"> True </bool>
- <bool name="flags/double_sided"> True </bool>
- <bool name="flags/invert_faces"> False </bool>
- <bool name="flags/unshaded"> False </bool>
- <bool name="flags/on_top"> False </bool>
- <bool name="flags/wireframe"> False </bool>
- <bool name="flags/billboard_sw"> False </bool>
- <bool name="hints/decal"> False </bool>
- <bool name="hints/opaque_pre_zpass"> False </bool>
- <bool name="hints/no_shadow"> False </bool>
- <bool name="hints/no_depth_draw"> False </bool>
- <int name="params/blend_mode"> 0 </int>
- <real name="params/line_width"> 0 </real>
- <bool name="fixed_flags/use_alpha"> False </bool>
- <bool name="fixed_flags/use_color_array"> False </bool>
- <bool name="fixed_flags/use_point_size"> False </bool>
- <color name="params/diffuse"> 0.0616188, 0.431354, 0.64, 1 </color>
- <color name="params/specular"> 0.5, 0.5, 0.5, 1 </color>
- <color name="params/emission"> 0.0196078, 0.235675, 0.675973, 1 </color>
- <real name="params/specular_exp"> 50 </real>
- <int name="params/detail_blend"> 0 </int>
- <real name="params/detail_mix"> 1 </real>
- <int name="params/normal_depth"> 1 </int>
- <real name="params/shade_param"> 0.5 </real>
- <real name="params/glow"> 0.4 </real>
- <real name="params/point_size"> 1 </real>
- <transform name="uv_xform"> 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 </transform>
- <resource name="textures/diffuse"></resource> <int name="textures/diffuse_tc"> 0 </int>
- <resource name="textures/detail"></resource> <int name="textures/detail_tc"> 0 </int>
- <resource name="textures/specular"></resource> <int name="textures/specular_tc"> 0 </int>
- <resource name="textures/emission"></resource> <int name="textures/emission_tc"> 0 </int>
- <resource name="textures/specular_exp"></resource> <int name="textures/specular_exp_tc"> 0 </int>
- <resource name="textures/glow"></resource> <int name="textures/glow_tc"> 0 </int>
- <resource name="textures/normal"></resource> <int name="textures/normal_tc"> 0 </int>
- <resource name="textures/shade_param"></resource> <int name="textures/shade_param_tc"> 0 </int>
-
- </resource>
- <resource type="Mesh" path="local://5">
- <string name="resource/name"> "Cube.002" </string>
- <dictionary name="surfaces/0" shared="false">
- <string> "alphasort" </string>
- <bool> False </bool>
- <string> "material" </string>
- <resource resource_type="Material" path="local://3"> </resource>
- <string> "morph_arrays" </string>
- <array len="0" shared="false">
- </array>
- <string> "primitive" </string>
- <int> 4 </int>
- <string> "arrays" </string>
- <array len="9" shared="false">
- <vector3_array len="679"> 0.2607, 6.45948, 0.980779, 0.852531, 6.83043, 0.609826, 0.852531, 6.93043, 0.609826, 0.2607, 6.55948, 0.980779, 0, 7.06621, 0.103096, 0.955654, 7.06621, 0.103096, 0.852531, 6.93043, -0.403642, 0, 6.93043, -0.403642, 0, 6.45948, -0.774594, 0, 6.55948, -0.774594, 0.2607, 6.55948, -0.774594, 0.2607, 6.45948, -0.774594, 0, 6.45948, 0.980779, 0, 6.55948, 0.980779, 0.852531, 6.83043, -0.403642, 0.955654, 6.96621, 0.103096, 0, 6.93043, 0.609826, 1.70474, 3.5573, -0.353999, 1.71449, 3.62366, -0.198996, 1.77916, 3.62988, -0.16353, 1.76754, 3.55083, -0.34818, 1.71511, 3.58298, -0.0127468, 1.70308, 3.74367, 0.0692484, 1.80667, 3.81951, -0.174607, 1.52592, 3.24162, -0.0839551, 1.50573, 3.18374, -0.268539, 1.36446, 3.09798, -0.344433, 1.38154, 3.17921, -0.0161709, 2.44682, 3.07552, 0.376618, 2.28993, 2.80163, 0.457827, 2.52299, 2.59433, 0.553631, 2.69474, 2.85281, 0.479075, 2.53359, 3.02984, -0.15501, 2.55604, 3.1449, 0.136694, 2.79433, 2.92572, 0.24463, 2.78064, 2.80757, -0.0472709, 2.39441, 2.7167, -0.284614, 2.64285, 2.49755, -0.175588, 2.70938, 2.79639, 0.46437, 2.79808, 2.86134, 0.255559, 2.78589, 2.75611, -0.00442547, 2.66316, 2.47998, -0.118712, 2.38561, 2.31013, 0.396952, 2.36919, 2.23204, 0.0813577, 2.41942, 2.2435, 0.110139, 2.43405, 2.31306, 0.391226, 2.55641, 2.56618, 0.530774, 2.47334, 2.30784, -0.0772789, 2.51219, 2.31101, -0.0311523, 2.38859, 2.74151, 0.0599679, 2.38864, 2.7416, 0.0600288, 2.12663, 2.44425, -0.0282163, 2.22321, 2.52508, -0.185319, 2.13459, 2.5274, 0.293671, 0.173831, 0.925795, -0.251959, 0.323615, 0.972996, -0.416293, 0.50934, 0.00104547, -0.453384, 0.175987, 0.00104547, -0.331706, 0.916812, 0.888823, 0.214332, 0.549239, 0.836962, 0.37006, 0.552121, 0.665123, 0.401021, 0.944465, 0.443271, 0.182901, 0.631626, 1.83578, -0.105239, 0.721202, 1.70631, 0.188726, 0.913722, 0.95431, -0.169976, 0.478232, 1.53675, 0.317272, 0.454208, 1.69171, -0.268756, 0.63543, 0.987243, -0.370343, 0.262225, 1.39447, 0.162709, 0.170564, 0.859014, 0.160279, 0.255551, 1.52426, -0.294896, 0.126803, 1.32882, -0.0395796, 0.0660405, 0.880691, -0.102965, 0.19102, 1.40531, -0.162224, 0.256767, 1.56023, -0.0958005, 0.300707, 1.62315, -0.168503, 0.292542, 1.58081, -0.213789, 0.245079, 1.4957, -0.123593, 0.426543, 1.69115, -0.196413, 0.547313, 1.79071, -0.0844079, 0.586182, 1.83924, -0.0975873, 0.434509, 1.71208, -0.231916, 0.212253, 1.44274, -0.0415312, 0.220281, 1.46968, -0.143048, 0.175617, 1.41154, -0.0437374, 0.543306, 0.573346, 0.523815, 0.207486, 0.384965, 0.351051, 0.269976, 0.320526, 0.743389, 0.53325, 0.468211, 0.783185, 0.792721, 0.321493, 0.73458, 0.514523, 0.271138, 0.956088, 0.631719, 0.163855, 0.92639, 0.386424, 0.163401, 0.930524, 0.486595, 0.00104547, 1.08874, 0.326299, 0.00104547, 0.904533, 0.668445, 1.73174, 0.152757, 0.462058, 1.58268, 0.259184, 0.290415, 1.46398, 0.121989, 1.57608, 3.45117, -0.0476083, 1.50191, 3.29774, -0.132197, 1.61428, 3.4244, 0.016813, 1.66072, 3.58429, -0.072422, 1.62434, 3.38222, -0.419987, 1.67177, 3.34226, -0.426789, 1.48496, 3.24915, -0.287145, 1.54119, 3.29007, -0.372791, 1.57272, 3.23249, -0.370566, 1.79243, 3.69662, -0.478226, 1.47279, 3.17682, -0.509438, 1.6491, 3.37415, -0.611694, 1.52444, 3.47482, 0.146797, 1.97806, 2.60303, -0.0912834, 1.98619, 2.68696, 0.233771, 2.07568, 2.68462, -0.249978, 2.24859, 2.87814, -0.35026, 2.14291, 2.96404, 0.3995, 2.30152, 3.24052, 0.317542, 2.38915, 3.19439, -0.219368, 2.41174, 3.31063, 0.0752657, 0.0964089, 0.00104547, -0.196812, 0.154027, 0.441809, 0.19622, 0.835003, 0.00104547, -0.205403, 0.55748, 1.72198, 0.0964474, 0.425773, 1.62639, 0.166544, 0.447702, 1.58483, 0.201877, 0.611101, 1.70343, 0.114914, 0.506064, 1.79234, -0.0642154, 0.311982, 1.54621, 0.0812291, 0.30653, 1.48536, 0.0960338, 0.408718, 1.71209, -0.154497, 0.23599, 1.51185, -0.0296548, 0.272186, 1.57784, -0.251696, 0.0508581, 0.00104547, 0.0402964, 0.14499, 0.00104547, 0.619324, 0.916171, 0.00104547, 0.0302318, 0.874277, 0.386199, 0.339815, 0.82337, 0.00104547, 0.611434, 0.644625, 0.00104547, 0.90083, 0.19633, 0.00104547, -0.176104, 0.736495, 0.00104547, -0.182387, 0.85902, 0.00104547, 0.0313234, 0.108829, 0.00104547, 0.040049, 1.86783, 5.49219, -0.536097, 1.99626, 5.62831, -0.300326, 1.99626, 5.45781, -0.129823, 1.86783, 5.22204, -0.265945, 1.86783, 6.50041, -0.265945, 1.99626, 6.26464, -0.129823, 1.99626, 6.09414, -0.300326, 1.86783, 6.23026, -0.536097, 1.99626, 5.86123, -0.362734, 1.86783, 5.86123, -0.63498, 1.7, 6.62333, -0.336911, 1.7, 6.30123, -0.659013, 1.7, 5.42123, -0.659013, 1.7, 5.09912, -0.336911, 1.7, 5.86123, -0.776911, 1.6, 6.62333, 0.543096, 1.6, 6.30123, 0.865198, 1.7, 6.30123, 0.865198, 1.7, 6.62333, 0.543096, 1.6, 5.86123, 0.983096, 1.7, 5.86123, 0.983096, 1.6, 5.42123, 0.865198, 1.7, 5.42123, 0.865198, 1.6, 5.42123, -0.659013, 1.6, 5.09912, -0.336911, 1.6, 5.09913, 0.543096, 1.7, 5.09913, 0.543096, 1.6, 5.86123, -0.776911, 1.6, 4.98123, 0.103096, 1.7, 4.98123, 0.103096, 1.6, 6.30123, -0.659013, 1.6, 6.62333, -0.336911, 1.6, 6.74123, 0.103096, 1.7, 6.74123, 0.103096, 1.86783, 5.86123, 0.841165, 1.86783, 6.23026, 0.742282, 1.86783, 5.49219, 0.742282, 1.86783, 5.22204, 0.47213, 1.86783, 5.12316, 0.103096, 1.86783, 6.50041, 0.47213, 1.86783, 6.5993, 0.103096, 1.99626, 5.3954, 0.103096, 1.99626, 5.45781, 0.336007, 1.99626, 5.62832, 0.50651, 1.99626, 5.86123, 0.568919, 1.99626, 6.09414, 0.50651, 1.99626, 6.26464, 0.336007, 1.99626, 6.32705, 0.103096, 0.102832, 2.48009, 0.176006, 5.00021e-06, 2.4738, 0.177211, 5.00021e-06, 2.42055, 0.19141, 0.0988953, 2.42787, 0.190009, 0.149215, 2.70638, -0.125392, 0.228589, 2.63923, -0.0490058, 0.245228, 2.61305, -0.0718189, 0.152867, 2.69118, -0.160703, 5.00021e-06, 2.7271, -0.192857, 0.200279, 2.72863, -0.178996, 5.00021e-06, 2.77269, -0.218433, 0.254515, 2.5228, 0.0532499, 0.177509, 2.46933, 0.131427, 0.230502, 2.45653, 0.179303, 0.32495, 2.52211, 0.0834183, 0.31356, 2.6328, -0.0699792, 5.00021e-06, 2.38434, 0.263172, 0.134082, 2.39331, 0.261453, 4.89224e-06, 2.18251, 0.500372, 0.225093, 2.1995, 0.49518, 0.391925, 2.2292, 0.34273, 0.272307, 2.12215, 0.166987, 0.273286, 2.15284, 0.145033, 0.377566, 2.23301, 0.230347, 0.509219, 2.60277, -0.0602789, 0.306467, 2.75371, -0.22827, 0.384471, 2.30721, 0.355435, 5.53206e-06, 2.7678, -0.324424, 0.340915, 2.69228, -0.257391, 0.141881, 2.21642, -0.246023, 5.00021e-06, 2.24749, -0.273838, 0.226149, 2.1204, 0.482878, 5.00021e-06, 2.10499, 0.484715, 5.00021e-06, 1.97359, 0.0658354, 0.0951926, 1.97992, 0.0646229, 0.536694, 2.41886, 0.193185, 0.163197, 2.02451, 0.00668271, 5.00021e-06, 2.80311, -0.262553, 0.221777, 2.14883, -0.169134, 5.0058e-06, 2.08031, -0.179583, 4.99835e-06, 2.12243, -0.227502, 5.00021e-06, 1.97109, -0.0331461, 4.99835e-06, 1.97504, -0.0339018, 0.229811, 2.07077, -0.0609438, 5.0058e-06, 2.03165, -0.112157, 4.99835e-06, 2.00283, -0.0700111, 5.00021e-06, 2.14179, -0.244837, 0.549486, 2.33903, 0.185763, 0.532141, 2.52821, -0.0726373, 0.367385, 2.32682, -0.123862, 0.198102, 4.44663, -0.00271145, 0.535945, 4.16951, 0.521097, 0.681184, 4.27477, 0.307467, 0.0960235, 4.4178, 0.0939296, 0, 4.41627, 0.145479, 0, 4.10504, 0.75232, 0.295152, 4.11437, 0.707528, 0, 4.62654, -0.650476, 0.75197, 4.49872, -0.484507, 0.568386, 3.97815, -0.416848, 0, 4.0743, -0.542347, 0.453404, 3.62952, 1.15385, 0, 3.62251, 1.22471, 0, 3.3304, 0.897974, 0.354866, 3.3434, 0.864531, 0.713601, 4.46674, -0.124363, 1.03995, 4.04518, 0.442157, 1.12602, 4.3213, -0.0494407, 0, 4.73174, -0.547059, 0.464921, 4.64317, -0.424668, 0.716219, 4.58287, -0.480226, 0, 4.71901, -0.593658, 0.850048, 3.71295, 0.879328, 0.649196, 3.42772, 0.674737, 0.84841, 3.80937, 0.873472, 0.451539, 3.72707, 1.15037, 0.155937, 3.05577, 0.331006, 0.258719, 3.09481, 0.245674, 0.822291, 3.77674, 0.0641416, 0.359401, 3.14451, 0.132252, 0.226502, 3.30884, -0.183514, 0, 3.34718, -0.233548, 0, 3.04671, 0.334585, 1.1403, 4.19005, 0.0860849, 1.11025, 4.20631, -0.0820755, 0, 3.71833, 1.2227, 1.07207, 4.04817, 0.195228, 0.177538, 3.25078, -0.147598, 0, 3.28068, -0.186631, 0.249187, 2.13753, -0.031997, 0.20137, 2.11848, 0.0341487, 0.497933, 2.32861, 0.160251, 0.252884, 2.22978, -0.1047, 0.438171, 2.39896, -0.000411894, 0.941862, 3.86072, 0.194563, 0.997836, 4.10049, -0.213272, 0.87372, 3.89175, -0.186777, 0.347259, 3.23006, -0.0503454, 0.821813, 3.80214, -0.0657451, 0.908494, 3.91354, 0.153681, 1.01577, 4.06798, 0.154229, 1.07199, 4.18489, 0.0643051, 1.04723, 4.19828, -0.0742428, 2.0359, 6.20719, -0.0966551, 2.0359, 6.06097, -0.242878, 2.0359, 5.66148, -0.242878, 2.0359, 5.51526, -0.0966551, 2.0359, 5.86123, -0.296399, 2.0359, 5.86123, 0.502584, 2.0359, 6.06097, 0.449063, 2.0359, 5.66148, 0.449063, 2.0359, 5.51526, 0.30284, 2.0359, 5.46174, 0.103096, 2.0359, 6.20719, 0.30284, 2.0359, 6.26072, 0.103096, 0, 5.86123, 1.1031, 0, 5.47658, 1.00003, 0.329213, 5.47658, 1.00003, 0, 5.20179, 0.809688, 0, 4.9952, 0.603096, 0.329213, 5.20344, 0.811334, 1.15486, 6.36123, 0.969121, 1.2072, 6.11123, 1.03611, 1.39648, 6.36123, 0.969121, 0, 5.86123, -0.896911, 1.39648, 5.86123, -0.896911, 1.39648, 5.36123, -0.762936, 0, 5.36123, -0.762936, 1.39648, 4.9952, -0.396911, 0, 4.9952, -0.396911, 0.329213, 5.36123, 0.969121, 0.257147, 5.40641, 0.875976, 0.257146, 5.2834, 0.752961, 0, 5.49634, 0.900073, 0.257147, 5.49634, 0.900073, 0, 5.28211, 0.751677, 0.685695, 5.86123, 1.1031, 0.633352, 6.11123, 1.03611, 1.39648, 5.36123, 0.969121, 1.39648, 5.86123, 1.1031, 1.15486, 5.86123, 1.1031, 1.39648, 4.9952, 0.603096, 0.23657, 2.56168, 0.0584772, 0.170392, 2.51572, 0.125662, 5.00021e-06, 2.73725, -0.153025, 0.350345, 2.31871, -0.0906937, 0, 4.66231, -0.410127, 0.153299, 4.61636, -0.336561, 0.252264, 4.53307, -0.191655, 0.271744, 3.18932, -0.0437093, 0.122488, 3.05335, 0.253795, 0.202672, 3.0838, 0.187225, 0.281216, 3.12258, 0.0987407, 0, 3.04628, 0.256587, 0.954611, 4.1111, -0.182336, 0.85235, 3.93911, -0.160509, 0.809584, 3.86528, -0.0607897, 0.809978, 3.84435, 0.0462258, 0, 4.97587, -0.315884, 1.39648, 4.86123, 0.103096, 0.18642, 4.95573, -0.248219, 0.269727, 4.92174, -0.116503, 0.212301, 4.88556, 0.0356146, 0, 4.86123, 0.103096, 0.942888, 6.86123, 0.103096, 1.39648, 6.86123, 0.103096, 1.39648, 6.72725, -0.396911, 0.841135, 6.72725, -0.396911, 1.39648, 6.36123, -0.762936, 0.257165, 6.36123, -0.762936, 0.841135, 6.72725, 0.603096, 1.39648, 6.72725, 0.603096, 0, 6.36123, -0.762936, 0.257165, 6.36123, 0.969121, 0.685695, 6.36123, 0.969121, 0, 6.36123, 0.969121, -0.2607, 6.45948, 0.980779, -0.2607, 6.55948, 0.980779, -0.852531, 6.93043, 0.609826, -0.852531, 6.83043, 0.609826, -0.852531, 6.93043, -0.403642, -0.955654, 7.06621, 0.103096, -0.2607, 6.45948, -0.774594, -0.2607, 6.55948, -0.774594, -0.852531, 6.83043, -0.403642, -0.955654, 6.96621, 0.103096, -1.70474, 3.5573, -0.353999, -1.76754, 3.55083, -0.34818, -1.77916, 3.62988, -0.16353, -1.71449, 3.62366, -0.198996, -1.80667, 3.81951, -0.174607, -1.70308, 3.74367, 0.0692484, -1.71511, 3.58298, -0.0127468, -1.52592, 3.24162, -0.0839551, -1.38154, 3.17921, -0.0161709, -1.36446, 3.09798, -0.344433, -1.50573, 3.18374, -0.268539, -2.44682, 3.07552, 0.376618, -2.69474, 2.85281, 0.479075, -2.52299, 2.59433, 0.553631, -2.28993, 2.80163, 0.457827, -2.53359, 3.02984, -0.15501, -2.78064, 2.80757, -0.0472709, -2.79433, 2.92572, 0.24463, -2.55604, 3.1449, 0.136694, -2.39441, 2.7167, -0.284614, -2.64285, 2.49755, -0.175588, -2.79808, 2.86134, 0.255559, -2.70938, 2.79639, 0.46437, -2.66316, 2.47998, -0.118712, -2.78589, 2.75611, -0.00442547, -2.38561, 2.31013, 0.396952, -2.43405, 2.31306, 0.391226, -2.41942, 2.2435, 0.110139, -2.36919, 2.23204, 0.0813577, -2.55641, 2.56618, 0.530774, -2.51219, 2.31101, -0.0311523, -2.47334, 2.30784, -0.0772789, -2.38859, 2.74151, 0.0599679, -2.38864, 2.7416, 0.0600288, -2.12663, 2.44425, -0.0282163, -2.22321, 2.52508, -0.185319, -2.13459, 2.5274, 0.293671, -0.173831, 0.925795, -0.251959, -0.175987, 0.00104547, -0.331706, -0.50934, 0.00104547, -0.453384, -0.323615, 0.972996, -0.416293, -0.916812, 0.888823, 0.214332, -0.944465, 0.443271, 0.182901, -0.552121, 0.665123, 0.401021, -0.549239, 0.836962, 0.37006, -0.631626, 1.83578, -0.105239, -0.913722, 0.95431, -0.169976, -0.721202, 1.70631, 0.188726, -0.478232, 1.53675, 0.317272, -0.454208, 1.69171, -0.268756, -0.63543, 0.987243, -0.370343, -0.170564, 0.859014, 0.160279, -0.262225, 1.39447, 0.162709, -0.255551, 1.52426, -0.294896, -0.0660405, 0.880691, -0.102965, -0.126803, 1.32882, -0.0395796, -0.19102, 1.40531, -0.162224, -0.256767, 1.56023, -0.0958005, -0.245079, 1.4957, -0.123593, -0.292542, 1.58081, -0.213789, -0.300707, 1.62315, -0.168503, -0.426543, 1.69115, -0.196413, -0.434509, 1.71208, -0.231916, -0.586182, 1.83924, -0.0975873, -0.547313, 1.79071, -0.0844079, -0.212253, 1.44274, -0.0415312, -0.175617, 1.41154, -0.0437374, -0.220281, 1.46968, -0.143048, -0.543306, 0.573346, 0.523815, -0.53325, 0.468211, 0.783185, -0.269976, 0.320526, 0.743389, -0.207486, 0.384965, 0.351051, -0.792721, 0.321493, 0.73458, -0.631719, 0.163855, 0.92639, -0.514523, 0.271138, 0.956088, -0.386424, 0.163401, 0.930524, -0.486595, 0.00104547, 1.08874, -0.326299, 0.00104547, 0.904533, -0.462058, 1.58268, 0.259184, -0.668445, 1.73174, 0.152757, -0.290415, 1.46398, 0.121989, -1.57608, 3.45117, -0.0476083, -1.61428, 3.4244, 0.016813, -1.50191, 3.29774, -0.132197, -1.66072, 3.58429, -0.072422, -1.62434, 3.38222, -0.419987, -1.67177, 3.34226, -0.426789, -1.48496, 3.24915, -0.287145, -1.57272, 3.23249, -0.370566, -1.54119, 3.29007, -0.372791, -1.79243, 3.69662, -0.478226, -1.47279, 3.17682, -0.509438, -1.6491, 3.37415, -0.611694, -1.52444, 3.47482, 0.146797, -1.98619, 2.68696, 0.233771, -1.97806, 2.60303, -0.0912834, -2.07568, 2.68462, -0.249978, -2.24859, 2.87814, -0.35026, -2.14291, 2.96404, 0.3995, -2.30152, 3.24052, 0.317542, -2.38915, 3.19439, -0.219368, -2.41174, 3.31063, 0.0752657, -0.0964089, 0.00104547, -0.196812, -0.154027, 0.441809, 0.19622, -0.835003, 0.00104547, -0.205403, -0.55748, 1.72198, 0.0964474, -0.611101, 1.70343, 0.114914, -0.447702, 1.58483, 0.201877, -0.425773, 1.62639, 0.166544, -0.506064, 1.79234, -0.0642154, -0.30653, 1.48536, 0.0960338, -0.311982, 1.54621, 0.0812291, -0.408718, 1.71209, -0.154497, -0.23599, 1.51185, -0.0296548, -0.272186, 1.57784, -0.251696, -0.14499, 0.00104547, 0.619324, -0.0508581, 0.00104547, 0.0402964, -0.916171, 0.00104547, 0.0302318, -0.82337, 0.00104547, 0.611434, -0.874277, 0.386199, 0.339815, -0.644625, 0.00104547, 0.90083, -0.19633, 0.00104547, -0.176104, -0.108829, 0.00104547, 0.040049, -0.85902, 0.00104547, 0.0313234, -0.736495, 0.00104547, -0.182387, -1.86783, 5.49219, -0.536097, -1.86783, 5.22204, -0.265945, -1.99626, 5.45781, -0.129823, -1.99626, 5.62831, -0.300326, -1.86783, 6.50041, -0.265945, -1.86783, 6.23026, -0.536097, -1.99626, 6.09414, -0.300326, -1.99626, 6.26464, -0.129823, -1.86783, 5.86123, -0.63498, -1.99626, 5.86123, -0.362734, -1.7, 6.62333, -0.336911, -1.7, 6.30123, -0.659013, -1.7, 5.42123, -0.659013, -1.7, 5.09912, -0.336911, -1.7, 5.86123, -0.776911, -1.6, 6.62333, 0.543096, -1.7, 6.62333, 0.543096, -1.7, 6.30123, 0.865198, -1.6, 6.30123, 0.865198, -1.7, 5.86123, 0.983096, -1.6, 5.86123, 0.983096, -1.7, 5.42123, 0.865198, -1.6, 5.42123, 0.865198, -1.6, 5.42123, -0.659013, -1.6, 5.09912, -0.336911, -1.7, 5.09913, 0.543096, -1.6, 5.09913, 0.543096, -1.6, 5.86123, -0.776911, -1.7, 4.98123, 0.103096, -1.6, 4.98123, 0.103096, -1.6, 6.30123, -0.659013, -1.6, 6.62333, -0.336911, -1.6, 6.74123, 0.103096, -1.7, 6.74123, 0.103096, -1.86783, 6.23026, 0.742282, -1.86783, 5.86123, 0.841165, -1.86783, 5.49219, 0.742282, -1.86783, 5.22204, 0.47213, -1.86783, 5.12316, 0.103096, -1.86783, 6.5993, 0.103096, -1.86783, 6.50041, 0.47213, -1.99626, 5.45781, 0.336007, -1.99626, 5.3954, 0.103096, -1.99626, 5.86123, 0.568919, -1.99626, 5.62832, 0.50651, -1.99626, 6.09414, 0.50651, -1.99626, 6.26464, 0.336007, -1.99626, 6.32705, 0.103096, -0.102832, 2.48009, 0.176006, -0.0988953, 2.42787, 0.190009, -0.149215, 2.70638, -0.125392, -0.152867, 2.69118, -0.160703, -0.245228, 2.61305, -0.0718189, -0.228589, 2.63923, -0.0490058, -0.200279, 2.72863, -0.178996, -0.254515, 2.5228, 0.0532499, -0.32495, 2.52211, 0.0834183, -0.230502, 2.45653, 0.179303, -0.177509, 2.46933, 0.131427, -0.31356, 2.6328, -0.0699792, -0.134082, 2.39331, 0.261453, -0.225093, 2.1995, 0.49518, -0.391925, 2.2292, 0.34273, -0.377566, 2.23301, 0.230347, -0.273286, 2.15284, 0.145033, -0.272307, 2.12215, 0.166987, -0.306467, 2.75371, -0.22827, -0.509219, 2.60277, -0.0602789, -0.384471, 2.30721, 0.355435, -0.141881, 2.21642, -0.246023, -0.340915, 2.69228, -0.257391, -0.226149, 2.1204, 0.482878, -0.0951926, 1.97992, 0.0646229, -0.536694, 2.41886, 0.193185, -0.163197, 2.02451, 0.00668271, -0.221777, 2.14883, -0.169134, -0.229811, 2.07077, -0.0609438, -0.549486, 2.33903, 0.185763, -0.532141, 2.52821, -0.0726373, -0.367385, 2.32682, -0.123862, -0.198102, 4.44663, -0.00271145, -0.681184, 4.27477, 0.307467, -0.535945, 4.16951, 0.521097, -0.0960235, 4.4178, 0.0939296, -0.295152, 4.11437, 0.707528, -0.568386, 3.97815, -0.416848, -0.75197, 4.49872, -0.484507, -0.453404, 3.62952, 1.15385, -0.354866, 3.3434, 0.864531, -0.713601, 4.46674, -0.124363, -1.12602, 4.3213, -0.0494407, -1.03995, 4.04518, 0.442157, -0.716219, 4.58287, -0.480226, -0.464921, 4.64317, -0.424668, -0.850048, 3.71295, 0.879328, -0.649196, 3.42772, 0.674737, -0.84841, 3.80937, 0.873472, -0.451539, 3.72707, 1.15037, -0.258719, 3.09481, 0.245674, -0.155937, 3.05577, 0.331006, -0.822291, 3.77674, 0.0641416, -0.359401, 3.14451, 0.132252, -0.226502, 3.30884, -0.183514, -1.1403, 4.19005, 0.0860849, -1.11025, 4.20631, -0.0820755, -1.07207, 4.04817, 0.195228, -0.177538, 3.25078, -0.147598, -0.20137, 2.11848, 0.0341487, -0.249187, 2.13753, -0.031997, -0.497933, 2.32861, 0.160251, -0.252884, 2.22978, -0.1047, -0.438171, 2.39896, -0.000411894, -0.941862, 3.86072, 0.194563, -0.997836, 4.10049, -0.213272, -0.87372, 3.89175, -0.186777, -0.347259, 3.23006, -0.0503454, -0.821813, 3.80214, -0.0657451, -1.01577, 4.06798, 0.154229, -0.908494, 3.91354, 0.153681, -1.04723, 4.19828, -0.0742428, -1.07199, 4.18489, 0.0643051, -2.0359, 6.06097, -0.242878, -2.0359, 6.20719, -0.0966551, -2.0359, 5.51526, -0.0966551, -2.0359, 5.66148, -0.242878, -2.0359, 5.86123, -0.296399, -2.0359, 6.06097, 0.449063, -2.0359, 5.86123, 0.502584, -2.0359, 5.66148, 0.449063, -2.0359, 5.51526, 0.30284, -2.0359, 5.46174, 0.103096, -2.0359, 6.26072, 0.103096, -2.0359, 6.20719, 0.30284, -0.329213, 5.47658, 1.00003, -0.329213, 5.20344, 0.811334, -1.15486, 6.36123, 0.969121, -1.39648, 6.36123, 0.969121, -1.2072, 6.11123, 1.03611, -1.39648, 5.36123, -0.762936, -1.39648, 5.86123, -0.896911, -1.39648, 4.9952, -0.396911, -0.257146, 5.2834, 0.752961, -0.257147, 5.40641, 0.875976, -0.329213, 5.36123, 0.969121, -0.257147, 5.49634, 0.900073, -0.685695, 5.86123, 1.1031, -0.633352, 6.11123, 1.03611, -1.39648, 5.36123, 0.969121, -1.15486, 5.86123, 1.1031, -1.39648, 5.86123, 1.1031, -1.39648, 4.9952, 0.603096, -0.23657, 2.56168, 0.0584772, -0.170392, 2.51572, 0.125662, -0.350345, 2.31871, -0.0906937, -0.153299, 4.61636, -0.336561, -0.252264, 4.53307, -0.191655, -0.271744, 3.18932, -0.0437093, -0.202672, 3.0838, 0.187225, -0.122488, 3.05335, 0.253795, -0.281216, 3.12258, 0.0987407, -0.85235, 3.93911, -0.160509, -0.954611, 4.1111, -0.182336, -0.809584, 3.86528, -0.0607897, -0.809978, 3.84435, 0.0462258, -1.39648, 4.86123, 0.103096, -0.18642, 4.95573, -0.248219, -0.269727, 4.92174, -0.116503, -0.212301, 4.88556, 0.0356146, -0.942888, 6.86123, 0.103096, -0.841135, 6.72725, -0.396911, -1.39648, 6.72725, -0.396911, -1.39648, 6.86123, 0.103096, -0.257165, 6.36123, -0.762936, -1.39648, 6.36123, -0.762936, -1.39648, 6.72725, 0.603096, -0.841135, 6.72725, 0.603096, -0.257165, 6.36123, 0.969121, -0.685695, 6.36123, 0.969121 </vector3_array>
- <vector3_array len="679"> 0.323483, -0.753124, 0.572855, 0.771126, -0.534781, 0.345505, 0.599478, 0.562448, 0.569454, 0.202252, 0.315394, 0.927157, 0, 1, -0, 0.696021, 0.718022, -0, 0.599136, 0.562128, -0.57013, 0, 0.866019, -0.500011, 0, -0.789191, -0.614148, 0, 0.382911, -0.923785, 0.202065, 0.315101, -0.927298, 0.323297, -0.752692, -0.573527, 0, -0.789675, 0.613525, 0, 0.383265, 0.923638, 0.770859, -0.534596, -0.346386, 0.868674, -0.495384, 0, 0, 0.866452, 0.49926, 0.167052, 0.584181, -0.794246, 0.308094, 0.942288, -0.13104, -0.783538, 0.601413, -0.156107, -0.724538, 0.614456, -0.312232, -0.831821, 0.51651, -0.203201, -0.468553, 0.81396, 0.343405, -0.207013, 0.970059, -0.127008, -0.839933, 0.527586, -0.127141, -0.839469, 0.51929, -0.16009, -0.952083, -0.0830945, -0.294335, -0.969325, 0.0600821, 0.238326, -0.242219, 0.80573, 0.54049, -0.618771, 0.285356, 0.731912, -0.00900884, -0.126124, 0.991974, 0.500138, 0.3651, 0.785216, 0.0490036, 0.723054, -0.689051, 0.0889861, 0.993844, -0.0659897, 0.858321, 0.492184, 0.145054, 0.845097, 0.209024, -0.492057, -0.210106, 0.16008, -0.964484, 0.529219, -0.36215, -0.767317, 0.835061, -0.3935, 0.384488, 0.882867, -0.432425, 0.18318, 0.857612, -0.49035, 0.155111, 0.828872, -0.533561, 0.168177, -0.311554, -0.724288, 0.615094, -0.251244, -0.959933, -0.124121, 0.661603, -0.73467, 0.150137, 0.642912, -0.678963, 0.354503, 0.72766, -0.516469, 0.45141, 0.115162, -0.7841, -0.609856, 0.772162, -0.611128, 0.174036, 0.773373, -0.45522, 0.441213, 0.537341, -0.81952, 0.199126, -0.891041, -0.346405, -0.293343, -0.609658, -0.17619, -0.772835, -0.901333, -0.16224, 0.401594, -0.77153, 0.0690475, -0.632435, -0.315127, 0.0940378, -0.944379, 0.055046, -0.627524, -0.776649, -0.536581, -0.621673, -0.570617, 0.861095, 0.107012, 0.497055, -0.0380375, 0.0810799, 0.995982, -0.00700771, -0.117129, 0.993092, 0.797008, -0.304385, 0.521659, 0.524884, 0.803823, -0.279938, 0.595044, 0.585044, 0.551041, 0.871559, 0.129934, -0.472761, -0.200267, 0.367489, 0.90821, 0.0669956, 0.520966, -0.850944, 0.382844, 0.129947, -0.914628, -0.739262, 0.276472, 0.614048, -0.776468, 0.0611156, 0.627186, -0.58619, 0.359116, -0.726235, -0.959877, 0.277253, 0.0420384, -0.992667, 0.0720484, -0.0970652, -0.896641, 0.277198, -0.345247, -0.943047, 0.164182, -0.289321, -0.728454, 0.359224, -0.583363, -0.765447, 0.642375, 0.0380222, -0.855938, 0.516566, 0.0230252, -0.610501, 0.786645, -0.0920755, -0.477172, 0.854307, 0.206074, -0.309014, 0.951044, 0.00500023, -0.513202, 0.81332, -0.274108, -0.781621, 0.597475, 0.179142, -0.831231, 0.554821, 0.0350519, -0.80571, 0.57851, 0.127112, 0.0110026, 0.996233, -0.0860201, -0.616626, 0.733745, -0.28529, -0.740791, 0.504539, 0.443474, 0.0110097, 0.826727, 0.562495, 0.798668, 0.375314, 0.470393, 0.00700849, 0.548665, 0.836013, 0.68171, 0.189197, 0.706736, -0.65479, 0.336406, 0.676817, -0.0310549, -0.441781, 0.896585, -0.617121, -0.634152, 0.465846, -0.16707, 0.870366, 0.463195, -0.5063, 0.725429, 0.466276, -0.711913, 0.614788, 0.339435, -0.409744, 0.0530964, 0.910654, -0.764085, -0.38755, 0.515732, -0.847732, 0.508439, -0.15113, 0.0380266, 0.718502, 0.694485, -0.160029, 0.076014, -0.984181, -0.759497, 0.484317, -0.434284, -0.812045, -0.505651, -0.291375, -0.511638, -0.289361, -0.809009, -0.820559, 0.421287, -0.386263, -0.223103, 0.739342, -0.635294, -0.724353, 0.0750365, -0.685334, -0.43004, 0.304028, -0.850078, -0.80007, 0.434581, 0.413553, -0.0460378, -0.996819, -0.0650535, -0.0350519, -0.808196, 0.58787, 0.267172, -0.820528, -0.505325, 0.6294, -0.428272, -0.648412, 0.297403, -0.309419, 0.903223, 0.622553, 0.221196, 0.750666, 0.897953, 0.117994, -0.423978, 0.920375, 0.351143, 0.17207, -0.753305, -0.654134, 0.0681181, -0.674119, -0.252419, 0.694153, 0.713493, -0.691478, -0.113078, 0.455352, 0.602466, 0.655507, -0.318438, 0.223307, 0.921266, -0.564392, 0.704489, 0.430299, -0.398344, 0.805696, 0.438379, 0.565223, 0.681269, -0.465184, -0.74958, 0.0670519, 0.658509, -0.747893, 0.534638, 0.39347, -0.0789773, 0.541844, -0.83676, -0.969378, 0.150213, 0.194276, -0.723252, 0.667233, -0.178062, -0.702756, -0.294317, -0.647697, -0.77343, -0.576065, 0.264489, 0.64207, -0.336037, -0.689075, 0.714816, 0.636836, -0.288926, 0.692559, -0.68055, 0.239193, 0.560659, -0.716842, 0.414487, -0.216317, -0.957402, 0.19128, 0.194204, -0.972021, 0.132139, 0.711943, 0.135989, -0.688945, -0.686439, 0.302193, -0.661423, 0.776432, -0.314175, -0.546304, 0.886017, -0.231005, -0.402008, 0.886168, -0.401076, -0.232044, 0.776611, -0.545429, -0.315248, 0.776187, 0.546132, -0.315076, 0.885812, 0.401915, -0.231951, 0.885812, 0.231951, -0.401915, 0.776187, 0.315076, -0.546132, 0.885871, 0, -0.463932, 0.776359, 0, -0.630291, 0.327036, 0.818089, -0.473052, 0.327036, 0.473052, -0.818089, 0.32719, -0.472275, -0.818476, 0.327303, -0.817758, -0.473439, 0.327008, 0, -0.945022, -0.652547, 0.65655, 0.378317, -0.652728, 0.379423, 0.655732, 0.327303, 0.473439, 0.817758, 0.32719, 0.818476, 0.472275, -0.653098, 0, 0.757273, 0.327317, 0, 0.944915, -0.652976, -0.378566, 0.65598, 0.327458, -0.472662, 0.818145, -0.652547, -0.378317, -0.65655, -0.652728, -0.655732, -0.379423, -0.652976, -0.65598, 0.378566, 0.327458, -0.818145, 0.472662, -0.652603, 0, -0.7577, -0.653098, -0.757273, 0, 0.327317, -0.944915, 0, -0.6523, 0.379174, -0.656302, -0.6523, 0.656302, -0.379174, -0.652603, 0.7577, 0, 0.327008, 0.945022, -0, 0.776848, 0, 0.629688, 0.776611, 0.315248, 0.545429, 0.776856, -0.314346, 0.545601, 0.776856, -0.545601, 0.314346, 0.776848, -0.629688, 0, 0.776432, 0.546304, 0.314175, 0.776359, 0.630291, -0, 0.886281, -0.463147, 0, 0.886373, -0.401169, 0.231097, 0.886373, -0.231097, 0.401169, 0.886281, 0, 0.463147, 0.886168, 0.232044, 0.401076, 0.886017, 0.402008, 0.231005, 0.885871, 0.463932, -0, 0.320359, 0.0650729, 0.945059, 0, 0.0700382, 0.997544, 0, 0.642347, 0.766414, 0.0170187, 0.688755, 0.724794, 0.609974, 0.430981, -0.664971, 0.947519, 0.264145, -0.180099, 0.303207, 0.801547, 0.515352, 0.183115, 0.866546, 0.464292, 0, 0.882519, 0.470277, -0.0130118, 0.73066, 0.682617, 0, 0.706106, 0.708106, 0.225998, 0.736995, 0.636996, 0.221247, 0.645722, 0.730817, -0.0530284, 0.84045, 0.539289, -0.0270074, 0.825227, 0.564155, -0.0350336, 0.777746, 0.627602, 0, 0.830353, 0.557237, -0.0410178, 0.818354, 0.573248, 0, 0.314425, 0.949282, 0.27534, 0.29136, 0.916132, 0.778752, -0.489473, 0.392379, 0.746544, -0.651475, -0.135099, 0.272405, -0.803194, 0.529788, 0.652602, -0.667616, 0.35833, 0.671414, 0.730451, 0.125077, 0.357959, 0.928893, -0.0949891, 0.443473, 0.436465, 0.782835, 0, 0.377932, -0.925833, 0.555211, 0.240091, -0.796302, 0.325138, -0.340145, -0.882376, 0, -0.203036, -0.979171, 0.405354, -0.612535, 0.678593, 0, -0.671726, 0.7408, 0, -0.989545, 0.144225, 0.324316, -0.945923, 0.00700683, 0.678459, 0.508344, 0.530359, 0.581287, -0.797393, -0.16208, 0, 0.993246, -0.116029, 0.624575, -0.536494, -0.567522, 0, -0.741749, -0.670677, 0, -0.556084, -0.831126, 0, -0.999902, -0.0140126, 0, -0.966632, -0.256168, 0.738289, -0.658258, -0.147058, 0, -0.851521, -0.524321, 0, -0.900741, -0.434357, 0, -0.346076, -0.938206, 0.897164, -0.425078, 0.120022, 0.916025, -0.0850023, -0.392011, 0.746835, -0.537601, -0.391438, 0.24712, 0.836407, 0.489238, 0.187033, 0.840147, 0.509089, 0.180007, 0.858032, 0.481018, 0.245128, 0.817427, 0.521272, 0, 0.768221, 0.640184, 0, 0.834352, 0.551232, 0.143113, 0.833656, 0.53342, 0, 0.114054, -0.993474, 0.536767, 0.0429814, -0.842635, 0.34218, -0.328173, -0.880463, 0, -0.278155, -0.960536, 0.372421, -0.379429, 0.846957, 0, -0.377424, 0.926041, 0, -0.819843, 0.572589, 0.295296, -0.813817, 0.500502, 0.195064, 0.900294, 0.389127, 0.804875, 0.356387, 0.474516, 0.808731, 0.587804, -0.020993, 0, 0.994988, 0.0999987, 0.169127, 0.969729, 0.176132, 0.451126, 0.771215, -0.449125, 0, 0.777245, -0.629198, 0.78993, -0.410483, 0.455536, 0.657391, -0.729434, 0.189112, 0.705632, 0.319286, 0.632566, 0.308272, 0.411363, 0.857758, 0.231245, -0.951006, 0.205217, 0.47266, -0.881231, 0.00500699, 0.887311, -0.393138, -0.241085, 0.618412, -0.762508, -0.190127, 0.259028, -0.529057, -0.808087, 0, -0.471055, -0.882104, 0, -0.97194, 0.235228, 0.972719, -0.231933, -0.00499856, 0.748485, -0.564366, -0.348226, 0, 0.419376, 0.907813, 0.793691, -0.521454, -0.313273, 0.307062, -0.405082, -0.861174, 0, -0.36621, -0.930532, -0.256367, -0.749072, -0.610874, 0.241336, -0.969348, -0.0460641, 0.800238, -0.563168, -0.206061, 0.679395, -0.526306, -0.511297, 0.794806, -0.441448, -0.416422, 0.78099, -0.430994, -0.451994, 0.727309, -0.686292, 0.00500213, 0.915343, -0.34713, -0.204077, 0.535473, -0.673595, -0.50945, 0.971477, -0.237116, 0.00300147, 0.731118, -0.68011, -0.0540087, 0.849093, -0.528058, -0.0140015, 0.83344, -0.540285, -0.116061, 0.864591, -0.499341, -0.0560383, 0.984291, 0.153045, -0.088026, 0.984291, 0.088026, -0.153045, 0.984377, -0.0870333, -0.153059, 0.984441, -0.152068, -0.0880395, 0.984378, 0, -0.176068, 0.984551, 0, 0.175098, 0.984441, 0.0880395, 0.152068, 0.984527, -0.0870466, 0.152081, 0.984527, -0.152081, 0.0870466, 0.984551, -0.175098, 0, 0.984377, 0.153059, 0.0870333, 0.984378, 0.176068, -0, 0, 0, 1, 0, -0.848897, 0.528558, -0.210351, -0.405676, 0.889483, 0, -0.0810577, 0.996709, 0, -0.92105, 0.389444, -0.197353, -0.573024, 0.795421, -0.167145, 0.336293, 0.926806, -0.401672, 0.237397, 0.884479, 0.653302, 0.379175, 0.655303, 0, 0, -1, 0.653177, 0, -0.757205, 0.653121, -0.37807, -0.656122, 0, -0.49926, -0.866452, 0.671631, -0.686645, -0.278262, 0, -0.926881, -0.375357, -0.433934, -0.447965, 0.781683, -0.4965, -0.437441, 0.749755, -0.353503, -0.137195, 0.925318, 0, -0.848897, 0.528558, -0.359502, -0.75906, 0.542758, 0, -0.0770792, 0.997025, 0.168109, 0.172111, 0.970627, 0.402511, 0.237301, 0.884123, 0.65355, -0.378318, 0.655551, 0.653672, 0, 0.756778, -0.167136, 0.17214, 0.97079, 0.668803, -0.684822, 0.289347, 0.880048, 0.129007, 0.457025, 0.644507, 0.0390307, 0.763601, 0, 0.542878, -0.839811, 0.823173, -0.419088, -0.383081, 0, 0.941447, 0.33716, 0.175995, 0.932972, 0.31399, 0.269002, 0.885006, 0.380003, 0.644374, -0.493286, -0.584339, 0.355385, -0.786851, 0.504546, 0.641692, -0.681736, 0.351379, 0.758512, -0.647437, -0.07405, 0, -0.746027, 0.665916, 0.905274, -0.411124, -0.107032, 0.759428, -0.614346, -0.214121, 0.64053, -0.74862, -0.171142, 0.712784, -0.693763, -0.103113, 0, -0.812786, -0.582563, 0.707572, -0.706571, 0.0100081, 0.463983, -0.666975, -0.582978, 0.721736, -0.682696, -0.114116, 0.557506, -0.667605, 0.493448, 0, -0.762778, 0.64666, -0.001, 1, 0, 0.653177, 0.757205, -0, 0.652874, 0.655873, -0.378927, -0.0379873, 0.86471, -0.500832, 0.652874, 0.378927, -0.655873, -0.0350082, 0.578135, -0.81519, -0.0380063, 0.865143, 0.500083, 0.653121, 0.656122, 0.37807, 0, 0.610194, -0.792252, -0.0350367, 0.578606, 0.814854, 0.168118, 0.336236, 0.926651, 0, 0.610678, 0.791879, -0.322586, -0.753368, 0.57304, -0.201292, 0.315457, 0.927345, -0.598836, 0.562786, 0.569796, -0.77072, -0.535194, 0.345772, -0.598495, 0.562465, -0.570471, -0.695505, 0.718521, 0, -0.322401, -0.752935, -0.573713, -0.201105, 0.315165, -0.927485, -0.770452, -0.535009, -0.346654, -0.868428, -0.495815, 0, -0.166079, 0.584278, -0.794378, 0.725013, 0.614011, -0.312005, 0.783924, 0.600942, -0.155985, -0.307188, 0.942578, -0.13108, 0.20797, 0.969858, -0.126981, 0.469334, 0.813578, 0.343244, 0.832129, 0.51608, -0.203032, 0.840228, 0.527143, -0.127034, 0.969385, 0.0600239, 0.238095, 0.952177, -0.0830154, -0.294055, 0.839764, 0.518854, -0.159955, 0.243161, 0.805534, 0.540358, -0.499387, 0.365283, 0.785609, 0.0100097, -0.126123, 0.991964, 0.619388, 0.285179, 0.731458, -0.0480059, 0.723089, -0.689085, -0.844811, 0.209201, -0.492473, -0.858057, 0.492607, 0.145179, -0.087994, 0.993932, -0.0659955, 0.211062, 0.160047, -0.964281, -0.528498, -0.362341, -0.767723, -0.882646, -0.432807, 0.183342, -0.834757, -0.393829, 0.38481, -0.828558, -0.534004, 0.168317, -0.857347, -0.490771, 0.155244, 0.312458, -0.724062, 0.614902, -0.642324, -0.679401, 0.354731, -0.66104, -0.735157, 0.150236, 0.252182, -0.959691, -0.124089, -0.727189, -0.516845, 0.451739, -0.771757, -0.6116, 0.174171, -0.114173, -0.784191, -0.609926, -0.772971, -0.455572, 0.441554, -0.536629, -0.819961, 0.199233, 0.891247, -0.346096, -0.293081, 0.610287, -0.176083, -0.772363, 0.90152, -0.162094, 0.401232, 0.771935, 0.0689942, -0.631947, 0.537293, -0.621339, -0.570311, -0.0540481, -0.627558, -0.776691, 0.316027, 0.0940081, -0.944081, -0.860836, 0.107104, 0.497483, -0.796642, -0.304628, 0.522076, 0.00800875, -0.117128, 0.993085, 0.039037, 0.0810768, 0.995943, -0.524159, 0.804245, -0.280085, -0.871318, 0.130047, -0.473173, -0.594398, 0.585392, 0.551369, 0.201228, 0.367416, 0.908027, -0.0660001, 0.521001, -0.851001, -0.381991, 0.129997, -0.914978, 0.776865, 0.061068, 0.626698, 0.739716, 0.276267, 0.613594, 0.586846, 0.358906, -0.725809, 0.992681, 0.0719769, -0.0969689, 0.959955, 0.276987, 0.0419981, 0.896837, 0.27695, -0.344937, 0.943158, 0.164027, -0.289048, 0.856205, 0.516124, 0.0230055, 0.765861, 0.641883, 0.0379931, 0.728923, 0.358962, -0.582938, 0.611128, 0.786165, -0.0920193, 0.513938, 0.812902, -0.273967, 0.309918, 0.95075, 0.00499869, 0.477944, 0.853899, 0.205976, 0.78201, 0.597008, 0.179002, 0.806061, 0.578044, 0.12701, 0.83154, 0.55436, 0.0350227, -0.0100024, 0.996243, -0.086021, -0.0100089, 0.826736, 0.562501, 0.741242, 0.504165, 0.443145, 0.617246, 0.733292, -0.285114, -0.798305, 0.375614, 0.470769, -0.681174, 0.189326, 0.707219, -0.00600732, 0.548668, 0.836019, 0.655362, 0.336185, 0.676373, 0.0320557, -0.441767, 0.896557, 0.617741, -0.63376, 0.465558, 0.507043, 0.725062, 0.46604, 0.168043, 0.870221, 0.463117, 0.712406, 0.61435, 0.339193, 0.410577, 0.0530746, 0.91028, 0.848013, 0.508008, -0.151002, 0.764501, -0.387254, 0.515338, -0.0370272, 0.718529, 0.694511, 0.161004, 0.0760018, -0.984023, 0.75992, 0.483949, -0.433954, 0.812386, -0.50524, -0.291138, 0.820886, 0.420942, -0.385946, 0.512377, -0.289213, -0.808595, 0.224054, 0.739177, -0.635152, 0.724828, 0.0749822, -0.684837, 0.430854, 0.303897, -0.849712, 0.80043, 0.434233, 0.413222, 0.0360521, -0.808167, 0.587849, 0.0470365, -0.996773, -0.0650504, -0.266242, -0.820747, -0.50546, -0.628795, -0.428542, -0.648821, -0.296489, -0.309511, 0.903492, -0.621939, 0.221334, 0.751134, -0.897759, 0.1181, -0.424359, -0.920222, 0.351467, 0.172229, 0.753738, -0.65364, 0.0680667, 0.674665, -0.252249, 0.693684, -0.713001, -0.691972, -0.113159, -0.454558, 0.60274, 0.655806, 0.399186, 0.805375, 0.438204, 0.565073, 0.704091, 0.430056, 0.319337, 0.223236, 0.920972, -0.564542, 0.681654, -0.465447, 0.748334, 0.534238, 0.393175, 0.750018, 0.0670016, 0.658015, 0.0799707, 0.541802, -0.836693, 0.969438, 0.150068, 0.194088, 0.723729, 0.66675, -0.177933, 0.773832, -0.575619, 0.264284, 0.703262, -0.29411, -0.647241, -0.641482, -0.336253, -0.689518, -0.692038, -0.681022, 0.239359, -0.714327, 0.637291, -0.289132, -0.559972, -0.717244, 0.41472, 0.217271, -0.957194, 0.191239, 0.686968, 0.301986, -0.660969, -0.711449, 0.136086, -0.689435, -0.19324, -0.972209, 0.132164, -0.776034, -0.314419, -0.546728, -0.776214, -0.545854, -0.315493, -0.885953, -0.401432, -0.23225, -0.885802, -0.231209, -0.402364, -0.775789, 0.546556, -0.315321, -0.775789, 0.315321, -0.546556, -0.885597, 0.232156, -0.402271, -0.885597, 0.402271, -0.232156, -0.775961, 0, -0.630781, -0.885655, 0, -0.464344, -0.326142, 0.818357, -0.473206, -0.326142, 0.473206, -0.818357, -0.326296, -0.472429, -0.818744, -0.326409, -0.818026, -0.473594, -0.326114, 0, -0.94533, 0.653121, 0.656122, 0.37807, -0.326296, 0.818744, 0.472429, -0.326409, 0.473594, 0.818026, 0.653302, 0.379175, 0.655303, -0.326423, 0, 0.945224, 0.653672, 0, 0.756778, -0.326564, -0.472817, 0.818413, 0.65355, -0.378318, 0.655551, 0.653121, -0.37807, -0.656122, 0.653302, -0.655303, -0.379175, -0.326564, -0.818413, 0.472817, 0.65355, -0.655551, 0.378318, 0.653177, 0, -0.757205, -0.326423, -0.945224, 0, 0.653672, -0.756778, 0, 0.652874, 0.378927, -0.655873, 0.652874, 0.655873, -0.378927, 0.653177, 0.757205, -0, -0.326114, 0.94533, 0, -0.776214, 0.315493, 0.545854, -0.776451, 0, 0.630178, -0.776459, -0.314591, 0.546026, -0.776459, -0.546026, 0.314591, -0.776451, -0.630178, 0, -0.775961, 0.630781, 0, -0.776034, 0.546728, 0.314419, -0.886159, -0.401525, 0.231302, -0.886067, -0.463558, 0, -0.886067, 0, 0.463558, -0.886159, -0.231302, 0.401525, -0.885953, 0.23225, 0.401432, -0.885802, 0.402364, 0.231209, -0.885655, 0.464344, 0, -0.31946, 0.0650937, 0.945361, -0.0160178, 0.688766, 0.724806, -0.609345, 0.431244, -0.665377, -0.182148, 0.866704, 0.464377, -0.302298, 0.80179, 0.515508, -0.947416, 0.264395, -0.18027, 0.0140125, 0.730651, 0.682608, -0.225049, 0.737161, 0.637139, 0.0280069, 0.825204, 0.56414, 0.054026, 0.840405, 0.53926, -0.220295, 0.645864, 0.730978, 0.0360333, 0.777718, 0.62758, 0.0420165, 0.81832, 0.573224, -0.274414, 0.29144, 0.916384, -0.778358, -0.489855, 0.392685, -0.652026, -0.668052, 0.358564, -0.271477, -0.803413, 0.529932, -0.746101, -0.651962, -0.135199, -0.357087, 0.929225, -0.095023, -0.670864, 0.730942, 0.125161, -0.442668, 0.436659, 0.783182, -0.324243, -0.340255, -0.882662, -0.554518, 0.240224, -0.796745, -0.404517, -0.612784, 0.678868, -0.323422, -0.946236, 0.00600785, -0.677918, 0.508689, 0.530719, -0.580624, -0.797857, -0.162174, -0.623964, -0.536829, -0.567877, -0.737833, -0.658744, -0.147166, -0.896969, -0.42546, 0.12013, -0.915864, -0.0850803, -0.39237, -0.746391, -0.538003, -0.39173, -0.246181, 0.836614, 0.489359, -0.179039, 0.858186, 0.481104, -0.186067, 0.840304, 0.509184, -0.244187, 0.817627, 0.5214, -0.142132, 0.833775, 0.533496, -0.341296, -0.328285, -0.880764, -0.536055, 0.0430044, -0.843087, -0.371558, -0.37957, 0.847273, -0.294382, -0.814057, 0.50065, -0.194101, 0.90047, 0.389203, -0.808384, 0.58828, -0.02101, -0.804522, 0.356675, 0.474898, -0.450328, 0.771563, -0.449328, -0.168155, 0.969892, 0.176162, -0.789553, -0.410808, 0.455897, -0.656822, -0.729914, 0.189237, -0.705129, 0.319511, 0.633013, -0.307366, 0.41149, 0.858022, -0.471882, -0.881648, 0.00500936, -0.230297, -0.951225, 0.205264, -0.887098, -0.393487, -0.241299, -0.617794, -0.76298, -0.190244, -0.258094, -0.529194, -0.808295, -0.972665, -0.232159, -0.00500342, -0.748045, -0.564789, -0.348487, -0.79332, -0.521869, -0.313522, -0.306156, -0.405206, -0.861439, -0.240392, -0.969582, -0.0460752, 0.257302, -0.748879, -0.610717, -0.799878, -0.563619, -0.206226, -0.678856, -0.526664, -0.511645, -0.794437, -0.441799, -0.416754, -0.780599, -0.431331, -0.452347, -0.726837, -0.686791, 0.00500577, -0.915181, -0.347448, -0.204264, -0.534758, -0.673956, -0.509723, -0.97142, -0.237347, 0.00300439, -0.848814, -0.528507, -0.0140134, -0.730652, -0.680607, -0.0540482, -0.864338, -0.499774, -0.0560868, -0.833134, -0.540736, -0.116158, -0.98426, 0.0881128, -0.153196, -0.98426, 0.153196, -0.0881128, -0.98441, -0.152218, -0.0881262, -0.984346, -0.0871191, -0.15321, -0.984347, 0, -0.176241, -0.98441, 0.0881262, 0.152218, -0.98452, 0, 0.175271, -0.984497, -0.0871325, 0.152231, -0.984497, -0.152231, 0.0871325, -0.98452, -0.175271, 0, -0.984347, 0.176241, 0, -0.984346, 0.15321, 0.0871191, 0.211308, -0.405591, 0.889295, 0.198315, -0.572911, 0.795264, 0.168118, 0.336236, 0.926651, -0.652728, 0.379423, 0.655732, 0.402511, 0.237301, 0.884123, -0.652547, -0.378317, -0.65655, -0.652603, 0, -0.7577, -0.671081, -0.687107, -0.278449, 0.354379, -0.137147, 0.92499, 0.497254, -0.437223, 0.749383, 0.434747, -0.44777, 0.781343, 0.360374, -0.758786, 0.542562, -0.167136, 0.17214, 0.97079, -0.401672, 0.237397, 0.884479, -0.652976, -0.378566, 0.65598, 0.168109, 0.172111, 0.970627, -0.653098, 0, 0.757273, -0.668249, -0.685281, 0.289541, -0.879823, 0.129121, 0.457428, -0.643922, 0.0390559, 0.764094, -0.82285, -0.419434, -0.383396, -0.175025, 0.933135, 0.314046, -0.268074, 0.885244, 0.380105, -0.643788, -0.493604, -0.584716, -0.641103, -0.682174, 0.351605, -0.354509, -0.787131, 0.504725, -0.758087, -0.647929, -0.0741063, -0.759004, -0.614813, -0.214283, -0.905093, -0.411497, -0.107129, -0.639939, -0.7491, -0.171251, -0.712291, -0.694258, -0.103187, -0.707071, -0.707071, 0.0100152, -0.463198, -0.667285, -0.583249, -0.721256, -0.68319, -0.114199, -0.556815, -0.667978, 0.493723, 0.002, 0.999998, -0, 0.0389854, 0.864677, -0.500813, -0.6523, 0.656302, -0.379174, -0.652603, 0.7577, 0, 0.0360071, 0.578114, -0.815161, -0.6523, 0.379174, -0.656302, -0.652547, 0.65655, 0.378317, 0.039005, 0.86511, 0.500063, 0.0360365, 0.578586, 0.814825, -0.167145, 0.336293, 0.926806 </vector3_array>
- <nil> </nil>
- <nil> </nil>
- <nil> </nil>
- <nil> </nil>
- <real_array len="2716"> 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 9, 8, 0, 0, 8, 9, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 12, 13, 0, 0, 12, 13, 0, 0, 13, 12, 0, 0, 13, 12, 0, 0, 13, 12, 0, 0, 13, 12, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 12, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 9, 8, 0, 0, 8, 9, 0, 0, 9, 0, 0, 0, 8, 9, 0, 0, 9, 8, 0, 0, 9, 0, 0, 0, 8, 9, 0, 0, 8, 9, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 12, 13, 0, 0, 12, 13, 0, 0, 13, 12, 0, 0, 13, 12, 0, 0, 12, 13, 0, 0, 12, 13, 0, 0, 13, 12, 0, 0, 12, 13, 0, 0, 12, 13, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 12, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 7, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 11, 10, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 10, 11, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 15, 16, 0, 0, 16, 15, 0, 0, 16, 15, 0, 0, 15, 16, 0, 0, 16, 15, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 15, 0, 0, 16, 15, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 11, 10, 0, 0, 11, 0, 0, 0, 10, 11, 0, 0, 10, 11, 0, 0, 11, 10, 0, 0, 11, 0, 0, 0, 10, 11, 0, 0, 11, 0, 0, 0, 10, 11, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 15, 16, 0, 0, 16, 15, 0, 0, 16, 15, 0, 0, 15, 16, 0, 0, 15, 16, 0, 0, 16, 15, 0, 0, 15, 16, 0, 0, 15, 16, 0, 0, 15, 16, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 15, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0 </real_array>
- <real_array len="2716"> 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.5, 0.5, 0, 0, 0.503159, 0.496841, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.700171, 0.299829, 0, 0, 0.66474, 0.33526, 0, 0, 0.704636, 0.295364, 0, 0, 0.664742, 0.335258, 0, 0, 0.719812, 0.280188, 0, 0, 0.682575, 0.317425, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.664813, 0.335187, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.533212, 0.466788, 0, 0, 0.538228, 0.461772, 0, 0, 1, 0, 0, 0, 0.500006, 0.499994, 0, 0, 0.525218, 0.474782, 0, 0, 1, 0, 0, 0, 0.563768, 0.436232, 0, 0, 0.523139, 0.476861, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.665519, 0.334481, 0, 0, 0.664658, 0.335342, 0, 0, 0.676033, 0.323967, 0, 0, 0.667711, 0.332289, 0, 0, 0.668675, 0.331325, 0, 0, 0.673479, 0.326521, 0, 0, 0.667424, 0.332576, 0, 0, 0.6672, 0.3328, 0, 0, 0.664792, 0.335208, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.500004, 0.499996, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.997415, 0.00258508, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.5, 0.5, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.503159, 0.496841, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.700171, 0.299829, 0, 0, 0.664742, 0.335258, 0, 0, 0.704636, 0.295364, 0, 0, 0.66474, 0.33526, 0, 0, 0.719812, 0.280188, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.682575, 0.317425, 0, 0, 0.664813, 0.335187, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.533212, 0.466788, 0, 0, 1, 0, 0, 0, 0.538228, 0.461772, 0, 0, 0.500006, 0.499994, 0, 0, 0.525218, 0.474782, 0, 0, 1, 0, 0, 0, 0.563768, 0.436232, 0, 0, 1, 0, 0, 0, 0.523139, 0.476861, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.665519, 0.334481, 0, 0, 0.667711, 0.332289, 0, 0, 0.676033, 0.323967, 0, 0, 0.664658, 0.335342, 0, 0, 0.668675, 0.331325, 0, 0, 0.667424, 0.332576, 0, 0, 0.673479, 0.326521, 0, 0, 0.6672, 0.3328, 0, 0, 0.664792, 0.335208, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.500004, 0.499996, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 </real_array>
- <int_array len="3246"> 0, 2, 1, 0, 3, 2, 4, 6, 5, 4, 7, 6, 8, 10, 9, 8, 11, 10, 12, 3, 0, 12, 13, 3, 11, 6, 10, 11, 14, 6, 14, 5, 6, 14, 15, 5, 1, 5, 15, 1, 2, 5, 4, 2, 16, 4, 5, 2, 16, 3, 13, 16, 2, 3, 7, 10, 6, 7, 9, 10, 17, 19, 18, 17, 20, 19, 19, 22, 21, 19, 23, 22, 24, 26, 25, 24, 27, 26, 28, 30, 29, 28, 31, 30, 32, 34, 33, 32, 35, 34, 33, 31, 28, 33, 34, 31, 36, 35, 32, 36, 37, 35, 34, 38, 31, 34, 39, 38, 37, 40, 35, 37, 41, 40, 42, 44, 43, 42, 45, 44, 31, 46, 30, 31, 38, 46, 35, 39, 34, 35, 40, 39, 43, 48, 47, 43, 44, 48, 47, 41, 37, 47, 48, 41, 30, 45, 42, 30, 46, 45, 44, 49, 48, 48, 49, 41, 46, 49, 45, 39, 50, 38, 41, 50, 40, 41, 49, 50, 45, 49, 44, 38, 49, 46, 38, 50, 49, 40, 50, 39, 51, 47, 52, 51, 43, 47, 52, 37, 36, 52, 47, 37, 53, 43, 51, 53, 42, 43, 29, 42, 53, 29, 30, 42, 54, 56, 55, 54, 57, 56, 58, 60, 59, 58, 61, 60, 62, 58, 63, 62, 64, 58, 63, 59, 65, 63, 58, 59, 66, 64, 62, 66, 67, 64, 65, 69, 68, 65, 59, 69, 70, 67, 66, 70, 55, 67, 68, 72, 71, 68, 69, 72, 73, 55, 70, 73, 54, 55, 74, 76, 75, 74, 77, 76, 78, 80, 79, 78, 81, 80, 82, 83, 77, 82, 84, 83, 85, 87, 86, 85, 88, 87, 89, 90, 88, 89, 91, 90, 88, 92, 87, 88, 90, 92, 91, 93, 90, 90, 93, 92, 92, 93, 94, 55, 56, 67, 65, 95, 63, 65, 96, 95, 68, 96, 65, 68, 97, 96, 71, 54, 73, 71, 72, 54, 98, 24, 99, 98, 100, 24, 18, 21, 101, 18, 19, 21, 102, 20, 17, 102, 103, 20, 99, 25, 104, 99, 24, 25, 101, 100, 98, 101, 21, 100, 104, 106, 105, 104, 25, 106, 105, 103, 102, 105, 106, 103, 20, 23, 19, 20, 107, 23, 25, 108, 106, 25, 26, 108, 106, 109, 103, 106, 108, 109, 100, 27, 24, 100, 110, 27, 103, 107, 20, 103, 109, 107, 21, 110, 100, 21, 22, 110, 27, 111, 26, 27, 112, 111, 26, 113, 108, 26, 111, 113, 108, 114, 109, 108, 113, 114, 110, 112, 27, 110, 115, 112, 22, 115, 110, 22, 116, 115, 109, 117, 107, 109, 114, 117, 107, 118, 23, 107, 117, 118, 23, 116, 22, 23, 118, 116, 72, 57, 54, 72, 119, 57, 59, 120, 69, 59, 60, 120, 64, 61, 58, 64, 121, 61, 69, 119, 72, 69, 120, 119, 122, 124, 123, 122, 125, 124, 126, 125, 122, 126, 79, 125, 123, 128, 127, 123, 124, 128, 129, 79, 126, 129, 78, 79, 130, 77, 74, 130, 82, 77, 75, 78, 129, 75, 76, 78, 127, 82, 130, 127, 128, 82, 124, 97, 128, 124, 96, 97, 79, 95, 125, 79, 80, 95, 128, 84, 82, 128, 97, 84, 76, 81, 78, 76, 131, 81, 77, 131, 76, 77, 83, 131, 125, 96, 124, 125, 95, 96, 86, 133, 132, 86, 87, 133, 134, 89, 135, 134, 136, 89, 135, 88, 85, 135, 89, 88, 136, 91, 89, 136, 137, 91, 87, 94, 133, 87, 92, 94, 137, 93, 91, 67, 121, 64, 67, 56, 121, 83, 70, 131, 83, 73, 70, 73, 84, 71, 73, 83, 84, 63, 80, 62, 63, 95, 80, 66, 131, 70, 66, 81, 131, 97, 71, 84, 97, 68, 71, 81, 62, 80, 81, 66, 62, 138, 140, 139, 138, 141, 140, 57, 139, 56, 138, 139, 119, 119, 139, 57, 56, 139, 121, 132, 136, 134, 132, 133, 136, 137, 133, 94, 137, 136, 133, 94, 93, 137, 142, 144, 143, 142, 145, 144, 146, 148, 147, 146, 149, 148, 149, 150, 148, 149, 151, 150, 151, 143, 150, 151, 142, 143, 152, 149, 146, 152, 153, 149, 154, 145, 142, 154, 155, 145, 156, 142, 151, 156, 154, 142, 153, 151, 149, 153, 156, 151, 157, 159, 158, 157, 160, 159, 158, 162, 161, 158, 159, 162, 161, 164, 163, 161, 162, 164, 165, 155, 154, 165, 166, 155, 163, 168, 167, 163, 164, 168, 169, 154, 156, 169, 165, 154, 167, 171, 170, 167, 168, 171, 172, 156, 153, 172, 169, 156, 173, 153, 152, 173, 172, 153, 174, 160, 157, 174, 175, 160, 159, 176, 162, 159, 177, 176, 162, 178, 164, 162, 176, 178, 164, 179, 168, 164, 178, 179, 168, 180, 171, 168, 179, 180, 175, 181, 160, 175, 182, 181, 160, 177, 159, 160, 181, 177, 179, 183, 180, 179, 184, 183, 176, 185, 178, 176, 186, 185, 177, 186, 176, 177, 187, 186, 181, 187, 177, 181, 188, 187, 178, 184, 179, 178, 185, 184, 182, 188, 181, 182, 189, 188, 182, 147, 189, 182, 146, 147, 145, 183, 144, 145, 180, 183, 175, 146, 182, 175, 152, 146, 155, 180, 145, 155, 171, 180, 174, 152, 175, 174, 173, 152, 166, 171, 155, 166, 170, 171, 190, 192, 191, 190, 193, 192, 194, 196, 195, 194, 197, 196, 198, 199, 197, 198, 200, 199, 201, 203, 202, 201, 204, 203, 197, 205, 196, 197, 199, 205, 193, 206, 192, 193, 207, 206, 196, 204, 201, 196, 205, 204, 202, 207, 193, 202, 203, 207, 207, 208, 206, 207, 209, 208, 210, 212, 211, 210, 213, 212, 199, 214, 205, 199, 215, 214, 203, 209, 207, 203, 216, 209, 217, 219, 218, 217, 220, 219, 221, 223, 222, 221, 224, 223, 205, 225, 204, 205, 214, 225, 204, 216, 203, 204, 225, 216, 224, 211, 226, 221, 211, 224, 210, 211, 221, 200, 215, 199, 200, 227, 215, 219, 229, 228, 219, 230, 229, 224, 231, 223, 224, 232, 231, 228, 234, 233, 228, 229, 234, 226, 232, 224, 226, 235, 232, 220, 230, 219, 220, 236, 230, 233, 235, 226, 233, 234, 235, 237, 214, 238, 237, 225, 214, 215, 238, 214, 215, 218, 238, 218, 227, 217, 218, 215, 227, 221, 216, 210, 221, 209, 216, 209, 222, 208, 209, 221, 222, 225, 210, 216, 225, 237, 210, 218, 219, 238, 238, 219, 239, 239, 219, 228, 240, 242, 241, 243, 245, 244, 243, 246, 245, 247, 249, 248, 247, 250, 249, 251, 253, 252, 251, 254, 253, 255, 256, 242, 255, 257, 256, 258, 260, 259, 258, 261, 260, 262, 254, 251, 262, 263, 254, 242, 264, 241, 242, 256, 264, 240, 246, 243, 240, 241, 246, 241, 265, 246, 241, 264, 265, 259, 257, 255, 259, 260, 257, 263, 266, 254, 263, 267, 266, 268, 267, 263, 268, 269, 267, 250, 270, 249, 250, 271, 270, 254, 272, 253, 254, 266, 272, 251, 264, 262, 251, 265, 264, 248, 261, 247, 248, 260, 261, 257, 273, 256, 260, 274, 257, 260, 248, 274, 265, 252, 275, 265, 251, 252, 256, 262, 264, 256, 276, 262, 246, 275, 245, 246, 265, 275, 271, 277, 270, 271, 278, 277, 226, 279, 233, 226, 280, 279, 211, 280, 226, 211, 212, 280, 237, 213, 210, 237, 281, 213, 233, 282, 228, 233, 279, 282, 238, 281, 237, 238, 283, 281, 276, 284, 262, 262, 284, 268, 262, 268, 263, 248, 249, 274, 274, 249, 285, 285, 249, 286, 249, 287, 286, 249, 270, 287, 286, 287, 288, 288, 287, 268, 268, 287, 269, 276, 289, 284, 276, 290, 289, 274, 291, 273, 274, 292, 291, 273, 290, 276, 273, 291, 290, 273, 257, 274, 256, 273, 276, 147, 294, 293, 147, 148, 294, 143, 296, 295, 143, 144, 296, 150, 295, 297, 150, 143, 295, 148, 297, 294, 148, 150, 297, 187, 298, 186, 187, 299, 298, 186, 300, 185, 186, 298, 300, 185, 301, 184, 185, 300, 301, 184, 302, 183, 184, 301, 302, 189, 303, 188, 189, 304, 303, 188, 299, 187, 188, 303, 299, 305, 307, 306, 308, 310, 309, 311, 313, 312, 189, 293, 304, 189, 147, 293, 144, 302, 296, 144, 183, 302, 314, 316, 315, 314, 317, 316, 317, 318, 316, 317, 319, 318, 310, 321, 320, 310, 322, 321, 307, 323, 306, 307, 324, 323, 320, 324, 307, 320, 321, 324, 308, 322, 310, 308, 325, 322, 326, 305, 327, 328, 330, 329, 328, 326, 330, 326, 320, 307, 320, 326, 328, 328, 310, 320, 326, 307, 305, 309, 310, 331, 331, 310, 328, 312, 329, 330, 313, 329, 312, 195, 201, 332, 195, 196, 201, 333, 193, 190, 333, 202, 193, 334, 197, 194, 334, 198, 197, 332, 202, 333, 332, 201, 202, 239, 283, 238, 239, 335, 283, 336, 259, 337, 336, 258, 259, 337, 255, 338, 337, 259, 255, 338, 242, 240, 338, 255, 242, 270, 339, 287, 270, 277, 339, 267, 340, 266, 267, 341, 340, 287, 342, 269, 287, 339, 342, 269, 341, 267, 269, 342, 341, 266, 343, 272, 266, 340, 343, 286, 344, 285, 286, 345, 344, 228, 335, 239, 228, 282, 335, 288, 345, 286, 288, 346, 345, 268, 346, 288, 268, 347, 346, 284, 347, 268, 284, 289, 347, 285, 292, 274, 285, 344, 292, 348, 318, 319, 348, 349, 318, 350, 349, 348, 351, 349, 350, 352, 349, 351, 353, 349, 352, 309, 349, 353, 309, 331, 349, 354, 356, 355, 354, 357, 356, 357, 358, 356, 357, 359, 358, 354, 361, 360, 354, 355, 361, 362, 314, 359, 359, 314, 358, 358, 314, 315, 360, 361, 363, 363, 361, 313, 363, 313, 364, 364, 313, 311, 365, 363, 305, 364, 327, 363, 327, 305, 363, 366, 368, 367, 366, 369, 368, 4, 370, 7, 4, 371, 370, 8, 373, 372, 8, 9, 373, 12, 367, 13, 12, 366, 367, 372, 370, 374, 372, 373, 370, 374, 371, 375, 374, 370, 371, 369, 371, 368, 369, 375, 371, 4, 368, 371, 4, 16, 368, 16, 367, 368, 16, 13, 367, 7, 373, 9, 7, 370, 373, 376, 378, 377, 376, 379, 378, 378, 381, 380, 378, 382, 381, 383, 385, 384, 383, 386, 385, 387, 389, 388, 387, 390, 389, 391, 393, 392, 391, 394, 393, 394, 388, 393, 394, 387, 388, 395, 392, 396, 395, 391, 392, 393, 398, 397, 393, 388, 398, 396, 400, 399, 396, 392, 400, 401, 403, 402, 401, 404, 403, 388, 405, 398, 388, 389, 405, 392, 397, 400, 392, 393, 397, 404, 406, 403, 404, 407, 406, 407, 399, 406, 407, 396, 399, 389, 402, 405, 389, 401, 402, 403, 406, 408, 406, 399, 408, 405, 402, 408, 397, 398, 409, 399, 409, 408, 399, 400, 409, 402, 403, 408, 398, 408, 409, 398, 405, 408, 400, 397, 409, 410, 407, 404, 410, 411, 407, 411, 396, 407, 411, 395, 396, 412, 404, 401, 412, 410, 404, 390, 401, 389, 390, 412, 401, 413, 415, 414, 413, 416, 415, 417, 419, 418, 417, 420, 419, 421, 417, 422, 421, 423, 417, 423, 420, 417, 423, 424, 420, 425, 422, 426, 425, 421, 422, 424, 427, 420, 424, 428, 427, 429, 426, 416, 429, 425, 426, 428, 430, 427, 428, 431, 430, 432, 416, 413, 432, 429, 416, 433, 435, 434, 433, 436, 435, 437, 439, 438, 437, 440, 439, 441, 443, 442, 441, 434, 443, 444, 446, 445, 444, 447, 446, 448, 450, 449, 448, 445, 450, 445, 451, 450, 445, 446, 451, 449, 450, 452, 450, 451, 452, 451, 453, 452, 416, 426, 415, 424, 455, 454, 424, 423, 455, 428, 454, 456, 428, 424, 454, 431, 413, 430, 431, 432, 413, 457, 383, 458, 457, 459, 383, 379, 382, 378, 379, 460, 382, 461, 377, 462, 461, 376, 377, 459, 386, 383, 459, 463, 386, 460, 458, 382, 460, 457, 458, 463, 464, 386, 463, 465, 464, 465, 462, 464, 465, 461, 462, 377, 380, 466, 377, 378, 380, 386, 467, 385, 386, 464, 467, 464, 468, 467, 464, 462, 468, 458, 384, 469, 458, 383, 384, 462, 466, 468, 462, 377, 466, 382, 469, 381, 382, 458, 469, 384, 471, 470, 384, 385, 471, 385, 472, 471, 385, 467, 472, 467, 473, 472, 467, 468, 473, 469, 470, 474, 469, 384, 470, 381, 474, 475, 381, 469, 474, 468, 476, 473, 468, 466, 476, 466, 477, 476, 466, 380, 477, 380, 475, 477, 380, 381, 475, 430, 414, 478, 430, 413, 414, 420, 479, 419, 420, 427, 479, 422, 418, 480, 422, 417, 418, 427, 478, 479, 427, 430, 478, 481, 483, 482, 481, 484, 483, 485, 482, 440, 485, 481, 482, 484, 486, 483, 484, 487, 486, 488, 440, 437, 488, 485, 440, 489, 434, 441, 489, 433, 434, 436, 437, 435, 436, 488, 437, 487, 441, 486, 487, 489, 441, 483, 456, 454, 483, 486, 456, 440, 455, 439, 440, 482, 455, 486, 442, 456, 486, 441, 442, 435, 438, 490, 435, 437, 438, 434, 490, 443, 434, 435, 490, 482, 454, 455, 482, 483, 454, 447, 491, 446, 447, 492, 491, 493, 448, 494, 493, 495, 448, 495, 445, 448, 495, 444, 445, 494, 449, 496, 494, 448, 449, 446, 453, 451, 446, 491, 453, 496, 449, 452, 426, 480, 415, 426, 422, 480, 443, 429, 432, 443, 490, 429, 432, 442, 443, 432, 431, 442, 423, 439, 455, 423, 421, 439, 425, 490, 438, 425, 429, 490, 456, 431, 428, 456, 442, 431, 438, 421, 425, 438, 439, 421, 497, 499, 498, 497, 500, 499, 414, 415, 500, 497, 478, 500, 478, 414, 500, 415, 480, 500, 492, 494, 491, 492, 493, 494, 496, 491, 494, 496, 453, 491, 453, 496, 452, 501, 503, 502, 501, 504, 503, 505, 507, 506, 505, 508, 507, 506, 510, 509, 506, 507, 510, 509, 504, 501, 509, 510, 504, 511, 506, 512, 511, 505, 506, 513, 502, 514, 513, 501, 502, 515, 501, 513, 515, 509, 501, 512, 509, 515, 512, 506, 509, 516, 518, 517, 516, 519, 518, 519, 520, 518, 519, 521, 520, 521, 522, 520, 521, 523, 522, 524, 514, 525, 524, 513, 514, 523, 526, 522, 523, 527, 526, 528, 513, 524, 528, 515, 513, 527, 529, 526, 527, 530, 529, 531, 515, 528, 531, 512, 515, 532, 512, 531, 532, 511, 512, 533, 517, 534, 533, 516, 517, 518, 536, 535, 518, 520, 536, 520, 537, 536, 520, 522, 537, 522, 538, 537, 522, 526, 538, 526, 539, 538, 526, 529, 539, 534, 541, 540, 534, 517, 541, 517, 535, 541, 517, 518, 535, 538, 543, 542, 538, 539, 543, 536, 545, 544, 536, 537, 545, 535, 544, 546, 535, 536, 544, 541, 546, 547, 541, 535, 546, 537, 542, 545, 537, 538, 542, 540, 547, 548, 540, 541, 547, 540, 508, 505, 540, 548, 508, 502, 543, 539, 502, 503, 543, 534, 505, 511, 534, 540, 505, 514, 539, 529, 514, 502, 539, 533, 511, 532, 533, 534, 511, 525, 529, 530, 525, 514, 529, 549, 192, 550, 549, 191, 192, 551, 553, 552, 551, 554, 553, 198, 555, 200, 198, 552, 555, 556, 558, 557, 556, 559, 558, 552, 560, 555, 552, 553, 560, 550, 206, 561, 550, 192, 206, 553, 557, 560, 553, 556, 557, 559, 561, 558, 559, 550, 561, 561, 208, 562, 561, 206, 208, 563, 565, 564, 563, 566, 565, 555, 568, 567, 555, 560, 568, 558, 562, 569, 558, 561, 562, 217, 570, 220, 217, 571, 570, 572, 223, 573, 572, 222, 223, 560, 574, 568, 560, 557, 574, 557, 569, 574, 557, 558, 569, 566, 573, 575, 566, 572, 573, 563, 572, 566, 200, 567, 227, 200, 555, 567, 570, 229, 230, 570, 576, 229, 573, 231, 232, 573, 223, 231, 576, 234, 229, 576, 577, 234, 575, 232, 235, 575, 573, 232, 220, 230, 236, 220, 570, 230, 577, 235, 234, 577, 575, 235, 578, 568, 574, 578, 579, 568, 567, 579, 571, 567, 568, 579, 571, 227, 567, 571, 217, 227, 572, 569, 562, 572, 563, 569, 562, 222, 572, 562, 208, 222, 574, 563, 578, 574, 569, 563, 571, 579, 570, 570, 579, 580, 570, 580, 576, 581, 583, 582, 584, 245, 585, 584, 244, 245, 247, 586, 250, 247, 587, 586, 588, 253, 589, 588, 252, 253, 590, 592, 591, 590, 582, 592, 258, 593, 261, 258, 594, 593, 595, 589, 596, 595, 588, 589, 582, 597, 592, 582, 583, 597, 581, 585, 583, 581, 584, 585, 583, 598, 597, 583, 585, 598, 594, 591, 593, 594, 590, 591, 596, 600, 599, 596, 589, 600, 601, 599, 602, 601, 596, 599, 250, 603, 271, 250, 586, 603, 589, 272, 600, 589, 253, 272, 588, 597, 598, 588, 595, 597, 587, 261, 593, 587, 247, 261, 591, 592, 604, 593, 605, 587, 593, 591, 605, 598, 252, 588, 598, 275, 252, 592, 595, 606, 592, 597, 595, 585, 275, 598, 585, 245, 275, 271, 607, 278, 271, 603, 607, 575, 609, 608, 575, 577, 609, 566, 608, 565, 566, 575, 608, 578, 564, 610, 578, 563, 564, 577, 611, 609, 577, 576, 611, 579, 610, 612, 579, 578, 610, 606, 595, 613, 613, 595, 601, 601, 595, 596, 587, 605, 586, 586, 605, 614, 586, 614, 615, 586, 616, 603, 586, 615, 616, 615, 617, 616, 616, 617, 601, 616, 601, 602, 606, 619, 618, 606, 613, 619, 605, 621, 620, 605, 604, 621, 604, 618, 621, 604, 606, 618, 604, 605, 591, 592, 606, 604, 508, 622, 507, 508, 623, 622, 504, 624, 503, 504, 625, 624, 510, 625, 504, 510, 626, 625, 507, 626, 510, 507, 622, 626, 546, 628, 627, 546, 544, 628, 544, 629, 628, 544, 545, 629, 545, 630, 629, 545, 542, 630, 542, 631, 630, 542, 543, 631, 548, 633, 632, 548, 547, 633, 547, 627, 633, 547, 546, 627, 305, 306, 634, 308, 309, 635, 636, 638, 637, 548, 623, 508, 548, 632, 623, 503, 631, 543, 503, 624, 631, 314, 639, 317, 314, 640, 639, 317, 641, 319, 317, 639, 641, 635, 643, 642, 635, 644, 643, 634, 323, 645, 634, 306, 323, 644, 645, 643, 644, 634, 645, 308, 642, 325, 308, 635, 642, 646, 647, 305, 648, 650, 649, 648, 649, 646, 646, 634, 644, 644, 648, 646, 648, 644, 635, 646, 305, 634, 309, 651, 635, 651, 648, 635, 638, 649, 650, 637, 638, 650, 554, 556, 553, 554, 652, 556, 653, 550, 559, 653, 549, 550, 334, 552, 198, 334, 551, 552, 652, 559, 556, 652, 653, 559, 580, 612, 654, 580, 579, 612, 336, 594, 258, 336, 655, 594, 655, 590, 594, 655, 656, 590, 656, 582, 590, 656, 581, 582, 603, 657, 607, 603, 616, 657, 599, 659, 658, 599, 600, 659, 616, 660, 657, 616, 602, 660, 602, 658, 660, 602, 599, 658, 600, 343, 659, 600, 272, 343, 615, 662, 661, 615, 614, 662, 576, 654, 611, 576, 580, 654, 617, 661, 663, 617, 615, 661, 601, 663, 664, 601, 617, 663, 613, 664, 619, 613, 601, 664, 614, 620, 662, 614, 605, 620, 665, 319, 641, 665, 348, 319, 665, 666, 348, 665, 667, 666, 665, 668, 667, 665, 353, 668, 651, 353, 665, 309, 353, 651, 669, 671, 670, 669, 672, 671, 670, 674, 673, 670, 671, 674, 669, 675, 672, 669, 676, 675, 640, 673, 674, 362, 673, 640, 362, 640, 314, 676, 637, 675, 676, 677, 637, 637, 677, 636, 636, 677, 678, 365, 305, 677, 678, 677, 647, 647, 677, 305 </int_array>
- </array>
- </dictionary>
- <dictionary name="surfaces/1" shared="false">
- <string> "alphasort" </string>
- <bool> False </bool>
- <string> "material" </string>
- <resource resource_type="Material" path="local://4"> </resource>
- <string> "morph_arrays" </string>
- <array len="0" shared="false">
- </array>
- <string> "primitive" </string>
- <int> 4 </int>
- <string> "arrays" </string>
- <array len="9" shared="false">
- <vector3_array len="625"> 0.23068, 6.41266, 0.879344, 0.754113, 6.74074, 0.551263, 0.754113, 6.81344, 0.551263, 0.23068, 6.48536, 0.879344, 0.845318, 6.86083, 0.103095, 0.845318, 6.93353, 0.103095, 0.754113, 6.74074, -0.345078, 0.754113, 6.81344, -0.345078, 0, 6.36123, 0.969121, 0.257165, 6.36123, 0.969121, 0, 6.41266, 0.879344, 0, 6.36123, -0.762936, 0, 6.41266, -0.673159, 0.23068, 6.41266, -0.673159, 0.257165, 6.36123, -0.762936, 0.23068, 6.48536, -0.673159, 0.2607, 6.45948, -0.774594, 0.852531, 6.83043, -0.403642, 0, 6.48536, -0.673159, 0, 6.48536, 0.879344, 0.955654, 6.96621, 0.103096, 0.852531, 6.83043, 0.609826, 0.2607, 6.45948, 0.980779, 0, 6.45948, -0.774594, 0, 6.45948, 0.980779, 0.144337, 4.62833, -0.267808, 0.227645, 4.56054, -0.149869, 0.230474, 4.54553, -0.1645, 0.145367, 4.61509, -0.285537, 0, 4.66573, -0.327684, 0, 4.65348, -0.346986, 0.16781, 4.49143, -0.0124773, 0.169802, 4.47494, -0.0244043, 2.39441, 2.7167, -0.284614, 2.22321, 2.52508, -0.185319, 2.22875, 2.57563, -0.151192, 2.37464, 2.73891, -0.235805, 0.829811, 0.39491, 0.192334, 0.539954, 0.53255, 0.320534, 0.53677, 0.505704, 0.45924, 0.823707, 0.343455, 0.299719, 0.251731, 0.393841, 0.202075, 0.245627, 0.342385, 0.30946, 2.37016, 3.14596, -0.180206, 2.39069, 3.24439, 0.0703977, 2.51365, 3.10316, 0.122743, 2.49324, 3.00574, -0.125365, 2.02679, 2.71357, 0.205928, 2.02114, 2.64141, -0.071524, 2.14773, 2.50612, -0.0177825, 2.15324, 2.5776, 0.25697, 0.197471, 4.75418, 0.019584, 0.212301, 4.88556, 0.0356146, 0, 4.86123, 0.103096, 0, 4.72999, 0.114516, 2.55604, 3.1449, 0.136694, 2.53359, 3.02984, -0.15501, 2.38915, 3.19439, -0.219368, 2.41174, 3.31063, 0.0752657, 2.13459, 2.5274, 0.293671, 2.28993, 2.80163, 0.457827, 2.27149, 2.82221, 0.391821, 2.44682, 3.07552, 0.376618, 2.41931, 3.04467, 0.327652, 1.98619, 2.68696, 0.233771, 1.97806, 2.60303, -0.0912834, 2.12663, 2.44425, -0.0282163, 2.24859, 2.87814, -0.35026, 2.25039, 2.87648, -0.291744, 2.07568, 2.68462, -0.249978, 2.10304, 2.71157, -0.20629, 2.30152, 3.24052, 0.317542, 2.29549, 3.18528, 0.277312, 2.14291, 2.96404, 0.3995, 2.1462, 2.9606, 0.342119, 1.31621, 3.39795, -0.203802, 1.35829, 3.43387, -0.29479, 1.54119, 3.29007, -0.372791, 1.48496, 3.24915, -0.287145, 0.552121, 0.665123, 0.401021, 0.154027, 0.441809, 0.19622, 0.944465, 0.443271, 0.182901, 0.0964089, 0.00104547, -0.196812, 0.19633, 0.00104547, -0.176104, 0.835003, 0.00104547, -0.205403, 0.736495, 0.00104547, -0.182387, 0.108829, 0.00104547, 0.040049, 0.85902, 0.00104547, 0.0313234, 0.0508581, 0.00104547, 0.0402964, 0.207486, 0.384965, 0.351051, 0.874277, 0.386199, 0.339815, 0.916171, 0.00104547, 0.0302318, 0.543306, 0.573346, 0.523815, 0.158656, 2.88784, -0.132794, 0.242974, 2.8226, -0.0472403, 0.228589, 2.63923, -0.0490058, 0.149215, 2.70638, -0.125392, 0.241672, 4.68094, -0.138747, 0.158365, 4.73746, -0.261278, 0, 4.76911, -0.32375, 0.18264, 4.62281, 0.00355331, 0, 4.46751, 0.137356, 0, 4.44976, 0.12846, 1.6, 5.86123, 0.903096, 1.6, 5.46123, 0.795916, 1.6, 5.42123, 0.865198, 1.6, 5.86123, 0.983096, 1.6, 5.16841, 0.503096, 1.6, 5.09913, 0.543096, 1.6, 5.06123, 0.103096, 1.6, 4.98123, 0.103096, 1.6, 5.46123, -0.589731, 1.6, 5.42123, -0.659013, 1.6, 5.09912, -0.336911, 1.6, 5.16841, -0.296911, 1.6, 5.86123, -0.696911, 1.6, 5.86123, -0.776911, 1.6, 6.26123, -0.589731, 1.6, 6.30123, -0.659013, 1.6, 6.55405, -0.296911, 1.6, 6.62333, -0.336911, 1.15486, 6.36123, 0.969121, 0.685695, 6.36123, 0.969121, 0.765488, 6.24202, 0.864397, 1.07507, 6.24202, 0.864397, 1.2072, 6.11123, 1.03611, 1.10961, 6.07706, 0.908599, 2.0359, 5.66148, 0.449063, 2.0359, 5.51526, 0.30284, 1.90356, 5.8612, 0.10311, 2.0359, 5.46174, 0.103096, 2.0359, 6.20719, 0.30284, 2.0359, 6.06097, 0.449063, 2.0359, 5.51526, -0.0966551, 2.0359, 5.66148, -0.242878, 2.0359, 5.86123, -0.296399, 0, 5.40641, 0.875976, 0, 5.28211, 0.751677, 0.257146, 5.2834, 0.752961, 0.257147, 5.40641, 0.875976, 1.39648, 4.9952, 0.603096, 1.39648, 4.86123, 0.103096, 1.39648, 5.06123, 0.103096, 1.39648, 5.16841, 0.503096, 1.39648, 6.86123, 0.103096, 1.39648, 6.72725, 0.603096, 1.39648, 6.55405, 0.503096, 1.39648, 6.66123, 0.103096, 1.39648, 6.36123, 0.969121, 1.39648, 6.26123, 0.795916, 1.39648, 5.86123, 1.1031, 1.39648, 5.86123, 0.903096, 1.39648, 5.36123, 0.969121, 1.39648, 5.46123, 0.795916, 1.6, 6.66123, 0.103096, 1.6, 6.55405, 0.503096, 1.6, 6.62333, 0.543096, 1.6, 6.74123, 0.103096, 1.6, 6.26123, 0.795916, 1.6, 6.30123, 0.865198, 1.39648, 5.36123, -0.762936, 1.39648, 5.46123, -0.589731, 1.39648, 5.16841, -0.296911, 1.39648, 4.9952, -0.396911, 1.39648, 5.86123, -0.896911, 1.39648, 5.86123, -0.696911, 1.39648, 6.36123, -0.762936, 1.39648, 6.26123, -0.589731, 1.39648, 6.72725, -0.396911, 1.39648, 6.55405, -0.296911, 0.73095, 6.07706, 0.908599, 0.765488, 5.9121, 0.9528, 1.07507, 5.9121, 0.9528, 1.10961, 6.07706, 0.908599, 0.765488, 6.24202, 0.864397, 1.07507, 6.24202, 0.864397, 0.685695, 5.86123, 1.1031, 1.15486, 5.86123, 1.1031, 1.07507, 5.9121, 0.9528, 0.765488, 5.9121, 0.9528, 0.633352, 6.11123, 1.03611, 0.73095, 6.07706, 0.908599, 1.39648, 6.66123, 0.103096, 1.39648, 6.55405, 0.503096, 1.6, 6.55405, 0.503096, 1.6, 6.66123, 0.103096, 1.39648, 6.26123, 0.795916, 1.6, 6.26123, 0.795916, 1.39648, 5.86123, 0.903096, 1.6, 5.86123, 0.903096, 1.39648, 5.46123, 0.795916, 1.6, 5.46123, 0.795916, 1.39648, 5.16841, 0.503096, 1.6, 5.16841, 0.503096, 1.39648, 5.06123, 0.103096, 1.6, 5.06123, 0.103096, 1.39648, 5.46123, -0.589731, 1.6, 5.46123, -0.589731, 1.6, 5.16841, -0.296911, 1.39648, 5.16841, -0.296911, 1.39648, 5.86123, -0.696911, 1.6, 5.86123, -0.696911, 1.39648, 6.26123, -0.589731, 1.6, 6.26123, -0.589731, 1.39648, 6.55405, -0.296911, 1.6, 6.55405, -0.296911, 2.0359, 5.86123, 0.502584, 2.0359, 6.26072, 0.103096, 2.0359, 6.06097, -0.242878, 2.0359, 6.20719, -0.0966551, 0, 5.49634, 0.900073, 0.257147, 5.49634, 0.900073, 0.252264, 4.53307, -0.191655, 0.153299, 4.61636, -0.336561, 0, 4.66231, -0.410127, 0.198102, 4.44663, -0.00271145, 0, 2.66463, 0.20367, 5.00021e-06, 2.4738, 0.177211, 0.102832, 2.48009, 0.176006, 0.109384, 2.67117, 0.201936, 0.251452, 2.74864, 0.0718984, 0.23657, 2.56168, 0.0584772, 0.181152, 2.70508, 0.146183, 0.170392, 2.51572, 0.125662, 0, 2.91839, -0.164227, 5.00021e-06, 2.73725, -0.153025, 1.35355, 3.45169, -0.0607277, 1.50191, 3.29774, -0.132197, 0.413722, 1.77804, 0.182495, 0.302308, 1.69787, 0.09718, 0.311982, 1.54621, 0.0812291, 0.425773, 1.62639, 0.166544, 0.489091, 1.94399, -0.0482645, 0.542593, 1.87364, 0.112398, 0.55748, 1.72198, 0.0964474, 0.506064, 1.79234, -0.0642154, 0.394125, 1.86374, -0.138546, 0.408718, 1.71209, -0.154497, 0.227335, 1.66351, -0.0137039, 0.23599, 1.51185, -0.0296548, 0.0960235, 4.4178, 0.0939296, 1.5172, 3.69575, -0.311084, 1.54768, 3.76732, -0.167808, 1.71449, 3.62366, -0.198996, 1.70474, 3.5573, -0.353999, 1.43134, 3.52144, -0.355117, 1.62434, 3.38222, -0.419987, 1.436, 3.60537, 0.00285106, 1.57608, 3.45117, -0.0476083, 1.51354, 3.73444, -0.0382403, 1.66072, 3.58429, -0.072422, 0.254872, 1.70456, -0.0798497, 0.256767, 1.56023, -0.0958005, 0.288751, 1.77481, -0.152552, 0.300707, 1.62315, -0.168503, 0, 4.41627, 0.145479, 0.841135, 6.72725, 0.603096, 0.841135, 6.72725, -0.396911, 0.942888, 6.86123, 0.103096, -0.23068, 6.41266, 0.879344, -0.23068, 6.48536, 0.879344, -0.754113, 6.81344, 0.551263, -0.754113, 6.74074, 0.551263, -0.845318, 6.93353, 0.103095, -0.845318, 6.86083, 0.103095, -0.754113, 6.74074, -0.345078, -0.754113, 6.81344, -0.345078, -0.257165, 6.36123, 0.969121, -0.257165, 6.36123, -0.762936, -0.23068, 6.41266, -0.673159, -0.23068, 6.48536, -0.673159, -0.852531, 6.83043, -0.403642, -0.2607, 6.45948, -0.774594, -0.852531, 6.83043, 0.609826, -0.955654, 6.96621, 0.103096, -0.2607, 6.45948, 0.980779, -0.144337, 4.62833, -0.267808, -0.145367, 4.61509, -0.285537, -0.230474, 4.54553, -0.1645, -0.227645, 4.56054, -0.149869, -0.169802, 4.47494, -0.0244043, -0.16781, 4.49143, -0.0124773, -2.39441, 2.7167, -0.284614, -2.37464, 2.73891, -0.235805, -2.22875, 2.57563, -0.151192, -2.22321, 2.52508, -0.185319, -0.829811, 0.39491, 0.192334, -0.823707, 0.343455, 0.299719, -0.53677, 0.505704, 0.45924, -0.539954, 0.53255, 0.320534, -0.245627, 0.342385, 0.30946, -0.251731, 0.393841, 0.202075, -2.37016, 3.14596, -0.180206, -2.49324, 3.00574, -0.125365, -2.51365, 3.10316, 0.122743, -2.39069, 3.24439, 0.0703977, -2.02679, 2.71357, 0.205928, -2.15324, 2.5776, 0.25697, -2.14773, 2.50612, -0.0177825, -2.02114, 2.64141, -0.071524, -0.197471, 4.75418, 0.019584, -0.212301, 4.88556, 0.0356146, -2.55604, 3.1449, 0.136694, -2.53359, 3.02984, -0.15501, -2.38915, 3.19439, -0.219368, -2.41174, 3.31063, 0.0752657, -2.13459, 2.5274, 0.293671, -2.27149, 2.82221, 0.391821, -2.28993, 2.80163, 0.457827, -2.44682, 3.07552, 0.376618, -2.41931, 3.04467, 0.327652, -1.98619, 2.68696, 0.233771, -1.97806, 2.60303, -0.0912834, -2.12663, 2.44425, -0.0282163, -2.24859, 2.87814, -0.35026, -2.25039, 2.87648, -0.291744, -2.07568, 2.68462, -0.249978, -2.10304, 2.71157, -0.20629, -2.29549, 3.18528, 0.277312, -2.30152, 3.24052, 0.317542, -2.1462, 2.9606, 0.342119, -2.14291, 2.96404, 0.3995, -1.31621, 3.39795, -0.203802, -1.48496, 3.24915, -0.287145, -1.54119, 3.29007, -0.372791, -1.35829, 3.43387, -0.29479, -0.552121, 0.665123, 0.401021, -0.154027, 0.441809, 0.19622, -0.944465, 0.443271, 0.182901, -0.19633, 0.00104547, -0.176104, -0.0964089, 0.00104547, -0.196812, -0.835003, 0.00104547, -0.205403, -0.736495, 0.00104547, -0.182387, -0.108829, 0.00104547, 0.040049, -0.85902, 0.00104547, 0.0313234, -0.207486, 0.384965, 0.351051, -0.0508581, 0.00104547, 0.0402964, -0.916171, 0.00104547, 0.0302318, -0.874277, 0.386199, 0.339815, -0.543306, 0.573346, 0.523815, -0.158656, 2.88784, -0.132794, -0.149215, 2.70638, -0.125392, -0.228589, 2.63923, -0.0490058, -0.242974, 2.8226, -0.0472403, -0.241672, 4.68094, -0.138747, -0.158365, 4.73746, -0.261278, -0.18264, 4.62281, 0.00355331, -1.6, 5.86123, 0.903096, -1.6, 5.86123, 0.983096, -1.6, 5.42123, 0.865198, -1.6, 5.46123, 0.795916, -1.6, 5.09913, 0.543096, -1.6, 5.16841, 0.503096, -1.6, 4.98123, 0.103096, -1.6, 5.06123, 0.103096, -1.6, 5.46123, -0.589731, -1.6, 5.16841, -0.296911, -1.6, 5.09912, -0.336911, -1.6, 5.42123, -0.659013, -1.6, 5.86123, -0.696911, -1.6, 5.86123, -0.776911, -1.6, 6.26123, -0.589731, -1.6, 6.30123, -0.659013, -1.6, 6.55405, -0.296911, -1.6, 6.62333, -0.336911, -1.15486, 6.36123, 0.969121, -1.07507, 6.24202, 0.864397, -0.765488, 6.24202, 0.864397, -0.685695, 6.36123, 0.969121, -1.2072, 6.11123, 1.03611, -1.10961, 6.07706, 0.908599, -2.0359, 5.66148, 0.449063, -1.90356, 5.8612, 0.10311, -2.0359, 5.51526, 0.30284, -2.0359, 5.46174, 0.103096, -2.0359, 6.20719, 0.30284, -2.0359, 6.06097, 0.449063, -2.0359, 5.51526, -0.0966551, -2.0359, 5.66148, -0.242878, -2.0359, 5.86123, -0.296399, -0.257147, 5.40641, 0.875976, -0.257146, 5.2834, 0.752961, -1.39648, 4.9952, 0.603096, -1.39648, 5.16841, 0.503096, -1.39648, 5.06123, 0.103096, -1.39648, 4.86123, 0.103096, -1.39648, 6.86123, 0.103096, -1.39648, 6.66123, 0.103096, -1.39648, 6.55405, 0.503096, -1.39648, 6.72725, 0.603096, -1.39648, 6.26123, 0.795916, -1.39648, 6.36123, 0.969121, -1.39648, 5.86123, 0.903096, -1.39648, 5.86123, 1.1031, -1.39648, 5.46123, 0.795916, -1.39648, 5.36123, 0.969121, -1.6, 6.66123, 0.103096, -1.6, 6.74123, 0.103096, -1.6, 6.62333, 0.543096, -1.6, 6.55405, 0.503096, -1.6, 6.30123, 0.865198, -1.6, 6.26123, 0.795916, -1.39648, 5.36123, -0.762936, -1.39648, 4.9952, -0.396911, -1.39648, 5.16841, -0.296911, -1.39648, 5.46123, -0.589731, -1.39648, 5.86123, -0.896911, -1.39648, 5.86123, -0.696911, -1.39648, 6.36123, -0.762936, -1.39648, 6.26123, -0.589731, -1.39648, 6.72725, -0.396911, -1.39648, 6.55405, -0.296911, -0.73095, 6.07706, 0.908599, -1.10961, 6.07706, 0.908599, -1.07507, 5.9121, 0.9528, -0.765488, 5.9121, 0.9528, -0.765488, 6.24202, 0.864397, -1.07507, 6.24202, 0.864397, -0.685695, 5.86123, 1.1031, -0.765488, 5.9121, 0.9528, -1.07507, 5.9121, 0.9528, -1.15486, 5.86123, 1.1031, -0.633352, 6.11123, 1.03611, -0.73095, 6.07706, 0.908599, -1.39648, 6.66123, 0.103096, -1.6, 6.66123, 0.103096, -1.6, 6.55405, 0.503096, -1.39648, 6.55405, 0.503096, -1.6, 6.26123, 0.795916, -1.39648, 6.26123, 0.795916, -1.6, 5.86123, 0.903096, -1.39648, 5.86123, 0.903096, -1.6, 5.46123, 0.795916, -1.39648, 5.46123, 0.795916, -1.6, 5.16841, 0.503096, -1.39648, 5.16841, 0.503096, -1.6, 5.06123, 0.103096, -1.39648, 5.06123, 0.103096, -1.39648, 5.46123, -0.589731, -1.39648, 5.16841, -0.296911, -1.6, 5.16841, -0.296911, -1.6, 5.46123, -0.589731, -1.39648, 5.86123, -0.696911, -1.6, 5.86123, -0.696911, -1.39648, 6.26123, -0.589731, -1.6, 6.26123, -0.589731, -1.39648, 6.55405, -0.296911, -1.6, 6.55405, -0.296911, -2.0359, 5.86123, 0.502584, -2.0359, 6.26072, 0.103096, -2.0359, 6.06097, -0.242878, -2.0359, 6.20719, -0.0966551, -0.257147, 5.49634, 0.900073, -0.153299, 4.61636, -0.336561, -0.252264, 4.53307, -0.191655, -0.198102, 4.44663, -0.00271145, -0.109384, 2.67117, 0.201936, -0.102832, 2.48009, 0.176006, -0.251452, 2.74864, 0.0718984, -0.23657, 2.56168, 0.0584772, -0.181152, 2.70508, 0.146183, -0.170392, 2.51572, 0.125662, -1.35355, 3.45169, -0.0607277, -1.50191, 3.29774, -0.132197, -0.413722, 1.77804, 0.182495, -0.425773, 1.62639, 0.166544, -0.311982, 1.54621, 0.0812291, -0.302308, 1.69787, 0.09718, -0.489091, 1.94399, -0.0482645, -0.506064, 1.79234, -0.0642154, -0.55748, 1.72198, 0.0964474, -0.542593, 1.87364, 0.112398, -0.394125, 1.86374, -0.138546, -0.408718, 1.71209, -0.154497, -0.23599, 1.51185, -0.0296548, -0.227335, 1.66351, -0.0137039, -0.0960235, 4.4178, 0.0939296, -1.5172, 3.69575, -0.311084, -1.70474, 3.5573, -0.353999, -1.71449, 3.62366, -0.198996, -1.54768, 3.76732, -0.167808, -1.62434, 3.38222, -0.419987, -1.43134, 3.52144, -0.355117, -1.436, 3.60537, 0.00285106, -1.57608, 3.45117, -0.0476083, -1.66072, 3.58429, -0.072422, -1.51354, 3.73444, -0.0382403, -0.256767, 1.56023, -0.0958005, -0.254872, 1.70456, -0.0798497, -0.288751, 1.77481, -0.152552, -0.300707, 1.62315, -0.168503, -0.841135, 6.72725, 0.603096, -0.841135, 6.72725, -0.396911, -0.942888, 6.86123, 0.103096, 0.177538, 3.25078, -0.147598, 0.271744, 3.18932, -0.0437093, 0.257359, 3.00596, -0.0454748, 0.168097, 3.06931, -0.140196, 0, 3.04628, 0.256587, 0, 2.85545, 0.230128, 0.115936, 2.86226, 0.227866, 0.122488, 3.05335, 0.253795, 0.281216, 3.12258, 0.0987407, 0.266334, 2.93561, 0.0853195, 0.202672, 3.0838, 0.187225, 0.191912, 2.89444, 0.166704, 0, 3.28068, -0.186631, 0, 3.09954, -0.175429, -0.177538, 3.25078, -0.147598, -0.168097, 3.06931, -0.140196, -0.257359, 3.00596, -0.0454748, -0.271744, 3.18932, -0.0437093, -0.122488, 3.05335, 0.253795, -0.115936, 2.86226, 0.227866, -0.281216, 3.12258, 0.0987407, -0.266334, 2.93561, 0.0853195, -0.202672, 3.0838, 0.187225, -0.191912, 2.89444, 0.166704, 0, 4.59875, 0.125936, 0.269727, 4.92174, -0.116503, 0.2557, 4.80134, -0.127625, 0.172392, 4.8466, -0.254748, 0.18642, 4.95573, -0.248219, 0, 4.87249, -0.319817, 0, 4.97587, -0.315884, -0.269727, 4.92174, -0.116503, -0.18642, 4.95573, -0.248219, -0.172392, 4.8466, -0.254748, -0.2557, 4.80134, -0.127625, -0.809978, 3.84435, 0.0462258, -0.978723, 3.69555, -0.0371168, -0.992485, 3.72148, -0.13879, -0.809584, 3.86528, -0.0607897, -1.14747, 3.54675, -0.120459, -1.17539, 3.57767, -0.21679, -0.908494, 3.91354, 0.153681, -1.05685, 3.75959, 0.0822117, -1.2052, 3.60564, 0.010742, -0.954611, 4.1111, -0.182336, -1.14214, 3.97265, -0.225252, -1.21405, 4.05463, -0.105431, -1.04723, 4.19828, -0.0742428, -1.32967, 3.8342, -0.268168, -1.38086, 3.91097, -0.136619, -1.04535, 3.79989, -0.225379, -0.85235, 3.93911, -0.160509, -1.23834, 3.66066, -0.290248, -1.01577, 4.06798, 0.154229, -1.15585, 3.91378, 0.10377, -1.29593, 3.75958, 0.0533104, -1.21917, 4.03474, 0.0301233, -1.07199, 4.18489, 0.0643051, -1.36635, 3.88459, -0.00405846, 0.809978, 3.84435, 0.0462258, 0.809584, 3.86528, -0.0607897, 0.992485, 3.72148, -0.13879, 0.978723, 3.69555, -0.0371168, 1.17539, 3.57767, -0.21679, 1.14747, 3.54675, -0.120459, 0.908494, 3.91354, 0.153681, 1.05685, 3.75959, 0.0822117, 1.2052, 3.60564, 0.010742, 0.954611, 4.1111, -0.182336, 1.04723, 4.19828, -0.0742428, 1.21405, 4.05463, -0.105431, 1.14214, 3.97265, -0.225252, 1.38086, 3.91097, -0.136619, 1.32967, 3.8342, -0.268168, 0.85235, 3.93911, -0.160509, 1.04535, 3.79989, -0.225379, 1.23834, 3.66066, -0.290248, 1.01577, 4.06798, 0.154229, 1.15585, 3.91378, 0.10377, 1.29593, 3.75958, 0.0533104, 1.07199, 4.18489, 0.0643051, 1.21917, 4.03474, 0.0301233, 1.36635, 3.88459, -0.00405846, 0.377566, 2.23301, 0.230347, 0.273286, 2.15284, 0.145033, 0.28296, 2.00118, 0.129082, 0.389618, 2.08136, 0.214396, 0.292634, 1.84952, 0.113131, 0.40167, 1.9297, 0.198445, 0.438171, 2.39896, -0.000411894, 0.497933, 2.32861, 0.160251, 0.51282, 2.17695, 0.1443, 0.455144, 2.24731, -0.0163628, 0.527707, 2.02529, 0.128349, 0.472118, 2.09565, -0.0323137, 0.350345, 2.31871, -0.0906937, 0.364938, 2.16706, -0.106645, 0.379531, 2.0154, -0.122595, 0.20137, 2.11848, 0.0341487, 0.210025, 1.96682, 0.0181978, 0.21868, 1.81516, 0.00224695, 0.249187, 2.13753, -0.031997, 0.251082, 1.9932, -0.0479479, 0.252977, 1.84888, -0.0638988, 0.252884, 2.22978, -0.1047, 0.26484, 2.07812, -0.12065, 0.276796, 1.92646, -0.136601, -0.377566, 2.23301, 0.230347, -0.389618, 2.08136, 0.214396, -0.28296, 2.00118, 0.129082, -0.273286, 2.15284, 0.145033, -0.40167, 1.9297, 0.198445, -0.292634, 1.84952, 0.113131, -0.438171, 2.39896, -0.000411894, -0.455144, 2.24731, -0.0163628, -0.51282, 2.17695, 0.1443, -0.497933, 2.32861, 0.160251, -0.472118, 2.09565, -0.0323137, -0.527707, 2.02529, 0.128349, -0.350345, 2.31871, -0.0906937, -0.364938, 2.16706, -0.106645, -0.379531, 2.0154, -0.122595, -0.210025, 1.96682, 0.0181978, -0.20137, 2.11848, 0.0341487, -0.21868, 1.81516, 0.00224695, -0.251082, 1.9932, -0.0479479, -0.249187, 2.13753, -0.031997, -0.252977, 1.84888, -0.0638988, -0.252884, 2.22978, -0.1047, -0.26484, 2.07812, -0.12065, -0.276796, 1.92646, -0.136601 </vector3_array>
- <vector3_array len="625"> 0.0360096, 0.589157, 0.807216, 0.379162, 0.648277, 0.660282, 0.710781, -0.701771, 0.0480528, 0.391591, -0.775171, 0.495749, 0.722924, 0.690928, -0, 0.722446, -0.691427, 0, 0.378912, 0.647849, -0.660846, 0.710746, -0.701737, -0.0490515, 0, 0.610678, 0.791879, -0.0350367, 0.578606, 0.814854, 0, 0.501628, 0.865083, 0, 0.610194, -0.792252, 0, 0.501194, -0.865335, 0.0359806, 0.588682, -0.807564, -0.0350082, 0.578135, -0.81519, 0.391397, -0.774786, -0.496503, 0.323297, -0.752692, -0.573527, 0.770859, -0.534596, -0.346386, 0, -0.789191, -0.614148, 0, -0.789675, 0.613525, 0.868674, -0.495384, 0, 0.771126, -0.534781, 0.345505, 0.323483, -0.753124, 0.572855, 0, -0.789191, -0.614148, 0, -0.789675, 0.613525, 0.705688, 0.318859, -0.63272, 0.999838, 0.00999838, 0.0149976, 0.799697, 0.565786, 0.200924, 0.540954, 0.82793, -0.147987, 0, 0.473026, -0.881048, 0, 0.986122, -0.166021, 0.790431, -0.193105, 0.581317, 0.744403, 0.310168, 0.59132, -0.210106, 0.16008, -0.964484, -0.609658, -0.17619, -0.772835, -0.695748, -0.0600646, -0.71577, -0.418461, 0.236261, -0.876967, 0.72763, -0.205178, 0.654566, 0.0120115, 0.213204, 0.976934, -0.0129987, 0.889909, -0.455953, 0.408168, 0.754311, -0.514212, -0.717691, -0.0310299, 0.69567, -0.403281, 0.782544, -0.47433, 0.962114, -0.068008, -0.264031, 0.98219, 0.109021, 0.15303, -0.0740053, 0.995071, -0.0660047, -0.0730215, 0.709209, -0.701207, 0.120177, -0.831221, 0.542797, 0.130096, -0.988732, -0.0740548, -0.9642, -0.11214, -0.240299, -0.953245, 0.0220288, 0.301394, 0.741648, -0.0980857, 0.66358, 0.557506, -0.667605, 0.493448, 0, -0.762778, 0.64666, 0, -0.0440454, 0.99903, 0.0889861, 0.993844, -0.0659897, 0.0490036, 0.723054, -0.689051, 0.897953, 0.117994, -0.423978, 0.920375, 0.351143, 0.17207, -0.901333, -0.16224, 0.401594, -0.618771, 0.285356, 0.731912, -0.721733, 0.300305, 0.623633, -0.242219, 0.80573, 0.54049, -0.400552, 0.758045, 0.514709, -0.0350519, -0.808196, 0.58787, -0.0460378, -0.996819, -0.0650535, -0.891041, -0.346405, -0.293343, 0.6294, -0.428272, -0.648412, 0.728593, -0.433353, -0.530432, 0.267172, -0.820528, -0.505325, 0.35736, -0.806813, -0.470474, 0.622553, 0.221196, 0.750666, 0.819836, -0.00400408, 0.572584, 0.297403, -0.309419, 0.903223, 0.487706, -0.344499, 0.802162, -0.679917, -0.730986, -0.0580783, -0.592431, -0.368268, -0.716522, -0.511638, -0.289361, -0.809009, -0.812045, -0.505651, -0.291375, -0.00700771, -0.117129, 0.993092, -0.674119, -0.252419, 0.694153, 0.797008, -0.304385, 0.521659, -0.753305, -0.654134, 0.0681181, -0.216317, -0.957402, 0.19128, 0.713493, -0.691478, -0.113078, 0.194204, -0.972021, 0.132139, -0.686439, 0.302193, -0.661423, 0.711943, 0.135989, -0.688945, -0.702756, -0.294317, -0.647697, -0.616626, 0.733745, -0.28529, 0.714816, 0.636836, -0.288926, 0.64207, -0.336037, -0.689075, 0.0110026, 0.996233, -0.0860201, 0.456853, -0.0569817, -0.887715, 0.891957, -0.0679967, -0.446978, 0.947519, 0.264145, -0.180099, 0.609974, 0.430981, -0.664971, 0.983744, -0.109971, -0.141963, 0.618615, -0.0169894, -0.785511, 0, 0.0229939, -0.999736, 0.785814, -0.0981016, 0.610633, 0, -0.271413, 0.962463, 0, 0.126129, 0.992014, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -0.167145, 0.336293, 0.926806, 0.168118, 0.336236, 0.926651, 0.327528, -0.185299, 0.926493, -0.326633, -0.185359, 0.926797, -0.401672, 0.237397, 0.884479, -0.493594, 0.225271, 0.840011, 0.984527, -0.0870466, 0.152081, 0.984527, -0.152081, 0.0870466, 1, 0, -0, 0.984551, -0.175098, 0, 0.984377, 0.153059, 0.0870333, 0.984441, 0.0880395, 0.152068, 0.984441, -0.152068, -0.0880395, 0.984377, -0.0870333, -0.153059, 0.984378, 0, -0.176068, 0, -0.499694, 0.866202, 0, -0.0770792, 0.997025, -0.353503, -0.137195, 0.925318, -0.4965, -0.437441, 0.749755, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0.168109, 0.172111, 0.970627, -0.167136, 0.17214, 0.97079, -0.326504, 0.624964, 0.709094, 0.327398, 0.62476, 0.708862, 0.402511, 0.237301, 0.884123, 0.494351, 0.22516, 0.839595, 0.770022, 0.638018, -0, 0.77049, 0.552351, 0.318202, -0.770083, 0.552777, 0.318448, -0.769614, 0.638509, 0, 0.77067, 0.319278, 0.551479, -0.770263, 0.319524, 0.551905, 0.770513, 0, 0.637424, -0.770106, 0, 0.637916, 0.770916, -0.318378, 0.551655, -0.770509, -0.318624, 0.552081, 0.770916, -0.551655, 0.318378, -0.770509, -0.552081, 0.318624, 0.770513, -0.637424, 0, -0.770106, -0.637916, 0, 0.77049, -0.318202, -0.552351, -0.770083, -0.318448, -0.552777, -0.770263, -0.551905, -0.319524, 0.77067, -0.551479, -0.319278, 0.770022, 0, -0.638018, -0.769614, 0, -0.638509, 0.770245, 0.319101, -0.552175, -0.769837, 0.319347, -0.552601, 0.770245, 0.552175, -0.319101, -0.769837, 0.552601, -0.319347, 0.984551, 0, 0.175098, 0.984378, 0.176068, -0, 0.984291, 0.088026, -0.153045, 0.984291, 0.153045, -0.088026, 0, -0.848897, 0.528558, -0.359502, -0.75906, 0.542758, 0.269002, 0.885006, 0.380003, 0.175995, 0.932972, 0.31399, 0, 0.941447, 0.33716, 0.24712, 0.836407, 0.489238, 0, -0.135113, 0.99083, 0, 0.0700382, 0.997544, 0.320359, 0.0650729, 0.945059, 0.353552, -0.136213, 0.925444, 0.952453, -0.0990471, 0.288137, 0.880048, 0.129007, 0.457025, 0.701409, -0.115067, 0.70341, 0.644507, 0.0390307, 0.763601, 0, -0.0550267, -0.998485, 0, 0.542878, -0.839811, -0.285466, -0.616005, 0.734198, -0.764085, -0.38755, 0.515732, -0.0240167, -0.100069, 0.994691, -0.686889, -0.119154, 0.716928, -0.74958, 0.0670519, 0.658509, -0.318438, 0.223307, 0.921266, 0.825985, 0.143997, -0.54499, 0.923944, 0.0519969, 0.378977, 0.455352, 0.602466, 0.655507, 0.565223, 0.681269, -0.465184, 0.342959, 0.132984, -0.929889, -0.0789773, 0.541844, -0.83676, -0.991178, -0.058069, 0.119142, -0.969378, 0.150213, 0.194276, 0.245128, 0.817427, 0.521272, 0.232988, 0.56297, -0.792958, 0.642155, 0.763184, -0.0720174, 0.308094, 0.942288, -0.13104, 0.167052, 0.584181, -0.794246, -0.281137, 0.0480233, -0.958465, -0.160029, 0.076014, -0.984181, 0.184197, -0.152163, 0.97104, -0.409744, 0.0530964, 0.910654, 0.581446, 0.410315, 0.702539, 0.0380266, 0.718502, 0.694485, -0.910035, 0.00700797, -0.414472, -0.943047, 0.164182, -0.289321, -0.529471, 0.0660587, -0.845752, -0.728454, 0.359224, -0.583363, 0, 0.768221, 0.640184, -0.0380063, 0.865143, 0.500083, -0.0379873, 0.86471, -0.500832, -0.001, 1, 0, -0.0350106, 0.589178, 0.807244, -0.390743, -0.775474, 0.495943, -0.710285, -0.70227, 0.048087, -0.378305, 0.648523, 0.660533, -0.721967, -0.691927, 0, -0.722446, 0.691427, 0, -0.378055, 0.648094, -0.661096, -0.71025, -0.702236, -0.0490864, 0.0360365, 0.578586, 0.814825, 0.0360071, 0.578114, -0.815161, -0.0349823, 0.588703, -0.807592, -0.390549, -0.775089, -0.496698, -0.770452, -0.535009, -0.346654, -0.322401, -0.752935, -0.573713, -0.77072, -0.535194, 0.345772, -0.868428, -0.495815, 0, -0.322586, -0.753368, 0.57304, -0.705185, 0.319084, -0.633166, -0.540246, 0.828378, -0.148068, -0.799337, 0.566238, 0.201085, -0.999837, 0.0100084, 0.0150126, -0.743957, 0.310399, 0.591761, -0.790055, -0.193258, 0.581777, 0.211062, 0.160047, -0.964281, 0.419287, 0.236161, -0.876599, 0.696264, -0.0600228, -0.715271, 0.610287, -0.176083, -0.772363, -0.727158, -0.205327, 0.655043, -0.407334, 0.754619, -0.514422, 0.0139984, 0.889897, -0.455947, -0.0110107, 0.213206, 0.976945, 0.404118, 0.782228, -0.474138, 0.718176, -0.0310076, 0.69517, -0.962039, -0.0680735, -0.264285, 0.0740164, 0.709157, -0.701155, 0.0749998, 0.994997, -0.0659998, -0.982154, 0.109128, 0.15318, -0.119189, -0.831321, 0.542862, 0.953337, 0.0220078, 0.301106, 0.96427, -0.112031, -0.240067, -0.129112, -0.98886, -0.0740644, -0.741197, -0.0981585, 0.664072, -0.556815, -0.667978, 0.493723, -0.087994, 0.993932, -0.0659955, -0.0480059, 0.723089, -0.689085, -0.897759, 0.1181, -0.424359, -0.920222, 0.351467, 0.172229, 0.90152, -0.162094, 0.401232, 0.722212, 0.300088, 0.623183, 0.619388, 0.285179, 0.731458, 0.243161, 0.805534, 0.540358, 0.401392, 0.757741, 0.514503, 0.0360521, -0.808167, 0.587849, 0.0470365, -0.996773, -0.0650504, 0.891247, -0.346096, -0.293081, -0.628795, -0.428542, -0.648821, -0.728123, -0.433669, -0.530819, -0.266242, -0.820747, -0.50546, -0.356487, -0.807102, -0.470642, -0.819508, -0.00400737, 0.573054, -0.621939, 0.221334, 0.751134, -0.486942, -0.344667, 0.802553, -0.296489, -0.309511, 0.903492, 0.680455, -0.730488, -0.0580388, 0.812386, -0.50524, -0.291138, 0.512377, -0.289213, -0.808595, 0.59308, -0.36805, -0.716097, 0.00800875, -0.117128, 0.993085, 0.674665, -0.252249, 0.693684, -0.796642, -0.304628, 0.522076, 0.217271, -0.957194, 0.191239, 0.753738, -0.65364, 0.0680667, -0.713001, -0.691972, -0.113159, -0.19324, -0.972209, 0.132164, 0.686968, 0.301986, -0.660969, -0.711449, 0.136086, -0.689435, 0.617246, 0.733292, -0.285114, 0.703262, -0.29411, -0.647241, -0.641482, -0.336253, -0.689518, -0.714327, 0.637291, -0.289132, -0.0100024, 0.996243, -0.086021, -0.456062, -0.0570077, -0.88812, -0.609345, 0.431244, -0.665377, -0.947416, 0.264395, -0.18027, -0.891752, -0.0680574, -0.447377, -0.983712, -0.11008, -0.142103, -0.617997, -0.0169999, -0.785996, -0.785431, -0.0981788, 0.611113, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 0.168118, 0.336236, 0.926651, 0.327528, -0.185299, 0.926493, -0.326633, -0.185359, 0.926797, -0.167145, 0.336293, 0.926806, 0.402511, 0.237301, 0.884123, 0.494351, 0.22516, 0.839595, -0.984497, -0.0871325, 0.152231, -1, 0, 0, -0.984497, -0.152231, 0.0871325, -0.98452, -0.175271, 0, -0.984346, 0.15321, 0.0871191, -0.98441, 0.0881262, 0.152218, -0.98441, -0.152218, -0.0881262, -0.984346, -0.0871191, -0.15321, -0.984347, 0, -0.176241, 0.497254, -0.437223, 0.749383, 0.354379, -0.137147, 0.92499, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, -0.167136, 0.17214, 0.97079, -0.326504, 0.624964, 0.709094, 0.327398, 0.62476, 0.708862, 0.168109, 0.172111, 0.970627, -0.401672, 0.237397, 0.884479, -0.493594, 0.225271, 0.840011, -0.769614, 0.638509, 0, 0.770022, 0.638018, -0, 0.77049, 0.552351, 0.318202, -0.770083, 0.552777, 0.318448, 0.77067, 0.319278, 0.551479, -0.770263, 0.319524, 0.551905, 0.770513, 0, 0.637424, -0.770106, 0, 0.637916, 0.770916, -0.318378, 0.551655, -0.770509, -0.318624, 0.552081, 0.770916, -0.551655, 0.318378, -0.770509, -0.552081, 0.318624, 0.770513, -0.637424, 0, -0.770106, -0.637916, 0, -0.770083, -0.318448, -0.552777, -0.770263, -0.551905, -0.319524, 0.77067, -0.551479, -0.319278, 0.77049, -0.318202, -0.552351, -0.769614, 0, -0.638509, 0.770022, 0, -0.638018, -0.769837, 0.319347, -0.552601, 0.770245, 0.319101, -0.552175, -0.769837, 0.552601, -0.319347, 0.770245, 0.552175, -0.319101, -0.98452, 0, 0.175271, -0.984347, 0.176241, 0, -0.98426, 0.0881128, -0.153196, -0.98426, 0.153196, -0.0881128, 0.360374, -0.758786, 0.542562, -0.175025, 0.933135, 0.314046, -0.268074, 0.885244, 0.380105, -0.246181, 0.836614, 0.489359, -0.352675, -0.136261, 0.925772, -0.31946, 0.0650937, 0.945361, -0.95236, -0.0991416, 0.288412, -0.879823, 0.129121, 0.457428, -0.7009, -0.115148, 0.703904, -0.643922, 0.0390559, 0.764094, 0.286385, -0.615829, 0.733988, 0.764501, -0.387254, 0.515338, 0.0250168, -0.100067, 0.994666, 0.319337, 0.223236, 0.920972, 0.750018, 0.0670016, 0.658015, 0.687417, -0.119072, 0.716435, -0.825667, 0.144116, -0.54544, -0.564542, 0.681654, -0.465447, -0.454558, 0.60274, 0.655806, -0.923798, 0.0520449, 0.379327, -0.342076, 0.13303, -0.930208, 0.0799707, 0.541802, -0.836693, 0.969438, 0.150068, 0.194088, 0.991195, -0.0580114, 0.119023, -0.244187, 0.817627, 0.5214, -0.232042, 0.563101, -0.793142, -0.166079, 0.584278, -0.794378, -0.307188, 0.942578, -0.13108, -0.641567, 0.763675, -0.0720637, 0.161004, 0.0760018, -0.984023, 0.282058, 0.0480098, -0.958196, -0.18323, -0.152191, 0.971218, 0.410577, 0.0530746, 0.91028, -0.0370272, 0.718529, 0.694511, -0.580783, 0.410554, 0.702948, 0.943158, 0.164027, -0.289048, 0.910207, 0.00700159, -0.414094, 0.530191, 0.0660237, -0.845304, 0.728923, 0.358962, -0.582938, 0.039005, 0.86511, 0.500063, 0.0389854, 0.864677, -0.500813, 0.002, 0.999998, -0, 0.307062, -0.405082, -0.861174, 0.644374, -0.493286, -0.584339, 0.899636, -0.0680481, -0.431305, 0.473063, -0.0580077, -0.879117, 0, -0.746027, 0.665916, 0, -0.135113, 0.99083, 0.361199, -0.136075, 0.922507, 0.355385, -0.786851, 0.504546, 0.758512, -0.647437, -0.07405, 0.952727, -0.0990756, 0.287219, 0.641692, -0.681736, 0.351379, 0.709379, -0.115062, 0.695372, 0, -0.36621, -0.930532, 0, -0.0550267, -0.998485, -0.306156, -0.405206, -0.861439, -0.472286, -0.0580352, -0.879533, -0.899445, -0.0681094, -0.431694, -0.643788, -0.493604, -0.584716, -0.354509, -0.787131, 0.504725, -0.360328, -0.136124, 0.92284, -0.758087, -0.647929, -0.0741063, -0.952635, -0.0991702, 0.287493, -0.641103, -0.682174, 0.351605, -0.708882, -0.115143, 0.695866, 0, -0.0550817, 0.998482, 0.721736, -0.682696, -0.114116, 0.984884, -0.110987, -0.132984, 0.620192, -0.0180056, -0.784243, 0.463983, -0.666975, -0.582978, 0, 0.0239931, -0.999712, 0, -0.812786, -0.582563, -0.721256, -0.68319, -0.114199, -0.463198, -0.667285, -0.583249, -0.619576, -0.0180168, -0.78473, -0.984854, -0.111096, -0.133115, -0.712291, -0.694258, -0.103187, 0.595443, -0.778579, 0.198147, 0.653726, -0.55762, -0.511568, -0.639939, -0.7491, -0.171251, 0.643677, -0.761801, 0.0730768, 0.630288, -0.468214, -0.619283, -0.730652, -0.680607, -0.0540482, 0.116169, -0.506735, 0.854239, 0.201265, -0.563742, 0.801054, -0.905093, -0.411497, -0.107129, -0.0970155, 0.416066, -0.904144, -0.581217, 0.747279, -0.32212, -0.864338, -0.499774, -0.0560868, -0.164974, 0.491923, -0.854866, -0.616439, 0.761542, -0.200142, 0.407071, -0.149026, -0.901157, -0.759004, -0.614813, -0.214283, 0.347173, -0.0500249, -0.936466, -0.848814, -0.528507, -0.0140134, -0.344309, 0.00500449, 0.938843, -0.266308, -0.0730846, 0.961113, -0.669545, 0.542441, 0.507413, -0.833134, -0.540736, -0.116158, -0.62997, 0.48074, 0.609939, 0.712784, -0.693763, -0.103113, 0.64053, -0.74862, -0.171142, -0.653152, -0.557985, -0.511903, -0.594796, -0.779043, 0.198265, -0.629685, -0.46851, -0.619674, -0.64309, -0.762292, 0.0731239, 0.731118, -0.68011, -0.0540087, -0.11518, -0.506794, 0.854338, -0.200304, -0.563855, 0.801215, 0.905274, -0.411124, -0.107032, 0.864591, -0.499341, -0.0560383, 0.581879, 0.746844, -0.321933, 0.0980061, 0.416026, -0.904056, 0.617059, 0.761072, -0.200019, 0.165946, 0.491841, -0.854724, 0.759428, -0.614346, -0.214121, -0.406236, -0.149087, -0.901524, -0.346292, -0.0500423, -0.936791, 0.849093, -0.528058, -0.0140015, 0.345191, 0.00500277, 0.938519, 0.267238, -0.0730651, 0.960857, 0.83344, -0.540285, -0.116061, 0.670096, 0.542078, 0.507073, 0.630574, 0.480437, 0.609555, 0.652602, -0.667616, 0.35833, 0.272405, -0.803194, 0.529788, -0.69805, -0.119179, 0.706062, -0.0250168, -0.100067, 0.994666, -0.692476, -0.119254, 0.711516, -0.0250168, -0.100067, 0.994666, 0.794806, -0.441448, -0.416422, 0.800238, -0.563168, -0.206061, 0.931286, 0.0550169, 0.360111, 0.825985, 0.143997, -0.54499, 0.927789, 0.0530451, 0.369314, 0.825985, 0.143997, -0.54499, 0.823173, -0.419088, -0.383081, 0.35507, 0.134026, -0.925182, 0.348836, 0.133937, -0.927564, 0.241336, -0.969348, -0.0460641, -0.998282, -0.049063, 0.0320411, -0.995768, -0.0530409, 0.0750579, -0.256367, -0.749072, -0.610874, -0.92242, 0.00300137, -0.386176, -0.915525, 0.00500287, -0.402231, 0.679395, -0.526306, -0.511297, -0.621461, 0.0540401, -0.781579, -0.575446, 0.0600465, -0.815632, -0.652026, -0.668052, 0.358564, 0.0260168, -0.100064, 0.994641, 0.698563, -0.119096, 0.705568, -0.271477, -0.803413, 0.529932, 0.0260168, -0.100064, 0.994641, 0.692997, -0.119171, 0.711023, -0.794437, -0.441799, -0.416754, -0.825667, 0.144116, -0.54544, -0.931153, 0.0550682, 0.360446, -0.799878, -0.563619, -0.206226, -0.825667, 0.144116, -0.54544, -0.92765, 0.0530944, 0.369657, -0.82285, -0.419434, -0.383396, -0.354195, 0.134074, -0.925511, -0.347958, 0.133984, -0.927887, 0.998285, -0.049014, 0.0320091, -0.240392, -0.969582, -0.0460752, 0.995776, -0.0529881, 0.0749831, 0.922569, 0.0029986, -0.38582, 0.257302, -0.748879, -0.610717, 0.915686, 0.00499829, -0.401862, -0.678856, -0.526664, -0.511645, 0.622074, 0.0540065, -0.781093, 0.576115, 0.060012, -0.815163 </vector3_array>
- <nil> </nil>
- <nil> </nil>
- <nil> </nil>
- <nil> </nil>
- <real_array len="2500"> 6, 7, 0, 0, 6, 7, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 6, 7, 0, 0, 7, 0, 0, 0, 7, 6, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 7, 0, 0, 6, 7, 0, 0, 6, 7, 0, 0, 6, 7, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 6, 3, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 3, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 8, 9, 3, 0, 8, 9, 3, 0, 8, 9, 0, 0, 8, 9, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 1, 3, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 6, 0, 0, 3, 6, 0, 0, 3, 6, 0, 0, 3, 6, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 8, 9, 3, 0, 8, 9, 0, 0, 12, 13, 1, 0, 12, 13, 1, 0, 12, 13, 0, 0, 12, 13, 0, 0, 12, 13, 1, 0, 12, 13, 1, 0, 12, 13, 0, 0, 12, 13, 0, 0, 12, 13, 1, 0, 12, 13, 0, 0, 12, 13, 1, 0, 12, 13, 0, 0, 3, 0, 0, 0, 8, 9, 3, 0, 8, 9, 3, 0, 8, 9, 0, 0, 9, 8, 0, 0, 9, 8, 3, 0, 9, 8, 0, 0, 9, 8, 3, 0, 9, 8, 0, 0, 8, 9, 3, 0, 8, 9, 0, 0, 12, 13, 1, 0, 12, 13, 0, 0, 12, 13, 1, 0, 12, 13, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 7, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 6, 7, 0, 0, 7, 0, 0, 0, 6, 7, 0, 0, 7, 6, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 7, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 16, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 6, 3, 0, 0, 6, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 10, 11, 3, 0, 10, 11, 0, 0, 10, 11, 0, 0, 10, 11, 3, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0, 3, 6, 0, 0, 3, 6, 0, 0, 3, 6, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 10, 11, 3, 0, 10, 11, 0, 0, 15, 16, 1, 0, 15, 16, 0, 0, 15, 16, 0, 0, 15, 16, 1, 0, 15, 16, 1, 0, 15, 16, 0, 0, 15, 16, 0, 0, 15, 16, 1, 0, 15, 16, 1, 0, 15, 16, 0, 0, 15, 16, 0, 0, 15, 16, 1, 0, 3, 0, 0, 0, 10, 11, 3, 0, 11, 10, 0, 0, 10, 11, 0, 0, 10, 11, 3, 0, 11, 10, 0, 0, 11, 10, 3, 0, 11, 10, 3, 0, 11, 10, 0, 0, 10, 11, 0, 0, 10, 11, 3, 0, 15, 16, 0, 0, 15, 16, 1, 0, 15, 16, 1, 0, 15, 16, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 6, 0, 0, 6, 0, 0, 0, 6, 3, 0, 0, 6, 3, 0, 0, 6, 0, 0, 0, 6, 3, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 3, 0, 0, 6, 3, 0, 0, 3, 0, 0, 0, 3, 10, 11, 0, 3, 10, 11, 0, 3, 0, 0, 0, 3, 10, 11, 0, 3, 10, 11, 0, 3, 0, 0, 0, 3, 10, 11, 0, 3, 10, 11, 0, 3, 0, 0, 0, 3, 10, 11, 0, 3, 10, 11, 0, 3, 0, 0, 0, 3, 11, 10, 0, 3, 10, 11, 0, 3, 11, 10, 0, 3, 0, 0, 0, 3, 11, 10, 0, 3, 0, 0, 0, 3, 11, 10, 0, 3, 11, 10, 0, 3, 10, 11, 0, 3, 0, 0, 0, 3, 10, 11, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 8, 9, 0, 3, 8, 9, 0, 3, 8, 9, 0, 3, 8, 9, 0, 3, 0, 0, 0, 3, 8, 9, 0, 3, 8, 9, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 8, 9, 0, 3, 8, 9, 0, 3, 8, 9, 0, 3, 9, 8, 0, 3, 0, 0, 0, 3, 9, 8, 0, 3, 9, 8, 0, 3, 0, 0, 0, 3, 9, 8, 0, 3, 9, 8, 0, 3, 0, 0, 0, 3, 8, 9, 0, 3, 8, 9, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 12, 0, 0, 12, 1, 13, 0, 12, 1, 13, 0, 1, 0, 0, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 0, 0, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 0, 0, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 0, 0, 0, 1, 15, 16, 0, 1, 15, 16, 0, 1, 0, 0, 0, 1, 15, 16, 0, 1, 15, 16, 0, 1, 0, 0, 0, 1, 15, 16, 0, 1, 15, 16, 0, 1, 0, 0, 0, 1, 15, 16, 0, 1, 15, 16, 0, 1, 15, 0, 0, 15, 1, 16, 0, 15, 1, 16, 0, 1, 15, 16, 0, 1, 0, 0, 0, 1, 15, 16, 0, 1, 15, 16, 0, 1, 0, 0, 0, 1, 15, 16, 0, 1, 0, 0, 0, 1, 15, 16, 0, 1, 15, 16, 0 </real_array>
- <real_array len="2500"> 0.500006, 0.499994, 0, 0, 0.500036, 0.499964, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.508359, 0.491641, 0, 0, 1, 0, 0, 0, 0.500012, 0.499988, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.500137, 0.499863, 0, 0, 0.997415, 0.00258508, 0, 0, 0.5, 0.5, 0, 0, 0.502778, 0.497222, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.439327, 0.339942, 0.220731, 0, 0.397775, 0.362587, 0.239639, 0, 0.523139, 0.476861, 0, 0, 0.563768, 0.436232, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.66667, 0.33333, 0, 0, 1, 0, 0, 0, 0.412375, 0.353797, 0.233829, 0, 0.538228, 0.461772, 0, 0, 0.544073, 0.274503, 0.181424, 0, 0.550005, 0.266658, 0.183337, 0, 0.673479, 0.326521, 0, 0, 0.664658, 0.335342, 0, 0, 0.546797, 0.270935, 0.182268, 0, 0.544673, 0.273746, 0.181581, 0, 0.665519, 0.334481, 0, 0, 0.668675, 0.331325, 0, 0, 0.615652, 0.230199, 0.154149, 0, 0.6672, 0.3328, 0, 0, 0.544198, 0.2744, 0.181402, 0, 0.664792, 0.335208, 0, 0, 1, 0, 0, 0, 0.37581, 0.37581, 0.24838, 0, 0.378779, 0.374023, 0.247199, 0, 0.503159, 0.496841, 0, 0, 0.5, 0.5, 0, 0, 0.399773, 0.361383, 0.238845, 0, 0.525218, 0.474782, 0, 0, 0.409739, 0.358697, 0.231565, 0, 0.533212, 0.466788, 0, 0, 0.375815, 0.375807, 0.248378, 0, 0.500006, 0.499994, 0, 0, 0.56732, 0.24294, 0.18974, 0, 0.700171, 0.299829, 0, 0, 0.544164, 0.274448, 0.181388, 0, 0.66474, 0.33526, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.500006, 0.499994, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.500036, 0.499964, 0, 0, 1, 0, 0, 0, 0.508359, 0.491641, 0, 0, 0.500012, 0.499988, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.502778, 0.497222, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.439327, 0.339942, 0.220731, 0, 0.563768, 0.436232, 0, 0, 0.523139, 0.476861, 0, 0, 0.397775, 0.362587, 0.239639, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.412375, 0.353797, 0.233829, 0, 0.538228, 0.461772, 0, 0, 0.544073, 0.274503, 0.181424, 0, 0.664658, 0.335342, 0, 0, 0.673479, 0.326521, 0, 0, 0.550005, 0.266658, 0.183337, 0, 0.546797, 0.270935, 0.182268, 0, 0.668675, 0.331325, 0, 0, 0.665519, 0.334481, 0, 0, 0.544673, 0.273746, 0.181581, 0, 0.615652, 0.230199, 0.154149, 0, 0.6672, 0.3328, 0, 0, 0.664792, 0.335208, 0, 0, 0.544198, 0.2744, 0.181402, 0, 1, 0, 0, 0, 0.37581, 0.37581, 0.24838, 0, 0.5, 0.5, 0, 0, 0.503159, 0.496841, 0, 0, 0.378779, 0.374023, 0.247199, 0, 0.525218, 0.474782, 0, 0, 0.399773, 0.361383, 0.238845, 0, 0.409739, 0.358697, 0.231565, 0, 0.533212, 0.466788, 0, 0, 0.500006, 0.499994, 0, 0, 0.375815, 0.375807, 0.248378, 0, 0.700171, 0.299829, 0, 0, 0.56732, 0.24294, 0.18974, 0, 0.544164, 0.274448, 0.181388, 0, 0.66474, 0.33526, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666663, 0.333337, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.718253, 0.15884, 0.122907, 0, 0.739344, 0.136359, 0.124296, 0, 1, 0, 0, 0, 0.45939, 0.304779, 0.235832, 0, 0.485992, 0.268898, 0.245111, 0, 1, 0, 0, 0, 0.7331, 0.143653, 0.123247, 0, 0.477963, 0.280975, 0.241062, 0, 1, 0, 0, 0, 0.748373, 0.125813, 0.125813, 0, 0.747178, 0.12721, 0.125612, 0, 1, 0, 0, 0, 0.497836, 0.251082, 0.251082, 0, 0.496251, 0.253466, 0.250283, 0, 0.738503, 0.137343, 0.124154, 0, 1, 0, 0, 0, 0.484902, 0.270539, 0.244559, 0, 1, 0, 0, 0, 0.730612, 0.143641, 0.125747, 0, 0.4748, 0.280042, 0.245157, 0, 0.748371, 0.125816, 0.125813, 0, 1, 0, 0, 0, 0.497833, 0.251086, 0.251081, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.739344, 0.136359, 0.124296, 0, 0.718253, 0.15884, 0.122907, 0, 0.485992, 0.268898, 0.245111, 0, 0.45939, 0.304779, 0.235832, 0, 1, 0, 0, 0, 0.7331, 0.143653, 0.123247, 0, 0.477963, 0.280975, 0.241062, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.747178, 0.12721, 0.125612, 0, 0.748373, 0.125813, 0.125813, 0, 0.496251, 0.253466, 0.250283, 0, 0.497836, 0.251082, 0.251082, 0, 1, 0, 0, 0, 0.738503, 0.137343, 0.124154, 0, 0.484902, 0.270539, 0.244559, 0, 1, 0, 0, 0, 0.730612, 0.143641, 0.125747, 0, 0.4748, 0.280042, 0.245157, 0, 1, 0, 0, 0, 0.748371, 0.125816, 0.125813, 0, 0.497833, 0.251086, 0.251081, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.668925, 0.222972, 0.108103, 0, 0.666077, 0.221944, 0.111978, 0, 0.402445, 0.40244, 0.195114, 0, 0.399364, 0.399217, 0.201418, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666312, 0.222075, 0.111612, 0, 0.667337, 0.222443, 0.110219, 0, 0.399617, 0.399566, 0.200817, 0, 0.400725, 0.40072, 0.198555, 0, 0.500004, 0.499996, 0, 0, 0.533361, 0.40023, 0.0664093, 0, 0.571539, 0.286063, 0.142398, 0, 1, 0, 0, 0, 0.666044, 0.222012, 0.111945, 0, 0.399328, 0.399322, 0.20135, 0, 1, 0, 0, 0, 0.678203, 0.225313, 0.0964842, 0, 0.412634, 0.411257, 0.176109, 0, 1, 0, 0, 0, 0.666023, 0.222008, 0.111969, 0, 0.399306, 0.399306, 0.201389, 0, 1, 0, 0, 0, 0.666077, 0.221944, 0.111978, 0, 0.668925, 0.222972, 0.108103, 0, 1, 0, 0, 0, 0.399364, 0.399217, 0.201418, 0, 0.402445, 0.40244, 0.195114, 0, 1, 0, 0, 0, 0.667337, 0.222443, 0.110219, 0, 0.666312, 0.222075, 0.111612, 0, 1, 0, 0, 0, 0.400725, 0.40072, 0.198555, 0, 0.399617, 0.399566, 0.200817, 0, 0.500004, 0.499996, 0, 0, 0.533361, 0.40023, 0.0664093, 0, 0.571539, 0.286063, 0.142398, 0, 0.666044, 0.222012, 0.111945, 0, 1, 0, 0, 0, 0.399328, 0.399322, 0.20135, 0, 0.678203, 0.225313, 0.0964842, 0, 1, 0, 0, 0, 0.412634, 0.411257, 0.176109, 0, 1, 0, 0, 0, 0.666023, 0.222008, 0.111969, 0, 0.399306, 0.399306, 0.201389, 0 </real_array>
- <int_array len="2502"> 0, 2, 1, 0, 3, 2, 1, 5, 4, 1, 2, 5, 6, 5, 7, 6, 4, 5, 8, 0, 9, 8, 10, 0, 11, 13, 12, 11, 14, 13, 15, 17, 16, 15, 7, 17, 12, 15, 18, 12, 13, 15, 10, 3, 0, 10, 19, 3, 13, 7, 15, 13, 6, 7, 2, 20, 5, 2, 21, 20, 7, 20, 17, 7, 5, 20, 21, 3, 22, 21, 2, 3, 18, 16, 23, 18, 15, 16, 22, 19, 24, 22, 3, 19, 25, 27, 26, 25, 28, 27, 29, 28, 25, 29, 30, 28, 26, 32, 31, 26, 27, 32, 33, 35, 34, 33, 36, 35, 37, 39, 38, 37, 40, 39, 38, 42, 41, 38, 39, 42, 43, 45, 44, 43, 46, 45, 47, 49, 48, 47, 50, 49, 51, 53, 52, 51, 54, 53, 55, 46, 56, 55, 45, 46, 57, 44, 58, 57, 43, 44, 59, 61, 60, 59, 50, 61, 62, 45, 55, 62, 63, 45, 64, 48, 65, 64, 47, 48, 66, 50, 59, 66, 49, 50, 67, 43, 57, 67, 68, 43, 69, 68, 67, 69, 70, 68, 34, 49, 66, 34, 35, 49, 65, 70, 69, 65, 48, 70, 58, 72, 71, 58, 44, 72, 56, 36, 33, 56, 46, 36, 71, 74, 73, 71, 72, 74, 60, 63, 62, 60, 61, 63, 73, 47, 64, 73, 74, 47, 75, 77, 76, 75, 78, 77, 79, 41, 80, 79, 38, 41, 81, 38, 79, 81, 37, 38, 80, 83, 82, 80, 41, 83, 84, 37, 81, 84, 85, 37, 41, 86, 83, 41, 42, 86, 85, 40, 37, 85, 87, 40, 42, 88, 86, 42, 89, 88, 87, 90, 40, 87, 91, 90, 40, 92, 39, 40, 90, 92, 39, 89, 42, 39, 92, 89, 48, 35, 70, 48, 49, 35, 74, 50, 47, 74, 61, 50, 70, 36, 68, 70, 35, 36, 44, 63, 72, 44, 45, 63, 68, 46, 43, 68, 36, 46, 72, 61, 74, 72, 63, 61, 93, 95, 94, 93, 96, 95, 97, 25, 26, 97, 98, 25, 98, 29, 25, 98, 99, 29, 100, 26, 31, 100, 97, 26, 31, 102, 101, 31, 32, 102, 103, 105, 104, 103, 106, 105, 104, 108, 107, 104, 105, 108, 107, 110, 109, 107, 108, 110, 111, 113, 112, 111, 114, 113, 115, 112, 116, 115, 111, 112, 117, 116, 118, 117, 115, 116, 119, 118, 120, 119, 117, 118, 114, 110, 113, 114, 109, 110, 121, 123, 122, 121, 124, 123, 125, 124, 121, 125, 126, 124, 127, 129, 128, 128, 129, 130, 131, 129, 132, 133, 130, 129, 134, 133, 129, 135, 134, 129, 136, 138, 137, 136, 139, 138, 140, 142, 141, 140, 143, 142, 144, 146, 145, 144, 147, 146, 145, 149, 148, 145, 146, 149, 148, 151, 150, 148, 149, 151, 150, 153, 152, 150, 151, 153, 152, 143, 140, 152, 153, 143, 154, 156, 155, 154, 157, 156, 155, 159, 158, 155, 156, 159, 158, 106, 103, 158, 159, 106, 160, 162, 161, 160, 163, 162, 164, 161, 165, 164, 160, 161, 166, 165, 167, 166, 164, 165, 168, 167, 169, 168, 166, 167, 154, 120, 157, 154, 119, 120, 144, 169, 147, 144, 168, 169, 163, 142, 162, 163, 141, 142, 170, 172, 171, 170, 173, 172, 174, 173, 170, 174, 175, 173, 176, 178, 177, 176, 179, 178, 177, 126, 125, 177, 178, 126, 180, 179, 176, 180, 181, 179, 122, 181, 180, 122, 123, 181, 182, 184, 183, 182, 185, 184, 183, 187, 186, 183, 184, 187, 186, 189, 188, 186, 187, 189, 188, 191, 190, 188, 189, 191, 190, 193, 192, 190, 191, 193, 192, 195, 194, 192, 193, 195, 196, 198, 197, 196, 199, 198, 200, 197, 201, 200, 196, 197, 202, 201, 203, 202, 200, 201, 204, 203, 205, 204, 202, 203, 199, 195, 198, 199, 194, 195, 182, 205, 185, 182, 204, 205, 206, 129, 127, 207, 129, 131, 132, 129, 206, 208, 135, 129, 209, 208, 129, 207, 209, 129, 210, 139, 136, 210, 211, 139, 28, 212, 27, 28, 213, 212, 30, 213, 28, 30, 214, 213, 27, 215, 32, 27, 212, 215, 216, 218, 217, 216, 219, 218, 220, 95, 221, 220, 94, 95, 222, 218, 219, 222, 223, 218, 224, 96, 93, 224, 225, 96, 220, 223, 222, 220, 221, 223, 226, 78, 75, 226, 227, 78, 228, 230, 229, 228, 231, 230, 232, 234, 233, 232, 235, 234, 236, 235, 232, 236, 237, 235, 229, 239, 238, 229, 230, 239, 233, 231, 228, 233, 234, 231, 32, 240, 102, 32, 215, 240, 241, 243, 242, 241, 244, 243, 76, 246, 245, 76, 77, 246, 247, 227, 226, 247, 248, 227, 242, 250, 249, 242, 243, 250, 245, 244, 241, 245, 246, 244, 249, 248, 247, 249, 250, 248, 238, 252, 251, 238, 239, 252, 253, 237, 236, 253, 254, 237, 251, 254, 253, 251, 252, 254, 102, 240, 255, 9, 1, 256, 9, 0, 1, 14, 6, 13, 14, 257, 6, 256, 4, 258, 256, 1, 4, 257, 4, 6, 257, 258, 4, 259, 261, 260, 259, 262, 261, 262, 263, 261, 262, 264, 263, 265, 263, 264, 265, 266, 263, 8, 259, 10, 8, 267, 259, 11, 269, 268, 11, 12, 269, 270, 271, 266, 270, 272, 271, 12, 270, 269, 12, 18, 270, 10, 260, 19, 10, 259, 260, 269, 266, 265, 269, 270, 266, 261, 274, 273, 261, 263, 274, 266, 274, 263, 266, 271, 274, 260, 273, 275, 260, 261, 273, 18, 272, 270, 18, 23, 272, 19, 275, 24, 19, 260, 275, 276, 278, 277, 276, 279, 278, 29, 277, 30, 29, 276, 277, 279, 280, 278, 279, 281, 280, 282, 284, 283, 282, 285, 284, 286, 288, 287, 286, 289, 288, 289, 290, 288, 289, 291, 290, 292, 294, 293, 292, 295, 294, 296, 298, 297, 296, 299, 298, 300, 53, 54, 300, 301, 53, 302, 293, 294, 302, 303, 293, 304, 295, 292, 304, 305, 295, 306, 307, 297, 306, 308, 307, 309, 294, 310, 309, 302, 294, 311, 299, 296, 311, 312, 299, 313, 297, 298, 313, 306, 297, 314, 292, 315, 314, 304, 292, 316, 315, 317, 316, 314, 315, 285, 298, 284, 285, 313, 298, 312, 317, 299, 312, 316, 317, 305, 318, 295, 305, 319, 318, 303, 283, 293, 303, 282, 283, 319, 320, 318, 319, 321, 320, 308, 310, 307, 308, 309, 310, 321, 296, 320, 321, 311, 296, 322, 324, 323, 322, 325, 324, 326, 291, 289, 326, 327, 291, 328, 289, 286, 328, 326, 289, 327, 329, 291, 327, 330, 329, 331, 286, 332, 331, 328, 286, 291, 333, 290, 291, 329, 333, 332, 287, 334, 332, 286, 287, 290, 336, 335, 290, 333, 336, 334, 338, 337, 334, 287, 338, 287, 339, 338, 287, 288, 339, 288, 335, 339, 288, 290, 335, 299, 284, 298, 299, 317, 284, 320, 297, 307, 320, 296, 297, 317, 283, 284, 317, 315, 283, 295, 310, 294, 295, 318, 310, 315, 293, 283, 315, 292, 293, 318, 307, 310, 318, 320, 307, 340, 342, 341, 340, 343, 342, 344, 276, 345, 344, 279, 276, 345, 29, 99, 345, 276, 29, 346, 279, 344, 346, 281, 279, 281, 102, 280, 281, 101, 102, 347, 349, 348, 347, 350, 349, 350, 351, 349, 350, 352, 351, 352, 353, 351, 352, 354, 353, 355, 357, 356, 355, 358, 357, 359, 358, 355, 359, 360, 358, 361, 360, 359, 361, 362, 360, 363, 362, 361, 363, 364, 362, 356, 353, 354, 356, 357, 353, 365, 367, 366, 365, 368, 367, 369, 366, 370, 369, 365, 366, 371, 373, 372, 373, 374, 372, 375, 376, 372, 377, 372, 374, 378, 372, 377, 379, 372, 378, 136, 381, 380, 136, 137, 381, 382, 384, 383, 382, 385, 384, 386, 388, 387, 386, 389, 388, 389, 390, 388, 389, 391, 390, 391, 392, 390, 391, 393, 392, 393, 394, 392, 393, 395, 394, 395, 383, 394, 395, 382, 383, 396, 398, 397, 396, 399, 398, 399, 400, 398, 399, 401, 400, 401, 348, 400, 401, 347, 348, 402, 404, 403, 402, 405, 404, 406, 405, 402, 406, 407, 405, 408, 407, 406, 408, 409, 407, 410, 409, 408, 410, 411, 409, 396, 364, 363, 396, 397, 364, 386, 411, 410, 386, 387, 411, 403, 384, 385, 403, 404, 384, 412, 414, 413, 412, 415, 414, 416, 413, 417, 416, 412, 413, 418, 420, 419, 418, 421, 420, 421, 370, 420, 421, 369, 370, 422, 419, 423, 422, 418, 419, 368, 423, 367, 368, 422, 423, 424, 426, 425, 424, 427, 426, 427, 428, 426, 427, 429, 428, 429, 430, 428, 429, 431, 430, 431, 432, 430, 431, 433, 432, 433, 434, 432, 433, 435, 434, 435, 436, 434, 435, 437, 436, 438, 440, 439, 438, 441, 440, 442, 441, 438, 442, 443, 441, 444, 443, 442, 444, 445, 443, 446, 445, 444, 446, 447, 445, 439, 436, 437, 439, 440, 436, 424, 447, 446, 424, 425, 447, 448, 371, 372, 449, 375, 372, 376, 448, 372, 450, 372, 379, 451, 372, 450, 449, 372, 451, 210, 380, 452, 210, 136, 380, 277, 454, 453, 277, 278, 454, 30, 453, 214, 30, 277, 453, 278, 455, 454, 278, 280, 455, 216, 457, 456, 216, 217, 457, 458, 342, 343, 458, 459, 342, 460, 457, 461, 460, 456, 457, 224, 341, 225, 224, 340, 341, 458, 461, 459, 458, 460, 461, 462, 323, 463, 462, 322, 323, 464, 466, 465, 464, 467, 466, 468, 470, 469, 468, 471, 470, 472, 469, 473, 472, 468, 469, 467, 474, 466, 467, 475, 474, 471, 465, 470, 471, 464, 465, 280, 476, 455, 280, 102, 476, 477, 479, 478, 477, 480, 479, 325, 481, 324, 325, 482, 481, 483, 463, 484, 483, 462, 463, 480, 485, 479, 480, 486, 485, 482, 478, 481, 482, 477, 478, 486, 484, 485, 486, 483, 484, 475, 487, 474, 475, 488, 487, 489, 473, 490, 489, 472, 473, 488, 490, 487, 488, 489, 490, 102, 255, 476, 267, 262, 259, 267, 491, 262, 268, 265, 492, 268, 269, 265, 491, 264, 262, 491, 493, 264, 492, 264, 493, 492, 265, 264, 494, 496, 495, 494, 497, 496, 497, 94, 496, 497, 93, 94, 498, 500, 499, 498, 501, 500, 499, 219, 216, 499, 500, 219, 502, 496, 503, 502, 495, 496, 503, 94, 220, 503, 496, 94, 504, 500, 501, 504, 505, 500, 505, 219, 500, 505, 222, 219, 506, 497, 494, 506, 507, 497, 507, 93, 497, 507, 224, 93, 502, 505, 504, 502, 503, 505, 503, 222, 505, 503, 220, 222, 508, 510, 509, 508, 511, 510, 509, 343, 340, 509, 510, 343, 498, 513, 512, 498, 499, 513, 499, 456, 513, 499, 216, 456, 514, 510, 511, 514, 515, 510, 515, 343, 510, 515, 458, 343, 516, 513, 517, 516, 512, 513, 517, 456, 460, 517, 513, 456, 506, 509, 507, 506, 508, 509, 507, 340, 224, 507, 509, 340, 514, 517, 515, 514, 516, 517, 515, 460, 458, 515, 517, 460, 31, 518, 100, 31, 101, 518, 100, 54, 51, 100, 518, 54, 519, 521, 520, 519, 522, 521, 520, 98, 97, 520, 521, 98, 522, 523, 521, 522, 524, 523, 521, 99, 98, 521, 523, 99, 52, 520, 51, 52, 519, 520, 51, 97, 100, 51, 520, 97, 281, 518, 101, 281, 346, 518, 346, 54, 518, 346, 300, 54, 525, 527, 526, 525, 528, 527, 528, 345, 527, 528, 344, 345, 526, 523, 524, 526, 527, 523, 527, 99, 523, 527, 345, 99, 301, 528, 525, 301, 300, 528, 300, 344, 528, 300, 346, 344, 529, 531, 530, 529, 532, 531, 530, 534, 533, 530, 531, 534, 533, 325, 322, 533, 534, 325, 535, 530, 536, 535, 529, 530, 536, 533, 537, 536, 530, 533, 537, 322, 462, 537, 533, 322, 538, 540, 539, 538, 541, 540, 539, 543, 542, 539, 540, 543, 542, 480, 477, 542, 543, 480, 532, 544, 531, 532, 545, 544, 531, 546, 534, 531, 544, 546, 534, 482, 325, 534, 546, 482, 547, 536, 548, 547, 535, 536, 548, 537, 549, 548, 536, 537, 549, 462, 483, 549, 537, 462, 541, 550, 540, 541, 551, 550, 540, 552, 543, 540, 550, 552, 543, 486, 480, 543, 552, 486, 545, 539, 544, 545, 538, 539, 544, 542, 546, 544, 539, 542, 546, 477, 482, 546, 542, 477, 551, 548, 550, 551, 547, 548, 550, 549, 552, 550, 548, 549, 552, 483, 486, 552, 549, 483, 553, 555, 554, 553, 556, 555, 556, 557, 555, 556, 558, 557, 558, 76, 557, 558, 75, 76, 559, 556, 553, 559, 560, 556, 560, 558, 556, 560, 561, 558, 561, 75, 558, 561, 226, 75, 562, 564, 563, 562, 565, 564, 565, 566, 564, 565, 567, 566, 567, 242, 566, 567, 241, 242, 554, 569, 568, 554, 555, 569, 555, 570, 569, 555, 557, 570, 557, 245, 570, 557, 76, 245, 571, 560, 559, 571, 572, 560, 572, 561, 560, 572, 573, 561, 573, 226, 561, 573, 247, 226, 563, 575, 574, 563, 564, 575, 564, 576, 575, 564, 566, 576, 566, 249, 576, 566, 242, 249, 568, 565, 562, 568, 569, 565, 569, 567, 565, 569, 570, 567, 570, 241, 567, 570, 245, 241, 574, 572, 571, 574, 575, 572, 575, 573, 572, 575, 576, 573, 576, 247, 573, 576, 249, 247, 577, 579, 578, 577, 580, 579, 580, 581, 579, 580, 582, 581, 582, 229, 581, 582, 228, 229, 583, 585, 584, 583, 586, 585, 586, 587, 585, 586, 588, 587, 588, 233, 587, 588, 232, 233, 589, 586, 583, 589, 590, 586, 590, 588, 586, 590, 591, 588, 591, 232, 588, 591, 236, 232, 578, 593, 592, 578, 579, 593, 579, 594, 593, 579, 581, 594, 581, 238, 594, 581, 229, 238, 584, 580, 577, 584, 585, 580, 585, 582, 580, 585, 587, 582, 587, 228, 582, 587, 233, 228, 592, 596, 595, 592, 593, 596, 593, 597, 596, 593, 594, 597, 594, 251, 597, 594, 238, 251, 598, 590, 589, 598, 599, 590, 599, 591, 590, 599, 600, 591, 600, 236, 591, 600, 253, 236, 595, 599, 598, 595, 596, 599, 596, 600, 599, 596, 597, 600, 597, 253, 600, 597, 251, 253, 601, 603, 602, 601, 604, 603, 602, 606, 605, 602, 603, 606, 605, 467, 464, 605, 606, 467, 607, 609, 608, 607, 610, 609, 608, 612, 611, 608, 609, 612, 611, 471, 468, 611, 612, 471, 613, 608, 614, 613, 607, 608, 614, 611, 615, 614, 608, 611, 615, 468, 472, 615, 611, 468, 604, 616, 603, 604, 617, 616, 603, 618, 606, 603, 616, 618, 606, 475, 467, 606, 618, 475, 610, 602, 609, 610, 601, 602, 609, 605, 612, 609, 602, 605, 612, 464, 471, 612, 605, 464, 617, 619, 616, 617, 620, 619, 616, 621, 618, 616, 619, 621, 618, 488, 475, 618, 621, 488, 622, 614, 623, 622, 613, 614, 623, 615, 624, 623, 614, 615, 624, 472, 489, 624, 615, 472, 620, 623, 619, 620, 622, 623, 619, 624, 621, 619, 623, 624, 621, 489, 488, 621, 624, 489 </int_array>
- </array>
- </dictionary>
-
- </resource>
- <resource type="SampleLibrary" path="local://6">
- <dictionary name="samples/jump" shared="false">
- <string> "db" </string>
- <real> 0 </real>
- <string> "pitch" </string>
- <real> 1 </real>
- <string> "sample" </string>
- <resource resource_type="Sample" path="res://sound_jump.wav"> </resource>
- </dictionary>
- <dictionary name="samples/shoot" shared="false">
- <string> "db" </string>
- <real> 0 </real>
- <string> "pitch" </string>
- <real> 1 </real>
- <string> "sample" </string>
- <resource resource_type="Sample" path="res://sound_shoot.wav"> </resource>
- </dictionary>
-
- </resource>
- <resource type="Animation" path="local://7">
- <string name="resource/name"> "idle" </string>
- <real name="length"> 1.25 </real>
- <bool name="loop"> True </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="180"> 0, 1, 1.01328e-06, -8.34465e-07, 1.07288e-06, -0.0255728, 0.138077, -0.259039, 0.955604, 1, 1, 1, 0.05, 1, 5.96046e-07, -2.38419e-07, 3.8743e-07, -0.0264725, 0.139277, -0.25962, 0.955248, 1, 1, 1, 0.1, 1, 5.36442e-07, -2.38419e-07, 3.8743e-07, -0.028916, 0.142508, -0.261183, 0.954274, 1, 1, 1, 0.15, 1, 1.19209e-07, 1.19209e-07, 5.96046e-08, -0.0326835, 0.14736, -0.26354, 0.952766, 1, 1, 1, 0.25, 1, 5.96046e-08, 1.19209e-07, 0, -0.0433083, 0.158072, -0.268982, 0.949098, 1, 1, 1, 0.3, 1, 8.9407e-07, -3.57628e-07, 5.96046e-07, -0.0481632, 0.16058, -0.27034, 0.948056, 1, 1, 1, 0.35, 1, 7.15256e-07, -3.57628e-07, 5.36442e-07, -0.0515519, 0.159894, -0.270034, 0.948081, 1, 1, 1, 0.4, 1, 6.25849e-07, -3.57628e-07, 5.06639e-07, -0.0529994, 0.155917, -0.267946, 0.949256, 1, 1, 1, 0.85, 1, 8.04663e-07, -5.96046e-07, 8.34465e-07, -0.01551, 0.114246, -0.235933, 0.964906, 1, 1, 1, 0.9, 1, 7.15256e-07, -4.76837e-07, 7.15256e-07, -0.0133439, 0.115591, -0.236366, 0.964672, 1, 1, 1, 0.95, 1, 5.06639e-07, -3.57628e-07, 4.76837e-07, -0.0142794, 0.118993, -0.239276, 0.963527, 1, 1, 1, 1.1, 1, 6.55651e-07, -3.57628e-07, 5.36442e-07, -0.0224776, 0.132362, -0.25315, 0.958066, 1, 1, 1, 1.15, 1, 7.45058e-07, -2.38419e-07, 4.17233e-07, -0.0241962, 0.135447, -0.25637, 0.956736, 1, 1, 1, 1.2, 1, 7.15256e-07, -2.38419e-07, 5.06639e-07, -0.0252313, 0.137384, -0.258343, 0.955902, 1, 1, 1, 1.25, 1, 1.01328e-06, -8.34465e-07, 1.07288e-06, -0.0255726, 0.138077, -0.259039, 0.955604, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="204"> 0, 1, 2.38419e-07, -8.34465e-07, -4.76837e-07, -0.218168, -0.120735, -0.0116329, 0.968344, 1, 1, 1, 0.05, 1, 2.98023e-08, -5.96046e-07, -2.38419e-07, -0.218633, -0.120967, -0.0119311, 0.968207, 1, 1, 1, 0.1, 1, 1.78814e-07, -7.7486e-07, -4.76837e-07, -0.219848, -0.121646, -0.0127373, 0.967836, 1, 1, 1, 0.15, 1, -5.96046e-08, -6.25849e-07, -4.76837e-07, -0.221585, -0.122891, -0.0139574, 0.967266, 1, 1, 1, 0.2, 1, -2.98023e-08, -9.83477e-07, -1.78814e-07, -0.223801, -0.125062, -0.0151597, 0.966459, 1, 1, 1, 0.25, 1, 1.49012e-07, -5.66244e-07, -2.38419e-07, -0.225991, -0.128733, -0.0159408, 0.965454, 1, 1, 1, 0.3, 1, 0, -1.04308e-06, -2.38419e-07, -0.227229, -0.134329, -0.0159913, 0.9644, 1, 0.999999, 1, 0.55, 1, 2.98023e-08, -5.66244e-07, -3.57628e-07, -0.218159, -0.170756, -0.00658222, 0.960836, 1, 1, 1, 0.6, 1, 1.49012e-07, -5.36442e-07, -2.98023e-07, -0.214746, -0.174272, -0.00460497, 0.960985, 1, 1, 1, 0.65, 1, 2.38419e-07, -2.08616e-07, -3.57628e-07, -0.21128, -0.17607, -0.0030008, 0.961432, 1, 1, 1, 0.7, 1, 1.49012e-07, -4.47035e-07, -2.38419e-07, -0.207961, -0.17612, -0.00179697, 0.962149, 1, 1, 1, 0.75, 1, -2.38419e-07, -6.55651e-07, -3.57628e-07, -0.204984, -0.174339, -0.000935222, 0.963113, 1, 1, 1, 0.8, 1, 8.9407e-08, -2.98023e-08, -1.19209e-07, -0.202542, -0.170485, -0.000499965, 0.964319, 1, 0.999999, 1, 0.85, 1, 8.9407e-08, -8.64267e-07, -4.17233e-07, -0.200954, -0.164989, -0.000498206, 0.965607, 1, 0.999999, 1, 1.15, 1, 1.19209e-07, -6.85453e-07, -2.98023e-07, -0.216378, -0.124725, -0.0104075, 0.968254, 1, 1, 1, 1.2, 1, -2.98023e-08, 2.98023e-08, -1.78814e-07, -0.217708, -0.121801, -0.0113103, 0.968318, 1, 1, 1, 1.25, 1, 2.38419e-07, -8.34465e-07, -4.76837e-07, -0.218168, -0.120734, -0.0116329, 0.968344, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="180"> 0, 1, -1.01328e-06, -8.34465e-07, 1.07288e-06, -0.0255728, -0.138077, 0.25904, 0.955604, 1, 1, 1, 0.05, 1, -5.96046e-07, -2.38419e-07, 3.8743e-07, -0.0264725, -0.139277, 0.25962, 0.955248, 1, 1, 1, 0.1, 1, -5.36442e-07, -2.38419e-07, 3.8743e-07, -0.028916, -0.142508, 0.261183, 0.954274, 1, 1, 1, 0.15, 1, -1.19209e-07, 1.19209e-07, 5.96046e-08, -0.0326835, -0.14736, 0.26354, 0.952766, 1, 1, 1, 0.25, 1, -5.96046e-08, 1.19209e-07, 0, -0.0433083, -0.158072, 0.268982, 0.949098, 1, 1, 1, 0.3, 1, -8.9407e-07, -3.57628e-07, 5.96046e-07, -0.0481632, -0.16058, 0.27034, 0.948056, 1, 1, 1, 0.35, 1, -7.15256e-07, -3.57628e-07, 5.36442e-07, -0.0515519, -0.159894, 0.270034, 0.948081, 1, 1, 1, 0.4, 1, -6.25849e-07, -3.57628e-07, 5.06639e-07, -0.0529994, -0.155917, 0.267946, 0.949256, 1, 1, 1, 0.85, 1, -8.04663e-07, -5.96046e-07, 8.34465e-07, -0.01551, -0.114246, 0.235933, 0.964906, 1, 1, 1, 0.9, 1, -7.15256e-07, -4.76837e-07, 7.15256e-07, -0.0133439, -0.115591, 0.236367, 0.964672, 1, 1, 1, 0.95, 1, -5.06639e-07, -3.57628e-07, 4.76837e-07, -0.0142794, -0.118993, 0.239276, 0.963527, 1, 1, 1, 1.1, 1, -6.55651e-07, -3.57628e-07, 5.36442e-07, -0.0224776, -0.132362, 0.25315, 0.958066, 1, 1, 1, 1.15, 1, -7.45058e-07, -2.38419e-07, 4.17233e-07, -0.0241962, -0.135447, 0.25637, 0.956736, 1, 1, 1, 1.2, 1, -7.15256e-07, -2.38419e-07, 5.06639e-07, -0.0252313, -0.137384, 0.258343, 0.955902, 1, 1, 1, 1.25, 1, -1.01328e-06, -8.34465e-07, 1.07288e-06, -0.0255726, -0.138077, 0.259039, 0.955604, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="204"> 0, 1, -2.38419e-07, -8.34465e-07, -4.76837e-07, -0.218168, 0.120735, 0.0116329, 0.968344, 1, 1, 1, 0.05, 1, -5.96046e-08, -8.04663e-07, -3.57628e-07, -0.218633, 0.120966, 0.0119311, 0.968207, 1, 1, 1, 0.1, 1, -3.57628e-07, -7.45058e-07, -4.17233e-07, -0.219848, 0.121646, 0.0127373, 0.967836, 1, 1, 1, 0.15, 1, -1.49012e-07, -6.25849e-07, -3.57628e-07, -0.221585, 0.122891, 0.0139575, 0.967266, 1, 1, 1, 0.2, 1, 0, -9.53674e-07, -1.19209e-07, -0.223801, 0.125062, 0.0151597, 0.966459, 1, 1, 1, 0.25, 1, -1.49012e-07, -5.66244e-07, -2.38419e-07, -0.225991, 0.128733, 0.0159408, 0.965454, 1, 1, 1, 0.3, 1, 0, -1.04308e-06, -2.38419e-07, -0.227229, 0.134329, 0.0159913, 0.9644, 1, 0.999999, 1, 0.55, 1, -2.98023e-08, -5.66244e-07, -3.57628e-07, -0.218159, 0.170756, 0.00658222, 0.960836, 1, 1, 1, 0.6, 1, -1.49012e-07, -5.36442e-07, -2.98023e-07, -0.214746, 0.174272, 0.00460497, 0.960985, 1, 1, 1, 0.65, 1, -2.38419e-07, -2.08616e-07, -3.57628e-07, -0.21128, 0.17607, 0.0030008, 0.961432, 1, 1, 1, 0.7, 1, -1.49012e-07, -4.47035e-07, -2.38419e-07, -0.207961, 0.17612, 0.00179697, 0.962149, 1, 1, 1, 0.75, 1, 2.38419e-07, -6.55651e-07, -3.57628e-07, -0.204984, 0.174339, 0.000935222, 0.963113, 1, 1, 1, 0.8, 1, -2.98023e-08, 0, -1.19209e-07, -0.202542, 0.170485, 0.000499968, 0.964319, 1, 1, 1, 0.85, 1, 1.49012e-07, -8.34465e-07, -4.17233e-07, -0.200954, 0.164989, 0.000498198, 0.965606, 1, 1, 1, 1.15, 1, -2.38419e-07, -8.04663e-07, -6.55651e-07, -0.216378, 0.124725, 0.0104075, 0.968254, 1, 1, 1, 1.2, 1, -2.08616e-07, 2.08616e-07, -2.98023e-07, -0.217708, 0.121801, 0.0113103, 0.968318, 1, 1, 1, 1.25, 1, -2.38419e-07, -8.34465e-07, -4.76837e-07, -0.218168, 0.120734, 0.0116329, 0.968344, 1, 1, 1 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="180"> 0, 1, 0, 5.21541e-08, -3.42727e-07, -0.0539951, -0.0696263, 0.0213632, 0.995882, 1, 1, 1, 0.05, 1, 0, 5.21541e-08, -3.42727e-07, -0.0567764, -0.0700338, 0.0212387, 0.995701, 1, 1, 1, 0.1, 1, 0, 3.72529e-08, -3.42727e-07, -0.06411, -0.0711033, 0.0209058, 0.995187, 1, 1, 1, 0.15, 1, 0, 9.68575e-08, -3.42727e-07, -0.0751103, -0.0727354, 0.0204167, 0.994309, 1, 1, 1, 0.45, 1, 0, 1.41561e-07, -1.3411e-07, -0.154319, -0.0862804, 0.0175296, 0.984091, 1, 1, 1, 0.5, 1, 2.98023e-08, 7.45058e-09, 2.5332e-07, -0.162001, -0.0877685, 0.017297, 0.982728, 1, 1, 1, 0.55, 1, 0, 3.72529e-08, -3.42727e-07, -0.166842, -0.0887317, 0.0171579, 0.981833, 1, 1, 1, 0.6, 1, 0, 2.98023e-08, -1.49012e-07, -0.169226, -0.0892111, 0.0170905, 0.981383, 1, 1, 1, 0.65, 1, 0, 2.98023e-08, -1.49012e-07, -0.169226, -0.0892111, 0.0170905, 0.981383, 1, 1, 1, 0.7, 1, 0, 3.72529e-08, -3.42727e-07, -0.166842, -0.0887317, 0.0171579, 0.981833, 1, 1, 1, 0.75, 1, 2.98023e-08, 7.45058e-09, 2.5332e-07, -0.162001, -0.0877685, 0.017297, 0.982728, 1, 1, 1, 0.8, 1, 0, 1.41561e-07, -1.3411e-07, -0.154319, -0.0862804, 0.0175296, 0.984091, 1, 1, 1, 1.15, 1, 0, 3.72529e-08, -3.42727e-07, -0.06411, -0.0711033, 0.0209058, 0.995187, 1, 1, 1, 1.2, 1, 0, 5.21541e-08, -3.42727e-07, -0.0567764, -0.0700338, 0.0212387, 0.995701, 1, 1, 1, 1.25, 1, 0, 5.21541e-08, -3.42727e-07, -0.0539951, -0.0696263, 0.0213632, 0.995882, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="192"> 0, 1, 1.42842e-07, 1.93715e-07, 2.98023e-07, -0.0965851, -0.0177476, 0.000627753, 0.995166, 1, 1, 1, 0.05, 1, 4.62169e-08, -6.70552e-08, 6.55651e-07, -0.100604, -0.0182764, 0.000608928, 0.994758, 1, 1, 1, 0.1, 1, 8.12579e-08, 5.96046e-08, 5.36442e-07, -0.111195, -0.0196529, 0.000562433, 0.993604, 1, 1, 1, 0.15, 1, 3.0268e-08, -2.98023e-08, 5.96046e-07, -0.127055, -0.0217242, 0.000494295, 0.991658, 1, 1, 1, 0.45, 1, 1.55647e-07, 1.49012e-07, 4.76837e-07, -0.240017, -0.0376881, -3.78875e-05, 0.970037, 1, 1, 1, 0.5, 1, -1.23866e-07, 3.57628e-07, 7.7486e-07, -0.250826, -0.0393224, -9.00224e-05, 0.967233, 1, 1, 1, 0.55, 1, 5.34346e-08, 3.72529e-08, 5.96046e-07, -0.25762, -0.040368, -0.000123774, 0.965403, 1, 1, 1, 0.6, 1, 1.08266e-08, 5.96046e-08, 7.15256e-07, -0.260963, -0.0408854, -0.000140397, 0.964483, 1, 1, 1, 0.65, 1, 1.08266e-08, 5.96046e-08, 7.15256e-07, -0.260963, -0.0408854, -0.000140397, 0.964483, 1, 1, 1, 0.7, 1, 5.34346e-08, 3.72529e-08, 5.96046e-07, -0.25762, -0.040368, -0.000123775, 0.965403, 1, 1, 1, 0.75, 1, -1.23866e-07, 3.57628e-07, 7.7486e-07, -0.250826, -0.0393224, -9.00224e-05, 0.967233, 1, 1, 1, 0.8, 1, 1.55647e-07, 1.49012e-07, 4.76837e-07, -0.240017, -0.0376881, -3.78871e-05, 0.970037, 1, 1, 1, 0.9, 1, -4.8778e-08, -1.3411e-07, 7.15256e-07, -0.208519, -0.0330444, 0.00011266, 0.97746, 1, 1, 1, 1.15, 1, 8.12579e-08, 5.96046e-08, 5.36442e-07, -0.111195, -0.0196529, 0.000562432, 0.993604, 1, 1, 1, 1.2, 1, 4.62169e-08, -6.70552e-08, 6.55651e-07, -0.100605, -0.0182764, 0.000608928, 0.994758, 1, 1, 1, 1.25, 1, 1.42842e-07, 1.93715e-07, 2.98023e-07, -0.0965852, -0.0177476, 0.000627753, 0.995166, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="180"> 0, 1, 8.9407e-08, 2.38419e-07, -2.23517e-08, 0.0349931, -0.0301778, 0.0362945, 0.998272, 1, 1, 1, 0.05, 1, 7.45058e-08, 2.38419e-07, 6.33299e-08, 0.0358993, -0.0301376, 0.0363473, 0.998239, 1, 1, 1, 0.1, 1, 5.21541e-08, 1.19209e-07, 2.98023e-08, 0.0384013, -0.0300263, 0.0364927, 0.998144, 1, 1, 1, 0.15, 1, 4.47035e-08, 1.19209e-07, -1.11759e-08, 0.0424549, -0.0298457, 0.0367279, 0.997977, 1, 1, 1, 0.5, 1, 5.21541e-08, 1.19209e-07, 7.45058e-09, 0.0873535, -0.0278095, 0.0392948, 0.995014, 1, 1, 1, 0.55, 1, -7.45058e-09, 0, -5.21541e-08, 0.0905253, -0.0276632, 0.0394735, 0.994727, 1, 1, 1, 0.6, 1, 2.98023e-08, 0, 2.23517e-08, 0.0921114, -0.0275899, 0.0395627, 0.99458, 1, 1, 1, 0.65, 1, 2.98023e-08, 0, 2.23517e-08, 0.0921114, -0.0275899, 0.0395627, 0.99458, 1, 1, 1, 0.7, 1, -7.45058e-09, 0, -5.21541e-08, 0.0905253, -0.0276632, 0.0394735, 0.994727, 1, 1, 1, 0.75, 1, 5.21541e-08, 1.19209e-07, 7.45058e-09, 0.0873535, -0.0278095, 0.0392948, 0.995014, 1, 1, 1, 0.8, 1, 1.04308e-07, 2.38419e-07, -1.49012e-08, 0.0824784, -0.0280337, 0.0390195, 0.995434, 1, 1, 1, 1.1, 1, 4.47035e-08, 1.19209e-07, -1.11759e-08, 0.0424549, -0.0298457, 0.0367279, 0.997977, 1, 1, 1, 1.15, 1, 5.21541e-08, 1.19209e-07, 2.98023e-08, 0.0384013, -0.0300263, 0.0364927, 0.998144, 1, 1, 1, 1.2, 1, 7.45058e-08, 2.38419e-07, 6.33299e-08, 0.0358993, -0.0301376, 0.0363473, 0.998239, 1, 1, 1, 1.25, 1, 8.9407e-08, 2.38419e-07, -2.23517e-08, 0.0349931, -0.0301778, 0.0362945, 0.998272, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="180"> 0, 1, 0, 6.70552e-08, -1.04308e-07, -0.0539995, 0.0696269, -0.0213643, 0.995881, 1, 0.999999, 1, 0.05, 1, 0, 6.70552e-08, -1.04308e-07, -0.05678, 0.0700343, -0.0212398, 0.995701, 1, 0.999999, 1, 0.1, 1, 0, 2.23517e-08, -1.04308e-07, -0.0641135, 0.0711039, -0.0209069, 0.995187, 1, 0.999999, 1, 0.15, 1, 0, 8.19564e-08, -1.04308e-07, -0.075114, 0.072736, -0.0204178, 0.994309, 1, 0.999999, 1, 0.45, 1, -2.98023e-08, 1.04308e-07, 1.04308e-07, -0.15432, 0.0862808, -0.0175308, 0.98409, 1, 0.999999, 1, 0.5, 1, -5.96046e-08, 2.98023e-08, 4.91738e-07, -0.162002, 0.0877689, -0.0172983, 0.982727, 1, 0.999999, 1, 0.55, 1, 0, 5.21541e-08, -1.04308e-07, -0.166843, 0.0887321, -0.0171591, 0.981833, 1, 0.999999, 1, 0.6, 1, -2.98023e-08, 4.47035e-08, 8.9407e-08, -0.169228, 0.0892116, -0.0170917, 0.981382, 1, 0.999999, 1, 0.65, 1, -2.98023e-08, 4.47035e-08, 8.9407e-08, -0.169228, 0.0892116, -0.0170917, 0.981382, 1, 0.999999, 1, 0.7, 1, 0, 5.21541e-08, -1.04308e-07, -0.166843, 0.0887321, -0.0171591, 0.981833, 1, 0.999999, 1, 0.75, 1, -5.96046e-08, 2.98023e-08, 4.91738e-07, -0.162002, 0.0877689, -0.0172983, 0.982727, 1, 0.999999, 1, 0.8, 1, -2.98023e-08, 1.04308e-07, 1.04308e-07, -0.15432, 0.0862808, -0.0175308, 0.98409, 1, 0.999999, 1, 1.15, 1, 0, 2.23517e-08, -1.04308e-07, -0.0641135, 0.0711039, -0.020907, 0.995187, 1, 0.999999, 1, 1.2, 1, 0, 6.70552e-08, -1.04308e-07, -0.05678, 0.0700343, -0.0212398, 0.995701, 1, 0.999999, 1, 1.25, 1, 0, 6.70552e-08, -1.04308e-07, -0.0539992, 0.0696269, -0.0213643, 0.995881, 1, 0.999999, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="192"> 0, 1, 9.06875e-08, -8.19564e-08, 3.57628e-07, -0.0965913, 0.0177484, -0.00062776, 0.995166, 1, 1, 1, 0.05, 1, 3.44589e-08, -1.93715e-07, 2.98023e-07, -0.10061, 0.0182771, -0.000608941, 0.994758, 1, 1, 1, 0.1, 1, 2.52621e-08, -1.86265e-07, 5.96046e-08, -0.1112, 0.0196536, -0.000562456, 0.993604, 1, 1, 1, 0.15, 1, 9.02219e-08, -1.19209e-07, 1.19209e-07, -0.127061, 0.021725, -0.000494313, 0.991657, 1, 1, 1, 0.45, 1, 7.13626e-08, -5.21541e-08, 1.19209e-07, -0.24002, 0.0376883, 3.78708e-05, 0.970036, 1, 1, 1, 0.5, 1, -2.84053e-08, -1.78814e-07, -1.78814e-07, -0.250828, 0.0393224, 9.00085e-05, 0.967233, 1, 1, 1, 0.55, 1, 1.234e-08, 2.01166e-07, 1.78814e-07, -0.257623, 0.0403681, 0.000123756, 0.965402, 1, 1, 1, 0.6, 1, -9.97679e-08, 5.21541e-08, -5.96046e-08, -0.260966, 0.0408856, 0.000140381, 0.964482, 1, 1, 1, 0.65, 1, -9.97679e-08, 5.21541e-08, -5.96046e-08, -0.260966, 0.0408856, 0.000140381, 0.964482, 1, 1, 1, 0.7, 1, 1.234e-08, 2.01166e-07, 1.78814e-07, -0.257623, 0.0403681, 0.000123754, 0.965402, 1, 1, 1, 0.75, 1, -2.84053e-08, -1.78814e-07, -1.78814e-07, -0.250828, 0.0393224, 9.00085e-05, 0.967233, 1, 1, 1, 0.8, 1, 7.13626e-08, -5.21541e-08, 1.19209e-07, -0.24002, 0.0376883, 3.78693e-05, 0.970036, 1, 1, 1, 0.9, 1, 3.73693e-08, -5.21541e-08, 2.38419e-07, -0.208521, 0.0330446, -0.000112648, 0.977459, 1, 1, 1, 1.15, 1, 2.52621e-08, -1.86265e-07, 5.96046e-08, -0.1112, 0.0196536, -0.000562457, 0.993604, 1, 1, 1, 1.2, 1, 3.44589e-08, -1.93715e-07, 2.98023e-07, -0.10061, 0.0182771, -0.000608943, 0.994758, 1, 1, 1, 1.25, 1, 9.06875e-08, -8.19564e-08, 3.57628e-07, -0.0965911, 0.0177484, -0.000627765, 0.995166, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="180"> 0, 1, -6.70552e-08, 0, -3.72529e-09, 0.0349931, 0.0301778, -0.0362945, 0.998272, 1, 1, 1, 0.05, 1, -1.49012e-08, 1.19209e-07, -7.45058e-09, 0.0358993, 0.0301376, -0.0363473, 0.998239, 1, 1, 1, 0.1, 1, 1.49012e-08, -1.19209e-07, 1.49012e-08, 0.0384013, 0.0300263, -0.0364927, 0.998144, 1, 1, 1, 0.15, 1, -4.47035e-08, 0, -3.72529e-09, 0.0424549, 0.0298457, -0.0367279, 0.997977, 1, 1, 1, 0.5, 1, 5.21541e-08, 0, -1.11759e-08, 0.0873535, 0.0278095, -0.0392948, 0.995014, 1, 1, 1, 0.55, 1, 4.47035e-08, 0, -2.98023e-08, 0.0905253, 0.0276632, -0.0394736, 0.994727, 1, 1, 1, 0.6, 1, 1.49012e-08, 0, -1.86265e-08, 0.0921114, 0.02759, -0.0395628, 0.99458, 1, 1, 1, 0.65, 1, 1.49012e-08, 0, -1.86265e-08, 0.0921114, 0.02759, -0.0395628, 0.99458, 1, 1, 1, 0.7, 1, 4.47035e-08, 0, -2.98023e-08, 0.0905253, 0.0276633, -0.0394736, 0.994727, 1, 1, 1, 0.75, 1, 5.21541e-08, 0, -1.11759e-08, 0.0873535, 0.0278095, -0.0392948, 0.995014, 1, 1, 1, 0.8, 1, -3.72529e-08, 1.19209e-07, -1.11759e-08, 0.0824784, 0.0280338, -0.0390195, 0.995434, 1, 1, 1, 1.1, 1, -4.47035e-08, 0, -3.72529e-09, 0.0424549, 0.0298457, -0.0367279, 0.997977, 1, 1, 1, 1.15, 1, 1.49012e-08, -1.19209e-07, 1.49012e-08, 0.0384013, 0.0300263, -0.0364927, 0.998144, 1, 1, 1, 1.2, 1, -1.49012e-08, 1.19209e-07, -7.45058e-09, 0.0358992, 0.0301376, -0.0363473, 0.998239, 1, 1, 1, 1.25, 1, -6.70552e-08, 0, -3.72529e-09, 0.0349931, 0.0301778, -0.0362945, 0.998272, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="24"> 0, 1, 0, -0.322829, 2.42144e-08, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0, -0.322829, 2.42144e-08, 5.1658e-08, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="24"> 0, 1, -5.68434e-14, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -5.68434e-14, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="24"> 0, 1, 0.220288, -4.0302e-11, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.220288, -4.0302e-11, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="24"> 0, 1, -0.220288, -4.0302e-11, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.220288, -4.0302e-11, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="24"> 0, 1, -0.183564, 0.0305941, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.183564, 0.0305941, 5.96046e-08, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="24"> 0, 1, 0.183564, 0.030594, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.183564, 0.030594, 5.96046e-08, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="168"> 0, 1, -1.15243, -0.687477, 0.0713858, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -1.15504, -0.689394, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -1.16214, -0.694617, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, -1.17317, -0.702725, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.3, 1, -1.21295, -0.731968, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.35, 1, -1.22128, -0.738092, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -1.2252, -0.740971, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -1.22553, -0.741211, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, -1.22422, -0.740253, 0.0713858, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -1.22161, -0.73833, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.6, 1, -1.21787, -0.735585, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.15, 1, -1.15488, -0.689275, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.2, 1, -1.15308, -0.687955, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.25, 1, -1.15243, -0.687477, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="168"> 0, 1, 1.15243, -0.687477, 0.0713859, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 1.15504, -0.689394, 0.0713859, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, 1.16214, -0.694617, 0.0713859, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, 1.17317, -0.702725, 0.0713859, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.3, 1, 1.21295, -0.731968, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.35, 1, 1.22128, -0.738092, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, 1.2252, -0.740971, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, 1.22553, -0.741211, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, 1.22422, -0.740253, 0.0713858, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, 1.22161, -0.73833, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.6, 1, 1.21787, -0.735585, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.15, 1, 1.15488, -0.689275, 0.0713859, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.2, 1, 1.15308, -0.687955, 0.0713859, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.25, 1, 1.15243, -0.687477, 0.0713859, -5.1658e-08, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="156"> 0, 1, 0.849557, -0.741664, 4.9468, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.849557, -0.741664, 4.93101, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, 0.849557, -0.741664, 4.88735, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, 0.849557, -0.741664, 4.81599, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, 0.849557, -0.741664, 4.71797, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.75, 1, 0.849557, -0.741664, 3.21234, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, 0.849557, -0.741664, 3.18081, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.85, 1, 0.849557, -0.741664, 3.18869, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.9, 1, 0.849557, -0.741664, 3.28296, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.95, 1, 0.849557, -0.741664, 3.48291, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.15, 1, 0.849557, -0.741664, 4.70777, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.2, 1, 0.849557, -0.741664, 4.88227, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.849557, -0.741664, 4.9468, -5.1658e-08, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="156"> 0, 1, -0.849557, -0.741664, 4.9468, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.849557, -0.741664, 4.93101, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -0.849557, -0.741664, 4.88735, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, -0.849557, -0.741664, 4.81599, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, -0.849557, -0.741664, 4.71797, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.75, 1, -0.849557, -0.741664, 3.21234, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -0.849557, -0.741664, 3.18081, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.85, 1, -0.849557, -0.741664, 3.18869, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.9, 1, -0.849557, -0.741664, 3.28296, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.95, 1, -0.849557, -0.741664, 3.48291, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.15, 1, -0.849557, -0.741664, 4.70777, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.2, 1, -0.849557, -0.741664, 4.88227, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.849557, -0.741664, 4.9468, -5.1658e-08, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="180"> 0, 1, 1.11759e-08, 0.0713859, 0.0510914, 0, 0, 1.44945e-21, 1, 1, 1, 1, 0.05, 1, 1.11759e-08, 0.0713859, 0.0522077, -4.26326e-14, 4.23516e-22, 1.44945e-21, 1, 1, 1, 1, 0.1, 1, 1.11759e-08, 0.0713859, 0.05529, -5.68434e-14, 2.11758e-21, 1.44945e-21, 1, 1, 1, 1, 0.15, 1, 1.11759e-08, 0.0713859, 0.0602832, -4.26326e-14, 4.23516e-22, 1.44945e-21, 1, 1, 1, 1, 0.5, 1, 1.11759e-08, 0.0713859, 0.115648, 0, 0, 1.44945e-21, 1, 1, 1, 1, 0.55, 1, 1.11759e-08, 0.0713859, 0.119568, -4.26326e-14, 4.23516e-22, 1.44945e-21, 1, 1, 1, 1, 0.6, 1, 1.11759e-08, 0.0713859, 0.121528, -4.26326e-14, 4.23516e-22, 1.44945e-21, 1, 1, 1, 1, 0.65, 1, 1.11759e-08, 0.0713859, 0.121528, -4.26326e-14, 4.23516e-22, 1.44945e-21, 1, 1, 1, 1, 0.7, 1, 1.11759e-08, 0.0713859, 0.119568, -5.68434e-14, 2.11758e-21, 1.44945e-21, 1, 1, 1, 1, 0.75, 1, 1.11759e-08, 0.0713859, 0.115648, 0, 0, 1.44945e-21, 1, 1, 1, 1, 0.8, 1, 1.11759e-08, 0.0713859, 0.109626, -5.68434e-14, 2.11758e-21, 1.44945e-21, 1, 1, 1, 1, 1.1, 1, 1.11759e-08, 0.0713859, 0.0602832, -5.68434e-14, 2.11758e-21, 1.44945e-21, 1, 1, 1, 1, 1.15, 1, 1.11759e-08, 0.0713859, 0.05529, -4.26326e-14, 4.23516e-22, 1.44945e-21, 1, 1, 1, 1, 1.2, 1, 1.11759e-08, 0.0713859, 0.0522077, -2.84217e-14, -4.23516e-22, 1.44945e-21, 1, 1, 1, 1, 1.25, 1, 1.11759e-08, 0.0713859, 0.0510914, -4.26326e-14, 4.23516e-22, 1.44945e-21, 1, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="168"> 0, 1, 5.71157e-15, -1.62345e-08, 8.9407e-08, 0, 0, 2.44616e-35, 1, 1, 1, 1, 0.05, 1, 5.75176e-15, -1.64873e-08, 8.9407e-08, 0.000214909, 1.42979e-18, -2.11758e-22, 1, 1, 1, 1, 0.1, 1, 4.06271e-15, -5.26452e-09, 8.9407e-08, 0.000808293, -3.04932e-19, 2.465e-22, 1, 1, 1, 1, 0.15, 1, 1.54246e-15, 1.14859e-08, 8.9407e-08, 0.00176961, 6.63395e-18, -1.17394e-20, 0.999998, 1, 1, 1, 0.5, 1, 4.42376e-15, -1.05373e-09, -2.98023e-08, 0.0124283, 2.20213e-20, -2.77954e-22, 0.999923, 1, 1, 1, 0.55, 1, 4.56489e-15, -1.94163e-09, 8.9407e-08, 0.0131829, 1.00996e-17, -7.10618e-15, 0.999913, 1, 1, 1, 0.65, 1, 1.79332e-15, -2.38573e-09, 8.9407e-08, 0.0135603, 1.03769e-16, -1.40726e-18, 0.999908, 1, 1, 1, 0.7, 1, 4.56489e-15, -1.94163e-09, 8.9407e-08, 0.0131829, -1.18256e-16, 1.5591e-18, 0.999913, 1, 1, 1, 0.75, 1, 4.42376e-15, -1.05373e-09, -2.98023e-08, 0.0124282, 2.20246e-20, -2.77954e-22, 0.999923, 1, 1, 1, 0.8, 1, 4.20699e-15, 3.1009e-10, -2.98023e-08, 0.011269, -6.2751e-17, 7.07106e-19, 0.999937, 1, 1, 1, 1.1, 1, 1.54246e-15, 1.14859e-08, 8.9407e-08, 0.00176961, 7.93788e-18, -7.10545e-15, 0.999998, 1, 1, 1, 1.15, 1, 4.06271e-15, -5.26452e-09, 8.9407e-08, 0.000808293, -3.04932e-19, 2.465e-22, 1, 1, 1, 1, 1.2, 1, 5.75176e-15, -1.64874e-08, 8.9407e-08, 0.00021491, -2.03966e-18, 4.23517e-22, 1, 1, 1, 1, 1.25, 1, 5.71157e-15, -1.62345e-08, 8.9407e-08, 3.83187e-10, 0, 1.22308e-35, 1, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="156"> 0, 1, 7.24544e-18, 1.86265e-08, 5.96046e-08, 0, 0, -1.33383e-23, 1, 1, 1, 1, 0.05, 1, -3.76414e-18, 3.72529e-09, 0, 0.00110099, -2.41201e-19, -1.97577e-17, 0.999999, 1, 1, 1, 0.1, 1, 9.18675e-18, 1.49012e-08, -1.19209e-07, 0.00410119, -8.96205e-19, -7.35977e-17, 0.999992, 1, 1, 1, 0.15, 1, 1.76552e-17, 7.45058e-09, -5.96046e-08, 0.00875896, -1.91283e-18, -1.57184e-16, 0.999962, 1, 1, 1, 0.3, 1, 1.31081e-17, -1.11759e-08, 0, 0.0255569, -5.58266e-18, -4.58633e-16, 0.999673, 1, 1, 1, 0.35, 1, 1.99653e-17, -1.49012e-08, -5.96046e-08, 0.0290738, -6.35135e-18, -5.21745e-16, 0.999577, 1, 1, 1, 0.4, 1, 1.92772e-17, 1.11759e-08, 1.19209e-07, 0.0307265, -6.71273e-18, -5.51404e-16, 0.999528, 1, 1, 1, 0.5, 1, 4.47552e-17, 1.11759e-08, 5.96046e-08, 0.0303143, -6.6203e-18, -5.44008e-16, 0.99954, 1, 1, 1, 0.55, 1, 1.08083e-17, 2.23517e-08, -5.96046e-08, 0.0292103, -6.38065e-18, -5.24195e-16, 0.999573, 1, 1, 1, 0.6, 1, -3.34373e-18, -1.11759e-08, -2.98023e-07, 0.0276344, -6.03606e-18, -4.95914e-16, 0.999618, 1, 1, 1, 1.15, 1, 9.18674e-18, 1.49012e-08, -1.19209e-07, 0.0010327, -2.26125e-19, -1.85323e-17, 0.999999, 1, 1, 1, 1.2, 1, -3.7641e-18, 0, 0, 0.000274137, -6.02241e-20, -4.91966e-18, 1, 1, 1, 1, 1.25, 1, 7.24539e-18, 1.86265e-08, 5.96046e-08, 0, 0, 1.31315e-23, 1, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="24"> 0, 1, -1.13687e-13, -1.49012e-08, -3.57628e-07, 1.17383e-27, 2.13163e-14, 5.50671e-14, 1, 1, 1, 1, 1.25, 1, -1.13687e-13, -1.49012e-08, -3.57628e-07, -2.46125e-27, 2.13163e-14, -1.77636e-15, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="180"> 0, 1, -2.16716e-13, 2.38419e-07, -1.20141e-07, 0.00540576, -3.97061e-09, 4.73012e-08, 0.999985, 1, 1, 1, 0.05, 1, 1.42109e-14, -6.85453e-07, -5.96046e-08, 0.00687155, -3.90174e-09, 4.73059e-08, 0.999976, 1, 1, 1, 0.1, 1, -1.06581e-13, -3.57628e-07, 4.65661e-09, 0.0108835, -3.7136e-09, 4.73184e-08, 0.999941, 1, 1, 1, 0.15, 1, 2.4869e-14, -7.15256e-07, -2.79397e-09, 0.0171898, -3.41769e-09, 4.73365e-08, 0.999852, 1, 1, 1, 0.35, 1, 5.68434e-14, -4.76837e-07, -2.16532e-08, 0.0482761, -1.95634e-09, 4.7399e-08, 0.998834, 1, 1, 1, 0.4, 1, 1.3145e-13, -4.76837e-07, 1.39698e-08, 0.0525864, -1.75345e-09, 4.74044e-08, 0.998616, 1, 1, 1, 0.45, 1, -7.10543e-15, -2.98023e-07, -2.23517e-08, 0.0549628, -1.64161e-09, 4.74072e-08, 0.998488, 1, 1, 1, 0.5, 1, 8.88178e-14, -4.47035e-07, -5.75092e-08, 0.056151, -1.58539e-09, 4.74086e-08, 0.998422, 1, 1, 1, 0.55, 1, -1.06581e-14, -7.15256e-07, -1.09896e-07, 0.0561279, -1.58659e-09, 4.74089e-08, 0.998424, 1, 1, 1, 0.6, 1, 1.49214e-13, -5.36442e-07, 8.3819e-09, 0.0550227, -1.63855e-09, 4.74081e-08, 0.998485, 1, 1, 1, 0.65, 1, 1.42109e-13, -5.66244e-07, -2.72412e-08, 0.0528693, -1.73995e-09, 4.74061e-08, 0.998601, 1, 1, 1, 0.7, 1, 1.27898e-13, -9.83477e-07, 2.23517e-08, 0.0497256, -1.88791e-09, 4.74026e-08, 0.998763, 1, 1, 1, 1.15, 1, 4.61853e-14, -2.68221e-07, -1.44821e-07, 0.00768525, -3.86364e-09, 4.73087e-08, 0.99997, 1, 1, 1, 1.2, 1, -4.61853e-14, -2.38419e-07, -9.12696e-08, 0.00601107, -3.94226e-09, 4.73032e-08, 0.999982, 1, 1, 1, 1.25, 1, -2.16716e-13, 2.38419e-07, -1.20141e-07, 0.00540581, -3.97061e-09, 4.73011e-08, 0.999985, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="156"> 0, 1, -1.11494e-13, -1.15717e-07, -2.08616e-07, 7.45058e-09, 8.88178e-15, 0, 1, 1, 1, 1, 0.05, 1, 1.80868e-10, 1.36495e-05, 0.000901487, 1.49012e-08, 1.77636e-14, -2.13163e-14, 1, 1, 1, 1, 0.1, 1, 6.8149e-10, 5.12244e-05, 0.00339634, 7.45058e-09, 1.77636e-15, -2.13163e-14, 1, 1, 1, 1, 0.15, 1, 1.5005e-09, 0.00011289, 0.00747763, 7.45058e-09, 7.10543e-15, -7.10543e-15, 1, 1, 1, 1, 0.2, 1, 2.6273e-09, 0.000197746, 0.0130927, 7.45058e-09, -5.32907e-15, 7.10543e-15, 1, 1, 1, 1, 0.75, 1, 2.00072e-08, 0.00150619, 0.0996987, 7.45058e-09, 3.55271e-15, -1.42109e-14, 1, 1, 1, 1, 0.8, 1, 2.03706e-08, 0.00153358, 0.10151, 1.49012e-08, 3.55271e-15, -1.42109e-14, 1, 1, 1, 1, 0.85, 1, 2.02794e-08, 0.00152671, 0.101055, 1.49012e-08, -5.32907e-15, 7.10543e-15, 1, 1, 1, 1, 0.9, 1, 1.91881e-08, 0.00144463, 0.0956172, 7.45058e-09, -7.10543e-15, 0, 1, 1, 1, 1, 0.95, 1, 1.68664e-08, 0.00126975, 0.084048, 1.49012e-08, 1.77636e-15, -2.13163e-14, 1, 1, 1, 1, 1.15, 1, 2.70661e-09, 0.000203704, 0.0134885, 7.45058e-09, -5.32907e-15, 7.10543e-15, 1, 1, 1, 1, 1.2, 1, 7.26606e-10, 5.46668e-05, 0.00362133, 7.45058e-09, 2.13163e-14, -1.42109e-14, 1, 1, 1, 1, 1.25, 1, -1.10217e-13, -1.15717e-07, -2.02097e-07, 7.45058e-09, -5.32907e-15, 7.10543e-15, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="24"> 0, 1, 4.48581e-08, 0.00292328, 0.204329, 1.04774e-09, -4.44089e-15, 5.58928e-15, 1, 1, 1, 1, 1.25, 1, 4.48581e-08, 0.00292328, 0.204329, 1.74623e-09, -6.21725e-15, 3.40058e-14, 1, 1, 1, 1 </real_array>
-
- </resource>
- <resource type="Animation" path="local://8">
- <string name="resource/name"> "shooting" </string>
- <real name="length"> 0.416667 </real>
- <bool name="loop"> False </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="108"> 0, 1, 2.98023e-07, 3.57628e-07, 2.38419e-07, 0.177354, -0.316176, -0.0334956, 0.931373, 1, 1, 1, 0.05, 1, 5.36442e-07, -1.19209e-07, 5.06639e-07, 0.188185, -0.332103, -0.0311768, 0.923754, 1, 1, 1, 0.1, 1, 7.15256e-07, -3.57628e-07, 5.66244e-07, 0.204001, -0.354515, -0.0276657, 0.912106, 1, 1, 1, 0.15, 1, 6.25849e-07, -1.19209e-07, 4.76837e-07, 0.207621, -0.359465, -0.0268362, 0.909372, 1, 1, 1, 0.2, 1, 4.47035e-07, -1.19209e-07, 4.76837e-07, 0.203765, -0.354216, -0.0277227, 0.912273, 1, 1, 1, 0.35, 1, 6.85453e-07, -3.57628e-07, 5.36442e-07, 0.181322, -0.322103, -0.0326568, 0.928604, 1, 1, 1, 0.4, 1, 5.36442e-07, -1.19209e-07, 4.76837e-07, 0.177926, -0.317037, -0.0333752, 0.930976, 1, 1, 1, 0.45, 1, 2.98023e-07, 3.57628e-07, 2.38419e-07, 0.177354, -0.316176, -0.0334956, 0.931373, 1, 1, 1, 1.25, 1, 2.98023e-07, 3.57628e-07, 2.38419e-07, 0.177354, -0.316176, -0.0334956, 0.931373, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="108"> 0, 1, -4.47035e-07, -2.98023e-07, 0, 0.00444313, -0.215306, 0.0125622, 0.976456, 1, 1, 1, 0.05, 1, -2.08616e-07, -4.17233e-07, -2.98023e-07, 0.00305205, -0.21031, 0.0121764, 0.977554, 1, 1, 1, 0.1, 1, 2.08616e-07, -3.57628e-07, -3.57628e-07, 0.000634907, -0.201765, 0.0115128, 0.979366, 1, 0.999999, 1, 0.15, 1, 1.19209e-07, -1.19209e-07, -4.17233e-07, 2.2336e-05, -0.199561, 0.0113313, 0.97982, 1, 1, 1, 0.2, 1, 2.98023e-07, -8.9407e-08, -4.17233e-07, 0.000688273, -0.201948, 0.0115275, 0.979328, 1, 1, 1, 0.3, 1, -1.78814e-07, -2.68221e-07, -5.96046e-08, 0.00309916, -0.210458, 0.0121876, 0.977522, 1, 1, 1, 0.35, 1, 2.98023e-07, -5.96046e-07, -4.17233e-07, 0.00397812, -0.213611, 0.0124303, 0.976832, 1, 1, 1, 0.4, 1, -2.68221e-07, -4.47035e-07, -1.78814e-07, 0.00437828, -0.215068, 0.0125436, 0.976509, 1, 1, 1, 1.25, 1, -4.47035e-07, -2.98023e-07, 0, 0.00444313, -0.215306, 0.0125622, 0.976456, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="108"> 0, 1, -5.66244e-07, 0, 2.68221e-07, -0.666114, -0.365882, 0.129948, 0.636817, 1, 1, 1, 0.05, 1, -5.96046e-07, -4.76837e-07, 4.76837e-07, -0.656623, -0.392941, 0.132853, 0.629916, 1, 1, 0.999999, 0.1, 1, -1.04308e-06, -5.96046e-07, 7.45058e-07, -0.641339, -0.431274, 0.137762, 0.619442, 1, 1, 1, 0.15, 1, -1.04308e-06, -7.15256e-07, 8.9407e-07, -0.637616, -0.439805, 0.139013, 0.617003, 1, 1, 0.999999, 0.2, 1, 2.98023e-08, 0, 3.27826e-07, -0.641587, -0.430741, 0.137654, 0.61958, 1, 1, 0.999999, 0.35, 1, -2.38419e-07, -3.57628e-07, 1.49012e-07, -0.662747, -0.375915, 0.130927, 0.634281, 1, 1, 0.999999, 0.4, 1, -5.66244e-07, -1.19209e-07, 3.57628e-07, -0.665636, -0.367338, 0.130084, 0.636451, 1, 1, 1, 0.45, 1, -5.66244e-07, 0, 2.68221e-07, -0.666114, -0.365882, 0.129948, 0.636817, 1, 1, 1, 1.25, 1, -5.66244e-07, 0, 2.68221e-07, -0.666114, -0.365882, 0.129948, 0.636817, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="108"> 0, 1, 2.98023e-08, -5.96046e-07, -4.17233e-07, -0.130784, -0.271804, -0.0853016, 0.949601, 1.3, 1.3, 1.3, 0.05, 1, 1.49012e-07, -6.55651e-07, -5.96046e-07, -0.133062, -0.270527, -0.0774246, 0.950324, 1.3, 1.3, 1.3, 0.1, 1, 2.68221e-07, -5.96046e-07, -2.38419e-07, -0.136329, -0.26867, -0.0661281, 0.95124, 1.3, 1.3, 1.3, 0.15, 1, -8.9407e-08, -8.04663e-07, -7.15256e-07, -0.137063, -0.26825, -0.0635932, 0.951426, 1.3, 1.3, 1.3, 0.2, 1, -8.9407e-08, -6.85453e-07, -7.15256e-07, -0.136283, -0.268695, -0.0662837, 0.951229, 1.3, 1.3, 1.3, 0.35, 1, -1.78814e-07, -5.66244e-07, -4.76837e-07, -0.131626, -0.271333, -0.0823877, 0.949876, 1.3, 1.3, 1.3, 0.4, 1, 5.96046e-08, -5.96046e-07, -3.57628e-07, -0.130906, -0.271736, -0.0848797, 0.949641, 1.3, 1.3, 1.3, 0.45, 1, 2.98023e-08, -5.96046e-07, -4.17233e-07, -0.130784, -0.271804, -0.0853016, 0.949601, 1.3, 1.3, 1.3, 1.25, 1, 2.98023e-08, -5.96046e-07, -4.17233e-07, -0.130784, -0.271804, -0.0853016, 0.949601, 1.3, 1.3, 1.3 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="24"> 0, 1, 0, 1.63913e-07, 1.93715e-07, -0.283345, 0.0300071, -0.0426225, 0.957601, 1, 1, 1, 1.25, 1, 0, 1.63913e-07, 1.93715e-07, -0.283345, 0.0300071, -0.0426225, 0.957601, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="24"> 0, 1, 2.29338e-08, 8.9407e-08, 5.36442e-07, -0.369097, -0.0505305, 0.00260278, 0.928013, 1, 1, 1, 1.25, 1, 2.29338e-08, 8.9407e-08, 5.36442e-07, -0.369097, -0.0505305, 0.00260278, 0.928013, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="24"> 0, 1, 1.49012e-08, 0, -5.21541e-08, 0.163945, 0.140221, -0.046324, 0.975354, 1, 1, 1, 1.25, 1, 1.49012e-08, 0, -5.21541e-08, 0.163945, 0.140221, -0.046324, 0.975354, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="24"> 0, 1, 0, 2.08616e-07, 1.49012e-08, 0.284249, 0.0874448, 0.000525696, 0.954754, 1, 1, 1, 1.25, 1, 0, 2.08616e-07, 1.49012e-08, 0.284249, 0.0874448, 0.000525696, 0.954754, 1, 1, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="24"> 0, 1, -6.98492e-10, -2.98023e-08, 4.76837e-07, -0.32359, -0.0556479, 0.000232734, 0.94456, 1, 1, 1, 1.25, 1, -6.98492e-10, -2.98023e-08, 4.76837e-07, -0.32359, -0.0556479, 0.000232734, 0.94456, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="24"> 0, 1, 2.23517e-08, 1.19209e-07, 7.45058e-09, -0.260411, 0.0677016, 0.0123204, 0.963042, 1, 1, 1, 1.25, 1, 2.23517e-08, 1.19209e-07, 7.45058e-09, -0.260411, 0.0677016, 0.0123204, 0.963042, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="24"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="24"> 0, 1, -5.68434e-14, 0, 0.994808, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -5.68434e-14, 0, 0.994808, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="24"> 0, 1, -0.142338, -0.593751, 0.041427, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.142338, -0.593751, 0.041427, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="24"> 0, 1, 0.133965, 1.12742, 1.35169, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.133965, 1.12742, 1.35169, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="24"> 0, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="24"> 0, 1, -0.0204011, -0.122407, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.0204011, -0.122407, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="24"> 0, 1, -0.868295, 0.288818, -0.834593, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.868295, 0.288818, -0.834593, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="24"> 0, 1, 1.73339, 0.895247, 5.13844, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 1.73339, 0.895247, 5.13844, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="24"> 0, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="24"> 0, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="24"> 0, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 1.25, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="24"> 0, 1, 7.45059e-09, -5.21541e-08, 2.38419e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1, 1.25, 1, 7.45059e-09, -5.21541e-08, 2.38419e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="108"> 0, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, 4.95597e-09, 0.00666624, -0.163159, 0.986577, 1, 1, 1, 0.05, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, -0.00988221, 0.00482982, -0.145309, 0.989325, 1, 1, 1, 0.1, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, -0.0244913, 0.00210965, -0.118794, 0.992615, 1, 1, 1, 0.15, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, -0.0278586, 0.00148179, -0.112662, 0.993242, 1, 1, 1, 0.2, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, -0.0242687, 0.00215113, -0.1192, 0.992571, 1, 1, 1, 0.35, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, -0.00360581, 0.00599648, -0.156654, 0.987629, 1, 1, 1, 0.4, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, -0.000519651, 0.00656974, -0.162222, 0.986732, 1, 1, 1, 0.45, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, 4.95597e-09, 0.00666624, -0.163159, 0.986577, 1, 1, 1, 1.25, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, 4.95597e-09, 0.00666624, -0.163159, 0.986577, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="24"> 0, 1, -2.91038e-08, -1.78814e-07, -9.53674e-07, -7.45058e-09, 2.57076e-09, -2.87348e-09, 1, 1, 1, 1, 1.25, 1, -2.91038e-08, -1.78814e-07, -9.53674e-07, -7.45058e-09, 2.57076e-09, -2.87348e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="108"> 0, 1, 1.05648e-08, -8.34465e-07, 8.61473e-09, 0.067043, -0.15676, 0.0458898, 0.984289, 1, 1, 1, 0.05, 1, -2.68221e-08, -7.7486e-07, -7.12462e-08, 0.0563978, -0.14039, 0.0396845, 0.987692, 1, 1, 1, 0.1, 1, 2.66356e-08, -1.78814e-07, -1.87429e-07, 0.0407343, -0.116242, 0.0305639, 0.991915, 1, 1, 1, 0.15, 1, -1.30386e-08, -3.57628e-07, -7.72998e-08, 0.0371396, -0.110688, 0.0284725, 0.992753, 1, 1, 1, 0.2, 1, 2.57045e-08, -5.96046e-07, -9.05711e-08, 0.0409678, -0.116604, 0.0306994, 0.991858, 1, 1, 1, 0.35, 1, 4.0076e-08, -1.78814e-07, -5.26197e-08, 0.0631478, -0.150775, 0.0436179, 0.985584, 1, 1, 1, 0.4, 1, 3.32831e-08, -5.36442e-07, 3.95812e-09, 0.0664811, -0.155897, 0.045562, 0.98448, 1, 1, 1, 0.45, 1, 1.05648e-08, -8.34465e-07, 8.61473e-09, 0.067043, -0.15676, 0.0458898, 0.984289, 1, 1, 1, 1.25, 1, 1.05648e-08, -8.34465e-07, 8.61473e-09, 0.067043, -0.15676, 0.0458898, 0.984289, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="24"> 0, 1, -7.38021e-13, 4.70318e-08, 9.16189e-08, -1.036e-25, -3.37508e-14, -8.17124e-13, 1, 1, 1, 1, 1.25, 1, -7.38021e-13, 4.70318e-08, 9.16189e-08, -1.036e-25, -3.37508e-14, -8.17124e-13, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="24"> 0, 1, 4.48982e-08, 0.00292331, 0.204329, 8.84756e-09, -3.8014e-13, 5.94471e-12, 1, 1, 1, 1, 1.25, 1, 4.48982e-08, 0.00292331, 0.204329, 8.84756e-09, -3.8014e-13, 5.94471e-12, 1, 1, 1, 1 </real_array>
-
- </resource>
- <resource type="Animation" path="local://9">
- <string name="resource/name"> "falling-cycle" </string>
- <real name="length"> 0.416667 </real>
- <bool name="loop"> True </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="132"> 0, 1, 2.98023e-08, 1.19209e-07, -2.98023e-08, -0.336022, 0.262721, 0.175267, 0.887326, 1, 1, 1, 0.05, 1, 7.45058e-07, -3.57628e-07, 5.36442e-07, -0.336851, 0.262046, 0.173695, 0.887521, 1, 1, 1, 0.1, 1, 8.34465e-07, -5.96046e-07, 7.15256e-07, -0.33853, 0.260365, 0.16952, 0.888184, 1, 1, 1, 0.15, 1, 8.9407e-07, -3.57628e-07, 8.9407e-07, -0.338209, 0.258327, 0.163568, 0.890015, 1, 1, 1, 0.2, 1, 5.96046e-07, -3.57628e-07, 7.45058e-07, -0.333363, 0.256341, 0.157703, 0.89347, 1, 1, 1, 0.25, 1, 1.43051e-06, -8.34465e-07, 1.3113e-06, -0.339001, 0.253177, 0.158008, 0.892196, 1, 1, 0.999999, 0.3, 1, 5.96046e-07, -1.19209e-07, 2.98023e-07, -0.348081, 0.252511, 0.164449, 0.887713, 1, 1, 1, 0.35, 1, 1.07288e-06, -5.96046e-07, 7.45058e-07, -0.343056, 0.25799, 0.170697, 0.886914, 1, 1, 1, 0.4, 1, 3.27826e-07, 0, 2.38419e-07, -0.337258, 0.26196, 0.174599, 0.887214, 1, 1, 1, 0.45, 1, 2.98023e-08, 1.19209e-07, -2.98023e-08, -0.336022, 0.262721, 0.175267, 0.887326, 1, 1, 1, 1.25, 1, 2.98023e-08, 1.19209e-07, -2.98023e-08, -0.336022, 0.262721, 0.175267, 0.887326, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="120"> 0, 1, 3.27826e-07, -6.55651e-07, -4.17233e-07, 0.46904, -0.387773, 0.0221851, 0.793184, 1, 1, 1, 0.05, 1, -1.49012e-07, -8.34465e-07, -5.36442e-07, 0.467449, -0.38757, 0.0209387, 0.794256, 1, 0.999999, 1, 0.15, 1, 8.9407e-08, -8.34465e-07, -2.38419e-07, 0.457674, -0.38779, 0.0142454, 0.799969, 1, 1, 1, 0.2, 1, -1.19209e-07, -9.53674e-07, -5.96046e-07, 0.453414, -0.391376, 0.0115749, 0.800692, 1, 1, 1, 0.25, 1, -2.98023e-08, -8.64267e-07, -5.96046e-07, 0.455951, -0.392917, 0.0127032, 0.798476, 1, 1, 1, 0.3, 1, -2.68221e-07, -5.96046e-07, -3.57628e-07, 0.461696, -0.389009, 0.0167183, 0.797013, 1, 1, 1, 0.35, 1, 5.96046e-08, -9.23872e-07, -5.96046e-07, 0.465445, -0.38698, 0.0198743, 0.795747, 1, 1, 1, 0.4, 1, 2.68221e-07, -8.64267e-07, -6.55651e-07, 0.4685, -0.387548, 0.0218417, 0.793623, 1, 1, 1, 0.45, 1, 3.27826e-07, -6.55651e-07, -4.17233e-07, 0.46904, -0.387773, 0.0221851, 0.793184, 1, 1, 1, 1.25, 1, 3.27826e-07, -6.55651e-07, -4.17233e-07, 0.46904, -0.387773, 0.0221851, 0.793184, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="132"> 0, 1, -2.98023e-08, 1.19209e-07, -2.98023e-08, -0.326141, -0.23441, -0.185472, 0.896819, 1, 1, 1, 0.05, 1, -9.53674e-07, -4.76837e-07, 5.66244e-07, -0.309655, -0.239675, -0.179325, 0.902503, 1, 1, 1, 0.1, 1, -8.64267e-07, -4.76837e-07, 7.15256e-07, -0.27681, -0.251556, -0.166111, 0.912416, 1, 1, 1, 0.15, 1, -8.64267e-07, -3.57628e-07, 8.04663e-07, -0.254018, -0.264552, -0.15679, 0.917008, 1, 1, 1, 0.2, 1, -4.76837e-07, -3.57628e-07, 4.47035e-07, -0.251196, -0.272504, -0.156931, 0.915431, 1, 1, 1, 0.25, 1, -1.13249e-06, -7.15256e-07, 8.9407e-07, -0.279016, -0.258742, -0.169921, 0.909027, 1, 1, 1, 0.3, 1, -7.15256e-07, 1.19209e-07, 5.06639e-07, -0.316679, -0.238757, -0.183476, 0.89947, 1, 1, 1, 0.35, 1, -6.25849e-07, -1.19209e-07, 3.57628e-07, -0.327726, -0.235686, -0.18601, 0.895795, 1, 1, 1, 0.4, 1, -2.68221e-07, 0, 1.49012e-07, -0.326797, -0.234512, -0.185665, 0.896514, 1, 1, 1, 0.45, 1, -2.98023e-08, 1.19209e-07, -2.98023e-08, -0.326141, -0.23441, -0.185472, 0.896819, 1, 1, 1, 1.25, 1, -2.98023e-08, 1.19209e-07, -2.98023e-08, -0.326141, -0.23441, -0.185472, 0.896819, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="120"> 0, 1, -2.08616e-07, -1.54972e-06, -1.19209e-07, 0.47174, 0.366267, -0.0198596, 0.80182, 1, 1, 1, 0.05, 1, -2.98023e-08, -6.25849e-07, 0, 0.468656, 0.375596, -0.0166676, 0.799382, 1, 1, 1, 0.1, 1, -8.9407e-08, -2.68221e-07, -5.96046e-08, 0.459943, 0.392089, -0.0107327, 0.79662, 1, 1, 1, 0.15, 1, -2.08616e-07, -2.08616e-07, -2.38419e-07, 0.451048, 0.400355, -0.00696642, 0.797636, 1, 1, 1, 0.2, 1, -2.38419e-07, -7.7486e-07, 0, 0.448637, 0.398723, -0.00658308, 0.799813, 1, 1, 1, 0.3, 1, -5.96046e-08, -2.98023e-07, -4.17233e-07, 0.465357, 0.361793, -0.0151844, 0.807662, 1, 1, 1, 0.35, 1, -1.49012e-07, -5.36442e-07, -3.57628e-07, 0.468536, 0.360417, -0.0183993, 0.806372, 1, 1, 1, 0.4, 1, -5.96046e-08, -8.64267e-07, -1.78814e-07, 0.471244, 0.365087, -0.0196777, 0.802654, 1, 1, 1, 0.45, 1, -2.08616e-07, -1.54972e-06, -1.19209e-07, 0.47174, 0.366267, -0.0198596, 0.80182, 1, 1, 1, 1.25, 1, -2.08616e-07, -1.54972e-06, -1.19209e-07, 0.47174, 0.366267, -0.0198596, 0.80182, 1, 1, 1 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="132"> 0, 1, 0, 7.45058e-09, -1.3411e-07, -0.0625169, 0.00920125, -0.00328561, 0.997996, 1, 1, 1, 0.05, 1, 5.96046e-08, 8.9407e-08, -6.10948e-07, -0.0877092, 0.00901381, -0.00306586, 0.996101, 1, 1, 1, 0.1, 1, 5.96046e-08, -2.23517e-08, -1.19209e-07, -0.138998, 0.00794913, -0.00288258, 0.990257, 1, 1, 1, 0.15, 1, 5.96046e-08, 1.49012e-08, -4.02331e-07, -0.178155, 0.00579277, -0.00296187, 0.983981, 1, 1, 1, 0.2, 1, 8.9407e-08, 0, 1.78814e-07, -0.18648, 0.0038127, -0.0029159, 0.982447, 1, 1, 1, 0.25, 1, 5.96046e-08, 5.21541e-08, -1.93715e-07, -0.189861, 0.00940162, -0.00299906, 0.981761, 1, 1, 1, 0.3, 1, 5.96046e-08, -5.96046e-08, 2.83122e-07, -0.170763, 0.015059, -0.00307746, 0.985192, 1, 1, 1, 0.35, 1, 0, -7.45058e-09, -1.3411e-07, -0.115285, 0.0123617, -0.00312517, 0.993251, 1, 1, 1, 0.4, 1, 0, 7.45058e-09, -1.3411e-07, -0.0713277, 0.00977016, -0.00325209, 0.9974, 1, 1, 1, 0.45, 1, 0, 7.45058e-09, -1.3411e-07, -0.0625169, 0.00920125, -0.00328561, 0.997996, 1, 1, 1, 1.25, 1, 0, 7.45058e-09, -1.3411e-07, -0.0625169, 0.00920125, -0.00328561, 0.997996, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="120"> 0, 1, 4.42378e-08, -8.19564e-08, 1.78814e-07, -0.407694, 0.0277893, 0.000765211, 0.912696, 1, 1, 1, 0.05, 1, 1.89757e-08, -5.21541e-08, 6.55651e-07, -0.435809, 0.0297697, 0.000893482, 0.899546, 1, 1, 1, 0.1, 1, 1.42027e-08, 6.70552e-08, 7.15256e-07, -0.489147, 0.0339313, 0.00115069, 0.871541, 1, 1, 1, 0.15, 1, 1.13854e-07, 0, 5.96046e-07, -0.523927, 0.0370339, 0.00133512, 0.850957, 1, 1, 1, 0.2, 1, 1.29221e-07, -3.72529e-08, 4.17233e-07, -0.526448, 0.0372296, 0.00134975, 0.849391, 1, 1, 1, 0.25, 1, 1.6077e-07, -2.68221e-07, 4.76837e-07, -0.538369, 0.0372441, 0.00135905, 0.841885, 1, 1, 1, 0.3, 1, 6.17001e-09, -1.04308e-07, 7.15256e-07, -0.530237, 0.0358611, 0.00127618, 0.84709, 1, 1, 1, 0.4, 1, 2.08383e-08, -2.23517e-08, 4.17233e-07, -0.418447, 0.0284447, 0.00080823, 0.907795, 1, 1, 1, 0.45, 1, 4.42378e-08, -8.19564e-08, 1.78814e-07, -0.407694, 0.0277893, 0.000765211, 0.912696, 1, 1, 1, 1.25, 1, 4.42378e-08, -8.19564e-08, 1.78814e-07, -0.407694, 0.0277893, 0.000765211, 0.912696, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="24"> 0, 1, 1.04308e-07, -1.19209e-07, 6.70552e-08, -1.11759e-08, 1.16415e-09, 7.45058e-09, 1, 1, 1, 1, 1.25, 1, 1.04308e-07, -1.19209e-07, 6.70552e-08, -1.11759e-08, 1.16415e-09, 7.45058e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="120"> 0, 1, -2.98023e-08, 1.49012e-08, 1.19209e-07, -0.630421, -0.0882657, 0.00990556, 0.771155, 1, 1, 1, 0.05, 1, 8.9407e-08, 9.68575e-08, -2.38419e-07, -0.641086, -0.0918399, 0.00914405, 0.7619, 1, 1, 1, 0.15, 1, 5.96046e-08, 2.23517e-08, -1.3411e-07, -0.695929, -0.109196, 0.0054072, 0.70974, 1, 1, 1, 0.2, 1, 0, 7.45058e-09, 4.61936e-07, -0.716484, -0.115048, 0.00471066, 0.688035, 0.999999, 1, 1, 0.25, 1, 2.98023e-08, 5.21541e-08, 7.45058e-08, -0.742062, -0.116709, 0.0109015, 0.660003, 1, 1, 1, 0.3, 1, -5.96046e-08, -6.70552e-08, 5.51343e-07, -0.738131, -0.110711, 0.0165993, 0.665304, 0.999999, 1, 1, 0.35, 1, -2.98023e-08, -1.49012e-08, 1.19209e-07, -0.683291, -0.098194, 0.0131016, 0.723395, 1, 1, 1, 0.4, 1, -2.98023e-08, 1.49012e-08, 1.19209e-07, -0.638973, -0.0897534, 0.0103931, 0.763904, 1, 1, 1, 0.45, 1, -2.98023e-08, 1.49012e-08, 1.19209e-07, -0.630421, -0.0882657, 0.00990556, 0.771155, 1, 1, 1, 1.25, 1, -2.98023e-08, 1.49012e-08, 1.19209e-07, -0.630421, -0.0882657, 0.00990556, 0.771155, 1, 1, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="120"> 0, 1, 4.48199e-08, -1.11759e-07, 1.78814e-07, -0.822993, -0.106344, -0.00540277, 0.557982, 1, 1, 1, 0.05, 1, 4.30737e-09, -2.08616e-07, -1.19209e-07, -0.827005, -0.107477, -0.00546779, 0.551799, 1, 1, 1, 0.1, 1, 8.84756e-09, -1.19209e-07, 1.19209e-07, -0.836608, -0.110063, -0.00562015, 0.536601, 1, 1, 1, 0.2, 1, -2.91038e-08, 1.19209e-07, 0, -0.857806, -0.115929, -0.00596456, 0.500693, 1, 1, 1, 0.25, 1, 7.33417e-09, 0, 5.96046e-08, 0.876669, 0.123709, 0.00633999, -0.464874, 1, 1, 1, 0.3, 1, -4.38886e-08, -1.3411e-07, -1.19209e-07, 0.881066, 0.125876, 0.00641456, -0.455891, 1, 1, 1, 0.35, 1, 9.66247e-09, 0, -5.96046e-08, -0.853515, -0.11545, -0.00587343, 0.508083, 1, 1, 1, 0.4, 1, 2.17697e-08, -3.72529e-08, 5.96046e-08, -0.828218, -0.107764, -0.00547631, 0.549921, 1, 1, 1, 0.45, 1, 4.48199e-08, -1.11759e-07, 1.78814e-07, -0.822993, -0.106344, -0.00540277, 0.557982, 1, 1, 1, 1.25, 1, 4.48199e-08, -1.11759e-07, 1.78814e-07, -0.822993, -0.106344, -0.00540277, 0.557982, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="24"> 0, 1, 7.45058e-09, -2.38419e-07, -8.19564e-08, -1.86265e-08, -1.28057e-09, 3.72529e-09, 1, 1, 1, 1, 1.25, 1, 7.45058e-09, -2.38419e-07, -8.19564e-08, -1.86265e-08, -1.28057e-09, 3.72529e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="24"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="108"> 0, 1, -5.68434e-14, 0, 2.81136, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -5.68434e-14, 0, 2.88275, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, 5.68434e-14, 4.76837e-07, 3.22584, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, 5.68434e-14, 4.76837e-07, 3.31311, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.25, 1, 5.68434e-14, 4.76837e-07, 3.27685, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, -5.68434e-14, 0, 2.93405, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.4, 1, -5.68434e-14, 0, 2.82965, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, -5.68434e-14, 0, 2.81136, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -5.68434e-14, 0, 2.81136, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="120"> 0, 1, -5.96046e-08, 0.623878, 0.831837, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -5.96046e-08, 0.623878, 0.85661, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, -5.96046e-08, 0.623878, 0.907642, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, -5.96046e-08, 0.623878, 0.942906, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, -5.96046e-08, 0.623878, 0.943599, 0, 0, 0, 1, 1, 1, 1, 0.25, 1, -5.96046e-08, 0.623878, 0.921011, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, -5.96046e-08, 0.623878, 0.851786, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, -5.96046e-08, 0.623878, 0.834743, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, -5.96046e-08, 0.623878, 0.831837, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -5.96046e-08, 0.623878, 0.831837, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="132"> 0, 1, -1.19209e-07, 1.00668e-07, 1.33339, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -1.19209e-07, 1.01535e-07, 1.34488, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, -1.19209e-07, 1.0373e-07, 1.37395, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, -1.19209e-07, 1.06482e-07, 1.41041, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, -1.19209e-07, 1.08677e-07, 1.43947, 0, 0, 0, 1, 1, 1, 1, 0.25, 1, -1.19209e-07, 1.09544e-07, 1.45096, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, -1.19209e-07, 1.07675e-07, 1.4262, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, -1.19209e-07, 1.03822e-07, 1.37517, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, -1.19209e-07, 1.01159e-07, 1.33989, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, -1.19209e-07, 1.00668e-07, 1.33339, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -1.19209e-07, 1.00668e-07, 1.33339, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="24"> 0, 1, -2.98023e-08, 1.19209e-07, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -2.98023e-08, 1.19209e-07, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="24"> 0, 1, 2.98023e-08, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 2.98023e-08, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="132"> 0, 1, -1.39671, 2.72686, 1.19541, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -1.39671, 2.70532, 1.19971, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -1.39671, 2.65088, 1.2106, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, -1.39671, 2.5826, 1.22425, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, -1.39671, 2.52819, 1.23514, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, -1.39671, 2.50668, 1.23944, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, -1.39671, 2.55303, 1.23017, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.35, 1, -1.39671, 2.64856, 1.21105, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -1.39671, 2.71466, 1.19784, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -1.39671, 2.72686, 1.19541, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -1.39671, 2.72686, 1.19541, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="120"> 0, 1, 1.27388, 2.72686, 1.19541, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 1.27388, 2.68042, 1.20468, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, 1.27388, 2.58486, 1.2238, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, 1.27388, 2.51885, 1.23701, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, 1.27388, 2.51756, 1.23727, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, 1.27388, 2.55985, 1.22881, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, 1.27388, 2.68948, 1.20288, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, 1.27388, 2.72141, 1.19649, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, 1.27388, 2.72686, 1.19541, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 1.27388, 2.72686, 1.19541, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="24"> 0, 1, 0.59069, -0.00390959, 0.736489, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.59069, -0.00390959, 0.736489, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="24"> 0, 1, -0.59069, -0.00390959, 0.736489, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.59069, -0.00390959, 0.736489, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="120"> 0, 1, -9.25123e-16, 1.16368e-07, -0.513782, -0.068257, 1.03065e-08, 8.40178e-15, 0.997668, 1, 1, 1, 0.05, 1, -0.00604435, -0.0171726, -0.516875, -0.068257, 1.03065e-08, 1.59689e-14, 0.997668, 1, 1, 1, 0.15, 1, -0.0352723, -0.100186, -0.531832, -0.068257, 1.03065e-08, 8.79127e-15, 0.997668, 1, 1, 1, 0.2, 1, -0.0427212, -0.121339, -0.535645, -0.068257, 1.03065e-08, 1.59689e-14, 0.997668, 1, 1, 1, 0.25, 1, -0.0251165, -0.102747, -0.494262, -0.068257, 1.03065e-08, 8.40178e-15, 0.997668, 1, 1, 1, 0.3, 1, -0.00387635, -0.0612733, -0.455449, -0.068257, 1.03065e-08, 8.79127e-15, 0.997668, 1, 1, 1, 0.35, 1, -0.000906605, -0.0266833, -0.479965, -0.068257, 1.03065e-08, 1.59689e-14, 0.997668, 1, 1, 1, 0.4, 1, -5.88306e-05, -0.00401501, -0.507859, -0.068257, 1.03065e-08, 8.79127e-15, 0.997668, 1, 1, 1, 0.45, 1, -9.25123e-16, 1.16368e-07, -0.513782, -0.068257, 1.03065e-08, 8.40178e-15, 0.997668, 1, 1, 1, 1.25, 1, -9.25123e-16, 1.16368e-07, -0.513782, -0.068257, 1.03065e-08, 8.40178e-15, 0.997668, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="108"> 0, 1, -5.25618e-15, 1.49011e-08, -1.49012e-07, 0.0904093, -6.07213e-16, 7.18977e-15, 0.995905, 1, 1, 1, 0.05, 1, -2.67973e-10, 2.32644e-08, -5.96046e-08, 0.0920949, -3.47794e-16, 7.16792e-15, 0.99575, 1, 1, 1, 0.15, 1, 2.52298e-09, 2.61876e-08, -2.98023e-08, 0.100243, -1.17281e-15, 7.25956e-15, 0.994963, 1, 1, 1, 0.2, 1, -5.62989e-10, 3.32728e-08, -1.49012e-07, 0.102318, -1.15767e-15, 7.26199e-15, 0.994752, 1, 1, 1, 0.25, 1, -1.24048e-09, 3.35948e-08, -8.9407e-08, 0.101456, -6.3375e-16, 7.20691e-15, 0.99484, 1, 1, 1, 0.35, 1, 8.229e-13, 2.99392e-08, -1.49012e-07, 0.0933096, -3.39049e-16, 7.16834e-15, 0.995637, 1, 1, 1, 0.4, 1, -3.31995e-12, 2.53408e-08, -1.49012e-07, 0.0908406, -1.44454e-15, 1.31767e-16, 0.995865, 1, 1, 1, 0.45, 1, -5.25618e-15, 1.49011e-08, -1.49012e-07, 0.0904093, -6.07213e-16, 7.18977e-15, 0.995905, 1, 1, 1, 1.25, 1, -5.25618e-15, 1.49011e-08, -1.49012e-07, 0.0904093, -6.07213e-16, 7.18977e-15, 0.995905, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="108"> 0, 1, -1.31025e-21, 7.45058e-09, -1.78814e-07, 0.0570428, -7.52314e-16, -1.03276e-15, 0.998372, 1, 1, 1, 0.05, 1, -6.93196e-14, 7.45058e-09, 0, 0.0590419, -0.00284152, 0.000283556, 0.998251, 1, 1, 1, 0.15, 1, 7.44988e-10, -3.72529e-09, 0, 0.0686997, -0.0165823, 0.00165476, 0.997498, 1, 1, 1, 0.2, 1, -7.04617e-14, -7.45058e-09, -5.96046e-08, 0.0711578, -0.0200834, 0.00200414, 0.997261, 1, 1, 1, 0.25, 1, -6.96491e-14, -3.72529e-09, -5.96046e-08, 0.0701373, -0.0186297, 0.00185908, 0.997362, 1, 1, 1, 0.35, 1, 6.97804e-11, 7.45058e-09, -1.78814e-07, 0.0604823, -0.00488944, 0.000487919, 0.998157, 1, 1, 1, 0.4, 1, -2.75782e-14, 1.11759e-08, -2.38419e-07, 0.0575543, -0.000727023, 7.25494e-05, 0.998342, 1, 1, 1, 0.45, 1, -1.31025e-21, 7.45058e-09, -1.78814e-07, 0.0570428, -7.52314e-16, -1.03276e-15, 0.998372, 1, 1, 1, 1.25, 1, -1.31025e-21, 7.45058e-09, -1.78814e-07, 0.0570428, -7.52314e-16, -1.03276e-15, 0.998372, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="24"> 0, 1, -8.52651e-14, -4.47035e-08, -4.76837e-07, -7.45058e-09, 2.13163e-14, -1.77636e-15, 1, 1, 1, 1, 1.25, 1, -8.52651e-14, -4.47035e-08, -4.76837e-07, -7.45058e-09, 2.13163e-14, -1.77636e-15, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="120"> 0, 1, 1.77636e-14, -4.17233e-07, -3.53903e-08, -0.197724, -1.34662e-08, 4.54456e-08, 0.980258, 1, 1, 1, 0.05, 1, -1.95943e-09, -5.06639e-07, -6.40284e-08, -0.199636, 0.000196518, -0.00285815, 0.979866, 1, 1, 1, 0.15, 1, -2.19083e-08, -2.38419e-07, -5.75092e-08, -0.207914, 0.00144056, -0.0167025, 0.978003, 1, 1, 1, 0.2, 1, 6.08469e-09, -3.8743e-07, -6.33299e-08, -0.209803, 0.00183038, -0.0202351, 0.977533, 1, 1, 1, 0.25, 1, -4.45088e-08, -8.64267e-07, -5.21541e-08, -0.20649, 0.000358444, -0.0190238, 0.978264, 1, 1, 1, 0.3, 1, 7.56265e-09, -8.34465e-07, -4.84288e-08, -0.200537, -0.000986884, -0.0126263, 0.979604, 1, 1, 1, 0.35, 1, 3.42126e-11, -4.17233e-07, -2.37487e-08, -0.198104, -0.000490507, -0.00505109, 0.980168, 1, 1, 1, 0.4, 1, 3.9655e-10, -3.57628e-07, -3.05008e-08, -0.197722, -8.26043e-05, -0.000750033, 0.980258, 1, 1, 1, 0.45, 1, 1.77636e-14, -4.17233e-07, -3.53903e-08, -0.197724, -1.34662e-08, 4.54456e-08, 0.980258, 1, 1, 1, 1.25, 1, 1.77636e-14, -4.17233e-07, -3.53903e-08, -0.197724, -1.34662e-08, 4.54456e-08, 0.980258, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="24"> 0, 1, 2.81164e-14, 2.468e-08, 3.32249e-07, 2.23517e-08, -5.32907e-15, 7.10543e-15, 1, 1, 1, 1, 1.25, 1, 2.81164e-14, 2.468e-08, 3.32249e-07, 2.23517e-08, -5.32907e-15, 7.10543e-15, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="24"> 0, 1, 7.99361e-14, 1.49012e-07, -8.34465e-07, 2.43308e-08, 6.21725e-15, -8.59209e-15, 1, 1, 1, 1, 1.25, 1, 7.99361e-14, 1.49012e-07, -8.34465e-07, 2.43308e-08, 6.21725e-15, -8.59209e-15, 1, 1, 1, 1 </real_array>
-
- </resource>
- <resource type="Animation" path="local://10">
- <string name="resource/name"> "default" </string>
- <real name="length"> 1.25 </real>
- <bool name="loop"> False </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="12"> 0, 1, 5.06639e-07, -1.19209e-07, 3.57628e-07, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="12"> 0, 1, 1.19209e-07, -8.9407e-07, -1.19209e-07, -3.72529e-08, -1.49012e-08, 2.23517e-08, 1, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="12"> 0, 1, -5.06639e-07, -1.19209e-07, 3.57628e-07, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="12"> 0, 1, -1.19209e-07, -8.9407e-07, -1.19209e-07, -3.72529e-08, 1.49012e-08, -2.23517e-08, 1, 1, 1, 1 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="12"> 0, 1, 0, 2.98023e-08, -2.5332e-07, 0, 5.20417e-18, -2.79397e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="12"> 0, 1, 2.10712e-08, -7.45058e-09, 5.96046e-07, 7.45058e-09, 3.60887e-09, 3.91446e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="12"> 0, 1, 6.70552e-08, 1.19209e-07, 0, 3.72529e-09, 1.16415e-09, 3.72529e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="12"> 0, 1, 0, 2.98023e-08, -1.49012e-08, 1.86265e-09, 7.45058e-09, 2.09548e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="12"> 0, 1, 1.74623e-08, -2.98023e-08, 2.98023e-07, 3.72529e-09, 7.45058e-09, -1.17143e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="12"> 0, 1, 1.49012e-08, 0, 0, 0, -1.39698e-09, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="12"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="12"> 0, 1, -5.68434e-14, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="12"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="12"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="12"> 0, 1, -2.98023e-08, 1.19209e-07, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="12"> 0, 1, 2.98023e-08, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="12"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="12"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="12"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="12"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="12"> 0, 1, 0, -2.84217e-14, 0, 0, 0, 1.44945e-21, 1, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="12"> 0, 1, -6.35275e-21, 2.84217e-14, 0, 0, 0, 2.44616e-35, 1, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="12"> 0, 1, -3.38813e-21, 0, 0, 0, 0, -1.33383e-23, 1, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="12"> 0, 1, -8.52651e-14, -5.96046e-08, -7.15256e-07, 1.17383e-27, 2.13163e-14, 5.50671e-14, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="12"> 0, 1, -1.77636e-13, 5.96046e-08, -5.98375e-08, 7.45058e-09, 1.04639e-13, -2.13163e-14, 1, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="12"> 0, 1, -2.30926e-14, -1.22469e-07, 2.39583e-07, -2.52436e-28, 7.10543e-15, -7.10543e-15, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="12"> 0, 1, 3.55271e-15, 5.96046e-08, -7.15256e-07, 1.97906e-09, -2.66454e-15, 5.59448e-15, 1, 1, 1, 1 </real_array>
-
- </resource>
- <resource type="Animation" path="local://11">
- <string name="resource/name"> "run-cycle" </string>
- <real name="length"> 0.833333 </real>
- <bool name="loop"> True </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="192"> 0, 1, 9.23872e-07, -3.57628e-07, 5.66244e-07, 0.222344, -0.226466, -0.0274315, 0.947905, 1, 1, 1, 0.05, 1, 6.55651e-07, -1.19209e-07, 2.98023e-07, 0.251975, -0.208305, -0.0408158, 0.944167, 1, 1, 1, 0.15, 1, 1.07288e-06, -3.57628e-07, 5.36442e-07, 0.379887, -0.057225, -0.102903, 0.917509, 1, 1, 1, 0.2, 1, 6.25849e-07, -3.57628e-07, 7.45058e-07, 0.418674, -0.00696497, -0.113328, 0.901011, 1, 1, 1, 0.25, 1, 8.64267e-07, -3.57628e-07, 3.8743e-07, 0.413182, 0.0386478, -0.0801881, 0.906287, 1, 1, 1, 0.3, 1, 9.53674e-07, -4.76837e-07, 5.96046e-07, 0.315261, 0.124735, -0.0152523, 0.940648, 1, 1, 1, 0.4, 1, 6.25849e-07, -3.57628e-07, 4.17233e-07, -0.151881, 0.360683, -0.0357324, 0.919545, 1, 1, 0.999999, 0.45, 1, 6.25849e-07, -3.57628e-07, 7.45058e-07, -0.172392, 0.343529, -0.046079, 0.922034, 1, 1, 0.999999, 0.55, 1, 6.55651e-07, -3.57628e-07, 5.36442e-07, 0.168352, 0.0191591, -0.0776353, 0.982478, 1, 1, 1, 0.6, 1, 9.53674e-07, -3.57628e-07, 3.27826e-07, 0.182793, -0.0233152, -0.109476, 0.976759, 1, 1, 1, 0.65, 1, 4.17233e-07, 0, 1.78814e-07, 0.138039, -0.0157468, -0.121765, 0.982787, 1, 1, 1, 0.7, 1, 6.25849e-07, -2.38419e-07, 1.78814e-07, 0.121673, -0.0809579, -0.109793, 0.983152, 1, 1, 1, 0.75, 1, 9.23872e-07, -3.57628e-07, 7.45058e-07, 0.131274, -0.176942, -0.0767055, 0.972407, 1, 1, 1, 0.8, 1, 5.66244e-07, -1.19209e-07, 5.96046e-07, 0.13073, -0.218021, -0.0501677, 0.965847, 1, 1, 1, 0.85, 1, 2.98023e-08, 0, -5.96046e-08, 0.129118, -0.224691, -0.0428281, 0.964888, 1, 1, 1, 1.25, 1, 2.98023e-08, 0, -5.96046e-08, 0.129118, -0.224691, -0.0428281, 0.964888, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="180"> 0, 1, 0, -4.17233e-07, -3.57628e-07, -0.0379169, -0.0715942, 0.00193508, 0.996711, 1, 1, 1, 0.05, 1, -1.78814e-07, -5.96046e-07, -4.17233e-07, -0.000241383, -0.109076, 0.00379063, 0.994026, 1, 1, 1, 0.1, 1, 8.9407e-08, -6.55651e-07, -6.55651e-07, 0.0679255, -0.167209, 0.00334064, 0.983573, 1, 0.999999, 1, 0.25, 1, -1.19209e-07, -3.8743e-07, 0, 0.158727, -0.350464, 0.00627285, 0.923007, 1, 1, 1, 0.3, 1, -3.27826e-07, -6.85453e-07, 1.78814e-07, 0.146536, -0.393807, 0.00119701, 0.907437, 1, 1, 1, 0.35, 1, -8.9407e-08, -6.55651e-07, -3.57628e-07, 0.153485, -0.416977, -0.0128296, 0.895772, 1, 1, 1, 0.4, 1, 8.9407e-08, -9.83477e-07, -5.36442e-07, 0.172873, -0.368078, -0.014432, 0.913469, 1, 0.999999, 1, 0.45, 1, 0, -9.83477e-07, -1.19209e-07, 0.191151, -0.391536, -0.0140892, 0.899979, 1, 1, 1, 0.5, 1, 8.9407e-08, -5.96046e-07, -6.55651e-07, 0.210133, -0.527231, -0.0202225, 0.823081, 1, 1, 1, 0.55, 1, 2.68221e-07, -6.25849e-07, -4.17233e-07, 0.159334, -0.589231, -0.00909611, 0.792046, 1, 1, 1, 0.65, 1, -1.19209e-07, -6.85453e-07, -7.15256e-07, 0.0168538, -0.43832, 0.0104639, 0.8986, 1, 1, 1, 0.7, 1, 1.78814e-07, -5.36442e-07, -1.78814e-07, -0.00524541, -0.376783, 0.0174757, 0.926122, 1, 1, 1, 0.8, 1, -5.96046e-08, -7.15256e-07, -5.36442e-07, 0.00762745, -0.243737, 0.014512, 0.969703, 1, 1, 1, 0.85, 1, 1.19209e-07, -6.85453e-07, -7.7486e-07, 0.00858928, -0.221202, 0.0126834, 0.975108, 1, 1, 1, 1.25, 1, 1.19209e-07, -6.85453e-07, -7.7486e-07, 0.00858928, -0.221202, 0.0126834, 0.975108, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="228"> 0, 1, -9.53674e-07, -5.96046e-07, 4.76837e-07, -0.211109, -0.378307, 0.04716, 0.900052, 1, 1, 1, 0.05, 1, -9.53674e-07, 1.19209e-07, 3.57628e-07, -0.122361, -0.307485, 0.0444022, 0.942608, 1, 1, 1, 0.1, 1, -6.85453e-07, -2.38419e-07, 5.96046e-07, 0.0655243, -0.124344, 0.0558387, 0.988497, 1, 1, 1, 0.15, 1, -7.7486e-07, -1.19209e-07, 5.66244e-07, 0.17223, 0.0168325, 0.088774, 0.980904, 1, 1, 1, 0.2, 1, -5.36442e-07, -3.57628e-07, 5.36442e-07, 0.151153, 0.0193605, 0.111763, 0.981981, 1, 1, 1, 0.25, 1, -6.25849e-07, -3.57628e-07, 5.96046e-07, 0.105831, 0.0199286, 0.119921, 0.986925, 1, 1, 1, 0.3, 1, -1.19209e-06, -5.96046e-07, 6.25849e-07, 0.11, 0.117841, 0.0973986, 0.982103, 1, 1, 1, 0.35, 1, -5.36442e-07, -1.19209e-07, 4.47035e-07, 0.163427, 0.213955, 0.0590648, 0.961263, 1, 1, 1, 0.4, 1, -6.85453e-07, -3.57628e-07, 5.06639e-07, 0.212517, 0.23167, 0.0327435, 0.948733, 1, 1, 1, 0.45, 1, -8.04663e-07, -2.38419e-07, 5.66244e-07, 0.240572, 0.207043, 0.0320326, 0.947751, 1, 1, 1, 0.5, 1, -9.23872e-07, 0, 8.04663e-07, 0.292283, 0.151342, 0.0529747, 0.942794, 1, 1, 1, 0.55, 1, -6.85453e-07, -3.57628e-07, 3.57628e-07, 0.354424, 0.0696654, 0.0852169, 0.928584, 1, 1, 1, 0.6, 1, -5.66244e-07, -2.38419e-07, 2.98023e-07, 0.397207, 0.0175472, 0.104303, 0.911614, 1, 1, 1, 0.65, 1, -8.34465e-07, -2.38419e-07, 4.47035e-07, 0.407225, -0.0166533, 0.0875941, 0.908965, 1, 1, 1, 0.7, 1, -1.2517e-06, -1.19209e-07, 6.55651e-07, 0.349327, -0.0813931, 0.0308211, 0.93295, 1, 1, 1, 0.75, 1, -1.19209e-07, 1.19209e-07, 2.08616e-07, 0.214708, -0.14004, -0.012317, 0.966508, 1, 1, 1, 0.8, 1, -6.55651e-07, -1.19209e-07, 2.98023e-07, -0.00140518, -0.171137, -0.0177305, 0.985087, 1, 1, 1, 0.85, 1, -4.76837e-07, -3.57628e-07, 3.8743e-07, -0.0925096, -0.171599, -0.011185, 0.98075, 1, 1, 1, 1.25, 1, -4.76837e-07, -3.57628e-07, 3.8743e-07, -0.0925096, -0.171599, -0.011185, 0.98075, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="180"> 0, 1, 2.08616e-07, -2.98023e-08, -5.96046e-07, 0.176871, 0.346752, 0.0115369, 0.921058, 1, 1, 1, 0.05, 1, -1.49012e-07, -4.76837e-07, -2.38419e-07, 0.1969, 0.431458, 0.0161118, 0.880236, 1, 1, 1, 0.1, 1, -3.57628e-07, -8.04663e-07, -4.76837e-07, 0.196923, 0.556224, 0.0152519, 0.80722, 1, 1, 1, 0.15, 1, -2.68221e-07, -4.17233e-07, -2.98023e-07, 0.134905, 0.568169, 0.00154346, 0.811777, 1, 1, 1, 0.2, 1, -1.49012e-07, -6.25849e-07, -4.17233e-07, 0.0562878, 0.484209, -0.00707307, 0.873111, 1, 1, 1, 0.25, 1, -2.98023e-08, -8.04663e-07, -3.57628e-07, 0.0047636, 0.406038, -0.0121859, 0.913763, 1, 1, 1, 0.3, 1, 5.96046e-08, -7.7486e-07, -1.78814e-07, -0.011494, 0.345751, -0.0179636, 0.938084, 1, 0.999999, 1, 0.4, 1, 5.36442e-07, -5.36442e-07, -1.19209e-07, -0.0325058, 0.107107, -0.00429871, 0.993707, 1, 0.999999, 1, 0.45, 1, 2.08616e-07, -8.34465e-07, -1.78814e-07, -0.0177273, 0.0767786, -0.00241131, 0.996888, 1, 1, 1, 0.65, 1, -5.96046e-08, -6.55651e-07, -1.07288e-06, 0.154364, 0.318848, -0.0046877, 0.935139, 1, 1, 1, 0.7, 1, 5.96046e-08, -9.23872e-07, -1.01328e-06, 0.155566, 0.376204, -0.00401138, 0.913375, 1, 1, 1, 0.75, 1, 0, -8.9407e-07, -4.17233e-07, 0.173064, 0.444685, 0.00561718, 0.87879, 1, 1, 1, 0.8, 1, 3.27826e-07, -6.55651e-07, -4.17233e-07, 0.251551, 0.464674, 0.00544377, 0.848982, 1, 1, 1, 0.85, 1, 8.9407e-08, -7.15256e-07, -9.53674e-07, 0.280639, 0.447823, -0.00246765, 0.848935, 1, 1, 1, 1.25, 1, 8.9407e-08, -7.15256e-07, -9.53674e-07, 0.280639, 0.447823, -0.00246765, 0.848935, 1, 1, 1 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="192"> 0, 1, 0, 1.63913e-07, 1.93715e-07, -0.283345, 0.0300071, -0.0426225, 0.957601, 1, 1, 1, 0.05, 1, 8.9407e-08, 1.93715e-07, -5.06639e-07, -0.221388, 0.0587497, -0.0627932, 0.971387, 1, 1, 1, 0.15, 1, 5.96046e-08, 6.70552e-08, -1.3411e-07, 0.127996, 0.137739, -0.113256, 0.975612, 1, 1, 1, 0.2, 1, -5.96046e-08, -7.45058e-09, -7.45058e-07, 0.264976, 0.121823, -0.100248, 0.951261, 1, 1, 1, 0.25, 1, 2.98023e-08, -2.01166e-07, -4.91738e-07, 0.314522, 0.0998354, -0.077727, 0.94078, 1, 1, 1, 0.3, 1, 1.49012e-07, 1.3411e-07, 1.3411e-07, 0.306548, 0.0507913, -0.0454783, 0.949411, 1, 1, 1, 0.35, 1, 8.9407e-08, 7.45058e-09, -2.83122e-07, 0.297828, -0.0187708, -0.0207563, 0.954209, 1, 1, 1, 0.4, 1, 8.9407e-08, 4.47035e-08, -2.98023e-07, 0.287784, -0.0733564, -0.00467344, 0.95487, 1, 1, 1, 0.45, 1, 2.98023e-08, 2.23517e-08, -2.5332e-07, 0.170166, -0.0854042, 0.00266015, 0.981704, 1, 1, 1, 0.6, 1, 0, 1.04308e-07, 0, -0.531982, -0.0722138, 0.0220251, 0.843383, 1, 1, 1, 0.65, 1, 0, 1.3411e-07, -3.12924e-07, -0.652152, -0.0747176, 0.0102306, 0.754328, 1, 1, 1, 0.7, 1, -2.98023e-08, 0, 1.49012e-07, -0.686637, -0.0649825, 0.00231536, 0.724087, 1, 1, 1, 0.75, 1, 2.98023e-08, -1.56462e-07, -2.38419e-07, -0.638385, -0.0394346, -0.00259775, 0.768702, 1, 1, 1, 0.8, 1, 1.49012e-07, -8.9407e-08, -1.93715e-07, -0.432358, 0.00843852, -0.0248422, 0.90132, 1, 1, 1, 0.85, 1, 0, 1.63913e-07, 1.93715e-07, -0.283345, 0.0300071, -0.0426225, 0.957601, 1, 1, 1, 1.25, 1, 0, 1.63913e-07, 1.93715e-07, -0.283345, 0.0300071, -0.0426225, 0.957601, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="216"> 0, 1, 2.29338e-08, 8.9407e-08, 5.36442e-07, -0.369097, -0.0505305, 0.00260278, 0.928013, 1, 1, 1, 0.05, 1, 8.26549e-08, 1.93715e-07, 4.76837e-07, -0.32656, -0.0387365, 0.00230976, 0.94438, 1, 1, 1, 0.15, 1, 4.78467e-08, -7.45058e-09, 7.7486e-07, -0.04833, 0.013837, -0.00331139, 0.99873, 1, 1, 1, 0.2, 1, 1.44588e-07, 0, 7.15256e-07, 0.0174433, 0.00914093, -0.00369525, 0.999799, 1, 1, 1, 0.25, 1, 4.49363e-08, 1.63913e-07, 2.38419e-07, -0.0309752, 0.0174032, -0.00233819, 0.999366, 1, 1, 1, 0.3, 1, 6.06524e-08, -7.45058e-08, 6.55651e-07, -0.161344, 0.031869, -0.00095907, 0.986383, 1, 1, 1, 0.35, 1, 6.23986e-08, 1.11759e-07, 5.36442e-07, -0.258604, 0.043227, -0.000463765, 0.965016, 1, 1, 1, 0.4, 1, 2.66591e-08, 1.11759e-07, 5.96046e-07, -0.311843, 0.0531668, -0.000274837, 0.948645, 1, 1, 1, 0.45, 1, -0.000736501, 0.00352155, -0.0507002, -0.471618, 0.0737067, 0.000546333, 0.878717, 1, 1, 1, 0.5, 1, -0.00351399, 0.0168005, -0.241486, -0.74573, 0.0999092, 7.49679e-05, 0.658714, 1, 1, 1, 0.55, 1, -0.00736267, 0.0352004, -0.505227, 0.896291, -0.0831834, 0.00513814, -0.435565, 1, 1, 1, 0.6, 1, -0.0098056, 0.0468799, -0.672563, 0.946677, -0.0409485, 0.00588309, -0.319519, 1, 1, 1, 0.65, 1, -0.0098056, 0.0468801, -0.672652, 0.947809, 0.0057637, 0.00256107, -0.318776, 1, 1, 1, 0.7, 1, -0.00736268, 0.0352004, -0.505962, 0.888767, 0.0669386, 0.000245982, -0.453445, 1, 1, 1, 0.75, 1, -0.003514, 0.016801, -0.242868, -0.757574, -0.0924392, -0.000540428, 0.64617, 1, 1, 1, 0.8, 1, -0.000736581, 0.0035219, -0.0512407, -0.527405, -0.0678553, 0.00109702, 0.846899, 1, 1, 1, 0.85, 1, 2.29338e-08, 8.9407e-08, 5.36442e-07, -0.369097, -0.0505305, 0.00260278, 0.928013, 1, 1, 1, 1.25, 1, 2.29338e-08, 8.9407e-08, 5.36442e-07, -0.369097, -0.0505305, 0.00260278, 0.928013, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="216"> 0, 1, 1.49012e-08, 0, -5.21541e-08, 0.163945, 0.140221, -0.046324, 0.975354, 1, 1, 1, 0.05, 1, 9.68575e-08, 0, 7.82311e-08, 0.163142, 0.147087, -0.0386578, 0.974811, 1, 1, 1, 0.1, 1, 7.45058e-08, 0, 1.11759e-08, 0.154504, 0.157524, -0.0272069, 0.974974, 1, 1, 1, 0.15, 1, 8.9407e-08, 0, 3.72529e-08, 0.106593, 0.145246, -0.0455539, 0.982581, 1, 1, 1, 0.2, 1, 3.72529e-08, 0, 0, 0.00306457, 0.0975244, -0.0887594, 0.991263, 1, 1, 1, 0.3, 1, 4.47035e-08, 1.19209e-07, -1.60187e-07, -0.165764, -0.00244496, -0.0619073, 0.984217, 1, 1, 1, 0.35, 1, 3.72529e-08, -1.19209e-07, -1.2666e-07, -0.225564, -0.0444232, -0.0320188, 0.972688, 1, 1, 1, 0.4, 1, -2.98023e-08, -1.19209e-07, 1.3411e-07, -0.254966, -0.0644888, -0.0152293, 0.964677, 1, 1, 1, 0.45, 1, 5.96046e-08, 1.19209e-07, -3.72529e-09, -0.263415, -0.0674915, -0.0129876, 0.962231, 1, 1, 1, 0.5, 1, 7.45058e-08, 0, -2.98023e-08, -0.26682, -0.065605, -0.0157537, 0.961382, 1, 1, 1, 0.55, 1, 5.96046e-08, 0, 3.35276e-08, -0.268414, -0.0578826, -0.0205736, 0.961343, 1, 1, 1, 0.6, 1, 2.23517e-08, -1.19209e-07, 1.49012e-07, -0.268984, -0.0431783, -0.0254932, 0.961839, 1, 1, 1, 0.65, 1, 3.72529e-08, 0, -1.11759e-08, -0.205247, -0.0144598, -0.0301062, 0.97814, 1, 1, 1, 0.7, 1, 7.45058e-08, -1.19209e-07, -5.58794e-08, 0.0302446, 0.0427142, -0.0345553, 0.998031, 1, 1, 1, 0.75, 1, 8.9407e-08, 0, -1.11759e-07, 0.187052, 0.0967062, -0.0379775, 0.97684, 1, 1, 1, 0.8, 1, 8.19564e-08, -1.19209e-07, 2.23517e-08, 0.173053, 0.130372, -0.0438442, 0.975261, 1, 1, 1, 0.85, 1, 1.49012e-08, 0, -5.21541e-08, 0.163945, 0.140221, -0.046324, 0.975354, 1, 1, 1, 1.25, 1, 1.49012e-08, 0, -5.21541e-08, 0.163945, 0.140221, -0.046324, 0.975354, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="204"> 0, 1, 0, 2.08616e-07, 1.49012e-08, 0.284249, 0.0874448, 0.000525696, 0.954754, 1, 1, 1, 0.05, 1, 0, 1.11759e-07, -1.63913e-07, 0.0840381, 0.068345, -0.00156289, 0.994115, 1, 1, 1, 0.15, 1, 0, -9.68575e-08, -1.19209e-07, -0.428198, 0.103089, -0.0309307, 0.897253, 1, 1, 1, 0.2, 1, 2.98023e-08, 0, -2.5332e-07, -0.585268, 0.121806, -0.0264258, 0.801203, 1, 1, 1, 0.25, 1, -5.96046e-08, -2.68221e-07, -1.93715e-07, -0.68271, 0.117151, -0.00691618, 0.721203, 1, 1, 1, 0.3, 1, 5.96046e-08, 5.21541e-08, 3.57628e-07, -0.675843, 0.0951763, -0.00368054, 0.730865, 1, 1, 1, 0.35, 1, -5.96046e-08, -8.9407e-08, -1.04308e-07, -0.577504, 0.0522321, 0.00297164, 0.81471, 1, 1, 1, 0.4, 1, 0, 7.45058e-09, 1.63913e-07, -0.36481, -0.00958558, 0.0300626, 0.930547, 1, 1, 1, 0.45, 1, -1.19209e-07, 7.45058e-08, 1.49012e-07, -0.214962, -0.0628985, 0.0719756, 0.971933, 1, 1, 1, 0.5, 1, 0, 7.45058e-09, -7.15256e-07, -0.0924244, -0.113076, 0.110988, 0.983033, 1, 1, 1, 0.6, 1, 2.98023e-08, 3.72529e-08, 7.30157e-07, 0.212199, -0.104928, 0.0711089, 0.968971, 1, 1, 1, 0.65, 1, 8.9407e-08, 1.49012e-08, -1.63913e-07, 0.280374, -0.0786743, 0.0551762, 0.955069, 1, 1, 1, 0.7, 1, 0, 1.11759e-07, 2.5332e-07, 0.288443, -0.0349057, 0.033278, 0.956282, 1, 1, 1, 0.75, 1, -2.98023e-08, -1.3411e-07, -6.85453e-07, 0.285487, 0.0289713, 0.0136411, 0.957847, 1, 1, 1, 0.8, 1, -5.96046e-08, 8.9407e-08, -3.27826e-07, 0.284867, 0.0752772, 0.00313844, 0.955602, 1, 1, 1, 0.85, 1, 0, 2.08616e-07, 1.49012e-08, 0.284249, 0.0874448, 0.000525696, 0.954754, 1, 1, 1, 1.25, 1, 0, 2.08616e-07, 1.49012e-08, 0.284249, 0.0874448, 0.000525696, 0.954754, 1, 1, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="216"> 0, 1, -6.98492e-10, -2.98023e-08, 4.76837e-07, -0.32359, -0.0556479, 0.000232734, 0.94456, 1, 1, 1, 0.05, 1, 0.0014394, 0.00688202, -0.0998148, -0.562955, -0.0817876, -0.000658042, 0.82243, 1, 1, 1, 0.1, 1, 0.00484604, 0.0231691, -0.333955, -0.80836, -0.0993527, 0.00161956, 0.580241, 1, 1, 1, 0.15, 1, 0.00839999, 0.04016, -0.576718, 0.916395, 0.0904963, -0.00581601, -0.389867, 1, 1, 1, 0.2, 1, 0.010174, 0.048641, -0.697832, 0.949699, 0.0597103, -0.00558806, -0.307368, 1, 1, 1, 0.25, 1, 0.00943748, 0.0451194, -0.647324, 0.940565, -0.00539416, -0.00131091, -0.339569, 1, 1, 1, 0.3, 1, 0.00617793, 0.0295368, -0.424059, -0.852217, 0.0810981, 0.000142268, 0.516865, 1, 1, 1, 0.35, 1, 0.00247674, 0.0118409, -0.170242, -0.686673, 0.0913182, 0.000156236, 0.721208, 1, 1, 1, 0.4, 1, 0.000368256, 0.00176083, -0.02535, -0.450712, 0.0617424, -0.0017981, 0.89053, 1, 1, 1, 0.45, 1, -3.27127e-08, -2.23517e-08, 0, -0.320919, 0.0402711, -0.00287403, 0.946246, 1, 1, 1, 0.5, 1, -3.65544e-08, 2.6077e-07, 0, -0.222093, 0.0121194, -0.000893378, 0.97495, 1, 1, 1, 0.55, 1, -7.85803e-08, -5.21541e-08, 5.96046e-08, -0.085227, -0.0121138, 0.00211304, 0.996286, 1, 1, 1, 0.6, 1, -9.66247e-09, -1.93715e-07, -5.96046e-08, -0.0204391, -0.0111085, 0.00211107, 0.999727, 1, 1, 1, 0.65, 1, -1.47847e-08, -7.45058e-09, 1.19209e-07, -0.0461144, -0.0137229, 0.00155832, 0.998841, 1, 1, 1, 0.75, 1, 9.77889e-08, -8.9407e-08, 0, -0.259445, -0.0379664, 0.000355786, 0.965011, 1, 1, 1, 0.8, 1, -3.06172e-08, -1.19209e-07, 1.19209e-07, -0.311223, -0.0514541, 0.000257438, 0.948943, 1, 1, 1, 0.85, 1, -6.98492e-10, -2.98023e-08, 4.76837e-07, -0.32359, -0.0556479, 0.000232734, 0.94456, 1, 1, 1, 1.25, 1, -6.98492e-10, -2.98023e-08, 4.76837e-07, -0.32359, -0.0556479, 0.000232734, 0.94456, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="204"> 0, 1, 2.23517e-08, 1.19209e-07, 7.45058e-09, -0.260411, 0.0677016, 0.0123204, 0.963042, 1, 1, 1, 0.05, 1, 1.49012e-08, 1.19209e-07, -6.33299e-08, -0.261291, 0.0586691, 0.0123934, 0.963396, 1, 1, 1, 0.1, 1, 1.49012e-08, 1.19209e-07, 3.35276e-08, -0.262834, 0.0342669, 0.0126709, 0.964149, 1, 1, 1, 0.2, 1, 1.49012e-08, 0, 1.86265e-08, -0.260355, -0.0293857, 0.0140367, 0.964964, 1, 1, 1, 0.25, 1, -6.70552e-08, 0, -2.49594e-07, -0.153196, -0.0556389, 0.0191204, 0.986443, 1, 1, 1, 0.3, 1, 7.45058e-09, 2.38419e-07, 3.35276e-08, 0.102501, -0.0807205, 0.0313849, 0.990956, 1, 1, 1, 0.35, 1, -1.49012e-08, 1.19209e-07, -1.11759e-08, 0.182765, -0.105332, 0.0403985, 0.976663, 1, 1, 1, 0.4, 1, 0, 2.38419e-07, 2.98023e-08, 0.1689, -0.131443, 0.0454069, 0.975773, 1, 1, 1, 0.45, 1, -2.23517e-08, 1.19209e-07, 1.11759e-08, 0.162548, -0.163949, 0.0367097, 0.972292, 1, 1, 1, 0.5, 1, -7.45058e-09, 1.19209e-07, -6.70552e-08, 0.160675, -0.186181, 0.0223394, 0.969031, 1, 1, 1, 0.55, 1, 0, 2.38419e-07, -4.09782e-08, 0.121712, -0.123055, 0.0340729, 0.984318, 1, 1, 1, 0.65, 1, -2.23517e-08, 2.38419e-07, -4.84288e-08, -0.0909908, -0.00331438, 0.030867, 0.995368, 1, 1, 1, 0.7, 1, -2.98023e-08, 0, -1.86265e-08, -0.167009, 0.0327264, 0.0253347, 0.985086, 1, 1, 1, 0.75, 1, -1.49012e-08, 2.38419e-07, -9.31323e-08, -0.225897, 0.0565391, 0.0182554, 0.972338, 1, 1, 1, 0.8, 1, 7.45058e-09, 0, 1.41561e-07, -0.254123, 0.0658906, 0.0135391, 0.96483, 1, 1, 1, 0.85, 1, 2.23517e-08, 1.19209e-07, 7.45058e-09, -0.260411, 0.0677016, 0.0123204, 0.963042, 1, 1, 1, 1.25, 1, 2.23517e-08, 1.19209e-07, 7.45058e-09, -0.260411, 0.0677016, 0.0123204, 0.963042, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="24"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="192"> 0, 1, -5.68434e-14, 0, 0.994808, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -5.68434e-14, 0, 0.908378, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, -5.68434e-14, 0, 0.865919, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.15, 1, -5.68434e-14, 0, 0.952043, 0, 0, 0, 1, 1, 1, 1, 0.25, 1, -5.68434e-14, 0, 1.23636, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, -5.68434e-14, 0, 1.26452, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.35, 1, -5.68434e-14, 0, 1.17812, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.45, 1, -5.68434e-14, 0, 0.917901, 0, 0, 0, 1, 1, 1, 1, 0.5, 1, -5.68434e-14, 0, 0.850875, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -5.68434e-14, 0, 0.90967, 0, 0, 0, 1, 1, 1, 1, 0.65, 1, -5.68434e-14, 0, 1.19399, 0, 0, 0, 1, 1, 1, 1, 0.7, 1, -5.68434e-14, 0, 1.26645, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.75, 1, -5.68434e-14, 0, 1.20667, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -5.68434e-14, 0, 1.04898, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.85, 1, -5.68434e-14, 0, 0.994808, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -5.68434e-14, 0, 0.994808, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="192"> 0, 1, -0.142338, -0.593751, 0.041427, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.141891, -0.466314, 0.0666584, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, -0.140854, -0.18721, 0.16679, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, -0.135712, 0.882052, 1.08263, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, -0.134593, 1.04285, 1.23903, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, -0.134052, 1.11594, 1.33052, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.134139, 1.01025, 1.37488, 0, 0, 0, 1, 1, 1, 1, 0.5, 1, -0.134864, 0.561422, 1.40083, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -0.136154, -0.107091, 1.41207, 0, 0, 0, 1, 1, 1, 1, 0.6, 1, -0.137517, -0.627938, 1.41499, 0, 0, 0, 1, 1, 1, 1, 0.65, 1, -0.138802, -0.880369, 1.32217, 0, 0, 0, 1, 1, 1, 1, 0.7, 1, -0.140187, -0.97361, 0.946171, 0, 0, 0, 1, 1, 1, 1, 0.75, 1, -0.141374, -0.990009, 0.507478, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -0.142135, -0.753522, 0.166703, 0, 0, 0, 1, 1, 1, 1, 0.85, 1, -0.142338, -0.593751, 0.041427, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.142338, -0.593751, 0.041427, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="192"> 0, 1, 0.133965, 1.12742, 1.35169, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.134319, 0.88137, 1.36048, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, 0.136624, -0.318866, 1.4031, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, 0.13794, -0.745207, 1.41408, 0, 0, 0, 1, 1, 1, 1, 0.25, 1, 0.139237, -0.932173, 1.26013, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, 0.140615, -0.985177, 0.795642, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, 0.141658, -0.933265, 0.382912, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, 0.142236, -0.69551, 0.103281, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, 0.142112, -0.449542, 0.0515677, 0, 0, 0, 1, 1, 1, 1, 0.5, 1, 0.141234, -0.239295, 0.11699, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, 0.140074, 0.0127278, 0.285218, 0, 0, 0, 1, 1, 1, 1, 0.7, 1, 0.136158, 0.812955, 1.03336, 0, 0, 0, 1, 1, 1, 1, 0.75, 1, 0.134866, 1.00553, 1.22614, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, 0.13414, 1.10444, 1.32777, 0, 0, 0, 1, 1, 1, 1, 0.85, 1, 0.133965, 1.12742, 1.35169, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.133965, 1.12742, 1.35169, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="180"> 0, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.0953997, 0.642052, -0.742965, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.1, 1, 0.0823101, 0.56581, -0.648221, 4.1297e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.35, 1, 0.0243976, -0.0441461, -0.063019, 4.1297e-08, 2.53394e-15, -7.10543e-15, 1, 1, 1, 1, 0.4, 1, 0.020945, -0.11126, -0.00892317, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.45, 1, 0.0214889, -0.0993756, -0.1204, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.5, 1, 0.0261557, -0.00703263, -0.571036, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, 0.0350212, 0.144668, -1.19143, 7.10993e-08, 6.08666e-15, -4.32757e-22, 1, 1, 1, 1, 0.6, 1, 0.0452013, 0.286137, -1.58564, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.65, 1, 0.056361, 0.396596, -1.62736, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.7, 1, 0.0713525, 0.504199, -1.41721, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.75, 1, 0.0877976, 0.602767, -1.08603, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, 0.097935, 0.656912, -0.843801, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.85, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="180"> 0, 1, -0.0204011, -0.122407, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.0226399, -0.0760723, -0.246171, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.15, 1, -0.0384328, 0.195889, -1.36473, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.2, 1, -0.0485586, 0.325533, -1.64571, 7.10993e-08, 9.63937e-15, -6.85353e-22, 1, 1, 1, 1, 0.25, 1, -0.0604436, 0.430887, -1.61593, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, -0.0768237, 0.538687, -1.39129, 7.10993e-08, 2.53394e-15, -2.11758e-22, 1, 1, 1, 1, 0.35, 1, -0.0915991, 0.623227, -1.09587, 4.1297e-08, 2.53394e-15, -7.10543e-15, 1, 1, 1, 1, 0.4, 1, -0.0992045, 0.663389, -0.847581, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.45, 1, -0.0979352, 0.656214, -0.687419, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.5, 1, -0.0877979, 0.599371, -0.580202, 0, 0, 0, 1, 1, 1, 1, 0.65, 1, -0.0452008, 0.276356, -0.334939, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.75, 1, -0.0261556, -0.010167, -0.0897738, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -0.0214889, -0.0999783, -0.0177123, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.85, 1, -0.0204011, -0.122407, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.0204011, -0.122407, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="168"> 0, 1, -0.868295, 0.288818, -0.834593, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.920336, 0.223441, -0.675278, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -1.0611, 0.0535004, -0.268795, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.3, 1, -1.81549, -0.572945, 1.93497, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.35, 1, -1.97521, -0.260334, 2.42549, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -2.07242, 0.0952058, 2.72719, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -2.06152, 0.134094, 2.70055, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, -1.94935, -0.00418663, 2.38214, 0, 0, 0, 1, 1, 1, 1, 0.6, 1, -1.5659, -0.316463, 1.27531, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.65, 1, -1.39564, -0.31023, 0.768786, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.75, 1, -1.01032, 0.0728607, -0.380929, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -0.896442, 0.243316, -0.739858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.85, 1, -0.868295, 0.288818, -0.834593, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.868295, 0.288818, -0.834593, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="168"> 0, 1, 2.08906, 0.170859, 2.78004, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 2.03311, 0.0989122, 2.61048, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, 1.88529, -0.0705678, 2.18507, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, 1.50915, -0.334755, 1.10648, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, 1.33866, -0.287646, 0.593788, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, 0.966909, 0.137533, -0.532556, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, 0.882217, 0.266322, -0.791318, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, 0.89374, 0.256562, -0.760212, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, 0.999084, 0.126561, -0.459517, 0, 0, 0, 1, 1, 1, 1, 0.7, 1, 1.75712, -0.595706, 1.75783, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.75, 1, 1.92686, -0.424236, 2.27222, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, 2.0556, 0.0151663, 2.66931, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.85, 1, 2.08906, 0.170859, 2.78004, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 2.08906, 0.170859, 2.78004, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="156"> 0, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.341349, -0.264663, 0.0556155, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, 0.0336542, -1.45692, 0.323532, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, -0.0452293, -1.75482, 0.391734, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, 0.0926713, -1.62165, 0.363375, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, 1.18685, -0.378264, 0.0954279, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, 1.51909, 0.00473738, 0.0141962, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, 1.55064, 0.0706801, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, 1.44211, 0.0639179, 0, 0, 0, 0, 1, 1, 1, 1, 0.75, 1, 0.54098, 0.00832748, 0, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, 0.432091, 0.00163841, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.85, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="168"> 0, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -1.5235, 0.0690539, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -1.38104, 0.0602572, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -0.448482, 0.0061903, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.312683, -0.140136, 0.0283925, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, -0.161211, -0.627825, 0.135386, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -0.030728, -1.28144, 0.283529, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.6, 1, 0.0389389, -1.69292, 0.377552, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.65, 1, -0.0330012, -1.68882, 0.377568, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.7, 1, -0.409697, -1.26443, 0.283661, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.75, 1, -1.00503, -0.588506, 0.135634, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -1.45325, -0.0721812, 0.0284887, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.85, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="216"> 0, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.05, 1, 0.0669454, 0.729981, 0.0847113, 0.0751978, 0.000902196, 0.0773167, 0.994166, 1, 1, 1, 0.15, 1, 0.147711, 0.887191, -0.02789, 0.103321, 0.0347243, 0.0196114, 0.993848, 1, 1, 1, 0.2, 1, 0.168294, 0.927241, -0.0565808, 0.110419, 0.0433374, -0.00845134, 0.992904, 1, 1, 1, 0.25, 1, 0.154709, 0.910602, -0.0446639, 0.107418, 0.0422538, -0.0318613, 0.992804, 1, 1, 1, 0.3, 1, 0.0960078, 0.836978, 0.00806546, 0.0942701, 0.034167, -0.0564973, 0.993355, 1, 1, 1, 0.35, 1, 0.021745, 0.753374, 0.0679436, 0.0793445, 0.0222103, -0.0760792, 0.993692, 1, 1, 1, 0.4, 1, -0.035471, 0.705747, 0.102054, 0.07085, 0.00995431, -0.0854402, 0.993771, 1, 1, 1, 0.45, 1, -0.0674228, 0.714066, 0.0960958, 0.0723594, -0.00257329, -0.0821245, 0.993989, 1, 1, 1, 0.5, 1, -0.0866932, 0.776805, 0.0511615, 0.0836199, -0.0185098, -0.0626717, 0.994353, 1, 1, 1, 0.55, 1, -0.0950061, 0.863738, -0.0110998, 0.0991637, -0.0338542, -0.0304325, 0.994029, 1, 1, 1, 0.6, 1, -0.0971422, 0.918921, -0.0506222, 0.108957, -0.0424157, -6.6921e-05, 0.993141, 1, 1, 1, 0.65, 1, -0.0894483, 0.918925, -0.0506237, 0.108927, -0.0421963, 0.0241723, 0.99286, 1, 1, 1, 0.7, 1, -0.0546535, 0.863773, -0.0111129, 0.0990954, -0.0332032, 0.0485143, 0.99334, 1, 1, 1, 0.75, 1, 0.000162542, 0.776872, 0.051137, 0.0835711, -0.0190219, 0.071275, 0.993768, 1, 1, 1, 0.8, 1, 0.0397389, 0.714092, 0.0960863, 0.072346, -0.00878352, 0.08392, 0.993804, 1, 1, 1, 0.85, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 1.25, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="180"> 0, 1, 7.45059e-09, -5.21541e-08, 2.38419e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1, 0.05, 1, -2.16067e-08, -1.49015e-09, 1.19209e-07, 0.0607085, -0.00428583, -0.0791363, 0.995004, 1, 1, 1, 0.1, 1, -2.23518e-09, 4.61936e-08, 1.49012e-07, 0.0742298, -0.00290666, -0.0580589, 0.995545, 1, 1, 1, 0.2, 1, -1.22934e-08, -7.00588e-08, 1.49012e-07, 0.0953622, 0.000412438, -0.00409159, 0.995434, 1, 1, 1, 0.25, 1, -1.86265e-08, 1.39698e-08, -1.49012e-07, 0.0924473, 0.00171257, 0.0202586, 0.99551, 1, 1, 1, 0.35, 1, -1.56462e-08, 3.1013e-08, 0, 0.0648424, 0.00419923, 0.0731356, 0.995203, 1, 1, 1, 0.4, 1, 2.23523e-09, -2.84985e-08, 1.19209e-07, 0.0564666, 0.00472734, 0.0850757, 0.994762, 1, 1, 1, 0.45, 1, -4.47039e-09, 2.23518e-08, -8.9407e-08, 0.0579181, 0.00454757, 0.0830774, 0.994848, 1, 1, 1, 0.5, 1, 8.43755e-15, -5.58794e-08, 8.9407e-08, 0.0689504, 0.00348495, 0.0670145, 0.995361, 1, 1, 1, 0.6, 1, 5.5879e-09, -7.60309e-08, -2.98023e-08, 0.0939097, 5.69107e-05, 0.0121633, 0.995506, 1, 1, 1, 0.65, 1, 1.78815e-08, -2.31898e-08, 3.27826e-07, 0.0939129, -0.00128467, -0.0120988, 0.995506, 1, 1, 1, 0.75, 1, -1.86265e-09, 3.11993e-08, -2.98023e-08, 0.0689717, -0.00392611, -0.0670089, 0.995358, 1, 1, 1, 0.8, 1, 1.49013e-09, 4.80559e-08, 0, 0.0579302, -0.00464071, -0.0830884, 0.994846, 1, 1, 1, 0.85, 1, 7.45059e-09, -5.21541e-08, 2.38419e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1, 1.25, 1, 7.45059e-09, -5.21541e-08, 2.38419e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="168"> 0, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, 0.0947232, -0.00739035, -0.0868418, 0.991681, 1, 1, 1, 0.05, 1, 9.31322e-10, 7.07805e-08, 5.96046e-08, 0.0947233, -0.00739035, -0.0868419, 0.991681, 1, 1, 1, 0.1, 1, 6.51926e-10, 7.07805e-08, 5.96046e-08, 0.0949443, -0.00694628, -0.0757376, 0.992573, 1, 1, 1, 0.15, 1, 3.7253e-10, -2.6077e-08, -2.38419e-07, 0.0959905, -0.00433497, -0.0114678, 0.995307, 1, 1, 1, 0.25, 1, 1.86265e-08, 2.23517e-08, 1.19209e-07, 0.0965992, 0.00494126, 0.201269, 0.974749, 1, 1, 1, 0.3, 1, -7.68343e-10, 7.45058e-09, 1.78814e-07, 0.0963173, 0.00675391, 0.221794, 0.970301, 1, 1, 1, 0.4, 1, -1.56574e-10, 7.82311e-08, -1.78814e-07, 0.0949654, 0.0073896, 0.100605, 0.990356, 1, 1, 1, 0.45, 1, 3.30057e-09, 1.08033e-07, -5.96046e-08, 0.0947232, 0.00739035, 0.0868418, 0.991681, 1, 1, 1, 0.5, 1, -3.25963e-09, -9.31323e-08, 5.96046e-08, 0.0947232, 0.00739035, 0.0868418, 0.991681, 1, 1, 1, 0.55, 1, -2.10027e-08, 7.45058e-08, -1.78814e-07, 0.0955253, 0.00546829, 0.0431828, 0.994475, 1, 1, 1, 0.65, 1, 1.26195e-08, -4.84288e-08, -2.38419e-07, 0.0967914, -0.0040173, -0.170015, 0.980668, 1, 1, 1, 0.7, 1, 1.23865e-08, -8.19564e-08, -5.96046e-08, 0.0964064, -0.00640121, -0.223121, 0.969991, 1, 1, 1, 0.75, 1, 1.86265e-09, -7.07805e-08, -2.98023e-07, 0.0963505, -0.00664593, -0.228565, 0.968726, 1, 1, 1, 1.25, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, 0.0963505, -0.00664594, -0.228565, 0.968726, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="24"> 0, 1, -1.95579e-08, -1.49012e-08, -9.53674e-07, -7.45058e-09, -2.48375e-09, 8.87174e-09, 1, 1, 1, 1, 1.25, 1, -6.51927e-08, -7.45058e-08, -9.53674e-07, 6.80667e-18, 2.71908e-09, -1.56593e-08, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="204"> 0, 1, 2.79375e-09, -5.96046e-07, -2.50526e-07, 0.174741, -0.0963796, 0.0144345, 0.97978, 1, 1, 1, 0.05, 1, -3.7254e-09, -2.08616e-07, -1.22236e-07, 0.195715, -0.0950264, 0.0238173, 0.975755, 1, 1, 1, 0.1, 1, 4.54485e-08, -7.15256e-07, -7.68341e-08, 0.229373, -0.0816785, 0.0404464, 0.969062, 1, 1, 1, 0.15, 1, -1.49012e-08, -6.85453e-07, -8.59145e-08, 0.25499, -0.0176933, 0.0391946, 0.965987, 1, 1, 1, 0.25, 1, 1.4901e-08, -1.49012e-07, -1.78115e-07, 0.23692, 0.192561, -0.0167461, 0.952108, 1, 1, 1, 0.3, 1, -4.61937e-08, -4.47035e-07, -1.46218e-07, 0.20349, 0.220566, -0.0253329, 0.953573, 1, 1, 1, 0.35, 1, 8.94071e-09, -2.68221e-07, -1.97906e-08, 0.179164, 0.172369, -0.0185073, 0.968425, 1, 1, 1, 0.4, 1, 2.23509e-09, -3.57628e-07, -9.56934e-08, 0.17384, 0.110352, -0.0138213, 0.978474, 1, 1, 1, 0.45, 1, -2.75671e-08, -7.45058e-07, 2.63099e-08, 0.188123, 0.0930304, -0.0247279, 0.977417, 1, 1, 1, 0.5, 1, -9.31436e-10, 4.47035e-07, -6.37956e-08, 0.217624, 0.0872372, -0.0441829, 0.971122, 1, 1, 1, 0.55, 1, 1.04306e-08, -2.38419e-07, -1.33412e-07, 0.247766, 0.0401273, -0.0490683, 0.966744, 1, 1, 1, 0.65, 1, 3.27827e-08, -4.47035e-07, -6.26314e-08, 0.245106, -0.170404, 0.00637661, 0.954382, 1, 1, 1, 0.7, 1, 3.27823e-08, -1.49012e-07, -6.70552e-08, 0.212986, -0.224596, 0.0272969, 0.950499, 1, 1, 1, 0.75, 1, -7.45057e-08, 0, 6.33299e-08, 0.183845, -0.233119, 0.0392625, 0.954104, 1, 1, 1, 0.8, 1, -6.7055e-08, -5.96046e-07, -5.00586e-08, 0.175853, -0.235075, 0.0484733, 0.954707, 1, 1, 1, 0.85, 1, 7.45066e-09, -6.55651e-07, 6.75209e-09, 0.174943, -0.235515, 0.051072, 0.95463, 1, 1, 1, 1.25, 1, 7.45066e-09, -6.55651e-07, 6.75209e-09, 0.174943, -0.235515, 0.051072, 0.95463, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="24"> 0, 1, -1.25867e-08, -4.23752e-08, -2.57976e-07, 2.23517e-08, 3.7017e-10, 7.60394e-10, 1, 1, 1, 1, 1.25, 1, 1.23749e-08, -2.09548e-09, 2.43308e-07, 2.23517e-08, -2.79233e-10, -7.29088e-11, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="24"> 0, 1, 5.20962e-08, 0.00292337, 0.204329, -7.21775e-09, 1.1358e-11, -7.03732e-10, 1, 1, 1, 1, 1.25, 1, 4.12186e-08, 0.00292328, 0.20433, -8.14907e-09, 9.21561e-11, 1.63806e-10, 1, 1, 1, 1 </real_array>
-
- </resource>
- <resource type="Animation" path="local://12">
- <string name="resource/name"> "walk-cycle" </string>
- <real name="length"> 1.041667 </real>
- <bool name="loop"> True </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="228"> 0, 1, 7.7486e-07, -3.57628e-07, 5.66244e-07, 0.132777, -0.115851, -0.0857195, 0.980613, 1, 1, 1, 0.05, 1, 4.17233e-07, 1.19209e-07, 3.27826e-07, 0.136218, -0.113975, -0.0877542, 0.980181, 1, 1, 1, 0.1, 1, 5.06639e-07, -2.38419e-07, 2.98023e-07, 0.144837, -0.108331, -0.0933223, 0.97907, 1, 1, 1, 0.15, 1, 5.36442e-07, -3.57628e-07, 3.57628e-07, 0.15539, -0.0990044, -0.102617, 0.977508, 1, 0.999999, 1, 0.2, 1, 7.15256e-07, -3.57628e-07, 4.47035e-07, 0.162073, -0.0835771, -0.115431, 0.976434, 1, 1, 1, 0.25, 1, 6.25849e-07, -3.57628e-07, 4.17233e-07, 0.160674, -0.0537521, -0.128708, 0.977102, 1, 1, 1, 0.3, 1, 6.85453e-07, -3.57628e-07, 2.98023e-07, 0.144844, 0.00232148, -0.137246, 0.979887, 1, 1, 1, 0.45, 1, 9.53674e-07, -7.15256e-07, 6.85453e-07, 0.0267683, 0.215793, -0.138386, 0.966212, 1, 1, 1, 0.5, 1, 7.7486e-07, -3.57628e-07, 4.17233e-07, -0.00441569, 0.255036, -0.137846, 0.957045, 1, 1, 1, 0.55, 1, 8.34465e-07, -5.96046e-07, 5.36442e-07, -0.00986276, 0.263176, -0.137756, 0.954811, 1, 1, 1, 0.6, 1, 4.76837e-07, 0, 3.8743e-07, 0.0174093, 0.245944, -0.13741, 0.959337, 1, 1, 1, 0.7, 1, 3.27826e-07, -1.19209e-07, 2.68221e-07, 0.12402, 0.181155, -0.127036, 0.967297, 1, 1, 1, 0.75, 1, 7.45058e-07, 0, 4.47035e-07, 0.157369, 0.166922, -0.11544, 0.96646, 1, 1, 1, 0.8, 1, 8.34465e-07, -1.19209e-07, 4.47035e-07, 0.166665, 0.143487, -0.108193, 0.969499, 1, 1, 1, 0.85, 1, 2.98023e-07, 0, 1.49012e-07, 0.164004, 0.0866041, -0.105149, 0.977009, 1, 0.999999, 1, 0.95, 1, 4.76837e-07, 0, 2.38419e-07, 0.144168, -0.0621538, -0.0938402, 0.983131, 1, 1, 1, 1, 1, 8.64267e-07, -4.76837e-07, 6.85453e-07, 0.135099, -0.105557, -0.0876091, 0.98129, 1, 1, 1, 1.05, 1, 7.7486e-07, -3.57628e-07, 5.66244e-07, 0.132777, -0.115851, -0.0857195, 0.980613, 1, 1, 1, 1.25, 1, 7.7486e-07, -3.57628e-07, 5.66244e-07, 0.132777, -0.115851, -0.0857195, 0.980613, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="228"> 0, 1, 7.45058e-07, -8.04663e-07, -8.34465e-07, -0.0607703, -0.240987, 0.00892511, 0.968583, 1, 1, 1, 0.05, 1, -2.98023e-07, -3.57628e-07, 1.78814e-07, -0.0608664, -0.247441, 0.00903588, 0.966947, 1, 0.999999, 1, 0.1, 1, -1.78814e-07, -7.45058e-07, -1.19209e-07, -0.0607357, -0.265635, 0.00908754, 0.962116, 1, 1, 1, 0.15, 1, 4.17233e-07, -8.64267e-07, -4.17233e-07, -0.0586521, -0.298966, 0.00880687, 0.952419, 1, 1, 1, 0.25, 1, 3.8743e-07, -5.96046e-07, -2.98023e-07, -0.0404347, -0.402042, 0.00443354, 0.914717, 1, 1, 1, 0.3, 1, -2.98023e-08, -6.85453e-07, -2.38419e-07, -0.0222657, -0.438743, -0.00390802, 0.898328, 1, 1, 1, 0.35, 1, -3.27826e-07, -2.68221e-07, -1.78814e-07, -0.001747, -0.450439, -0.0151044, 0.892678, 1, 0.999999, 1, 0.4, 1, -2.98023e-08, -3.57628e-07, -4.76837e-07, 0.0165229, -0.440184, -0.0247739, 0.897414, 1, 1, 1, 0.5, 1, 2.98023e-08, -3.27826e-07, 0, 0.0357718, -0.396841, -0.0343986, 0.916545, 1, 1, 1, 0.55, 1, 1.49012e-07, -6.25849e-07, -1.78814e-07, 0.0355214, -0.39013, -0.0350975, 0.919405, 1, 1, 1, 0.6, 1, 1.78814e-07, -5.06639e-07, -5.36442e-07, 0.01977, -0.384514, -0.0345495, 0.92226, 1, 1, 1, 0.65, 1, -1.19209e-07, -4.17233e-07, -2.38419e-07, -0.0162325, -0.357154, -0.033198, 0.933314, 1, 0.999999, 1, 0.75, 1, -2.98023e-08, -3.57628e-07, -2.98023e-07, -0.0986698, -0.203446, -0.0321126, 0.973572, 1, 0.999999, 1, 0.8, 1, 5.96046e-08, -7.45058e-07, -2.38419e-07, -0.110421, -0.161891, -0.0281555, 0.980207, 1, 1, 1, 0.85, 1, 4.76837e-07, -8.04663e-07, -8.34465e-07, -0.104832, -0.172931, -0.0183971, 0.979166, 1, 0.999999, 1, 0.95, 1, 0, -6.55651e-07, -5.96046e-07, -0.0743493, -0.227469, 0.00271093, 0.970939, 1, 1, 1, 1, 1, -2.98023e-08, -3.57628e-07, -2.38419e-07, -0.0636988, -0.238854, 0.00790001, 0.968932, 1, 1, 1, 1.05, 1, 7.45058e-07, -8.04663e-07, -8.34465e-07, -0.0607703, -0.240987, 0.00892511, 0.968583, 1, 1, 1, 1.25, 1, 7.45058e-07, -8.04663e-07, -8.34465e-07, -0.0607703, -0.240987, 0.00892511, 0.968583, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="216"> 0, 1, -7.45058e-07, -4.76837e-07, 4.47035e-07, -0.0127337, -0.264935, 0.137763, 0.954289, 1, 1, 1, 0.05, 1, -3.8743e-07, 0, 2.38419e-07, 0.0104992, -0.248758, 0.137429, 0.958709, 1, 1, 1, 0.15, 1, -5.66244e-07, -1.19209e-07, 4.47035e-07, 0.119317, -0.176495, 0.127478, 0.968691, 1, 1, 1, 0.2, 1, -5.06639e-07, -1.19209e-07, 3.27826e-07, 0.156208, -0.160784, 0.115735, 0.967653, 1, 1, 1, 0.25, 1, -4.17233e-07, -1.19209e-07, 2.68221e-07, 0.170588, -0.146234, 0.10696, 0.968543, 1, 0.999999, 1, 0.3, 1, -8.34465e-07, -3.57628e-07, 8.9407e-07, 0.16899, -0.106962, 0.104274, 0.974232, 1, 1, 1, 0.45, 1, -9.23872e-07, -5.96046e-07, 7.7486e-07, 0.141826, 0.058077, 0.0901382, 0.984067, 1, 1, 1, 0.5, 1, -7.7486e-07, -5.96046e-07, 2.98023e-07, 0.134623, 0.0959315, 0.0862667, 0.982462, 1, 1, 1, 0.55, 1, -7.45058e-07, -3.57628e-07, 6.25849e-07, 0.133233, 0.11842, 0.0861958, 0.980202, 1, 1, 1, 0.6, 1, -4.76837e-07, 0, 4.47035e-07, 0.137596, 0.131505, 0.0903706, 0.977551, 1, 1, 1, 0.65, 1, -6.55651e-07, -3.57628e-07, 5.36442e-07, 0.146837, 0.135484, 0.0990691, 0.974817, 1, 1, 1, 0.7, 1, -5.96046e-07, -3.57628e-07, 6.25849e-07, 0.15676, 0.127354, 0.111789, 0.972991, 1, 1, 1, 0.75, 1, -4.17233e-07, 0, 3.8743e-07, 0.161767, 0.101349, 0.126219, 0.973462, 1, 1, 1, 0.8, 1, -6.85453e-07, -3.57628e-07, 5.06639e-07, 0.154473, 0.0449621, 0.136756, 0.977453, 1, 1, 1, 0.95, 1, -6.55651e-07, -2.38419e-07, 4.76837e-07, 0.0363447, -0.203514, 0.138296, 0.968574, 1, 1, 1, 1, 1, -5.96046e-07, -3.57628e-07, 3.57628e-07, -0.00218869, -0.252498, 0.137778, 0.957735, 1, 1, 1, 1.05, 1, -7.45058e-07, -4.76837e-07, 4.47035e-07, -0.0127337, -0.264935, 0.137763, 0.954289, 1, 1, 1, 1.25, 1, -7.45058e-07, -4.76837e-07, 4.47035e-07, -0.0127337, -0.264935, 0.137763, 0.954289, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="192"> 0, 1, 3.57628e-07, -5.96046e-07, -3.57628e-07, 0.0370915, 0.39046, 0.0351404, 0.919201, 1, 1, 1, 0.05, 1, -1.49012e-07, -5.96046e-07, -2.38419e-07, 0.0247868, 0.388139, 0.0345456, 0.92062, 1, 1, 1, 0.1, 1, -3.57628e-07, -5.66244e-07, -4.76837e-07, -0.00839952, 0.367653, 0.0329431, 0.929342, 1, 1, 1, 0.15, 1, -1.78814e-07, -5.66244e-07, -7.7486e-07, -0.0538019, 0.307417, 0.0309853, 0.949547, 1, 1, 1, 0.2, 1, 0, -3.8743e-07, -4.17233e-07, -0.0934157, 0.21941, 0.0316565, 0.970634, 1, 1, 1, 0.25, 1, -1.49012e-07, -7.7486e-07, -3.57628e-07, -0.112029, 0.160435, 0.0303507, 0.980198, 1, 1, 1, 0.3, 1, 1.19209e-07, -7.15256e-07, -2.38419e-07, -0.111906, 0.1565, 0.0231637, 0.981045, 1, 1, 1, 0.35, 1, 2.68221e-07, -5.06639e-07, -2.38419e-07, -0.104709, 0.167819, 0.0144275, 0.980135, 1, 1, 1, 0.6, 1, 2.38419e-07, -3.57628e-07, -2.98023e-07, -0.0540049, 0.274564, -0.0119163, 0.959977, 1, 1, 1, 0.65, 1, 2.68221e-07, -2.68221e-07, 5.96046e-08, -0.0496356, 0.312827, -0.0136146, 0.948415, 1, 1, 1, 0.8, 1, 1.78814e-07, -3.8743e-07, -2.38419e-07, -0.0228587, 0.449632, -0.00310725, 0.892916, 1, 1, 1, 0.85, 1, -2.08616e-07, -6.25849e-07, -5.36442e-07, -0.00418434, 0.463526, 0.00969348, 0.886021, 1, 1, 1, 0.9, 1, -2.68221e-07, -6.85453e-07, -1.19209e-07, 0.0143603, 0.452468, 0.0218435, 0.891397, 1, 1, 1, 1, 1, 8.9407e-08, -5.96046e-07, -5.36442e-07, 0.0356796, 0.398885, 0.0342096, 0.915668, 1, 1, 1, 1.05, 1, 3.57628e-07, -5.96046e-07, -3.57628e-07, 0.0370915, 0.39046, 0.0351404, 0.919201, 1, 1, 1, 1.25, 1, 3.57628e-07, -5.96046e-07, -3.57628e-07, 0.0370915, 0.39046, 0.0351404, 0.919201, 1, 1, 1 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="180"> 0, 1, -5.96046e-08, 7.45058e-09, -1.3411e-07, -0.47466, -0.0131527, -0.012987, 0.879975, 1, 1, 1, 0.05, 1, 2.98023e-08, 2.23517e-08, -2.23517e-07, -0.410091, -0.00379406, -0.0158917, 0.911898, 1, 1, 1, 0.25, 1, -1.19209e-07, 1.11759e-07, -5.21541e-07, 0.0997313, 0.0337367, -0.0261638, 0.994098, 1, 1, 1, 0.3, 1, 8.9407e-08, 4.47035e-08, -4.02331e-07, 0.122513, 0.0214196, -0.0200121, 0.992034, 1, 1, 1, 0.45, 1, 1.19209e-07, 7.45058e-09, -3.27826e-07, 0.229705, -0.0511077, 0.00301582, 0.971913, 1, 1, 1, 0.5, 1, 0, 3.72529e-08, -3.72529e-07, 0.236488, -0.0697987, 0.00859063, 0.969086, 1, 1, 1, 0.55, 1, 0, 2.98023e-08, -2.5332e-07, 0.206064, -0.0732532, 0.0100766, 0.975741, 1, 1, 1, 0.6, 1, -2.98023e-08, 4.47035e-08, -2.68221e-07, 0.118009, -0.0599028, 0.00750554, 0.991176, 1, 1, 1, 0.65, 1, -8.9407e-08, 2.23517e-08, -2.83122e-07, -0.0368129, -0.031384, 0.00214083, 0.998827, 1, 1, 1, 0.8, 1, -5.96046e-08, 2.23517e-08, -3.42727e-07, -0.634332, 0.0354032, -0.00990766, 0.772186, 1, 1, 1, 0.85, 1, 0, 2.23517e-08, -5.51343e-07, -0.746229, 0.0185993, -0.00698883, 0.665393, 1, 1, 1, 0.9, 1, 2.98023e-08, 1.49012e-08, -3.72529e-07, -0.740985, -0.00577112, -0.000829951, 0.671497, 1, 1, 1, 1, 1, 0, 2.98023e-08, -2.68221e-07, -0.523042, -0.0161244, -0.00986391, 0.852097, 1, 1, 1, 1.05, 1, -5.96046e-08, 7.45058e-09, -1.3411e-07, -0.47466, -0.0131527, -0.012987, 0.879975, 1, 1, 1, 1.25, 1, -5.96046e-08, 7.45058e-09, -1.3411e-07, -0.47466, -0.0131527, -0.012987, 0.879975, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="216"> 0, 1, 9.0804e-08, -5.21541e-08, 5.36442e-07, -0.373219, -0.0555838, 8.64882e-05, 0.926077, 1, 1, 1, 0.05, 1, 2.50293e-08, 1.3411e-07, 5.96046e-07, -0.322099, -0.0481091, 0.000521386, 0.945483, 1, 1, 1, 0.1, 1, 1.20257e-07, -1.49012e-07, 7.15256e-07, -0.224139, -0.0330777, 0.00125387, 0.973995, 1, 1, 1, 0.15, 1, 3.94648e-08, -1.3411e-07, 6.55651e-07, -0.165692, -0.0218823, 0.00143977, 0.985934, 1, 1, 1, 0.2, 1, 1.33412e-07, -1.56462e-07, 5.36442e-07, -0.09297, -0.0104596, 0.00125276, 0.995613, 1, 1, 1, 0.25, 1, 3.55067e-08, 4.47035e-08, 1.78814e-07, -0.0411288, -0.0028586, 0.000542978, 0.99915, 1, 1, 1, 0.35, 1, 9.26666e-08, 5.96046e-08, 6.55651e-07, -0.159491, 0.00874812, -0.00126692, 0.98716, 1, 1, 1, 0.45, 1, 3.87663e-08, 0, 4.76837e-07, -0.233894, 0.0318884, -0.00310529, 0.971734, 1, 1, 1, 0.5, 1, -3.53903e-08, -7.45058e-08, 5.96046e-07, -0.280896, 0.0453351, -0.00364749, 0.95866, 1, 1, 1, 0.55, 1, 1.59489e-08, 4.47035e-08, 5.96046e-07, -0.352331, 0.0592861, -0.00363569, 0.933989, 1, 1, 1, 0.6, 1, 2.16532e-08, 1.3411e-07, 6.55651e-07, -0.469209, 0.0766892, -0.00261066, 0.879747, 1, 1, 1, 0.75, 1, 9.51113e-08, -2.01166e-07, 7.15256e-07, -0.846575, 0.0999882, 0.00219129, 0.522789, 1, 1, 1, 0.8, 1, 3.77186e-08, -1.49012e-07, 6.55651e-07, 0.900504, -0.0754152, -0.00223886, -0.428252, 1, 1, 1, 0.85, 1, 4.92437e-08, 1.49012e-07, 6.55651e-07, 0.906482, -0.0264902, -0.00126108, -0.42141, 1, 1, 1, 0.9, 1, -2.71248e-08, 1.63913e-07, 5.36442e-07, -0.830638, -0.0316768, -0.000334372, 0.555911, 1, 1, 1, 1, 1, 2.87546e-08, 4.84288e-07, 7.7486e-07, -0.453335, -0.0623349, -0.000381388, 0.889158, 1, 1, 1, 1.05, 1, 9.0804e-08, -5.21541e-08, 5.36442e-07, -0.373219, -0.0555838, 8.64882e-05, 0.926077, 1, 1, 1, 1.25, 1, 9.0804e-08, -5.21541e-08, 5.36442e-07, -0.373219, -0.0555838, 8.64882e-05, 0.926077, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="168"> 0, 1, 5.21541e-08, -1.19209e-07, 9.31323e-08, 0.00219921, 0.118787, -0.0237834, 0.992633, 1, 1, 1, 0.05, 1, 5.96046e-08, 0, -5.58794e-08, 0.00569734, 0.111426, -0.0235639, 0.993477, 1, 1, 1, 0.1, 1, 4.47035e-08, -1.19209e-07, 3.35276e-08, 0.015864, 0.0910374, -0.022104, 0.995476, 1, 1, 1, 0.25, 1, 2.98023e-08, 1.19209e-07, -5.58794e-08, 0.0701794, 0.000367211, 0.000696922, 0.997534, 1, 1, 1, 0.35, 1, 8.19564e-08, -1.19209e-07, -1.11759e-08, 0.121501, -0.050768, 0.0840024, 0.987727, 1, 1, 1, 0.4, 1, 7.45058e-08, 1.19209e-07, 1.04308e-07, 0.115586, -0.0703619, 0.0928345, 0.986444, 1, 1, 1, 0.45, 1, 7.45058e-08, 1.19209e-07, 3.72529e-08, 0.0659214, -0.0866695, 0.0774413, 0.991033, 1, 1, 1, 0.5, 1, -5.96046e-08, 1.19209e-07, -1.11759e-07, 0.0031081, -0.0968864, 0.054063, 0.993821, 1, 1, 1, 0.55, 1, 5.96046e-08, 0, -6.70552e-08, -0.0166663, -0.0982007, 0.0374834, 0.994321, 1, 1, 1, 0.6, 1, 5.96046e-08, 1.19209e-07, -4.84288e-08, -0.0148445, -0.0906634, 0.0264974, 0.995418, 1, 1, 1, 0.65, 1, 0, 0, 4.09782e-08, -0.0108355, -0.0727448, 0.0177847, 0.997133, 1, 1, 1, 1, 1, 6.70552e-08, 0, 7.07805e-08, 0.00219189, 0.11394, -0.0230367, 0.993218, 1, 1, 1, 1.05, 1, 5.21541e-08, -1.19209e-07, 9.31323e-08, 0.00219921, 0.118787, -0.0237834, 0.992633, 1, 1, 1, 1.25, 1, 5.21541e-08, -1.19209e-07, 9.31323e-08, 0.00219921, 0.118787, -0.0237834, 0.992633, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="144"> 0, 1, 2.98023e-08, 2.98023e-08, 1.04308e-07, 0.217295, 0.0746597, -0.0103365, 0.973192, 1, 0.999999, 1, 0.05, 1, -8.9407e-08, 1.49012e-08, 1.49012e-08, 0.151772, 0.0624666, -0.00777083, 0.986409, 1, 1, 1, 0.1, 1, -2.98023e-08, 2.98023e-08, -8.9407e-08, -0.00391929, 0.0335048, -0.00214722, 0.999429, 1, 0.999999, 1, 0.3, 1, 0, 3.72529e-08, -1.49012e-07, -0.748933, -0.0405244, 0.0112371, 0.66131, 1, 1, 1, 0.35, 1, 5.96046e-08, 7.45058e-09, -3.12924e-07, -0.802758, -0.0149771, 0.00481471, 0.596097, 1, 1, 1, 0.4, 1, 0, 7.45058e-09, -1.78814e-07, -0.770121, 0.00992629, -0.000335305, 0.63782, 1, 1, 1, 0.8, 1, -5.96046e-08, 5.21541e-08, -1.04308e-07, 0.0878935, -0.0301616, 0.023494, 0.995396, 1, 1, 1, 0.85, 1, 2.98023e-08, 5.21541e-08, -2.98023e-07, 0.0819817, -0.0162162, 0.0156585, 0.996379, 1, 0.999999, 1, 0.9, 1, -5.96046e-08, 7.45058e-09, -1.3411e-07, 0.0980511, 0.00664153, 0.00756362, 0.99513, 1, 0.999999, 1, 1, 1, -5.96046e-08, 2.98023e-08, -2.98023e-08, 0.201153, 0.0660118, -0.00800331, 0.9773, 1, 0.999999, 1, 1.05, 1, 2.98023e-08, 2.98023e-08, 1.04308e-07, 0.217295, 0.0746597, -0.0103365, 0.973192, 1, 0.999999, 1, 1.25, 1, 2.98023e-08, 2.98023e-08, 1.04308e-07, 0.217295, 0.0746597, -0.0103365, 0.973192, 1, 0.999999, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="228"> 0, 1, 4.19095e-08, 1.41561e-07, 2.98023e-07, -0.33502, -0.0565195, 0.00376308, 0.940507, 1, 1, 1, 0.05, 1, 2.82889e-08, 1.86265e-07, 0, -0.412041, -0.0666523, 0.00293558, 0.908719, 1, 1, 1, 0.2, 1, -7.12462e-08, -1.2666e-07, 5.96046e-08, -0.831864, -0.10996, -0.00255585, 0.543972, 1, 1, 1, 0.25, 1, 2.32831e-09, -1.04308e-07, 5.96046e-08, 0.89602, 0.0970023, 0.00298318, -0.433277, 1, 1, 1, 0.3, 1, 1.9907e-08, 3.65078e-07, 2.98023e-07, 0.921569, 0.0590099, 0.00230107, -0.383696, 1, 1, 1, 0.35, 1, -8.28877e-08, -1.93715e-07, 2.38419e-07, 0.901128, 0.00554219, 0.000798309, -0.433517, 1, 1, 1, 0.4, 1, -7.53207e-08, 5.21541e-08, 1.19209e-07, -0.81758, 0.0439972, 0.000730356, 0.574132, 1, 1, 1, 0.5, 1, -2.91038e-09, 1.41561e-07, 2.38419e-07, -0.503688, 0.068707, 0.00074972, 0.861149, 1, 1, 1, 0.55, 1, 6.1933e-08, 8.19564e-08, 5.96046e-08, -0.352333, 0.0527461, -0.000239235, 0.934387, 1, 1, 1, 0.6, 1, -2.95695e-08, 1.04308e-07, 1.78814e-07, -0.244271, 0.03738, -0.00103017, 0.968986, 1, 1, 1, 0.65, 1, 9.54606e-09, 3.50177e-07, 1.78814e-07, -0.200824, 0.0283491, -0.00130918, 0.979216, 1, 1, 1, 0.7, 1, 2.01399e-08, 2.23517e-08, 0, -0.167963, 0.0193272, -0.0011918, 0.985603, 1, 1, 1, 0.75, 1, -2.47965e-08, -2.23517e-07, 1.19209e-07, -0.0847999, 0.00700657, -0.000838314, 0.996373, 1, 1, 1, 0.8, 1, -4.88944e-08, -7.45058e-09, 0, -0.073705, 0.000793342, 3.27131e-05, 0.99728, 1, 1, 1, 0.9, 1, -5.50644e-08, 0, 1.19209e-07, -0.297998, -0.0240387, 0.0012853, 0.954263, 1, 1, 1, 0.95, 1, -1.08266e-08, -2.98023e-08, 1.19209e-07, -0.340478, -0.0423349, 0.0021981, 0.939296, 1, 1, 1, 1, 1, 5.07571e-08, -1.63913e-07, 0, -0.339784, -0.0539663, 0.00332048, 0.938948, 1, 1, 1, 1.05, 1, 4.19095e-08, 1.41561e-07, 2.98023e-07, -0.33502, -0.0565195, 0.00376308, 0.940507, 1, 1, 1, 1.25, 1, 4.19095e-08, 1.41561e-07, 2.98023e-07, -0.33502, -0.0565195, 0.00376308, 0.940507, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="192"> 0, 1, -3.72529e-08, 0, 8.19564e-08, -0.0168517, 0.0989445, -0.0394225, 0.994169, 1, 1, 1, 0.05, 1, 6.70552e-08, 1.19209e-07, -4.47035e-08, -0.0168456, 0.0944203, -0.0381151, 0.99466, 1, 1, 1, 0.1, 1, 1.49012e-08, 1.19209e-07, -3.35276e-08, -0.0167772, 0.0819293, -0.034504, 0.995899, 1, 1, 1, 0.15, 1, -7.45058e-09, 1.19209e-07, -1.3411e-07, -0.0165494, 0.0617975, -0.0286797, 0.997539, 1, 1, 1, 0.4, 1, -2.23517e-08, 0, 2.6077e-08, -0.00864448, -0.0855905, 0.0141105, 0.996193, 1, 1, 1, 0.45, 1, 7.45058e-09, 2.38419e-07, -7.45058e-08, -0.00528641, -0.10464, 0.0196597, 0.994302, 1, 1, 1, 0.5, 1, -1.49012e-08, 1.19209e-07, 7.45058e-09, -0.00140908, -0.115976, 0.0229639, 0.992986, 1, 1, 1, 0.55, 1, 1.49012e-08, 2.38419e-07, 3.72529e-08, 0.00315788, -0.117918, 0.023482, 0.992741, 1, 1, 1, 0.6, 1, -2.98023e-08, 1.19209e-07, -1.49012e-08, 0.00993965, -0.108994, 0.0205203, 0.993781, 1, 1, 1, 0.65, 1, 1.49012e-08, 0, 1.86265e-08, 0.0206495, -0.0875135, 0.0140912, 0.99585, 1, 1, 1, 0.8, 1, -2.23517e-08, 1.19209e-07, -3.72529e-09, 0.0751354, 0.00445886, 0.00173853, 0.997162, 1, 1, 1, 0.9, 1, 0, 0, -2.98023e-08, 0.131833, 0.0617586, 0.0448617, 0.988329, 1, 1, 1, 0.95, 1, 3.72529e-08, 0, -6.70552e-08, 0.10712, 0.0825392, 0.0325464, 0.99028, 1, 1, 1, 1, 1, 1.49012e-08, 2.38419e-07, -4.84288e-08, 0.0202877, 0.0962194, -0.0179372, 0.994992, 1, 1, 1, 1.05, 1, -3.72529e-08, 0, 8.19564e-08, -0.0168517, 0.0989445, -0.0394225, 0.994169, 1, 1, 1, 1.25, 1, -3.72529e-08, 0, 8.19564e-08, -0.0168517, 0.0989445, -0.0394225, 0.994169, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="24"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="216"> 0, 1, -5.68434e-14, 0, 0.850875, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -5.68434e-14, 0, 0.888268, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, -5.68434e-14, 0, 0.982704, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.15, 1, -5.68434e-14, 0, 1.10101, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, -5.68434e-14, 0, 1.19526, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.25, 1, -5.68434e-14, 0, 1.23253, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, -5.68434e-14, 0, 1.20497, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.35, 1, -5.68434e-14, 0, 1.13278, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.45, 1, -5.68434e-14, 0, 0.935015, 0, 0, 0, 1, 1, 1, 1, 0.5, 1, -5.68434e-14, 0, 0.868188, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -5.68434e-14, 0, 0.85559, 0, 0, 0, 1, 1, 1, 1, 0.6, 1, -5.68434e-14, 0, 0.901897, 0, 0, 0, 1, 1, 1, 1, 0.75, 1, -5.68434e-14, 0, 1.20896, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -5.68434e-14, 0, 1.22782, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.85, 1, -5.68434e-14, 0, 1.18155, 0, 0, 0, 1, 1, 1, 1, 1, 1, -5.68434e-14, 0, 0.874524, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, -5.68434e-14, 0, 0.850875, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -5.68434e-14, 0, 0.850875, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="180"> 0, 1, -0.142338, -0.946415, 0.217759, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.142333, -0.853172, 0.14976, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, -0.142326, -0.626394, 0.0493819, 0, 0, 0, 1, 1, 1, 1, 0.25, 1, -0.142324, 0.323052, 0.113333, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.139402, 1.42157, 0.666575, 0, 0, 0, 1, 1, 1, 1, 0.5, 1, -0.136793, 1.55206, 0.805069, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -0.131841, 1.57295, 0.911952, 0, 0, 0, 1, 1, 1, 1, 0.6, 1, -0.113377, 1.47151, 1.00452, 0, 0, 0, 1, 1, 1, 1, 0.65, 1, -0.077946, 1.23249, 1.08549, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -0.0017584, 0.265596, 1.17195, 0, 0, 0, 1, 1, 1, 1, 0.85, 1, -0.0190262, -0.03908, 1.05516, 0, 0, 0, 1, 1, 1, 1, 0.95, 1, -0.100589, -0.692012, 0.50379, 0, 0, 0, 1, 1, 1, 1, 1, 1, -0.133542, -0.895383, 0.278588, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, -0.142338, -0.946415, 0.217759, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.142338, -0.946415, 0.217759, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="192"> 0, 1, 0.133965, 1.58294, 0.896163, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.120869, 1.49689, 0.924311, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, 0.0877482, 1.26696, 0.995435, 0, 0, 0, 1, 1, 1, 1, 0.25, 1, 0, 0.313476, 1.18387, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, 0.0102771, 0.0502403, 1.13241, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, 0.0744684, -0.535892, 0.782828, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, 0.110957, -0.769809, 0.54983, 0, 0, 0, 1, 1, 1, 1, 0.5, 1, 0.13588, -0.912113, 0.342608, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, 0.142337, -0.934969, 0.197995, 0, 0, 0, 1, 1, 1, 1, 0.6, 1, 0.142331, -0.819832, 0.0904105, 0, 0, 0, 1, 1, 1, 1, 0.65, 1, 0.142325, -0.584709, 0.0345853, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, 0.14222, 0.375652, 0.134472, 0, 0, 0, 1, 1, 1, 1, 0.95, 1, 0.136416, 1.34572, 0.707882, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0.134481, 1.53602, 0.857536, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, 0.133965, 1.58294, 0.896163, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.133965, 1.58294, 0.896163, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="192"> 0, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.098364, 0.655731, -0.762274, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.1, 1, 0.092555, 0.616937, -0.717148, 4.1297e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.15, 1, 0.0832335, 0.55472, -0.644792, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.4, 1, 0.0154476, 0.102931, -0.119635, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.45, 1, 0.00660282, 0.0440027, -0.051146, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.5, 1, 0.00131494, 0.00876498, -0.0101888, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, 0.000308841, 0.00205886, -0.00239307, 7.10993e-08, 6.08666e-15, -4.32757e-22, 1, 1, 1, 1, 0.6, 1, 0.00340915, 0.0227199, -0.0264083, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.65, 1, 0.0108188, 0.0720865, -0.0837842, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.7, 1, 0.0221942, 0.14786, -0.171845, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.9, 1, 0.0824287, 0.549322, -0.638501, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.95, 1, 0.0927294, 0.618084, -0.718475, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 1, 1, 0.0989292, 0.659501, -0.766658, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="192"> 0, 1, 2.98023e-08, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.00210956, 0.0140947, -0.0163979, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.1, 1, -0.00791863, 0.0528884, -0.0615235, 4.1297e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.15, 1, -0.0172402, 0.115105, -0.13388, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.4, 1, -0.085026, 0.566894, -0.659037, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.45, 1, -0.0938708, 0.625823, -0.727526, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.5, 1, -0.0991587, 0.66106, -0.768483, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -0.100165, 0.667766, -0.776279, 7.10993e-08, 6.08666e-15, -4.32757e-22, 1, 1, 1, 1, 0.6, 1, -0.0970645, 0.647105, -0.752263, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.65, 1, -0.0896548, 0.597739, -0.694888, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.7, 1, -0.0782794, 0.521965, -0.606827, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.9, 1, -0.0180449, 0.120504, -0.14017, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.95, 1, -0.00774428, 0.0517416, -0.0601966, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 1, 1, -0.00154439, 0.0103241, -0.0120134, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, 2.98023e-08, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 2.98023e-08, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="180"> 0, 1, -0.868295, -0.434147, -0.728793, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.894115, -0.429589, -0.685758, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -0.965105, -0.417039, -0.56775, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, -1.07881, -0.396902, -0.379345, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -1.9017, -0.250463, 0.973224, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -2.00893, -0.231348, 1.14912, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, -2.07309, -0.219917, 1.25447, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -2.08428, -0.222594, 1.27283, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.6, 1, -2.0356, -0.276793, 1.19246, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.65, 1, -1.92036, -0.39421, 1.00266, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.75, 1, -1.5939, -0.636021, 0.464508, 0, 0, 0, 1, 1, 1, 1, 0.95, 1, -0.989962, -0.50147, -0.527541, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1, 1, -0.8923, -0.448337, -0.688738, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, -0.868295, -0.434147, -0.728793, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.868295, -0.434147, -0.728793, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="180"> 0, 1, 2.08906, -0.217074, 1.28073, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 2.04863, -0.260861, 1.21323, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, 1.93875, -0.371377, 1.03141, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, 1.47813, -0.663608, 0.273554, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, 0.953814, -0.514624, -0.588262, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, 0.884829, -0.464922, -0.701557, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, 0.872045, -0.428974, -0.722627, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.6, 1, 0.909668, -0.39768, -0.660821, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.65, 1, 0.999508, -0.365756, -0.513451, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.7, 1, 1.13734, -0.334072, -0.287612, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.9, 1, 1.86856, -0.237138, 0.914287, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.95, 1, 1.99427, -0.225258, 1.12276, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1, 1, 2.07012, -0.218627, 1.24908, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, 2.08906, -0.217074, 1.28073, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 2.08906, -0.217074, 1.28073, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="192"> 0, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.429983, 0.0015192, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, 0.498118, 0.0057025, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, 0.607264, 0.0124156, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, 1.39747, 0.061233, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, 1.50046, 0.0676029, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, 1.56207, 0.0714109, 0, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, 1.5738, 0.0721354, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.6, 1, 1.53767, 0.0699027, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.65, 1, 1.45139, 0.0645664, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.7, 1, 1.31902, 0.0563741, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.9, 1, 0.616836, 0.0129952, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.95, 1, 0.496168, 0.00557709, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1, 1, 0.423375, 0.00111222, 0, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="192"> 0, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -1.55262, 0.0708387, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -1.48449, 0.0666554, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, -1.37534, 0.0599422, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -0.585136, 0.0111248, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.482148, 0.00475502, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, -0.420538, 0.000946999, 0, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -0.408805, 0.000222445, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.6, 1, -0.444934, 0.00245523, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.65, 1, -0.531212, 0.00779152, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.7, 1, -0.663587, 0.0159838, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.9, 1, -1.36577, 0.0593629, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.95, 1, -1.48644, 0.0667808, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1, 1, -1.55923, 0.0712457, 0, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="276"> 0, 1, 0.0502379, 0.036174, 0.108012, 7.74552e-15, -1.97402e-08, 0.0871557, 0.996195, 1, 1, 1, 0.05, 1, 0.0469382, 0.0509099, 0.094259, -3.35906e-14, -1.89171e-08, 0.0835209, 0.996506, 1, 1, 1, 0.1, 1, 0.0379226, 0.088175, 0.0594788, -4.57539e-14, -1.66467e-08, 0.0734954, 0.997296, 1, 1, 1, 0.15, 1, 0.0249111, 0.134917, 0.0158529, -3.14989e-14, -1.29934e-08, 0.0573644, 0.998353, 1, 1, 1, 0.2, 1, 0.0112907, 0.17217, -0.0189178, -1.3373e-14, -8.15547e-09, 0.0360035, 0.999352, 1, 1, 1, 0.25, 1, 2.27588e-08, 0.186899, -0.0326645, -1.50375e-14, -2.49281e-09, 0.0110021, 0.99994, 1, 1, 1, 0.3, 1, -0.0104418, 0.176016, -0.0225072, -7.05369e-14, 3.45387e-09, -0.0152525, 0.999884, 1, 1, 1, 0.35, 1, -0.0222285, 0.147506, 0.00410175, -3.23609e-14, 9.01354e-09, -0.039798, 0.999208, 1, 1, 1, 0.4, 1, -0.0338161, 0.108041, 0.0409362, -3.84007e-14, 1.36964e-08, -0.0604725, 0.99817, 1, 1, 1, 0.45, 1, -0.043192, 0.0694027, 0.0769985, -3.85801e-14, 1.71613e-08, -0.0757699, 0.997125, 1, 1, 1, 0.5, 1, -0.0488776, 0.0430113, 0.10163, -7.13117e-15, 1.92273e-08, -0.084891, 0.99639, 1, 1, 1, 0.55, 1, -0.049846, 0.0380361, 0.106274, -6.66418e-14, 1.96198e-08, -0.0866238, 0.996241, 1, 1, 1, 0.6, 1, -0.0458462, 0.0563236, 0.0892055, -1.43694e-14, 1.84095e-08, -0.0812805, 0.996691, 1, 1, 1, 0.65, 1, -0.0363638, 0.0959547, 0.0522163, -5.40282e-14, 1.5511e-08, -0.0684838, 0.997652, 1, 1, 1, 0.7, 1, -0.0231681, 0.1427, 0.0085876, -3.25683e-14, 1.10473e-08, -0.0487772, 0.99881, 1, 1, 1, 0.75, 1, -0.00951665, 0.177588, -0.0239747, 1.83932e-15, 5.34013e-09, -0.0235807, 0.999722, 1, 1, 1, 0.8, 1, 0.00190332, 0.185037, -0.0309267, -4.07805e-14, -1.06814e-09, 0.00471147, 0.999989, 1, 1, 1, 0.85, 1, 0.0140465, 0.166752, -0.0138602, -8.20187e-14, -7.29738e-09, 0.0322142, 0.999481, 1, 1, 1, 0.9, 1, 0.0278208, 0.127127, 0.0231235, -3.37482e-14, -1.26773e-08, 0.0559684, 0.998433, 1, 1, 1, 0.95, 1, 0.0402532, 0.080384, 0.0667505, -4.05783e-14, -1.67149e-08, 0.0737966, 0.997273, 1, 1, 1, 1, 1, 0.0482781, 0.0454891, 0.0993183, 1.00279e-15, -1.91378e-08, 0.0844954, 0.996424, 1, 1, 1, 1.05, 1, 0.0502379, 0.036174, 0.108012, 7.74552e-15, -1.97402e-08, 0.0871557, 0.996195, 1, 1, 1, 1.25, 1, 0.0502379, 0.036174, 0.108012, 7.74552e-15, -1.97402e-08, 0.0871557, 0.996195, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="192"> 0, 1, 4.1909e-09, -2.55596e-10, -3.57628e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1, 0.05, 1, 3.53838e-09, 6.53649e-11, -5.96046e-08, 0.0550183, -0.0046113, -0.0833935, 0.994986, 1, 1, 1, 0.1, 1, -5.60775e-10, -7.51698e-09, -2.98023e-08, 0.0550619, -0.00405785, -0.0733833, 0.995774, 1, 1, 1, 0.15, 1, -2.23866e-09, -1.11867e-08, -1.49012e-07, 0.0551203, -0.00316731, -0.0572769, 0.996831, 1, 1, 1, 0.4, 1, -2.04997e-09, -2.75862e-09, 1.78814e-07, 0.0551102, 0.00333869, 0.0603803, 0.996647, 1, 1, 1, 0.45, 1, 2.0486e-09, 4.35754e-10, 5.96046e-08, 0.0550525, 0.00418331, 0.0756543, 0.995605, 1, 1, 1, 0.5, 1, -5.1223e-09, 2.12108e-09, 1.19209e-07, 0.0550119, 0.00468692, 0.0847616, 0.994871, 1, 1, 1, 0.55, 1, 9.31448e-11, -6.0701e-10, 0, 0.0550037, 0.00478259, 0.0864917, 0.994722, 1, 1, 1, 0.6, 1, -8.38328e-10, -2.70165e-09, 0, 0.0550285, 0.00448757, 0.0811565, 0.995171, 1, 1, 1, 0.65, 1, -5.5956e-10, 2.044e-09, 2.98023e-08, 0.0550816, 0.00378102, 0.0683793, 0.996131, 1, 1, 1, 0.7, 1, -1.88318e-10, -1.00538e-08, -1.49012e-07, 0.0551455, 0.00269294, 0.0487028, 0.997286, 1, 1, 1, 0.9, 1, -2.42557e-09, -9.9462e-09, 1.19209e-07, 0.0551247, -0.00309027, -0.055883, 0.99691, 1, 1, 1, 0.95, 1, 2.79174e-09, -8.13951e-09, 0, 0.0550607, -0.00407449, -0.073684, 0.995752, 1, 1, 1, 1, 1, -4.66262e-10, 1.71346e-09, 0, 0.0550138, -0.0046651, -0.0843665, 0.994904, 1, 1, 1, 1.05, 1, 4.1909e-09, -2.55596e-10, -3.57628e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1, 1.25, 1, 4.1909e-09, -2.55596e-10, -3.57628e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="192"> 0, 1, 4.20218e-09, -1.49012e-08, 0, 0.0550026, -0.0108562, -0.086477, 0.994675, 1, 1, 1, 0.05, 1, 6.60681e-10, -7.45058e-09, -5.96046e-08, 0.0550197, -0.0104035, -0.0828704, 0.994986, 1, 1, 1, 0.1, 1, 1.42138e-09, -7.45058e-09, 1.19209e-07, 0.0550633, -0.00915483, -0.072923, 0.995774, 1, 1, 1, 0.15, 1, -1.4402e-10, -1.86265e-08, -5.96046e-08, 0.0551217, -0.00714571, -0.0569177, 0.99683, 1, 1, 1, 0.4, 1, -2.54046e-09, 7.45058e-09, -1.78814e-07, 0.0551116, 0.00753235, 0.0600015, 0.996647, 1, 1, 1, 0.45, 1, -2.31643e-09, 1.86265e-08, -1.78814e-07, 0.0550539, 0.00943788, 0.0751797, 0.995604, 1, 1, 1, 0.5, 1, -3.16026e-09, 1.49012e-08, 5.96046e-08, 0.0550134, 0.0105741, 0.0842299, 0.99487, 1, 1, 1, 0.55, 1, -4.35034e-09, 2.23517e-08, -1.78814e-07, 0.0550051, 0.0107899, 0.0859492, 0.994722, 1, 1, 1, 0.6, 1, -1.53961e-09, -7.45058e-09, 5.96046e-08, 0.05503, 0.0101243, 0.0806475, 0.995171, 1, 1, 1, 0.65, 1, -1.47879e-09, -1.86265e-08, -5.96046e-08, 0.055083, 0.00853027, 0.0679504, 0.996131, 1, 1, 1, 0.7, 1, -2.07954e-09, 2.6077e-08, -2.38419e-07, 0.0551469, 0.00607548, 0.0483973, 0.997286, 1, 1, 1, 0.9, 1, -1.29246e-09, -2.6077e-08, 5.96046e-08, 0.0551261, -0.00697189, -0.0555325, 0.99691, 1, 1, 1, 0.95, 1, 2.48766e-09, -7.45058e-09, 5.96046e-08, 0.0550621, -0.00919238, -0.0732219, 0.995752, 1, 1, 1, 1, 1, -1.94411e-09, -7.45058e-09, -1.19209e-07, 0.0550152, -0.0105248, -0.0838373, 0.994904, 1, 1, 1, 1.05, 1, 4.20218e-09, -1.49012e-08, 0, 0.0550026, -0.0108562, -0.086477, 0.994675, 1, 1, 1, 1.25, 1, 4.20218e-09, -1.49012e-08, 0, 0.0550026, -0.0108562, -0.086477, 0.994675, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="24"> 0, 1, 1.58195e-10, -1.19209e-07, -8.34465e-07, -1.49012e-08, 2.17021e-10, 8.15234e-10, 1, 1, 1, 1, 1.25, 1, 1.58195e-10, -1.19209e-07, -8.34465e-07, -1.49012e-08, 2.17021e-10, 8.15234e-10, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="144"> 0, 1, 8.86136e-10, -2.38419e-07, -4.91273e-08, 0.0549542, -0.0952446, 0.00487296, 0.993924, 1, 1, 1, 0.05, 1, 2.18506e-09, -1.78814e-07, -5.65778e-08, 0.0504772, -0.0912067, 0.0042631, 0.994543, 1, 1, 1, 0.1, 1, 5.53928e-10, -4.17233e-07, -3.67872e-08, 0.0390059, -0.0800384, 0.00284171, 0.996024, 1, 1, 1, 0.45, 1, -5.1797e-09, -8.04663e-07, -5.82077e-08, 0.0448447, 0.08285, -0.00340957, 0.995547, 1, 1, 1, 0.5, 1, 3.73723e-09, 3.57628e-07, -5.28526e-08, 0.052893, 0.0927872, -0.00455309, 0.99427, 1, 1, 1, 0.55, 1, 3.81474e-09, -2.98023e-08, -4.30737e-08, 0.0543919, 0.0946615, -0.00479041, 0.994011, 1, 1, 1, 0.6, 1, 5.97727e-09, -1.01328e-06, -7.35745e-08, 0.0488359, 0.0887913, -0.00401032, 0.994844, 1, 1, 1, 0.65, 1, -3.89822e-10, -6.25849e-07, -7.96281e-08, 0.0366099, 0.0746935, -0.00247956, 0.996531, 1, 1, 1, 0.95, 1, -4.46247e-09, 1.19209e-07, -6.96164e-08, 0.0414353, -0.080551, 0.00304791, 0.995884, 1, 1, 1, 1, 1, 2.64143e-09, -5.96046e-07, -7.72998e-08, 0.052136, -0.0923283, 0.0044599, 0.994353, 1, 1, 1, 1.05, 1, 8.86136e-10, -2.38419e-07, -4.91273e-08, 0.0549542, -0.0952446, 0.00487296, 0.993924, 1, 1, 1, 1.25, 1, 8.86136e-10, -2.38419e-07, -4.91273e-08, 0.0549542, -0.0952446, 0.00487296, 0.993924, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="24"> 0, 1, -3.08853e-09, 1.69966e-08, 3.98955e-07, 4.70848e-20, -1.3217e-10, -5.67425e-10, 1, 1, 1, 1, 1.25, 1, -3.08853e-09, 1.69966e-08, 3.98955e-07, 4.70848e-20, -1.3217e-10, -5.67425e-10, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="24"> 0, 1, 5.17831e-08, 0.00292331, 0.204329, 3.25963e-09, -2.17324e-11, 3.00563e-10, 1, 1, 1, 1, 1.25, 1, 5.17831e-08, 0.00292331, 0.204329, 3.25963e-09, -2.17324e-11, 3.00563e-10, 1, 1, 1, 1 </real_array>
-
- </resource>
- <resource type="Animation" path="local://13">
- <string name="resource/name"> "shooting_standing" </string>
- <real name="length"> 0.416667 </real>
- <bool name="loop"> False </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="132"> 0, 1, 5.96046e-07, -1.19209e-07, 4.47035e-07, -0.206314, 0.709894, -0.150643, 0.656348, 1, 1, 1, 0.05, 1, 1.07288e-06, -4.76837e-07, 8.34465e-07, -0.199825, 0.723236, -0.14911, 0.644023, 1, 1, 1, 0.1, 1, 4.47035e-07, -1.19209e-07, 3.27826e-07, -0.186028, 0.74616, -0.147051, 0.622106, 1, 1, 1, 0.15, 1, 4.47035e-07, -1.19209e-07, 1.49012e-07, -0.168011, 0.761016, -0.149525, 0.608497, 1, 1, 1, 0.2, 1, 2.38419e-07, 1.19209e-07, -1.19209e-07, -0.141127, 0.777642, -0.158168, 0.591895, 1, 1, 1, 0.25, 1, 7.15256e-07, -2.38419e-07, 2.68221e-07, -0.129783, 0.779527, -0.165304, 0.590059, 1, 1, 1, 0.3, 1, 6.25849e-07, -1.19209e-07, 2.08616e-07, -0.152097, 0.757922, -0.164122, 0.612768, 1, 1, 1, 0.35, 1, 8.9407e-07, -4.76837e-07, 8.34465e-07, -0.183836, 0.730436, -0.157254, 0.638701, 1, 1, 1, 0.4, 1, 7.45058e-07, -3.57628e-07, 5.66244e-07, -0.202964, 0.713054, -0.151716, 0.653714, 1, 1, 1, 0.45, 1, 5.96046e-07, -1.19209e-07, 4.47035e-07, -0.206314, 0.709894, -0.150643, 0.656348, 1, 1, 1, 1.25, 1, 5.96046e-07, -1.19209e-07, 4.47035e-07, -0.206314, 0.709894, -0.150643, 0.656348, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="120"> 0, 1, 0, -4.76837e-07, -7.7486e-07, 0.0490264, -0.364254, 0.0100564, 0.929954, 1, 1, 1, 0.05, 1, 1.19209e-07, -4.47035e-07, -4.76837e-07, 0.0346734, -0.325178, 0.00768963, 0.944986, 1, 1, 1, 0.1, 1, 1.19209e-07, -5.06639e-07, -3.57628e-07, 0.00822793, -0.255634, 0.00344931, 0.966732, 1, 1, 1, 0.15, 1, 2.98023e-08, -7.15256e-07, -5.96046e-07, -0.00893206, -0.219161, 0.00118009, 0.975647, 1, 1, 1, 0.2, 1, 1.49012e-07, -4.47035e-07, -5.96046e-07, -0.0220165, -0.204408, 0.000203021, 0.978638, 1, 1, 1, 0.25, 1, 4.17233e-07, -4.76837e-07, -5.36442e-07, -0.0204464, -0.223283, 0.00158917, 0.974538, 1, 1, 1, 0.35, 1, 1.19209e-07, -6.85453e-07, -2.98023e-07, 0.0295549, -0.331584, 0.00842644, 0.942925, 1, 1, 1, 0.4, 1, 0, -6.55651e-07, -6.55651e-07, 0.0460614, -0.359518, 0.00983853, 0.931949, 1, 1, 1, 0.45, 1, 0, -4.76837e-07, -7.7486e-07, 0.0490264, -0.364254, 0.0100564, 0.929954, 1, 1, 1, 1.25, 1, 0, -4.76837e-07, -7.7486e-07, 0.0490264, -0.364254, 0.0100564, 0.929954, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="132"> 0, 1, -4.17233e-07, -3.57628e-07, 4.47035e-07, -0.474516, -0.584521, 0.0340579, 0.657274, 1, 1, 1, 0.05, 1, -7.45058e-07, -3.57628e-07, 5.36442e-07, -0.46761, -0.58693, 0.0339523, 0.660076, 1, 1, 1, 0.1, 1, -4.76837e-07, -2.38419e-07, 2.98023e-07, -0.452786, -0.591715, 0.0339493, 0.666112, 1, 1, 1, 0.15, 1, -6.55651e-07, -3.57628e-07, 2.98023e-07, -0.443727, -0.588057, 0.0337848, 0.675392, 1, 1, 1, 0.2, 1, 2.98023e-08, 1.19209e-07, -3.27826e-07, -0.450408, -0.563251, 0.0324613, 0.691973, 1, 1, 1, 0.25, 1, -5.96046e-07, -3.57628e-07, 2.98023e-07, -0.461281, -0.543778, 0.0314456, 0.700383, 1, 1, 1, 0.3, 1, -4.17233e-07, 0, 1.78814e-07, -0.469244, -0.550688, 0.0318109, 0.689595, 1, 1, 1, 0.35, 1, -7.7486e-07, -2.38419e-07, 4.76837e-07, -0.473462, -0.569016, 0.0329517, 0.671542, 1, 1, 1, 0.4, 1, -6.25849e-07, -3.57628e-07, 5.96046e-07, -0.474439, -0.5821, 0.0338759, 0.659485, 1, 1, 1, 0.45, 1, -4.17233e-07, -3.57628e-07, 4.47035e-07, -0.474516, -0.584521, 0.0340579, 0.657274, 1, 1, 1, 1.25, 1, -4.17233e-07, -3.57628e-07, 4.47035e-07, -0.474516, -0.584521, 0.0340579, 0.657274, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="96"> 0, 1, 1.78814e-07, 2.98023e-08, -3.57628e-07, -0.156054, -0.257929, 9.29801e-05, 0.953478, 1.3, 1.3, 1.3, 0.05, 1, -8.9407e-08, -9.23872e-07, -2.98023e-07, -0.156186, -0.25785, 0.000491834, 0.953477, 1.3, 1.3, 1.3, 0.1, 1, 0, -5.06639e-07, -2.98023e-07, -0.156442, -0.257682, 0.00128265, 0.95348, 1.3, 1.3, 1.3, 0.15, 1, -2.08616e-07, -5.36442e-07, -5.96046e-08, -0.156528, -0.257623, 0.00155313, 0.953481, 1.3, 1.3, 1.3, 0.25, 1, 2.98023e-08, -5.36442e-07, -3.57628e-07, -0.155874, -0.258131, -0.000583909, 0.953452, 1.3, 1.3, 1.3, 0.35, 1, 2.98023e-08, -4.76837e-07, -3.57628e-07, -0.15592, -0.258051, -0.000371468, 0.953467, 1.3, 1.3, 1.3, 0.4, 1, 1.49012e-07, -2.68221e-07, -2.98023e-07, -0.156032, -0.257949, 1.56283e-05, 0.953476, 1.3, 1.3, 1.3, 1.25, 1, 1.78814e-07, 2.98023e-08, -3.57628e-07, -0.156054, -0.257929, 9.29801e-05, 0.953478, 1.3, 1.3, 1.3 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="120"> 0, 1, 5.96046e-08, 2.23517e-08, -1.3411e-07, 0.301601, -0.0701581, -0.00864293, 0.95081, 1, 1, 1, 0.05, 1, 5.96046e-08, 2.98023e-08, -1.04308e-07, 0.248345, -0.0620849, -0.00736271, 0.966652, 1, 1, 1, 0.1, 1, 8.9407e-08, 6.70552e-08, -1.04308e-07, 0.175365, -0.0511626, -0.00552639, 0.983158, 1, 1, 1, 0.15, 1, 8.9407e-08, 4.47035e-08, -1.04308e-07, 0.153891, -0.0497144, -0.00660778, 0.986814, 1, 1, 1, 0.2, 1, 5.96046e-08, -2.98023e-08, -1.49012e-08, 0.151238, -0.0561188, -0.0117034, 0.986834, 1, 1, 1, 0.25, 1, 2.98023e-08, -1.49012e-08, -1.04308e-07, 0.168743, -0.0655087, -0.0152581, 0.983362, 1, 1, 1, 0.35, 1, 2.98023e-08, 2.23517e-08, -1.63913e-07, 0.26593, -0.072486, -0.0117415, 0.961192, 1, 1, 1, 0.4, 1, 5.96046e-08, 7.45058e-09, -1.78814e-07, 0.296131, -0.070636, -0.00916634, 0.952488, 1, 1, 1, 0.45, 1, 5.96046e-08, 2.23517e-08, -1.3411e-07, 0.301601, -0.0701581, -0.00864293, 0.95081, 1, 1, 1, 1.25, 1, 5.96046e-08, 2.23517e-08, -1.3411e-07, 0.301601, -0.0701581, -0.00864293, 0.95081, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="120"> 0, 1, -4.31901e-08, -7.45058e-08, 7.7486e-07, -0.33852, 0.053398, -0.0152903, 0.939319, 1, 1, 1, 0.05, 1, 5.6345e-08, -2.23517e-08, 6.55651e-07, -0.403989, 0.0628472, -0.0146608, 0.912484, 1, 1, 1, 0.1, 1, 5.02914e-08, -1.49012e-08, 5.36442e-07, -0.486228, 0.0751824, -0.0137902, 0.870483, 1, 1, 1, 0.15, 1, 1.11642e-07, 5.96046e-08, 5.96046e-07, -0.506485, 0.0840018, -0.0142775, 0.858028, 1, 1, 1, 0.2, 1, 1.23633e-07, 8.19564e-08, 5.36442e-07, -0.500531, 0.103313, -0.0168649, 0.859367, 1, 1, 1, 0.25, 1, 9.58098e-08, 1.49012e-08, 6.55651e-07, -0.475505, 0.111896, -0.0189746, 0.872361, 1, 1, 1, 0.35, 1, 7.84639e-08, 9.68575e-08, 5.96046e-07, -0.376662, 0.0699087, -0.0169347, 0.923554, 1, 1, 1, 0.4, 1, -1.16415e-09, -7.45058e-09, 7.15256e-07, -0.344524, 0.0558207, -0.0155573, 0.936987, 1, 1, 1, 0.45, 1, -4.31901e-08, -7.45058e-08, 7.7486e-07, -0.33852, 0.053398, -0.0152903, 0.939319, 1, 1, 1, 1.25, 1, -4.31901e-08, -7.45058e-08, 7.7486e-07, -0.33852, 0.053398, -0.0152903, 0.939319, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="108"> 0, 1, 1.19209e-07, 0, 1.82539e-07, -0.218034, -0.0651501, 0.015764, 0.973637, 1, 1, 1, 0.05, 1, 5.21541e-08, 0, -9.31323e-08, -0.206333, -0.0662009, 0.0171463, 0.976089, 1, 1, 1, 0.1, 1, 2.98023e-08, -1.19209e-07, -7.45058e-08, -0.188973, -0.0677374, 0.0191861, 0.979455, 1, 1, 1, 0.15, 1, 0, 0, -4.84288e-08, -0.184958, -0.0680889, 0.0196559, 0.980188, 1, 1, 1, 0.2, 1, 5.96046e-08, 0, -1.19209e-07, -0.189238, -0.0677142, 0.019155, 0.979406, 1, 1, 1, 0.35, 1, 8.19564e-08, 1.19209e-07, 3.72529e-08, -0.213767, -0.0655347, 0.0162687, 0.974548, 1, 1, 1, 0.4, 1, 1.04308e-07, 0, 5.21541e-08, -0.217419, -0.0652056, 0.0158368, 0.973769, 1, 1, 1, 0.45, 1, 1.19209e-07, 0, 1.82539e-07, -0.218034, -0.0651501, 0.015764, 0.973637, 1, 1, 1, 1.25, 1, 1.19209e-07, 0, 1.82539e-07, -0.218034, -0.0651501, 0.015764, 0.973637, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="132"> 0, 1, -5.96046e-08, -1.2666e-07, 1.04308e-07, -0.633392, 0.109953, 0.00349885, 0.765972, 1, 1, 1, 0.05, 1, 0, -4.47035e-08, 1.3411e-07, -0.628866, 0.106487, 0.00414994, 0.770176, 1, 1, 1, 0.1, 1, -2.98023e-08, 4.47035e-08, 1.49012e-07, -0.619935, 0.101098, 0.00522767, 0.778095, 1, 1, 1, 0.15, 1, -2.98023e-08, 5.96046e-08, 1.49012e-07, -0.616185, 0.108634, 0.00550208, 0.780054, 1, 1, 1, 0.2, 1, 5.96046e-08, 4.47035e-08, 2.5332e-07, -0.613177, 0.141231, 0.00523592, 0.7772, 1, 1, 1, 0.25, 1, 0, 0, 1.49012e-07, -0.612177, 0.164991, 0.00476259, 0.773301, 1, 1, 1, 0.3, 1, 5.96046e-08, -7.45058e-09, 1.3411e-07, -0.619021, 0.155086, 0.00421746, 0.769898, 1, 1, 1, 0.35, 1, 2.98023e-08, 7.45058e-09, 7.45058e-08, -0.627679, 0.130628, 0.00377015, 0.767425, 1, 1, 1, 0.4, 1, -2.98023e-08, -1.3411e-07, 7.45058e-08, -0.632568, 0.11319, 0.0035387, 0.766181, 1, 1, 1, 0.45, 1, -5.96046e-08, -1.2666e-07, 1.04308e-07, -0.633392, 0.109953, 0.00349885, 0.765972, 1, 1, 1, 1.25, 1, -5.96046e-08, -1.2666e-07, 1.04308e-07, -0.633392, 0.109953, 0.00349885, 0.765972, 1, 1, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="120"> 0, 1, -4.07454e-08, -1.11759e-07, 0, -0.55604, 0.155102, 0.00378888, 0.816547, 1, 1, 1, 0.05, 1, 7.60192e-08, -8.9407e-08, 1.19209e-07, -0.534898, 0.148998, 0.00358481, 0.831668, 1, 1, 1, 0.1, 1, -1.0326e-07, -1.49012e-08, 2.38419e-07, -0.500235, 0.139173, 0.00323174, 0.854626, 1, 1, 1, 0.15, 1, 6.41448e-08, 4.47035e-08, 1.78814e-07, -0.492131, 0.143377, 0.00332103, 0.858626, 1, 1, 1, 0.25, 1, -6.58911e-08, -8.19564e-08, 1.78814e-07, -0.517192, 0.191548, 0.00473312, 0.834146, 1, 1, 1, 0.3, 1, 3.0268e-08, 1.49012e-08, 1.19209e-07, -0.534465, 0.187415, 0.00465677, 0.824136, 1, 1, 1, 0.35, 1, 3.11993e-08, -5.21541e-08, 2.38419e-07, -0.548296, 0.170437, 0.0042049, 0.818722, 1, 1, 1, 0.4, 1, 2.51457e-08, -9.68575e-08, 1.19209e-07, -0.554953, 0.157536, 0.00385503, 0.81682, 1, 1, 1, 0.45, 1, -4.07454e-08, -1.11759e-07, 0, -0.55604, 0.155102, 0.00378888, 0.816547, 1, 1, 1, 1.25, 1, -4.07454e-08, -1.11759e-07, 0, -0.55604, 0.155102, 0.00378888, 0.816547, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="108"> 0, 1, 7.45058e-08, 1.19209e-07, 3.72529e-09, -0.143967, -0.0951747, 0.00523759, 0.984981, 1, 1, 1, 0.05, 1, 7.45058e-09, 2.38419e-07, 3.35276e-08, -0.157581, -0.0952617, 0.00367365, 0.982894, 1, 1, 1, 0.1, 1, -2.23517e-08, 1.19209e-07, -1.11759e-08, -0.17766, -0.0953568, 0.00135921, 0.97946, 1, 1, 1, 0.15, 1, -3.72529e-08, 1.19209e-07, 4.84288e-08, -0.182282, -0.0953731, 0.000825106, 0.97861, 1, 1, 1, 0.2, 1, 1.49012e-08, 1.19209e-07, -5.21541e-08, -0.177354, -0.0953557, 0.00139453, 0.979516, 1, 1, 1, 0.35, 1, 4.47035e-08, 0, 5.96046e-08, -0.148938, -0.0952085, 0.00466699, 0.984241, 1, 1, 1, 0.4, 1, 5.21541e-08, 1.19209e-07, -4.09782e-08, -0.144684, -0.0951797, 0.00515536, 0.984876, 1, 1, 1, 0.45, 1, 7.45058e-08, 1.19209e-07, 3.72529e-09, -0.143967, -0.0951747, 0.00523759, 0.984981, 1, 1, 1, 1.25, 1, 7.45058e-08, 1.19209e-07, 3.72529e-09, -0.143967, -0.0951747, 0.00523759, 0.984981, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="24"> 0, 1, 0, 1.36988, -1.03377e-07, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0, 1.36988, -1.03377e-07, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="108"> 0, 1, 8.64522e-08, 0.572547, -4.76837e-07, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 8.64522e-08, 0.572548, 0.471507, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, 8.64522e-08, 0.572548, 1.12029, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.15, 1, 8.64522e-08, 0.572548, 1.26782, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, 8.64522e-08, 0.572548, 1.10411, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.35, 1, 8.64522e-08, 0.572548, 0.166984, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.4, 1, 8.64522e-08, 0.572547, 0.024261, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, 8.64522e-08, 0.572547, -4.76837e-07, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 8.64522e-08, 0.572547, -4.76837e-07, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="108"> 0, 1, -0.0366479, -0.0811065, 0.809552, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.0366479, -0.0811065, 0.816585, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, -0.0366479, -0.0811065, 0.826986, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, -0.0366479, -0.0811065, 0.829386, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, -0.0366479, -0.0811065, 0.826827, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, -0.0366479, -0.0811065, 0.812119, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, -0.0366479, -0.0811065, 0.809922, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.0366479, -0.0811065, 0.809552, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.0366479, -0.0811065, 0.809552, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="24"> 0, 1, 0.0611181, -2.75446, 0.0815672, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.0611181, -2.75446, 0.0815672, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="24"> 0, 1, 0.0798243, -0.0543702, -2.95838, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.0798243, -0.0543702, -2.95838, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="24"> 0, 1, 0.183564, 0.0305935, -3.02205, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.183564, 0.0305935, -3.02205, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="24"> 0, 1, -2.74884, 1.12805, 3.06242, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -2.74884, 1.12805, 3.06242, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="24"> 0, 1, 1.73339, 0.895247, 5.13844, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 1.73339, 0.895247, 5.13844, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="24"> 0, 1, 0.101768, -0.813356, 5.76642, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.101768, -0.813356, 5.76642, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="24"> 0, 1, -0.849557, -0.741664, 5.51935, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.849557, -0.741664, 5.51935, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="132"> 0, 1, 2.65402e-07, 1.83685, 0.489514, -5.25643e-15, 1.43922e-08, -0.0635436, 0.997979, 1, 1, 1, 0.05, 1, 2.56992e-07, 1.7811, 0.489514, -1.96073e-14, 1.43922e-08, -0.0635436, 0.997979, 1, 1, 1, 0.1, 1, 2.44553e-07, 1.69876, 0.489514, -1.94961e-14, 1.43922e-08, -0.0635436, 0.997979, 1, 1, 1, 0.15, 1, 2.41683e-07, 1.67977, 0.489514, -4.43536e-14, 1.60316e-08, -0.070782, 0.997492, 1, 1, 1, 0.2, 1, 2.44743e-07, 1.70003, 0.489514, -3.42428e-14, 2.17962e-08, -0.0962332, 0.995359, 1, 1, 1, 0.25, 1, 2.50383e-07, 1.73738, 0.489514, -5.58716e-16, 2.56855e-08, -0.113405, 0.993549, 1, 1, 1, 0.3, 1, 2.57035e-07, 1.78143, 0.489514, -6.36206e-15, 2.33115e-08, -0.102924, 0.994689, 1, 1, 1, 0.35, 1, 2.62333e-07, 1.81652, 0.489514, -1.06935e-14, 1.84103e-08, -0.0812848, 0.996691, 1, 1, 1, 0.4, 1, 2.6496e-07, 1.83392, 0.489514, -2.45344e-14, 1.50179e-08, -0.0663065, 0.997799, 1, 1, 1, 0.45, 1, 2.65402e-07, 1.83685, 0.489514, -5.25643e-15, 1.43922e-08, -0.0635436, 0.997979, 1, 1, 1, 1.25, 1, 2.65402e-07, 1.83685, 0.489514, -5.25643e-15, 1.43922e-08, -0.0635436, 0.997979, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="120"> 0, 1, -4.65684e-10, 7.57313e-10, 0, -8.93894e-16, 2.55708e-08, -0.112898, 0.993607, 1, 1, 1, 0.05, 1, -4.18389e-09, 6.71868e-09, -2.98023e-08, -0.00385828, -0.000945429, -0.112898, 0.993599, 1, 1, 1, 0.1, 1, -2.6989e-09, 6.71803e-09, -2.98023e-08, -0.0118093, -0.00289381, -0.11289, 0.993533, 1, 1, 1, 0.15, 1, -1.65698e-09, 6.19854e-09, -1.19209e-07, -0.0173041, -0.00424031, -0.112881, 0.993449, 1, 1, 1, 0.2, 1, 6.17568e-09, 2.79554e-08, -1.78814e-07, -0.0174121, -0.00426678, -0.11288, 0.993447, 1, 1, 1, 0.25, 1, -9.69976e-10, -3.44268e-09, -2.98023e-08, -0.013893, -0.00340444, -0.112887, 0.993505, 1, 1, 1, 0.35, 1, 8.55826e-09, 2.92274e-08, -2.98023e-08, -0.00310744, -0.000761444, -0.112898, 0.993601, 1, 1, 1, 0.4, 1, 2.05826e-09, 1.24848e-08, 0, -0.000452603, -0.000110883, -0.112898, 0.993606, 1, 1, 1, 0.45, 1, -4.65684e-10, 7.57313e-10, 0, -8.93894e-16, 2.55708e-08, -0.112898, 0.993607, 1, 1, 1, 1.25, 1, -4.65684e-10, 7.57313e-10, 0, -8.93894e-16, 2.55708e-08, -0.112898, 0.993607, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="108"> 0, 1, -7.51303e-09, 2.23517e-08, -2.38419e-07, 2.43554e-09, -0.00270918, 0.0663084, 0.997796, 1, 1, 1, 0.05, 1, -5.41336e-11, 3.72529e-09, -2.38419e-07, -0.00158657, -0.00317713, 0.0662892, 0.997794, 1, 1, 1, 0.15, 1, -3.26683e-10, 0, 5.96046e-08, -0.00925885, -0.00543992, 0.0661937, 0.997749, 1, 1, 1, 0.2, 1, -2.06055e-09, 1.49012e-08, -2.38419e-07, -0.0112141, -0.00601653, 0.0661687, 0.997727, 1, 1, 1, 0.25, 1, 1.76951e-08, -3.72529e-09, -1.78814e-07, -0.0104022, -0.00577711, 0.0661791, 0.997737, 1, 1, 1, 0.35, 1, 7.20902e-09, 7.45058e-09, -1.19209e-07, -0.00273, -0.00351437, 0.0662752, 0.997791, 1, 1, 1, 0.4, 1, 4.13622e-10, 3.72529e-09, -1.78814e-07, -0.000405934, -0.00282891, 0.0663035, 0.997795, 1, 1, 1, 0.45, 1, -7.51303e-09, 2.23517e-08, -2.38419e-07, 2.43554e-09, -0.00270918, 0.0663084, 0.997796, 1, 1, 1, 1.25, 1, -7.51303e-09, 2.23517e-08, -2.38419e-07, 2.43554e-09, -0.00270918, 0.0663084, 0.997796, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="24"> 0, 1, 4.48992e-09, -1.3411e-07, -1.07288e-06, -1.49012e-08, 7.81341e-10, 2.3736e-09, 1, 1, 1, 1, 1.25, 1, 4.48992e-09, -1.3411e-07, -1.07288e-06, -1.49012e-08, 7.81341e-10, 2.3736e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="120"> 0, 1, -1.54592e-09, -2.38419e-07, -3.32948e-08, 0.0746069, -0.101992, 0.0306522, 0.99151, 1, 1, 1, 0.05, 1, -1.11768e-09, -1.19209e-07, -9.73232e-08, 0.0219469, -0.103542, 0.0251775, 0.994064, 1, 1, 1, 0.1, 1, 3.72477e-10, -2.98023e-07, -7.61356e-08, -0.0560921, -0.105311, 0.0169133, 0.992712, 1, 1, 1, 0.15, 1, 1.49005e-09, -3.8743e-07, -9.8953e-08, -0.0807068, -0.112423, 0.0155536, 0.990255, 1, 1, 1, 0.2, 1, 9.68555e-09, -1.78814e-07, -2.06754e-07, -0.0663987, -0.135548, 0.0221852, 0.988294, 1, 1, 1, 0.25, 1, 1.86265e-08, -2.68221e-07, -1.18744e-08, -0.0319373, -0.150579, 0.0303761, 0.987615, 1, 1, 1, 0.35, 1, 7.26442e-09, -6.85453e-07, 3.81842e-08, 0.0516026, -0.119052, 0.0329235, 0.990999, 1, 1, 1, 0.4, 1, -1.48637e-09, -2.38419e-07, -5.07571e-08, 0.0712567, -0.10465, 0.03106, 0.991467, 1, 1, 1, 0.45, 1, -1.54592e-09, -2.38419e-07, -3.32948e-08, 0.0746069, -0.101992, 0.0306522, 0.99151, 1, 1, 1, 1.25, 1, -1.54592e-09, -2.38419e-07, -3.32948e-08, 0.0746069, -0.101992, 0.0306522, 0.99151, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="24"> 0, 1, 3.53794e-09, -1.25496e-07, -8.33534e-08, 2.23517e-08, 1.01485e-10, -1.43572e-10, 1, 1, 1, 1, 1.25, 1, 3.53794e-09, -1.25496e-07, -8.33534e-08, 2.23517e-08, 1.01485e-10, -1.43572e-10, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="24"> 0, 1, 1.23685e-09, 2.38419e-07, -5.96046e-07, -2.32831e-09, -1.31362e-12, 1.19249e-11, 1, 1, 1, 1, 1.25, 1, 1.23685e-09, 2.38419e-07, -5.96046e-07, -2.32831e-09, -1.31362e-12, 1.19249e-11, 1, 1, 1, 1 </real_array>
-
- </resource>
- <resource type="Animation" path="local://14">
- <string name="resource/name"> "jump-up-cycle" </string>
- <real name="length"> 0.416667 </real>
- <bool name="loop"> True </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="120"> 0, 1, 6.55651e-07, -3.57628e-07, 5.66244e-07, 0.208387, -0.176945, -0.0164982, 0.961766, 1, 1, 1, 0.05, 1, 6.85453e-07, -2.38419e-07, 4.17233e-07, 0.211256, -0.175803, -0.0179009, 0.961324, 1, 1, 1, 0.1, 1, 6.55651e-07, -2.38419e-07, 3.27826e-07, 0.216682, -0.174684, -0.0207438, 0.960263, 1, 1, 1, 0.15, 1, 6.25849e-07, -3.57628e-07, 6.25849e-07, 0.219812, -0.176984, -0.0232576, 0.959072, 1, 1, 1, 0.25, 1, 1.3113e-06, -9.53674e-07, 9.23872e-07, 0.223631, -0.219998, -0.0262768, 0.949157, 1, 1, 1, 0.3, 1, 8.9407e-07, -4.76837e-07, 6.85453e-07, 0.220416, -0.21329, -0.0232336, 0.951517, 1, 1, 1, 0.35, 1, 8.34465e-07, -3.57628e-07, 6.25849e-07, 0.214429, -0.195082, -0.0193009, 0.956865, 1, 1, 1, 0.4, 1, 8.34465e-07, -3.57628e-07, 6.25849e-07, 0.209436, -0.180062, -0.0169379, 0.960951, 1, 1, 1, 0.45, 1, 6.55651e-07, -3.57628e-07, 5.66244e-07, 0.208387, -0.176945, -0.0164982, 0.961766, 1, 1, 1, 1.25, 1, 6.55651e-07, -3.57628e-07, 5.66244e-07, 0.208387, -0.176945, -0.0164982, 0.961766, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="108"> 0, 1, 5.06639e-07, -8.64267e-07, -8.9407e-07, -0.0797867, 0.0313898, -0.00372185, 0.996311, 1, 1, 1, 0.05, 1, -5.96046e-08, -4.76837e-07, -3.57628e-07, -0.0735466, 0.0175489, -0.00298843, 0.997133, 1, 1, 1, 0.2, 1, 2.98023e-07, -9.83477e-07, -5.36442e-07, -0.0401349, -0.0767179, 0.000985969, 0.996244, 1, 1, 1, 0.25, 1, -2.98023e-08, -6.25849e-07, -4.17233e-07, -0.0324823, -0.0976145, 0.00230383, 0.994691, 1, 1, 1, 0.3, 1, 2.08616e-07, -9.53674e-07, -6.55651e-07, -0.0445163, -0.0629722, 0.000635031, 0.997022, 1, 0.999999, 1, 0.35, 1, -1.49012e-07, -8.34465e-07, -4.17233e-07, -0.0633553, -0.0111982, -0.0018671, 0.997926, 1, 1, 1, 0.4, 1, 2.38419e-07, -8.64267e-07, -7.7486e-07, -0.0770585, 0.0244395, -0.00342743, 0.996721, 1, 1, 1, 0.45, 1, 5.06639e-07, -8.64267e-07, -8.9407e-07, -0.0797867, 0.0313898, -0.00372185, 0.996311, 1, 1, 1, 1.25, 1, 5.06639e-07, -8.64267e-07, -8.9407e-07, -0.0797867, 0.0313898, -0.00372185, 0.996311, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="132"> 0, 1, -1.19209e-07, -5.96046e-07, 5.36442e-07, -0.488489, -0.631801, -0.249807, 0.547542, 1, 1, 1, 0.05, 1, -1.49012e-07, -7.15256e-07, 5.96046e-07, -0.474017, -0.625071, -0.244485, 0.569931, 1, 1, 0.999999, 0.1, 1, -5.96046e-07, -3.57628e-07, 6.25849e-07, -0.454842, -0.607865, -0.232791, 0.607805, 1, 1, 0.999999, 0.15, 1, -6.25849e-07, -4.76837e-07, 6.85453e-07, -0.465321, -0.582319, -0.222366, 0.628437, 1, 1, 1, 0.2, 1, -3.8743e-07, -5.96046e-07, 6.25849e-07, -0.510621, -0.547625, -0.217789, 0.626052, 1, 1, 1, 0.25, 1, -5.96046e-07, -7.15256e-07, 2.98023e-07, -0.546434, -0.526096, -0.217482, 0.614275, 1, 1, 1, 0.3, 1, -3.57628e-07, -5.96046e-07, 6.85453e-07, -0.543207, -0.547611, -0.225218, 0.595252, 1, 1, 0.999999, 0.35, 1, -5.06639e-07, -5.96046e-07, 7.7486e-07, -0.516521, -0.594071, -0.238908, 0.568514, 1, 1, 1, 0.4, 1, -3.27826e-07, -5.96046e-07, 7.15256e-07, -0.493183, -0.625944, -0.248106, 0.550825, 1, 1, 1, 0.45, 1, -1.19209e-07, -5.96046e-07, 5.36442e-07, -0.488489, -0.631801, -0.249807, 0.547542, 1, 1, 1, 1.25, 1, -1.19209e-07, -5.96046e-07, 5.36442e-07, -0.488489, -0.631801, -0.249807, 0.547542, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="132"> 0, 1, -8.9407e-08, -5.96046e-07, -2.38419e-07, 0.170167, 0.120493, -0.091473, 0.973734, 1, 1, 1, 0.05, 1, -5.96046e-08, -5.36442e-07, -2.98023e-07, 0.191507, 0.15179, -0.0881411, 0.965669, 1, 1, 1, 0.1, 1, -2.98023e-08, -5.06639e-07, -1.19209e-07, 0.225056, 0.198248, -0.0838434, 0.950273, 1, 1, 1, 0.15, 1, -1.78814e-07, -6.85453e-07, -2.38419e-07, 0.242609, 0.209269, -0.0881917, 0.94317, 1, 1, 1, 0.2, 1, -3.27826e-07, -5.36442e-07, -1.19209e-07, 0.246276, 0.185328, -0.105902, 0.945403, 1, 1, 1, 0.25, 1, -4.76837e-07, -5.06639e-07, -7.7486e-07, 0.240434, 0.157542, -0.120519, 0.950183, 1, 1, 1, 0.3, 1, -8.9407e-08, -6.85453e-07, -2.98023e-07, 0.22081, 0.140399, -0.117544, 0.957974, 1, 0.999999, 1, 0.35, 1, -1.19209e-07, -7.7486e-07, -2.98023e-07, 0.191979, 0.127301, -0.104336, 0.967498, 1, 1, 1, 0.4, 1, -8.9407e-08, -6.55651e-07, -2.98023e-07, 0.173508, 0.121415, -0.0935976, 0.972827, 1, 1, 1, 0.45, 1, -8.9407e-08, -5.96046e-07, -2.38419e-07, 0.170167, 0.120493, -0.091473, 0.973734, 1, 1, 1, 1.25, 1, -8.9407e-08, -5.96046e-07, -2.38419e-07, 0.170167, 0.120493, -0.091473, 0.973734, 1, 1, 1 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="120"> 0, 1, 0, 1.63913e-07, 1.93715e-07, -0.731646, -0.0455606, -0.00930311, 0.680097, 1, 1, 1, 0.05, 1, -8.9407e-08, 5.96046e-08, -3.57628e-07, -0.699019, -0.0340935, -0.0129449, 0.714172, 1, 1, 1, 0.1, 1, -8.9407e-08, 1.41561e-07, -2.83122e-07, -0.643626, -0.015991, -0.0189581, 0.764938, 1, 1, 1, 0.15, 1, -8.9407e-08, 3.72529e-08, -5.06639e-07, -0.617849, -0.00879986, -0.0226563, 0.785921, 1, 1, 1, 0.2, 1, -5.96046e-08, 9.68575e-08, 7.45058e-08, -0.628974, -0.00984708, -0.0265256, 0.776912, 1, 1, 1, 0.25, 1, -5.96046e-08, 9.68575e-08, -4.47035e-07, -0.653197, -0.0153019, -0.02661, 0.756565, 1, 1, 1, 0.35, 1, -2.98023e-08, 2.98023e-08, 2.98023e-07, -0.712225, -0.0376632, -0.0133416, 0.700813, 1, 1, 1, 0.4, 1, -2.98023e-08, 1.04308e-07, 1.63913e-07, -0.728798, -0.0444052, -0.00986262, 0.683216, 1, 1, 1, 0.45, 1, 0, 1.63913e-07, 1.93715e-07, -0.731646, -0.0455606, -0.00930311, 0.680097, 1, 1, 1, 1.25, 1, 0, 1.63913e-07, 1.93715e-07, -0.731646, -0.0455606, -0.00930311, 0.680097, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="120"> 0, 1, -0.0436297, 0.0381679, -0.243318, 0.903835, 0.221183, 0.00392365, -0.366258, 1, 1, 1, 0.05, 1, -0.0436298, 0.0381678, -0.243318, 0.894017, 0.213358, 0.00409072, -0.393949, 1, 1, 1, 0.1, 1, -0.0436297, 0.0381675, -0.243318, 0.873591, 0.198684, 0.00402625, -0.444239, 1, 1, 1, 0.15, 1, -0.0436297, 0.0381679, -0.243318, 0.86099, 0.194348, 0.00472605, -0.470004, 1, 1, 1, 0.2, 1, -0.0436298, 0.038168, -0.243318, 0.866453, 0.209209, 0.00740134, -0.453251, 1, 1, 1, 0.25, 1, -0.0436297, 0.0381682, -0.243318, 0.877278, 0.223532, 0.00901692, -0.42466, 1, 1, 1, 0.35, 1, -0.0436297, 0.0381675, -0.243318, 0.89824, 0.222872, 0.00544398, -0.378765, 1, 1, 1, 0.4, 1, -0.0436297, 0.0381677, -0.243318, 0.90306, 0.22143, 0.0041485, -0.368015, 1, 1, 1, 0.45, 1, -0.0436297, 0.0381679, -0.243318, 0.903835, 0.221183, 0.00392365, -0.366258, 1, 1, 1, 1.25, 1, -0.0436297, 0.0381679, -0.243318, 0.903835, 0.221183, 0.00392365, -0.366258, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="108"> 0, 1, 7.45058e-08, 1.19209e-07, -3.72529e-09, -0.278586, 0.162913, 0.049835, 0.94518, 1, 1, 1, 0.05, 1, 5.21541e-08, -1.19209e-07, 4.47035e-08, -0.263884, 0.163221, 0.0462377, 0.949519, 1, 1, 1, 0.15, 1, 3.72529e-08, 0, 2.98023e-08, -0.191844, 0.164134, 0.02867, 0.967178, 1, 1, 1, 0.2, 1, 9.68575e-08, 0, -7.45058e-09, -0.173312, 0.164214, 0.0241673, 0.970779, 1, 1, 1, 0.25, 1, 8.9407e-08, -3.57628e-07, 2.6077e-08, -0.181008, 0.164188, 0.0260364, 0.96933, 1, 1, 1, 0.35, 1, 7.45058e-08, 3.57628e-07, 7.45058e-09, -0.253238, 0.163417, 0.0436354, 0.952503, 1, 1, 1, 0.4, 1, 8.19564e-08, 2.38419e-07, 2.6077e-08, -0.274832, 0.162996, 0.0489163, 0.946312, 1, 1, 1, 0.45, 1, 7.45058e-08, 1.19209e-07, -3.72529e-09, -0.278586, 0.162913, 0.049835, 0.94518, 1, 1, 1, 1.25, 1, 7.45058e-08, 1.19209e-07, -3.72529e-09, -0.278586, 0.162913, 0.049835, 0.94518, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="120"> 0, 1, 0, 2.08616e-07, 1.49012e-08, 0.318341, 0.0708015, -0.00441775, 0.945318, 1, 1, 1, 0.05, 1, 0, 1.93715e-07, 3.42727e-07, 0.307147, 0.068999, -0.0035256, 0.949151, 1, 1, 1, 0.1, 1, 2.98023e-08, 2.01166e-07, 4.47035e-08, 0.292292, 0.0665824, -0.00232838, 0.954006, 1, 1, 1, 0.15, 1, 5.96046e-08, 1.04308e-07, -1.93715e-07, 0.272221, 0.0650766, -0.00188312, 0.96003, 1, 1, 1, 0.2, 1, 2.98023e-08, 2.23517e-08, -1.78814e-07, 0.232486, 0.0650023, -0.00182597, 0.970424, 1, 1, 1, 0.25, 1, 5.96046e-08, -1.49012e-08, -1.04308e-07, 0.226129, 0.0676028, -0.00263455, 0.971745, 1, 1, 1, 0.35, 1, -2.98023e-08, 5.21541e-08, 1.63913e-07, 0.288667, 0.069411, -0.00418897, 0.954901, 1, 1, 1, 0.4, 1, -2.98023e-08, 1.41561e-07, 1.93715e-07, 0.312853, 0.0704368, -0.0043685, 0.947176, 1, 1, 1, 0.45, 1, 0, 2.08616e-07, 1.49012e-08, 0.318341, 0.0708015, -0.00441775, 0.945318, 1, 1, 1, 1.25, 1, 0, 2.08616e-07, 1.49012e-08, 0.318341, 0.0708015, -0.00441775, 0.945318, 1, 1, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="108"> 0, 1, 5.78584e-08, 5.96046e-08, 2.38419e-07, -0.0511448, -0.0112637, 0.00107338, 0.998627, 1, 1, 1, 0.05, 1, -2.94531e-08, -8.19564e-08, 1.78814e-07, -0.0669256, -0.012717, 0.000882011, 0.997677, 1, 1, 1, 0.1, 1, -3.07336e-08, -2.98023e-08, 3.57628e-07, -0.0875047, -0.0145704, 0.000627808, 0.996057, 1, 1, 1, 0.15, 1, 1.66474e-08, -8.9407e-08, 2.38419e-07, -0.12177, -0.0175352, 0.000386084, 0.992403, 1, 1, 1, 0.2, 1, 1.28057e-08, -1.49012e-08, 1.19209e-07, -0.196391, -0.0229446, -2.58925e-05, 0.980257, 1, 1, 1, 0.25, 1, -7.91624e-08, 8.9407e-08, 0, -0.21572, -0.0236374, -9.3472e-05, 0.976169, 1, 1, 1, 0.4, 1, 2.95695e-08, 6.70552e-08, 1.19209e-07, -0.060964, -0.012162, 0.00100229, 0.998065, 1, 1, 1, 0.45, 1, 5.78584e-08, 5.96046e-08, 2.38419e-07, -0.0511448, -0.0112637, 0.00107338, 0.998627, 1, 1, 1, 1.25, 1, 5.78584e-08, 5.96046e-08, 2.38419e-07, -0.0511448, -0.0112637, 0.00107338, 0.998627, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="108"> 0, 1, 5.21541e-08, 1.19209e-07, -1.9744e-07, -0.285587, 0.0658082, 0.0159816, 0.955957, 1, 1, 1, 0.05, 1, 7.45058e-09, 1.19209e-07, -1.08033e-07, -0.295281, 0.0650349, 0.017475, 0.953034, 1, 1, 1, 0.15, 1, -2.23517e-08, 1.19209e-07, 2.98023e-08, -0.341727, 0.0611981, 0.0246725, 0.93748, 1, 1, 1, 0.2, 1, 5.21541e-08, 1.19209e-07, -1.19209e-07, -0.353427, 0.0601963, 0.0264969, 0.933147, 1, 1, 1, 0.25, 1, -1.49012e-08, 2.38419e-07, -4.84288e-08, -0.348577, 0.0606133, 0.0257401, 0.934964, 1, 1, 1, 0.35, 1, -7.45058e-09, 1.19209e-07, -7.45058e-09, -0.302251, 0.0644732, 0.0185506, 0.950865, 1, 1, 1, 0.4, 1, 5.21541e-08, 1.19209e-07, -8.19564e-08, -0.28807, 0.065611, 0.0163638, 0.955219, 1, 1, 1, 0.45, 1, 5.21541e-08, 1.19209e-07, -1.9744e-07, -0.285587, 0.0658082, 0.0159816, 0.955957, 1, 1, 1, 1.25, 1, 5.21541e-08, 1.19209e-07, -1.9744e-07, -0.285587, 0.0658082, 0.0159816, 0.955957, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="24"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="108"> 0, 1, 1.37965e-08, 0.0913706, -0.0102687, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 1.37965e-08, 0.0913706, 0.0826712, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, 1.37965e-08, 0.0913706, 0.527418, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, 1.37965e-08, 0.0913706, 0.640416, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.25, 1, 1.37965e-08, 0.0913706, 0.59344, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, 1.37965e-08, 0.0913706, 0.149321, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.4, 1, 1.37965e-08, 0.0913706, 0.0135775, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, 1.37965e-08, 0.0913706, -0.0102687, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 1.37965e-08, 0.0913706, -0.0102687, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="108"> 0, 1, -0.142338, -0.579062, 1.09897, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.142338, -0.574357, 1.07628, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, -0.142338, -0.551601, 0.966619, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, -0.142338, -0.545802, 0.938678, 0, 0, 0, 1, 1, 1, 1, 0.25, 1, -0.142338, -0.54821, 0.950281, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, -0.142338, -0.570965, 1.05993, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, -0.142338, -0.577858, 1.09316, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.142338, -0.579062, 1.09897, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.142338, -0.579062, 1.09897, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="108"> 0, 1, 0.133965, 0.921787, 0.705414, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.133965, 0.88632, 0.724279, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, 0.133965, 0.833892, 0.752174, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, 0.133965, 0.821796, 0.758611, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, 0.133965, 0.834697, 0.751748, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, 0.133965, 0.908846, 0.712298, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, 0.133965, 0.919922, 0.706406, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, 0.133965, 0.921787, 0.705414, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.133965, 0.921787, 0.705414, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="24"> 0, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="24"> 0, 1, -0.0204011, -0.122407, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.0204011, -0.122407, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="120"> 0, 1, -0.868295, 0.267668, -0.820401, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.868295, 0.253357, -0.761204, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -0.868295, 0.216179, -0.653431, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, -0.868295, 0.157463, -0.585229, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, -0.868295, 0.102061, -0.562116, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, -0.868295, 0.10969, -0.583242, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, -0.868295, 0.226187, -0.758093, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -0.868295, 0.261497, -0.811129, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.868295, 0.267668, -0.820401, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.868295, 0.267668, -0.820401, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="108"> 0, 1, 2.08906, 2.18272, 3.23967, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 2.08906, 2.16545, 3.23967, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, 2.08906, 2.08198, 3.23967, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, 2.08906, 2.06071, 3.23967, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, 2.08906, 2.06954, 3.23967, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, 2.08906, 2.15301, 3.23967, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, 2.08906, 2.1783, 3.23967, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, 2.08906, 2.18272, 3.23967, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 2.08906, 2.18272, 3.23967, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="24"> 0, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="132"> 0, 1, -0.495073, -1.94554, 0.375148, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.529633, -1.94554, 0.375148, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -0.616933, -1.94554, 0.375148, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, -0.726325, -1.94554, 0.375148, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, -0.813485, -1.94554, 0.375148, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, -0.847955, -1.94554, 0.375148, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, -0.773744, -1.94554, 0.375148, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.35, 1, -0.620743, -1.94554, 0.375148, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -0.514687, -1.94554, 0.375148, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.495073, -1.94554, 0.375148, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.495073, -1.94554, 0.375148, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="132"> 0, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.05, 1, 0.050238, 0.727833, 0.0877454, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.1, 1, 0.050238, 0.772783, 0.0577767, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.15, 1, 0.050238, 0.78451, 0.0674334, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.2, 1, 0.050238, 0.778496, 0.13139, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.25, 1, 0.050238, 0.766398, 0.174636, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.3, 1, 0.050238, 0.744412, 0.160603, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.35, 1, 0.050238, 0.716858, 0.131686, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.4, 1, 0.050238, 0.700317, 0.111698, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.45, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 1.25, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="24"> 0, 1, 7.45059e-09, -5.21541e-08, 2.38419e-07, 0.126301, -0.0110499, -0.0864524, 0.988156, 1, 1, 1, 1.25, 1, 7.45059e-09, -5.21541e-08, 2.38419e-07, 0.126301, -0.0110499, -0.0864524, 0.988156, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="24"> 0, 1, -2.26918e-09, 5.21541e-08, -1.78814e-07, 0.0237758, -0.0135633, -0.0860939, 0.995911, 1, 1, 1, 1.25, 1, -2.26918e-09, 5.21541e-08, -1.78814e-07, 0.0237758, -0.0135633, -0.0860939, 0.995911, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="24"> 0, 1, -1.11758e-08, -2.23517e-07, -1.43051e-06, -7.45058e-09, -4.4605e-10, 4.26538e-09, 1, 1, 1, 1, 1.25, 1, -1.11758e-08, -2.23517e-07, -1.43051e-06, -7.45058e-09, -4.4605e-10, 4.26538e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="108"> 0, 1, 1.02445e-08, -4.47035e-07, -1.05007e-07, 0.287287, -0.0941088, 0.0255168, 0.952869, 1, 1, 1, 0.05, 1, -2.68222e-08, -2.98023e-08, -7.10133e-08, 0.277009, -0.0944548, 0.024506, 0.9559, 1, 1, 1, 0.15, 1, -2.42144e-08, -3.57628e-07, -3.39933e-08, 0.229614, -0.0956923, 0.0198279, 0.968363, 1, 1, 1, 0.2, 1, -1.22934e-08, -1.78814e-07, 1.30385e-08, 0.224057, -0.0957887, 0.0192787, 0.969665, 1, 1, 1, 0.25, 1, -3.91156e-08, 1.19209e-07, -4.79631e-08, 0.233664, -0.0955615, 0.0202274, 0.967399, 1, 1, 1, 0.35, 1, -3.35279e-09, -3.27826e-07, -4.61005e-08, 0.274341, -0.0944949, 0.024241, 0.956671, 1, 1, 1, 0.4, 1, -1.67641e-09, -2.68221e-07, -8.21892e-08, 0.285395, -0.0941665, 0.0253304, 0.953436, 1, 1, 1, 0.45, 1, 1.02445e-08, -4.47035e-07, -1.05007e-07, 0.287287, -0.0941088, 0.0255168, 0.952869, 1, 1, 1, 1.25, 1, 1.02445e-08, -4.47035e-07, -1.05007e-07, 0.287287, -0.0941088, 0.0255168, 0.952869, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="24"> 0, 1, -7.74519e-09, -9.56934e-08, 3.16533e-07, 7.45058e-09, 3.37575e-10, -1.99442e-09, 1, 1, 1, 1, 1.25, 1, -7.74519e-09, -9.56934e-08, 3.16533e-07, 7.45058e-09, 3.37575e-10, -1.99442e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="24"> 0, 1, 3.38022e-08, 0.00292349, 0.20433, 6.98492e-10, 2.45226e-11, 6.71222e-11, 1, 1, 1, 1, 1.25, 1, 3.38022e-08, 0.00292349, 0.20433, 6.98492e-10, 2.45226e-11, 6.71222e-11, 1, 1, 1, 1 </real_array>
-
- </resource>
- <main_resource>
- <dictionary name="_bundled" shared="false">
- <string> "names" </string>
- <string_array len="248">
- <string> "player" </string>
- <string> "RigidBody" </string>
- <string> "shape_count" </string>
- <string> "shapes/0/shape" </string>
- <string> "shapes/0/transform" </string>
- <string> "shapes/0/trigger" </string>
- <string> "shapes/1/shape" </string>
- <string> "shapes/1/transform" </string>
- <string> "shapes/1/trigger" </string>
- <string> "mode" </string>
- <string> "mass" </string>
- <string> "friction" </string>
- <string> "bounce" </string>
- <string> "custom_integrator" </string>
- <string> "continuous_cd" </string>
- <string> "contacts_reported" </string>
- <string> "contact_monitor" </string>
- <string> "active" </string>
- <string> "can_sleep" </string>
- <string> "velocity/linear" </string>
- <string> "velocity/angular" </string>
- <string> "script/script" </string>
- <string> "__meta__" </string>
- <string> "collision_capsule" </string>
- <string> "CollisionShape" </string>
- <string> "transform/local" </string>
- <string> "shape" </string>
- <string> "trigger" </string>
- <string> "collision_ray" </string>
- <string> "target" </string>
- <string> "Spatial" </string>
- <string> "camera" </string>
- <string> "Camera" </string>
- <string> "projection" </string>
- <string> "fov" </string>
- <string> "near" </string>
- <string> "far" </string>
- <string> "vaspect" </string>
- <string> "current" </string>
- <string> "visible_layers" </string>
- <string> "environment" </string>
- <string> "min_distance" </string>
- <string> "max_distance" </string>
- <string> "angle_v_adjust" </string>
- <string> "autoturn_ray_aperture" </string>
- <string> "autoturn_speed" </string>
- <string> "Armature" </string>
- <string> "Skeleton" </string>
- <string> "bones/0/name" </string>
- <string> "bones/0/parent" </string>
- <string> "bones/0/rest" </string>
- <string> "bones/0/enabled" </string>
- <string> "bones/0/bound_childs" </string>
- <string> "bones/1/name" </string>
- <string> "bones/1/parent" </string>
- <string> "bones/1/rest" </string>
- <string> "bones/1/enabled" </string>
- <string> "bones/1/bound_childs" </string>
- <string> "bones/2/name" </string>
- <string> "bones/2/parent" </string>
- <string> "bones/2/rest" </string>
- <string> "bones/2/enabled" </string>
- <string> "bones/2/bound_childs" </string>
- <string> "bones/3/name" </string>
- <string> "bones/3/parent" </string>
- <string> "bones/3/rest" </string>
- <string> "bones/3/enabled" </string>
- <string> "bones/3/bound_childs" </string>
- <string> "bones/4/name" </string>
- <string> "bones/4/parent" </string>
- <string> "bones/4/rest" </string>
- <string> "bones/4/enabled" </string>
- <string> "bones/4/bound_childs" </string>
- <string> "bones/5/name" </string>
- <string> "bones/5/parent" </string>
- <string> "bones/5/rest" </string>
- <string> "bones/5/enabled" </string>
- <string> "bones/5/bound_childs" </string>
- <string> "bones/6/name" </string>
- <string> "bones/6/parent" </string>
- <string> "bones/6/rest" </string>
- <string> "bones/6/enabled" </string>
- <string> "bones/6/bound_childs" </string>
- <string> "bones/7/name" </string>
- <string> "bones/7/parent" </string>
- <string> "bones/7/rest" </string>
- <string> "bones/7/enabled" </string>
- <string> "bones/7/bound_childs" </string>
- <string> "bones/8/name" </string>
- <string> "bones/8/parent" </string>
- <string> "bones/8/rest" </string>
- <string> "bones/8/enabled" </string>
- <string> "bones/8/bound_childs" </string>
- <string> "bones/9/name" </string>
- <string> "bones/9/parent" </string>
- <string> "bones/9/rest" </string>
- <string> "bones/9/enabled" </string>
- <string> "bones/9/bound_childs" </string>
- <string> "bones/10/name" </string>
- <string> "bones/10/parent" </string>
- <string> "bones/10/rest" </string>
- <string> "bones/10/enabled" </string>
- <string> "bones/10/bound_childs" </string>
- <string> "bones/11/name" </string>
- <string> "bones/11/parent" </string>
- <string> "bones/11/rest" </string>
- <string> "bones/11/enabled" </string>
- <string> "bones/11/bound_childs" </string>
- <string> "bones/12/name" </string>
- <string> "bones/12/parent" </string>
- <string> "bones/12/rest" </string>
- <string> "bones/12/enabled" </string>
- <string> "bones/12/bound_childs" </string>
- <string> "bones/13/name" </string>
- <string> "bones/13/parent" </string>
- <string> "bones/13/rest" </string>
- <string> "bones/13/enabled" </string>
- <string> "bones/13/bound_childs" </string>
- <string> "bones/14/name" </string>
- <string> "bones/14/parent" </string>
- <string> "bones/14/rest" </string>
- <string> "bones/14/enabled" </string>
- <string> "bones/14/bound_childs" </string>
- <string> "bones/15/name" </string>
- <string> "bones/15/parent" </string>
- <string> "bones/15/rest" </string>
- <string> "bones/15/enabled" </string>
- <string> "bones/15/bound_childs" </string>
- <string> "bones/16/name" </string>
- <string> "bones/16/parent" </string>
- <string> "bones/16/rest" </string>
- <string> "bones/16/enabled" </string>
- <string> "bones/16/bound_childs" </string>
- <string> "bones/17/name" </string>
- <string> "bones/17/parent" </string>
- <string> "bones/17/rest" </string>
- <string> "bones/17/enabled" </string>
- <string> "bones/17/bound_childs" </string>
- <string> "bones/18/name" </string>
- <string> "bones/18/parent" </string>
- <string> "bones/18/rest" </string>
- <string> "bones/18/enabled" </string>
- <string> "bones/18/bound_childs" </string>
- <string> "bones/19/name" </string>
- <string> "bones/19/parent" </string>
- <string> "bones/19/rest" </string>
- <string> "bones/19/enabled" </string>
- <string> "bones/19/bound_childs" </string>
- <string> "bones/20/name" </string>
- <string> "bones/20/parent" </string>
- <string> "bones/20/rest" </string>
- <string> "bones/20/enabled" </string>
- <string> "bones/20/bound_childs" </string>
- <string> "bones/21/name" </string>
- <string> "bones/21/parent" </string>
- <string> "bones/21/rest" </string>
- <string> "bones/21/enabled" </string>
- <string> "bones/21/bound_childs" </string>
- <string> "bones/22/name" </string>
- <string> "bones/22/parent" </string>
- <string> "bones/22/rest" </string>
- <string> "bones/22/enabled" </string>
- <string> "bones/22/bound_childs" </string>
- <string> "bones/23/name" </string>
- <string> "bones/23/parent" </string>
- <string> "bones/23/rest" </string>
- <string> "bones/23/enabled" </string>
- <string> "bones/23/bound_childs" </string>
- <string> "bones/24/name" </string>
- <string> "bones/24/parent" </string>
- <string> "bones/24/rest" </string>
- <string> "bones/24/enabled" </string>
- <string> "bones/24/bound_childs" </string>
- <string> "bones/25/name" </string>
- <string> "bones/25/parent" </string>
- <string> "bones/25/rest" </string>
- <string> "bones/25/enabled" </string>
- <string> "bones/25/bound_childs" </string>
- <string> "bones/26/name" </string>
- <string> "bones/26/parent" </string>
- <string> "bones/26/rest" </string>
- <string> "bones/26/enabled" </string>
- <string> "bones/26/bound_childs" </string>
- <string> "robot" </string>
- <string> "MeshInstance" </string>
- <string> "layers" </string>
- <string> "geometry/visible" </string>
- <string> "geometry/material_override" </string>
- <string> "geometry/cast_shadow" </string>
- <string> "geometry/receive_shadows" </string>
- <string> "geometry/range_begin" </string>
- <string> "geometry/range_end" </string>
- <string> "geometry/billboard" </string>
- <string> "geometry/billboard_y" </string>
- <string> "geometry/depth_scale" </string>
- <string> "geometry/visible_in_all_rooms" </string>
- <string> "mesh/mesh" </string>
- <string> "bullet" </string>
- <string> "Position3D" </string>
- <string> "sfx" </string>
- <string> "SpatialSamplePlayer" </string>
- <string> "params/volume_db" </string>
- <string> "params/pitch_scale" </string>
- <string> "params/attenuation/min_distance" </string>
- <string> "params/attenuation/max_distance" </string>
- <string> "params/attenuation/distance_exp" </string>
- <string> "params/emission_cone/degrees" </string>
- <string> "params/emission_cone/attenuation_db" </string>
- <string> "config/polyphony" </string>
- <string> "config/samples" </string>
- <string> "AnimationPlayer" </string>
- <string> "playback/process_mode" </string>
- <string> "playback/default_blend_time" </string>
- <string> "root/root" </string>
- <string> "anims/idle" </string>
- <string> "anims/shooting" </string>
- <string> "anims/falling-cycle" </string>
- <string> "anims/default" </string>
- <string> "anims/run-cycle" </string>
- <string> "anims/walk-cycle" </string>
- <string> "anims/shooting_standing" </string>
- <string> "anims/jump-up-cycle" </string>
- <string> "playback/active" </string>
- <string> "playback/speed" </string>
- <string> "blend_times" </string>
- <string> "autoplay" </string>
- <string> "AnimationTreePlayer" </string>
- <string> "base_path" </string>
- <string> "master_player" </string>
- <string> "data" </string>
- <string> "fwd" </string>
- <string> "TouchScreenButton" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/behind_parent" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
- <string> "normal" </string>
- <string> "pressed" </string>
- <string> "bitmask" </string>
- <string> "passby_press" </string>
- <string> "action" </string>
- <string> "visibility_mode" </string>
- <string> "bwd" </string>
- <string> "left" </string>
- <string> "right" </string>
- </string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
- <string> "node_count" </string>
- <int> 16 </int>
- <string> "variants" </string>
- <array len="121" shared="false">
- <int> 2 </int>
- <resource resource_type="Shape" path="local://1"> </resource>
- <transform> 1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0.954765, 0 </transform>
- <bool> False </bool>
- <resource resource_type="Shape" path="local://2"> </resource>
- <transform> 1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 1.01236, 0 </transform>
- <real> 1 </real>
- <real> 0 </real>
- <bool> True </bool>
- <int> 3 </int>
- <vector3> 0, 0, 0 </vector3>
- <resource resource_type="Script" path="res://player.gd"> </resource>
- <dictionary shared="false">
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 1 </int>
- <string> "sources" </string>
- <array len="2" shared="false">
- <string> "res://follow_camera.gd" </string>
- <string> "res://player.gd" </string>
- </array>
- </dictionary>
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "pixel_snap" </string>
- <bool> False </bool>
- <string> "zoom" </string>
- <real> 1 </real>
- <string> "ofs" </string>
- <vector2> -241, -19 </vector2>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "fov" </string>
- <real> 400 </real>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 2.161076 </real>
- <string> "x_rot" </string>
- <real> 0.520797 </real>
- <string> "y_rot" </string>
- <real> 26.741669 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> -0.415811, 0.486899, 0.089334 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- </array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "znear" </string>
- <real> 0.1 </real>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "3D" </string>
- </dictionary>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.95244, 0 </transform>
- <transform> 1, 0, 0, 0, 0.871263, 0.490817, 0, -0.490817, 0.871263, 0, 2.59805, 1.25672 </transform>
- <int> 0 </int>
- <real> 70 </real>
- <real> 0.1 </real>
- <real> 100 </real>
- <int> -1 </int>
- <resource name=""></resource> <resource resource_type="Script" path="res://follow_camera.gd"> </resource>
- <real> 3 </real>
- <int> 25 </int>
- <int> 50 </int>
- <transform> 0.3, 0, 0, 0, 0.3, 0, 0, 0, 0.3, 0, 0, 0 </transform>
- <string> "MASTER" </string>
- <transform> 1, 0, -0, 0, 7.54979e-08, 1, -0, -1, 7.54979e-08, 0, -0.011277, -0 </transform>
- <array len="0" shared="false">
- </array>
- <string> "hip" </string>
- <transform> 1, -1.50996e-07, -3.60002e-14, -1.50996e-07, -1, -3.01992e-07, 9.59926e-15, 3.01992e-07, -1, -3.38813e-21, 2.58363e-07, 2.10612 </transform>
- <string> "waist" </string>
- <int> 1 </int>
- <transform> 1, 1.50996e-07, 1.80001e-14, -1.50996e-07, 1, 0, -1.80001e-14, 0, 1, 3.38813e-21, 2.84217e-14, -0.384614 </transform>
- <string> "chest" </string>
- <transform> 1, -7.31455e-16, 4.86029e-17, 7.28861e-16, 0.999166, 0.040823, -7.84198e-17, -0.040823, 0.999166, 0, 4.84022e-11, -0.8217 </transform>
- <string> "neck" </string>
- <transform> -1, -1.10548e-06, -9.37766e-09, 1.08766e-06, -0.985328, 0.170671, -1.97913e-07, 0.170671, 0.985328, -1.64727e-13, 5.96046e-08, -1.24906 </transform>
- <string> "headtracker" </string>
- <int> 4 </int>
- <transform> 1, 9.87793e-08, -1.09789e-06, 1.09743e-06, 0.00449866, 0.99999, 1.03717e-07, -0.99999, 0.00449866, 0, 5.96046e-08, -0.491774 </transform>
- <string> "head" </string>
- <int> 5 </int>
- <transform> -1, 2.36978e-07, 1.97097e-07, -2.5035e-07, -0.25144, -0.967873, -1.79807e-07, -0.967873, 0.25144, -2.94648e-10, 4.76837e-07, 0.00400549 </transform>
- <string> "vent" </string>
- <int> 6 </int>
- <transform> 1, -2.54965e-07, -1.4699e-08, 2.55005e-07, 0.999996, 0.00282324, 1.39791e-08, -0.00282325, 0.999996, -7.04808e-08, 0.270992, -1.2429 </transform>
- <string> "r-arm" </string>
- <transform> 0.11477, -0.699489, -0.705367, -0.802661, -0.483653, 0.349021, -0.585289, 0.526113, -0.616961, 0.940786, 0.107144, -0.773564 </transform>
- <string> "r-forearm" </string>
- <int> 8 </int>
- <transform> -0.859542, 0.0564943, 0.507934, 0.107631, -0.951571, 0.287973, 0.499604, 0.302194, 0.811834, 2.38419e-07, -4.76837e-07, -0.935513 </transform>
- <string> "l-arm" </string>
- <transform> 0.11477, 0.699489, 0.705367, 0.802661, -0.483653, 0.349021, 0.585289, 0.526113, -0.616961, -0.940786, 0.107144, -0.773564 </transform>
- <string> "l-forearm" </string>
- <int> 10 </int>
- <transform> -0.859542, -0.0564943, -0.507934, -0.107631, -0.951571, 0.287973, -0.499604, 0.302194, 0.811834, -2.38419e-07, -4.76837e-07, -0.935513 </transform>
- <string> "r-thigh" </string>
- <transform> 0.994883, -0.0545632, -0.085028, -0.0580629, -0.997541, -0.0392442, -0.0826777, 0.0439804, -0.995605, 0.349652, 0.0628238, -0.163877 </transform>
- <string> "r-leg" </string>
- <int> 12 </int>
- <transform> -0.999508, -0.031366, -0.000870243, 0.0312939, -0.994411, -0.100835, 0.00229738, -0.100812, 0.994903, 5.96046e-08, 5.96046e-08, -0.644636 </transform>
- <string> "r-foot" </string>
- <int> 13 </int>
- <transform> 0.996208, -0.0766666, -0.0411273, -0.0442384, -0.0393329, -0.998246, 0.0749145, 0.996281, -0.0425754, -5.96046e-08, 4.19095e-09, -1.43073 </transform>
- <string> "l-thigh" </string>
- <transform> 0.994883, 0.0545632, 0.085028, 0.0580633, -0.997541, -0.0392452, 0.0826776, 0.0439813, -0.995606, -0.349652, 0.0628238, -0.163877 </transform>
- <string> "l-leg" </string>
- <int> 15 </int>
- <transform> -0.999508, 0.0313662, 0.000870456, -0.0312941, -0.994411, -0.100836, -0.00229725, -0.100814, 0.994903, 0, 1.49012e-08, -0.644636 </transform>
- <string> "l-foot" </string>
- <int> 16 </int>
- <transform> 0.996208, 0.0766668, 0.0411275, 0.0442386, -0.0393327, -0.998246, -0.0749147, 0.996281, -0.0425752, 0, -8.3819e-09, -1.43073 </transform>
- <string> "HEAD" </string>
- <transform> 1, -1.50996e-07, -0, -1.50996e-07, -1, 0, 0, 0, -1, 5.68434e-14, -5.79659, 6.35228 </transform>
- <string> "r-LEGCONTROL" </string>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.518863, 3.72276e-07, 0.204768 </transform>
- <string> "l-LEGCONTROL" </string>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, -0.518863, 3.72276e-07, 0.204768 </transform>
- <string> "r-LEGORIENT" </string>
- <transform> -1, -1.50996e-07, -5.03577e-15, -3.75647e-14, 2.15429e-07, 1, -1.50996e-07, 1, -2.15429e-07, 0.411677, -0.66395, 1.62881 </transform>
- <string> "l-LEGORIENT" </string>
- <transform> -1, -1.50996e-07, -5.03577e-15, -3.75647e-14, 2.15429e-07, 1, -1.50996e-07, 1, -2.15429e-07, -0.411677, -0.66395, 1.62881 </transform>
- <string> "r-ARMCONTROL" </string>
- <transform> 1, 0, 0, 0, 7.54979e-08, -1, 0, 1, 7.54979e-08, 2.62535, -0.186879, 2.59016 </transform>
- <string> "l-ARMCONTROL" </string>
- <transform> 1, 0, 0, 0, 7.54979e-08, -1, 0, 1, 7.54979e-08, -2.62535, -0.186879, 2.59016 </transform>
- <string> "r-ARMORIENT" </string>
- <transform> 1, 0, 0, 0, 7.54979e-08, -1, 0, 1, 7.54979e-08, 1.57185, 0.510255, 3.44768 </transform>
- <string> "l-ARMORIENT" </string>
- <transform> 1, 0, 0, 0, 7.54979e-08, -1, 0, 1, 7.54979e-08, -1.57185, 0.510255, 3.44768 </transform>
- <resource resource_type="Mesh" path="local://5"> </resource>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, -1.94071, 3.64079, 3.3802 </transform>
- <real> 180 </real>
- <real> -6 </real>
- <resource resource_type="SampleLibrary" path="local://6"> </resource>
- <node_path> ".." </node_path>
- <resource resource_type="Animation" path="local://7"> </resource>
- <resource resource_type="Animation" path="local://8"> </resource>
- <resource resource_type="Animation" path="local://9"> </resource>
- <resource resource_type="Animation" path="local://10"> </resource>
- <resource resource_type="Animation" path="local://11"> </resource>
- <resource resource_type="Animation" path="local://12"> </resource>
- <resource resource_type="Animation" path="local://13"> </resource>
- <resource resource_type="Animation" path="local://14"> </resource>
- <string> "" </string>
- <node_path> "../AnimationPlayer" </node_path>
- <dictionary shared="false">
- <string> "connections" </string>
- <array len="27" shared="false">
- <string> "walk" </string>
- <string> "scale" </string>
- <int> 0 </int>
- <string> "scale" </string>
- <string> "state" </string>
- <int> 0 </int>
- <string> "anim 3" </string>
- <string> "state" </string>
- <int> 1 </int>
- <string> "anim 4" </string>
- <string> "state" </string>
- <int> 2 </int>
- <string> "gun" </string>
- <string> "out" </string>
- <int> 0 </int>
- <string> "state" </string>
- <string> "gun" </string>
- <int> 0 </int>
- <string> "anim 5" </string>
- <string> "gun" </string>
- <int> 1 </int>
- <string> "anim" </string>
- <string> "walk" </string>
- <int> 0 </int>
- <string> "anim 2" </string>
- <string> "walk" </string>
- <int> 1 </int>
- </array>
- <string> "master" </string>
- <node_path> "../AnimationPlayer" </node_path>
- <string> "active" </string>
- <bool> True </bool>
- <string> "nodes" </string>
- <array len="10" shared="false">
- <dictionary shared="false">
- <string> "id" </string>
- <string> "scale" </string>
- <string> "scale" </string>
- <real> 1.2 </real>
- <string> "pos" </string>
- <vector2> 247, 68 </vector2>
- <string> "type" </string>
- <string> "timescale" </string>
- </dictionary>
- <dictionary shared="false">
- <string> "id" </string>
- <string> "state" </string>
- <string> "transitions" </string>
- <array len="3" shared="false">
- <dictionary shared="false">
- <string> "auto_advance" </string>
- <bool> False </bool>
- </dictionary>
- <dictionary shared="false">
- <string> "auto_advance" </string>
- <bool> False </bool>
- </dictionary>
- <dictionary shared="false">
- <string> "auto_advance" </string>
- <bool> False </bool>
- </dictionary>
- </array>
- <string> "xfade" </string>
- <real> 0.1 </real>
- <string> "type" </string>
- <string> "transition" </string>
- <string> "pos" </string>
- <vector2> 359, 132 </vector2>
- </dictionary>
- <dictionary shared="false">
- <string> "from" </string>
- <string> "idle" </string>
- <string> "id" </string>
- <string> "anim" </string>
- <string> "pos" </string>
- <vector2> 7, 70 </vector2>
- <string> "type" </string>
- <string> "animation" </string>
- </dictionary>
- <dictionary shared="false">
- <string> "id" </string>
- <string> "out" </string>
- <string> "type" </string>
- <string> "output" </string>
- <string> "pos" </string>
- <vector2> 579, 114 </vector2>
- </dictionary>
- <dictionary shared="false">
- <string> "from" </string>
- <string> "shooting_standing" </string>
- <string> "id" </string>
- <string> "anim 5" </string>
- <string> "pos" </string>
- <vector2> 331, 242 </vector2>
- <string> "type" </string>
- <string> "animation" </string>
- </dictionary>
- <dictionary shared="false">
- <string> "from" </string>
- <string> "jump-up-cycle" </string>
- <string> "id" </string>
- <string> "anim 3" </string>
- <string> "pos" </string>
- <vector2> 143, 144 </vector2>
- <string> "type" </string>
- <string> "animation" </string>
- </dictionary>
- <dictionary shared="false">
- <string> "from" </string>
- <string> "walk-cycle" </string>
- <string> "id" </string>
- <string> "anim 2" </string>
- <string> "pos" </string>
- <vector2> 7, 152 </vector2>
- <string> "type" </string>
- <string> "animation" </string>
- </dictionary>
- <dictionary shared="false">
- <string> "id" </string>
- <string> "gun" </string>
- <string> "blend" </string>
- <real> 1 </real>
- <string> "filter" </string>
- <array len="22" shared="false">
- <node_path> "Armature/Skeleton:MASTER" </node_path>
- <node_path> "Armature/Skeleton:l-thigh" </node_path>
- <node_path> "Armature/Skeleton:headtracker" </node_path>
- <node_path> "Armature/Skeleton:r-foot" </node_path>
- <node_path> "Armature/Skeleton:r-leg" </node_path>
- <node_path> "Armature/Skeleton:waist" </node_path>
- <node_path> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <node_path> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <node_path> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <node_path> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <node_path> "Armature/Skeleton:hip" </node_path>
- <node_path> "Armature/Skeleton:l-foot" </node_path>
- <node_path> "Armature/Skeleton:l-leg" </node_path>
- <node_path> "Armature/Skeleton:neck" </node_path>
- <node_path> "Armature" </node_path>
- <node_path> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <node_path> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <node_path> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <node_path> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <node_path> "Armature/Skeleton:HEAD" </node_path>
- <node_path> "Armature/Skeleton:head" </node_path>
- <node_path> "Armature/Skeleton:r-thigh" </node_path>
- </array>
- <string> "type" </string>
- <string> "blend2" </string>
- <string> "pos" </string>
- <vector2> 469, 127 </vector2>
- </dictionary>
- <dictionary shared="false">
- <string> "from" </string>
- <string> "falling-cycle" </string>
- <string> "id" </string>
- <string> "anim 4" </string>
- <string> "pos" </string>
- <vector2> 141, 230 </vector2>
- <string> "type" </string>
- <string> "animation" </string>
- </dictionary>
- <dictionary shared="false">
- <string> "id" </string>
- <string> "walk" </string>
- <string> "blend" </string>
- <real> 1 </real>
- <string> "filter" </string>
- <array len="0" shared="false">
- </array>
- <string> "type" </string>
- <string> "blend2" </string>
- <string> "pos" </string>
- <vector2> 148, 46 </vector2>
- </dictionary>
- </array>
- </dictionary>
- <vector2> 72, 301 </vector2>
- <vector2> 1, 1 </vector2>
- <resource resource_type="Texture" path="res://osb_up.png"> </resource>
- <string> "move_forward" </string>
- <vector2> 72, 365 </vector2>
- <resource resource_type="Texture" path="res://osb_down.png"> </resource>
- <string> "move_backwards" </string>
- <vector2> 29, 332 </vector2>
- <resource resource_type="Texture" path="res://osb_left.png"> </resource>
- <string> "move_left" </string>
- <vector2> 108, 327 </vector2>
- <resource resource_type="Texture" path="res://osb_right.png"> </resource>
- <string> "move_right" </string>
- </array>
- <string> "nodes" </string>
- <int_array len="654"> -1, -1, 1, 0, -1, 21, 2, 0, 3, 1, 4, 2, 5, 3, 6, 4, 7, 5, 8, 3, 9, 0, 10, 6, 11, 7, 12, 7, 13, 8, 14, 3, 15, 9, 16, 8, 17, 8, 18, 8, 19, 10, 20, 10, 21, 11, 22, 12, 0, 0, 0, 24, 23, -1, 3, 25, 2, 26, 1, 27, 3, 0, 0, 0, 24, 28, -1, 3, 25, 5, 26, 4, 27, 3, 0, 0, 0, 30, 29, -1, 1, 25, 13, 0, 3, 0, 32, 31, -1, 15, 25, 14, 33, 15, 34, 16, 35, 17, 36, 18, 37, 3, 38, 3, 39, 19, 40, 20, 21, 21, 41, 6, 42, 22, 43, 7, 44, 23, 45, 24, 0, 0, 0, 30, 46, -1, 1, 25, 25, 0, 5, 0, 47, 47, -1, 135, 48, 26, 49, 19, 50, 27, 51, 8, 52, 28, 53, 29, 54, 15, 55, 30, 56, 8, 57, 28, 58, 31, 59, 32, 60, 33, 61, 8, 62, 28, 63, 34, 64, 0, 65, 35, 66, 8, 67, 28, 68, 36, 69, 9, 70, 37, 71, 8, 72, 28, 73, 38, 74, 39, 75, 40, 76, 8, 77, 28, 78, 41, 79, 42, 80, 43, 81, 8, 82, 28, 83, 44, 84, 45, 85, 46, 86, 8, 87, 28, 88, 47, 89, 9, 90, 48, 91, 8, 92, 28, 93, 49, 94, 50, 95, 51, 96, 8, 97, 28, 98, 52, 99, 9, 100, 53, 101, 8, 102, 28, 103, 54, 104, 55, 105, 56, 106, 8, 107, 28, 108, 57, 109, 32, 110, 58, 111, 8, 112, 28, 113, 59, 114, 60, 115, 61, 116, 8, 117, 28, 118, 62, 119, 63, 120, 64, 121, 8, 122, 28, 123, 65, 124, 32, 125, 66, 126, 8, 127, 28, 128, 67, 129, 68, 130, 69, 131, 8, 132, 28, 133, 70, 134, 71, 135, 72, 136, 8, 137, 28, 138, 73, 139, 15, 140, 74, 141, 8, 142, 28, 143, 75, 144, 15, 145, 76, 146, 8, 147, 28, 148, 77, 149, 15, 150, 78, 151, 8, 152, 28, 153, 79, 154, 15, 155, 80, 156, 8, 157, 28, 158, 81, 159, 15, 160, 82, 161, 8, 162, 28, 163, 83, 164, 15, 165, 84, 166, 8, 167, 28, 168, 85, 169, 15, 170, 86, 171, 8, 172, 28, 173, 87, 174, 15, 175, 88, 176, 8, 177, 28, 178, 89, 179, 15, 180, 90, 181, 8, 182, 28, 0, 6, 0, 184, 183, -1, 12, 185, 32, 186, 8, 187, 20, 188, 8, 189, 8, 190, 7, 191, 7, 192, 3, 193, 3, 194, 3, 195, 3, 196, 91, 0, 5, 0, 198, 197, -1, 1, 25, 92, 0, 0, 0, 200, 199, -1, 9, 201, 7, 202, 6, 203, 6, 204, 18, 205, 6, 206, 93, 207, 94, 208, 32, 209, 95, 0, 0, 0, 210, 210, -1, 15, 211, 32, 212, 7, 213, 96, 214, 97, 215, 98, 216, 99, 217, 100, 218, 101, 219, 102, 220, 103, 221, 104, 222, 8, 223, 6, 224, 28, 225, 105, 0, 0, 0, 226, 226, -1, 3, 227, 96, 228, 106, 229, 107, 0, 0, 0, 231, 230, -1, 13, 232, 8, 233, 6, 234, 6, 235, 3, 236, 108, 237, 7, 238, 109, 239, 110, 240, 20, 241, 20, 242, 8, 243, 111, 244, 32, 0, 0, 0, 231, 245, -1, 13, 232, 8, 233, 6, 234, 6, 235, 3, 236, 112, 237, 7, 238, 109, 239, 113, 240, 20, 241, 20, 242, 8, 243, 114, 244, 32, 0, 0, 0, 231, 246, -1, 13, 232, 8, 233, 6, 234, 6, 235, 3, 236, 115, 237, 7, 238, 109, 239, 116, 240, 20, 241, 20, 242, 8, 243, 117, 244, 32, 0, 0, 0, 231, 247, -1, 13, 232, 8, 233, 6, 234, 6, 235, 3, 236, 118, 237, 7, 238, 109, 239, 119, 240, 20, 241, 20, 242, 8, 243, 120, 244, 32, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
- </dictionary>
-
- </main_resource>
-</resource_file> \ No newline at end of file
diff --git a/demos/3d/platformer/robotrigged.scn b/demos/3d/platformer/robotrigged.scn
index e54125a07e..68af0cfe47 100644
--- a/demos/3d/platformer/robotrigged.scn
+++ b/demos/3d/platformer/robotrigged.scn
Binary files differ
diff --git a/demos/3d/platformer/stage.scn b/demos/3d/platformer/stage.scn
new file mode 100644
index 0000000000..7eafda5888
--- /dev/null
+++ b/demos/3d/platformer/stage.scn
Binary files differ
diff --git a/demos/3d/platformer/stage.xml b/demos/3d/platformer/stage.xml
deleted file mode 100644
index 37a11068c9..0000000000
--- a/demos/3d/platformer/stage.xml
+++ /dev/null
@@ -1,697 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="7" version="1.0" version_name="Godot Engine v1.0.stable.custom_build">
- <ext_resource path="res://sb.cube" type="CubeMap"></ext_resource>
- <ext_resource path="res://tiles.res" type="MeshLibrary"></ext_resource>
- <ext_resource path="res://enemy.scn" type="PackedScene"></ext_resource>
- <ext_resource path="res://player.xml" type="PackedScene"></ext_resource>
- <ext_resource path="res://coin.scn" type="PackedScene"></ext_resource>
- <resource type="Environment" path="local://1">
- <bool name="ambient_light/enabled"> True </bool>
- <color name="ambient_light/color"> 0, 0.409429, 0.596681, 1 </color>
- <real name="ambient_light/energy"> 1 </real>
- <bool name="fxaa/enabled"> False </bool>
- <int name="background/mode"> 4 </int>
- <color name="background/color"> 0, 0, 0, 1 </color>
- <nil name="background/texture"> </nil>
- <resource name="background/cubemap" resource_type="CubeMap" path="res://sb.cube"> </resource>
- <real name="background/energy"> 1 </real>
- <real name="background/scale"> 1 </real>
- <real name="background/glow"> 0.6 </real>
- <bool name="glow/enabled"> True </bool>
- <int name="glow/blur_passes"> 2 </int>
- <real name="glow/blur_scale"> 1.3 </real>
- <real name="glow/blur_strength"> 1.2 </real>
- <int name="glow/blur_blend_mode"> 1 </int>
- <real name="glow/bloom"> 0 </real>
- <real name="glow/bloom_treshold"> 0.5 </real>
- <bool name="dof_blur/enabled"> False </bool>
- <int name="dof_blur/blur_passes"> 1 </int>
- <real name="dof_blur/begin"> 100 </real>
- <real name="dof_blur/range"> 10 </real>
- <bool name="hdr/enabled"> True </bool>
- <int name="hdr/tonemapper"> 0 </int>
- <real name="hdr/exposure"> 0.4 </real>
- <real name="hdr/white"> 1 </real>
- <real name="hdr/glow_treshold"> 0.9 </real>
- <real name="hdr/glow_scale"> 0.5 </real>
- <real name="hdr/min_luminance"> 0.4 </real>
- <real name="hdr/max_luminance"> 8 </real>
- <real name="hdr/exposure_adj_speed"> 2 </real>
- <bool name="fog/enabled"> True </bool>
- <real name="fog/begin"> 10 </real>
- <color name="fog/begin_color"> 0, 0.773632, 0.985852, 1 </color>
- <color name="fog/end_color"> 0, 0, 0, 1 </color>
- <real name="fog/attenuation"> 0.965936 </real>
- <bool name="fog/bg"> True </bool>
- <bool name="bcs/enabled"> False </bool>
- <real name="bcs/brightness"> 1 </real>
- <real name="bcs/contrast"> 1 </real>
- <real name="bcs/saturation"> 1.608 </real>
- <bool name="srgb/enabled"> False </bool>
-
- </resource>
- <main_resource>
- <dictionary name="_bundled" shared="false">
- <string> "names" </string>
- <string_array len="94">
- <string> "world" </string>
- <string> "Spatial" </string>
- <string> "_import_path" </string>
- <string> "_import_transform" </string>
- <string> "visibility/visible" </string>
- <string> "__meta__" </string>
- <string> "GridMap" </string>
- <string> "theme/theme" </string>
- <string> "theme/bake" </string>
- <string> "lighting/bake" </string>
- <string> "cell/size" </string>
- <string> "cell/octant_size" </string>
- <string> "cell/center_x" </string>
- <string> "cell/center_y" </string>
- <string> "cell/center_z" </string>
- <string> "cell/scale" </string>
- <string> "data" </string>
- <string> "DirectionalLight" </string>
- <string> "transform/local" </string>
- <string> "layers" </string>
- <string> "params/enabled" </string>
- <string> "params/editor_only" </string>
- <string> "params/bake_mode" </string>
- <string> "params/energy" </string>
- <string> "colors/diffuse" </string>
- <string> "colors/specular" </string>
- <string> "shadow/shadow" </string>
- <string> "shadow/darkening" </string>
- <string> "shadow/z_offset" </string>
- <string> "shadow/z_slope_scale" </string>
- <string> "shadow/esm_multiplier" </string>
- <string> "shadow/blur_passes" </string>
- <string> "projector" </string>
- <string> "operator" </string>
- <string> "shadow/mode" </string>
- <string> "shadow/max_distance" </string>
- <string> "shadow/split_weight" </string>
- <string> "shadow/zoffset_scale" </string>
- <string> "environment" </string>
- <string> "WorldEnvironment" </string>
- <string> "coins" </string>
- <string> "Node" </string>
- <string> "coin" </string>
- <string> "Area" </string>
- <string> "coin 2" </string>
- <string> "coin 3" </string>
- <string> "coin 3 2" </string>
- <string> "coin 4" </string>
- <string> "coin 4 2" </string>
- <string> "coin 4 3" </string>
- <string> "coin 3 3" </string>
- <string> "coin 5" </string>
- <string> "coin 4 4" </string>
- <string> "coin 3 4" </string>
- <string> "coin 4 4 2" </string>
- <string> "coin 6" </string>
- <string> "coin 4 5" </string>
- <string> "coin 3 5" </string>
- <string> "coin 4 5 2" </string>
- <string> "coin 4 4 3" </string>
- <string> "coin 3 5 2" </string>
- <string> "coin 6 2" </string>
- <string> "coin 4 5 3" </string>
- <string> "coin 7" </string>
- <string> "coin 4 6" </string>
- <string> "coin 6 3" </string>
- <string> "coin 3 5 3" </string>
- <string> "coin 4 4 4" </string>
- <string> "coin 3 6" </string>
- <string> "coin 4 5 4" </string>
- <string> "coin 4 5 4 2" </string>
- <string> "coin 8" </string>
- <string> "coin 4 4 5" </string>
- <string> "coin 4 7" </string>
- <string> "coin 6 4" </string>
- <string> "coin 3 5 4" </string>
- <string> "coin 4 5 5" </string>
- <string> "coin 3 7" </string>
- <string> "coin 4 5 4 3" </string>
- <string> "coin 9" </string>
- <string> "coin 4 4 6" </string>
- <string> "coin 4 8" </string>
- <string> "coin 4 5 6" </string>
- <string> "coin 3 5 5" </string>
- <string> "coin 6 5" </string>
- <string> "coin 3 8" </string>
- <string> "coin 4 5 4 4" </string>
- <string> "enemies" </string>
- <string> "enemy" </string>
- <string> "RigidBody" </string>
- <string> "enemy 2" </string>
- <string> "enemy 3" </string>
- <string> "enemy 4" </string>
- <string> "player" </string>
- </string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
- <string> "node_count" </string>
- <int> 55 </int>
- <string> "variants" </string>
- <array len="82" shared="false">
- <node_path> "" </node_path>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 </transform>
- <bool> True </bool>
- <dictionary shared="false">
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "pixel_snap" </string>
- <bool> False </bool>
- <string> "zoom" </string>
- <real> 1 </real>
- <string> "use_snap" </string>
- <bool> False </bool>
- <string> "ofs" </string>
- <vector2> 1, 1 </vector2>
- <string> "snap" </string>
- <int> 10 </int>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "deflight_rot_y" </string>
- <real> 0.628319 </real>
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "fov" </string>
- <real> 179 </real>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 9.009935 </real>
- <string> "x_rot" </string>
- <real> 0.458294 </real>
- <string> "y_rot" </string>
- <real> -1.2 </real>
- <string> "listener" </string>
- <bool> True </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 13.4535, 5.75047, 13.8175 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "listener" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "listener" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "listener" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- </array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> False </bool>
- <string> "ambient_light_color" </string>
- <color> 0.15, 0.15, 0.15, 1 </color>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "znear" </string>
- <real> 0.1 </real>
- <string> "default_srgb" </string>
- <bool> False </bool>
- <string> "deflight_rot_x" </string>
- <real> 0.942478 </real>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "3D" </string>
- </dictionary>
- <resource resource_type="MeshLibrary" path="res://tiles.res"> </resource>
- <bool> False </bool>
- <real> 2 </real>
- <int> 4 </int>
- <real> 1.001 </real>
- <dictionary shared="false">
- <string> "cells" </string>
- <int_array len="5133"> 3, 0, 1048584, 12, 0, 1441800, 65539, 0, 1048584, 65548, 0, 1441800, 131075, 0, 1048578, 131084, 0, 1441800, 196611, 0, 1048578, 196620, 0, 1441800, 262147, 0, 1048578, 262156, 0, 1441800, 327683, 0, 1048584, 327692, 0, 1441794, 393219, 0, 1048584, 393228, 0, 1441794, 458752, 0, 655367, 458753, 0, 655367, 458754, 0, 655367, 458755, 0, 655367, 458764, 0, 1441794, 524286, 0, 655367, 524287, 0, 655367, 524300, 0, 1441798, -65533, 0, 1048579, -65532, 0, 1441799, -65531, 0, 1441799, -65530, 0, 1441799, -65529, 0, 1441799, -65528, 0, 1441799, -65527, 0, 1441799, -65526, 0, 1441799, -65525, 0, 1441799, -65524, 0, 1441800, 3, 1, 1048584, 12, 1, 1441800, 29, 1, 8, 30, 1, 8, 31, 1, 8, 65539, 1, 1048584, 65548, 1, 1441800, 65560, 1, 655366, 65561, 1, 655366, 65562, 1, 655366, 65563, 1, 655366, 65564, 1, 655365, 65565, 1, 6, 65566, 1, 6, 65567, 1, 6, 65568, 1, 655366, 65569, 1, 655365, 131075, 1, 1048578, 131084, 1, 1441800, 196611, 1, 1048578, 196620, 1, 1441800, 262147, 1, 1048578, 262156, 1, 1441800, 327683, 1, 1048584, 327692, 1, 1441794, 393219, 1, 1048584, 393228, 1, 1441794, 458752, 1, 655367, 458753, 1, 655367, 458754, 1, 655367, 458755, 1, 655367, 458764, 1, 1441794, 524285, 1, 655367, 524286, 1, 655367, 524287, 1, 655367, 524300, 1, 1441798, -65533, 1, 1048579, -65532, 1, 1441799, -65531, 1, 1441799, -65530, 1, 1441799, -65529, 1, 1441799, -65528, 1, 1441799, -65527, 1, 1441799, -65526, 1, 1441799, -65525, 1, 1441799, -65524, 1, 1441800, -65507, 1, 3, -65506, 1, 3, -65505, 1, 3, 3, 2, 1048584, 5, 2, 1441797, 6, 2, 655365, 8, 2, 1441801, 9, 2, 655368, 10, 2, 655368, 11, 2, 655368, 12, 2, 1441800, 28, 2, 1048584, 32, 2, 9, 65539, 2, 1048584, 65544, 2, 1441797, 65545, 2, 655366, 65546, 2, 655366, 65547, 2, 655366, 65548, 2, 1441800, 65564, 2, 655369, 65568, 2, 5, 65569, 2, 1048583, 65570, 2, 655365, 131075, 2, 1048578, 131084, 2, 1441800, 131100, 2, 655369, 196611, 2, 1048578, 196620, 2, 1441800, 196632, 2, 655366, 196633, 2, 655366, 196634, 2, 655366, 196635, 2, 655366, 196636, 2, 655365, 262147, 2, 1048578, 262156, 2, 1441800, 327683, 2, 1048584, 327692, 2, 1441794, 393219, 2, 1048584, 393228, 2, 1441794, 458752, 2, 655367, 458753, 2, 655367, 458754, 2, 655367, 458755, 2, 655367, 458764, 2, 1441794, 524285, 2, 655367, 524286, 2, 655367, 524287, 2, 655367, 524300, 2, 1441798, -65533, 2, 1048579, -65532, 2, 1048583, -65531, 2, 1441796, -65530, 2, 655364, -65529, 2, 1441799, -65528, 2, 1441796, -65527, 2, 655363, -65526, 2, 655363, -65525, 2, 655363, -65524, 2, 1441800, -65508, 2, 1048579, -65507, 2, 1441799, -65506, 2, 1441799, -65505, 2, 1441799, -65504, 2, 4, 3, 3, 1048584, 5, 3, 5, 6, 3, 1048581, 8, 3, 9, 9, 3, 8, 10, 3, 8, 11, 3, 8, 12, 3, 1441800, 28, 3, 1048585, 33, 3, 9, 65539, 3, 1048584, 65544, 3, 5, 65545, 3, 6, 65546, 3, 6, 65547, 3, 6, 65548, 3, 1441800, 65564, 3, 1048585, 65569, 3, 5, 65570, 3, 1048583, 65571, 3, 655365, 131075, 3, 1048578, 131084, 3, 1441800, 131100, 3, 1048585, 196611, 3, 1048578, 196620, 3, 1441800, 196632, 3, 655363, 196633, 3, 655363, 196634, 3, 655363, 196635, 3, 655364, 196636, 3, 1048581, 262147, 3, 1048578, 262156, 3, 1441800, 262168, 3, 655366, 262169, 3, 655366, 262170, 3, 655366, 262171, 3, 655365, 327683, 3, 1048584, 327692, 3, 1441794, 393219, 3, 1048584, 393228, 3, 1441794, 458752, 3, 655367, 458753, 3, 655366, 458754, 3, 655366, 458755, 3, 655367, 458764, 3, 1441794, 458771, 3, 1048578, 524284, 3, 655367, 524285, 3, 655367, 524286, 3, 655367, 524287, 3, 655367, 524300, 3, 1441798, -65533, 3, 1048579, -65532, 3, 1048583, -65531, 3, 4, -65530, 3, 1048580, -65529, 3, 1441799, -65528, 3, 4, -65527, 3, 3, -65526, 3, 3, -65525, 3, 3, -65524, 3, 1441800, -65508, 3, 1048580, -65507, 3, 1441799, -65506, 3, 1441799, -65505, 3, 1441799, -65504, 3, 1441799, -65503, 3, 4, 3, 4, 1048584, 12, 4, 1441800, 27, 4, 1048584, 34, 4, 1441800, 65539, 4, 1048584, 65548, 4, 1441800, 65563, 4, 1048584, 65570, 4, 1048583, 65571, 4, 1048582, 131075, 4, 1048578, 131084, 4, 9, 131085, 4, 3, 131086, 4, 3, 131087, 4, 3, 131088, 4, 3, 131089, 4, 3, 131090, 4, 3, 131099, 4, 1048584, 196611, 4, 1048578, 196620, 4, 9, 196621, 4, 8, 196622, 4, 8, 196623, 4, 8, 196624, 4, 8, 196625, 4, 8, 196626, 4, 8, 196635, 4, 1048584, 262147, 4, 1048578, 262156, 4, 1441800, 262168, 4, 655363, 262169, 4, 655363, 262170, 4, 655364, 262171, 4, 1048582, 327680, 4, 8, 327681, 4, 8, 327682, 4, 8, 327683, 4, 1048580, 327691, 4, 1441808, 327692, 4, 9, 327693, 4, 3, 327694, 4, 3, 327695, 4, 3, 327696, 4, 3, 327697, 4, 3, 393216, 4, 8, 393217, 4, 8, 393218, 4, 8, 393219, 4, 1048585, 393228, 4, 9, 393229, 4, 2, 393230, 4, 2, 393231, 4, 2, 393232, 4, 2, 393233, 4, 2, 458752, 4, 6, 458753, 4, 6, 458754, 4, 6, 458755, 4, 1048581, 458764, 4, 1441800, 458771, 4, 1048578, 458774, 4, 1048583, 458775, 4, 1048583, 458776, 4, 1048583, 458777, 4, 1048583, 458778, 4, 1048582, 524284, 4, 655367, 524285, 4, 655367, 524286, 4, 655367, 524287, 4, 1048583, 524300, 4, 1441798, 524307, 4, 1048582, -65533, 4, 1048579, -65532, 4, 7, -65531, 4, 7, -65530, 4, 7, -65529, 4, 7, -65528, 4, 1441799, -65527, 4, 1441799, -65526, 4, 1441799, -65525, 4, 1441799, -65524, 4, 1441800, -65509, 4, 1048579, -65508, 4, 1441799, -65507, 4, 1441799, -65506, 4, 1441799, -65505, 4, 1441799, -65504, 4, 1441799, -65503, 4, 1441799, -65502, 4, 1441795, 3, 5, 1048584, 11, 5, 1441801, 27, 5, 1048584, 34, 5, 9, 65538, 5, 3, 65539, 5, 1048580, 65547, 5, 1441801, 65563, 5, 1048584, 65570, 5, 5, 65571, 5, 1048582, 131074, 5, 2, 131075, 5, 1048585, 131083, 5, 1441797, 131084, 5, 7, 131085, 5, 7, 131086, 5, 7, 131087, 5, 7, 131088, 5, 7, 131089, 5, 7, 131090, 5, 7, 131091, 5, 1441795, 131099, 5, 1048584, 196610, 5, 2, 196611, 5, 1048585, 196627, 5, 1441800, 196635, 5, 1048584, 262146, 5, 2, 262147, 5, 1048585, 262156, 5, 1441806, 262157, 5, 1, 262158, 5, 1, 262159, 5, 1, 262160, 5, 1, 262161, 5, 655361, 262162, 5, 655361, 262170, 5, 1048584, 262171, 5, 1048582, 327680, 5, 655366, 327681, 5, 1441798, 327682, 5, 6, 327683, 5, 1048581, 327692, 5, 1441798, 327693, 5, 7, 327694, 5, 7, 327695, 5, 7, 327696, 5, 7, 327697, 5, 1048583, 327698, 5, 1441795, 393215, 5, 1048584, 393234, 5, 1441794, 458751, 5, 1048584, 458764, 5, 1441806, 458765, 5, 655361, 458766, 5, 655361, 458767, 5, 655361, 458768, 5, 655361, 458769, 5, 655361, 458771, 5, 1048578, 458773, 5, 1048583, 458774, 5, 1048583, 458775, 5, 1048583, 458776, 5, 1048583, 458777, 5, 1048583, 458778, 5, 1048582, 524283, 5, 655367, 524284, 5, 655367, 524285, 5, 655367, 524286, 5, 655367, 524287, 5, 1048582, 524300, 5, 1441798, 524301, 5, 1441799, 524302, 5, 1441799, 524303, 5, 1441799, 524304, 5, 1441799, 524305, 5, 1441799, 524306, 5, 1441799, 524307, 5, 1048582, -65533, 5, 1048579, -65532, 5, 7, -65531, 5, 7, -65530, 5, 7, -65529, 5, 1048583, -65528, 5, 1441799, -65527, 5, 1441799, -65526, 5, 1441799, -65525, 5, 1441801, -65509, 5, 1048579, -65508, 5, 1441799, -65507, 5, 1441799, -65506, 5, 1441799, -65505, 5, 1441799, -65504, 5, 1441799, -65503, 5, 1441799, -65502, 5, 4, 2, 6, 655368, 3, 6, 655368, 4, 6, 655369, 11, 6, 1441794, 27, 6, 1048584, 35, 6, 1441800, 65537, 6, 1048579, 65538, 6, 655366, 65539, 6, 655366, 65540, 6, 655365, 65547, 6, 1441794, 65563, 6, 1048584, 65571, 6, 1441798, 131073, 6, 1048584, 131083, 6, 1441798, 131084, 6, 7, 131085, 6, 7, 131086, 6, 7, 131087, 6, 7, 131088, 6, 7, 131089, 6, 7, 131090, 6, 7, 131091, 6, 1441795, 131099, 6, 1048584, 196609, 6, 1048584, 196627, 6, 1441800, 196635, 6, 1048584, 262145, 6, 1048584, 262156, 6, 1441806, 262157, 6, 1, 262158, 6, 1, 262159, 6, 1, 262160, 6, 1, 262161, 6, 655361, 262162, 6, 655361, 262170, 6, 1048584, 262171, 6, 1048582, 327680, 6, 1441799, 327681, 6, 1048582, 327692, 6, 1441798, 327693, 6, 7, 327694, 6, 7, 327695, 6, 7, 327696, 6, 7, 327697, 6, 1048583, 327698, 6, 1441795, 393215, 6, 1048584, 393234, 6, 1441794, 458751, 6, 1048584, 458764, 6, 1441806, 458765, 6, 655361, 458766, 6, 655361, 458767, 6, 655361, 458768, 6, 655361, 458769, 6, 655361, 458771, 6, 1048578, 458773, 6, 1048583, 458774, 6, 1048583, 458775, 6, 1048583, 458776, 6, 1048583, 458777, 6, 1048583, 458778, 6, 1048582, 524283, 6, 655367, 524284, 6, 655367, 524285, 6, 655367, 524286, 6, 655367, 524287, 6, 1048582, 524300, 6, 1441798, 524301, 6, 1441799, 524302, 6, 1441799, 524303, 6, 1441799, 524304, 6, 1441799, 524305, 6, 1441799, 524306, 6, 1441799, 524307, 6, 1048582, -65534, 6, 655363, -65533, 6, 655363, -65532, 6, 655364, -65531, 6, 655367, -65530, 6, 655367, -65529, 6, 1048583, -65528, 6, 7, -65527, 6, 1441799, -65526, 6, 1441799, -65525, 6, 1441795, -65509, 6, 1048579, -65508, 6, 1441799, -65507, 6, 1441799, -65506, 6, 1441799, -65505, 6, 1441799, -65504, 6, 1441799, -65503, 6, 1441799, -65502, 6, 1441799, -65501, 6, 1441800, 4, 7, 1048584, 6, 7, 11, 11, 7, 9, 27, 7, 1048584, 35, 7, 1441800, 65537, 7, 1048579, 65538, 7, 1441799, 65539, 7, 1441799, 65540, 7, 1048582, 65542, 7, 12, 65547, 7, 9, 65563, 7, 1048584, 65571, 7, 1441798, 131073, 7, 1048584, 131078, 7, 1441804, 131083, 7, 5, 131084, 7, 7, 131085, 7, 1441796, 131086, 7, 655363, 131087, 7, 655363, 131088, 7, 655364, 131089, 7, 7, 131090, 7, 7, 131091, 7, 1441795, 131099, 7, 1048584, 196609, 7, 1048584, 196614, 7, 13, 196621, 7, 1441801, 196622, 7, 655362, 196623, 7, 655362, 196624, 7, 655369, 196627, 7, 1441800, 196635, 7, 1048584, 262145, 7, 1048584, 262156, 7, 1441806, 262157, 7, 1441806, 262158, 7, 1, 262159, 7, 1, 262160, 7, 1, 262161, 7, 655361, 262162, 7, 655361, 262170, 7, 1048584, 262171, 7, 1048582, 327680, 7, 1441799, 327681, 7, 1048582, 327691, 7, 1441809, 327692, 7, 1441801, 327693, 7, 655363, 327694, 7, 655363, 327695, 7, 655363, 327696, 7, 655364, 327697, 7, 1048583, 327698, 7, 1441795, 393215, 7, 1048584, 393228, 7, 1441801, 393229, 7, 655368, 393230, 7, 655368, 393231, 7, 655368, 393232, 7, 655369, 393234, 7, 1441794, 458751, 7, 1048584, 458764, 7, 1441800, 458768, 7, 655361, 458769, 7, 655361, 458771, 7, 1048578, 458774, 7, 1048583, 458775, 7, 1048583, 458776, 7, 1048583, 458777, 7, 1048583, 458778, 7, 1048582, 524282, 7, 655367, 524283, 7, 655367, 524284, 7, 655367, 524285, 7, 655367, 524286, 7, 655367, 524287, 7, 1048582, 524300, 7, 1441798, 524301, 7, 1441799, 524302, 7, 1441799, 524303, 7, 1441799, 524304, 7, 1441799, 524305, 7, 1441799, 524306, 7, 1441799, 524307, 7, 1048582, -65532, 7, 1048579, -65531, 7, 1048583, -65530, 7, 10, -65529, 7, 1441799, -65528, 7, 1441799, -65527, 7, 1441799, -65526, 7, 1441799, -65525, 7, 4, -65509, 7, 1048579, -65508, 7, 1441799, -65507, 7, 1441799, -65506, 7, 1441799, -65505, 7, 1441799, -65504, 7, 1441799, -65503, 7, 1441799, -65502, 7, 1441799, -65501, 7, 1441800, 2, 8, 3, 3, 8, 3, 4, 8, 1048585, 12, 8, 1441800, 27, 8, 1048584, 35, 8, 1441800, 65537, 8, 1048579, 65538, 8, 6, 65539, 8, 6, 65540, 8, 1048581, 65548, 8, 1441800, 65563, 8, 1048584, 65571, 8, 1441798, 65572, 8, 655366, 65573, 8, 655366, 65574, 8, 655366, 65575, 8, 655366, 65576, 8, 655366, 65577, 8, 655365, 131073, 8, 1048584, 131084, 8, 1441796, 131088, 8, 1048579, 131089, 8, 7, 131090, 8, 7, 131091, 8, 1441795, 131099, 8, 1048584, 196609, 8, 1048584, 196620, 8, 1441801, 196624, 8, 1048584, 196627, 8, 1441800, 196635, 8, 1048584, 262145, 8, 1048584, 262156, 8, 1441800, 262161, 8, 655361, 262162, 8, 655361, 262170, 8, 1048584, 262171, 8, 1048582, 327680, 8, 1441799, 327681, 8, 1048581, 327692, 8, 1441800, 327695, 8, 3, 327696, 8, 1048580, 327697, 8, 1048583, 327698, 8, 1441795, 393215, 8, 1048584, 393228, 8, 1441800, 393231, 8, 8, 393232, 8, 1048585, 393234, 8, 1441794, 458751, 8, 1048584, 458764, 8, 9, 458769, 8, 655361, 458771, 8, 1048578, 458774, 8, 1048583, 458775, 8, 1048583, 458776, 8, 1048583, 458777, 8, 1048583, 458778, 8, 1048582, 524282, 8, 655367, 524283, 8, 655367, 524284, 8, 655367, 524285, 8, 655367, 524286, 8, 655367, 524287, 8, 1048582, 524300, 8, 5, 524301, 8, 1441799, 524302, 8, 1441799, 524303, 8, 1441799, 524304, 8, 1441799, 524305, 8, 1441799, 524306, 8, 1441799, 524307, 8, 1048582, -65534, 8, 3, -65533, 8, 3, -65532, 8, 1048580, -65531, 8, 655367, -65530, 8, 655367, -65529, 8, 655367, -65528, 8, 1441799, -65527, 8, 1441799, -65526, 8, 1441799, -65525, 8, 655367, -65524, 8, 1441800, -65509, 8, 1048579, -65508, 8, 1441799, -65507, 8, 1441799, -65506, 8, 1441799, -65505, 8, 1441799, -65504, 8, 1441799, -65503, 8, 1441799, -65502, 8, 1441799, -65501, 8, 1441800, 1, 9, 1048578, 2, 9, 5, 3, 9, 1048581, 8, 9, 11, 12, 9, 1441800, 27, 9, 1048584, 35, 9, 1441800, 65537, 9, 1048578, 65544, 9, 12, 65548, 9, 1441800, 65563, 9, 1048584, 65570, 9, 1441809, 65571, 9, 1441801, 65572, 9, 655363, 65573, 9, 655363, 65574, 9, 655363, 65575, 9, 655363, 65576, 9, 655363, 131073, 9, 1048578, 131080, 9, 1048588, 131084, 9, 1441800, 131088, 9, 1048579, 131089, 9, 7, 131090, 9, 7, 131091, 9, 1441795, 131099, 9, 1048584, 131107, 9, 1441797, 131108, 9, 655366, 131109, 9, 655366, 131110, 9, 655366, 131111, 9, 655366, 131112, 9, 655366, 131113, 9, 655365, 196609, 9, 1048578, 196616, 9, 1048588, 196620, 9, 1441800, 196624, 9, 1048584, 196627, 9, 1441800, 196635, 9, 1048584, 262145, 9, 1048578, 262152, 9, 1048589, 262156, 9, 1441800, 262161, 9, 655361, 262162, 9, 655361, 262169, 9, 3, 262170, 9, 1048580, 262171, 9, 1048582, 327680, 9, 655368, 327681, 9, 655369, 327682, 9, 1048592, 327692, 9, 1441800, 327694, 9, 1048579, 327695, 9, 1441799, 327696, 9, 1441799, 327697, 9, 1441799, 327698, 9, 1441795, 327705, 9, 8, 327706, 9, 1048585, 393216, 9, 655368, 393217, 9, 655369, 393228, 9, 1441800, 393230, 9, 1048584, 393234, 9, 1441794, 393241, 9, 8, 393242, 9, 1048585, 458752, 9, 655366, 458753, 9, 655365, 458764, 9, 1441798, 458765, 9, 1441795, 458767, 9, 655361, 458768, 9, 655361, 458769, 9, 655361, 458771, 9, 1048578, 458774, 9, 1048583, 458775, 9, 1048583, 458776, 9, 1048583, 458777, 9, 6, 458778, 9, 1048581, 524282, 9, 655367, 524283, 9, 655367, 524284, 9, 655367, 524285, 9, 655367, 524286, 9, 655367, 524287, 9, 655367, 524301, 9, 1441798, 524302, 9, 1441799, 524303, 9, 1441799, 524304, 9, 1441799, 524305, 9, 1441799, 524306, 9, 1441799, 524307, 9, 1048582, -65535, 9, 1048584, -65534, 9, 4, -65533, 9, 1048580, -65532, 9, 7, -65531, 9, 7, -65530, 9, 7, -65529, 9, 7, -65528, 9, 10, -65527, 9, 1441799, -65526, 9, 1441799, -65525, 9, 655367, -65524, 9, 1441800, -65509, 9, 1048579, -65508, 9, 1441799, -65507, 9, 1441799, -65506, 9, 1441799, -65505, 9, 1441799, -65504, 9, 1441799, -65503, 9, 1441799, -65502, 9, 1441799, -65501, 9, 1441800, 1, 10, 1048578, 12, 10, 1441800, 26, 10, 8, 27, 10, 1048585, 35, 10, 1441800, 65537, 10, 1048578, 65548, 10, 1441800, 65561, 10, 3, 65562, 10, 3, 65563, 10, 1048585, 65571, 10, 1441800, 131073, 10, 1048578, 131084, 10, 1441800, 131088, 10, 1048580, 131089, 10, 1048583, 131090, 10, 1048583, 131091, 10, 4, 131097, 10, 8, 131098, 10, 8, 131099, 10, 1048585, 131106, 10, 1441809, 131107, 10, 1441801, 131108, 10, 655363, 131109, 10, 655363, 131110, 10, 655363, 131111, 10, 655363, 131112, 10, 655364, 131113, 10, 1048582, 196609, 10, 1048578, 196620, 10, 1441800, 196624, 10, 1048585, 196627, 10, 9, 196633, 10, 8, 196634, 10, 8, 196635, 10, 1048585, 196643, 10, 1441797, 196644, 10, 655366, 196645, 10, 655366, 196646, 10, 655366, 196647, 10, 655366, 196648, 10, 655366, 196649, 10, 655365, 262145, 10, 1048578, 262156, 10, 1441800, 262161, 10, 1, 262162, 10, 1, 262168, 10, 1048579, 262169, 10, 6, 262170, 10, 6, 262171, 10, 1048581, 327681, 10, 1048578, 327685, 10, 655377, 327689, 10, 655376, 327692, 10, 1441800, 327694, 10, 1048579, 327695, 10, 1441799, 327696, 10, 1441796, 327697, 10, 655363, 327704, 10, 1048584, 393217, 10, 1048584, 393228, 10, 1441800, 393230, 10, 1048584, 393232, 10, 1441801, 393233, 10, 655362, 393240, 10, 1048584, 458752, 10, 6, 458753, 10, 1048582, 458764, 10, 1441798, 458765, 10, 4, 458766, 10, 3, 458767, 10, 14, 458768, 10, 3, 458769, 10, 8, 458770, 10, 8, 458771, 10, 1048585, 458774, 10, 1048583, 458775, 10, 1048583, 458776, 10, 1048582, 524282, 10, 655367, 524283, 10, 655367, 524284, 10, 655367, 524285, 10, 655367, 524286, 10, 655367, 524287, 10, 655367, 524301, 10, 5, 524302, 10, 6, 524303, 10, 6, 524304, 10, 6, 524305, 10, 6, 524306, 10, 6, 524307, 10, 1048581, -65535, 10, 1048584, -65534, 10, 1048583, -65533, 10, 7, -65532, 10, 7, -65531, 10, 7, -65530, 10, 7, -65529, 10, 7, -65528, 10, 655367, -65527, 10, 655367, -65526, 10, 655367, -65525, 10, 655367, -65524, 10, 1441800, -65511, 10, 3, -65510, 10, 3, -65509, 10, 1048580, -65508, 10, 7, -65507, 10, 7, -65506, 10, 7, -65505, 10, 7, -65504, 10, 7, -65503, 10, 7, -65502, 10, 1441799, -65501, 10, 1441795, 2, 11, 655368, 3, 11, 655368, 4, 11, 655368, 5, 11, 655368, 6, 11, 655368, 7, 11, 655368, 8, 11, 655368, 9, 11, 655368, 10, 11, 655368, 11, 11, 655368, 21, 11, 8, 22, 11, 8, 23, 11, 8, 24, 11, 1048585, 25, 11, 1441801, 26, 11, 655369, 35, 11, 1441800, 65538, 11, 655368, 65539, 11, 655368, 65540, 11, 655368, 65541, 11, 655368, 65542, 11, 655368, 65543, 11, 655368, 65544, 11, 655368, 65545, 11, 655368, 65546, 11, 655368, 65547, 11, 655368, 65549, 11, 8, 65550, 11, 8, 65551, 11, 8, 65552, 11, 8, 65553, 11, 8, 65554, 11, 8, 65555, 11, 8, 65556, 11, 8, 65557, 11, 8, 65558, 11, 8, 65559, 11, 8, 65560, 11, 1048585, 65561, 11, 1441797, 65562, 11, 655365, 65571, 11, 1441800, 131074, 11, 655368, 131075, 11, 655368, 131076, 11, 655368, 131077, 11, 655368, 131078, 11, 655368, 131079, 11, 655368, 131080, 11, 655368, 131081, 11, 655368, 131082, 11, 655368, 131083, 11, 655368, 131085, 11, 8, 131086, 11, 8, 131087, 11, 1048585, 131088, 11, 6, 131089, 11, 6, 131090, 11, 6, 131091, 11, 6, 131092, 11, 9, 131093, 11, 8, 131094, 11, 8, 131095, 11, 8, 131096, 11, 1048585, 131107, 11, 1441800, 196610, 11, 655368, 196611, 11, 655368, 196612, 11, 655368, 196613, 11, 655368, 196614, 11, 655368, 196615, 11, 655368, 196616, 11, 655368, 196617, 11, 655368, 196618, 11, 655368, 196619, 11, 655368, 196621, 11, 8, 196622, 11, 8, 196623, 11, 1048585, 196628, 11, 9, 196629, 11, 8, 196630, 11, 8, 196631, 11, 8, 196632, 11, 1048585, 196642, 11, 1441809, 196643, 11, 1441801, 196644, 11, 655363, 196645, 11, 655363, 196646, 11, 655363, 196647, 11, 655363, 196648, 11, 655364, 196649, 11, 1048582, 262146, 11, 655368, 262147, 11, 655368, 262148, 11, 655368, 262149, 11, 655368, 262150, 11, 655368, 262151, 11, 655368, 262152, 11, 655368, 262153, 11, 655368, 262154, 11, 655368, 262155, 11, 655368, 262157, 11, 8, 262158, 11, 8, 262159, 11, 8, 262160, 11, 14, 262161, 11, 14, 262162, 11, 14, 262163, 11, 14, 262164, 11, 8, 262165, 11, 8, 262166, 11, 8, 262167, 11, 8, 262168, 11, 1048585, 262179, 11, 1441797, 262180, 11, 655366, 262181, 11, 655366, 262182, 11, 655366, 262183, 11, 655366, 262184, 11, 655366, 262185, 11, 655365, 327682, 11, 655362, 327683, 11, 655362, 327684, 11, 655362, 327685, 11, 655369, 327686, 11, 655366, 327687, 11, 655366, 327688, 11, 655366, 327689, 11, 1441801, 327690, 11, 655368, 327691, 11, 655368, 327693, 11, 8, 327694, 11, 1048585, 327695, 11, 6, 327696, 11, 9, 327697, 11, 8, 327698, 11, 8, 327699, 11, 8, 327700, 11, 8, 327701, 11, 8, 327702, 11, 8, 327703, 11, 8, 327704, 11, 1048585, 393218, 11, 655362, 393219, 11, 655362, 393220, 11, 655362, 393221, 11, 655369, 393225, 11, 1441801, 393226, 11, 655368, 393227, 11, 655368, 393229, 11, 8, 393230, 11, 1048585, 393232, 11, 9, 393233, 11, 2, 393234, 11, 2, 393235, 11, 2, 393236, 11, 2, 393237, 11, 8, 393238, 11, 8, 393239, 11, 8, 393240, 11, 1048585, 458752, 11, 655367, 458753, 11, 655367, 458754, 11, 655366, 458755, 11, 655366, 458756, 11, 655366, 458757, 11, 655366, 458761, 11, 1441797, 458762, 11, 655366, 458763, 11, 655366, 458764, 11, 1441799, 458765, 11, 6, 458766, 11, 1048581, 458768, 11, 5, 458769, 11, 6, 458770, 11, 6, 458771, 11, 6, 458772, 11, 6, 458773, 11, 6, 458774, 11, 6, 458775, 11, 6, 458776, 11, 1048581, 524282, 11, 655367, 524283, 11, 655367, 524284, 11, 655367, 524285, 11, 655367, 524286, 11, 655367, 524287, 11, 655367, -65534, 11, 655363, -65533, 11, 655363, -65532, 11, 655363, -65531, 11, 655363, -65530, 11, 655363, -65529, 11, 655363, -65528, 11, 655363, -65527, 11, 655363, -65526, 11, 655363, -65525, 11, 655363, -65512, 11, 1048580, -65511, 11, 1441796, -65510, 11, 655364, -65509, 11, 7, -65508, 11, 7, -65507, 11, 7, -65506, 11, 7, -65505, 11, 7, -65504, 11, 7, -65503, 11, 7, -65502, 11, 7, -65501, 11, 1441795, 21, 12, 15, 23, 12, 1048582, 25, 12, 9, 26, 12, 1048585, 35, 12, 1441800, 65548, 12, 1048584, 65549, 12, 1048583, 65550, 12, 1048583, 65551, 12, 1048583, 65552, 12, 1048583, 65553, 12, 1048583, 65554, 12, 1048583, 65555, 12, 1048583, 65556, 12, 1048583, 65561, 12, 5, 65562, 12, 1048581, 65571, 12, 1441800, 131084, 12, 1048584, 131087, 12, 16, 131092, 12, 17, 131107, 12, 1441800, 196620, 12, 1048584, 196643, 12, 1441800, 262156, 12, 1048584, 262178, 12, 1441809, 262179, 12, 1441801, 262180, 12, 655363, 262181, 12, 655363, 262182, 12, 655363, 262183, 12, 655363, 262184, 12, 655364, 262185, 12, 1048582, 327686, 12, 655363, 327687, 12, 655363, 327688, 12, 655363, 327692, 12, 1048584, 327694, 12, 16, 327696, 12, 17, 327715, 12, 1441797, 327716, 12, 655366, 327717, 12, 655366, 327718, 12, 655366, 327719, 12, 655366, 327720, 12, 655365, 393222, 12, 655368, 393223, 12, 655368, 393224, 12, 655368, 393228, 12, 1048584, 458752, 12, 655367, 458753, 12, 655367, 458754, 12, 655367, 458755, 12, 655367, 458756, 12, 655367, 458757, 12, 655367, 458758, 12, 655366, 458759, 12, 655366, 458760, 12, 655366, 458761, 12, 1441799, 458762, 12, 1441799, 458763, 12, 1441799, 458764, 12, 655366, 524282, 12, 655367, 524283, 12, 655367, 524284, 12, 655367, 524285, 12, 655367, 524286, 12, 655367, 524287, 12, 655367, -65513, 12, 1048579, -65512, 12, 7, -65511, 12, 4, -65510, 12, 1048580, -65509, 12, 7, -65508, 12, 7, -65507, 12, 7, -65506, 12, 7, -65505, 12, 7, -65504, 12, 7, -65503, 12, 7, -65502, 12, 7, -65501, 12, 1441795, 21, 13, 15, 23, 13, 1048582, 28, 13, 1441801, 29, 13, 655369, 35, 13, 1441800, 65548, 13, 1048584, 65549, 13, 1048583, 65550, 13, 1048583, 65551, 13, 1048583, 65552, 13, 1048583, 65553, 13, 1048583, 65554, 13, 1048583, 65555, 13, 1048583, 65556, 13, 1048583, 65564, 13, 1441801, 65565, 13, 655369, 65571, 13, 1441800, 131084, 13, 1048584, 131100, 13, 1441797, 131101, 13, 655365, 131107, 13, 1441800, 196620, 13, 1048584, 196643, 13, 1441800, 262156, 13, 1048584, 262179, 13, 1441800, 327692, 13, 1048584, 327715, 13, 1441798, 393228, 13, 1048584, 458752, 13, 655367, 458753, 13, 655367, 458754, 13, 655367, 458755, 13, 655367, 458756, 13, 655367, 458757, 13, 655367, 458758, 13, 655367, 458759, 13, 655367, 458760, 13, 655367, 458761, 13, 655367, 458762, 13, 1441799, 458763, 13, 1441799, 458764, 13, 655366, 524282, 13, 655367, 524283, 13, 655367, 524284, 13, 655367, 524285, 13, 655367, 524286, 13, 655367, 524287, 13, 655367, -65513, 13, 1048579, -65512, 13, 7, -65511, 13, 7, -65510, 13, 7, -65509, 13, 7, -65508, 13, 1441796, -65507, 13, 655364, -65506, 13, 7, -65505, 13, 7, -65504, 13, 7, -65503, 13, 7, -65502, 13, 7, -65501, 13, 1441795, 21, 14, 15, 23, 14, 1048582, 28, 14, 9, 29, 14, 1048585, 35, 14, 1441800, 65548, 14, 1048584, 65549, 14, 1048583, 65550, 14, 1048583, 65551, 14, 1048583, 65552, 14, 1048583, 65553, 14, 655373, 65554, 14, 655373, 65555, 14, 1048583, 65556, 14, 1048583, 65564, 14, 9, 65565, 14, 1048585, 65571, 14, 1441800, 131084, 14, 1048584, 131090, 14, 655373, 131100, 14, 5, 131101, 14, 1048581, 131107, 14, 1441800, 196620, 14, 1048584, 196643, 14, 1441800, 262156, 14, 1048584, 262179, 14, 1441800, 327692, 14, 1048584, 327715, 14, 1441798, 393228, 14, 1048584, 458752, 14, 655367, 458753, 14, 655367, 458754, 14, 655367, 458755, 14, 655367, 458756, 14, 655367, 458757, 14, 655367, 458758, 14, 655367, 458759, 14, 655367, 458760, 14, 655367, 458761, 14, 655367, 458762, 14, 1441799, 458763, 14, 1441799, 458764, 14, 655366, 524282, 14, 655367, 524283, 14, 655367, 524284, 14, 655367, 524285, 14, 655367, 524286, 14, 655367, 524287, 14, 655367, -65513, 14, 1048579, -65512, 14, 7, -65511, 14, 7, -65510, 14, 7, -65509, 14, 7, -65508, 14, 4, -65507, 14, 1048580, -65506, 14, 7, -65505, 14, 7, -65504, 14, 7, -65503, 14, 7, -65502, 14, 7, -65501, 14, 1441795, 21, 15, 655368, 22, 15, 655368, 23, 15, 655368, 24, 15, 655369, 31, 15, 1441801, 32, 15, 655369, 35, 15, 1441800, 65548, 15, 1048584, 65549, 15, 655368, 65550, 15, 655368, 65551, 15, 655368, 65552, 15, 655368, 65553, 15, 655368, 65554, 15, 655368, 65555, 15, 655368, 65556, 15, 655368, 65557, 15, 655368, 65558, 15, 655368, 65559, 15, 655368, 65560, 15, 655369, 65567, 15, 1441801, 65568, 15, 655369, 65571, 15, 1441800, 131084, 15, 1048584, 131085, 15, 655368, 131086, 15, 655368, 131087, 15, 655368, 131088, 15, 655368, 131089, 15, 655368, 131090, 15, 655368, 131091, 15, 655368, 131092, 15, 655368, 131093, 15, 655368, 131094, 15, 655368, 131095, 15, 655368, 131096, 15, 655369, 131103, 15, 1441801, 131104, 15, 655369, 131107, 15, 1441800, 196620, 15, 1048584, 196621, 15, 655368, 196622, 15, 655368, 196623, 15, 655368, 196624, 15, 655368, 196625, 15, 655368, 196626, 15, 655368, 196627, 15, 655368, 196628, 15, 655368, 196629, 15, 655368, 196630, 15, 655368, 196631, 15, 655368, 196632, 15, 655369, 196639, 15, 1441797, 196640, 15, 655365, 196643, 15, 1441800, 262156, 15, 1048584, 262158, 15, 655368, 262159, 15, 655368, 262160, 15, 655368, 262161, 15, 655368, 262162, 15, 655368, 262163, 15, 655368, 262164, 15, 655368, 262165, 15, 655368, 262166, 15, 655368, 262167, 15, 655368, 262168, 15, 655369, 262179, 15, 1441800, 327692, 15, 1048584, 327693, 15, 655368, 327694, 15, 655368, 327695, 15, 655368, 327696, 15, 655368, 327697, 15, 655368, 327698, 15, 655368, 327699, 15, 655368, 327700, 15, 655366, 327701, 15, 655366, 327702, 15, 655366, 327703, 15, 655366, 327704, 15, 655365, 327715, 15, 1441798, 393228, 15, 1048584, 393229, 15, 655368, 393230, 15, 655368, 393231, 15, 655368, 393232, 15, 655368, 393233, 15, 655368, 393234, 15, 655368, 393235, 15, 655368, 458752, 15, 655367, 458753, 15, 655367, 458754, 15, 655367, 458755, 15, 655367, 458756, 15, 655367, 458757, 15, 655367, 458758, 15, 655367, 458759, 15, 655367, 458760, 15, 655367, 458761, 15, 655367, 458762, 15, 1441799, 458763, 15, 1441799, 458764, 15, 655366, 458765, 15, 655366, 458766, 15, 655366, 458767, 15, 655366, 458768, 15, 655366, 458769, 15, 655366, 458770, 15, 655366, 458771, 15, 655366, 524282, 15, 655367, 524284, 15, 655367, 524285, 15, 655367, 524286, 15, 655367, 524287, 15, 655367, -65512, 15, 655364, -65511, 15, 7, -65510, 15, 7, -65509, 15, 7, -65508, 15, 7, -65507, 15, 7, -65506, 15, 7, -65505, 15, 1441796, -65504, 15, 655364, -65503, 15, 7, -65502, 15, 7, -65501, 15, 1441795, 25, 16, 655369, 31, 16, 9, 32, 16, 1048585, 34, 16, 1441801, 65548, 16, 1048584, 65561, 16, 655369, 65567, 16, 9, 65568, 16, 1048585, 65570, 16, 1441801, 131084, 16, 1048584, 131097, 16, 655369, 131103, 16, 9, 131104, 16, 1048585, 131106, 16, 1441801, 196620, 16, 1048584, 196633, 16, 655369, 196639, 16, 5, 196640, 16, 1048581, 196642, 16, 1441801, 262156, 16, 1048584, 262169, 16, 655369, 262178, 16, 1441801, 327692, 16, 1048584, 327705, 16, 655365, 327714, 16, 1441797, 393228, 16, 1048584, 458752, 16, 655367, 458753, 16, 655367, 458754, 16, 655367, 458755, 16, 655367, 458756, 16, 655367, 458757, 16, 655367, 458758, 16, 655367, 458759, 16, 655367, 458760, 16, 655367, 458761, 16, 655367, 458762, 16, 1441799, 458763, 16, 1441799, 458764, 16, 655366, 524282, 16, 655367, 524284, 16, 655367, 524285, 16, 655367, 524286, 16, 655367, 524287, 16, 655367, -65511, 16, 655364, -65510, 16, 7, -65509, 16, 7, -65508, 16, 7, -65507, 16, 7, -65506, 16, 7, -65505, 16, 4, -65504, 16, 1048580, -65503, 16, 7, -65502, 16, 1441796, 25, 17, 1048584, 34, 17, 1441800, 65548, 17, 1048584, 65561, 17, 1048584, 65570, 17, 1441800, 131084, 17, 1048584, 131097, 17, 1048584, 131106, 17, 1441800, 196633, 17, 1048584, 196642, 17, 1441800, 262169, 17, 1048584, 262174, 17, 655377, 262177, 17, 655376, 262178, 17, 1441800, 327705, 17, 1048582, 327714, 17, 1441798, 458752, 17, 655367, 458753, 17, 655367, 458754, 17, 655367, 458755, 17, 655367, 458756, 17, 655367, 458757, 17, 655367, 458758, 17, 655367, 458759, 17, 655367, 458760, 17, 655367, 458761, 17, 655367, 458762, 17, 1441799, 458763, 17, 1441799, 458764, 17, 1441799, 524282, 17, 655367, 524283, 17, 655367, 524284, 17, 655367, 524285, 17, 655367, 524286, 17, 655367, 524287, 17, 655367, -65511, 17, 1048579, -65510, 17, 7, -65509, 17, 7, -65508, 17, 7, -65507, 17, 7, -65506, 17, 7, -65505, 17, 7, -65504, 17, 7, -65503, 17, 7, -65502, 17, 1441795, 26, 18, 655368, 27, 18, 655368, 28, 18, 655368, 29, 18, 655368, 30, 18, 655368, 31, 18, 655368, 32, 18, 655368, 33, 18, 655368, 65562, 18, 655368, 65563, 18, 655368, 65564, 18, 655368, 65565, 18, 655368, 65566, 18, 655368, 65567, 18, 655368, 65568, 18, 655368, 65569, 18, 655368, 131098, 18, 655368, 131099, 18, 655368, 131100, 18, 655368, 131101, 18, 655368, 131102, 18, 655368, 131103, 18, 655368, 131104, 18, 655368, 131105, 18, 655368, 196634, 18, 655368, 196635, 18, 655368, 196636, 18, 655368, 196637, 18, 655368, 196638, 18, 655368, 196639, 18, 655368, 196640, 18, 655368, 196641, 18, 655368, 262170, 18, 655368, 262171, 18, 655368, 262172, 18, 655368, 262173, 18, 655368, 262174, 18, 655369, 262175, 18, 655366, 262176, 18, 655366, 262177, 18, 1441801, 327706, 18, 655366, 327707, 18, 655366, 327708, 18, 655366, 327709, 18, 655366, 327710, 18, 655366, 327713, 18, 1441797, 458752, 18, 655367, 458753, 18, 655367, 458754, 18, 655367, 458755, 18, 655367, 458756, 18, 655367, 458757, 18, 655367, 458758, 18, 655367, 458759, 18, 655367, 458760, 18, 655367, 458762, 18, 1441799, 458763, 18, 1441799, 458764, 18, 1441799, 524283, 18, 655367, 524284, 18, 655367, 524285, 18, 655367, 524286, 18, 655367, 524287, 18, 655367, -65510, 18, 655363, -65509, 18, 655363, -65508, 18, 655363, -65507, 18, 655363, -65506, 18, 655363, -65505, 18, 655363, -65504, 18, 655363, -65503, 18, 655363, 524287, 19, 655367, 65540, 65533, 3, 131076, 65533, 2, 131077, 65533, 3, 196611, 65533, 1048579, 196612, 65533, 6, 196613, 65533, 6, 196614, 65533, 655366, 196615, 65533, 655366, 196616, 65533, 655366, 196617, 65533, 655366, 196618, 65533, 7, 196619, 65533, 655366, 196620, 65533, 1441801, 262147, 65533, 1048578, 262156, 65533, 1441801, 327683, 65533, 1048584, 327692, 65533, 1441801, 393219, 65533, 1048584, 393228, 65533, 1441801, 458764, 65533, 1441801, 524300, 65533, 1441797, 65539, 65534, 1048579, 65540, 65534, 1048583, 65541, 65534, 4, 131075, 65534, 1048578, 131077, 65534, 5, 131078, 65534, 4, 196611, 65534, 1048578, 196614, 65534, 5, 196615, 65534, 7, 196616, 65534, 655370, 196617, 65534, 7, 196618, 65534, 7, 196619, 65534, 7, 196620, 65534, 1441800, 262147, 65534, 1048578, 262152, 65534, 655372, 262156, 65534, 1441800, 327683, 65534, 1048584, 327688, 65534, 655373, 327692, 65534, 1441794, 393219, 65534, 1048584, 393228, 65534, 1441794, 458753, 65534, 655367, 458754, 65534, 655367, 458764, 65534, 1441794, 524300, 65534, 1441798, 4, 65535, 2, 5, 65535, 2, 6, 65535, 2, 7, 65535, 2, 8, 65535, 2, 9, 65535, 2, 10, 65535, 2, 11, 65535, 2, 65539, 65535, 1048579, 65540, 65535, 5, 65541, 65535, 1048581, 65542, 65535, 4, 65543, 65535, 2, 65544, 65535, 2, 65545, 65535, 2, 65546, 65535, 2, 65547, 65535, 2, 131075, 65535, 1048578, 131078, 65535, 5, 131079, 65535, 9, 131080, 65535, 2, 131081, 65535, 2, 131082, 65535, 2, 131083, 65535, 2, 196611, 65535, 1048578, 196615, 65535, 5, 196616, 65535, 6, 196617, 65535, 6, 196618, 65535, 6, 196619, 65535, 6, 196620, 65535, 1441800, 262147, 65535, 1048578, 262156, 65535, 1441800, 327683, 65535, 1048584, 327692, 65535, 1441794, 393219, 65535, 1048584, 393228, 65535, 1441794, 458752, 65535, 655367, 458753, 65535, 655367, 458754, 65535, 655367, 458755, 65535, 655367, 458764, 65535, 1441794, 524287, 65535, 655367, 524300, 65535, 1441798, -65532, 65535, 2, -65531, 65535, 2, -65530, 65535, 2, -65529, 65535, 2, -65528, 65535, 2, -65527, 65535, 2, -65526, 65535, 2, -65525, 65535, 2 </int_array>
- </dictionary>
- <dictionary shared="false">
- <string> "_editor_clip_" </string>
- <int> 0 </int>
- <string> "_editor_floor_" </string>
- <vector3> 0, 2, 0 </vector3>
- </dictionary>
- <transform> 0.522923, 0.663002, -0.535706, -0.24539, 0.718971, 0.650281, 0.816294, -0.20859, 0.53866, 0, 0, 0 </transform>
- <int> 1 </int>
- <int> 0 </int>
- <real> 1.5 </real>
- <color> 1, 1, 1, 1 </color>
- <real> 0 </real>
- <real> 0.08 </real>
- <real> 0.5 </real>
- <real> 60 </real>
- <real> 1 </real>
- <resource name=""></resource> <int> 2 </int>
- <real> 40 </real>
- <real> 0.410558 </real>
- <resource resource_type="Environment" path="local://1"> </resource>
- <dictionary shared="false">
- <string> "_editor_collapsed" </string>
- <bool> True </bool>
- </dictionary>
- <resource resource_type="PackedScene" path="res://coin.scn"> </resource>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 18.5311, 2.85075, 5.24675 </transform>
- <dictionary shared="false">
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 0 </int>
- <string> "sources" </string>
- <array len="1" shared="false">
- <string> "res://coin.gd" </string>
- </array>
- </dictionary>
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "zoom" </string>
- <real> 1 </real>
- <string> "ofs" </string>
- <vector2> 1, 1 </vector2>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "fov" </string>
- <real> 400 </real>
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 1.361845 </real>
- <string> "x_rot" </string>
- <real> 0.0125 </real>
- <string> "y_rot" </string>
- <real> 12.050008 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> -0.00892573, 0.51052, -0.216081 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- </array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "znear" </string>
- <real> 0.1 </real>
- <string> "show_origin" </string>
- <bool> True </bool>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "3D" </string>
- </dictionary>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 18.5311, 2.85075, 7.24675 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 20.5311, 2.85075, 5.24675 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 20.5311, 2.85075, 7.24675 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 11.28, 11.0239 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 11.28, 13.0239 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 11.28, 11.0239 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 11.28, 13.0239 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 12.9027, 11.03 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 12.9027, 13.03 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 12.9027, 13.03 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 12.9027, 11.03 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 11.28, 15.0922 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 11.28, 17.0922 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 11.28, 17.0922 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 11.28, 15.0922 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 12.9027, 15.0983 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 12.9027, 17.0983 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 12.9027, 15.0983 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 12.9027, 17.0983 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 57.057, 4.14271, 26.9338 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 57.057, 4.14271, 28.9338 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 57.057, 5.76534, 26.9399 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 59.057, 5.76534, 28.9399 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 59.057, 5.76534, 26.9399 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 59.057, 4.14271, 28.9338 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 59.057, 4.14271, 26.9338 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 57.057, 5.76534, 28.9399 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 62.9108, 6.16547, 31.0899 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 64.9108, 7.7881, 31.096 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 62.9108, 6.16547, 33.0899 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 62.9108, 7.7881, 31.096 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 64.9108, 7.7881, 33.096 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 64.9108, 6.16547, 31.0899 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 64.9108, 6.16547, 33.0899 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 62.9108, 7.7881, 33.096 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 51.5614, 2.98252, 23.1775 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 53.5614, 4.60515, 23.1836 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 51.5614, 2.98252, 25.1775 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 53.5614, 2.98252, 23.1775 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 53.5614, 4.60515, 25.1836 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 51.5614, 4.60515, 23.1836 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 53.5614, 2.98252, 25.1775 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 51.5614, 4.60515, 25.1836 </transform>
- <resource resource_type="PackedScene" path="res://enemy.scn"> </resource>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 18.3062, 5.40827, 5.96938 </transform>
- <dictionary shared="false">
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 0 </int>
- <string> "sources" </string>
- <array len="2" shared="false">
- <string> "res://enemy.gd" </string>
- <string> "res://player.gd" </string>
- </array>
- </dictionary>
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "zoom" </string>
- <real> 1 </real>
- <string> "ofs" </string>
- <vector2> 1, 1 </vector2>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "fov" </string>
- <real> 400 </real>
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 7.403724 </real>
- <string> "x_rot" </string>
- <real> 0.25 </real>
- <string> "y_rot" </string>
- <real> 3.312502 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0.898236, 0.953557, 0.742913 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- </array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "znear" </string>
- <real> 0.1 </real>
- <string> "show_origin" </string>
- <bool> True </bool>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "Script" </string>
- </dictionary>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 64.1292, 5.40827, 17.1396 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 64.1292, 5.40827, 32.6128 </transform>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 55.5702, 5.40827, 32.6128 </transform>
- <resource resource_type="PackedScene" path="res://player.xml"> </resource>
- <transform> 0.0160676, 0, -0.999871, 0, 1, 0, 0.999871, 0, 0.0160676, 8.50167, 4.15811, 15.9334 </transform>
- <dictionary shared="false">
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 1 </int>
- <string> "sources" </string>
- <array len="2" shared="false">
- <string> "res://follow_camera.gd" </string>
- <string> "res://player.gd" </string>
- </array>
- </dictionary>
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "pixel_snap" </string>
- <bool> False </bool>
- <string> "zoom" </string>
- <real> 1 </real>
- <string> "ofs" </string>
- <vector2> -241, -19 </vector2>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "fov" </string>
- <real> 400 </real>
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 2.161076 </real>
- <string> "x_rot" </string>
- <real> 0.520797 </real>
- <string> "y_rot" </string>
- <real> 26.741669 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> -0.415811, 0.486899, 0.089334 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- </array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "znear" </string>
- <real> 0.1 </real>
- <string> "show_origin" </string>
- <bool> True </bool>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "3D" </string>
- </dictionary>
- </array>
- <string> "nodes" </string>
- <int_array len="873"> -1, -1, 1, 0, -1, 4, 2, 0, 3, 1, 4, 2, 5, 3, 0, 0, 0, 6, 6, -1, 14, 2, 0, 3, 1, 4, 2, 7, 4, 8, 5, 9, 5, 10, 6, 11, 7, 12, 2, 13, 2, 14, 2, 15, 8, 16, 9, 5, 10, 0, 0, 0, 17, 17, -1, 23, 2, 0, 3, 1, 18, 11, 4, 2, 19, 12, 20, 2, 21, 5, 22, 13, 23, 14, 24, 15, 25, 15, 26, 2, 27, 16, 28, 17, 29, 18, 30, 19, 31, 20, 32, 21, 33, 13, 34, 22, 35, 23, 36, 24, 37, 6, 0, 0, 0, 39, 38, -1, 4, 2, 0, 3, 1, 4, 2, 38, 25, 0, 0, 0, 41, 40, -1, 2, 2, 0, 5, 26, 0, 4, 0, 43, 42, 27, 4, 2, 0, 3, 1, 18, 28, 5, 29, 0, 4, 0, 43, 44, 27, 4, 2, 0, 3, 1, 18, 30, 5, 29, 0, 4, 0, 43, 45, 27, 4, 2, 0, 3, 1, 18, 31, 5, 29, 0, 4, 0, 43, 46, 27, 4, 2, 0, 3, 1, 18, 32, 5, 29, 0, 4, 0, 43, 47, 27, 4, 2, 0, 3, 1, 18, 33, 5, 29, 0, 4, 0, 43, 48, 27, 4, 2, 0, 3, 1, 18, 34, 5, 29, 0, 4, 0, 43, 49, 27, 4, 2, 0, 3, 1, 18, 35, 5, 29, 0, 4, 0, 43, 50, 27, 4, 2, 0, 3, 1, 18, 36, 5, 29, 0, 4, 0, 43, 51, 27, 4, 2, 0, 3, 1, 18, 37, 5, 29, 0, 4, 0, 43, 52, 27, 4, 2, 0, 3, 1, 18, 38, 5, 29, 0, 4, 0, 43, 53, 27, 4, 2, 0, 3, 1, 18, 39, 5, 29, 0, 4, 0, 43, 54, 27, 4, 2, 0, 3, 1, 18, 40, 5, 29, 0, 4, 0, 43, 55, 27, 4, 2, 0, 3, 1, 18, 41, 5, 29, 0, 4, 0, 43, 56, 27, 4, 2, 0, 3, 1, 18, 42, 5, 29, 0, 4, 0, 43, 57, 27, 4, 2, 0, 3, 1, 18, 43, 5, 29, 0, 4, 0, 43, 58, 27, 4, 2, 0, 3, 1, 18, 44, 5, 29, 0, 4, 0, 43, 59, 27, 4, 2, 0, 3, 1, 18, 45, 5, 29, 0, 4, 0, 43, 60, 27, 4, 2, 0, 3, 1, 18, 46, 5, 29, 0, 4, 0, 43, 61, 27, 4, 2, 0, 3, 1, 18, 47, 5, 29, 0, 4, 0, 43, 62, 27, 4, 2, 0, 3, 1, 18, 48, 5, 29, 0, 4, 0, 43, 63, 27, 4, 2, 0, 3, 1, 18, 49, 5, 29, 0, 4, 0, 43, 64, 27, 4, 2, 0, 3, 1, 18, 50, 5, 29, 0, 4, 0, 43, 65, 27, 4, 2, 0, 3, 1, 18, 51, 5, 29, 0, 4, 0, 43, 66, 27, 4, 2, 0, 3, 1, 18, 52, 5, 29, 0, 4, 0, 43, 67, 27, 4, 2, 0, 3, 1, 18, 53, 5, 29, 0, 4, 0, 43, 68, 27, 4, 2, 0, 3, 1, 18, 54, 5, 29, 0, 4, 0, 43, 69, 27, 4, 2, 0, 3, 1, 18, 55, 5, 29, 0, 4, 0, 43, 70, 27, 4, 2, 0, 3, 1, 18, 56, 5, 29, 0, 4, 0, 43, 71, 27, 4, 2, 0, 3, 1, 18, 57, 5, 29, 0, 4, 0, 43, 72, 27, 4, 2, 0, 3, 1, 18, 58, 5, 29, 0, 4, 0, 43, 73, 27, 4, 2, 0, 3, 1, 18, 59, 5, 29, 0, 4, 0, 43, 74, 27, 4, 2, 0, 3, 1, 18, 60, 5, 29, 0, 4, 0, 43, 75, 27, 4, 2, 0, 3, 1, 18, 61, 5, 29, 0, 4, 0, 43, 76, 27, 4, 2, 0, 3, 1, 18, 62, 5, 29, 0, 4, 0, 43, 77, 27, 4, 2, 0, 3, 1, 18, 63, 5, 29, 0, 4, 0, 43, 78, 27, 4, 2, 0, 3, 1, 18, 64, 5, 29, 0, 4, 0, 43, 79, 27, 4, 2, 0, 3, 1, 18, 65, 5, 29, 0, 4, 0, 43, 80, 27, 4, 2, 0, 3, 1, 18, 66, 5, 29, 0, 4, 0, 43, 81, 27, 4, 2, 0, 3, 1, 18, 67, 5, 29, 0, 4, 0, 43, 82, 27, 4, 2, 0, 3, 1, 18, 68, 5, 29, 0, 4, 0, 43, 83, 27, 4, 2, 0, 3, 1, 18, 69, 5, 29, 0, 4, 0, 43, 84, 27, 4, 2, 0, 3, 1, 18, 70, 5, 29, 0, 4, 0, 43, 85, 27, 4, 2, 0, 3, 1, 18, 71, 5, 29, 0, 4, 0, 43, 86, 27, 4, 2, 0, 3, 1, 18, 72, 5, 29, 0, 0, 0, 41, 87, -1, 1, 2, 0, 0, 49, 0, 89, 88, 73, 4, 2, 0, 3, 1, 18, 74, 5, 75, 0, 49, 0, 89, 90, 73, 4, 2, 0, 3, 1, 18, 76, 5, 75, 0, 49, 0, 89, 91, 73, 4, 2, 0, 3, 1, 18, 77, 5, 75, 0, 49, 0, 89, 92, 73, 4, 2, 0, 3, 1, 18, 78, 5, 75, 0, 0, 0, 89, 93, 79, 4, 2, 0, 3, 1, 18, 80, 5, 81, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
- </dictionary>
-
- </main_resource>
-</resource_file> \ No newline at end of file
diff --git a/demos/3d/platformer/tiles.scn b/demos/3d/platformer/tiles.scn
index ca804d2d09..4c3442dbeb 100644
--- a/demos/3d/platformer/tiles.scn
+++ b/demos/3d/platformer/tiles.scn
Binary files differ
diff --git a/demos/2d/polygon_path_finder/engine.cfg b/demos/3d/polygon_path_finder/engine.cfg
index 47450408af..47450408af 100644
--- a/demos/2d/polygon_path_finder/engine.cfg
+++ b/demos/3d/polygon_path_finder/engine.cfg
diff --git a/demos/2d/polygon_path_finder/icon.png b/demos/3d/polygon_path_finder/icon.png
index 643f5595ee..643f5595ee 100644
--- a/demos/2d/polygon_path_finder/icon.png
+++ b/demos/3d/polygon_path_finder/icon.png
Binary files differ
diff --git a/demos/2d/polygon_path_finder/poly_with_holes.scn b/demos/3d/polygon_path_finder/poly_with_holes.scn
index 6b340377b7..6b340377b7 100644
--- a/demos/2d/polygon_path_finder/poly_with_holes.scn
+++ b/demos/3d/polygon_path_finder/poly_with_holes.scn
Binary files differ
diff --git a/demos/2d/polygon_path_finder/polygonpathfinder.gd b/demos/3d/polygon_path_finder/polygonpathfinder.gd
index a0e71dd127..1e843043da 100644
--- a/demos/2d/polygon_path_finder/polygonpathfinder.gd
+++ b/demos/3d/polygon_path_finder/polygonpathfinder.gd
@@ -1,37 +1,38 @@
extends Spatial
+
func _ready():
var pf = PolygonPathFinder.new()
var points = Vector2Array()
var connections = IntArray()
- # poly 1
- points.push_back(Vector2(0, 0)) #0
- points.push_back(Vector2(10, 0)) #1
- points.push_back(Vector2(10, 10)) #2
- points.push_back(Vector2(0, 10)) #3
-
- connections.push_back(0) # connect vertex 0 ...
+ # Poly 1
+ points.push_back(Vector2(0, 0)) # 0
+ points.push_back(Vector2(10, 0)) # 1
+ points.push_back(Vector2(10, 10)) # 2
+ points.push_back(Vector2(0, 10)) # 3
+
+ connections.push_back(0) # Connect vertex 0...
connections.push_back(1) # ... to 1
drawLine(points[0], points[1], get_node("/root/Spatial/Polys"))
- connections.push_back(1) # connect vertex 1 ...
+ connections.push_back(1) # Connect vertex 1...
connections.push_back(2) # ... to 2
drawLine(points[1], points[2], get_node("/root/Spatial/Polys"))
- connections.push_back(2) # etc.
+ connections.push_back(2) # Etc.
connections.push_back(3)
drawLine(points[2], points[3], get_node("/root/Spatial/Polys"))
- connections.push_back(3) # connect vertex 3 ...
- connections.push_back(0) # back to vertex 0, to close the polygon
+ connections.push_back(3) # Connect vertex 3...
+ connections.push_back(0) # ... back to vertex 0, to close the polygon
drawLine(points[3], points[0], get_node("/root/Spatial/Polys"))
-
- # poly 2, as obstacle inside poly 1
- points.push_back(Vector2(2, 0.5)) #4
- points.push_back(Vector2(4, 0.5)) #5
- points.push_back(Vector2(4, 9.5)) #6
- points.push_back(Vector2(2, 9.5)) #7
-
+
+ # Poly 2, as obstacle inside poly 1
+ points.push_back(Vector2(2, 0.5)) # 4
+ points.push_back(Vector2(4, 0.5)) # 5
+ points.push_back(Vector2(4, 9.5)) # 6
+ points.push_back(Vector2(2, 9.5)) # 7
+
connections.push_back(4)
connections.push_back(5)
drawLine(points[4], points[5], get_node("/root/Spatial/Polys"))
@@ -44,24 +45,22 @@ func _ready():
connections.push_back(7)
connections.push_back(4)
drawLine(points[7], points[4], get_node("/root/Spatial/Polys"))
-
- print("points: ",points)
- print("connections: ",connections)
+ print("points: ", points)
+ print("connections: ", connections)
pf.setup(points, connections)
var path = pf.find_path(Vector2(1, 5), Vector2(8, 5))
var lastStep = null
- print("path: ",path)
+ print("path: ", path)
for step in path:
- print("step: ",step)
+ print("step: ", step)
if (lastStep != null):
var currPathSegment = Vector2Array()
drawLine(lastStep, step, get_node("/root/Spatial/Path"))
lastStep = step
-
func drawLine(pointA, pointB, immediateGeo):
@@ -76,5 +75,3 @@ func drawLine(pointA, pointB, immediateGeo):
im.add_vertex(Vector3(pointA.x, drawPosY, pointA.y))
im.add_vertex(Vector3(pointB.x, drawPosY, pointB.y))
im.end()
-
-
diff --git a/demos/3d/sat_test/box.scn b/demos/3d/sat_test/box.scn
index 8b02826ea7..f9c15839a2 100644
--- a/demos/3d/sat_test/box.scn
+++ b/demos/3d/sat_test/box.scn
Binary files differ
diff --git a/demos/3d/sat_test/capsule.scn b/demos/3d/sat_test/capsule.scn
index a4fe2b2b3f..db8ff43116 100644
--- a/demos/3d/sat_test/capsule.scn
+++ b/demos/3d/sat_test/capsule.scn
Binary files differ
diff --git a/demos/3d/sat_test/convex.scn b/demos/3d/sat_test/convex.scn
index 5f62beccaf..93e05338eb 100644
--- a/demos/3d/sat_test/convex.scn
+++ b/demos/3d/sat_test/convex.scn
Binary files differ
diff --git a/demos/3d/sat_test/engine.cfg b/demos/3d/sat_test/engine.cfg
index 82c688635d..e21c9b1eff 100644
--- a/demos/3d/sat_test/engine.cfg
+++ b/demos/3d/sat_test/engine.cfg
@@ -1,5 +1,5 @@
[application]
name="SAT Collision Test"
-main_scene="res://sat_test.xml"
+main_scene="res://sat_test.scn"
icon="res://icon.png"
diff --git a/demos/3d/sat_test/sat_test.scn b/demos/3d/sat_test/sat_test.scn
new file mode 100644
index 0000000000..0b25431202
--- /dev/null
+++ b/demos/3d/sat_test/sat_test.scn
Binary files differ
diff --git a/demos/3d/sat_test/sat_test.xml b/demos/3d/sat_test/sat_test.xml
deleted file mode 100644
index f11dec3292..0000000000
--- a/demos/3d/sat_test/sat_test.xml
+++ /dev/null
@@ -1,179 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="5" version="0.99" version_name="Godot Engine v0.99.3735-pre-beta">
- <ext_resource path="res://box.*" type="PackedScene"></ext_resource>
- <ext_resource path="res://sphere.*" type="PackedScene"></ext_resource>
- <ext_resource path="res://capsule.*" type="PackedScene"></ext_resource>
- <ext_resource path="res://convex.*" type="PackedScene"></ext_resource>
- <main_resource>
- <dictionary name="_bundled" shared="false">
- <string> "names" </string>
- <string_array len="30">
- <string> "Node" </string>
- <string> "__meta__" </string>
- <string> "sphere" </string>
- <string> "Spatial" </string>
- <string> "transform/local" </string>
- <string> "box" </string>
- <string> "convex" </string>
- <string> "Camera" </string>
- <string> "projection" </string>
- <string> "fov" </string>
- <string> "near" </string>
- <string> "far" </string>
- <string> "vaspect" </string>
- <string> "current" </string>
- <string> "visible_layers" </string>
- <string> "environment" </string>
- <string> "OmniLight" </string>
- <string> "layers" </string>
- <string> "params/energy" </string>
- <string> "colors/ambient" </string>
- <string> "colors/diffuse" </string>
- <string> "colors/specular" </string>
- <string> "shadow/shadow" </string>
- <string> "shadow/darkening" </string>
- <string> "shadow/z_offset" </string>
- <string> "shadow/z_slope_scale" </string>
- <string> "projector" </string>
- <string> "operator" </string>
- <string> "params/radius" </string>
- <string> "params/attenuation" </string>
- </string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
- <string> "node_count" </string>
- <int> 7 </int>
- <string> "variants" </string>
- <array len="26" shared="false">
- <dictionary shared="false">
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "zoom" </string>
- <real> 1 </real>
- <string> "ofs" </string>
- <vector2> 1, 1 </vector2>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "fov" </string>
- <real> 400 </real>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 34.508423 </real>
- <string> "x_rot" </string>
- <real> 0.7 </real>
- <string> "y_rot" </string>
- <real> 1.262503 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 13.3659, 3.22136, 2.27417 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- </array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> False </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "znear" </string>
- <real> 0.1 </real>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "3D" </string>
- </dictionary>
- <resource resource_type="PackedScene" path="res://sphere.*"> </resource>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -2.93877 </transform>
- <resource resource_type="PackedScene" path="res://box.*"> </resource>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 13.5356, 0, -3.40082 </transform>
- <resource resource_type="PackedScene" path="res://convex.*"> </resource>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 22.8626, 0, -2.50073 </transform>
- <resource resource_type="PackedScene" path="res://capsule.*"> </resource>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 28.4061, 0, -2.76809 </transform>
- <transform> 1, 0, 0, 0, 0.819152, 0.573576, 0, -0.573576, 0.819152, 14.482, 11.1225, 20.5858 </transform>
- <int> 0 </int>
- <real> 60 </real>
- <real> 0.1 </real>
- <real> 100 </real>
- <bool> False </bool>
- <int> -1 </int>
- <resource name=""></resource> <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 66.4797, 0, 10.4696 </transform>
- <int> 1 </int>
- <real> 1.5 </real>
- <color> 0.355828, 0.346354, 0.329995, 1 </color>
- <color> 1, 1, 1, 1 </color>
- <real> 0 </real>
- <real> 0.05 </real>
- <real> 500 </real>
- <real> 0.535887 </real>
- </array>
- <string> "nodes" </string>
- <int_array len="105"> -1, -1, 0, 0, -1, 1, 1, 0, 0, 0, 0, 3, 2, 1, 1, 4, 2, 0, 0, 0, 3, 5, 3, 1, 4, 4, 0, 0, 0, 3, 6, 5, 1, 4, 6, 0, 0, 0, 3, 3, 7, 1, 4, 8, 0, 0, 0, 7, 7, -1, 9, 4, 9, 8, 10, 9, 11, 10, 12, 11, 13, 12, 14, 13, 14, 14, 15, 15, 16, 0, 0, 0, 16, 16, -1, 14, 4, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 21, 22, 14, 23, 22, 24, 23, 25, 22, 26, 16, 27, 10, 28, 24, 29, 25, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
- </dictionary>
-
- </main_resource>
-</resource_file> \ No newline at end of file
diff --git a/demos/3d/sat_test/shapes.scn b/demos/3d/sat_test/shapes.scn
index 584237b89d..bf10be0a59 100644
--- a/demos/3d/sat_test/shapes.scn
+++ b/demos/3d/sat_test/shapes.scn
Binary files differ
diff --git a/demos/3d/sat_test/sphere.scn b/demos/3d/sat_test/sphere.scn
index dd49c914b3..e40c3bd42d 100644
--- a/demos/3d/sat_test/sphere.scn
+++ b/demos/3d/sat_test/sphere.scn
Binary files differ
diff --git a/demos/3d/shader_materials/shader_materials.scn b/demos/3d/shader_materials/shader_materials.scn
index 243c6c8f06..7eb43cda0d 100644
--- a/demos/3d/shader_materials/shader_materials.scn
+++ b/demos/3d/shader_materials/shader_materials.scn
Binary files differ
diff --git a/demos/3d/truck_town/car_base.scn b/demos/3d/truck_town/car_base.scn
index d62c8dcb29..acfbfae162 100644
--- a/demos/3d/truck_town/car_base.scn
+++ b/demos/3d/truck_town/car_base.scn
Binary files differ
diff --git a/demos/3d/truck_town/car_select.gd b/demos/3d/truck_town/car_select.gd
index 00b4d853b8..4efcf63426 100644
--- a/demos/3d/truck_town/car_select.gd
+++ b/demos/3d/truck_town/car_select.gd
@@ -1,40 +1,30 @@
extends Control
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-func _ready():
- # Initalization here
- pass
-
-var town=null
+# Member variables
+var town = null
func _back():
-
town.queue_free()
show()
-
-func _load_scene(car):
+func _load_scene(car):
var tt = load(car).instance()
tt.set_name("car")
town = load("res://truck_scene.scn").instance()
town.get_node("instance_pos").add_child(tt)
- town.get_node("back").connect("pressed",self,"_back")
+ town.get_node("back").connect("pressed", self, "_back")
get_parent().add_child(town)
hide()
-func _on_van_1_pressed():
+func _on_van_1_pressed():
_load_scene("res://car_base.scn")
func _on_van_2_pressed():
-
_load_scene("res://trailer_truck.scn")
diff --git a/demos/3d/truck_town/car_select.scn b/demos/3d/truck_town/car_select.scn
index 024adf1423..d838e995b2 100644
--- a/demos/3d/truck_town/car_select.scn
+++ b/demos/3d/truck_town/car_select.scn
Binary files differ
diff --git a/demos/3d/truck_town/crane.scn b/demos/3d/truck_town/crane.scn
index 2c4645af69..dfddd97882 100644
--- a/demos/3d/truck_town/crane.scn
+++ b/demos/3d/truck_town/crane.scn
Binary files differ
diff --git a/demos/3d/truck_town/follow_camera.gd b/demos/3d/truck_town/follow_camera.gd
index cf7172d7bb..7c6a0a2ba6 100644
--- a/demos/3d/truck_town/follow_camera.gd
+++ b/demos/3d/truck_town/follow_camera.gd
@@ -1,69 +1,57 @@
extends Camera
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-var collision_exception=[]
-export var min_distance=0.5
-export var max_distance=4.0
-export var angle_v_adjust=0.0
-export var autoturn_ray_aperture=25
-export var autoturn_speed=50
+# Member variables
+var collision_exception = []
+export var min_distance = 0.5
+export var max_distance = 4.0
+export var angle_v_adjust = 0.0
+export var autoturn_ray_aperture = 25
+export var autoturn_speed = 50
var max_height = 2.0
var min_height = 0
+
func _fixed_process(dt):
- var target = get_parent().get_global_transform().origin
+ var target = get_parent().get_global_transform().origin
var pos = get_global_transform().origin
- var up = Vector3(0,1,0)
+ var up = Vector3(0, 1, 0)
var delta = pos - target
- #regular delta follow
+ # Regular delta follow
- #check ranges
-
+ # Check ranges
if (delta.length() < min_distance):
- delta = delta.normalized() * min_distance
+ delta = delta.normalized()*min_distance
elif (delta.length() > max_distance):
- delta = delta.normalized() * max_distance
+ delta = delta.normalized()*max_distance
- #check upper and lower height
+ # Check upper and lower height
if ( delta.y > max_height):
delta.y = max_height
if ( delta.y < min_height):
delta.y = min_height
-
+
pos = target + delta
- look_at_from_pos(pos,target,up)
+ look_at_from_pos(pos, target, up)
- #turn a little up or down
+ # Turn a little up or down
var t = get_transform()
- t.basis = Matrix3(t.basis[0],deg2rad(angle_v_adjust)) * t.basis
+ t.basis = Matrix3(t.basis[0], deg2rad(angle_v_adjust))*t.basis
set_transform(t)
-
-
-func _ready():
-#find collision exceptions for ray
+func _ready():
+ # Find collision exceptions for ray
var node = self
while(node):
if (node extends RigidBody):
collision_exception.append(node.get_rid())
break
else:
- node=node.get_parent()
- # Initalization here
+ node = node.get_parent()
set_fixed_process(true)
- #this detaches the camera transform from the parent spatial node
+ # This detaches the camera transform from the parent spatial node
set_as_toplevel(true)
-
-
-
-
-
-
diff --git a/demos/3d/truck_town/trailer_truck.scn b/demos/3d/truck_town/trailer_truck.scn
index 0131e9e3a2..6fcf83e270 100644
--- a/demos/3d/truck_town/trailer_truck.scn
+++ b/demos/3d/truck_town/trailer_truck.scn
Binary files differ
diff --git a/demos/3d/truck_town/truck_scene.scn b/demos/3d/truck_town/truck_scene.scn
index a02ce259c1..0c1be13ce2 100644
--- a/demos/3d/truck_town/truck_scene.scn
+++ b/demos/3d/truck_town/truck_scene.scn
Binary files differ
diff --git a/demos/3d/truck_town/trucktown.scn b/demos/3d/truck_town/trucktown.scn
index 57a84315ee..4a8f7e7e52 100644
--- a/demos/3d/truck_town/trucktown.scn
+++ b/demos/3d/truck_town/trucktown.scn
Binary files differ
diff --git a/demos/3d/truck_town/vehicle.gd b/demos/3d/truck_town/vehicle.gd
index 1aa7f0faa2..c4224577c6 100644
--- a/demos/3d/truck_town/vehicle.gd
+++ b/demos/3d/truck_town/vehicle.gd
@@ -1,54 +1,45 @@
extends VehicleBody
-# member variables here, example:
-# var a=2
-# var b="textvar"
+# Member variables
+const STEER_SPEED = 1
+const STEER_LIMIT = 0.4
+var steer_angle = 0
+var steer_target = 0
-const STEER_SPEED=1
-const STEER_LIMIT=0.4
+export var engine_force = 40
-var steer_angle=0
-var steer_target=0
-
-
-export var engine_force=40
func _fixed_process(delta):
-
-
if (Input.is_action_pressed("ui_left")):
- steer_target=-STEER_LIMIT
+ steer_target = -STEER_LIMIT
elif (Input.is_action_pressed("ui_right")):
- steer_target=STEER_LIMIT
+ steer_target = STEER_LIMIT
else:
- steer_target=0
-
+ steer_target = 0
+
if (Input.is_action_pressed("ui_up")):
set_engine_force(engine_force)
else:
set_engine_force(0)
-
+
if (Input.is_action_pressed("ui_down")):
set_brake(1)
else:
set_brake(0.0)
-
-
+
if (steer_target < steer_angle):
steer_angle -= STEER_SPEED*delta
if (steer_target > steer_angle):
- steer_angle=steer_target
+ steer_angle = steer_target
elif (steer_target > steer_angle):
steer_angle += STEER_SPEED*delta
if (steer_target < steer_angle):
- steer_angle=steer_target
-
+ steer_angle = steer_target
+
set_steering(steer_angle)
-func _ready():
- # Initalization here
- set_fixed_process(true)
- pass
+func _ready():
+ set_fixed_process(true)
diff --git a/demos/gui/drag_and_drop/drag_and_drop.scn b/demos/gui/drag_and_drop/drag_and_drop.scn
index 94a25cc53e..9dec254ef7 100644
--- a/demos/gui/drag_and_drop/drag_and_drop.scn
+++ 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
index 21a737ce1a..719c42fe8f 100644
--- a/demos/gui/drag_and_drop/drag_drop_script.gd
+++ b/demos/gui/drag_and_drop/drag_drop_script.gd
@@ -2,23 +2,19 @@
extends ColorPickerButton
-#virtual function
func get_drag_data(pos):
-
- #use another colorpicker as drag preview
+ # Use another colorpicker as drag preview
var cpb = ColorPickerButton.new()
- cpb.set_color( get_color() )
- cpb.set_size(Vector2(50,50))
+ cpb.set_color(get_color())
+ cpb.set_size(Vector2(50, 50))
set_drag_preview(cpb)
- #return color as drag data
+ # Return color as drag data
return get_color()
-#virtual function
+
func can_drop_data(pos, data):
- return typeof(data)==TYPE_COLOR
+ return typeof(data) == TYPE_COLOR
+
-#virtual function
func drop_data(pos, data):
set_color(data)
-
-
diff --git a/demos/gui/input_mapping/controls.gd b/demos/gui/input_mapping/controls.gd
index 6ca059c812..3cee6e6871 100644
--- a/demos/gui/input_mapping/controls.gd
+++ b/demos/gui/input_mapping/controls.gd
@@ -1,3 +1,6 @@
+
+extends Control
+
# Note for the reader:
#
# This demo conveniently uses the same names for actions and for the container nodes
@@ -9,12 +12,12 @@
# action and the node, e.g.:
# button.connect("pressed", self, "wait_for_input", [ button, action ])
-extends Control
-
+# Member variables
var player_actions = [ "move_up", "move_down", "move_left", "move_right", "jump" ]
var action # To register the action the UI is currently handling
var button # Button node corresponding to the above action
+
func wait_for_input(action_bind):
action = action_bind
# See note at the beginning of the script
@@ -22,6 +25,7 @@ func wait_for_input(action_bind):
get_node("contextual_help").set_text("Press a key to assign to the '" + action + "' action.")
set_process_input(true)
+
func _input(event):
# Handle the first pressed key
if (event.type == InputEvent.KEY):
@@ -39,6 +43,7 @@ func _input(event):
# Add the new key binding
InputMap.action_add_event(action, event)
+
func _ready():
# Initialise each button with the default key binding from InputMap
var input_event
diff --git a/demos/gui/input_mapping/controls.scn b/demos/gui/input_mapping/controls.scn
index 276712ba22..98cbbca464 100644
--- a/demos/gui/input_mapping/controls.scn
+++ b/demos/gui/input_mapping/controls.scn
Binary files differ
diff --git a/demos/gui/rich_text_bbcode/rich_text_bbcode.gd b/demos/gui/rich_text_bbcode/rich_text_bbcode.gd
index 30fac1f729..79a08c1303 100644
--- a/demos/gui/rich_text_bbcode/rich_text_bbcode.gd
+++ b/demos/gui/rich_text_bbcode/rich_text_bbcode.gd
@@ -1,17 +1,6 @@
extends Panel
-# member variables here, example:
-# var a=2
-# var b="textvar"
-func _ready():
- # Initialization here
- pass
-
-
-
-
-func _on_RichTextLabel_meta_clicked( meta ):
+func _on_RichTextLabel_meta_clicked(meta):
OS.shell_open(meta)
- pass # replace with function body
diff --git a/demos/gui/rich_text_bbcode/rich_text_bbcode.scn b/demos/gui/rich_text_bbcode/rich_text_bbcode.scn
index 081338fd91..c908d44dc3 100644
--- a/demos/gui/rich_text_bbcode/rich_text_bbcode.scn
+++ b/demos/gui/rich_text_bbcode/rich_text_bbcode.scn
Binary files differ
diff --git a/demos/gui/translation/controls.gd b/demos/gui/translation/controls.gd
index f8403f49a7..ae2e26362b 100644
--- a/demos/gui/translation/controls.gd
+++ b/demos/gui/translation/controls.gd
@@ -1,20 +1,9 @@
extends Panel
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-func _ready():
- # Initialization here
- pass
-
-
-
func _on_back_pressed():
var s = load("res://main.scn")
var si = s.instance()
get_parent().add_child(si)
queue_free()
- pass # replace with function body
diff --git a/demos/gui/translation/controls.scn b/demos/gui/translation/controls.scn
index 66e6d47702..055ac90b9b 100644
--- a/demos/gui/translation/controls.scn
+++ b/demos/gui/translation/controls.scn
Binary files differ
diff --git a/demos/gui/translation/main.gd b/demos/gui/translation/main.gd
index bf3c0c0840..c3e788f82b 100644
--- a/demos/gui/translation/main.gd
+++ b/demos/gui/translation/main.gd
@@ -1,31 +1,21 @@
extends Panel
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-func _ready():
- # Initialization here
- pass
-
-
func _goto_scene():
var s = load("res://controls.scn")
var si = s.instance()
get_parent().add_child(si)
queue_free()
- pass
func _on_system_pressed():
- #will autodetect based on system, then fall back
- #to english if not found
+ # Will autodetect based on system, then fall back
+ # to english if not found
_goto_scene()
-#NOTE: Changling locale will not change the text in the controls,
-# The scene must be reloaded for changes to take effect.
+# NOTE: Changing locale will not change the text in the controls,
+# The scene must be reloaded for changes to take effect.
func _on_english_pressed():
TranslationServer.set_locale("en")
diff --git a/demos/gui/translation/main.scn b/demos/gui/translation/main.scn
index 76c9ba7b45..8fc0b4ffb2 100644
--- a/demos/gui/translation/main.scn
+++ b/demos/gui/translation/main.scn
Binary files differ
diff --git a/demos/misc/autoload/global.gd b/demos/misc/autoload/global.gd
index d1bd45461f..735995e806 100644
--- a/demos/misc/autoload/global.gd
+++ b/demos/misc/autoload/global.gd
@@ -1,43 +1,36 @@
extends Node
-var current_scene = null
+# Changing scenes is most easily done using the functions `change_scene`
+# and `change_scene_to` of the SceneTree. This script demonstrates how to
+# change scenes without those helpers.
func goto_scene(path):
-
# This function will usually be called from a signal callback,
# or some other function from the running scene.
# Deleting the current scene at this point might be
# a bad idea, because it may be inside of a callback or function of it.
# The worst case will be a crash or unexpected behavior.
-
+
# The way around this is deferring the load to a later time, when
# it is ensured that no code from the current scene is running:
-
+
call_deferred("_deferred_goto_scene",path)
func _deferred_goto_scene(path):
-
- # Immediately free the current scene,
- # there is no risk here.
- current_scene.free()
-
+ # Immediately free the current scene, there is no risk here.
+ get_tree().get_current_scene().free()
+
# Load new scene
- var s = ResourceLoader.load(path)
-
+ var packed_scene = ResourceLoader.load(path)
+
# Instance the new scene
- current_scene = s.instance()
-
- # Add it to the active scene, as child of root
- get_tree().get_root().add_child(current_scene)
-
-
-func _ready():
- # Get the current scene, the first time.
- # it is always the last child of root,
- # after the autoloaded nodes.
-
- var root = get_tree().get_root()
- current_scene = root.get_child( root.get_child_count() -1 )
+ var instanced_scene = packed_scene.instance()
+
+ # Add it to the scene tree, as direct child of root
+ get_tree().get_root().add_child(instanced_scene)
+
+ # Set it as the current scene, only after it has been added to the tree
+ get_tree().set_current_scene(instanced_scene)
diff --git a/demos/misc/autoload/scene_a.gd b/demos/misc/autoload/scene_a.gd
index 21a6a84eb9..03da86d9a0 100644
--- a/demos/misc/autoload/scene_a.gd
+++ b/demos/misc/autoload/scene_a.gd
@@ -1,17 +1,5 @@
-
extends Panel
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-func _ready():
- # Initalization here
- pass
-
-
-
func _on_goto_scene_pressed():
get_node("/root/global").goto_scene("res://scene_b.scn")
- pass # replace with function body
diff --git a/demos/misc/autoload/scene_a.scn b/demos/misc/autoload/scene_a.scn
index 61727a57ba..eff314e29d 100644
--- a/demos/misc/autoload/scene_a.scn
+++ b/demos/misc/autoload/scene_a.scn
Binary files differ
diff --git a/demos/misc/autoload/scene_b.gd b/demos/misc/autoload/scene_b.gd
index 4a88fddda9..dea8c4623f 100644
--- a/demos/misc/autoload/scene_b.gd
+++ b/demos/misc/autoload/scene_b.gd
@@ -1,17 +1,5 @@
-
extends Panel
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-func _ready():
- # Initalization here
- pass
-
-
-
func _on_goto_scene_pressed():
get_node("/root/global").goto_scene("res://scene_a.scn")
- pass # replace with function body
diff --git a/demos/misc/autoload/scene_b.scn b/demos/misc/autoload/scene_b.scn
index ae09eeff88..4cdb03e90e 100644
--- a/demos/misc/autoload/scene_b.scn
+++ b/demos/misc/autoload/scene_b.scn
Binary files differ
diff --git a/demos/misc/instancing/ball.scn b/demos/misc/instancing/ball.scn
index 81c222a306..4d6367885e 100644
--- a/demos/misc/instancing/ball.scn
+++ b/demos/misc/instancing/ball.scn
Binary files differ
diff --git a/demos/misc/instancing/container.scn b/demos/misc/instancing/container.scn
index 9a365ac494..0f65daa2ca 100644
--- a/demos/misc/instancing/container.scn
+++ b/demos/misc/instancing/container.scn
Binary files differ
diff --git a/demos/misc/joysticks/diagram.png b/demos/misc/joysticks/diagram.png
new file mode 100644
index 0000000000..3f8ba1f973
--- /dev/null
+++ b/demos/misc/joysticks/diagram.png
Binary files differ
diff --git a/demos/misc/joysticks/engine.cfg b/demos/misc/joysticks/engine.cfg
index 71ac91000e..79cda1eeb4 100644
--- a/demos/misc/joysticks/engine.cfg
+++ b/demos/misc/joysticks/engine.cfg
@@ -6,5 +6,5 @@ icon="res://icon.png"
[display]
-width=260
+width=550
height=300
diff --git a/demos/misc/joysticks/indicators.png b/demos/misc/joysticks/indicators.png
new file mode 100644
index 0000000000..90fee48498
--- /dev/null
+++ b/demos/misc/joysticks/indicators.png
Binary files differ
diff --git a/demos/misc/joysticks/joysticks.gd b/demos/misc/joysticks/joysticks.gd
index d359e993e6..f5bc1bddad 100644
--- a/demos/misc/joysticks/joysticks.gd
+++ b/demos/misc/joysticks/joysticks.gd
@@ -8,33 +8,46 @@ extends Node2D
#
# Licensed under the MIT license
+# Member variables
var joy_num
var cur_joy
var axis_value
var btn_state
-func _ready():
- set_process_input(true)
+const DEADZONE = 0.2
-func _input(ev):
- # get the joystick device number from the spinbox
+func _fixed_process(delta):
+ # Get the joystick device number from the spinbox
joy_num = get_node("joy_num").get_value()
-
- # display the name of the joystick if we haven't already
+
+ # Display the name of the joystick if we haven't already
if joy_num != cur_joy:
cur_joy = joy_num
- get_node("joy_name").set_text( Input.get_joy_name(joy_num) )
-
- # loop through the axes and show their current values
- for axis in range(0,8):
- axis_value = Input.get_joy_axis(joy_num,axis)
- get_node("axis_prog"+str(axis)).set_value(100*axis_value)
- get_node("axis_val"+str(axis)).set_text(str(axis_value))
-
- # loop through the buttons and highlight the ones that are pressed
- for btn in range(0,17):
+ get_node("joy_name").set_text(Input.get_joy_name(joy_num))
+
+ # Loop through the axes and show their current values
+ for axis in range(0, 8):
+ axis_value = Input.get_joy_axis(joy_num, axis)
+ get_node("axis_prog" + str(axis)).set_value(100*axis_value)
+ get_node("axis_val" + str(axis)).set_text(str(axis_value))
+ if (axis < 4):
+ if (abs(axis_value) < DEADZONE):
+ get_node("diagram/axes/" + str(axis) + "+").hide()
+ get_node("diagram/axes/" + str(axis) + "-").hide()
+ elif (axis_value > 0):
+ get_node("diagram/axes/" + str(axis) + "+").show()
+ else:
+ get_node("diagram/axes/" + str(axis) + "-").show()
+
+ # Loop through the buttons and highlight the ones that are pressed
+ for btn in range(0, 16):
btn_state = 1
if (Input.is_joy_button_pressed(joy_num, btn)):
- get_node("btn"+str(btn)).add_color_override("font_color",Color(1,1,1,1))
+ get_node("btn" + str(btn)).add_color_override("font_color", Color(1, 1, 1, 1))
+ get_node("diagram/buttons/" + str(btn)).show()
else:
- get_node("btn"+str(btn)).add_color_override("font_color",Color(0.2,0.1,0.3,1))
+ get_node("btn" + str(btn)).add_color_override("font_color", Color(0.2, 0.1, 0.3, 1))
+ get_node("diagram/buttons/" + str(btn)).hide()
+
+func _ready():
+ set_fixed_process(true)
diff --git a/demos/misc/joysticks/joysticks.scn b/demos/misc/joysticks/joysticks.scn
index 5dbd7f49bf..3e0f326a0d 100644
--- a/demos/misc/joysticks/joysticks.scn
+++ b/demos/misc/joysticks/joysticks.scn
Binary files differ
diff --git a/demos/misc/joysticks/jsdiagram.xscn b/demos/misc/joysticks/jsdiagram.xscn
new file mode 100644
index 0000000000..537ad30278
--- /dev/null
+++ b/demos/misc/joysticks/jsdiagram.xscn
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<resource_file type="PackedScene" subresource_count="3" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+ <ext_resource path="res://indicators.png" type="Texture" index="1"></ext_resource>
+ <ext_resource path="res://diagram.png" type="Texture" index="0"></ext_resource>
+ <main_resource>
+ <dictionary name="_bundled" shared="false">
+ <string> "conn_count" </string>
+ <int> 0 </int>
+ <string> "conns" </string>
+ <int_array len="0"> </int_array>
+ <string> "editable_instances" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "names" </string>
+ <string_array len="37">
+ <string> "diagram" </string>
+ <string> "transform/pos" </string>
+ <string> "transform/scale" </string>
+ <string> "texture" </string>
+ <string> "__meta__" </string>
+ <string> "Sprite" </string>
+ <string> "buttons" </string>
+ <string> "Node2D" </string>
+ <string> "0" </string>
+ <string> "region" </string>
+ <string> "region_rect" </string>
+ <string> "1" </string>
+ <string> "2" </string>
+ <string> "3" </string>
+ <string> "4" </string>
+ <string> "5" </string>
+ <string> "6" </string>
+ <string> "flip_h" </string>
+ <string> "7" </string>
+ <string> "8" </string>
+ <string> "9" </string>
+ <string> "10" </string>
+ <string> "11" </string>
+ <string> "12" </string>
+ <string> "13" </string>
+ <string> "flip_v" </string>
+ <string> "14" </string>
+ <string> "15" </string>
+ <string> "axes" </string>
+ <string> "0-" </string>
+ <string> "0+" </string>
+ <string> "1-" </string>
+ <string> "1+" </string>
+ <string> "3-" </string>
+ <string> "3+" </string>
+ <string> "2-" </string>
+ <string> "2+" </string>
+ </string_array>
+ <string> "node_count" </string>
+ <int> 27 </int>
+ <string> "node_paths" </string>
+ <array len="0" shared="false">
+ </array>
+ <string> "nodes" </string>
+ <int_array len="453"> -1, -1, 5, 0, -1, 4, 1, 0, 2, 1, 3, 2, 4, 3, 0, 0, 0, 7, 6, -1, 1, 4, 4, 0, 1, 0, 5, 8, -1, 5, 1, 5, 2, 6, 3, 7, 9, 8, 10, 9, 0, 1, 0, 5, 11, -1, 5, 1, 10, 2, 6, 3, 7, 9, 8, 10, 9, 0, 1, 0, 5, 12, -1, 5, 1, 11, 2, 6, 3, 7, 9, 8, 10, 9, 0, 1, 0, 5, 13, -1, 5, 1, 12, 2, 6, 3, 7, 9, 8, 10, 9, 0, 1, 0, 5, 14, -1, 5, 1, 13, 2, 14, 3, 7, 9, 8, 10, 15, 0, 1, 0, 5, 15, -1, 5, 1, 16, 2, 14, 3, 7, 9, 8, 10, 15, 0, 1, 0, 5, 16, -1, 6, 1, 17, 2, 18, 3, 7, 17, 8, 9, 8, 10, 19, 0, 1, 0, 5, 18, -1, 5, 1, 20, 2, 18, 3, 7, 9, 8, 10, 19, 0, 1, 0, 5, 19, -1, 5, 1, 21, 2, 6, 3, 7, 9, 8, 10, 9, 0, 1, 0, 5, 20, -1, 5, 1, 22, 2, 6, 3, 7, 9, 8, 10, 9, 0, 1, 0, 5, 21, -1, 5, 1, 23, 2, 24, 3, 7, 9, 8, 10, 9, 0, 1, 0, 5, 22, -1, 5, 1, 25, 2, 24, 3, 7, 9, 8, 10, 9, 0, 1, 0, 5, 23, -1, 5, 1, 26, 2, 6, 3, 7, 9, 8, 10, 27, 0, 1, 0, 5, 24, -1, 6, 1, 28, 2, 6, 3, 7, 25, 8, 9, 8, 10, 27, 0, 1, 0, 5, 26, -1, 5, 1, 29, 2, 6, 3, 7, 9, 8, 10, 30, 0, 1, 0, 5, 27, -1, 6, 1, 31, 2, 6, 3, 7, 17, 8, 9, 8, 10, 30, 0, 0, 0, 7, 28, -1, 0, 0, 18, 0, 5, 29, -1, 5, 1, 32, 2, 6, 3, 7, 9, 8, 10, 30, 0, 18, 0, 5, 30, -1, 6, 1, 33, 2, 6, 3, 7, 17, 8, 9, 8, 10, 30, 0, 18, 0, 5, 31, -1, 5, 1, 34, 2, 6, 3, 7, 9, 8, 10, 27, 0, 18, 0, 5, 32, -1, 6, 1, 35, 2, 6, 3, 7, 25, 8, 9, 8, 10, 27, 0, 18, 0, 5, 33, -1, 5, 1, 36, 2, 6, 3, 7, 9, 8, 10, 27, 0, 18, 0, 5, 34, -1, 6, 1, 37, 2, 6, 3, 7, 25, 8, 9, 8, 10, 27, 0, 18, 0, 5, 35, -1, 5, 1, 38, 2, 6, 3, 7, 9, 8, 10, 30, 0, 18, 0, 5, 36, -1, 6, 1, 39, 2, 6, 3, 7, 17, 8, 9, 8, 10, 30, 0 </int_array>
+ <string> "variants" </string>
+ <array len="40" shared="false">
+ <vector2> 368.635, 155.289 </vector2>
+ <vector2> 0.432859, 0.446287 </vector2>
+ <resource external="0"> </resource>
+ <dictionary shared="false">
+ <string> "__editor_plugin_screen__" </string>
+ <string> "2D" </string>
+ </dictionary>
+ <dictionary shared="false">
+ <string> "_editor_collapsed" </string>
+ <bool> True </bool>
+ </dictionary>
+ <vector2> 147.73, 120.925 </vector2>
+ <vector2> 0.9, 0.9 </vector2>
+ <resource external="1"> </resource>
+ <bool> True </bool>
+ <rect2> 0, 0, 45, 45 </rect2>
+ <vector2> 185.769, 82.4874 </vector2>
+ <vector2> 112.377, 82.4874 </vector2>
+ <vector2> 149.073, 47.3293 </vector2>
+ <vector2> -161.038, -158.037 </vector2>
+ <vector2> 5.3348, 3.35512 </vector2>
+ <rect2> 10, 10, 10, 10 </rect2>
+ <vector2> 159.362, -156.977 </vector2>
+ <vector2> -159.349, -221.878 </vector2>
+ <vector2> 1.0458, 2.16952 </vector2>
+ <rect2> 0, 0, 45, 22 </rect2>
+ <vector2> 156.677, -220.11 </vector2>
+ <vector2> -67.5308, 164.422 </vector2>
+ <vector2> 75.8825, 167.363 </vector2>
+ <vector2> -46.6707, 52.702 </vector2>
+ <vector2> 0.810497, 0.57205 </vector2>
+ <vector2> 56.2581, 54.4382 </vector2>
+ <vector2> -139.402, 46.8295 </vector2>
+ <rect2> 50, 0, 54, 14 </rect2>
+ <vector2> -139.838, 115.789 </vector2>
+ <vector2> -172.262, 81.8793 </vector2>
+ <rect2> 50, 0, 14, 54 </rect2>
+ <vector2> -105.085, 81.0326 </vector2>
+ <vector2> -94.4295, 164.932 </vector2>
+ <vector2> -40.3475, 164.509 </vector2>
+ <vector2> -67.6802, 137.926 </vector2>
+ <vector2> -67.4618, 192.915 </vector2>
+ <vector2> 76.6557, 140.986 </vector2>
+ <vector2> 76.0009, 195.339 </vector2>
+ <vector2> 48.8152, 167.145 </vector2>
+ <vector2> 102.899, 167.857 </vector2>
+ </array>
+ <string> "version" </string>
+ <int> 2 </int>
+ </dictionary>
+
+ </main_resource>
+</resource_file> \ No newline at end of file
diff --git a/demos/misc/pause/spinpause.gd b/demos/misc/pause/spinpause.gd
index 1b8f8388f0..ea5617c06f 100644
--- a/demos/misc/pause/spinpause.gd
+++ b/demos/misc/pause/spinpause.gd
@@ -11,5 +11,3 @@ func _on_pause_pressed():
func _on_unpause_pressed():
get_node("pause_popup").hide()
get_tree().set_pause(false)
-
-
diff --git a/demos/misc/pause/spinpause.scn b/demos/misc/pause/spinpause.scn
index a3835c4374..2cbe85ec9a 100644
--- a/demos/misc/pause/spinpause.scn
+++ b/demos/misc/pause/spinpause.scn
Binary files differ
diff --git a/demos/misc/regex/regex.gd b/demos/misc/regex/regex.gd
index 409b4cab05..98e5ca8828 100644
--- a/demos/misc/regex/regex.gd
+++ b/demos/misc/regex/regex.gd
@@ -1,11 +1,15 @@
+
extends VBoxContainer
+# Member variables
var regex = RegEx.new()
+
func update_expression(text):
regex.compile(text)
update_text()
+
func update_text():
var text = get_node("Text").get_text()
var list = get_node("List")
@@ -18,7 +22,7 @@ func update_text():
label.set_text(res)
list.add_child(label)
+
func _ready():
get_node("Text").set_text("They asked me \"What's going on \\\"in the manor\\\"?\"")
update_expression(get_node("Expression").get_text())
-
diff --git a/demos/misc/regex/regex.scn b/demos/misc/regex/regex.scn
index 1f46521d0d..debd55504f 100644
--- a/demos/misc/regex/regex.scn
+++ b/demos/misc/regex/regex.scn
Binary files differ
diff --git a/demos/misc/scene_changer/scene_a.gd b/demos/misc/scene_changer/scene_a.gd
index 956878b0f7..0e80395e84 100644
--- a/demos/misc/scene_changer/scene_a.gd
+++ b/demos/misc/scene_changer/scene_a.gd
@@ -1,17 +1,16 @@
extends Panel
-# member variables here, example:
+# Member variables here, example:
# var a=2
# var b="textvar"
+
func _ready():
# Initalization here
pass
-
-
func _on_goto_scene_pressed():
get_tree().change_scene("res://scene_b.scn")
- pass # replace with function body
+ pass # Replace with function body
diff --git a/demos/misc/scene_changer/scene_a.scn b/demos/misc/scene_changer/scene_a.scn
index 61727a57ba..9a4b6434be 100644
--- a/demos/misc/scene_changer/scene_a.scn
+++ b/demos/misc/scene_changer/scene_a.scn
Binary files differ
diff --git a/demos/misc/scene_changer/scene_b.gd b/demos/misc/scene_changer/scene_b.gd
index 4f94d6bb8f..9ed13cf26b 100644
--- a/demos/misc/scene_changer/scene_b.gd
+++ b/demos/misc/scene_changer/scene_b.gd
@@ -1,17 +1,16 @@
extends Panel
-# member variables here, example:
+# Member variables here, example:
# var a=2
# var b="textvar"
+
func _ready():
# Initalization here
pass
-
-
func _on_goto_scene_pressed():
get_tree().change_scene("res://scene_a.scn")
- pass # replace with function body
+ pass # Replace with function body
diff --git a/demos/misc/scene_changer/scene_b.scn b/demos/misc/scene_changer/scene_b.scn
index ae09eeff88..4cdb03e90e 100644
--- a/demos/misc/scene_changer/scene_b.scn
+++ b/demos/misc/scene_changer/scene_b.scn
Binary files differ
diff --git a/demos/misc/threads/thread.gd b/demos/misc/threads/thread.gd
index 7d8aabd1b7..1ef67e403c 100644
--- a/demos/misc/threads/thread.gd
+++ b/demos/misc/threads/thread.gd
@@ -1,31 +1,31 @@
extends Node2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
+# Member variables
var thread = Thread.new()
-#this function runs in a thread!
-#threads always take one userdata argument
+
+# This function runs in a thread!
+# Threads always take one userdata argument
func _bg_load(path):
print("THREAD FUNC!")
- #load the resource
+ # Load the resource
var tex = ResourceLoader.load(path)
- #call _bg_load_done on main thread
+ # Call _bg_load_done on main thread
call_deferred("_bg_load_done")
- return tex #return it
+ return tex # return it
+
func _bg_load_done():
- #wait for the thread to complete, get the returned value
+ # Wait for the thread to complete, get the returned value
var tex = thread.wait_to_finish()
- #set to the sprite
+ # Set to the sprite
get_node("sprite").set_texture(tex)
+
func _on_load_pressed():
if (thread.is_active()):
- #already working
+ # Already working
return
print("START THREAD!")
- thread.start(self,"_bg_load","res://mona.png")
+ thread.start(self, "_bg_load", "res://mona.png")
diff --git a/demos/misc/threads/thread.scn b/demos/misc/threads/thread.scn
index 349127529a..eea93615c7 100644
--- a/demos/misc/threads/thread.scn
+++ b/demos/misc/threads/thread.scn
Binary files differ
diff --git a/demos/misc/tween/engine.cfg b/demos/misc/tween/engine.cfg
index 3d3d639964..1d87303015 100644
--- a/demos/misc/tween/engine.cfg
+++ b/demos/misc/tween/engine.cfg
@@ -1,7 +1,7 @@
[application]
name="Tween Demo"
-main_scene="res://main.xml"
+main_scene="res://main.scn"
icon="res://icon.png"
target_fps=60
diff --git a/demos/misc/tween/main.gd b/demos/misc/tween/main.gd
index a0106a7682..512271311e 100644
--- a/demos/misc/tween/main.gd
+++ b/demos/misc/tween/main.gd
@@ -1,10 +1,7 @@
extends Control
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
+# Member variables
var trans = ["linear", "sine", "quint", "quart", "quad", "expo", "elastic", "cubic", "circ", "bounce", "back"]
var eases = ["in", "out", "in_out", "out_in"]
var modes = ["move", "color", "scale", "rotate", "callback", "follow", "repeat", "pause"]
@@ -14,6 +11,7 @@ var state = {
eases = Tween.EASE_IN,
}
+
func _ready():
for index in range(trans.size()):
var name = trans[index]
@@ -39,9 +37,7 @@ func _ready():
get_node("modes/repeat").set_pressed(true)
reset_tween()
-
- # Initalization here
- pass
+
func on_trans_changed(name, index):
for index in range(trans.size()):
@@ -53,7 +49,8 @@ func on_trans_changed(name, index):
state.trans = index
reset_tween()
-
+
+
func on_eases_changed(name, index):
for index in range(eases.size()):
var pressed = eases[index] == name
@@ -64,7 +61,8 @@ func on_eases_changed(name, index):
state.eases = index
reset_tween()
-
+
+
func on_modes_changed(name):
var tween = get_node("tween")
if name == "pause":
@@ -76,10 +74,12 @@ func on_modes_changed(name):
get_node("timeline").set_ignore_mouse(true)
else:
reset_tween()
-
+
+
func on_color_changed(color):
reset_tween()
-
+
+
func reset_tween():
var tween = get_node("tween")
var pos = tween.tell()
@@ -92,20 +92,20 @@ func reset_tween():
var size = get_node("tween/area").get_size()
if get_node("modes/move").is_pressed():
- tween.interpolate_method(sprite, "set_pos", Vector2(0,0), Vector2(size.width, size.height), 2, state.trans, state.eases)
- tween.interpolate_property(sprite, "transform/pos", Vector2(size.width,size.height), Vector2(0, 0), 2, state.trans, state.eases, 2)
+ tween.interpolate_method(sprite, "set_pos", Vector2(0, 0), Vector2(size.width, size.height), 2, state.trans, state.eases)
+ tween.interpolate_property(sprite, "transform/pos", Vector2(size.width, size.height), Vector2(0, 0), 2, state.trans, state.eases, 2)
if get_node("modes/color").is_pressed():
tween.interpolate_method(sprite, "set_modulate", get_node("color/color_from").get_color(), get_node("color/color_to").get_color(), 2, state.trans, state.eases)
tween.interpolate_property(sprite, "modulate", get_node("color/color_to").get_color(), get_node("color/color_from").get_color(), 2, state.trans, state.eases, 2)
else:
- sprite.set_modulate(Color(1, 1, 1, 1))
+ sprite.set_modulate(Color(1,1,1,1))
if get_node("modes/scale").is_pressed():
- tween.interpolate_method(sprite, "set_scale", Vector2(0.5,0.5), Vector2(1.5, 1.5), 2, state.trans, state.eases)
- tween.interpolate_property(sprite, "transform/scale", Vector2(1.5,1.5), Vector2(0.5, 0.5), 2, state.trans, state.eases, 2)
+ tween.interpolate_method(sprite, "set_scale", Vector2(0.5, 0.5), Vector2(1.5, 1.5), 2, state.trans, state.eases)
+ tween.interpolate_property(sprite, "transform/scale", Vector2(1.5, 1.5), Vector2(0.5, 0.5), 2, state.trans, state.eases, 2)
else:
- sprite.set_scale(Vector2(1, 1))
+ sprite.set_scale(Vector2(1,1))
if get_node("modes/rotate").is_pressed():
tween.interpolate_method(sprite, "_set_rotd", 0, 360, 2, state.trans, state.eases)
@@ -139,26 +139,27 @@ func reset_tween():
else:
tween.resume_all()
get_node("timeline").set_ignore_mouse(true)
-
-func _on_tween_step( object, key, elapsed, value ):
- var timeline = get_node("timeline")
+func _on_tween_step(object, key, elapsed, value):
+ var timeline = get_node("timeline")
+
var tween = get_node("tween")
var runtime = tween.get_runtime()
-
- var ratio = 100 * (elapsed / runtime)
- timeline.set_value(ratio)
+ var ratio = 100*(elapsed/runtime)
+ timeline.set_value(ratio)
+
-func _on_timeline_value_changed( value ):
+func _on_timeline_value_changed(value):
if !get_node("modes/pause").is_pressed():
return
var tween = get_node("tween")
var runtime = tween.get_runtime()
- tween.seek(runtime * value / 100)
-
+ tween.seek(runtime*value/100)
+
+
func on_callback(arg):
var label = get_node("tween/area/label")
label.add_text("on_callback -> " + arg + "\n")
diff --git a/demos/misc/tween/main.scn b/demos/misc/tween/main.scn
new file mode 100644
index 0000000000..3f25bfd75c
--- /dev/null
+++ b/demos/misc/tween/main.scn
Binary files differ
diff --git a/demos/misc/tween/main.xml b/demos/misc/tween/main.xml
deleted file mode 100644
index 6580ba04da..0000000000
--- a/demos/misc/tween/main.xml
+++ /dev/null
@@ -1,367 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="3" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
- <ext_resource path="res://icon.png" type="Texture"></ext_resource>
- <ext_resource path="res://main.gd" type="Script"></ext_resource>
- <main_resource>
- <dictionary name="_bundled" shared="false">
- <string> "names" </string>
- <string_array len="115">
- <string> "main" </string>
- <string> "Control" </string>
- <string> "_import_path" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/behind_parent" </string>
- <string> "margin/right" </string>
- <string> "margin/bottom" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
- <string> "focus_neighbour/left" </string>
- <string> "focus_neighbour/top" </string>
- <string> "focus_neighbour/right" </string>
- <string> "focus_neighbour/bottom" </string>
- <string> "focus/ignore_mouse" </string>
- <string> "focus/stop_mouse" </string>
- <string> "size_flags/horizontal" </string>
- <string> "size_flags/vertical" </string>
- <string> "size_flags/stretch_ratio" </string>
- <string> "script/script" </string>
- <string> "__meta__" </string>
- <string> "trans" </string>
- <string> "VBoxContainer" </string>
- <string> "margin/left" </string>
- <string> "margin/top" </string>
- <string> "linear" </string>
- <string> "Button" </string>
- <string> "disabled" </string>
- <string> "pressed" </string>
- <string> "toggle_mode" </string>
- <string> "click_on_press" </string>
- <string> "text" </string>
- <string> "icon" </string>
- <string> "flat" </string>
- <string> "clip_text" </string>
- <string> "align" </string>
- <string> "sine" </string>
- <string> "quint" </string>
- <string> "quart" </string>
- <string> "quad" </string>
- <string> "expo" </string>
- <string> "elastic" </string>
- <string> "cubic" </string>
- <string> "circ" </string>
- <string> "bounce" </string>
- <string> "back" </string>
- <string> "eases" </string>
- <string> "in" </string>
- <string> "out" </string>
- <string> "in_out" </string>
- <string> "out_in" </string>
- <string> "modes" </string>
- <string> "move" </string>
- <string> "color" </string>
- <string> "scale" </string>
- <string> "rotate" </string>
- <string> "callback" </string>
- <string> "follow" </string>
- <string> "repeat" </string>
- <string> "pause" </string>
- <string> "label_1" </string>
- <string> "Label" </string>
- <string> "range/min" </string>
- <string> "range/max" </string>
- <string> "range/step" </string>
- <string> "range/page" </string>
- <string> "range/value" </string>
- <string> "range/exp_edit" </string>
- <string> "rounded_values" </string>
- <string> "valign" </string>
- <string> "autowrap" </string>
- <string> "uppercase" </string>
- <string> "percent_visible" </string>
- <string> "color_from" </string>
- <string> "ColorPicker" </string>
- <string> "label_2" </string>
- <string> "color_to" </string>
- <string> "tween" </string>
- <string> "Tween" </string>
- <string> "playback/process_mode" </string>
- <string> "playback/active" </string>
- <string> "playback/repeat" </string>
- <string> "playback/speed" </string>
- <string> "area" </string>
- <string> "Panel" </string>
- <string> "label" </string>
- <string> "RichTextLabel" </string>
- <string> "scroll_active" </string>
- <string> "scroll_follow" </string>
- <string> "tab_size" </string>
- <string> "selection_enabled" </string>
- <string> "sprite" </string>
- <string> "Sprite" </string>
- <string> "transform/pos" </string>
- <string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
- <string> "follow_2" </string>
- <string> "timeline" </string>
- <string> "HSlider" </string>
- <string> "tick_count" </string>
- <string> "ticks_on_borders" </string>
- <string> "_on_tween_step" </string>
- <string> "tween_step" </string>
- <string> "_on_timeline_value_changed" </string>
- <string> "value_changed" </string>
- </string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 2 </int>
- <string> "node_count" </string>
- <int> 39 </int>
- <string> "variants" </string>
- <array len="104" shared="false">
- <node_path> "" </node_path>
- <bool> True </bool>
- <real> 1 </real>
- <bool> False </bool>
- <real> 800 </real>
- <real> 600 </real>
- <real> 0 </real>
- <vector2> 1, 1 </vector2>
- <int> 2 </int>
- <resource resource_type="Script" path="res://main.gd"> </resource>
- <dictionary shared="false">
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 0 </int>
- <string> "sources" </string>
- <array len="1" shared="false">
- <string> "res://main.gd" </string>
- </array>
- </dictionary>
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "pixel_snap" </string>
- <bool> False </bool>
- <string> "zoom" </string>
- <real> 1.360374 </real>
- <string> "use_snap" </string>
- <bool> True </bool>
- <string> "ofs" </string>
- <vector2> -215.073, -20.8125 </vector2>
- <string> "snap" </string>
- <int> 8 </int>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "fov" </string>
- <real> 45 </real>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- </array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "znear" </string>
- <real> 0.1 </real>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "Script" </string>
- </dictionary>
- <real> 56 </real>
- <real> 256 </real>
- <real> 129 </real>
- <real> 582 </real>
- <dictionary shared="false">
- <string> "_editor_collapsed" </string>
- <bool> True </bool>
- </dictionary>
- <real> 73 </real>
- <real> 26 </real>
- <string> "linear" </string>
- <resource name=""></resource> <int> 1 </int>
- <real> 30 </real>
- <string> "sine" </string>
- <real> 60 </real>
- <real> 86 </real>
- <string> "quint" </string>
- <real> 90 </real>
- <real> 116 </real>
- <string> "quart" </string>
- <real> 120 </real>
- <real> 146 </real>
- <string> "quad" </string>
- <real> 150 </real>
- <real> 176 </real>
- <string> "expo" </string>
- <real> 180 </real>
- <real> 206 </real>
- <string> "elastic" </string>
- <real> 210 </real>
- <real> 236 </real>
- <string> "cubic" </string>
- <real> 240 </real>
- <real> 266 </real>
- <string> "circ" </string>
- <real> 270 </real>
- <real> 296 </real>
- <string> "bounce" </string>
- <real> 300 </real>
- <real> 326 </real>
- <string> "back" </string>
- <real> 152 </real>
- <real> 215 </real>
- <real> 372 </real>
- <dictionary shared="false">
- <string> "_editor_collapsed" </string>
- <bool> True </bool>
- </dictionary>
- <real> 63 </real>
- <string> "in" </string>
- <string> "out" </string>
- <string> "in_out" </string>
- <string> "out_in" </string>
- <real> 317 </real>
- <real> 492 </real>
- <dictionary shared="false">
- <string> "_editor_collapsed" </string>
- <bool> True </bool>
- </dictionary>
- <real> 77 </real>
- <string> "move" </string>
- <string> "color" </string>
- <string> "scale" </string>
- <string> "rotate" </string>
- <string> "callback" </string>
- <string> "follow" </string>
- <string> "repeat" </string>
- <string> "pause" </string>
- <real> 384 </real>
- <real> 760 </real>
- <real> 592 </real>
- <dictionary shared="false">
- <string> "_editor_collapsed" </string>
- <bool> True </bool>
- </dictionary>
- <real> 376 </real>
- <real> 19 </real>
- <string> "Color From:" </string>
- <int> 0 </int>
- <real> -1 </real>
- <real> 23 </real>
- <real> 174 </real>
- <real> 178 </real>
- <real> 197 </real>
- <string> "Color To:" </string>
- <real> 201 </real>
- <real> 352 </real>
- <real> 32 </real>
- <real> 768 </real>
- <real> 216 </real>
- <real> 24 </real>
- <real> 552 </real>
- <real> 160 </real>
- <string> "" </string>
- <int> 4 </int>
- <vector2> 0, 0 </vector2>
- <resource resource_type="Texture" path="res://icon.png"> </resource>
- <color> 1, 1, 1, 1 </color>
- <rect2> 0, 0, 0, 0 </rect2>
- <vector2> 0, 184 </vector2>
- <vector2> 736, 0 </vector2>
- <real> 40 </real>
- <real> 224 </real>
- <real> 100 </real>
- </array>
- <string> "nodes" </string>
- <int_array len="2229"> -1, -1, 1, 0, -1, 20, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 20, 9, 21, 10, 0, 0, 0, 23, 22, -1, 21, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 24, 11, 25, 12, 7, 13, 8, 14, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 3, 17, 8, 18, 8, 19, 2, 21, 15, 0, 1, 0, 27, 26, -1, 27, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 16, 8, 17, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 18, 33, 19, 34, 3, 35, 3, 36, 20, 0, 1, 0, 27, 37, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 21, 7, 16, 8, 11, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 22, 33, 19, 34, 3, 35, 3, 36, 20, 0, 1, 0, 27, 38, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 23, 7, 16, 8, 24, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 25, 33, 19, 34, 3, 35, 3, 36, 20, 0, 1, 0, 27, 39, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 26, 7, 16, 8, 27, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 28, 33, 19, 34, 3, 35, 3, 36, 20, 0, 1, 0, 27, 40, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 29, 7, 16, 8, 30, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 31, 33, 19, 34, 3, 35, 3, 36, 20, 0, 1, 0, 27, 41, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 32, 7, 16, 8, 33, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 34, 33, 19, 34, 3, 35, 3, 36, 20, 0, 1, 0, 27, 42, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 35, 7, 16, 8, 36, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 37, 33, 19, 34, 3, 35, 3, 36, 20, 0, 1, 0, 27, 43, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 38, 7, 16, 8, 39, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 40, 33, 19, 34, 3, 35, 3, 36, 20, 0, 1, 0, 27, 44, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 41, 7, 16, 8, 42, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 43, 33, 19, 34, 3, 35, 3, 36, 20, 0, 1, 0, 27, 45, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 44, 7, 16, 8, 45, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 46, 33, 19, 34, 3, 35, 3, 36, 20, 0, 1, 0, 27, 46, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 47, 7, 16, 8, 48, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 49, 33, 19, 34, 3, 35, 3, 36, 20, 0, 0, 0, 23, 47, -1, 21, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 24, 50, 25, 12, 7, 51, 8, 52, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 3, 17, 8, 18, 8, 19, 2, 21, 53, 0, 13, 0, 27, 48, -1, 27, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 54, 8, 17, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 55, 33, 19, 34, 3, 35, 3, 36, 20, 0, 13, 0, 27, 49, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 21, 7, 54, 8, 11, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 56, 33, 19, 34, 3, 35, 3, 36, 20, 0, 13, 0, 27, 50, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 23, 7, 54, 8, 24, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 57, 33, 19, 34, 3, 35, 3, 36, 20, 0, 13, 0, 27, 51, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 26, 7, 54, 8, 27, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 58, 33, 19, 34, 3, 35, 3, 36, 20, 0, 0, 0, 23, 52, -1, 21, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 24, 41, 25, 12, 7, 59, 8, 60, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 3, 17, 8, 18, 8, 19, 2, 21, 61, 0, 18, 0, 27, 53, -1, 27, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 62, 8, 17, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 63, 33, 19, 34, 3, 35, 3, 36, 20, 0, 18, 0, 27, 54, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 21, 7, 62, 8, 11, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 64, 33, 19, 34, 3, 35, 3, 36, 20, 0, 18, 0, 27, 55, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 23, 7, 62, 8, 24, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 65, 33, 19, 34, 3, 35, 3, 36, 20, 0, 18, 0, 27, 56, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 26, 7, 62, 8, 27, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 66, 33, 19, 34, 3, 35, 3, 36, 20, 0, 18, 0, 27, 57, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 29, 7, 62, 8, 30, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 67, 33, 19, 34, 3, 35, 3, 36, 20, 0, 18, 0, 27, 58, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 32, 7, 62, 8, 33, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 68, 33, 19, 34, 3, 35, 3, 36, 20, 0, 18, 0, 27, 59, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 35, 7, 62, 8, 36, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 69, 33, 19, 34, 3, 35, 3, 36, 20, 0, 18, 0, 27, 60, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 38, 7, 62, 8, 39, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 28, 3, 29, 3, 30, 1, 31, 3, 32, 70, 33, 19, 34, 3, 35, 3, 36, 20, 0, 0, 0, 23, 54, -1, 21, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 24, 71, 25, 41, 7, 72, 8, 73, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 3, 17, 8, 18, 8, 19, 2, 21, 74, 0, 27, 0, 62, 61, -1, 30, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 75, 8, 76, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 1, 16, 1, 17, 8, 19, 2, 63, 6, 64, 2, 65, 2, 66, 2, 67, 6, 68, 3, 69, 3, 32, 77, 36, 78, 70, 78, 71, 3, 72, 3, 73, 79, 0, 27, 0, 75, 74, -1, 19, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 80, 7, 75, 8, 81, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 3, 17, 8, 18, 8, 19, 2, 0, 27, 0, 62, 76, -1, 31, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 82, 7, 75, 8, 83, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 1, 16, 1, 17, 8, 19, 2, 63, 6, 64, 2, 65, 2, 66, 2, 67, 6, 68, 3, 69, 3, 32, 84, 36, 78, 70, 78, 71, 3, 72, 3, 73, 79, 0, 27, 0, 75, 77, -1, 19, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 25, 85, 7, 75, 8, 86, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 3, 17, 8, 18, 8, 19, 2, 0, 0, 0, 79, 78, -1, 5, 2, 0, 80, 20, 81, 1, 82, 1, 83, 2, 0, 32, 0, 85, 84, -1, 20, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 24, 87, 25, 87, 7, 88, 8, 89, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 18, 8, 19, 2, 0, 33, 0, 87, 86, -1, 24, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 24, 33, 25, 90, 7, 91, 8, 92, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 19, 2, 32, 93, 88, 1, 89, 1, 90, 94, 91, 3, 0, 33, 0, 93, 92, -1, 19, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 94, 95, 9, 6, 10, 7, 95, 96, 96, 1, 97, 95, 98, 3, 99, 3, 100, 20, 101, 20, 102, 78, 103, 97, 104, 3, 105, 98, 0, 33, 0, 93, 58, -1, 19, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 94, 99, 9, 6, 10, 7, 95, 96, 96, 1, 97, 95, 98, 3, 99, 3, 100, 20, 101, 20, 102, 78, 103, 97, 104, 3, 105, 98, 0, 33, 0, 93, 106, -1, 19, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 94, 100, 9, 6, 10, 7, 95, 96, 96, 1, 97, 95, 98, 3, 99, 3, 100, 20, 101, 20, 102, 78, 103, 97, 104, 3, 105, 98, 0, 0, 0, 108, 107, -1, 28, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 24, 101, 25, 102, 7, 72, 8, 41, 9, 6, 10, 7, 11, 0, 12, 0, 13, 0, 14, 0, 15, 3, 16, 1, 17, 8, 19, 2, 63, 6, 64, 103, 65, 2, 66, 6, 67, 2, 68, 3, 69, 3, 109, 78, 110, 3, 0 </int_array>
- <string> "conns" </string>
- <int_array len="12"> 32, 0, 112, 111, 2, 0, 38, 0, 114, 113, 2, 0 </int_array>
- </dictionary>
-
- </main_resource>
-</resource_file>
diff --git a/demos/misc/udp_chat/chat.gd b/demos/misc/udp_chat/chat.gd
index 3270eebbfe..b60afa9ded 100644
--- a/demos/misc/udp_chat/chat.gd
+++ b/demos/misc/udp_chat/chat.gd
@@ -1,72 +1,66 @@
extends Panel
-# Really simple UDP chat client, not intended as a chat example!!
+# Really simple UDP chat client, not intended as a comprehensive chat implementation.
# (UDP can lose packets and you won't normally find out, so don't do a chat this way)
# This is just a demo that shows how to use the UDP class.
+# Member variables
var udp = PacketPeerUDP.new()
-func _process(delta):
+func _process(delta):
if (not udp.is_listening()):
return
-
- while(udp.get_available_packet_count()>0):
+
+ while(udp.get_available_packet_count() > 0):
var packet = udp.get_var()
- if (typeof(packet)==TYPE_STRING):
+ if (typeof(packet) == TYPE_STRING):
var host = udp.get_packet_ip()
var port = udp.get_packet_port()
- get_node("chat/text").add_text("("+host+":"+str(port)+":) "+packet)
+ get_node("chat/text").add_text("(" + host + ":" + str(port) + ":) " + packet)
get_node("chat/text").newline()
-
-
+
func _ready():
- # Initalization here
- get_node("chat").add_style_override("panel",get_stylebox("bg","Tree"))
+ get_node("chat").add_style_override("panel", get_stylebox("bg", "Tree"))
set_process(true)
-
func send_message(text):
if (udp.is_listening()):
udp.put_var(text)
-
-
-func _on_connect_toggled( pressed ):
+func _on_connect_toggled(pressed):
if (pressed):
- var err = udp.listen( get_node("listen_port").get_val() )
- if (err!=OK):
- get_node("status").set_text("Error:\nCan't Listen.")
+ var err = udp.listen(get_node("listen_port").get_val())
+ if (err != OK):
+ get_node("status").set_text("Error:\nCan't listen.")
get_node("connect").set_pressed(false)
else:
get_node("status").set_text("Connected.")
get_node("connect").set_text("Disconnect")
err = udp.set_send_address(get_node("remote_host").get_text(),get_node("remote_port").get_val())
- if (err!=OK):
- get_node("status").set_text("Error:\nCan't Resolve.")
+ if (err != OK):
+ get_node("status").set_text("Error:\nCan't resolve.")
get_node("connect").set_pressed(false)
else:
- send_message("* "+get_node("user_name").get_text()+" entered chat.")
+ send_message("* " + get_node("user_name").get_text() + " entered chat.")
else:
-
udp.close()
get_node("status").set_text("Disconnected.")
get_node("connect").set_text("Connect")
-
+func _on_entry_line_text_entered(text):
+ _on_entry_button_pressed()
-func _on_entry_line_text_entered( text ):
- _on_entry_button_pressed();
func _on_entry_button_pressed():
var msg = get_node("entry_line").get_text()
- if (msg==""):
+ if (msg == ""):
return
- send_message(get_node("user_name").get_text()+"> "+msg)
+ send_message(get_node("user_name").get_text() + "> " + msg)
get_node("entry_line").set_text("")
diff --git a/demos/misc/udp_chat/chat.scn b/demos/misc/udp_chat/chat.scn
index efa4b799a0..fe38e9da72 100644
--- a/demos/misc/udp_chat/chat.scn
+++ b/demos/misc/udp_chat/chat.scn
Binary files differ
diff --git a/demos/misc/window_management/control.gd b/demos/misc/window_management/control.gd
index 1609dda699..cd8e0e185b 100644
--- a/demos/misc/window_management/control.gd
+++ b/demos/misc/window_management/control.gd
@@ -1,17 +1,18 @@
extends Control
+# Member variables
var mousepos
-func _fixed_process(delta):
+func _fixed_process(delta):
var modetext = "Mode:\n"
if(OS.is_window_fullscreen()):
modetext += "Fullscreen\n"
else:
modetext += "Windowed\n"
-
+
if(!OS.is_window_resizable()):
modetext += "FixedSize\n"
@@ -29,119 +30,119 @@ func _fixed_process(delta):
get_node("Label_Mode").set_text(modetext)
- get_node("Label_Position").set_text( str("Position:\n", OS.get_window_position() ) )
+ 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_Size").set_text(str("Size:\n", OS.get_window_size()))
- get_node("Label_MousePosition").set_text(str("Mouse Position:\n", mousepos ) )
+ get_node("Label_MousePosition").set_text(str("Mouse Position:\n", mousepos))
- get_node("Label_Screen_Count").set_text( str("Screen_Count:\n", OS.get_screen_count() ) )
+ get_node("Label_Screen_Count").set_text(str("Screen_Count:\n", OS.get_screen_count()))
- get_node("Label_Screen_Current").set_text( str("Screen:\n", OS.get_current_screen() ) )
+ get_node("Label_Screen_Current").set_text(str("Screen:\n", OS.get_current_screen()))
- get_node("Label_Screen0_Resolution").set_text( str("Screen0 Resolution:\n", OS.get_screen_size() ) )
+ get_node("Label_Screen0_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() ) )
+ 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) ) )
+ get_node("Label_Screen1_Resolution").set_text(str("Screen1 Resolution:\n", OS.get_screen_size(1)))
+ get_node("Label_Screen1_Position").set_text(str("Screen1 Position:\n", OS.get_screen_position(1)))
else:
get_node("Button_Screen0").hide()
get_node("Button_Screen1").hide()
get_node("Label_Screen1_Resolution").hide()
get_node("Label_Screen1_Position").hide()
-
- get_node("Button_Fullscreen").set_pressed( OS.is_window_fullscreen() )
- get_node("Button_FixedSize").set_pressed( !OS.is_window_resizable() )
- get_node("Button_Minimized").set_pressed( OS.is_window_minimized() )
- get_node("Button_Maximized").set_pressed( OS.is_window_maximized() )
- get_node("Button_Mouse_Grab").set_pressed( Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED )
+
+ get_node("Button_Fullscreen").set_pressed(OS.is_window_fullscreen())
+ get_node("Button_FixedSize").set_pressed(!OS.is_window_resizable())
+ get_node("Button_Minimized").set_pressed(OS.is_window_minimized())
+ get_node("Button_Maximized").set_pressed(OS.is_window_maximized())
+ get_node("Button_Mouse_Grab").set_pressed(Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED)
func check_wm_api():
var s = ""
- if( !OS.has_method("get_screen_count") ):
+ if(!OS.has_method("get_screen_count")):
s += " - get_screen_count()\n"
- if( !OS.has_method("get_current_screen") ):
+ if(!OS.has_method("get_current_screen")):
s += " - get_current_screen()\n"
- if( !OS.has_method("set_current_screen") ):
+ if(!OS.has_method("set_current_screen")):
s += " - set_current_screen()\n"
- if( !OS.has_method("get_screen_position") ):
+ if(!OS.has_method("get_screen_position")):
s += " - get_screen_position()\n"
- if( !OS.has_method("get_screen_size") ):
+ if(!OS.has_method("get_screen_size")):
s += " - get_screen_size()\n"
- if( !OS.has_method("get_window_position") ):
+ if(!OS.has_method("get_window_position")):
s += " - get_window_position()\n"
- if( !OS.has_method("set_window_position") ):
+ if(!OS.has_method("set_window_position")):
s += " - set_window_position()\n"
- if( !OS.has_method("get_window_size") ):
+ if(!OS.has_method("get_window_size")):
s += " - get_window_size()\n"
- if( !OS.has_method("set_window_size") ):
+ if(!OS.has_method("set_window_size")):
s += " - set_window_size()\n"
- if( !OS.has_method("set_window_fullscreen") ):
+ if(!OS.has_method("set_window_fullscreen")):
s += " - set_window_fullscreen()\n"
- if( !OS.has_method("is_window_fullscreen") ):
+ if(!OS.has_method("is_window_fullscreen")):
s += " - is_window_fullscreen()\n"
- if( !OS.has_method("set_window_resizable") ):
+ if(!OS.has_method("set_window_resizable")):
s += " - set_window_resizable()\n"
- if( !OS.has_method("is_window_resizable") ):
+ if(!OS.has_method("is_window_resizable")):
s += " - is_window_resizable()\n"
- if( !OS.has_method("set_window_minimized") ):
+ if(!OS.has_method("set_window_minimized")):
s += " - set_window_minimized()\n"
- if( !OS.has_method("is_window_minimized") ):
+ if(!OS.has_method("is_window_minimized")):
s += " - is_window_minimized()\n"
- if( !OS.has_method("set_window_maximized") ):
+ if(!OS.has_method("set_window_maximized")):
s += " - set_window_maximized()\n"
- if( !OS.has_method("is_window_maximized") ):
+ if(!OS.has_method("is_window_maximized")):
s += " - is_window_maximized()\n"
- if( s.length() == 0 ):
+ 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/Text").set_text(text + s)
get_node("ImplementationDialog").show()
return false
func _ready():
- if( check_wm_api() ):
+ if(check_wm_api()):
set_fixed_process(true)
set_process_input(true)
-func _input(ev):
- if (ev.type==InputEvent.MOUSE_MOTION):
- mousepos = ev.pos
+func _input(event):
+ if (event.type == InputEvent.MOUSE_MOTION):
+ mousepos = event.pos
func _on_Button_MoveTo_pressed():
- OS.set_window_position( Vector2(100,100) )
+ OS.set_window_position(Vector2(100, 100))
func _on_Button_Resize_pressed():
- OS.set_window_size( Vector2(1024,768) )
+ OS.set_window_size(Vector2(1024, 768))
func _on_Button_Screen0_pressed():
diff --git a/demos/misc/window_management/observer/observer.gd b/demos/misc/window_management/observer/observer.gd
index d27912a670..f100811859 100644
--- a/demos/misc/window_management/observer/observer.gd
+++ b/demos/misc/window_management/observer/observer.gd
@@ -1,16 +1,17 @@
extends Spatial
+# Member variables
var r_pos = Vector2()
var state
-const STATE_MENU=0
-const STATE_GRAB=1
+const STATE_MENU = 0
+const STATE_GRAB = 1
+
func direction(vector):
- var v = get_node("Camera").get_global_transform().basis * vector
+ var v = get_node("Camera").get_global_transform().basis*vector
v = v.normalized()
-
return v
@@ -22,43 +23,42 @@ func impulse(event, action):
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 dir = Vector3()
var cam = get_global_transform()
var org = get_translation()
if (Input.is_action_pressed("move_forward")):
- dir += direction(Vector3(0,0,-1))
+ dir += direction(Vector3(0, 0, -1))
if (Input.is_action_pressed("move_backwards")):
- dir += direction(Vector3(0,0,1))
+ dir += direction(Vector3(0, 0, 1))
if (Input.is_action_pressed("move_left")):
- dir += direction(Vector3(-1,0,0))
+ dir += direction(Vector3(-1, 0, 0))
if (Input.is_action_pressed("move_right")):
- dir += direction(Vector3(1,0,0))
+ dir += direction(Vector3(1, 0, 0))
dir = dir.normalized()
- move(dir * 10 * delta)
- var d = delta * 0.1
+ move(dir*10*delta)
+ var d = delta*0.1
- var yaw = get_transform().rotated(Vector3(0,1,0), d * r_pos.x)
+ 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)
+ 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 ):
+func _input(event):
if(event.type == InputEvent.MOUSE_MOTION):
r_pos = event.relative_pos
@@ -76,4 +76,3 @@ func _ready():
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
index da29ad62b8..813d7d4587 100644
--- a/demos/misc/window_management/observer/observer.scn
+++ 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
index 8db43b6638..35662871f1 100644
--- a/demos/misc/window_management/window_management.scn
+++ b/demos/misc/window_management/window_management.scn
Binary files differ
diff --git a/demos/viewport/2d_in_3d/pong.gd b/demos/viewport/2d_in_3d/pong.gd
index bfffdcf0d8..ac3457453b 100644
--- a/demos/viewport/2d_in_3d/pong.gd
+++ b/demos/viewport/2d_in_3d/pong.gd
@@ -1,73 +1,66 @@
extends Node2D
-# member variables here, example:
-# var a=2
-# var b="textvar"
+# Member variables
const INITIAL_BALL_SPEED = 80
var ball_speed = INITIAL_BALL_SPEED
-var screen_size = Vector2(640,400)
-#default ball direction
-var direction = Vector2(-1,0)
-var pad_size = Vector2(8,32)
+var screen_size = Vector2(640, 400)
+# Default ball direction
+var direction = Vector2(-1, 0)
+var pad_size = Vector2(8, 32)
const PAD_SPEED = 150
func _process(delta):
-
-
- # get ball positio and pad rectangles
+ # Get ball position and pad rectangles
var ball_pos = get_node("ball").get_pos()
- var left_rect = Rect2( get_node("left").get_pos() - pad_size*0.5, pad_size )
- var right_rect = Rect2( get_node("right").get_pos() - pad_size*0.5, pad_size )
+ var left_rect = Rect2(get_node("left").get_pos() - pad_size*0.5, pad_size)
+ var right_rect = Rect2(get_node("right").get_pos() - pad_size*0.5, pad_size)
- #integrate new ball postion
- ball_pos+=direction*ball_speed*delta
+ # Integrate new ball postion
+ ball_pos += direction*ball_speed*delta
- #flip when touching roof or floor
- if ( (ball_pos.y<0 and direction.y <0) or (ball_pos.y>screen_size.y and direction.y>0)):
+ # Flip when touching roof or floor
+ if ((ball_pos.y < 0 and direction.y < 0) or (ball_pos.y > screen_size.y and direction.y > 0)):
direction.y = -direction.y
-
- #flip, change direction and increase speed when touching pads
- if ( (left_rect.has_point(ball_pos) and direction.x < 0) or (right_rect.has_point(ball_pos) and direction.x > 0)):
- direction.x=-direction.x
- ball_speed*=1.1
- direction.y=randf()*2.0-1
+
+ # Flip, change direction and increase speed when touching pads
+ if ((left_rect.has_point(ball_pos) and direction.x < 0) or (right_rect.has_point(ball_pos) and direction.x > 0)):
+ direction.x = -direction.x
+ ball_speed *= 1.1
+ direction.y = randf()*2.0 - 1
direction = direction.normalized()
-
- #check gameover
- if (ball_pos.x<0 or ball_pos.x>screen_size.x):
- ball_pos=screen_size*0.5
- ball_speed=INITIAL_BALL_SPEED
- direction=Vector2(-1,0)
-
-
+
+ # Check gameover
+ if (ball_pos.x < 0 or ball_pos.x > screen_size.x):
+ ball_pos = screen_size*0.5
+ ball_speed = INITIAL_BALL_SPEED
+ direction = Vector2(-1, 0)
+
get_node("ball").set_pos(ball_pos)
-
- #move left pad
+
+ # Move left pad
var left_pos = get_node("left").get_pos()
if (left_pos.y > 0 and Input.is_action_pressed("left_move_up")):
- left_pos.y+=-PAD_SPEED*delta
+ left_pos.y += -PAD_SPEED*delta
if (left_pos.y < screen_size.y and Input.is_action_pressed("left_move_down")):
- left_pos.y+=PAD_SPEED*delta
-
+ left_pos.y += PAD_SPEED*delta
+
get_node("left").set_pos(left_pos)
-
- #move right pad
+
+ # Move right pad
var right_pos = get_node("right").get_pos()
if (right_pos.y > 0 and Input.is_action_pressed("right_move_up")):
- right_pos.y+=-PAD_SPEED*delta
+ right_pos.y += -PAD_SPEED*delta
if (right_pos.y < screen_size.y and Input.is_action_pressed("right_move_down")):
- right_pos.y+=PAD_SPEED*delta
-
- get_node("right").set_pos(right_pos)
+ right_pos.y += PAD_SPEED*delta
-
+ get_node("right").set_pos(right_pos)
+
func _ready():
- screen_size = get_viewport_rect().size # get actual size
+ screen_size = get_viewport_rect().size # Get actual size
pad_size = get_node("left").get_texture().get_size()
set_process(true)
-
diff --git a/demos/viewport/2d_in_3d/pong.scn b/demos/viewport/2d_in_3d/pong.scn
new file mode 100644
index 0000000000..559e2f96bc
--- /dev/null
+++ b/demos/viewport/2d_in_3d/pong.scn
Binary files differ
diff --git a/demos/viewport/2d_in_3d/pong.xml b/demos/viewport/2d_in_3d/pong.xml
deleted file mode 100644
index cf47a8db9f..0000000000
--- a/demos/viewport/2d_in_3d/pong.xml
+++ /dev/null
@@ -1,183 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="6" version="0.99" version_name="Godot Engine v0.99.3735-pre-beta">
- <ext_resource path="res://pong.*" type="GDScript"></ext_resource>
- <ext_resource path="res://separator.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://left_pallete.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://right_pallete.*" type="ImageTexture"></ext_resource>
- <ext_resource path="res://ball.*" type="ImageTexture"></ext_resource>
- <main_resource>
- <dictionary name="_bundled" shared="false">
- <string> "names" </string>
- <string_array len="27">
- <string> "game" </string>
- <string> "Node2D" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
- <string> "script/script" </string>
- <string> "__meta__" </string>
- <string> "left" </string>
- <string> "Sprite" </string>
- <string> "texture" </string>
- <string> "centered" </string>
- <string> "offset" </string>
- <string> "flip_h" </string>
- <string> "flip_v" </string>
- <string> "vframes" </string>
- <string> "hframes" </string>
- <string> "frame" </string>
- <string> "modulate" </string>
- <string> "region" </string>
- <string> "region_rect" </string>
- <string> "right" </string>
- <string> "separator" </string>
- <string> "ball" </string>
- </string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
- <string> "node_count" </string>
- <int> 5 </int>
- <string> "variants" </string>
- <array len="20" shared="false">
- <bool> True </bool>
- <real> 1 </real>
- <vector2> 0, 0 </vector2>
- <real> 0 </real>
- <vector2> 1, 1 </vector2>
- <resource resource_type="GDScript" path="res://pong.*"> </resource>
- <dictionary shared="false">
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 0 </int>
- <string> "sources" </string>
- <array len="1" shared="false">
- <string> "res://pong.gd" </string>
- </array>
- </dictionary>
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "pixel_snap" </string>
- <bool> True </bool>
- <string> "zoom" </string>
- <real> 1.108033 </real>
- <string> "ofs" </string>
- <vector2> -54.59, -36.0052 </vector2>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "fov" </string>
- <real> 45 </real>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- </array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "znear" </string>
- <real> 0.1 </real>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "Script" </string>
- </dictionary>
- <vector2> 67.6875, 183.208 </vector2>
- <resource resource_type="ImageTexture" path="res://left_pallete.*"> </resource>
- <bool> False </bool>
- <int> 1 </int>
- <int> 0 </int>
- <color> 1, 1, 1, 1 </color>
- <rect2> 0, 0, 0, 0 </rect2>
- <vector2> 577, 187 </vector2>
- <resource resource_type="ImageTexture" path="res://right_pallete.*"> </resource>
- <vector2> 320, 200 </vector2>
- <resource resource_type="ImageTexture" path="res://separator.*"> </resource>
- <vector2> 320.283, 188 </vector2>
- <resource resource_type="ImageTexture" path="res://ball.*"> </resource>
- </array>
- <string> "nodes" </string>
- <int_array len="197"> -1, -1, 1, 0, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 0, 0, 0, 12, 11, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 7, 7, 3, 8, 4, 13, 8, 14, 0, 15, 2, 16, 9, 17, 9, 18, 10, 19, 10, 20, 11, 21, 12, 22, 9, 23, 13, 0, 0, 0, 12, 24, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 14, 7, 3, 8, 4, 13, 15, 14, 0, 15, 2, 16, 9, 17, 9, 18, 10, 19, 10, 20, 11, 21, 12, 22, 9, 23, 13, 0, 0, 0, 12, 25, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 16, 7, 3, 8, 4, 13, 17, 14, 0, 15, 2, 16, 9, 17, 9, 18, 10, 19, 10, 20, 11, 21, 12, 22, 9, 23, 13, 0, 0, 0, 12, 26, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 18, 7, 3, 8, 4, 13, 19, 14, 0, 15, 2, 16, 9, 17, 9, 18, 10, 19, 10, 20, 11, 21, 12, 22, 9, 23, 13, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
- </dictionary>
-
- </main_resource>
-</resource_file> \ No newline at end of file
diff --git a/demos/viewport/2d_in_3d/pong3d.gd b/demos/viewport/2d_in_3d/pong3d.gd
index 046d4dd859..79a7a36801 100644
--- a/demos/viewport/2d_in_3d/pong3d.gd
+++ b/demos/viewport/2d_in_3d/pong3d.gd
@@ -1,14 +1,7 @@
extends Spatial
-# member variables here, example:
-# var a=2
-# var b="textvar"
func _ready():
- # Initalization here
var tex = get_node("Viewport").get_render_target_texture()
- get_node("Quad").get_material_override().set_texture(FixedMaterial.PARAM_DIFFUSE,tex)
- pass
-
-
+ get_node("Quad").get_material_override().set_texture(FixedMaterial.PARAM_DIFFUSE, tex)
diff --git a/demos/viewport/2d_in_3d/pong3d.scn b/demos/viewport/2d_in_3d/pong3d.scn
index 58fd1513c0..2e60764a88 100644
--- a/demos/viewport/2d_in_3d/pong3d.scn
+++ b/demos/viewport/2d_in_3d/pong3d.scn
Binary files differ
diff --git a/demos/viewport/3d_in_2d/main.scn b/demos/viewport/3d_in_2d/main.scn
index ad371b4417..d6c4deea42 100644
--- a/demos/viewport/3d_in_2d/main.scn
+++ b/demos/viewport/3d_in_2d/main.scn
Binary files differ
diff --git a/demos/viewport/3d_in_2d/player.scn b/demos/viewport/3d_in_2d/player.scn
index d6e6ddc461..7f490237fb 100644
--- a/demos/viewport/3d_in_2d/player.scn
+++ b/demos/viewport/3d_in_2d/player.scn
Binary files differ
diff --git a/demos/viewport/3d_in_2d/player.xml b/demos/viewport/3d_in_2d/player.xml
deleted file mode 100644
index 5730336107..0000000000
--- a/demos/viewport/3d_in_2d/player.xml
+++ /dev/null
@@ -1,1736 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" version="0.99" version_name="Godot Engine v0.99.3735-pre-beta">
- <resource type="CapsuleShape" path="local://1">
- <real name="radius"> 0.4 </real>
- <real name="height"> 0.4 </real>
-
- </resource>
- <resource type="RayShape" path="local://2">
- <real name="length"> 1 </real>
-
- </resource>
- <resource type="FixedMaterial" path="local://3">
- <bool name="flags/visible"> True </bool>
- <bool name="flags/double_sided"> True </bool>
- <bool name="flags/invert_faces"> False </bool>
- <bool name="flags/unshaded"> False </bool>
- <bool name="flags/on_top"> False </bool>
- <bool name="flags/wireframe"> False </bool>
- <bool name="flags/billboard_sw"> False </bool>
- <bool name="hints/decal"> False </bool>
- <bool name="hints/opaque_pre_zpass"> False </bool>
- <bool name="hints/no_shadow"> False </bool>
- <bool name="hints/no_depth_draw"> False </bool>
- <int name="params/blend_mode"> 0 </int>
- <real name="params/line_width"> 0 </real>
- <bool name="fixed_flags/use_alpha"> False </bool>
- <bool name="fixed_flags/use_color_array"> False </bool>
- <bool name="fixed_flags/use_point_size"> False </bool>
- <color name="params/diffuse"> 0.702475, 0.707942, 0.727015, 1 </color>
- <color name="params/specular"> 0.351321, 0.35466, 0.377071, 1 </color>
- <color name="params/emission"> 0, 0, 0, 1 </color>
- <real name="params/specular_exp"> 34.20256 </real>
- <int name="params/detail_blend"> 0 </int>
- <real name="params/detail_mix"> 1 </real>
- <int name="params/normal_depth"> 1 </int>
- <real name="params/shade_param"> 0.5 </real>
- <int name="params/glow"> 0 </int>
- <real name="params/point_size"> 1 </real>
- <transform name="uv_xform"> 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 </transform>
- <resource name="textures/diffuse"></resource> <int name="textures/diffuse_tc"> 0 </int>
- <resource name="textures/detail"></resource> <int name="textures/detail_tc"> 0 </int>
- <resource name="textures/specular"></resource> <int name="textures/specular_tc"> 0 </int>
- <resource name="textures/emission"></resource> <int name="textures/emission_tc"> 0 </int>
- <resource name="textures/specular_exp"></resource> <int name="textures/specular_exp_tc"> 0 </int>
- <resource name="textures/glow"></resource> <int name="textures/glow_tc"> 0 </int>
- <resource name="textures/normal"></resource> <int name="textures/normal_tc"> 0 </int>
- <resource name="textures/shade_param"></resource> <int name="textures/shade_param_tc"> 0 </int>
-
- </resource>
- <resource type="FixedMaterial" path="local://4">
- <bool name="flags/visible"> True </bool>
- <bool name="flags/double_sided"> True </bool>
- <bool name="flags/invert_faces"> False </bool>
- <bool name="flags/unshaded"> False </bool>
- <bool name="flags/on_top"> False </bool>
- <bool name="flags/wireframe"> False </bool>
- <bool name="flags/billboard_sw"> False </bool>
- <bool name="hints/decal"> False </bool>
- <bool name="hints/opaque_pre_zpass"> False </bool>
- <bool name="hints/no_shadow"> False </bool>
- <bool name="hints/no_depth_draw"> False </bool>
- <int name="params/blend_mode"> 0 </int>
- <real name="params/line_width"> 0 </real>
- <bool name="fixed_flags/use_alpha"> False </bool>
- <bool name="fixed_flags/use_color_array"> False </bool>
- <bool name="fixed_flags/use_point_size"> False </bool>
- <color name="params/diffuse"> 0.0616188, 0.431354, 0.64, 1 </color>
- <color name="params/specular"> 0.5, 0.5, 0.5, 1 </color>
- <color name="params/emission"> 0.0196078, 0.235675, 0.675973, 1 </color>
- <real name="params/specular_exp"> 50 </real>
- <int name="params/detail_blend"> 0 </int>
- <real name="params/detail_mix"> 1 </real>
- <int name="params/normal_depth"> 1 </int>
- <real name="params/shade_param"> 0.5 </real>
- <real name="params/glow"> 0.4 </real>
- <real name="params/point_size"> 1 </real>
- <transform name="uv_xform"> 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 </transform>
- <resource name="textures/diffuse"></resource> <int name="textures/diffuse_tc"> 0 </int>
- <resource name="textures/detail"></resource> <int name="textures/detail_tc"> 0 </int>
- <resource name="textures/specular"></resource> <int name="textures/specular_tc"> 0 </int>
- <resource name="textures/emission"></resource> <int name="textures/emission_tc"> 0 </int>
- <resource name="textures/specular_exp"></resource> <int name="textures/specular_exp_tc"> 0 </int>
- <resource name="textures/glow"></resource> <int name="textures/glow_tc"> 0 </int>
- <resource name="textures/normal"></resource> <int name="textures/normal_tc"> 0 </int>
- <resource name="textures/shade_param"></resource> <int name="textures/shade_param_tc"> 0 </int>
-
- </resource>
- <resource type="Mesh" path="local://5">
- <string name="resource/name"> "Cube.002" </string>
- <dictionary name="surfaces/0" shared="false">
- <string> "alphasort" </string>
- <bool> False </bool>
- <string> "material" </string>
- <resource resource_type="FixedMaterial" path="local://3"> </resource>
- <string> "morph_arrays" </string>
- <array len="0" shared="false">
- </array>
- <string> "primitive" </string>
- <int> 4 </int>
- <string> "arrays" </string>
- <array len="9" shared="false">
- <vector3_array len="679"> 0.2607, 6.45948, 0.980779, 0.852531, 6.83043, 0.609826, 0.852531, 6.93043, 0.609826, 0.2607, 6.55948, 0.980779, 0, 7.06621, 0.103096, 0.955654, 7.06621, 0.103096, 0.852531, 6.93043, -0.403642, 0, 6.93043, -0.403642, 0, 6.45948, -0.774594, 0, 6.55948, -0.774594, 0.2607, 6.55948, -0.774594, 0.2607, 6.45948, -0.774594, 0, 6.45948, 0.980779, 0, 6.55948, 0.980779, 0.852531, 6.83043, -0.403642, 0.955654, 6.96621, 0.103096, 0, 6.93043, 0.609826, 1.70474, 3.5573, -0.353999, 1.71449, 3.62366, -0.198996, 1.77916, 3.62988, -0.16353, 1.76754, 3.55083, -0.34818, 1.71511, 3.58298, -0.0127468, 1.70308, 3.74367, 0.0692484, 1.80667, 3.81951, -0.174607, 1.52592, 3.24162, -0.0839551, 1.50573, 3.18374, -0.268539, 1.36446, 3.09798, -0.344433, 1.38154, 3.17921, -0.0161709, 2.44682, 3.07552, 0.376618, 2.28993, 2.80163, 0.457827, 2.52299, 2.59433, 0.553631, 2.69474, 2.85281, 0.479075, 2.53359, 3.02984, -0.15501, 2.55604, 3.1449, 0.136694, 2.79433, 2.92572, 0.24463, 2.78064, 2.80757, -0.0472709, 2.39441, 2.7167, -0.284614, 2.64285, 2.49755, -0.175588, 2.70938, 2.79639, 0.46437, 2.79808, 2.86134, 0.255559, 2.78589, 2.75611, -0.00442547, 2.66316, 2.47998, -0.118712, 2.38561, 2.31013, 0.396952, 2.36919, 2.23204, 0.0813577, 2.41942, 2.2435, 0.110139, 2.43405, 2.31306, 0.391226, 2.55641, 2.56618, 0.530774, 2.47334, 2.30784, -0.0772789, 2.51219, 2.31101, -0.0311523, 2.38859, 2.74151, 0.0599679, 2.38864, 2.7416, 0.0600288, 2.12663, 2.44425, -0.0282163, 2.22321, 2.52508, -0.185319, 2.13459, 2.5274, 0.293671, 0.173831, 0.925795, -0.251959, 0.323615, 0.972996, -0.416293, 0.50934, 0.00104547, -0.453384, 0.175987, 0.00104547, -0.331706, 0.916812, 0.888823, 0.214332, 0.549239, 0.836962, 0.37006, 0.552121, 0.665123, 0.401021, 0.944465, 0.443271, 0.182901, 0.631626, 1.83578, -0.105239, 0.721202, 1.70631, 0.188726, 0.913722, 0.95431, -0.169976, 0.478232, 1.53675, 0.317272, 0.454208, 1.69171, -0.268756, 0.63543, 0.987243, -0.370343, 0.262225, 1.39447, 0.162709, 0.170564, 0.859014, 0.160279, 0.255551, 1.52426, -0.294896, 0.126803, 1.32882, -0.0395796, 0.0660405, 0.880691, -0.102965, 0.19102, 1.40531, -0.162224, 0.256767, 1.56023, -0.0958005, 0.300707, 1.62315, -0.168503, 0.292542, 1.58081, -0.213789, 0.245079, 1.4957, -0.123593, 0.426543, 1.69115, -0.196413, 0.547313, 1.79071, -0.0844079, 0.586182, 1.83924, -0.0975873, 0.434509, 1.71208, -0.231916, 0.212253, 1.44274, -0.0415312, 0.220281, 1.46968, -0.143048, 0.175617, 1.41154, -0.0437374, 0.543306, 0.573346, 0.523815, 0.207486, 0.384965, 0.351051, 0.269976, 0.320526, 0.743389, 0.53325, 0.468211, 0.783185, 0.792721, 0.321493, 0.73458, 0.514523, 0.271138, 0.956088, 0.631719, 0.163855, 0.92639, 0.386424, 0.163401, 0.930524, 0.486595, 0.00104547, 1.08874, 0.326299, 0.00104547, 0.904533, 0.668445, 1.73174, 0.152757, 0.462058, 1.58268, 0.259184, 0.290415, 1.46398, 0.121989, 1.57608, 3.45117, -0.0476083, 1.50191, 3.29774, -0.132197, 1.61428, 3.4244, 0.016813, 1.66072, 3.58429, -0.072422, 1.62434, 3.38222, -0.419987, 1.67177, 3.34226, -0.426789, 1.48496, 3.24915, -0.287145, 1.54119, 3.29007, -0.372791, 1.57272, 3.23249, -0.370566, 1.79243, 3.69662, -0.478226, 1.47279, 3.17682, -0.509438, 1.6491, 3.37415, -0.611694, 1.52444, 3.47482, 0.146797, 1.97806, 2.60303, -0.0912834, 1.98619, 2.68696, 0.233771, 2.07568, 2.68462, -0.249978, 2.24859, 2.87814, -0.35026, 2.14291, 2.96404, 0.3995, 2.30152, 3.24052, 0.317542, 2.38915, 3.19439, -0.219368, 2.41174, 3.31063, 0.0752657, 0.0964089, 0.00104547, -0.196812, 0.154027, 0.441809, 0.19622, 0.835003, 0.00104547, -0.205403, 0.55748, 1.72198, 0.0964474, 0.425773, 1.62639, 0.166544, 0.447702, 1.58483, 0.201877, 0.611101, 1.70343, 0.114914, 0.506064, 1.79234, -0.0642154, 0.311982, 1.54621, 0.0812291, 0.30653, 1.48536, 0.0960338, 0.408718, 1.71209, -0.154497, 0.23599, 1.51185, -0.0296548, 0.272186, 1.57784, -0.251696, 0.0508581, 0.00104547, 0.0402964, 0.14499, 0.00104547, 0.619324, 0.916171, 0.00104547, 0.0302318, 0.874277, 0.386199, 0.339815, 0.82337, 0.00104547, 0.611434, 0.644625, 0.00104547, 0.90083, 0.19633, 0.00104547, -0.176104, 0.736495, 0.00104547, -0.182387, 0.85902, 0.00104547, 0.0313234, 0.108829, 0.00104547, 0.040049, 1.86783, 5.49219, -0.536097, 1.99626, 5.62831, -0.300326, 1.99626, 5.45781, -0.129823, 1.86783, 5.22204, -0.265945, 1.86783, 6.50041, -0.265945, 1.99626, 6.26464, -0.129823, 1.99626, 6.09414, -0.300326, 1.86783, 6.23026, -0.536097, 1.99626, 5.86123, -0.362734, 1.86783, 5.86123, -0.63498, 1.7, 6.62333, -0.336911, 1.7, 6.30123, -0.659013, 1.7, 5.42123, -0.659013, 1.7, 5.09912, -0.336911, 1.7, 5.86123, -0.776911, 1.6, 6.62333, 0.543096, 1.6, 6.30123, 0.865198, 1.7, 6.30123, 0.865198, 1.7, 6.62333, 0.543096, 1.6, 5.86123, 0.983096, 1.7, 5.86123, 0.983096, 1.6, 5.42123, 0.865198, 1.7, 5.42123, 0.865198, 1.6, 5.42123, -0.659013, 1.6, 5.09912, -0.336911, 1.6, 5.09913, 0.543096, 1.7, 5.09913, 0.543096, 1.6, 5.86123, -0.776911, 1.6, 4.98123, 0.103096, 1.7, 4.98123, 0.103096, 1.6, 6.30123, -0.659013, 1.6, 6.62333, -0.336911, 1.6, 6.74123, 0.103096, 1.7, 6.74123, 0.103096, 1.86783, 5.86123, 0.841165, 1.86783, 6.23026, 0.742282, 1.86783, 5.49219, 0.742282, 1.86783, 5.22204, 0.47213, 1.86783, 5.12316, 0.103096, 1.86783, 6.50041, 0.47213, 1.86783, 6.5993, 0.103096, 1.99626, 5.3954, 0.103096, 1.99626, 5.45781, 0.336007, 1.99626, 5.62832, 0.50651, 1.99626, 5.86123, 0.568919, 1.99626, 6.09414, 0.50651, 1.99626, 6.26464, 0.336007, 1.99626, 6.32705, 0.103096, 0.102832, 2.48009, 0.176006, 5.00021e-06, 2.4738, 0.177211, 5.00021e-06, 2.42055, 0.19141, 0.0988953, 2.42787, 0.190009, 0.149215, 2.70638, -0.125392, 0.228589, 2.63923, -0.0490058, 0.245228, 2.61305, -0.0718189, 0.152867, 2.69118, -0.160703, 5.00021e-06, 2.7271, -0.192857, 0.200279, 2.72863, -0.178996, 5.00021e-06, 2.77269, -0.218433, 0.254515, 2.5228, 0.0532499, 0.177509, 2.46933, 0.131427, 0.230502, 2.45653, 0.179303, 0.32495, 2.52211, 0.0834183, 0.31356, 2.6328, -0.0699792, 5.00021e-06, 2.38434, 0.263172, 0.134082, 2.39331, 0.261453, 4.89224e-06, 2.18251, 0.500372, 0.225093, 2.1995, 0.49518, 0.391925, 2.2292, 0.34273, 0.272307, 2.12215, 0.166987, 0.273286, 2.15284, 0.145033, 0.377566, 2.23301, 0.230347, 0.509219, 2.60277, -0.0602789, 0.306467, 2.75371, -0.22827, 0.384471, 2.30721, 0.355435, 5.53206e-06, 2.7678, -0.324424, 0.340915, 2.69228, -0.257391, 0.141881, 2.21642, -0.246023, 5.00021e-06, 2.24749, -0.273838, 0.226149, 2.1204, 0.482878, 5.00021e-06, 2.10499, 0.484715, 5.00021e-06, 1.97359, 0.0658354, 0.0951926, 1.97992, 0.0646229, 0.536694, 2.41886, 0.193185, 0.163197, 2.02451, 0.00668271, 5.00021e-06, 2.80311, -0.262553, 0.221777, 2.14883, -0.169134, 5.0058e-06, 2.08031, -0.179583, 4.99835e-06, 2.12243, -0.227502, 5.00021e-06, 1.97109, -0.0331461, 4.99835e-06, 1.97504, -0.0339018, 0.229811, 2.07077, -0.0609438, 5.0058e-06, 2.03165, -0.112157, 4.99835e-06, 2.00283, -0.0700111, 5.00021e-06, 2.14179, -0.244837, 0.549486, 2.33903, 0.185763, 0.532141, 2.52821, -0.0726373, 0.367385, 2.32682, -0.123862, 0.198102, 4.44663, -0.00271145, 0.535945, 4.16951, 0.521097, 0.681184, 4.27477, 0.307467, 0.0960235, 4.4178, 0.0939296, 0, 4.41627, 0.145479, 0, 4.10504, 0.75232, 0.295152, 4.11437, 0.707528, 0, 4.62654, -0.650476, 0.75197, 4.49872, -0.484507, 0.568386, 3.97815, -0.416848, 0, 4.0743, -0.542347, 0.453404, 3.62952, 1.15385, 0, 3.62251, 1.22471, 0, 3.3304, 0.897974, 0.354866, 3.3434, 0.864531, 0.713601, 4.46674, -0.124363, 1.03995, 4.04518, 0.442157, 1.12602, 4.3213, -0.0494407, 0, 4.73174, -0.547059, 0.464921, 4.64317, -0.424668, 0.716219, 4.58287, -0.480226, 0, 4.71901, -0.593658, 0.850048, 3.71295, 0.879328, 0.649196, 3.42772, 0.674737, 0.84841, 3.80937, 0.873472, 0.451539, 3.72707, 1.15037, 0.155937, 3.05577, 0.331006, 0.258719, 3.09481, 0.245674, 0.822291, 3.77674, 0.0641416, 0.359401, 3.14451, 0.132252, 0.226502, 3.30884, -0.183514, 0, 3.34718, -0.233548, 0, 3.04671, 0.334585, 1.1403, 4.19005, 0.0860849, 1.11025, 4.20631, -0.0820755, 0, 3.71833, 1.2227, 1.07207, 4.04817, 0.195228, 0.177538, 3.25078, -0.147598, 0, 3.28068, -0.186631, 0.249187, 2.13753, -0.031997, 0.20137, 2.11848, 0.0341487, 0.497933, 2.32861, 0.160251, 0.252884, 2.22978, -0.1047, 0.438171, 2.39896, -0.000411894, 0.941862, 3.86072, 0.194563, 0.997836, 4.10049, -0.213272, 0.87372, 3.89175, -0.186777, 0.347259, 3.23006, -0.0503454, 0.821813, 3.80214, -0.0657451, 0.908494, 3.91354, 0.153681, 1.01577, 4.06798, 0.154229, 1.07199, 4.18489, 0.0643051, 1.04723, 4.19828, -0.0742428, 2.0359, 6.20719, -0.0966551, 2.0359, 6.06097, -0.242878, 2.0359, 5.66148, -0.242878, 2.0359, 5.51526, -0.0966551, 2.0359, 5.86123, -0.296399, 2.0359, 5.86123, 0.502584, 2.0359, 6.06097, 0.449063, 2.0359, 5.66148, 0.449063, 2.0359, 5.51526, 0.30284, 2.0359, 5.46174, 0.103096, 2.0359, 6.20719, 0.30284, 2.0359, 6.26072, 0.103096, 0, 5.86123, 1.1031, 0, 5.47658, 1.00003, 0.329213, 5.47658, 1.00003, 0, 5.20179, 0.809688, 0, 4.9952, 0.603096, 0.329213, 5.20344, 0.811334, 1.15486, 6.36123, 0.969121, 1.2072, 6.11123, 1.03611, 1.39648, 6.36123, 0.969121, 0, 5.86123, -0.896911, 1.39648, 5.86123, -0.896911, 1.39648, 5.36123, -0.762936, 0, 5.36123, -0.762936, 1.39648, 4.9952, -0.396911, 0, 4.9952, -0.396911, 0.329213, 5.36123, 0.969121, 0.257147, 5.40641, 0.875976, 0.257146, 5.2834, 0.752961, 0, 5.49634, 0.900073, 0.257147, 5.49634, 0.900073, 0, 5.28211, 0.751677, 0.685695, 5.86123, 1.1031, 0.633352, 6.11123, 1.03611, 1.39648, 5.36123, 0.969121, 1.39648, 5.86123, 1.1031, 1.15486, 5.86123, 1.1031, 1.39648, 4.9952, 0.603096, 0.23657, 2.56168, 0.0584772, 0.170392, 2.51572, 0.125662, 5.00021e-06, 2.73725, -0.153025, 0.350345, 2.31871, -0.0906937, 0, 4.66231, -0.410127, 0.153299, 4.61636, -0.336561, 0.252264, 4.53307, -0.191655, 0.271744, 3.18932, -0.0437093, 0.122488, 3.05335, 0.253795, 0.202672, 3.0838, 0.187225, 0.281216, 3.12258, 0.0987407, 0, 3.04628, 0.256587, 0.954611, 4.1111, -0.182336, 0.85235, 3.93911, -0.160509, 0.809584, 3.86528, -0.0607897, 0.809978, 3.84435, 0.0462258, 0, 4.97587, -0.315884, 1.39648, 4.86123, 0.103096, 0.18642, 4.95573, -0.248219, 0.269727, 4.92174, -0.116503, 0.212301, 4.88556, 0.0356146, 0, 4.86123, 0.103096, 0.942888, 6.86123, 0.103096, 1.39648, 6.86123, 0.103096, 1.39648, 6.72725, -0.396911, 0.841135, 6.72725, -0.396911, 1.39648, 6.36123, -0.762936, 0.257165, 6.36123, -0.762936, 0.841135, 6.72725, 0.603096, 1.39648, 6.72725, 0.603096, 0, 6.36123, -0.762936, 0.257165, 6.36123, 0.969121, 0.685695, 6.36123, 0.969121, 0, 6.36123, 0.969121, -0.2607, 6.45948, 0.980779, -0.2607, 6.55948, 0.980779, -0.852531, 6.93043, 0.609826, -0.852531, 6.83043, 0.609826, -0.852531, 6.93043, -0.403642, -0.955654, 7.06621, 0.103096, -0.2607, 6.45948, -0.774594, -0.2607, 6.55948, -0.774594, -0.852531, 6.83043, -0.403642, -0.955654, 6.96621, 0.103096, -1.70474, 3.5573, -0.353999, -1.76754, 3.55083, -0.34818, -1.77916, 3.62988, -0.16353, -1.71449, 3.62366, -0.198996, -1.80667, 3.81951, -0.174607, -1.70308, 3.74367, 0.0692484, -1.71511, 3.58298, -0.0127468, -1.52592, 3.24162, -0.0839551, -1.38154, 3.17921, -0.0161709, -1.36446, 3.09798, -0.344433, -1.50573, 3.18374, -0.268539, -2.44682, 3.07552, 0.376618, -2.69474, 2.85281, 0.479075, -2.52299, 2.59433, 0.553631, -2.28993, 2.80163, 0.457827, -2.53359, 3.02984, -0.15501, -2.78064, 2.80757, -0.0472709, -2.79433, 2.92572, 0.24463, -2.55604, 3.1449, 0.136694, -2.39441, 2.7167, -0.284614, -2.64285, 2.49755, -0.175588, -2.79808, 2.86134, 0.255559, -2.70938, 2.79639, 0.46437, -2.66316, 2.47998, -0.118712, -2.78589, 2.75611, -0.00442547, -2.38561, 2.31013, 0.396952, -2.43405, 2.31306, 0.391226, -2.41942, 2.2435, 0.110139, -2.36919, 2.23204, 0.0813577, -2.55641, 2.56618, 0.530774, -2.51219, 2.31101, -0.0311523, -2.47334, 2.30784, -0.0772789, -2.38859, 2.74151, 0.0599679, -2.38864, 2.7416, 0.0600288, -2.12663, 2.44425, -0.0282163, -2.22321, 2.52508, -0.185319, -2.13459, 2.5274, 0.293671, -0.173831, 0.925795, -0.251959, -0.175987, 0.00104547, -0.331706, -0.50934, 0.00104547, -0.453384, -0.323615, 0.972996, -0.416293, -0.916812, 0.888823, 0.214332, -0.944465, 0.443271, 0.182901, -0.552121, 0.665123, 0.401021, -0.549239, 0.836962, 0.37006, -0.631626, 1.83578, -0.105239, -0.913722, 0.95431, -0.169976, -0.721202, 1.70631, 0.188726, -0.478232, 1.53675, 0.317272, -0.454208, 1.69171, -0.268756, -0.63543, 0.987243, -0.370343, -0.170564, 0.859014, 0.160279, -0.262225, 1.39447, 0.162709, -0.255551, 1.52426, -0.294896, -0.0660405, 0.880691, -0.102965, -0.126803, 1.32882, -0.0395796, -0.19102, 1.40531, -0.162224, -0.256767, 1.56023, -0.0958005, -0.245079, 1.4957, -0.123593, -0.292542, 1.58081, -0.213789, -0.300707, 1.62315, -0.168503, -0.426543, 1.69115, -0.196413, -0.434509, 1.71208, -0.231916, -0.586182, 1.83924, -0.0975873, -0.547313, 1.79071, -0.0844079, -0.212253, 1.44274, -0.0415312, -0.175617, 1.41154, -0.0437374, -0.220281, 1.46968, -0.143048, -0.543306, 0.573346, 0.523815, -0.53325, 0.468211, 0.783185, -0.269976, 0.320526, 0.743389, -0.207486, 0.384965, 0.351051, -0.792721, 0.321493, 0.73458, -0.631719, 0.163855, 0.92639, -0.514523, 0.271138, 0.956088, -0.386424, 0.163401, 0.930524, -0.486595, 0.00104547, 1.08874, -0.326299, 0.00104547, 0.904533, -0.462058, 1.58268, 0.259184, -0.668445, 1.73174, 0.152757, -0.290415, 1.46398, 0.121989, -1.57608, 3.45117, -0.0476083, -1.61428, 3.4244, 0.016813, -1.50191, 3.29774, -0.132197, -1.66072, 3.58429, -0.072422, -1.62434, 3.38222, -0.419987, -1.67177, 3.34226, -0.426789, -1.48496, 3.24915, -0.287145, -1.57272, 3.23249, -0.370566, -1.54119, 3.29007, -0.372791, -1.79243, 3.69662, -0.478226, -1.47279, 3.17682, -0.509438, -1.6491, 3.37415, -0.611694, -1.52444, 3.47482, 0.146797, -1.98619, 2.68696, 0.233771, -1.97806, 2.60303, -0.0912834, -2.07568, 2.68462, -0.249978, -2.24859, 2.87814, -0.35026, -2.14291, 2.96404, 0.3995, -2.30152, 3.24052, 0.317542, -2.38915, 3.19439, -0.219368, -2.41174, 3.31063, 0.0752657, -0.0964089, 0.00104547, -0.196812, -0.154027, 0.441809, 0.19622, -0.835003, 0.00104547, -0.205403, -0.55748, 1.72198, 0.0964474, -0.611101, 1.70343, 0.114914, -0.447702, 1.58483, 0.201877, -0.425773, 1.62639, 0.166544, -0.506064, 1.79234, -0.0642154, -0.30653, 1.48536, 0.0960338, -0.311982, 1.54621, 0.0812291, -0.408718, 1.71209, -0.154497, -0.23599, 1.51185, -0.0296548, -0.272186, 1.57784, -0.251696, -0.14499, 0.00104547, 0.619324, -0.0508581, 0.00104547, 0.0402964, -0.916171, 0.00104547, 0.0302318, -0.82337, 0.00104547, 0.611434, -0.874277, 0.386199, 0.339815, -0.644625, 0.00104547, 0.90083, -0.19633, 0.00104547, -0.176104, -0.108829, 0.00104547, 0.040049, -0.85902, 0.00104547, 0.0313234, -0.736495, 0.00104547, -0.182387, -1.86783, 5.49219, -0.536097, -1.86783, 5.22204, -0.265945, -1.99626, 5.45781, -0.129823, -1.99626, 5.62831, -0.300326, -1.86783, 6.50041, -0.265945, -1.86783, 6.23026, -0.536097, -1.99626, 6.09414, -0.300326, -1.99626, 6.26464, -0.129823, -1.86783, 5.86123, -0.63498, -1.99626, 5.86123, -0.362734, -1.7, 6.62333, -0.336911, -1.7, 6.30123, -0.659013, -1.7, 5.42123, -0.659013, -1.7, 5.09912, -0.336911, -1.7, 5.86123, -0.776911, -1.6, 6.62333, 0.543096, -1.7, 6.62333, 0.543096, -1.7, 6.30123, 0.865198, -1.6, 6.30123, 0.865198, -1.7, 5.86123, 0.983096, -1.6, 5.86123, 0.983096, -1.7, 5.42123, 0.865198, -1.6, 5.42123, 0.865198, -1.6, 5.42123, -0.659013, -1.6, 5.09912, -0.336911, -1.7, 5.09913, 0.543096, -1.6, 5.09913, 0.543096, -1.6, 5.86123, -0.776911, -1.7, 4.98123, 0.103096, -1.6, 4.98123, 0.103096, -1.6, 6.30123, -0.659013, -1.6, 6.62333, -0.336911, -1.6, 6.74123, 0.103096, -1.7, 6.74123, 0.103096, -1.86783, 6.23026, 0.742282, -1.86783, 5.86123, 0.841165, -1.86783, 5.49219, 0.742282, -1.86783, 5.22204, 0.47213, -1.86783, 5.12316, 0.103096, -1.86783, 6.5993, 0.103096, -1.86783, 6.50041, 0.47213, -1.99626, 5.45781, 0.336007, -1.99626, 5.3954, 0.103096, -1.99626, 5.86123, 0.568919, -1.99626, 5.62832, 0.50651, -1.99626, 6.09414, 0.50651, -1.99626, 6.26464, 0.336007, -1.99626, 6.32705, 0.103096, -0.102832, 2.48009, 0.176006, -0.0988953, 2.42787, 0.190009, -0.149215, 2.70638, -0.125392, -0.152867, 2.69118, -0.160703, -0.245228, 2.61305, -0.0718189, -0.228589, 2.63923, -0.0490058, -0.200279, 2.72863, -0.178996, -0.254515, 2.5228, 0.0532499, -0.32495, 2.52211, 0.0834183, -0.230502, 2.45653, 0.179303, -0.177509, 2.46933, 0.131427, -0.31356, 2.6328, -0.0699792, -0.134082, 2.39331, 0.261453, -0.225093, 2.1995, 0.49518, -0.391925, 2.2292, 0.34273, -0.377566, 2.23301, 0.230347, -0.273286, 2.15284, 0.145033, -0.272307, 2.12215, 0.166987, -0.306467, 2.75371, -0.22827, -0.509219, 2.60277, -0.0602789, -0.384471, 2.30721, 0.355435, -0.141881, 2.21642, -0.246023, -0.340915, 2.69228, -0.257391, -0.226149, 2.1204, 0.482878, -0.0951926, 1.97992, 0.0646229, -0.536694, 2.41886, 0.193185, -0.163197, 2.02451, 0.00668271, -0.221777, 2.14883, -0.169134, -0.229811, 2.07077, -0.0609438, -0.549486, 2.33903, 0.185763, -0.532141, 2.52821, -0.0726373, -0.367385, 2.32682, -0.123862, -0.198102, 4.44663, -0.00271145, -0.681184, 4.27477, 0.307467, -0.535945, 4.16951, 0.521097, -0.0960235, 4.4178, 0.0939296, -0.295152, 4.11437, 0.707528, -0.568386, 3.97815, -0.416848, -0.75197, 4.49872, -0.484507, -0.453404, 3.62952, 1.15385, -0.354866, 3.3434, 0.864531, -0.713601, 4.46674, -0.124363, -1.12602, 4.3213, -0.0494407, -1.03995, 4.04518, 0.442157, -0.716219, 4.58287, -0.480226, -0.464921, 4.64317, -0.424668, -0.850048, 3.71295, 0.879328, -0.649196, 3.42772, 0.674737, -0.84841, 3.80937, 0.873472, -0.451539, 3.72707, 1.15037, -0.258719, 3.09481, 0.245674, -0.155937, 3.05577, 0.331006, -0.822291, 3.77674, 0.0641416, -0.359401, 3.14451, 0.132252, -0.226502, 3.30884, -0.183514, -1.1403, 4.19005, 0.0860849, -1.11025, 4.20631, -0.0820755, -1.07207, 4.04817, 0.195228, -0.177538, 3.25078, -0.147598, -0.20137, 2.11848, 0.0341487, -0.249187, 2.13753, -0.031997, -0.497933, 2.32861, 0.160251, -0.252884, 2.22978, -0.1047, -0.438171, 2.39896, -0.000411894, -0.941862, 3.86072, 0.194563, -0.997836, 4.10049, -0.213272, -0.87372, 3.89175, -0.186777, -0.347259, 3.23006, -0.0503454, -0.821813, 3.80214, -0.0657451, -1.01577, 4.06798, 0.154229, -0.908494, 3.91354, 0.153681, -1.04723, 4.19828, -0.0742428, -1.07199, 4.18489, 0.0643051, -2.0359, 6.06097, -0.242878, -2.0359, 6.20719, -0.0966551, -2.0359, 5.51526, -0.0966551, -2.0359, 5.66148, -0.242878, -2.0359, 5.86123, -0.296399, -2.0359, 6.06097, 0.449063, -2.0359, 5.86123, 0.502584, -2.0359, 5.66148, 0.449063, -2.0359, 5.51526, 0.30284, -2.0359, 5.46174, 0.103096, -2.0359, 6.26072, 0.103096, -2.0359, 6.20719, 0.30284, -0.329213, 5.47658, 1.00003, -0.329213, 5.20344, 0.811334, -1.15486, 6.36123, 0.969121, -1.39648, 6.36123, 0.969121, -1.2072, 6.11123, 1.03611, -1.39648, 5.36123, -0.762936, -1.39648, 5.86123, -0.896911, -1.39648, 4.9952, -0.396911, -0.257146, 5.2834, 0.752961, -0.257147, 5.40641, 0.875976, -0.329213, 5.36123, 0.969121, -0.257147, 5.49634, 0.900073, -0.685695, 5.86123, 1.1031, -0.633352, 6.11123, 1.03611, -1.39648, 5.36123, 0.969121, -1.15486, 5.86123, 1.1031, -1.39648, 5.86123, 1.1031, -1.39648, 4.9952, 0.603096, -0.23657, 2.56168, 0.0584772, -0.170392, 2.51572, 0.125662, -0.350345, 2.31871, -0.0906937, -0.153299, 4.61636, -0.336561, -0.252264, 4.53307, -0.191655, -0.271744, 3.18932, -0.0437093, -0.202672, 3.0838, 0.187225, -0.122488, 3.05335, 0.253795, -0.281216, 3.12258, 0.0987407, -0.85235, 3.93911, -0.160509, -0.954611, 4.1111, -0.182336, -0.809584, 3.86528, -0.0607897, -0.809978, 3.84435, 0.0462258, -1.39648, 4.86123, 0.103096, -0.18642, 4.95573, -0.248219, -0.269727, 4.92174, -0.116503, -0.212301, 4.88556, 0.0356146, -0.942888, 6.86123, 0.103096, -0.841135, 6.72725, -0.396911, -1.39648, 6.72725, -0.396911, -1.39648, 6.86123, 0.103096, -0.257165, 6.36123, -0.762936, -1.39648, 6.36123, -0.762936, -1.39648, 6.72725, 0.603096, -0.841135, 6.72725, 0.603096, -0.257165, 6.36123, 0.969121, -0.685695, 6.36123, 0.969121 </vector3_array>
- <vector3_array len="679"> 0.323483, -0.753124, 0.572855, 0.771126, -0.534781, 0.345505, 0.599478, 0.562448, 0.569454, 0.202252, 0.315394, 0.927157, 0, 1, -0, 0.696021, 0.718022, -0, 0.599136, 0.562128, -0.57013, 0, 0.866019, -0.500011, 0, -0.789191, -0.614148, 0, 0.382911, -0.923785, 0.202065, 0.315101, -0.927298, 0.323297, -0.752692, -0.573527, 0, -0.789675, 0.613525, 0, 0.383265, 0.923638, 0.770859, -0.534596, -0.346386, 0.868674, -0.495384, 0, 0, 0.866452, 0.49926, 0.167052, 0.584181, -0.794246, 0.308094, 0.942288, -0.13104, -0.783538, 0.601413, -0.156107, -0.724538, 0.614456, -0.312232, -0.831821, 0.51651, -0.203201, -0.468553, 0.81396, 0.343405, -0.207013, 0.970059, -0.127008, -0.839933, 0.527586, -0.127141, -0.839469, 0.51929, -0.16009, -0.952083, -0.0830945, -0.294335, -0.969325, 0.0600821, 0.238326, -0.242219, 0.80573, 0.54049, -0.618771, 0.285356, 0.731912, -0.00900884, -0.126124, 0.991974, 0.500138, 0.3651, 0.785216, 0.0490036, 0.723054, -0.689051, 0.0889861, 0.993844, -0.0659897, 0.858321, 0.492184, 0.145054, 0.845097, 0.209024, -0.492057, -0.210106, 0.16008, -0.964484, 0.529219, -0.36215, -0.767317, 0.835061, -0.3935, 0.384488, 0.882867, -0.432425, 0.18318, 0.857612, -0.49035, 0.155111, 0.828872, -0.533561, 0.168177, -0.311554, -0.724288, 0.615094, -0.251244, -0.959933, -0.124121, 0.661603, -0.73467, 0.150137, 0.642912, -0.678963, 0.354503, 0.72766, -0.516469, 0.45141, 0.115162, -0.7841, -0.609856, 0.772162, -0.611128, 0.174036, 0.773373, -0.45522, 0.441213, 0.537341, -0.81952, 0.199126, -0.891041, -0.346405, -0.293343, -0.609658, -0.17619, -0.772835, -0.901333, -0.16224, 0.401594, -0.77153, 0.0690475, -0.632435, -0.315127, 0.0940378, -0.944379, 0.055046, -0.627524, -0.776649, -0.536581, -0.621673, -0.570617, 0.861095, 0.107012, 0.497055, -0.0380375, 0.0810799, 0.995982, -0.00700771, -0.117129, 0.993092, 0.797008, -0.304385, 0.521659, 0.524884, 0.803823, -0.279938, 0.595044, 0.585044, 0.551041, 0.871559, 0.129934, -0.472761, -0.200267, 0.367489, 0.90821, 0.0669956, 0.520966, -0.850944, 0.382844, 0.129947, -0.914628, -0.739262, 0.276472, 0.614048, -0.776468, 0.0611156, 0.627186, -0.58619, 0.359116, -0.726235, -0.959877, 0.277253, 0.0420384, -0.992667, 0.0720484, -0.0970652, -0.896641, 0.277198, -0.345247, -0.943047, 0.164182, -0.289321, -0.728454, 0.359224, -0.583363, -0.765447, 0.642375, 0.0380222, -0.855938, 0.516566, 0.0230252, -0.610501, 0.786645, -0.0920755, -0.477172, 0.854307, 0.206074, -0.309014, 0.951044, 0.00500023, -0.513202, 0.81332, -0.274108, -0.781621, 0.597475, 0.179142, -0.831231, 0.554821, 0.0350519, -0.80571, 0.57851, 0.127112, 0.0110026, 0.996233, -0.0860201, -0.616626, 0.733745, -0.28529, -0.740791, 0.504539, 0.443474, 0.0110097, 0.826727, 0.562495, 0.798668, 0.375314, 0.470393, 0.00700849, 0.548665, 0.836013, 0.68171, 0.189197, 0.706736, -0.65479, 0.336406, 0.676817, -0.0310549, -0.441781, 0.896585, -0.617121, -0.634152, 0.465846, -0.16707, 0.870366, 0.463195, -0.5063, 0.725429, 0.466276, -0.711913, 0.614788, 0.339435, -0.409744, 0.0530964, 0.910654, -0.764085, -0.38755, 0.515732, -0.847732, 0.508439, -0.15113, 0.0380266, 0.718502, 0.694485, -0.160029, 0.076014, -0.984181, -0.759497, 0.484317, -0.434284, -0.812045, -0.505651, -0.291375, -0.511638, -0.289361, -0.809009, -0.820559, 0.421287, -0.386263, -0.223103, 0.739342, -0.635294, -0.724353, 0.0750365, -0.685334, -0.43004, 0.304028, -0.850078, -0.80007, 0.434581, 0.413553, -0.0460378, -0.996819, -0.0650535, -0.0350519, -0.808196, 0.58787, 0.267172, -0.820528, -0.505325, 0.6294, -0.428272, -0.648412, 0.297403, -0.309419, 0.903223, 0.622553, 0.221196, 0.750666, 0.897953, 0.117994, -0.423978, 0.920375, 0.351143, 0.17207, -0.753305, -0.654134, 0.0681181, -0.674119, -0.252419, 0.694153, 0.713493, -0.691478, -0.113078, 0.455352, 0.602466, 0.655507, -0.318438, 0.223307, 0.921266, -0.564392, 0.704489, 0.430299, -0.398344, 0.805696, 0.438379, 0.565223, 0.681269, -0.465184, -0.74958, 0.0670519, 0.658509, -0.747893, 0.534638, 0.39347, -0.0789773, 0.541844, -0.83676, -0.969378, 0.150213, 0.194276, -0.723252, 0.667233, -0.178062, -0.702756, -0.294317, -0.647697, -0.77343, -0.576065, 0.264489, 0.64207, -0.336037, -0.689075, 0.714816, 0.636836, -0.288926, 0.692559, -0.68055, 0.239193, 0.560659, -0.716842, 0.414487, -0.216317, -0.957402, 0.19128, 0.194204, -0.972021, 0.132139, 0.711943, 0.135989, -0.688945, -0.686439, 0.302193, -0.661423, 0.776432, -0.314175, -0.546304, 0.886017, -0.231005, -0.402008, 0.886168, -0.401076, -0.232044, 0.776611, -0.545429, -0.315248, 0.776187, 0.546132, -0.315076, 0.885812, 0.401915, -0.231951, 0.885812, 0.231951, -0.401915, 0.776187, 0.315076, -0.546132, 0.885871, 0, -0.463932, 0.776359, 0, -0.630291, 0.327036, 0.818089, -0.473052, 0.327036, 0.473052, -0.818089, 0.32719, -0.472275, -0.818476, 0.327303, -0.817758, -0.473439, 0.327008, 0, -0.945022, -0.652547, 0.65655, 0.378317, -0.652728, 0.379423, 0.655732, 0.327303, 0.473439, 0.817758, 0.32719, 0.818476, 0.472275, -0.653098, 0, 0.757273, 0.327317, 0, 0.944915, -0.652976, -0.378566, 0.65598, 0.327458, -0.472662, 0.818145, -0.652547, -0.378317, -0.65655, -0.652728, -0.655732, -0.379423, -0.652976, -0.65598, 0.378566, 0.327458, -0.818145, 0.472662, -0.652603, 0, -0.7577, -0.653098, -0.757273, 0, 0.327317, -0.944915, 0, -0.6523, 0.379174, -0.656302, -0.6523, 0.656302, -0.379174, -0.652603, 0.7577, 0, 0.327008, 0.945022, -0, 0.776848, 0, 0.629688, 0.776611, 0.315248, 0.545429, 0.776856, -0.314346, 0.545601, 0.776856, -0.545601, 0.314346, 0.776848, -0.629688, 0, 0.776432, 0.546304, 0.314175, 0.776359, 0.630291, -0, 0.886281, -0.463147, 0, 0.886373, -0.401169, 0.231097, 0.886373, -0.231097, 0.401169, 0.886281, 0, 0.463147, 0.886168, 0.232044, 0.401076, 0.886017, 0.402008, 0.231005, 0.885871, 0.463932, -0, 0.320359, 0.0650729, 0.945059, 0, 0.0700382, 0.997544, 0, 0.642347, 0.766414, 0.0170187, 0.688755, 0.724794, 0.609974, 0.430981, -0.664971, 0.947519, 0.264145, -0.180099, 0.303207, 0.801547, 0.515352, 0.183115, 0.866546, 0.464292, 0, 0.882519, 0.470277, -0.0130118, 0.73066, 0.682617, 0, 0.706106, 0.708106, 0.225998, 0.736995, 0.636996, 0.221247, 0.645722, 0.730817, -0.0530284, 0.84045, 0.539289, -0.0270074, 0.825227, 0.564155, -0.0350336, 0.777746, 0.627602, 0, 0.830353, 0.557237, -0.0410178, 0.818354, 0.573248, 0, 0.314425, 0.949282, 0.27534, 0.29136, 0.916132, 0.778752, -0.489473, 0.392379, 0.746544, -0.651475, -0.135099, 0.272405, -0.803194, 0.529788, 0.652602, -0.667616, 0.35833, 0.671414, 0.730451, 0.125077, 0.357959, 0.928893, -0.0949891, 0.443473, 0.436465, 0.782835, 0, 0.377932, -0.925833, 0.555211, 0.240091, -0.796302, 0.325138, -0.340145, -0.882376, 0, -0.203036, -0.979171, 0.405354, -0.612535, 0.678593, 0, -0.671726, 0.7408, 0, -0.989545, 0.144225, 0.324316, -0.945923, 0.00700683, 0.678459, 0.508344, 0.530359, 0.581287, -0.797393, -0.16208, 0, 0.993246, -0.116029, 0.624575, -0.536494, -0.567522, 0, -0.741749, -0.670677, 0, -0.556084, -0.831126, 0, -0.999902, -0.0140126, 0, -0.966632, -0.256168, 0.738289, -0.658258, -0.147058, 0, -0.851521, -0.524321, 0, -0.900741, -0.434357, 0, -0.346076, -0.938206, 0.897164, -0.425078, 0.120022, 0.916025, -0.0850023, -0.392011, 0.746835, -0.537601, -0.391438, 0.24712, 0.836407, 0.489238, 0.187033, 0.840147, 0.509089, 0.180007, 0.858032, 0.481018, 0.245128, 0.817427, 0.521272, 0, 0.768221, 0.640184, 0, 0.834352, 0.551232, 0.143113, 0.833656, 0.53342, 0, 0.114054, -0.993474, 0.536767, 0.0429814, -0.842635, 0.34218, -0.328173, -0.880463, 0, -0.278155, -0.960536, 0.372421, -0.379429, 0.846957, 0, -0.377424, 0.926041, 0, -0.819843, 0.572589, 0.295296, -0.813817, 0.500502, 0.195064, 0.900294, 0.389127, 0.804875, 0.356387, 0.474516, 0.808731, 0.587804, -0.020993, 0, 0.994988, 0.0999987, 0.169127, 0.969729, 0.176132, 0.451126, 0.771215, -0.449125, 0, 0.777245, -0.629198, 0.78993, -0.410483, 0.455536, 0.657391, -0.729434, 0.189112, 0.705632, 0.319286, 0.632566, 0.308272, 0.411363, 0.857758, 0.231245, -0.951006, 0.205217, 0.47266, -0.881231, 0.00500699, 0.887311, -0.393138, -0.241085, 0.618412, -0.762508, -0.190127, 0.259028, -0.529057, -0.808087, 0, -0.471055, -0.882104, 0, -0.97194, 0.235228, 0.972719, -0.231933, -0.00499856, 0.748485, -0.564366, -0.348226, 0, 0.419376, 0.907813, 0.793691, -0.521454, -0.313273, 0.307062, -0.405082, -0.861174, 0, -0.36621, -0.930532, -0.256367, -0.749072, -0.610874, 0.241336, -0.969348, -0.0460641, 0.800238, -0.563168, -0.206061, 0.679395, -0.526306, -0.511297, 0.794806, -0.441448, -0.416422, 0.78099, -0.430994, -0.451994, 0.727309, -0.686292, 0.00500213, 0.915343, -0.34713, -0.204077, 0.535473, -0.673595, -0.50945, 0.971477, -0.237116, 0.00300147, 0.731118, -0.68011, -0.0540087, 0.849093, -0.528058, -0.0140015, 0.83344, -0.540285, -0.116061, 0.864591, -0.499341, -0.0560383, 0.984291, 0.153045, -0.088026, 0.984291, 0.088026, -0.153045, 0.984377, -0.0870333, -0.153059, 0.984441, -0.152068, -0.0880395, 0.984378, 0, -0.176068, 0.984551, 0, 0.175098, 0.984441, 0.0880395, 0.152068, 0.984527, -0.0870466, 0.152081, 0.984527, -0.152081, 0.0870466, 0.984551, -0.175098, 0, 0.984377, 0.153059, 0.0870333, 0.984378, 0.176068, -0, 0, 0, 1, 0, -0.848897, 0.528558, -0.210351, -0.405676, 0.889483, 0, -0.0810577, 0.996709, 0, -0.92105, 0.389444, -0.197353, -0.573024, 0.795421, -0.167145, 0.336293, 0.926806, -0.401672, 0.237397, 0.884479, 0.653302, 0.379175, 0.655303, 0, 0, -1, 0.653177, 0, -0.757205, 0.653121, -0.37807, -0.656122, 0, -0.49926, -0.866452, 0.671631, -0.686645, -0.278262, 0, -0.926881, -0.375357, -0.433934, -0.447965, 0.781683, -0.4965, -0.437441, 0.749755, -0.353503, -0.137195, 0.925318, 0, -0.848897, 0.528558, -0.359502, -0.75906, 0.542758, 0, -0.0770792, 0.997025, 0.168109, 0.172111, 0.970627, 0.402511, 0.237301, 0.884123, 0.65355, -0.378318, 0.655551, 0.653672, 0, 0.756778, -0.167136, 0.17214, 0.97079, 0.668803, -0.684822, 0.289347, 0.880048, 0.129007, 0.457025, 0.644507, 0.0390307, 0.763601, 0, 0.542878, -0.839811, 0.823173, -0.419088, -0.383081, 0, 0.941447, 0.33716, 0.175995, 0.932972, 0.31399, 0.269002, 0.885006, 0.380003, 0.644374, -0.493286, -0.584339, 0.355385, -0.786851, 0.504546, 0.641692, -0.681736, 0.351379, 0.758512, -0.647437, -0.07405, 0, -0.746027, 0.665916, 0.905274, -0.411124, -0.107032, 0.759428, -0.614346, -0.214121, 0.64053, -0.74862, -0.171142, 0.712784, -0.693763, -0.103113, 0, -0.812786, -0.582563, 0.707572, -0.706571, 0.0100081, 0.463983, -0.666975, -0.582978, 0.721736, -0.682696, -0.114116, 0.557506, -0.667605, 0.493448, 0, -0.762778, 0.64666, -0.001, 1, 0, 0.653177, 0.757205, -0, 0.652874, 0.655873, -0.378927, -0.0379873, 0.86471, -0.500832, 0.652874, 0.378927, -0.655873, -0.0350082, 0.578135, -0.81519, -0.0380063, 0.865143, 0.500083, 0.653121, 0.656122, 0.37807, 0, 0.610194, -0.792252, -0.0350367, 0.578606, 0.814854, 0.168118, 0.336236, 0.926651, 0, 0.610678, 0.791879, -0.322586, -0.753368, 0.57304, -0.201292, 0.315457, 0.927345, -0.598836, 0.562786, 0.569796, -0.77072, -0.535194, 0.345772, -0.598495, 0.562465, -0.570471, -0.695505, 0.718521, 0, -0.322401, -0.752935, -0.573713, -0.201105, 0.315165, -0.927485, -0.770452, -0.535009, -0.346654, -0.868428, -0.495815, 0, -0.166079, 0.584278, -0.794378, 0.725013, 0.614011, -0.312005, 0.783924, 0.600942, -0.155985, -0.307188, 0.942578, -0.13108, 0.20797, 0.969858, -0.126981, 0.469334, 0.813578, 0.343244, 0.832129, 0.51608, -0.203032, 0.840228, 0.527143, -0.127034, 0.969385, 0.0600239, 0.238095, 0.952177, -0.0830154, -0.294055, 0.839764, 0.518854, -0.159955, 0.243161, 0.805534, 0.540358, -0.499387, 0.365283, 0.785609, 0.0100097, -0.126123, 0.991964, 0.619388, 0.285179, 0.731458, -0.0480059, 0.723089, -0.689085, -0.844811, 0.209201, -0.492473, -0.858057, 0.492607, 0.145179, -0.087994, 0.993932, -0.0659955, 0.211062, 0.160047, -0.964281, -0.528498, -0.362341, -0.767723, -0.882646, -0.432807, 0.183342, -0.834757, -0.393829, 0.38481, -0.828558, -0.534004, 0.168317, -0.857347, -0.490771, 0.155244, 0.312458, -0.724062, 0.614902, -0.642324, -0.679401, 0.354731, -0.66104, -0.735157, 0.150236, 0.252182, -0.959691, -0.124089, -0.727189, -0.516845, 0.451739, -0.771757, -0.6116, 0.174171, -0.114173, -0.784191, -0.609926, -0.772971, -0.455572, 0.441554, -0.536629, -0.819961, 0.199233, 0.891247, -0.346096, -0.293081, 0.610287, -0.176083, -0.772363, 0.90152, -0.162094, 0.401232, 0.771935, 0.0689942, -0.631947, 0.537293, -0.621339, -0.570311, -0.0540481, -0.627558, -0.776691, 0.316027, 0.0940081, -0.944081, -0.860836, 0.107104, 0.497483, -0.796642, -0.304628, 0.522076, 0.00800875, -0.117128, 0.993085, 0.039037, 0.0810768, 0.995943, -0.524159, 0.804245, -0.280085, -0.871318, 0.130047, -0.473173, -0.594398, 0.585392, 0.551369, 0.201228, 0.367416, 0.908027, -0.0660001, 0.521001, -0.851001, -0.381991, 0.129997, -0.914978, 0.776865, 0.061068, 0.626698, 0.739716, 0.276267, 0.613594, 0.586846, 0.358906, -0.725809, 0.992681, 0.0719769, -0.0969689, 0.959955, 0.276987, 0.0419981, 0.896837, 0.27695, -0.344937, 0.943158, 0.164027, -0.289048, 0.856205, 0.516124, 0.0230055, 0.765861, 0.641883, 0.0379931, 0.728923, 0.358962, -0.582938, 0.611128, 0.786165, -0.0920193, 0.513938, 0.812902, -0.273967, 0.309918, 0.95075, 0.00499869, 0.477944, 0.853899, 0.205976, 0.78201, 0.597008, 0.179002, 0.806061, 0.578044, 0.12701, 0.83154, 0.55436, 0.0350227, -0.0100024, 0.996243, -0.086021, -0.0100089, 0.826736, 0.562501, 0.741242, 0.504165, 0.443145, 0.617246, 0.733292, -0.285114, -0.798305, 0.375614, 0.470769, -0.681174, 0.189326, 0.707219, -0.00600732, 0.548668, 0.836019, 0.655362, 0.336185, 0.676373, 0.0320557, -0.441767, 0.896557, 0.617741, -0.63376, 0.465558, 0.507043, 0.725062, 0.46604, 0.168043, 0.870221, 0.463117, 0.712406, 0.61435, 0.339193, 0.410577, 0.0530746, 0.91028, 0.848013, 0.508008, -0.151002, 0.764501, -0.387254, 0.515338, -0.0370272, 0.718529, 0.694511, 0.161004, 0.0760018, -0.984023, 0.75992, 0.483949, -0.433954, 0.812386, -0.50524, -0.291138, 0.820886, 0.420942, -0.385946, 0.512377, -0.289213, -0.808595, 0.224054, 0.739177, -0.635152, 0.724828, 0.0749822, -0.684837, 0.430854, 0.303897, -0.849712, 0.80043, 0.434233, 0.413222, 0.0360521, -0.808167, 0.587849, 0.0470365, -0.996773, -0.0650504, -0.266242, -0.820747, -0.50546, -0.628795, -0.428542, -0.648821, -0.296489, -0.309511, 0.903492, -0.621939, 0.221334, 0.751134, -0.897759, 0.1181, -0.424359, -0.920222, 0.351467, 0.172229, 0.753738, -0.65364, 0.0680667, 0.674665, -0.252249, 0.693684, -0.713001, -0.691972, -0.113159, -0.454558, 0.60274, 0.655806, 0.399186, 0.805375, 0.438204, 0.565073, 0.704091, 0.430056, 0.319337, 0.223236, 0.920972, -0.564542, 0.681654, -0.465447, 0.748334, 0.534238, 0.393175, 0.750018, 0.0670016, 0.658015, 0.0799707, 0.541802, -0.836693, 0.969438, 0.150068, 0.194088, 0.723729, 0.66675, -0.177933, 0.773832, -0.575619, 0.264284, 0.703262, -0.29411, -0.647241, -0.641482, -0.336253, -0.689518, -0.692038, -0.681022, 0.239359, -0.714327, 0.637291, -0.289132, -0.559972, -0.717244, 0.41472, 0.217271, -0.957194, 0.191239, 0.686968, 0.301986, -0.660969, -0.711449, 0.136086, -0.689435, -0.19324, -0.972209, 0.132164, -0.776034, -0.314419, -0.546728, -0.776214, -0.545854, -0.315493, -0.885953, -0.401432, -0.23225, -0.885802, -0.231209, -0.402364, -0.775789, 0.546556, -0.315321, -0.775789, 0.315321, -0.546556, -0.885597, 0.232156, -0.402271, -0.885597, 0.402271, -0.232156, -0.775961, 0, -0.630781, -0.885655, 0, -0.464344, -0.326142, 0.818357, -0.473206, -0.326142, 0.473206, -0.818357, -0.326296, -0.472429, -0.818744, -0.326409, -0.818026, -0.473594, -0.326114, 0, -0.94533, 0.653121, 0.656122, 0.37807, -0.326296, 0.818744, 0.472429, -0.326409, 0.473594, 0.818026, 0.653302, 0.379175, 0.655303, -0.326423, 0, 0.945224, 0.653672, 0, 0.756778, -0.326564, -0.472817, 0.818413, 0.65355, -0.378318, 0.655551, 0.653121, -0.37807, -0.656122, 0.653302, -0.655303, -0.379175, -0.326564, -0.818413, 0.472817, 0.65355, -0.655551, 0.378318, 0.653177, 0, -0.757205, -0.326423, -0.945224, 0, 0.653672, -0.756778, 0, 0.652874, 0.378927, -0.655873, 0.652874, 0.655873, -0.378927, 0.653177, 0.757205, -0, -0.326114, 0.94533, 0, -0.776214, 0.315493, 0.545854, -0.776451, 0, 0.630178, -0.776459, -0.314591, 0.546026, -0.776459, -0.546026, 0.314591, -0.776451, -0.630178, 0, -0.775961, 0.630781, 0, -0.776034, 0.546728, 0.314419, -0.886159, -0.401525, 0.231302, -0.886067, -0.463558, 0, -0.886067, 0, 0.463558, -0.886159, -0.231302, 0.401525, -0.885953, 0.23225, 0.401432, -0.885802, 0.402364, 0.231209, -0.885655, 0.464344, 0, -0.31946, 0.0650937, 0.945361, -0.0160178, 0.688766, 0.724806, -0.609345, 0.431244, -0.665377, -0.182148, 0.866704, 0.464377, -0.302298, 0.80179, 0.515508, -0.947416, 0.264395, -0.18027, 0.0140125, 0.730651, 0.682608, -0.225049, 0.737161, 0.637139, 0.0280069, 0.825204, 0.56414, 0.054026, 0.840405, 0.53926, -0.220295, 0.645864, 0.730978, 0.0360333, 0.777718, 0.62758, 0.0420165, 0.81832, 0.573224, -0.274414, 0.29144, 0.916384, -0.778358, -0.489855, 0.392685, -0.652026, -0.668052, 0.358564, -0.271477, -0.803413, 0.529932, -0.746101, -0.651962, -0.135199, -0.357087, 0.929225, -0.095023, -0.670864, 0.730942, 0.125161, -0.442668, 0.436659, 0.783182, -0.324243, -0.340255, -0.882662, -0.554518, 0.240224, -0.796745, -0.404517, -0.612784, 0.678868, -0.323422, -0.946236, 0.00600785, -0.677918, 0.508689, 0.530719, -0.580624, -0.797857, -0.162174, -0.623964, -0.536829, -0.567877, -0.737833, -0.658744, -0.147166, -0.896969, -0.42546, 0.12013, -0.915864, -0.0850803, -0.39237, -0.746391, -0.538003, -0.39173, -0.246181, 0.836614, 0.489359, -0.179039, 0.858186, 0.481104, -0.186067, 0.840304, 0.509184, -0.244187, 0.817627, 0.5214, -0.142132, 0.833775, 0.533496, -0.341296, -0.328285, -0.880764, -0.536055, 0.0430044, -0.843087, -0.371558, -0.37957, 0.847273, -0.294382, -0.814057, 0.50065, -0.194101, 0.90047, 0.389203, -0.808384, 0.58828, -0.02101, -0.804522, 0.356675, 0.474898, -0.450328, 0.771563, -0.449328, -0.168155, 0.969892, 0.176162, -0.789553, -0.410808, 0.455897, -0.656822, -0.729914, 0.189237, -0.705129, 0.319511, 0.633013, -0.307366, 0.41149, 0.858022, -0.471882, -0.881648, 0.00500936, -0.230297, -0.951225, 0.205264, -0.887098, -0.393487, -0.241299, -0.617794, -0.76298, -0.190244, -0.258094, -0.529194, -0.808295, -0.972665, -0.232159, -0.00500342, -0.748045, -0.564789, -0.348487, -0.79332, -0.521869, -0.313522, -0.306156, -0.405206, -0.861439, -0.240392, -0.969582, -0.0460752, 0.257302, -0.748879, -0.610717, -0.799878, -0.563619, -0.206226, -0.678856, -0.526664, -0.511645, -0.794437, -0.441799, -0.416754, -0.780599, -0.431331, -0.452347, -0.726837, -0.686791, 0.00500577, -0.915181, -0.347448, -0.204264, -0.534758, -0.673956, -0.509723, -0.97142, -0.237347, 0.00300439, -0.848814, -0.528507, -0.0140134, -0.730652, -0.680607, -0.0540482, -0.864338, -0.499774, -0.0560868, -0.833134, -0.540736, -0.116158, -0.98426, 0.0881128, -0.153196, -0.98426, 0.153196, -0.0881128, -0.98441, -0.152218, -0.0881262, -0.984346, -0.0871191, -0.15321, -0.984347, 0, -0.176241, -0.98441, 0.0881262, 0.152218, -0.98452, 0, 0.175271, -0.984497, -0.0871325, 0.152231, -0.984497, -0.152231, 0.0871325, -0.98452, -0.175271, 0, -0.984347, 0.176241, 0, -0.984346, 0.15321, 0.0871191, 0.211308, -0.405591, 0.889295, 0.198315, -0.572911, 0.795264, 0.168118, 0.336236, 0.926651, -0.652728, 0.379423, 0.655732, 0.402511, 0.237301, 0.884123, -0.652547, -0.378317, -0.65655, -0.652603, 0, -0.7577, -0.671081, -0.687107, -0.278449, 0.354379, -0.137147, 0.92499, 0.497254, -0.437223, 0.749383, 0.434747, -0.44777, 0.781343, 0.360374, -0.758786, 0.542562, -0.167136, 0.17214, 0.97079, -0.401672, 0.237397, 0.884479, -0.652976, -0.378566, 0.65598, 0.168109, 0.172111, 0.970627, -0.653098, 0, 0.757273, -0.668249, -0.685281, 0.289541, -0.879823, 0.129121, 0.457428, -0.643922, 0.0390559, 0.764094, -0.82285, -0.419434, -0.383396, -0.175025, 0.933135, 0.314046, -0.268074, 0.885244, 0.380105, -0.643788, -0.493604, -0.584716, -0.641103, -0.682174, 0.351605, -0.354509, -0.787131, 0.504725, -0.758087, -0.647929, -0.0741063, -0.759004, -0.614813, -0.214283, -0.905093, -0.411497, -0.107129, -0.639939, -0.7491, -0.171251, -0.712291, -0.694258, -0.103187, -0.707071, -0.707071, 0.0100152, -0.463198, -0.667285, -0.583249, -0.721256, -0.68319, -0.114199, -0.556815, -0.667978, 0.493723, 0.002, 0.999998, -0, 0.0389854, 0.864677, -0.500813, -0.6523, 0.656302, -0.379174, -0.652603, 0.7577, 0, 0.0360071, 0.578114, -0.815161, -0.6523, 0.379174, -0.656302, -0.652547, 0.65655, 0.378317, 0.039005, 0.86511, 0.500063, 0.0360365, 0.578586, 0.814825, -0.167145, 0.336293, 0.926806 </vector3_array>
- <nil> </nil>
- <nil> </nil>
- <nil> </nil>
- <nil> </nil>
- <real_array len="2716"> 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 9, 8, 0, 0, 8, 9, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 12, 13, 0, 0, 12, 13, 0, 0, 13, 12, 0, 0, 13, 12, 0, 0, 13, 12, 0, 0, 13, 12, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 12, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 9, 8, 0, 0, 8, 9, 0, 0, 9, 0, 0, 0, 8, 9, 0, 0, 9, 8, 0, 0, 9, 0, 0, 0, 8, 9, 0, 0, 8, 9, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 12, 13, 0, 0, 12, 13, 0, 0, 13, 12, 0, 0, 13, 12, 0, 0, 12, 13, 0, 0, 12, 13, 0, 0, 13, 12, 0, 0, 12, 13, 0, 0, 12, 13, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 12, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 7, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 11, 10, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 10, 11, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 15, 16, 0, 0, 16, 15, 0, 0, 16, 15, 0, 0, 15, 16, 0, 0, 16, 15, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 15, 0, 0, 16, 15, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 11, 10, 0, 0, 11, 0, 0, 0, 10, 11, 0, 0, 10, 11, 0, 0, 11, 10, 0, 0, 11, 0, 0, 0, 10, 11, 0, 0, 11, 0, 0, 0, 10, 11, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 15, 16, 0, 0, 16, 15, 0, 0, 16, 15, 0, 0, 15, 16, 0, 0, 15, 16, 0, 0, 16, 15, 0, 0, 15, 16, 0, 0, 15, 16, 0, 0, 15, 16, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 15, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0 </real_array>
- <real_array len="2716"> 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.5, 0.5, 0, 0, 0.503159, 0.496841, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.700171, 0.299829, 0, 0, 0.66474, 0.33526, 0, 0, 0.704636, 0.295364, 0, 0, 0.664742, 0.335258, 0, 0, 0.719812, 0.280188, 0, 0, 0.682575, 0.317425, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.664813, 0.335187, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.533212, 0.466788, 0, 0, 0.538228, 0.461772, 0, 0, 1, 0, 0, 0, 0.500006, 0.499994, 0, 0, 0.525218, 0.474782, 0, 0, 1, 0, 0, 0, 0.563768, 0.436232, 0, 0, 0.523139, 0.476861, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.665519, 0.334481, 0, 0, 0.664658, 0.335342, 0, 0, 0.676033, 0.323967, 0, 0, 0.667711, 0.332289, 0, 0, 0.668675, 0.331325, 0, 0, 0.673479, 0.326521, 0, 0, 0.667424, 0.332576, 0, 0, 0.6672, 0.3328, 0, 0, 0.664792, 0.335208, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.500004, 0.499996, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.997415, 0.00258508, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.5, 0.5, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.503159, 0.496841, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.700171, 0.299829, 0, 0, 0.664742, 0.335258, 0, 0, 0.704636, 0.295364, 0, 0, 0.66474, 0.33526, 0, 0, 0.719812, 0.280188, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.682575, 0.317425, 0, 0, 0.664813, 0.335187, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.533212, 0.466788, 0, 0, 1, 0, 0, 0, 0.538228, 0.461772, 0, 0, 0.500006, 0.499994, 0, 0, 0.525218, 0.474782, 0, 0, 1, 0, 0, 0, 0.563768, 0.436232, 0, 0, 1, 0, 0, 0, 0.523139, 0.476861, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.665519, 0.334481, 0, 0, 0.667711, 0.332289, 0, 0, 0.676033, 0.323967, 0, 0, 0.664658, 0.335342, 0, 0, 0.668675, 0.331325, 0, 0, 0.667424, 0.332576, 0, 0, 0.673479, 0.326521, 0, 0, 0.6672, 0.3328, 0, 0, 0.664792, 0.335208, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.500004, 0.499996, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 </real_array>
- <int_array len="3246"> 0, 2, 1, 0, 3, 2, 4, 6, 5, 4, 7, 6, 8, 10, 9, 8, 11, 10, 12, 3, 0, 12, 13, 3, 11, 6, 10, 11, 14, 6, 14, 5, 6, 14, 15, 5, 1, 5, 15, 1, 2, 5, 4, 2, 16, 4, 5, 2, 16, 3, 13, 16, 2, 3, 7, 10, 6, 7, 9, 10, 17, 19, 18, 17, 20, 19, 19, 22, 21, 19, 23, 22, 24, 26, 25, 24, 27, 26, 28, 30, 29, 28, 31, 30, 32, 34, 33, 32, 35, 34, 33, 31, 28, 33, 34, 31, 36, 35, 32, 36, 37, 35, 34, 38, 31, 34, 39, 38, 37, 40, 35, 37, 41, 40, 42, 44, 43, 42, 45, 44, 31, 46, 30, 31, 38, 46, 35, 39, 34, 35, 40, 39, 43, 48, 47, 43, 44, 48, 47, 41, 37, 47, 48, 41, 30, 45, 42, 30, 46, 45, 44, 49, 48, 48, 49, 41, 46, 49, 45, 39, 50, 38, 41, 50, 40, 41, 49, 50, 45, 49, 44, 38, 49, 46, 38, 50, 49, 40, 50, 39, 51, 47, 52, 51, 43, 47, 52, 37, 36, 52, 47, 37, 53, 43, 51, 53, 42, 43, 29, 42, 53, 29, 30, 42, 54, 56, 55, 54, 57, 56, 58, 60, 59, 58, 61, 60, 62, 58, 63, 62, 64, 58, 63, 59, 65, 63, 58, 59, 66, 64, 62, 66, 67, 64, 65, 69, 68, 65, 59, 69, 70, 67, 66, 70, 55, 67, 68, 72, 71, 68, 69, 72, 73, 55, 70, 73, 54, 55, 74, 76, 75, 74, 77, 76, 78, 80, 79, 78, 81, 80, 82, 83, 77, 82, 84, 83, 85, 87, 86, 85, 88, 87, 89, 90, 88, 89, 91, 90, 88, 92, 87, 88, 90, 92, 91, 93, 90, 90, 93, 92, 92, 93, 94, 55, 56, 67, 65, 95, 63, 65, 96, 95, 68, 96, 65, 68, 97, 96, 71, 54, 73, 71, 72, 54, 98, 24, 99, 98, 100, 24, 18, 21, 101, 18, 19, 21, 102, 20, 17, 102, 103, 20, 99, 25, 104, 99, 24, 25, 101, 100, 98, 101, 21, 100, 104, 106, 105, 104, 25, 106, 105, 103, 102, 105, 106, 103, 20, 23, 19, 20, 107, 23, 25, 108, 106, 25, 26, 108, 106, 109, 103, 106, 108, 109, 100, 27, 24, 100, 110, 27, 103, 107, 20, 103, 109, 107, 21, 110, 100, 21, 22, 110, 27, 111, 26, 27, 112, 111, 26, 113, 108, 26, 111, 113, 108, 114, 109, 108, 113, 114, 110, 112, 27, 110, 115, 112, 22, 115, 110, 22, 116, 115, 109, 117, 107, 109, 114, 117, 107, 118, 23, 107, 117, 118, 23, 116, 22, 23, 118, 116, 72, 57, 54, 72, 119, 57, 59, 120, 69, 59, 60, 120, 64, 61, 58, 64, 121, 61, 69, 119, 72, 69, 120, 119, 122, 124, 123, 122, 125, 124, 126, 125, 122, 126, 79, 125, 123, 128, 127, 123, 124, 128, 129, 79, 126, 129, 78, 79, 130, 77, 74, 130, 82, 77, 75, 78, 129, 75, 76, 78, 127, 82, 130, 127, 128, 82, 124, 97, 128, 124, 96, 97, 79, 95, 125, 79, 80, 95, 128, 84, 82, 128, 97, 84, 76, 81, 78, 76, 131, 81, 77, 131, 76, 77, 83, 131, 125, 96, 124, 125, 95, 96, 86, 133, 132, 86, 87, 133, 134, 89, 135, 134, 136, 89, 135, 88, 85, 135, 89, 88, 136, 91, 89, 136, 137, 91, 87, 94, 133, 87, 92, 94, 137, 93, 91, 67, 121, 64, 67, 56, 121, 83, 70, 131, 83, 73, 70, 73, 84, 71, 73, 83, 84, 63, 80, 62, 63, 95, 80, 66, 131, 70, 66, 81, 131, 97, 71, 84, 97, 68, 71, 81, 62, 80, 81, 66, 62, 138, 140, 139, 138, 141, 140, 57, 139, 56, 138, 139, 119, 119, 139, 57, 56, 139, 121, 132, 136, 134, 132, 133, 136, 137, 133, 94, 137, 136, 133, 94, 93, 137, 142, 144, 143, 142, 145, 144, 146, 148, 147, 146, 149, 148, 149, 150, 148, 149, 151, 150, 151, 143, 150, 151, 142, 143, 152, 149, 146, 152, 153, 149, 154, 145, 142, 154, 155, 145, 156, 142, 151, 156, 154, 142, 153, 151, 149, 153, 156, 151, 157, 159, 158, 157, 160, 159, 158, 162, 161, 158, 159, 162, 161, 164, 163, 161, 162, 164, 165, 155, 154, 165, 166, 155, 163, 168, 167, 163, 164, 168, 169, 154, 156, 169, 165, 154, 167, 171, 170, 167, 168, 171, 172, 156, 153, 172, 169, 156, 173, 153, 152, 173, 172, 153, 174, 160, 157, 174, 175, 160, 159, 176, 162, 159, 177, 176, 162, 178, 164, 162, 176, 178, 164, 179, 168, 164, 178, 179, 168, 180, 171, 168, 179, 180, 175, 181, 160, 175, 182, 181, 160, 177, 159, 160, 181, 177, 179, 183, 180, 179, 184, 183, 176, 185, 178, 176, 186, 185, 177, 186, 176, 177, 187, 186, 181, 187, 177, 181, 188, 187, 178, 184, 179, 178, 185, 184, 182, 188, 181, 182, 189, 188, 182, 147, 189, 182, 146, 147, 145, 183, 144, 145, 180, 183, 175, 146, 182, 175, 152, 146, 155, 180, 145, 155, 171, 180, 174, 152, 175, 174, 173, 152, 166, 171, 155, 166, 170, 171, 190, 192, 191, 190, 193, 192, 194, 196, 195, 194, 197, 196, 198, 199, 197, 198, 200, 199, 201, 203, 202, 201, 204, 203, 197, 205, 196, 197, 199, 205, 193, 206, 192, 193, 207, 206, 196, 204, 201, 196, 205, 204, 202, 207, 193, 202, 203, 207, 207, 208, 206, 207, 209, 208, 210, 212, 211, 210, 213, 212, 199, 214, 205, 199, 215, 214, 203, 209, 207, 203, 216, 209, 217, 219, 218, 217, 220, 219, 221, 223, 222, 221, 224, 223, 205, 225, 204, 205, 214, 225, 204, 216, 203, 204, 225, 216, 224, 211, 226, 221, 211, 224, 210, 211, 221, 200, 215, 199, 200, 227, 215, 219, 229, 228, 219, 230, 229, 224, 231, 223, 224, 232, 231, 228, 234, 233, 228, 229, 234, 226, 232, 224, 226, 235, 232, 220, 230, 219, 220, 236, 230, 233, 235, 226, 233, 234, 235, 237, 214, 238, 237, 225, 214, 215, 238, 214, 215, 218, 238, 218, 227, 217, 218, 215, 227, 221, 216, 210, 221, 209, 216, 209, 222, 208, 209, 221, 222, 225, 210, 216, 225, 237, 210, 218, 219, 238, 238, 219, 239, 239, 219, 228, 240, 242, 241, 243, 245, 244, 243, 246, 245, 247, 249, 248, 247, 250, 249, 251, 253, 252, 251, 254, 253, 255, 256, 242, 255, 257, 256, 258, 260, 259, 258, 261, 260, 262, 254, 251, 262, 263, 254, 242, 264, 241, 242, 256, 264, 240, 246, 243, 240, 241, 246, 241, 265, 246, 241, 264, 265, 259, 257, 255, 259, 260, 257, 263, 266, 254, 263, 267, 266, 268, 267, 263, 268, 269, 267, 250, 270, 249, 250, 271, 270, 254, 272, 253, 254, 266, 272, 251, 264, 262, 251, 265, 264, 248, 261, 247, 248, 260, 261, 257, 273, 256, 260, 274, 257, 260, 248, 274, 265, 252, 275, 265, 251, 252, 256, 262, 264, 256, 276, 262, 246, 275, 245, 246, 265, 275, 271, 277, 270, 271, 278, 277, 226, 279, 233, 226, 280, 279, 211, 280, 226, 211, 212, 280, 237, 213, 210, 237, 281, 213, 233, 282, 228, 233, 279, 282, 238, 281, 237, 238, 283, 281, 276, 284, 262, 262, 284, 268, 262, 268, 263, 248, 249, 274, 274, 249, 285, 285, 249, 286, 249, 287, 286, 249, 270, 287, 286, 287, 288, 288, 287, 268, 268, 287, 269, 276, 289, 284, 276, 290, 289, 274, 291, 273, 274, 292, 291, 273, 290, 276, 273, 291, 290, 273, 257, 274, 256, 273, 276, 147, 294, 293, 147, 148, 294, 143, 296, 295, 143, 144, 296, 150, 295, 297, 150, 143, 295, 148, 297, 294, 148, 150, 297, 187, 298, 186, 187, 299, 298, 186, 300, 185, 186, 298, 300, 185, 301, 184, 185, 300, 301, 184, 302, 183, 184, 301, 302, 189, 303, 188, 189, 304, 303, 188, 299, 187, 188, 303, 299, 305, 307, 306, 308, 310, 309, 311, 313, 312, 189, 293, 304, 189, 147, 293, 144, 302, 296, 144, 183, 302, 314, 316, 315, 314, 317, 316, 317, 318, 316, 317, 319, 318, 310, 321, 320, 310, 322, 321, 307, 323, 306, 307, 324, 323, 320, 324, 307, 320, 321, 324, 308, 322, 310, 308, 325, 322, 326, 305, 327, 328, 330, 329, 328, 326, 330, 326, 320, 307, 320, 326, 328, 328, 310, 320, 326, 307, 305, 309, 310, 331, 331, 310, 328, 312, 329, 330, 313, 329, 312, 195, 201, 332, 195, 196, 201, 333, 193, 190, 333, 202, 193, 334, 197, 194, 334, 198, 197, 332, 202, 333, 332, 201, 202, 239, 283, 238, 239, 335, 283, 336, 259, 337, 336, 258, 259, 337, 255, 338, 337, 259, 255, 338, 242, 240, 338, 255, 242, 270, 339, 287, 270, 277, 339, 267, 340, 266, 267, 341, 340, 287, 342, 269, 287, 339, 342, 269, 341, 267, 269, 342, 341, 266, 343, 272, 266, 340, 343, 286, 344, 285, 286, 345, 344, 228, 335, 239, 228, 282, 335, 288, 345, 286, 288, 346, 345, 268, 346, 288, 268, 347, 346, 284, 347, 268, 284, 289, 347, 285, 292, 274, 285, 344, 292, 348, 318, 319, 348, 349, 318, 350, 349, 348, 351, 349, 350, 352, 349, 351, 353, 349, 352, 309, 349, 353, 309, 331, 349, 354, 356, 355, 354, 357, 356, 357, 358, 356, 357, 359, 358, 354, 361, 360, 354, 355, 361, 362, 314, 359, 359, 314, 358, 358, 314, 315, 360, 361, 363, 363, 361, 313, 363, 313, 364, 364, 313, 311, 365, 363, 305, 364, 327, 363, 327, 305, 363, 366, 368, 367, 366, 369, 368, 4, 370, 7, 4, 371, 370, 8, 373, 372, 8, 9, 373, 12, 367, 13, 12, 366, 367, 372, 370, 374, 372, 373, 370, 374, 371, 375, 374, 370, 371, 369, 371, 368, 369, 375, 371, 4, 368, 371, 4, 16, 368, 16, 367, 368, 16, 13, 367, 7, 373, 9, 7, 370, 373, 376, 378, 377, 376, 379, 378, 378, 381, 380, 378, 382, 381, 383, 385, 384, 383, 386, 385, 387, 389, 388, 387, 390, 389, 391, 393, 392, 391, 394, 393, 394, 388, 393, 394, 387, 388, 395, 392, 396, 395, 391, 392, 393, 398, 397, 393, 388, 398, 396, 400, 399, 396, 392, 400, 401, 403, 402, 401, 404, 403, 388, 405, 398, 388, 389, 405, 392, 397, 400, 392, 393, 397, 404, 406, 403, 404, 407, 406, 407, 399, 406, 407, 396, 399, 389, 402, 405, 389, 401, 402, 403, 406, 408, 406, 399, 408, 405, 402, 408, 397, 398, 409, 399, 409, 408, 399, 400, 409, 402, 403, 408, 398, 408, 409, 398, 405, 408, 400, 397, 409, 410, 407, 404, 410, 411, 407, 411, 396, 407, 411, 395, 396, 412, 404, 401, 412, 410, 404, 390, 401, 389, 390, 412, 401, 413, 415, 414, 413, 416, 415, 417, 419, 418, 417, 420, 419, 421, 417, 422, 421, 423, 417, 423, 420, 417, 423, 424, 420, 425, 422, 426, 425, 421, 422, 424, 427, 420, 424, 428, 427, 429, 426, 416, 429, 425, 426, 428, 430, 427, 428, 431, 430, 432, 416, 413, 432, 429, 416, 433, 435, 434, 433, 436, 435, 437, 439, 438, 437, 440, 439, 441, 443, 442, 441, 434, 443, 444, 446, 445, 444, 447, 446, 448, 450, 449, 448, 445, 450, 445, 451, 450, 445, 446, 451, 449, 450, 452, 450, 451, 452, 451, 453, 452, 416, 426, 415, 424, 455, 454, 424, 423, 455, 428, 454, 456, 428, 424, 454, 431, 413, 430, 431, 432, 413, 457, 383, 458, 457, 459, 383, 379, 382, 378, 379, 460, 382, 461, 377, 462, 461, 376, 377, 459, 386, 383, 459, 463, 386, 460, 458, 382, 460, 457, 458, 463, 464, 386, 463, 465, 464, 465, 462, 464, 465, 461, 462, 377, 380, 466, 377, 378, 380, 386, 467, 385, 386, 464, 467, 464, 468, 467, 464, 462, 468, 458, 384, 469, 458, 383, 384, 462, 466, 468, 462, 377, 466, 382, 469, 381, 382, 458, 469, 384, 471, 470, 384, 385, 471, 385, 472, 471, 385, 467, 472, 467, 473, 472, 467, 468, 473, 469, 470, 474, 469, 384, 470, 381, 474, 475, 381, 469, 474, 468, 476, 473, 468, 466, 476, 466, 477, 476, 466, 380, 477, 380, 475, 477, 380, 381, 475, 430, 414, 478, 430, 413, 414, 420, 479, 419, 420, 427, 479, 422, 418, 480, 422, 417, 418, 427, 478, 479, 427, 430, 478, 481, 483, 482, 481, 484, 483, 485, 482, 440, 485, 481, 482, 484, 486, 483, 484, 487, 486, 488, 440, 437, 488, 485, 440, 489, 434, 441, 489, 433, 434, 436, 437, 435, 436, 488, 437, 487, 441, 486, 487, 489, 441, 483, 456, 454, 483, 486, 456, 440, 455, 439, 440, 482, 455, 486, 442, 456, 486, 441, 442, 435, 438, 490, 435, 437, 438, 434, 490, 443, 434, 435, 490, 482, 454, 455, 482, 483, 454, 447, 491, 446, 447, 492, 491, 493, 448, 494, 493, 495, 448, 495, 445, 448, 495, 444, 445, 494, 449, 496, 494, 448, 449, 446, 453, 451, 446, 491, 453, 496, 449, 452, 426, 480, 415, 426, 422, 480, 443, 429, 432, 443, 490, 429, 432, 442, 443, 432, 431, 442, 423, 439, 455, 423, 421, 439, 425, 490, 438, 425, 429, 490, 456, 431, 428, 456, 442, 431, 438, 421, 425, 438, 439, 421, 497, 499, 498, 497, 500, 499, 414, 415, 500, 497, 478, 500, 478, 414, 500, 415, 480, 500, 492, 494, 491, 492, 493, 494, 496, 491, 494, 496, 453, 491, 453, 496, 452, 501, 503, 502, 501, 504, 503, 505, 507, 506, 505, 508, 507, 506, 510, 509, 506, 507, 510, 509, 504, 501, 509, 510, 504, 511, 506, 512, 511, 505, 506, 513, 502, 514, 513, 501, 502, 515, 501, 513, 515, 509, 501, 512, 509, 515, 512, 506, 509, 516, 518, 517, 516, 519, 518, 519, 520, 518, 519, 521, 520, 521, 522, 520, 521, 523, 522, 524, 514, 525, 524, 513, 514, 523, 526, 522, 523, 527, 526, 528, 513, 524, 528, 515, 513, 527, 529, 526, 527, 530, 529, 531, 515, 528, 531, 512, 515, 532, 512, 531, 532, 511, 512, 533, 517, 534, 533, 516, 517, 518, 536, 535, 518, 520, 536, 520, 537, 536, 520, 522, 537, 522, 538, 537, 522, 526, 538, 526, 539, 538, 526, 529, 539, 534, 541, 540, 534, 517, 541, 517, 535, 541, 517, 518, 535, 538, 543, 542, 538, 539, 543, 536, 545, 544, 536, 537, 545, 535, 544, 546, 535, 536, 544, 541, 546, 547, 541, 535, 546, 537, 542, 545, 537, 538, 542, 540, 547, 548, 540, 541, 547, 540, 508, 505, 540, 548, 508, 502, 543, 539, 502, 503, 543, 534, 505, 511, 534, 540, 505, 514, 539, 529, 514, 502, 539, 533, 511, 532, 533, 534, 511, 525, 529, 530, 525, 514, 529, 549, 192, 550, 549, 191, 192, 551, 553, 552, 551, 554, 553, 198, 555, 200, 198, 552, 555, 556, 558, 557, 556, 559, 558, 552, 560, 555, 552, 553, 560, 550, 206, 561, 550, 192, 206, 553, 557, 560, 553, 556, 557, 559, 561, 558, 559, 550, 561, 561, 208, 562, 561, 206, 208, 563, 565, 564, 563, 566, 565, 555, 568, 567, 555, 560, 568, 558, 562, 569, 558, 561, 562, 217, 570, 220, 217, 571, 570, 572, 223, 573, 572, 222, 223, 560, 574, 568, 560, 557, 574, 557, 569, 574, 557, 558, 569, 566, 573, 575, 566, 572, 573, 563, 572, 566, 200, 567, 227, 200, 555, 567, 570, 229, 230, 570, 576, 229, 573, 231, 232, 573, 223, 231, 576, 234, 229, 576, 577, 234, 575, 232, 235, 575, 573, 232, 220, 230, 236, 220, 570, 230, 577, 235, 234, 577, 575, 235, 578, 568, 574, 578, 579, 568, 567, 579, 571, 567, 568, 579, 571, 227, 567, 571, 217, 227, 572, 569, 562, 572, 563, 569, 562, 222, 572, 562, 208, 222, 574, 563, 578, 574, 569, 563, 571, 579, 570, 570, 579, 580, 570, 580, 576, 581, 583, 582, 584, 245, 585, 584, 244, 245, 247, 586, 250, 247, 587, 586, 588, 253, 589, 588, 252, 253, 590, 592, 591, 590, 582, 592, 258, 593, 261, 258, 594, 593, 595, 589, 596, 595, 588, 589, 582, 597, 592, 582, 583, 597, 581, 585, 583, 581, 584, 585, 583, 598, 597, 583, 585, 598, 594, 591, 593, 594, 590, 591, 596, 600, 599, 596, 589, 600, 601, 599, 602, 601, 596, 599, 250, 603, 271, 250, 586, 603, 589, 272, 600, 589, 253, 272, 588, 597, 598, 588, 595, 597, 587, 261, 593, 587, 247, 261, 591, 592, 604, 593, 605, 587, 593, 591, 605, 598, 252, 588, 598, 275, 252, 592, 595, 606, 592, 597, 595, 585, 275, 598, 585, 245, 275, 271, 607, 278, 271, 603, 607, 575, 609, 608, 575, 577, 609, 566, 608, 565, 566, 575, 608, 578, 564, 610, 578, 563, 564, 577, 611, 609, 577, 576, 611, 579, 610, 612, 579, 578, 610, 606, 595, 613, 613, 595, 601, 601, 595, 596, 587, 605, 586, 586, 605, 614, 586, 614, 615, 586, 616, 603, 586, 615, 616, 615, 617, 616, 616, 617, 601, 616, 601, 602, 606, 619, 618, 606, 613, 619, 605, 621, 620, 605, 604, 621, 604, 618, 621, 604, 606, 618, 604, 605, 591, 592, 606, 604, 508, 622, 507, 508, 623, 622, 504, 624, 503, 504, 625, 624, 510, 625, 504, 510, 626, 625, 507, 626, 510, 507, 622, 626, 546, 628, 627, 546, 544, 628, 544, 629, 628, 544, 545, 629, 545, 630, 629, 545, 542, 630, 542, 631, 630, 542, 543, 631, 548, 633, 632, 548, 547, 633, 547, 627, 633, 547, 546, 627, 305, 306, 634, 308, 309, 635, 636, 638, 637, 548, 623, 508, 548, 632, 623, 503, 631, 543, 503, 624, 631, 314, 639, 317, 314, 640, 639, 317, 641, 319, 317, 639, 641, 635, 643, 642, 635, 644, 643, 634, 323, 645, 634, 306, 323, 644, 645, 643, 644, 634, 645, 308, 642, 325, 308, 635, 642, 646, 647, 305, 648, 650, 649, 648, 649, 646, 646, 634, 644, 644, 648, 646, 648, 644, 635, 646, 305, 634, 309, 651, 635, 651, 648, 635, 638, 649, 650, 637, 638, 650, 554, 556, 553, 554, 652, 556, 653, 550, 559, 653, 549, 550, 334, 552, 198, 334, 551, 552, 652, 559, 556, 652, 653, 559, 580, 612, 654, 580, 579, 612, 336, 594, 258, 336, 655, 594, 655, 590, 594, 655, 656, 590, 656, 582, 590, 656, 581, 582, 603, 657, 607, 603, 616, 657, 599, 659, 658, 599, 600, 659, 616, 660, 657, 616, 602, 660, 602, 658, 660, 602, 599, 658, 600, 343, 659, 600, 272, 343, 615, 662, 661, 615, 614, 662, 576, 654, 611, 576, 580, 654, 617, 661, 663, 617, 615, 661, 601, 663, 664, 601, 617, 663, 613, 664, 619, 613, 601, 664, 614, 620, 662, 614, 605, 620, 665, 319, 641, 665, 348, 319, 665, 666, 348, 665, 667, 666, 665, 668, 667, 665, 353, 668, 651, 353, 665, 309, 353, 651, 669, 671, 670, 669, 672, 671, 670, 674, 673, 670, 671, 674, 669, 675, 672, 669, 676, 675, 640, 673, 674, 362, 673, 640, 362, 640, 314, 676, 637, 675, 676, 677, 637, 637, 677, 636, 636, 677, 678, 365, 305, 677, 678, 677, 647, 647, 677, 305 </int_array>
- </array>
- </dictionary>
- <dictionary name="surfaces/1" shared="false">
- <string> "alphasort" </string>
- <bool> False </bool>
- <string> "material" </string>
- <resource resource_type="FixedMaterial" path="local://4"> </resource>
- <string> "morph_arrays" </string>
- <array len="0" shared="false">
- </array>
- <string> "primitive" </string>
- <int> 4 </int>
- <string> "arrays" </string>
- <array len="9" shared="false">
- <vector3_array len="625"> 0.23068, 6.41266, 0.879344, 0.754113, 6.74074, 0.551263, 0.754113, 6.81344, 0.551263, 0.23068, 6.48536, 0.879344, 0.845318, 6.86083, 0.103095, 0.845318, 6.93353, 0.103095, 0.754113, 6.74074, -0.345078, 0.754113, 6.81344, -0.345078, 0, 6.36123, 0.969121, 0.257165, 6.36123, 0.969121, 0, 6.41266, 0.879344, 0, 6.36123, -0.762936, 0, 6.41266, -0.673159, 0.23068, 6.41266, -0.673159, 0.257165, 6.36123, -0.762936, 0.23068, 6.48536, -0.673159, 0.2607, 6.45948, -0.774594, 0.852531, 6.83043, -0.403642, 0, 6.48536, -0.673159, 0, 6.48536, 0.879344, 0.955654, 6.96621, 0.103096, 0.852531, 6.83043, 0.609826, 0.2607, 6.45948, 0.980779, 0, 6.45948, -0.774594, 0, 6.45948, 0.980779, 0.144337, 4.62833, -0.267808, 0.227645, 4.56054, -0.149869, 0.230474, 4.54553, -0.1645, 0.145367, 4.61509, -0.285537, 0, 4.66573, -0.327684, 0, 4.65348, -0.346986, 0.16781, 4.49143, -0.0124773, 0.169802, 4.47494, -0.0244043, 2.39441, 2.7167, -0.284614, 2.22321, 2.52508, -0.185319, 2.22875, 2.57563, -0.151192, 2.37464, 2.73891, -0.235805, 0.829811, 0.39491, 0.192334, 0.539954, 0.53255, 0.320534, 0.53677, 0.505704, 0.45924, 0.823707, 0.343455, 0.299719, 0.251731, 0.393841, 0.202075, 0.245627, 0.342385, 0.30946, 2.37016, 3.14596, -0.180206, 2.39069, 3.24439, 0.0703977, 2.51365, 3.10316, 0.122743, 2.49324, 3.00574, -0.125365, 2.02679, 2.71357, 0.205928, 2.02114, 2.64141, -0.071524, 2.14773, 2.50612, -0.0177825, 2.15324, 2.5776, 0.25697, 0.197471, 4.75418, 0.019584, 0.212301, 4.88556, 0.0356146, 0, 4.86123, 0.103096, 0, 4.72999, 0.114516, 2.55604, 3.1449, 0.136694, 2.53359, 3.02984, -0.15501, 2.38915, 3.19439, -0.219368, 2.41174, 3.31063, 0.0752657, 2.13459, 2.5274, 0.293671, 2.28993, 2.80163, 0.457827, 2.27149, 2.82221, 0.391821, 2.44682, 3.07552, 0.376618, 2.41931, 3.04467, 0.327652, 1.98619, 2.68696, 0.233771, 1.97806, 2.60303, -0.0912834, 2.12663, 2.44425, -0.0282163, 2.24859, 2.87814, -0.35026, 2.25039, 2.87648, -0.291744, 2.07568, 2.68462, -0.249978, 2.10304, 2.71157, -0.20629, 2.30152, 3.24052, 0.317542, 2.29549, 3.18528, 0.277312, 2.14291, 2.96404, 0.3995, 2.1462, 2.9606, 0.342119, 1.31621, 3.39795, -0.203802, 1.35829, 3.43387, -0.29479, 1.54119, 3.29007, -0.372791, 1.48496, 3.24915, -0.287145, 0.552121, 0.665123, 0.401021, 0.154027, 0.441809, 0.19622, 0.944465, 0.443271, 0.182901, 0.0964089, 0.00104547, -0.196812, 0.19633, 0.00104547, -0.176104, 0.835003, 0.00104547, -0.205403, 0.736495, 0.00104547, -0.182387, 0.108829, 0.00104547, 0.040049, 0.85902, 0.00104547, 0.0313234, 0.0508581, 0.00104547, 0.0402964, 0.207486, 0.384965, 0.351051, 0.874277, 0.386199, 0.339815, 0.916171, 0.00104547, 0.0302318, 0.543306, 0.573346, 0.523815, 0.158656, 2.88784, -0.132794, 0.242974, 2.8226, -0.0472403, 0.228589, 2.63923, -0.0490058, 0.149215, 2.70638, -0.125392, 0.241672, 4.68094, -0.138747, 0.158365, 4.73746, -0.261278, 0, 4.76911, -0.32375, 0.18264, 4.62281, 0.00355331, 0, 4.46751, 0.137356, 0, 4.44976, 0.12846, 1.6, 5.86123, 0.903096, 1.6, 5.46123, 0.795916, 1.6, 5.42123, 0.865198, 1.6, 5.86123, 0.983096, 1.6, 5.16841, 0.503096, 1.6, 5.09913, 0.543096, 1.6, 5.06123, 0.103096, 1.6, 4.98123, 0.103096, 1.6, 5.46123, -0.589731, 1.6, 5.42123, -0.659013, 1.6, 5.09912, -0.336911, 1.6, 5.16841, -0.296911, 1.6, 5.86123, -0.696911, 1.6, 5.86123, -0.776911, 1.6, 6.26123, -0.589731, 1.6, 6.30123, -0.659013, 1.6, 6.55405, -0.296911, 1.6, 6.62333, -0.336911, 1.15486, 6.36123, 0.969121, 0.685695, 6.36123, 0.969121, 0.765488, 6.24202, 0.864397, 1.07507, 6.24202, 0.864397, 1.2072, 6.11123, 1.03611, 1.10961, 6.07706, 0.908599, 2.0359, 5.66148, 0.449063, 2.0359, 5.51526, 0.30284, 1.90356, 5.8612, 0.10311, 2.0359, 5.46174, 0.103096, 2.0359, 6.20719, 0.30284, 2.0359, 6.06097, 0.449063, 2.0359, 5.51526, -0.0966551, 2.0359, 5.66148, -0.242878, 2.0359, 5.86123, -0.296399, 0, 5.40641, 0.875976, 0, 5.28211, 0.751677, 0.257146, 5.2834, 0.752961, 0.257147, 5.40641, 0.875976, 1.39648, 4.9952, 0.603096, 1.39648, 4.86123, 0.103096, 1.39648, 5.06123, 0.103096, 1.39648, 5.16841, 0.503096, 1.39648, 6.86123, 0.103096, 1.39648, 6.72725, 0.603096, 1.39648, 6.55405, 0.503096, 1.39648, 6.66123, 0.103096, 1.39648, 6.36123, 0.969121, 1.39648, 6.26123, 0.795916, 1.39648, 5.86123, 1.1031, 1.39648, 5.86123, 0.903096, 1.39648, 5.36123, 0.969121, 1.39648, 5.46123, 0.795916, 1.6, 6.66123, 0.103096, 1.6, 6.55405, 0.503096, 1.6, 6.62333, 0.543096, 1.6, 6.74123, 0.103096, 1.6, 6.26123, 0.795916, 1.6, 6.30123, 0.865198, 1.39648, 5.36123, -0.762936, 1.39648, 5.46123, -0.589731, 1.39648, 5.16841, -0.296911, 1.39648, 4.9952, -0.396911, 1.39648, 5.86123, -0.896911, 1.39648, 5.86123, -0.696911, 1.39648, 6.36123, -0.762936, 1.39648, 6.26123, -0.589731, 1.39648, 6.72725, -0.396911, 1.39648, 6.55405, -0.296911, 0.73095, 6.07706, 0.908599, 0.765488, 5.9121, 0.9528, 1.07507, 5.9121, 0.9528, 1.10961, 6.07706, 0.908599, 0.765488, 6.24202, 0.864397, 1.07507, 6.24202, 0.864397, 0.685695, 5.86123, 1.1031, 1.15486, 5.86123, 1.1031, 1.07507, 5.9121, 0.9528, 0.765488, 5.9121, 0.9528, 0.633352, 6.11123, 1.03611, 0.73095, 6.07706, 0.908599, 1.39648, 6.66123, 0.103096, 1.39648, 6.55405, 0.503096, 1.6, 6.55405, 0.503096, 1.6, 6.66123, 0.103096, 1.39648, 6.26123, 0.795916, 1.6, 6.26123, 0.795916, 1.39648, 5.86123, 0.903096, 1.6, 5.86123, 0.903096, 1.39648, 5.46123, 0.795916, 1.6, 5.46123, 0.795916, 1.39648, 5.16841, 0.503096, 1.6, 5.16841, 0.503096, 1.39648, 5.06123, 0.103096, 1.6, 5.06123, 0.103096, 1.39648, 5.46123, -0.589731, 1.6, 5.46123, -0.589731, 1.6, 5.16841, -0.296911, 1.39648, 5.16841, -0.296911, 1.39648, 5.86123, -0.696911, 1.6, 5.86123, -0.696911, 1.39648, 6.26123, -0.589731, 1.6, 6.26123, -0.589731, 1.39648, 6.55405, -0.296911, 1.6, 6.55405, -0.296911, 2.0359, 5.86123, 0.502584, 2.0359, 6.26072, 0.103096, 2.0359, 6.06097, -0.242878, 2.0359, 6.20719, -0.0966551, 0, 5.49634, 0.900073, 0.257147, 5.49634, 0.900073, 0.252264, 4.53307, -0.191655, 0.153299, 4.61636, -0.336561, 0, 4.66231, -0.410127, 0.198102, 4.44663, -0.00271145, 0, 2.66463, 0.20367, 5.00021e-06, 2.4738, 0.177211, 0.102832, 2.48009, 0.176006, 0.109384, 2.67117, 0.201936, 0.251452, 2.74864, 0.0718984, 0.23657, 2.56168, 0.0584772, 0.181152, 2.70508, 0.146183, 0.170392, 2.51572, 0.125662, 0, 2.91839, -0.164227, 5.00021e-06, 2.73725, -0.153025, 1.35355, 3.45169, -0.0607277, 1.50191, 3.29774, -0.132197, 0.413722, 1.77804, 0.182495, 0.302308, 1.69787, 0.09718, 0.311982, 1.54621, 0.0812291, 0.425773, 1.62639, 0.166544, 0.489091, 1.94399, -0.0482645, 0.542593, 1.87364, 0.112398, 0.55748, 1.72198, 0.0964474, 0.506064, 1.79234, -0.0642154, 0.394125, 1.86374, -0.138546, 0.408718, 1.71209, -0.154497, 0.227335, 1.66351, -0.0137039, 0.23599, 1.51185, -0.0296548, 0.0960235, 4.4178, 0.0939296, 1.5172, 3.69575, -0.311084, 1.54768, 3.76732, -0.167808, 1.71449, 3.62366, -0.198996, 1.70474, 3.5573, -0.353999, 1.43134, 3.52144, -0.355117, 1.62434, 3.38222, -0.419987, 1.436, 3.60537, 0.00285106, 1.57608, 3.45117, -0.0476083, 1.51354, 3.73444, -0.0382403, 1.66072, 3.58429, -0.072422, 0.254872, 1.70456, -0.0798497, 0.256767, 1.56023, -0.0958005, 0.288751, 1.77481, -0.152552, 0.300707, 1.62315, -0.168503, 0, 4.41627, 0.145479, 0.841135, 6.72725, 0.603096, 0.841135, 6.72725, -0.396911, 0.942888, 6.86123, 0.103096, -0.23068, 6.41266, 0.879344, -0.23068, 6.48536, 0.879344, -0.754113, 6.81344, 0.551263, -0.754113, 6.74074, 0.551263, -0.845318, 6.93353, 0.103095, -0.845318, 6.86083, 0.103095, -0.754113, 6.74074, -0.345078, -0.754113, 6.81344, -0.345078, -0.257165, 6.36123, 0.969121, -0.257165, 6.36123, -0.762936, -0.23068, 6.41266, -0.673159, -0.23068, 6.48536, -0.673159, -0.852531, 6.83043, -0.403642, -0.2607, 6.45948, -0.774594, -0.852531, 6.83043, 0.609826, -0.955654, 6.96621, 0.103096, -0.2607, 6.45948, 0.980779, -0.144337, 4.62833, -0.267808, -0.145367, 4.61509, -0.285537, -0.230474, 4.54553, -0.1645, -0.227645, 4.56054, -0.149869, -0.169802, 4.47494, -0.0244043, -0.16781, 4.49143, -0.0124773, -2.39441, 2.7167, -0.284614, -2.37464, 2.73891, -0.235805, -2.22875, 2.57563, -0.151192, -2.22321, 2.52508, -0.185319, -0.829811, 0.39491, 0.192334, -0.823707, 0.343455, 0.299719, -0.53677, 0.505704, 0.45924, -0.539954, 0.53255, 0.320534, -0.245627, 0.342385, 0.30946, -0.251731, 0.393841, 0.202075, -2.37016, 3.14596, -0.180206, -2.49324, 3.00574, -0.125365, -2.51365, 3.10316, 0.122743, -2.39069, 3.24439, 0.0703977, -2.02679, 2.71357, 0.205928, -2.15324, 2.5776, 0.25697, -2.14773, 2.50612, -0.0177825, -2.02114, 2.64141, -0.071524, -0.197471, 4.75418, 0.019584, -0.212301, 4.88556, 0.0356146, -2.55604, 3.1449, 0.136694, -2.53359, 3.02984, -0.15501, -2.38915, 3.19439, -0.219368, -2.41174, 3.31063, 0.0752657, -2.13459, 2.5274, 0.293671, -2.27149, 2.82221, 0.391821, -2.28993, 2.80163, 0.457827, -2.44682, 3.07552, 0.376618, -2.41931, 3.04467, 0.327652, -1.98619, 2.68696, 0.233771, -1.97806, 2.60303, -0.0912834, -2.12663, 2.44425, -0.0282163, -2.24859, 2.87814, -0.35026, -2.25039, 2.87648, -0.291744, -2.07568, 2.68462, -0.249978, -2.10304, 2.71157, -0.20629, -2.29549, 3.18528, 0.277312, -2.30152, 3.24052, 0.317542, -2.1462, 2.9606, 0.342119, -2.14291, 2.96404, 0.3995, -1.31621, 3.39795, -0.203802, -1.48496, 3.24915, -0.287145, -1.54119, 3.29007, -0.372791, -1.35829, 3.43387, -0.29479, -0.552121, 0.665123, 0.401021, -0.154027, 0.441809, 0.19622, -0.944465, 0.443271, 0.182901, -0.19633, 0.00104547, -0.176104, -0.0964089, 0.00104547, -0.196812, -0.835003, 0.00104547, -0.205403, -0.736495, 0.00104547, -0.182387, -0.108829, 0.00104547, 0.040049, -0.85902, 0.00104547, 0.0313234, -0.207486, 0.384965, 0.351051, -0.0508581, 0.00104547, 0.0402964, -0.916171, 0.00104547, 0.0302318, -0.874277, 0.386199, 0.339815, -0.543306, 0.573346, 0.523815, -0.158656, 2.88784, -0.132794, -0.149215, 2.70638, -0.125392, -0.228589, 2.63923, -0.0490058, -0.242974, 2.8226, -0.0472403, -0.241672, 4.68094, -0.138747, -0.158365, 4.73746, -0.261278, -0.18264, 4.62281, 0.00355331, -1.6, 5.86123, 0.903096, -1.6, 5.86123, 0.983096, -1.6, 5.42123, 0.865198, -1.6, 5.46123, 0.795916, -1.6, 5.09913, 0.543096, -1.6, 5.16841, 0.503096, -1.6, 4.98123, 0.103096, -1.6, 5.06123, 0.103096, -1.6, 5.46123, -0.589731, -1.6, 5.16841, -0.296911, -1.6, 5.09912, -0.336911, -1.6, 5.42123, -0.659013, -1.6, 5.86123, -0.696911, -1.6, 5.86123, -0.776911, -1.6, 6.26123, -0.589731, -1.6, 6.30123, -0.659013, -1.6, 6.55405, -0.296911, -1.6, 6.62333, -0.336911, -1.15486, 6.36123, 0.969121, -1.07507, 6.24202, 0.864397, -0.765488, 6.24202, 0.864397, -0.685695, 6.36123, 0.969121, -1.2072, 6.11123, 1.03611, -1.10961, 6.07706, 0.908599, -2.0359, 5.66148, 0.449063, -1.90356, 5.8612, 0.10311, -2.0359, 5.51526, 0.30284, -2.0359, 5.46174, 0.103096, -2.0359, 6.20719, 0.30284, -2.0359, 6.06097, 0.449063, -2.0359, 5.51526, -0.0966551, -2.0359, 5.66148, -0.242878, -2.0359, 5.86123, -0.296399, -0.257147, 5.40641, 0.875976, -0.257146, 5.2834, 0.752961, -1.39648, 4.9952, 0.603096, -1.39648, 5.16841, 0.503096, -1.39648, 5.06123, 0.103096, -1.39648, 4.86123, 0.103096, -1.39648, 6.86123, 0.103096, -1.39648, 6.66123, 0.103096, -1.39648, 6.55405, 0.503096, -1.39648, 6.72725, 0.603096, -1.39648, 6.26123, 0.795916, -1.39648, 6.36123, 0.969121, -1.39648, 5.86123, 0.903096, -1.39648, 5.86123, 1.1031, -1.39648, 5.46123, 0.795916, -1.39648, 5.36123, 0.969121, -1.6, 6.66123, 0.103096, -1.6, 6.74123, 0.103096, -1.6, 6.62333, 0.543096, -1.6, 6.55405, 0.503096, -1.6, 6.30123, 0.865198, -1.6, 6.26123, 0.795916, -1.39648, 5.36123, -0.762936, -1.39648, 4.9952, -0.396911, -1.39648, 5.16841, -0.296911, -1.39648, 5.46123, -0.589731, -1.39648, 5.86123, -0.896911, -1.39648, 5.86123, -0.696911, -1.39648, 6.36123, -0.762936, -1.39648, 6.26123, -0.589731, -1.39648, 6.72725, -0.396911, -1.39648, 6.55405, -0.296911, -0.73095, 6.07706, 0.908599, -1.10961, 6.07706, 0.908599, -1.07507, 5.9121, 0.9528, -0.765488, 5.9121, 0.9528, -0.765488, 6.24202, 0.864397, -1.07507, 6.24202, 0.864397, -0.685695, 5.86123, 1.1031, -0.765488, 5.9121, 0.9528, -1.07507, 5.9121, 0.9528, -1.15486, 5.86123, 1.1031, -0.633352, 6.11123, 1.03611, -0.73095, 6.07706, 0.908599, -1.39648, 6.66123, 0.103096, -1.6, 6.66123, 0.103096, -1.6, 6.55405, 0.503096, -1.39648, 6.55405, 0.503096, -1.6, 6.26123, 0.795916, -1.39648, 6.26123, 0.795916, -1.6, 5.86123, 0.903096, -1.39648, 5.86123, 0.903096, -1.6, 5.46123, 0.795916, -1.39648, 5.46123, 0.795916, -1.6, 5.16841, 0.503096, -1.39648, 5.16841, 0.503096, -1.6, 5.06123, 0.103096, -1.39648, 5.06123, 0.103096, -1.39648, 5.46123, -0.589731, -1.39648, 5.16841, -0.296911, -1.6, 5.16841, -0.296911, -1.6, 5.46123, -0.589731, -1.39648, 5.86123, -0.696911, -1.6, 5.86123, -0.696911, -1.39648, 6.26123, -0.589731, -1.6, 6.26123, -0.589731, -1.39648, 6.55405, -0.296911, -1.6, 6.55405, -0.296911, -2.0359, 5.86123, 0.502584, -2.0359, 6.26072, 0.103096, -2.0359, 6.06097, -0.242878, -2.0359, 6.20719, -0.0966551, -0.257147, 5.49634, 0.900073, -0.153299, 4.61636, -0.336561, -0.252264, 4.53307, -0.191655, -0.198102, 4.44663, -0.00271145, -0.109384, 2.67117, 0.201936, -0.102832, 2.48009, 0.176006, -0.251452, 2.74864, 0.0718984, -0.23657, 2.56168, 0.0584772, -0.181152, 2.70508, 0.146183, -0.170392, 2.51572, 0.125662, -1.35355, 3.45169, -0.0607277, -1.50191, 3.29774, -0.132197, -0.413722, 1.77804, 0.182495, -0.425773, 1.62639, 0.166544, -0.311982, 1.54621, 0.0812291, -0.302308, 1.69787, 0.09718, -0.489091, 1.94399, -0.0482645, -0.506064, 1.79234, -0.0642154, -0.55748, 1.72198, 0.0964474, -0.542593, 1.87364, 0.112398, -0.394125, 1.86374, -0.138546, -0.408718, 1.71209, -0.154497, -0.23599, 1.51185, -0.0296548, -0.227335, 1.66351, -0.0137039, -0.0960235, 4.4178, 0.0939296, -1.5172, 3.69575, -0.311084, -1.70474, 3.5573, -0.353999, -1.71449, 3.62366, -0.198996, -1.54768, 3.76732, -0.167808, -1.62434, 3.38222, -0.419987, -1.43134, 3.52144, -0.355117, -1.436, 3.60537, 0.00285106, -1.57608, 3.45117, -0.0476083, -1.66072, 3.58429, -0.072422, -1.51354, 3.73444, -0.0382403, -0.256767, 1.56023, -0.0958005, -0.254872, 1.70456, -0.0798497, -0.288751, 1.77481, -0.152552, -0.300707, 1.62315, -0.168503, -0.841135, 6.72725, 0.603096, -0.841135, 6.72725, -0.396911, -0.942888, 6.86123, 0.103096, 0.177538, 3.25078, -0.147598, 0.271744, 3.18932, -0.0437093, 0.257359, 3.00596, -0.0454748, 0.168097, 3.06931, -0.140196, 0, 3.04628, 0.256587, 0, 2.85545, 0.230128, 0.115936, 2.86226, 0.227866, 0.122488, 3.05335, 0.253795, 0.281216, 3.12258, 0.0987407, 0.266334, 2.93561, 0.0853195, 0.202672, 3.0838, 0.187225, 0.191912, 2.89444, 0.166704, 0, 3.28068, -0.186631, 0, 3.09954, -0.175429, -0.177538, 3.25078, -0.147598, -0.168097, 3.06931, -0.140196, -0.257359, 3.00596, -0.0454748, -0.271744, 3.18932, -0.0437093, -0.122488, 3.05335, 0.253795, -0.115936, 2.86226, 0.227866, -0.281216, 3.12258, 0.0987407, -0.266334, 2.93561, 0.0853195, -0.202672, 3.0838, 0.187225, -0.191912, 2.89444, 0.166704, 0, 4.59875, 0.125936, 0.269727, 4.92174, -0.116503, 0.2557, 4.80134, -0.127625, 0.172392, 4.8466, -0.254748, 0.18642, 4.95573, -0.248219, 0, 4.87249, -0.319817, 0, 4.97587, -0.315884, -0.269727, 4.92174, -0.116503, -0.18642, 4.95573, -0.248219, -0.172392, 4.8466, -0.254748, -0.2557, 4.80134, -0.127625, -0.809978, 3.84435, 0.0462258, -0.978723, 3.69555, -0.0371168, -0.992485, 3.72148, -0.13879, -0.809584, 3.86528, -0.0607897, -1.14747, 3.54675, -0.120459, -1.17539, 3.57767, -0.21679, -0.908494, 3.91354, 0.153681, -1.05685, 3.75959, 0.0822117, -1.2052, 3.60564, 0.010742, -0.954611, 4.1111, -0.182336, -1.14214, 3.97265, -0.225252, -1.21405, 4.05463, -0.105431, -1.04723, 4.19828, -0.0742428, -1.32967, 3.8342, -0.268168, -1.38086, 3.91097, -0.136619, -1.04535, 3.79989, -0.225379, -0.85235, 3.93911, -0.160509, -1.23834, 3.66066, -0.290248, -1.01577, 4.06798, 0.154229, -1.15585, 3.91378, 0.10377, -1.29593, 3.75958, 0.0533104, -1.21917, 4.03474, 0.0301233, -1.07199, 4.18489, 0.0643051, -1.36635, 3.88459, -0.00405846, 0.809978, 3.84435, 0.0462258, 0.809584, 3.86528, -0.0607897, 0.992485, 3.72148, -0.13879, 0.978723, 3.69555, -0.0371168, 1.17539, 3.57767, -0.21679, 1.14747, 3.54675, -0.120459, 0.908494, 3.91354, 0.153681, 1.05685, 3.75959, 0.0822117, 1.2052, 3.60564, 0.010742, 0.954611, 4.1111, -0.182336, 1.04723, 4.19828, -0.0742428, 1.21405, 4.05463, -0.105431, 1.14214, 3.97265, -0.225252, 1.38086, 3.91097, -0.136619, 1.32967, 3.8342, -0.268168, 0.85235, 3.93911, -0.160509, 1.04535, 3.79989, -0.225379, 1.23834, 3.66066, -0.290248, 1.01577, 4.06798, 0.154229, 1.15585, 3.91378, 0.10377, 1.29593, 3.75958, 0.0533104, 1.07199, 4.18489, 0.0643051, 1.21917, 4.03474, 0.0301233, 1.36635, 3.88459, -0.00405846, 0.377566, 2.23301, 0.230347, 0.273286, 2.15284, 0.145033, 0.28296, 2.00118, 0.129082, 0.389618, 2.08136, 0.214396, 0.292634, 1.84952, 0.113131, 0.40167, 1.9297, 0.198445, 0.438171, 2.39896, -0.000411894, 0.497933, 2.32861, 0.160251, 0.51282, 2.17695, 0.1443, 0.455144, 2.24731, -0.0163628, 0.527707, 2.02529, 0.128349, 0.472118, 2.09565, -0.0323137, 0.350345, 2.31871, -0.0906937, 0.364938, 2.16706, -0.106645, 0.379531, 2.0154, -0.122595, 0.20137, 2.11848, 0.0341487, 0.210025, 1.96682, 0.0181978, 0.21868, 1.81516, 0.00224695, 0.249187, 2.13753, -0.031997, 0.251082, 1.9932, -0.0479479, 0.252977, 1.84888, -0.0638988, 0.252884, 2.22978, -0.1047, 0.26484, 2.07812, -0.12065, 0.276796, 1.92646, -0.136601, -0.377566, 2.23301, 0.230347, -0.389618, 2.08136, 0.214396, -0.28296, 2.00118, 0.129082, -0.273286, 2.15284, 0.145033, -0.40167, 1.9297, 0.198445, -0.292634, 1.84952, 0.113131, -0.438171, 2.39896, -0.000411894, -0.455144, 2.24731, -0.0163628, -0.51282, 2.17695, 0.1443, -0.497933, 2.32861, 0.160251, -0.472118, 2.09565, -0.0323137, -0.527707, 2.02529, 0.128349, -0.350345, 2.31871, -0.0906937, -0.364938, 2.16706, -0.106645, -0.379531, 2.0154, -0.122595, -0.210025, 1.96682, 0.0181978, -0.20137, 2.11848, 0.0341487, -0.21868, 1.81516, 0.00224695, -0.251082, 1.9932, -0.0479479, -0.249187, 2.13753, -0.031997, -0.252977, 1.84888, -0.0638988, -0.252884, 2.22978, -0.1047, -0.26484, 2.07812, -0.12065, -0.276796, 1.92646, -0.136601 </vector3_array>
- <vector3_array len="625"> 0.0360096, 0.589157, 0.807216, 0.379162, 0.648277, 0.660282, 0.710781, -0.701771, 0.0480528, 0.391591, -0.775171, 0.495749, 0.722924, 0.690928, -0, 0.722446, -0.691427, 0, 0.378912, 0.647849, -0.660846, 0.710746, -0.701737, -0.0490515, 0, 0.610678, 0.791879, -0.0350367, 0.578606, 0.814854, 0, 0.501628, 0.865083, 0, 0.610194, -0.792252, 0, 0.501194, -0.865335, 0.0359806, 0.588682, -0.807564, -0.0350082, 0.578135, -0.81519, 0.391397, -0.774786, -0.496503, 0.323297, -0.752692, -0.573527, 0.770859, -0.534596, -0.346386, 0, -0.789191, -0.614148, 0, -0.789675, 0.613525, 0.868674, -0.495384, 0, 0.771126, -0.534781, 0.345505, 0.323483, -0.753124, 0.572855, 0, -0.789191, -0.614148, 0, -0.789675, 0.613525, 0.705688, 0.318859, -0.63272, 0.999838, 0.00999838, 0.0149976, 0.799697, 0.565786, 0.200924, 0.540954, 0.82793, -0.147987, 0, 0.473026, -0.881048, 0, 0.986122, -0.166021, 0.790431, -0.193105, 0.581317, 0.744403, 0.310168, 0.59132, -0.210106, 0.16008, -0.964484, -0.609658, -0.17619, -0.772835, -0.695748, -0.0600646, -0.71577, -0.418461, 0.236261, -0.876967, 0.72763, -0.205178, 0.654566, 0.0120115, 0.213204, 0.976934, -0.0129987, 0.889909, -0.455953, 0.408168, 0.754311, -0.514212, -0.717691, -0.0310299, 0.69567, -0.403281, 0.782544, -0.47433, 0.962114, -0.068008, -0.264031, 0.98219, 0.109021, 0.15303, -0.0740053, 0.995071, -0.0660047, -0.0730215, 0.709209, -0.701207, 0.120177, -0.831221, 0.542797, 0.130096, -0.988732, -0.0740548, -0.9642, -0.11214, -0.240299, -0.953245, 0.0220288, 0.301394, 0.741648, -0.0980857, 0.66358, 0.557506, -0.667605, 0.493448, 0, -0.762778, 0.64666, 0, -0.0440454, 0.99903, 0.0889861, 0.993844, -0.0659897, 0.0490036, 0.723054, -0.689051, 0.897953, 0.117994, -0.423978, 0.920375, 0.351143, 0.17207, -0.901333, -0.16224, 0.401594, -0.618771, 0.285356, 0.731912, -0.721733, 0.300305, 0.623633, -0.242219, 0.80573, 0.54049, -0.400552, 0.758045, 0.514709, -0.0350519, -0.808196, 0.58787, -0.0460378, -0.996819, -0.0650535, -0.891041, -0.346405, -0.293343, 0.6294, -0.428272, -0.648412, 0.728593, -0.433353, -0.530432, 0.267172, -0.820528, -0.505325, 0.35736, -0.806813, -0.470474, 0.622553, 0.221196, 0.750666, 0.819836, -0.00400408, 0.572584, 0.297403, -0.309419, 0.903223, 0.487706, -0.344499, 0.802162, -0.679917, -0.730986, -0.0580783, -0.592431, -0.368268, -0.716522, -0.511638, -0.289361, -0.809009, -0.812045, -0.505651, -0.291375, -0.00700771, -0.117129, 0.993092, -0.674119, -0.252419, 0.694153, 0.797008, -0.304385, 0.521659, -0.753305, -0.654134, 0.0681181, -0.216317, -0.957402, 0.19128, 0.713493, -0.691478, -0.113078, 0.194204, -0.972021, 0.132139, -0.686439, 0.302193, -0.661423, 0.711943, 0.135989, -0.688945, -0.702756, -0.294317, -0.647697, -0.616626, 0.733745, -0.28529, 0.714816, 0.636836, -0.288926, 0.64207, -0.336037, -0.689075, 0.0110026, 0.996233, -0.0860201, 0.456853, -0.0569817, -0.887715, 0.891957, -0.0679967, -0.446978, 0.947519, 0.264145, -0.180099, 0.609974, 0.430981, -0.664971, 0.983744, -0.109971, -0.141963, 0.618615, -0.0169894, -0.785511, 0, 0.0229939, -0.999736, 0.785814, -0.0981016, 0.610633, 0, -0.271413, 0.962463, 0, 0.126129, 0.992014, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -0.167145, 0.336293, 0.926806, 0.168118, 0.336236, 0.926651, 0.327528, -0.185299, 0.926493, -0.326633, -0.185359, 0.926797, -0.401672, 0.237397, 0.884479, -0.493594, 0.225271, 0.840011, 0.984527, -0.0870466, 0.152081, 0.984527, -0.152081, 0.0870466, 1, 0, -0, 0.984551, -0.175098, 0, 0.984377, 0.153059, 0.0870333, 0.984441, 0.0880395, 0.152068, 0.984441, -0.152068, -0.0880395, 0.984377, -0.0870333, -0.153059, 0.984378, 0, -0.176068, 0, -0.499694, 0.866202, 0, -0.0770792, 0.997025, -0.353503, -0.137195, 0.925318, -0.4965, -0.437441, 0.749755, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0.168109, 0.172111, 0.970627, -0.167136, 0.17214, 0.97079, -0.326504, 0.624964, 0.709094, 0.327398, 0.62476, 0.708862, 0.402511, 0.237301, 0.884123, 0.494351, 0.22516, 0.839595, 0.770022, 0.638018, -0, 0.77049, 0.552351, 0.318202, -0.770083, 0.552777, 0.318448, -0.769614, 0.638509, 0, 0.77067, 0.319278, 0.551479, -0.770263, 0.319524, 0.551905, 0.770513, 0, 0.637424, -0.770106, 0, 0.637916, 0.770916, -0.318378, 0.551655, -0.770509, -0.318624, 0.552081, 0.770916, -0.551655, 0.318378, -0.770509, -0.552081, 0.318624, 0.770513, -0.637424, 0, -0.770106, -0.637916, 0, 0.77049, -0.318202, -0.552351, -0.770083, -0.318448, -0.552777, -0.770263, -0.551905, -0.319524, 0.77067, -0.551479, -0.319278, 0.770022, 0, -0.638018, -0.769614, 0, -0.638509, 0.770245, 0.319101, -0.552175, -0.769837, 0.319347, -0.552601, 0.770245, 0.552175, -0.319101, -0.769837, 0.552601, -0.319347, 0.984551, 0, 0.175098, 0.984378, 0.176068, -0, 0.984291, 0.088026, -0.153045, 0.984291, 0.153045, -0.088026, 0, -0.848897, 0.528558, -0.359502, -0.75906, 0.542758, 0.269002, 0.885006, 0.380003, 0.175995, 0.932972, 0.31399, 0, 0.941447, 0.33716, 0.24712, 0.836407, 0.489238, 0, -0.135113, 0.99083, 0, 0.0700382, 0.997544, 0.320359, 0.0650729, 0.945059, 0.353552, -0.136213, 0.925444, 0.952453, -0.0990471, 0.288137, 0.880048, 0.129007, 0.457025, 0.701409, -0.115067, 0.70341, 0.644507, 0.0390307, 0.763601, 0, -0.0550267, -0.998485, 0, 0.542878, -0.839811, -0.285466, -0.616005, 0.734198, -0.764085, -0.38755, 0.515732, -0.0240167, -0.100069, 0.994691, -0.686889, -0.119154, 0.716928, -0.74958, 0.0670519, 0.658509, -0.318438, 0.223307, 0.921266, 0.825985, 0.143997, -0.54499, 0.923944, 0.0519969, 0.378977, 0.455352, 0.602466, 0.655507, 0.565223, 0.681269, -0.465184, 0.342959, 0.132984, -0.929889, -0.0789773, 0.541844, -0.83676, -0.991178, -0.058069, 0.119142, -0.969378, 0.150213, 0.194276, 0.245128, 0.817427, 0.521272, 0.232988, 0.56297, -0.792958, 0.642155, 0.763184, -0.0720174, 0.308094, 0.942288, -0.13104, 0.167052, 0.584181, -0.794246, -0.281137, 0.0480233, -0.958465, -0.160029, 0.076014, -0.984181, 0.184197, -0.152163, 0.97104, -0.409744, 0.0530964, 0.910654, 0.581446, 0.410315, 0.702539, 0.0380266, 0.718502, 0.694485, -0.910035, 0.00700797, -0.414472, -0.943047, 0.164182, -0.289321, -0.529471, 0.0660587, -0.845752, -0.728454, 0.359224, -0.583363, 0, 0.768221, 0.640184, -0.0380063, 0.865143, 0.500083, -0.0379873, 0.86471, -0.500832, -0.001, 1, 0, -0.0350106, 0.589178, 0.807244, -0.390743, -0.775474, 0.495943, -0.710285, -0.70227, 0.048087, -0.378305, 0.648523, 0.660533, -0.721967, -0.691927, 0, -0.722446, 0.691427, 0, -0.378055, 0.648094, -0.661096, -0.71025, -0.702236, -0.0490864, 0.0360365, 0.578586, 0.814825, 0.0360071, 0.578114, -0.815161, -0.0349823, 0.588703, -0.807592, -0.390549, -0.775089, -0.496698, -0.770452, -0.535009, -0.346654, -0.322401, -0.752935, -0.573713, -0.77072, -0.535194, 0.345772, -0.868428, -0.495815, 0, -0.322586, -0.753368, 0.57304, -0.705185, 0.319084, -0.633166, -0.540246, 0.828378, -0.148068, -0.799337, 0.566238, 0.201085, -0.999837, 0.0100084, 0.0150126, -0.743957, 0.310399, 0.591761, -0.790055, -0.193258, 0.581777, 0.211062, 0.160047, -0.964281, 0.419287, 0.236161, -0.876599, 0.696264, -0.0600228, -0.715271, 0.610287, -0.176083, -0.772363, -0.727158, -0.205327, 0.655043, -0.407334, 0.754619, -0.514422, 0.0139984, 0.889897, -0.455947, -0.0110107, 0.213206, 0.976945, 0.404118, 0.782228, -0.474138, 0.718176, -0.0310076, 0.69517, -0.962039, -0.0680735, -0.264285, 0.0740164, 0.709157, -0.701155, 0.0749998, 0.994997, -0.0659998, -0.982154, 0.109128, 0.15318, -0.119189, -0.831321, 0.542862, 0.953337, 0.0220078, 0.301106, 0.96427, -0.112031, -0.240067, -0.129112, -0.98886, -0.0740644, -0.741197, -0.0981585, 0.664072, -0.556815, -0.667978, 0.493723, -0.087994, 0.993932, -0.0659955, -0.0480059, 0.723089, -0.689085, -0.897759, 0.1181, -0.424359, -0.920222, 0.351467, 0.172229, 0.90152, -0.162094, 0.401232, 0.722212, 0.300088, 0.623183, 0.619388, 0.285179, 0.731458, 0.243161, 0.805534, 0.540358, 0.401392, 0.757741, 0.514503, 0.0360521, -0.808167, 0.587849, 0.0470365, -0.996773, -0.0650504, 0.891247, -0.346096, -0.293081, -0.628795, -0.428542, -0.648821, -0.728123, -0.433669, -0.530819, -0.266242, -0.820747, -0.50546, -0.356487, -0.807102, -0.470642, -0.819508, -0.00400737, 0.573054, -0.621939, 0.221334, 0.751134, -0.486942, -0.344667, 0.802553, -0.296489, -0.309511, 0.903492, 0.680455, -0.730488, -0.0580388, 0.812386, -0.50524, -0.291138, 0.512377, -0.289213, -0.808595, 0.59308, -0.36805, -0.716097, 0.00800875, -0.117128, 0.993085, 0.674665, -0.252249, 0.693684, -0.796642, -0.304628, 0.522076, 0.217271, -0.957194, 0.191239, 0.753738, -0.65364, 0.0680667, -0.713001, -0.691972, -0.113159, -0.19324, -0.972209, 0.132164, 0.686968, 0.301986, -0.660969, -0.711449, 0.136086, -0.689435, 0.617246, 0.733292, -0.285114, 0.703262, -0.29411, -0.647241, -0.641482, -0.336253, -0.689518, -0.714327, 0.637291, -0.289132, -0.0100024, 0.996243, -0.086021, -0.456062, -0.0570077, -0.88812, -0.609345, 0.431244, -0.665377, -0.947416, 0.264395, -0.18027, -0.891752, -0.0680574, -0.447377, -0.983712, -0.11008, -0.142103, -0.617997, -0.0169999, -0.785996, -0.785431, -0.0981788, 0.611113, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 0.168118, 0.336236, 0.926651, 0.327528, -0.185299, 0.926493, -0.326633, -0.185359, 0.926797, -0.167145, 0.336293, 0.926806, 0.402511, 0.237301, 0.884123, 0.494351, 0.22516, 0.839595, -0.984497, -0.0871325, 0.152231, -1, 0, 0, -0.984497, -0.152231, 0.0871325, -0.98452, -0.175271, 0, -0.984346, 0.15321, 0.0871191, -0.98441, 0.0881262, 0.152218, -0.98441, -0.152218, -0.0881262, -0.984346, -0.0871191, -0.15321, -0.984347, 0, -0.176241, 0.497254, -0.437223, 0.749383, 0.354379, -0.137147, 0.92499, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, 1, 0, -0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, 0, 0.25922, 0.965818, -0.167136, 0.17214, 0.97079, -0.326504, 0.624964, 0.709094, 0.327398, 0.62476, 0.708862, 0.168109, 0.172111, 0.970627, -0.401672, 0.237397, 0.884479, -0.493594, 0.225271, 0.840011, -0.769614, 0.638509, 0, 0.770022, 0.638018, -0, 0.77049, 0.552351, 0.318202, -0.770083, 0.552777, 0.318448, 0.77067, 0.319278, 0.551479, -0.770263, 0.319524, 0.551905, 0.770513, 0, 0.637424, -0.770106, 0, 0.637916, 0.770916, -0.318378, 0.551655, -0.770509, -0.318624, 0.552081, 0.770916, -0.551655, 0.318378, -0.770509, -0.552081, 0.318624, 0.770513, -0.637424, 0, -0.770106, -0.637916, 0, -0.770083, -0.318448, -0.552777, -0.770263, -0.551905, -0.319524, 0.77067, -0.551479, -0.319278, 0.77049, -0.318202, -0.552351, -0.769614, 0, -0.638509, 0.770022, 0, -0.638018, -0.769837, 0.319347, -0.552601, 0.770245, 0.319101, -0.552175, -0.769837, 0.552601, -0.319347, 0.770245, 0.552175, -0.319101, -0.98452, 0, 0.175271, -0.984347, 0.176241, 0, -0.98426, 0.0881128, -0.153196, -0.98426, 0.153196, -0.0881128, 0.360374, -0.758786, 0.542562, -0.175025, 0.933135, 0.314046, -0.268074, 0.885244, 0.380105, -0.246181, 0.836614, 0.489359, -0.352675, -0.136261, 0.925772, -0.31946, 0.0650937, 0.945361, -0.95236, -0.0991416, 0.288412, -0.879823, 0.129121, 0.457428, -0.7009, -0.115148, 0.703904, -0.643922, 0.0390559, 0.764094, 0.286385, -0.615829, 0.733988, 0.764501, -0.387254, 0.515338, 0.0250168, -0.100067, 0.994666, 0.319337, 0.223236, 0.920972, 0.750018, 0.0670016, 0.658015, 0.687417, -0.119072, 0.716435, -0.825667, 0.144116, -0.54544, -0.564542, 0.681654, -0.465447, -0.454558, 0.60274, 0.655806, -0.923798, 0.0520449, 0.379327, -0.342076, 0.13303, -0.930208, 0.0799707, 0.541802, -0.836693, 0.969438, 0.150068, 0.194088, 0.991195, -0.0580114, 0.119023, -0.244187, 0.817627, 0.5214, -0.232042, 0.563101, -0.793142, -0.166079, 0.584278, -0.794378, -0.307188, 0.942578, -0.13108, -0.641567, 0.763675, -0.0720637, 0.161004, 0.0760018, -0.984023, 0.282058, 0.0480098, -0.958196, -0.18323, -0.152191, 0.971218, 0.410577, 0.0530746, 0.91028, -0.0370272, 0.718529, 0.694511, -0.580783, 0.410554, 0.702948, 0.943158, 0.164027, -0.289048, 0.910207, 0.00700159, -0.414094, 0.530191, 0.0660237, -0.845304, 0.728923, 0.358962, -0.582938, 0.039005, 0.86511, 0.500063, 0.0389854, 0.864677, -0.500813, 0.002, 0.999998, -0, 0.307062, -0.405082, -0.861174, 0.644374, -0.493286, -0.584339, 0.899636, -0.0680481, -0.431305, 0.473063, -0.0580077, -0.879117, 0, -0.746027, 0.665916, 0, -0.135113, 0.99083, 0.361199, -0.136075, 0.922507, 0.355385, -0.786851, 0.504546, 0.758512, -0.647437, -0.07405, 0.952727, -0.0990756, 0.287219, 0.641692, -0.681736, 0.351379, 0.709379, -0.115062, 0.695372, 0, -0.36621, -0.930532, 0, -0.0550267, -0.998485, -0.306156, -0.405206, -0.861439, -0.472286, -0.0580352, -0.879533, -0.899445, -0.0681094, -0.431694, -0.643788, -0.493604, -0.584716, -0.354509, -0.787131, 0.504725, -0.360328, -0.136124, 0.92284, -0.758087, -0.647929, -0.0741063, -0.952635, -0.0991702, 0.287493, -0.641103, -0.682174, 0.351605, -0.708882, -0.115143, 0.695866, 0, -0.0550817, 0.998482, 0.721736, -0.682696, -0.114116, 0.984884, -0.110987, -0.132984, 0.620192, -0.0180056, -0.784243, 0.463983, -0.666975, -0.582978, 0, 0.0239931, -0.999712, 0, -0.812786, -0.582563, -0.721256, -0.68319, -0.114199, -0.463198, -0.667285, -0.583249, -0.619576, -0.0180168, -0.78473, -0.984854, -0.111096, -0.133115, -0.712291, -0.694258, -0.103187, 0.595443, -0.778579, 0.198147, 0.653726, -0.55762, -0.511568, -0.639939, -0.7491, -0.171251, 0.643677, -0.761801, 0.0730768, 0.630288, -0.468214, -0.619283, -0.730652, -0.680607, -0.0540482, 0.116169, -0.506735, 0.854239, 0.201265, -0.563742, 0.801054, -0.905093, -0.411497, -0.107129, -0.0970155, 0.416066, -0.904144, -0.581217, 0.747279, -0.32212, -0.864338, -0.499774, -0.0560868, -0.164974, 0.491923, -0.854866, -0.616439, 0.761542, -0.200142, 0.407071, -0.149026, -0.901157, -0.759004, -0.614813, -0.214283, 0.347173, -0.0500249, -0.936466, -0.848814, -0.528507, -0.0140134, -0.344309, 0.00500449, 0.938843, -0.266308, -0.0730846, 0.961113, -0.669545, 0.542441, 0.507413, -0.833134, -0.540736, -0.116158, -0.62997, 0.48074, 0.609939, 0.712784, -0.693763, -0.103113, 0.64053, -0.74862, -0.171142, -0.653152, -0.557985, -0.511903, -0.594796, -0.779043, 0.198265, -0.629685, -0.46851, -0.619674, -0.64309, -0.762292, 0.0731239, 0.731118, -0.68011, -0.0540087, -0.11518, -0.506794, 0.854338, -0.200304, -0.563855, 0.801215, 0.905274, -0.411124, -0.107032, 0.864591, -0.499341, -0.0560383, 0.581879, 0.746844, -0.321933, 0.0980061, 0.416026, -0.904056, 0.617059, 0.761072, -0.200019, 0.165946, 0.491841, -0.854724, 0.759428, -0.614346, -0.214121, -0.406236, -0.149087, -0.901524, -0.346292, -0.0500423, -0.936791, 0.849093, -0.528058, -0.0140015, 0.345191, 0.00500277, 0.938519, 0.267238, -0.0730651, 0.960857, 0.83344, -0.540285, -0.116061, 0.670096, 0.542078, 0.507073, 0.630574, 0.480437, 0.609555, 0.652602, -0.667616, 0.35833, 0.272405, -0.803194, 0.529788, -0.69805, -0.119179, 0.706062, -0.0250168, -0.100067, 0.994666, -0.692476, -0.119254, 0.711516, -0.0250168, -0.100067, 0.994666, 0.794806, -0.441448, -0.416422, 0.800238, -0.563168, -0.206061, 0.931286, 0.0550169, 0.360111, 0.825985, 0.143997, -0.54499, 0.927789, 0.0530451, 0.369314, 0.825985, 0.143997, -0.54499, 0.823173, -0.419088, -0.383081, 0.35507, 0.134026, -0.925182, 0.348836, 0.133937, -0.927564, 0.241336, -0.969348, -0.0460641, -0.998282, -0.049063, 0.0320411, -0.995768, -0.0530409, 0.0750579, -0.256367, -0.749072, -0.610874, -0.92242, 0.00300137, -0.386176, -0.915525, 0.00500287, -0.402231, 0.679395, -0.526306, -0.511297, -0.621461, 0.0540401, -0.781579, -0.575446, 0.0600465, -0.815632, -0.652026, -0.668052, 0.358564, 0.0260168, -0.100064, 0.994641, 0.698563, -0.119096, 0.705568, -0.271477, -0.803413, 0.529932, 0.0260168, -0.100064, 0.994641, 0.692997, -0.119171, 0.711023, -0.794437, -0.441799, -0.416754, -0.825667, 0.144116, -0.54544, -0.931153, 0.0550682, 0.360446, -0.799878, -0.563619, -0.206226, -0.825667, 0.144116, -0.54544, -0.92765, 0.0530944, 0.369657, -0.82285, -0.419434, -0.383396, -0.354195, 0.134074, -0.925511, -0.347958, 0.133984, -0.927887, 0.998285, -0.049014, 0.0320091, -0.240392, -0.969582, -0.0460752, 0.995776, -0.0529881, 0.0749831, 0.922569, 0.0029986, -0.38582, 0.257302, -0.748879, -0.610717, 0.915686, 0.00499829, -0.401862, -0.678856, -0.526664, -0.511645, 0.622074, 0.0540065, -0.781093, 0.576115, 0.060012, -0.815163 </vector3_array>
- <nil> </nil>
- <nil> </nil>
- <nil> </nil>
- <nil> </nil>
- <real_array len="2500"> 6, 7, 0, 0, 6, 7, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 6, 7, 0, 0, 7, 0, 0, 0, 7, 6, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 7, 0, 0, 6, 7, 0, 0, 6, 7, 0, 0, 6, 7, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 6, 3, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 3, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 8, 9, 3, 0, 8, 9, 3, 0, 8, 9, 0, 0, 8, 9, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 1, 3, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 6, 0, 0, 3, 6, 0, 0, 3, 6, 0, 0, 3, 6, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 8, 9, 3, 0, 8, 9, 0, 0, 12, 13, 1, 0, 12, 13, 1, 0, 12, 13, 0, 0, 12, 13, 0, 0, 12, 13, 1, 0, 12, 13, 1, 0, 12, 13, 0, 0, 12, 13, 0, 0, 12, 13, 1, 0, 12, 13, 0, 0, 12, 13, 1, 0, 12, 13, 0, 0, 3, 0, 0, 0, 8, 9, 3, 0, 8, 9, 3, 0, 8, 9, 0, 0, 9, 8, 0, 0, 9, 8, 3, 0, 9, 8, 0, 0, 9, 8, 3, 0, 9, 8, 0, 0, 8, 9, 3, 0, 8, 9, 0, 0, 12, 13, 1, 0, 12, 13, 0, 0, 12, 13, 1, 0, 12, 13, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 7, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 6, 7, 0, 0, 7, 0, 0, 0, 6, 7, 0, 0, 7, 6, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 7, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 16, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 6, 3, 0, 0, 6, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 10, 11, 3, 0, 10, 11, 0, 0, 10, 11, 0, 0, 10, 11, 3, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0, 3, 6, 0, 0, 3, 6, 0, 0, 3, 6, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 10, 11, 3, 0, 10, 11, 0, 0, 15, 16, 1, 0, 15, 16, 0, 0, 15, 16, 0, 0, 15, 16, 1, 0, 15, 16, 1, 0, 15, 16, 0, 0, 15, 16, 0, 0, 15, 16, 1, 0, 15, 16, 1, 0, 15, 16, 0, 0, 15, 16, 0, 0, 15, 16, 1, 0, 3, 0, 0, 0, 10, 11, 3, 0, 11, 10, 0, 0, 10, 11, 0, 0, 10, 11, 3, 0, 11, 10, 0, 0, 11, 10, 3, 0, 11, 10, 3, 0, 11, 10, 0, 0, 10, 11, 0, 0, 10, 11, 3, 0, 15, 16, 0, 0, 15, 16, 1, 0, 15, 16, 1, 0, 15, 16, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 0, 0, 0, 3, 1, 0, 0, 3, 6, 0, 0, 6, 0, 0, 0, 6, 3, 0, 0, 6, 3, 0, 0, 6, 0, 0, 0, 6, 3, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 3, 0, 0, 6, 3, 0, 0, 3, 0, 0, 0, 3, 10, 11, 0, 3, 10, 11, 0, 3, 0, 0, 0, 3, 10, 11, 0, 3, 10, 11, 0, 3, 0, 0, 0, 3, 10, 11, 0, 3, 10, 11, 0, 3, 0, 0, 0, 3, 10, 11, 0, 3, 10, 11, 0, 3, 0, 0, 0, 3, 11, 10, 0, 3, 10, 11, 0, 3, 11, 10, 0, 3, 0, 0, 0, 3, 11, 10, 0, 3, 0, 0, 0, 3, 11, 10, 0, 3, 11, 10, 0, 3, 10, 11, 0, 3, 0, 0, 0, 3, 10, 11, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 8, 9, 0, 3, 8, 9, 0, 3, 8, 9, 0, 3, 8, 9, 0, 3, 0, 0, 0, 3, 8, 9, 0, 3, 8, 9, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 8, 9, 0, 3, 8, 9, 0, 3, 8, 9, 0, 3, 9, 8, 0, 3, 0, 0, 0, 3, 9, 8, 0, 3, 9, 8, 0, 3, 0, 0, 0, 3, 9, 8, 0, 3, 9, 8, 0, 3, 0, 0, 0, 3, 8, 9, 0, 3, 8, 9, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 12, 0, 0, 12, 1, 13, 0, 12, 1, 13, 0, 1, 0, 0, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 0, 0, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 0, 0, 0, 1, 12, 13, 0, 1, 12, 13, 0, 1, 0, 0, 0, 1, 15, 16, 0, 1, 15, 16, 0, 1, 0, 0, 0, 1, 15, 16, 0, 1, 15, 16, 0, 1, 0, 0, 0, 1, 15, 16, 0, 1, 15, 16, 0, 1, 0, 0, 0, 1, 15, 16, 0, 1, 15, 16, 0, 1, 15, 0, 0, 15, 1, 16, 0, 15, 1, 16, 0, 1, 15, 16, 0, 1, 0, 0, 0, 1, 15, 16, 0, 1, 15, 16, 0, 1, 0, 0, 0, 1, 15, 16, 0, 1, 0, 0, 0, 1, 15, 16, 0, 1, 15, 16, 0 </real_array>
- <real_array len="2500"> 0.500006, 0.499994, 0, 0, 0.500036, 0.499964, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.508359, 0.491641, 0, 0, 1, 0, 0, 0, 0.500012, 0.499988, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.500137, 0.499863, 0, 0, 0.997415, 0.00258508, 0, 0, 0.5, 0.5, 0, 0, 0.502778, 0.497222, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.439327, 0.339942, 0.220731, 0, 0.397775, 0.362587, 0.239639, 0, 0.523139, 0.476861, 0, 0, 0.563768, 0.436232, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.66667, 0.33333, 0, 0, 1, 0, 0, 0, 0.412375, 0.353797, 0.233829, 0, 0.538228, 0.461772, 0, 0, 0.544073, 0.274503, 0.181424, 0, 0.550005, 0.266658, 0.183337, 0, 0.673479, 0.326521, 0, 0, 0.664658, 0.335342, 0, 0, 0.546797, 0.270935, 0.182268, 0, 0.544673, 0.273746, 0.181581, 0, 0.665519, 0.334481, 0, 0, 0.668675, 0.331325, 0, 0, 0.615652, 0.230199, 0.154149, 0, 0.6672, 0.3328, 0, 0, 0.544198, 0.2744, 0.181402, 0, 0.664792, 0.335208, 0, 0, 1, 0, 0, 0, 0.37581, 0.37581, 0.24838, 0, 0.378779, 0.374023, 0.247199, 0, 0.503159, 0.496841, 0, 0, 0.5, 0.5, 0, 0, 0.399773, 0.361383, 0.238845, 0, 0.525218, 0.474782, 0, 0, 0.409739, 0.358697, 0.231565, 0, 0.533212, 0.466788, 0, 0, 0.375815, 0.375807, 0.248378, 0, 0.500006, 0.499994, 0, 0, 0.56732, 0.24294, 0.18974, 0, 0.700171, 0.299829, 0, 0, 0.544164, 0.274448, 0.181388, 0, 0.66474, 0.33526, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.500006, 0.499994, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.500036, 0.499964, 0, 0, 1, 0, 0, 0, 0.508359, 0.491641, 0, 0, 0.500012, 0.499988, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.502778, 0.497222, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.439327, 0.339942, 0.220731, 0, 0.563768, 0.436232, 0, 0, 0.523139, 0.476861, 0, 0, 0.397775, 0.362587, 0.239639, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.412375, 0.353797, 0.233829, 0, 0.538228, 0.461772, 0, 0, 0.544073, 0.274503, 0.181424, 0, 0.664658, 0.335342, 0, 0, 0.673479, 0.326521, 0, 0, 0.550005, 0.266658, 0.183337, 0, 0.546797, 0.270935, 0.182268, 0, 0.668675, 0.331325, 0, 0, 0.665519, 0.334481, 0, 0, 0.544673, 0.273746, 0.181581, 0, 0.615652, 0.230199, 0.154149, 0, 0.6672, 0.3328, 0, 0, 0.664792, 0.335208, 0, 0, 0.544198, 0.2744, 0.181402, 0, 1, 0, 0, 0, 0.37581, 0.37581, 0.24838, 0, 0.5, 0.5, 0, 0, 0.503159, 0.496841, 0, 0, 0.378779, 0.374023, 0.247199, 0, 0.525218, 0.474782, 0, 0, 0.399773, 0.361383, 0.238845, 0, 0.409739, 0.358697, 0.231565, 0, 0.533212, 0.466788, 0, 0, 0.500006, 0.499994, 0, 0, 0.375815, 0.375807, 0.248378, 0, 0.700171, 0.299829, 0, 0, 0.56732, 0.24294, 0.18974, 0, 0.544164, 0.274448, 0.181388, 0, 0.66474, 0.33526, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666663, 0.333337, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666667, 0.333333, 0, 0, 0.666667, 0.333333, 0, 0, 1, 0, 0, 0, 0.718253, 0.15884, 0.122907, 0, 0.739344, 0.136359, 0.124296, 0, 1, 0, 0, 0, 0.45939, 0.304779, 0.235832, 0, 0.485992, 0.268898, 0.245111, 0, 1, 0, 0, 0, 0.7331, 0.143653, 0.123247, 0, 0.477963, 0.280975, 0.241062, 0, 1, 0, 0, 0, 0.748373, 0.125813, 0.125813, 0, 0.747178, 0.12721, 0.125612, 0, 1, 0, 0, 0, 0.497836, 0.251082, 0.251082, 0, 0.496251, 0.253466, 0.250283, 0, 0.738503, 0.137343, 0.124154, 0, 1, 0, 0, 0, 0.484902, 0.270539, 0.244559, 0, 1, 0, 0, 0, 0.730612, 0.143641, 0.125747, 0, 0.4748, 0.280042, 0.245157, 0, 0.748371, 0.125816, 0.125813, 0, 1, 0, 0, 0, 0.497833, 0.251086, 0.251081, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.739344, 0.136359, 0.124296, 0, 0.718253, 0.15884, 0.122907, 0, 0.485992, 0.268898, 0.245111, 0, 0.45939, 0.304779, 0.235832, 0, 1, 0, 0, 0, 0.7331, 0.143653, 0.123247, 0, 0.477963, 0.280975, 0.241062, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.747178, 0.12721, 0.125612, 0, 0.748373, 0.125813, 0.125813, 0, 0.496251, 0.253466, 0.250283, 0, 0.497836, 0.251082, 0.251082, 0, 1, 0, 0, 0, 0.738503, 0.137343, 0.124154, 0, 0.484902, 0.270539, 0.244559, 0, 1, 0, 0, 0, 0.730612, 0.143641, 0.125747, 0, 0.4748, 0.280042, 0.245157, 0, 1, 0, 0, 0, 0.748371, 0.125816, 0.125813, 0, 0.497833, 0.251086, 0.251081, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.668925, 0.222972, 0.108103, 0, 0.666077, 0.221944, 0.111978, 0, 0.402445, 0.40244, 0.195114, 0, 0.399364, 0.399217, 0.201418, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0.666312, 0.222075, 0.111612, 0, 0.667337, 0.222443, 0.110219, 0, 0.399617, 0.399566, 0.200817, 0, 0.400725, 0.40072, 0.198555, 0, 0.500004, 0.499996, 0, 0, 0.533361, 0.40023, 0.0664093, 0, 0.571539, 0.286063, 0.142398, 0, 1, 0, 0, 0, 0.666044, 0.222012, 0.111945, 0, 0.399328, 0.399322, 0.20135, 0, 1, 0, 0, 0, 0.678203, 0.225313, 0.0964842, 0, 0.412634, 0.411257, 0.176109, 0, 1, 0, 0, 0, 0.666023, 0.222008, 0.111969, 0, 0.399306, 0.399306, 0.201389, 0, 1, 0, 0, 0, 0.666077, 0.221944, 0.111978, 0, 0.668925, 0.222972, 0.108103, 0, 1, 0, 0, 0, 0.399364, 0.399217, 0.201418, 0, 0.402445, 0.40244, 0.195114, 0, 1, 0, 0, 0, 0.667337, 0.222443, 0.110219, 0, 0.666312, 0.222075, 0.111612, 0, 1, 0, 0, 0, 0.400725, 0.40072, 0.198555, 0, 0.399617, 0.399566, 0.200817, 0, 0.500004, 0.499996, 0, 0, 0.533361, 0.40023, 0.0664093, 0, 0.571539, 0.286063, 0.142398, 0, 0.666044, 0.222012, 0.111945, 0, 1, 0, 0, 0, 0.399328, 0.399322, 0.20135, 0, 0.678203, 0.225313, 0.0964842, 0, 1, 0, 0, 0, 0.412634, 0.411257, 0.176109, 0, 1, 0, 0, 0, 0.666023, 0.222008, 0.111969, 0, 0.399306, 0.399306, 0.201389, 0 </real_array>
- <int_array len="2502"> 0, 2, 1, 0, 3, 2, 1, 5, 4, 1, 2, 5, 6, 5, 7, 6, 4, 5, 8, 0, 9, 8, 10, 0, 11, 13, 12, 11, 14, 13, 15, 17, 16, 15, 7, 17, 12, 15, 18, 12, 13, 15, 10, 3, 0, 10, 19, 3, 13, 7, 15, 13, 6, 7, 2, 20, 5, 2, 21, 20, 7, 20, 17, 7, 5, 20, 21, 3, 22, 21, 2, 3, 18, 16, 23, 18, 15, 16, 22, 19, 24, 22, 3, 19, 25, 27, 26, 25, 28, 27, 29, 28, 25, 29, 30, 28, 26, 32, 31, 26, 27, 32, 33, 35, 34, 33, 36, 35, 37, 39, 38, 37, 40, 39, 38, 42, 41, 38, 39, 42, 43, 45, 44, 43, 46, 45, 47, 49, 48, 47, 50, 49, 51, 53, 52, 51, 54, 53, 55, 46, 56, 55, 45, 46, 57, 44, 58, 57, 43, 44, 59, 61, 60, 59, 50, 61, 62, 45, 55, 62, 63, 45, 64, 48, 65, 64, 47, 48, 66, 50, 59, 66, 49, 50, 67, 43, 57, 67, 68, 43, 69, 68, 67, 69, 70, 68, 34, 49, 66, 34, 35, 49, 65, 70, 69, 65, 48, 70, 58, 72, 71, 58, 44, 72, 56, 36, 33, 56, 46, 36, 71, 74, 73, 71, 72, 74, 60, 63, 62, 60, 61, 63, 73, 47, 64, 73, 74, 47, 75, 77, 76, 75, 78, 77, 79, 41, 80, 79, 38, 41, 81, 38, 79, 81, 37, 38, 80, 83, 82, 80, 41, 83, 84, 37, 81, 84, 85, 37, 41, 86, 83, 41, 42, 86, 85, 40, 37, 85, 87, 40, 42, 88, 86, 42, 89, 88, 87, 90, 40, 87, 91, 90, 40, 92, 39, 40, 90, 92, 39, 89, 42, 39, 92, 89, 48, 35, 70, 48, 49, 35, 74, 50, 47, 74, 61, 50, 70, 36, 68, 70, 35, 36, 44, 63, 72, 44, 45, 63, 68, 46, 43, 68, 36, 46, 72, 61, 74, 72, 63, 61, 93, 95, 94, 93, 96, 95, 97, 25, 26, 97, 98, 25, 98, 29, 25, 98, 99, 29, 100, 26, 31, 100, 97, 26, 31, 102, 101, 31, 32, 102, 103, 105, 104, 103, 106, 105, 104, 108, 107, 104, 105, 108, 107, 110, 109, 107, 108, 110, 111, 113, 112, 111, 114, 113, 115, 112, 116, 115, 111, 112, 117, 116, 118, 117, 115, 116, 119, 118, 120, 119, 117, 118, 114, 110, 113, 114, 109, 110, 121, 123, 122, 121, 124, 123, 125, 124, 121, 125, 126, 124, 127, 129, 128, 128, 129, 130, 131, 129, 132, 133, 130, 129, 134, 133, 129, 135, 134, 129, 136, 138, 137, 136, 139, 138, 140, 142, 141, 140, 143, 142, 144, 146, 145, 144, 147, 146, 145, 149, 148, 145, 146, 149, 148, 151, 150, 148, 149, 151, 150, 153, 152, 150, 151, 153, 152, 143, 140, 152, 153, 143, 154, 156, 155, 154, 157, 156, 155, 159, 158, 155, 156, 159, 158, 106, 103, 158, 159, 106, 160, 162, 161, 160, 163, 162, 164, 161, 165, 164, 160, 161, 166, 165, 167, 166, 164, 165, 168, 167, 169, 168, 166, 167, 154, 120, 157, 154, 119, 120, 144, 169, 147, 144, 168, 169, 163, 142, 162, 163, 141, 142, 170, 172, 171, 170, 173, 172, 174, 173, 170, 174, 175, 173, 176, 178, 177, 176, 179, 178, 177, 126, 125, 177, 178, 126, 180, 179, 176, 180, 181, 179, 122, 181, 180, 122, 123, 181, 182, 184, 183, 182, 185, 184, 183, 187, 186, 183, 184, 187, 186, 189, 188, 186, 187, 189, 188, 191, 190, 188, 189, 191, 190, 193, 192, 190, 191, 193, 192, 195, 194, 192, 193, 195, 196, 198, 197, 196, 199, 198, 200, 197, 201, 200, 196, 197, 202, 201, 203, 202, 200, 201, 204, 203, 205, 204, 202, 203, 199, 195, 198, 199, 194, 195, 182, 205, 185, 182, 204, 205, 206, 129, 127, 207, 129, 131, 132, 129, 206, 208, 135, 129, 209, 208, 129, 207, 209, 129, 210, 139, 136, 210, 211, 139, 28, 212, 27, 28, 213, 212, 30, 213, 28, 30, 214, 213, 27, 215, 32, 27, 212, 215, 216, 218, 217, 216, 219, 218, 220, 95, 221, 220, 94, 95, 222, 218, 219, 222, 223, 218, 224, 96, 93, 224, 225, 96, 220, 223, 222, 220, 221, 223, 226, 78, 75, 226, 227, 78, 228, 230, 229, 228, 231, 230, 232, 234, 233, 232, 235, 234, 236, 235, 232, 236, 237, 235, 229, 239, 238, 229, 230, 239, 233, 231, 228, 233, 234, 231, 32, 240, 102, 32, 215, 240, 241, 243, 242, 241, 244, 243, 76, 246, 245, 76, 77, 246, 247, 227, 226, 247, 248, 227, 242, 250, 249, 242, 243, 250, 245, 244, 241, 245, 246, 244, 249, 248, 247, 249, 250, 248, 238, 252, 251, 238, 239, 252, 253, 237, 236, 253, 254, 237, 251, 254, 253, 251, 252, 254, 102, 240, 255, 9, 1, 256, 9, 0, 1, 14, 6, 13, 14, 257, 6, 256, 4, 258, 256, 1, 4, 257, 4, 6, 257, 258, 4, 259, 261, 260, 259, 262, 261, 262, 263, 261, 262, 264, 263, 265, 263, 264, 265, 266, 263, 8, 259, 10, 8, 267, 259, 11, 269, 268, 11, 12, 269, 270, 271, 266, 270, 272, 271, 12, 270, 269, 12, 18, 270, 10, 260, 19, 10, 259, 260, 269, 266, 265, 269, 270, 266, 261, 274, 273, 261, 263, 274, 266, 274, 263, 266, 271, 274, 260, 273, 275, 260, 261, 273, 18, 272, 270, 18, 23, 272, 19, 275, 24, 19, 260, 275, 276, 278, 277, 276, 279, 278, 29, 277, 30, 29, 276, 277, 279, 280, 278, 279, 281, 280, 282, 284, 283, 282, 285, 284, 286, 288, 287, 286, 289, 288, 289, 290, 288, 289, 291, 290, 292, 294, 293, 292, 295, 294, 296, 298, 297, 296, 299, 298, 300, 53, 54, 300, 301, 53, 302, 293, 294, 302, 303, 293, 304, 295, 292, 304, 305, 295, 306, 307, 297, 306, 308, 307, 309, 294, 310, 309, 302, 294, 311, 299, 296, 311, 312, 299, 313, 297, 298, 313, 306, 297, 314, 292, 315, 314, 304, 292, 316, 315, 317, 316, 314, 315, 285, 298, 284, 285, 313, 298, 312, 317, 299, 312, 316, 317, 305, 318, 295, 305, 319, 318, 303, 283, 293, 303, 282, 283, 319, 320, 318, 319, 321, 320, 308, 310, 307, 308, 309, 310, 321, 296, 320, 321, 311, 296, 322, 324, 323, 322, 325, 324, 326, 291, 289, 326, 327, 291, 328, 289, 286, 328, 326, 289, 327, 329, 291, 327, 330, 329, 331, 286, 332, 331, 328, 286, 291, 333, 290, 291, 329, 333, 332, 287, 334, 332, 286, 287, 290, 336, 335, 290, 333, 336, 334, 338, 337, 334, 287, 338, 287, 339, 338, 287, 288, 339, 288, 335, 339, 288, 290, 335, 299, 284, 298, 299, 317, 284, 320, 297, 307, 320, 296, 297, 317, 283, 284, 317, 315, 283, 295, 310, 294, 295, 318, 310, 315, 293, 283, 315, 292, 293, 318, 307, 310, 318, 320, 307, 340, 342, 341, 340, 343, 342, 344, 276, 345, 344, 279, 276, 345, 29, 99, 345, 276, 29, 346, 279, 344, 346, 281, 279, 281, 102, 280, 281, 101, 102, 347, 349, 348, 347, 350, 349, 350, 351, 349, 350, 352, 351, 352, 353, 351, 352, 354, 353, 355, 357, 356, 355, 358, 357, 359, 358, 355, 359, 360, 358, 361, 360, 359, 361, 362, 360, 363, 362, 361, 363, 364, 362, 356, 353, 354, 356, 357, 353, 365, 367, 366, 365, 368, 367, 369, 366, 370, 369, 365, 366, 371, 373, 372, 373, 374, 372, 375, 376, 372, 377, 372, 374, 378, 372, 377, 379, 372, 378, 136, 381, 380, 136, 137, 381, 382, 384, 383, 382, 385, 384, 386, 388, 387, 386, 389, 388, 389, 390, 388, 389, 391, 390, 391, 392, 390, 391, 393, 392, 393, 394, 392, 393, 395, 394, 395, 383, 394, 395, 382, 383, 396, 398, 397, 396, 399, 398, 399, 400, 398, 399, 401, 400, 401, 348, 400, 401, 347, 348, 402, 404, 403, 402, 405, 404, 406, 405, 402, 406, 407, 405, 408, 407, 406, 408, 409, 407, 410, 409, 408, 410, 411, 409, 396, 364, 363, 396, 397, 364, 386, 411, 410, 386, 387, 411, 403, 384, 385, 403, 404, 384, 412, 414, 413, 412, 415, 414, 416, 413, 417, 416, 412, 413, 418, 420, 419, 418, 421, 420, 421, 370, 420, 421, 369, 370, 422, 419, 423, 422, 418, 419, 368, 423, 367, 368, 422, 423, 424, 426, 425, 424, 427, 426, 427, 428, 426, 427, 429, 428, 429, 430, 428, 429, 431, 430, 431, 432, 430, 431, 433, 432, 433, 434, 432, 433, 435, 434, 435, 436, 434, 435, 437, 436, 438, 440, 439, 438, 441, 440, 442, 441, 438, 442, 443, 441, 444, 443, 442, 444, 445, 443, 446, 445, 444, 446, 447, 445, 439, 436, 437, 439, 440, 436, 424, 447, 446, 424, 425, 447, 448, 371, 372, 449, 375, 372, 376, 448, 372, 450, 372, 379, 451, 372, 450, 449, 372, 451, 210, 380, 452, 210, 136, 380, 277, 454, 453, 277, 278, 454, 30, 453, 214, 30, 277, 453, 278, 455, 454, 278, 280, 455, 216, 457, 456, 216, 217, 457, 458, 342, 343, 458, 459, 342, 460, 457, 461, 460, 456, 457, 224, 341, 225, 224, 340, 341, 458, 461, 459, 458, 460, 461, 462, 323, 463, 462, 322, 323, 464, 466, 465, 464, 467, 466, 468, 470, 469, 468, 471, 470, 472, 469, 473, 472, 468, 469, 467, 474, 466, 467, 475, 474, 471, 465, 470, 471, 464, 465, 280, 476, 455, 280, 102, 476, 477, 479, 478, 477, 480, 479, 325, 481, 324, 325, 482, 481, 483, 463, 484, 483, 462, 463, 480, 485, 479, 480, 486, 485, 482, 478, 481, 482, 477, 478, 486, 484, 485, 486, 483, 484, 475, 487, 474, 475, 488, 487, 489, 473, 490, 489, 472, 473, 488, 490, 487, 488, 489, 490, 102, 255, 476, 267, 262, 259, 267, 491, 262, 268, 265, 492, 268, 269, 265, 491, 264, 262, 491, 493, 264, 492, 264, 493, 492, 265, 264, 494, 496, 495, 494, 497, 496, 497, 94, 496, 497, 93, 94, 498, 500, 499, 498, 501, 500, 499, 219, 216, 499, 500, 219, 502, 496, 503, 502, 495, 496, 503, 94, 220, 503, 496, 94, 504, 500, 501, 504, 505, 500, 505, 219, 500, 505, 222, 219, 506, 497, 494, 506, 507, 497, 507, 93, 497, 507, 224, 93, 502, 505, 504, 502, 503, 505, 503, 222, 505, 503, 220, 222, 508, 510, 509, 508, 511, 510, 509, 343, 340, 509, 510, 343, 498, 513, 512, 498, 499, 513, 499, 456, 513, 499, 216, 456, 514, 510, 511, 514, 515, 510, 515, 343, 510, 515, 458, 343, 516, 513, 517, 516, 512, 513, 517, 456, 460, 517, 513, 456, 506, 509, 507, 506, 508, 509, 507, 340, 224, 507, 509, 340, 514, 517, 515, 514, 516, 517, 515, 460, 458, 515, 517, 460, 31, 518, 100, 31, 101, 518, 100, 54, 51, 100, 518, 54, 519, 521, 520, 519, 522, 521, 520, 98, 97, 520, 521, 98, 522, 523, 521, 522, 524, 523, 521, 99, 98, 521, 523, 99, 52, 520, 51, 52, 519, 520, 51, 97, 100, 51, 520, 97, 281, 518, 101, 281, 346, 518, 346, 54, 518, 346, 300, 54, 525, 527, 526, 525, 528, 527, 528, 345, 527, 528, 344, 345, 526, 523, 524, 526, 527, 523, 527, 99, 523, 527, 345, 99, 301, 528, 525, 301, 300, 528, 300, 344, 528, 300, 346, 344, 529, 531, 530, 529, 532, 531, 530, 534, 533, 530, 531, 534, 533, 325, 322, 533, 534, 325, 535, 530, 536, 535, 529, 530, 536, 533, 537, 536, 530, 533, 537, 322, 462, 537, 533, 322, 538, 540, 539, 538, 541, 540, 539, 543, 542, 539, 540, 543, 542, 480, 477, 542, 543, 480, 532, 544, 531, 532, 545, 544, 531, 546, 534, 531, 544, 546, 534, 482, 325, 534, 546, 482, 547, 536, 548, 547, 535, 536, 548, 537, 549, 548, 536, 537, 549, 462, 483, 549, 537, 462, 541, 550, 540, 541, 551, 550, 540, 552, 543, 540, 550, 552, 543, 486, 480, 543, 552, 486, 545, 539, 544, 545, 538, 539, 544, 542, 546, 544, 539, 542, 546, 477, 482, 546, 542, 477, 551, 548, 550, 551, 547, 548, 550, 549, 552, 550, 548, 549, 552, 483, 486, 552, 549, 483, 553, 555, 554, 553, 556, 555, 556, 557, 555, 556, 558, 557, 558, 76, 557, 558, 75, 76, 559, 556, 553, 559, 560, 556, 560, 558, 556, 560, 561, 558, 561, 75, 558, 561, 226, 75, 562, 564, 563, 562, 565, 564, 565, 566, 564, 565, 567, 566, 567, 242, 566, 567, 241, 242, 554, 569, 568, 554, 555, 569, 555, 570, 569, 555, 557, 570, 557, 245, 570, 557, 76, 245, 571, 560, 559, 571, 572, 560, 572, 561, 560, 572, 573, 561, 573, 226, 561, 573, 247, 226, 563, 575, 574, 563, 564, 575, 564, 576, 575, 564, 566, 576, 566, 249, 576, 566, 242, 249, 568, 565, 562, 568, 569, 565, 569, 567, 565, 569, 570, 567, 570, 241, 567, 570, 245, 241, 574, 572, 571, 574, 575, 572, 575, 573, 572, 575, 576, 573, 576, 247, 573, 576, 249, 247, 577, 579, 578, 577, 580, 579, 580, 581, 579, 580, 582, 581, 582, 229, 581, 582, 228, 229, 583, 585, 584, 583, 586, 585, 586, 587, 585, 586, 588, 587, 588, 233, 587, 588, 232, 233, 589, 586, 583, 589, 590, 586, 590, 588, 586, 590, 591, 588, 591, 232, 588, 591, 236, 232, 578, 593, 592, 578, 579, 593, 579, 594, 593, 579, 581, 594, 581, 238, 594, 581, 229, 238, 584, 580, 577, 584, 585, 580, 585, 582, 580, 585, 587, 582, 587, 228, 582, 587, 233, 228, 592, 596, 595, 592, 593, 596, 593, 597, 596, 593, 594, 597, 594, 251, 597, 594, 238, 251, 598, 590, 589, 598, 599, 590, 599, 591, 590, 599, 600, 591, 600, 236, 591, 600, 253, 236, 595, 599, 598, 595, 596, 599, 596, 600, 599, 596, 597, 600, 597, 253, 600, 597, 251, 253, 601, 603, 602, 601, 604, 603, 602, 606, 605, 602, 603, 606, 605, 467, 464, 605, 606, 467, 607, 609, 608, 607, 610, 609, 608, 612, 611, 608, 609, 612, 611, 471, 468, 611, 612, 471, 613, 608, 614, 613, 607, 608, 614, 611, 615, 614, 608, 611, 615, 468, 472, 615, 611, 468, 604, 616, 603, 604, 617, 616, 603, 618, 606, 603, 616, 618, 606, 475, 467, 606, 618, 475, 610, 602, 609, 610, 601, 602, 609, 605, 612, 609, 602, 605, 612, 464, 471, 612, 605, 464, 617, 619, 616, 617, 620, 619, 616, 621, 618, 616, 619, 621, 618, 488, 475, 618, 621, 488, 622, 614, 623, 622, 613, 614, 623, 615, 624, 623, 614, 615, 624, 472, 489, 624, 615, 472, 620, 623, 619, 620, 622, 623, 619, 624, 621, 619, 623, 624, 621, 489, 488, 621, 624, 489 </int_array>
- </array>
- </dictionary>
-
- </resource>
- <resource type="SampleLibrary" path="local://6">
- </resource>
- <resource type="Animation" path="local://7">
- <string name="resource/name"> "idle" </string>
- <real name="length"> 1.25 </real>
- <bool name="loop"> True </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="180"> 0, 1, 1.01328e-06, -8.34465e-07, 1.07288e-06, -0.0255728, 0.138077, -0.259039, 0.955604, 1, 1, 1, 0.05, 1, 5.96046e-07, -2.38419e-07, 3.8743e-07, -0.0264725, 0.139277, -0.25962, 0.955248, 1, 1, 1, 0.1, 1, 5.36442e-07, -2.38419e-07, 3.8743e-07, -0.028916, 0.142508, -0.261183, 0.954274, 1, 1, 1, 0.15, 1, 1.19209e-07, 1.19209e-07, 5.96046e-08, -0.0326835, 0.14736, -0.26354, 0.952766, 1, 1, 1, 0.25, 1, 5.96046e-08, 1.19209e-07, 0, -0.0433083, 0.158072, -0.268982, 0.949098, 1, 1, 1, 0.3, 1, 8.9407e-07, -3.57628e-07, 5.96046e-07, -0.0481632, 0.16058, -0.27034, 0.948056, 1, 1, 1, 0.35, 1, 7.15256e-07, -3.57628e-07, 5.36442e-07, -0.0515519, 0.159894, -0.270034, 0.948081, 1, 1, 1, 0.4, 1, 6.25849e-07, -3.57628e-07, 5.06639e-07, -0.0529994, 0.155917, -0.267946, 0.949256, 1, 1, 1, 0.85, 1, 8.04663e-07, -5.96046e-07, 8.34465e-07, -0.01551, 0.114246, -0.235933, 0.964906, 1, 1, 1, 0.9, 1, 7.15256e-07, -4.76837e-07, 7.15256e-07, -0.0133439, 0.115591, -0.236366, 0.964672, 1, 1, 1, 0.95, 1, 5.06639e-07, -3.57628e-07, 4.76837e-07, -0.0142794, 0.118993, -0.239276, 0.963527, 1, 1, 1, 1.1, 1, 6.55651e-07, -3.57628e-07, 5.36442e-07, -0.0224776, 0.132362, -0.25315, 0.958066, 1, 1, 1, 1.15, 1, 7.45058e-07, -2.38419e-07, 4.17233e-07, -0.0241962, 0.135447, -0.25637, 0.956736, 1, 1, 1, 1.2, 1, 7.15256e-07, -2.38419e-07, 5.06639e-07, -0.0252313, 0.137384, -0.258343, 0.955902, 1, 1, 1, 1.25, 1, 1.01328e-06, -8.34465e-07, 1.07288e-06, -0.0255726, 0.138077, -0.259039, 0.955604, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="204"> 0, 1, 2.38419e-07, -8.34465e-07, -4.76837e-07, -0.218168, -0.120735, -0.0116329, 0.968344, 1, 1, 1, 0.05, 1, 2.98023e-08, -5.96046e-07, -2.38419e-07, -0.218633, -0.120967, -0.0119311, 0.968207, 1, 1, 1, 0.1, 1, 1.78814e-07, -7.7486e-07, -4.76837e-07, -0.219848, -0.121646, -0.0127373, 0.967836, 1, 1, 1, 0.15, 1, -5.96046e-08, -6.25849e-07, -4.76837e-07, -0.221585, -0.122891, -0.0139574, 0.967266, 1, 1, 1, 0.2, 1, -2.98023e-08, -9.83477e-07, -1.78814e-07, -0.223801, -0.125062, -0.0151597, 0.966459, 1, 1, 1, 0.25, 1, 1.49012e-07, -5.66244e-07, -2.38419e-07, -0.225991, -0.128733, -0.0159408, 0.965454, 1, 1, 1, 0.3, 1, 0, -1.04308e-06, -2.38419e-07, -0.227229, -0.134329, -0.0159913, 0.9644, 1, 0.999999, 1, 0.55, 1, 2.98023e-08, -5.66244e-07, -3.57628e-07, -0.218159, -0.170756, -0.00658222, 0.960836, 1, 1, 1, 0.6, 1, 1.49012e-07, -5.36442e-07, -2.98023e-07, -0.214746, -0.174272, -0.00460497, 0.960985, 1, 1, 1, 0.65, 1, 2.38419e-07, -2.08616e-07, -3.57628e-07, -0.21128, -0.17607, -0.0030008, 0.961432, 1, 1, 1, 0.7, 1, 1.49012e-07, -4.47035e-07, -2.38419e-07, -0.207961, -0.17612, -0.00179697, 0.962149, 1, 1, 1, 0.75, 1, -2.38419e-07, -6.55651e-07, -3.57628e-07, -0.204984, -0.174339, -0.000935222, 0.963113, 1, 1, 1, 0.8, 1, 8.9407e-08, -2.98023e-08, -1.19209e-07, -0.202542, -0.170485, -0.000499965, 0.964319, 1, 0.999999, 1, 0.85, 1, 8.9407e-08, -8.64267e-07, -4.17233e-07, -0.200954, -0.164989, -0.000498206, 0.965607, 1, 0.999999, 1, 1.15, 1, 1.19209e-07, -6.85453e-07, -2.98023e-07, -0.216378, -0.124725, -0.0104075, 0.968254, 1, 1, 1, 1.2, 1, -2.98023e-08, 2.98023e-08, -1.78814e-07, -0.217708, -0.121801, -0.0113103, 0.968318, 1, 1, 1, 1.25, 1, 2.38419e-07, -8.34465e-07, -4.76837e-07, -0.218168, -0.120734, -0.0116329, 0.968344, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="180"> 0, 1, -1.01328e-06, -8.34465e-07, 1.07288e-06, -0.0255728, -0.138077, 0.25904, 0.955604, 1, 1, 1, 0.05, 1, -5.96046e-07, -2.38419e-07, 3.8743e-07, -0.0264725, -0.139277, 0.25962, 0.955248, 1, 1, 1, 0.1, 1, -5.36442e-07, -2.38419e-07, 3.8743e-07, -0.028916, -0.142508, 0.261183, 0.954274, 1, 1, 1, 0.15, 1, -1.19209e-07, 1.19209e-07, 5.96046e-08, -0.0326835, -0.14736, 0.26354, 0.952766, 1, 1, 1, 0.25, 1, -5.96046e-08, 1.19209e-07, 0, -0.0433083, -0.158072, 0.268982, 0.949098, 1, 1, 1, 0.3, 1, -8.9407e-07, -3.57628e-07, 5.96046e-07, -0.0481632, -0.16058, 0.27034, 0.948056, 1, 1, 1, 0.35, 1, -7.15256e-07, -3.57628e-07, 5.36442e-07, -0.0515519, -0.159894, 0.270034, 0.948081, 1, 1, 1, 0.4, 1, -6.25849e-07, -3.57628e-07, 5.06639e-07, -0.0529994, -0.155917, 0.267946, 0.949256, 1, 1, 1, 0.85, 1, -8.04663e-07, -5.96046e-07, 8.34465e-07, -0.01551, -0.114246, 0.235933, 0.964906, 1, 1, 1, 0.9, 1, -7.15256e-07, -4.76837e-07, 7.15256e-07, -0.0133439, -0.115591, 0.236367, 0.964672, 1, 1, 1, 0.95, 1, -5.06639e-07, -3.57628e-07, 4.76837e-07, -0.0142794, -0.118993, 0.239276, 0.963527, 1, 1, 1, 1.1, 1, -6.55651e-07, -3.57628e-07, 5.36442e-07, -0.0224776, -0.132362, 0.25315, 0.958066, 1, 1, 1, 1.15, 1, -7.45058e-07, -2.38419e-07, 4.17233e-07, -0.0241962, -0.135447, 0.25637, 0.956736, 1, 1, 1, 1.2, 1, -7.15256e-07, -2.38419e-07, 5.06639e-07, -0.0252313, -0.137384, 0.258343, 0.955902, 1, 1, 1, 1.25, 1, -1.01328e-06, -8.34465e-07, 1.07288e-06, -0.0255726, -0.138077, 0.259039, 0.955604, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="204"> 0, 1, -2.38419e-07, -8.34465e-07, -4.76837e-07, -0.218168, 0.120735, 0.0116329, 0.968344, 1, 1, 1, 0.05, 1, -5.96046e-08, -8.04663e-07, -3.57628e-07, -0.218633, 0.120966, 0.0119311, 0.968207, 1, 1, 1, 0.1, 1, -3.57628e-07, -7.45058e-07, -4.17233e-07, -0.219848, 0.121646, 0.0127373, 0.967836, 1, 1, 1, 0.15, 1, -1.49012e-07, -6.25849e-07, -3.57628e-07, -0.221585, 0.122891, 0.0139575, 0.967266, 1, 1, 1, 0.2, 1, 0, -9.53674e-07, -1.19209e-07, -0.223801, 0.125062, 0.0151597, 0.966459, 1, 1, 1, 0.25, 1, -1.49012e-07, -5.66244e-07, -2.38419e-07, -0.225991, 0.128733, 0.0159408, 0.965454, 1, 1, 1, 0.3, 1, 0, -1.04308e-06, -2.38419e-07, -0.227229, 0.134329, 0.0159913, 0.9644, 1, 0.999999, 1, 0.55, 1, -2.98023e-08, -5.66244e-07, -3.57628e-07, -0.218159, 0.170756, 0.00658222, 0.960836, 1, 1, 1, 0.6, 1, -1.49012e-07, -5.36442e-07, -2.98023e-07, -0.214746, 0.174272, 0.00460497, 0.960985, 1, 1, 1, 0.65, 1, -2.38419e-07, -2.08616e-07, -3.57628e-07, -0.21128, 0.17607, 0.0030008, 0.961432, 1, 1, 1, 0.7, 1, -1.49012e-07, -4.47035e-07, -2.38419e-07, -0.207961, 0.17612, 0.00179697, 0.962149, 1, 1, 1, 0.75, 1, 2.38419e-07, -6.55651e-07, -3.57628e-07, -0.204984, 0.174339, 0.000935222, 0.963113, 1, 1, 1, 0.8, 1, -2.98023e-08, 0, -1.19209e-07, -0.202542, 0.170485, 0.000499968, 0.964319, 1, 1, 1, 0.85, 1, 1.49012e-07, -8.34465e-07, -4.17233e-07, -0.200954, 0.164989, 0.000498198, 0.965606, 1, 1, 1, 1.15, 1, -2.38419e-07, -8.04663e-07, -6.55651e-07, -0.216378, 0.124725, 0.0104075, 0.968254, 1, 1, 1, 1.2, 1, -2.08616e-07, 2.08616e-07, -2.98023e-07, -0.217708, 0.121801, 0.0113103, 0.968318, 1, 1, 1, 1.25, 1, -2.38419e-07, -8.34465e-07, -4.76837e-07, -0.218168, 0.120734, 0.0116329, 0.968344, 1, 1, 1 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="180"> 0, 1, 0, 5.21541e-08, -3.42727e-07, -0.0539951, -0.0696263, 0.0213632, 0.995882, 1, 1, 1, 0.05, 1, 0, 5.21541e-08, -3.42727e-07, -0.0567764, -0.0700338, 0.0212387, 0.995701, 1, 1, 1, 0.1, 1, 0, 3.72529e-08, -3.42727e-07, -0.06411, -0.0711033, 0.0209058, 0.995187, 1, 1, 1, 0.15, 1, 0, 9.68575e-08, -3.42727e-07, -0.0751103, -0.0727354, 0.0204167, 0.994309, 1, 1, 1, 0.45, 1, 0, 1.41561e-07, -1.3411e-07, -0.154319, -0.0862804, 0.0175296, 0.984091, 1, 1, 1, 0.5, 1, 2.98023e-08, 7.45058e-09, 2.5332e-07, -0.162001, -0.0877685, 0.017297, 0.982728, 1, 1, 1, 0.55, 1, 0, 3.72529e-08, -3.42727e-07, -0.166842, -0.0887317, 0.0171579, 0.981833, 1, 1, 1, 0.6, 1, 0, 2.98023e-08, -1.49012e-07, -0.169226, -0.0892111, 0.0170905, 0.981383, 1, 1, 1, 0.65, 1, 0, 2.98023e-08, -1.49012e-07, -0.169226, -0.0892111, 0.0170905, 0.981383, 1, 1, 1, 0.7, 1, 0, 3.72529e-08, -3.42727e-07, -0.166842, -0.0887317, 0.0171579, 0.981833, 1, 1, 1, 0.75, 1, 2.98023e-08, 7.45058e-09, 2.5332e-07, -0.162001, -0.0877685, 0.017297, 0.982728, 1, 1, 1, 0.8, 1, 0, 1.41561e-07, -1.3411e-07, -0.154319, -0.0862804, 0.0175296, 0.984091, 1, 1, 1, 1.15, 1, 0, 3.72529e-08, -3.42727e-07, -0.06411, -0.0711033, 0.0209058, 0.995187, 1, 1, 1, 1.2, 1, 0, 5.21541e-08, -3.42727e-07, -0.0567764, -0.0700338, 0.0212387, 0.995701, 1, 1, 1, 1.25, 1, 0, 5.21541e-08, -3.42727e-07, -0.0539951, -0.0696263, 0.0213632, 0.995882, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="192"> 0, 1, 1.42842e-07, 1.93715e-07, 2.98023e-07, -0.0965851, -0.0177476, 0.000627753, 0.995166, 1, 1, 1, 0.05, 1, 4.62169e-08, -6.70552e-08, 6.55651e-07, -0.100604, -0.0182764, 0.000608928, 0.994758, 1, 1, 1, 0.1, 1, 8.12579e-08, 5.96046e-08, 5.36442e-07, -0.111195, -0.0196529, 0.000562433, 0.993604, 1, 1, 1, 0.15, 1, 3.0268e-08, -2.98023e-08, 5.96046e-07, -0.127055, -0.0217242, 0.000494295, 0.991658, 1, 1, 1, 0.45, 1, 1.55647e-07, 1.49012e-07, 4.76837e-07, -0.240017, -0.0376881, -3.78875e-05, 0.970037, 1, 1, 1, 0.5, 1, -1.23866e-07, 3.57628e-07, 7.7486e-07, -0.250826, -0.0393224, -9.00224e-05, 0.967233, 1, 1, 1, 0.55, 1, 5.34346e-08, 3.72529e-08, 5.96046e-07, -0.25762, -0.040368, -0.000123774, 0.965403, 1, 1, 1, 0.6, 1, 1.08266e-08, 5.96046e-08, 7.15256e-07, -0.260963, -0.0408854, -0.000140397, 0.964483, 1, 1, 1, 0.65, 1, 1.08266e-08, 5.96046e-08, 7.15256e-07, -0.260963, -0.0408854, -0.000140397, 0.964483, 1, 1, 1, 0.7, 1, 5.34346e-08, 3.72529e-08, 5.96046e-07, -0.25762, -0.040368, -0.000123775, 0.965403, 1, 1, 1, 0.75, 1, -1.23866e-07, 3.57628e-07, 7.7486e-07, -0.250826, -0.0393224, -9.00224e-05, 0.967233, 1, 1, 1, 0.8, 1, 1.55647e-07, 1.49012e-07, 4.76837e-07, -0.240017, -0.0376881, -3.78871e-05, 0.970037, 1, 1, 1, 0.9, 1, -4.8778e-08, -1.3411e-07, 7.15256e-07, -0.208519, -0.0330444, 0.00011266, 0.97746, 1, 1, 1, 1.15, 1, 8.12579e-08, 5.96046e-08, 5.36442e-07, -0.111195, -0.0196529, 0.000562432, 0.993604, 1, 1, 1, 1.2, 1, 4.62169e-08, -6.70552e-08, 6.55651e-07, -0.100605, -0.0182764, 0.000608928, 0.994758, 1, 1, 1, 1.25, 1, 1.42842e-07, 1.93715e-07, 2.98023e-07, -0.0965852, -0.0177476, 0.000627753, 0.995166, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="180"> 0, 1, 8.9407e-08, 2.38419e-07, -2.23517e-08, 0.0349931, -0.0301778, 0.0362945, 0.998272, 1, 1, 1, 0.05, 1, 7.45058e-08, 2.38419e-07, 6.33299e-08, 0.0358993, -0.0301376, 0.0363473, 0.998239, 1, 1, 1, 0.1, 1, 5.21541e-08, 1.19209e-07, 2.98023e-08, 0.0384013, -0.0300263, 0.0364927, 0.998144, 1, 1, 1, 0.15, 1, 4.47035e-08, 1.19209e-07, -1.11759e-08, 0.0424549, -0.0298457, 0.0367279, 0.997977, 1, 1, 1, 0.5, 1, 5.21541e-08, 1.19209e-07, 7.45058e-09, 0.0873535, -0.0278095, 0.0392948, 0.995014, 1, 1, 1, 0.55, 1, -7.45058e-09, 0, -5.21541e-08, 0.0905253, -0.0276632, 0.0394735, 0.994727, 1, 1, 1, 0.6, 1, 2.98023e-08, 0, 2.23517e-08, 0.0921114, -0.0275899, 0.0395627, 0.99458, 1, 1, 1, 0.65, 1, 2.98023e-08, 0, 2.23517e-08, 0.0921114, -0.0275899, 0.0395627, 0.99458, 1, 1, 1, 0.7, 1, -7.45058e-09, 0, -5.21541e-08, 0.0905253, -0.0276632, 0.0394735, 0.994727, 1, 1, 1, 0.75, 1, 5.21541e-08, 1.19209e-07, 7.45058e-09, 0.0873535, -0.0278095, 0.0392948, 0.995014, 1, 1, 1, 0.8, 1, 1.04308e-07, 2.38419e-07, -1.49012e-08, 0.0824784, -0.0280337, 0.0390195, 0.995434, 1, 1, 1, 1.1, 1, 4.47035e-08, 1.19209e-07, -1.11759e-08, 0.0424549, -0.0298457, 0.0367279, 0.997977, 1, 1, 1, 1.15, 1, 5.21541e-08, 1.19209e-07, 2.98023e-08, 0.0384013, -0.0300263, 0.0364927, 0.998144, 1, 1, 1, 1.2, 1, 7.45058e-08, 2.38419e-07, 6.33299e-08, 0.0358993, -0.0301376, 0.0363473, 0.998239, 1, 1, 1, 1.25, 1, 8.9407e-08, 2.38419e-07, -2.23517e-08, 0.0349931, -0.0301778, 0.0362945, 0.998272, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="180"> 0, 1, 0, 6.70552e-08, -1.04308e-07, -0.0539995, 0.0696269, -0.0213643, 0.995881, 1, 0.999999, 1, 0.05, 1, 0, 6.70552e-08, -1.04308e-07, -0.05678, 0.0700343, -0.0212398, 0.995701, 1, 0.999999, 1, 0.1, 1, 0, 2.23517e-08, -1.04308e-07, -0.0641135, 0.0711039, -0.0209069, 0.995187, 1, 0.999999, 1, 0.15, 1, 0, 8.19564e-08, -1.04308e-07, -0.075114, 0.072736, -0.0204178, 0.994309, 1, 0.999999, 1, 0.45, 1, -2.98023e-08, 1.04308e-07, 1.04308e-07, -0.15432, 0.0862808, -0.0175308, 0.98409, 1, 0.999999, 1, 0.5, 1, -5.96046e-08, 2.98023e-08, 4.91738e-07, -0.162002, 0.0877689, -0.0172983, 0.982727, 1, 0.999999, 1, 0.55, 1, 0, 5.21541e-08, -1.04308e-07, -0.166843, 0.0887321, -0.0171591, 0.981833, 1, 0.999999, 1, 0.6, 1, -2.98023e-08, 4.47035e-08, 8.9407e-08, -0.169228, 0.0892116, -0.0170917, 0.981382, 1, 0.999999, 1, 0.65, 1, -2.98023e-08, 4.47035e-08, 8.9407e-08, -0.169228, 0.0892116, -0.0170917, 0.981382, 1, 0.999999, 1, 0.7, 1, 0, 5.21541e-08, -1.04308e-07, -0.166843, 0.0887321, -0.0171591, 0.981833, 1, 0.999999, 1, 0.75, 1, -5.96046e-08, 2.98023e-08, 4.91738e-07, -0.162002, 0.0877689, -0.0172983, 0.982727, 1, 0.999999, 1, 0.8, 1, -2.98023e-08, 1.04308e-07, 1.04308e-07, -0.15432, 0.0862808, -0.0175308, 0.98409, 1, 0.999999, 1, 1.15, 1, 0, 2.23517e-08, -1.04308e-07, -0.0641135, 0.0711039, -0.020907, 0.995187, 1, 0.999999, 1, 1.2, 1, 0, 6.70552e-08, -1.04308e-07, -0.05678, 0.0700343, -0.0212398, 0.995701, 1, 0.999999, 1, 1.25, 1, 0, 6.70552e-08, -1.04308e-07, -0.0539992, 0.0696269, -0.0213643, 0.995881, 1, 0.999999, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="192"> 0, 1, 9.06875e-08, -8.19564e-08, 3.57628e-07, -0.0965913, 0.0177484, -0.00062776, 0.995166, 1, 1, 1, 0.05, 1, 3.44589e-08, -1.93715e-07, 2.98023e-07, -0.10061, 0.0182771, -0.000608941, 0.994758, 1, 1, 1, 0.1, 1, 2.52621e-08, -1.86265e-07, 5.96046e-08, -0.1112, 0.0196536, -0.000562456, 0.993604, 1, 1, 1, 0.15, 1, 9.02219e-08, -1.19209e-07, 1.19209e-07, -0.127061, 0.021725, -0.000494313, 0.991657, 1, 1, 1, 0.45, 1, 7.13626e-08, -5.21541e-08, 1.19209e-07, -0.24002, 0.0376883, 3.78708e-05, 0.970036, 1, 1, 1, 0.5, 1, -2.84053e-08, -1.78814e-07, -1.78814e-07, -0.250828, 0.0393224, 9.00085e-05, 0.967233, 1, 1, 1, 0.55, 1, 1.234e-08, 2.01166e-07, 1.78814e-07, -0.257623, 0.0403681, 0.000123756, 0.965402, 1, 1, 1, 0.6, 1, -9.97679e-08, 5.21541e-08, -5.96046e-08, -0.260966, 0.0408856, 0.000140381, 0.964482, 1, 1, 1, 0.65, 1, -9.97679e-08, 5.21541e-08, -5.96046e-08, -0.260966, 0.0408856, 0.000140381, 0.964482, 1, 1, 1, 0.7, 1, 1.234e-08, 2.01166e-07, 1.78814e-07, -0.257623, 0.0403681, 0.000123754, 0.965402, 1, 1, 1, 0.75, 1, -2.84053e-08, -1.78814e-07, -1.78814e-07, -0.250828, 0.0393224, 9.00085e-05, 0.967233, 1, 1, 1, 0.8, 1, 7.13626e-08, -5.21541e-08, 1.19209e-07, -0.24002, 0.0376883, 3.78693e-05, 0.970036, 1, 1, 1, 0.9, 1, 3.73693e-08, -5.21541e-08, 2.38419e-07, -0.208521, 0.0330446, -0.000112648, 0.977459, 1, 1, 1, 1.15, 1, 2.52621e-08, -1.86265e-07, 5.96046e-08, -0.1112, 0.0196536, -0.000562457, 0.993604, 1, 1, 1, 1.2, 1, 3.44589e-08, -1.93715e-07, 2.98023e-07, -0.10061, 0.0182771, -0.000608943, 0.994758, 1, 1, 1, 1.25, 1, 9.06875e-08, -8.19564e-08, 3.57628e-07, -0.0965911, 0.0177484, -0.000627765, 0.995166, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="180"> 0, 1, -6.70552e-08, 0, -3.72529e-09, 0.0349931, 0.0301778, -0.0362945, 0.998272, 1, 1, 1, 0.05, 1, -1.49012e-08, 1.19209e-07, -7.45058e-09, 0.0358993, 0.0301376, -0.0363473, 0.998239, 1, 1, 1, 0.1, 1, 1.49012e-08, -1.19209e-07, 1.49012e-08, 0.0384013, 0.0300263, -0.0364927, 0.998144, 1, 1, 1, 0.15, 1, -4.47035e-08, 0, -3.72529e-09, 0.0424549, 0.0298457, -0.0367279, 0.997977, 1, 1, 1, 0.5, 1, 5.21541e-08, 0, -1.11759e-08, 0.0873535, 0.0278095, -0.0392948, 0.995014, 1, 1, 1, 0.55, 1, 4.47035e-08, 0, -2.98023e-08, 0.0905253, 0.0276632, -0.0394736, 0.994727, 1, 1, 1, 0.6, 1, 1.49012e-08, 0, -1.86265e-08, 0.0921114, 0.02759, -0.0395628, 0.99458, 1, 1, 1, 0.65, 1, 1.49012e-08, 0, -1.86265e-08, 0.0921114, 0.02759, -0.0395628, 0.99458, 1, 1, 1, 0.7, 1, 4.47035e-08, 0, -2.98023e-08, 0.0905253, 0.0276633, -0.0394736, 0.994727, 1, 1, 1, 0.75, 1, 5.21541e-08, 0, -1.11759e-08, 0.0873535, 0.0278095, -0.0392948, 0.995014, 1, 1, 1, 0.8, 1, -3.72529e-08, 1.19209e-07, -1.11759e-08, 0.0824784, 0.0280338, -0.0390195, 0.995434, 1, 1, 1, 1.1, 1, -4.47035e-08, 0, -3.72529e-09, 0.0424549, 0.0298457, -0.0367279, 0.997977, 1, 1, 1, 1.15, 1, 1.49012e-08, -1.19209e-07, 1.49012e-08, 0.0384013, 0.0300263, -0.0364927, 0.998144, 1, 1, 1, 1.2, 1, -1.49012e-08, 1.19209e-07, -7.45058e-09, 0.0358992, 0.0301376, -0.0363473, 0.998239, 1, 1, 1, 1.25, 1, -6.70552e-08, 0, -3.72529e-09, 0.0349931, 0.0301778, -0.0362945, 0.998272, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="24"> 0, 1, 0, -0.322829, 2.42144e-08, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0, -0.322829, 2.42144e-08, 5.1658e-08, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="24"> 0, 1, -5.68434e-14, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -5.68434e-14, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="24"> 0, 1, 0.220288, -4.0302e-11, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.220288, -4.0302e-11, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="24"> 0, 1, -0.220288, -4.0302e-11, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.220288, -4.0302e-11, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="24"> 0, 1, -0.183564, 0.0305941, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.183564, 0.0305941, 5.96046e-08, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="24"> 0, 1, 0.183564, 0.030594, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.183564, 0.030594, 5.96046e-08, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="168"> 0, 1, -1.15243, -0.687477, 0.0713858, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -1.15504, -0.689394, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -1.16214, -0.694617, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, -1.17317, -0.702725, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.3, 1, -1.21295, -0.731968, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.35, 1, -1.22128, -0.738092, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -1.2252, -0.740971, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -1.22553, -0.741211, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, -1.22422, -0.740253, 0.0713858, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -1.22161, -0.73833, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.6, 1, -1.21787, -0.735585, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.15, 1, -1.15488, -0.689275, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.2, 1, -1.15308, -0.687955, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.25, 1, -1.15243, -0.687477, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="168"> 0, 1, 1.15243, -0.687477, 0.0713859, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 1.15504, -0.689394, 0.0713859, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, 1.16214, -0.694617, 0.0713859, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, 1.17317, -0.702725, 0.0713859, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.3, 1, 1.21295, -0.731968, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.35, 1, 1.22128, -0.738092, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, 1.2252, -0.740971, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, 1.22553, -0.741211, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, 1.22422, -0.740253, 0.0713858, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, 1.22161, -0.73833, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.6, 1, 1.21787, -0.735585, 0.0713858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.15, 1, 1.15488, -0.689275, 0.0713859, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.2, 1, 1.15308, -0.687955, 0.0713859, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.25, 1, 1.15243, -0.687477, 0.0713859, -5.1658e-08, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="156"> 0, 1, 0.849557, -0.741664, 4.9468, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.849557, -0.741664, 4.93101, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, 0.849557, -0.741664, 4.88735, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, 0.849557, -0.741664, 4.81599, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, 0.849557, -0.741664, 4.71797, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.75, 1, 0.849557, -0.741664, 3.21234, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, 0.849557, -0.741664, 3.18081, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.85, 1, 0.849557, -0.741664, 3.18869, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.9, 1, 0.849557, -0.741664, 3.28296, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.95, 1, 0.849557, -0.741664, 3.48291, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.15, 1, 0.849557, -0.741664, 4.70777, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.2, 1, 0.849557, -0.741664, 4.88227, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.849557, -0.741664, 4.9468, -5.1658e-08, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="156"> 0, 1, -0.849557, -0.741664, 4.9468, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.849557, -0.741664, 4.93101, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -0.849557, -0.741664, 4.88735, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, -0.849557, -0.741664, 4.81599, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, -0.849557, -0.741664, 4.71797, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.75, 1, -0.849557, -0.741664, 3.21234, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -0.849557, -0.741664, 3.18081, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.85, 1, -0.849557, -0.741664, 3.18869, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.9, 1, -0.849557, -0.741664, 3.28296, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.95, 1, -0.849557, -0.741664, 3.48291, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.15, 1, -0.849557, -0.741664, 4.70777, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.2, 1, -0.849557, -0.741664, 4.88227, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.849557, -0.741664, 4.9468, -5.1658e-08, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="180"> 0, 1, 1.11759e-08, 0.0713859, 0.0510914, 0, 0, 1.44945e-21, 1, 1, 1, 1, 0.05, 1, 1.11759e-08, 0.0713859, 0.0522077, -4.26326e-14, 4.23516e-22, 1.44945e-21, 1, 1, 1, 1, 0.1, 1, 1.11759e-08, 0.0713859, 0.05529, -5.68434e-14, 2.11758e-21, 1.44945e-21, 1, 1, 1, 1, 0.15, 1, 1.11759e-08, 0.0713859, 0.0602832, -4.26326e-14, 4.23516e-22, 1.44945e-21, 1, 1, 1, 1, 0.5, 1, 1.11759e-08, 0.0713859, 0.115648, 0, 0, 1.44945e-21, 1, 1, 1, 1, 0.55, 1, 1.11759e-08, 0.0713859, 0.119568, -4.26326e-14, 4.23516e-22, 1.44945e-21, 1, 1, 1, 1, 0.6, 1, 1.11759e-08, 0.0713859, 0.121528, -4.26326e-14, 4.23516e-22, 1.44945e-21, 1, 1, 1, 1, 0.65, 1, 1.11759e-08, 0.0713859, 0.121528, -4.26326e-14, 4.23516e-22, 1.44945e-21, 1, 1, 1, 1, 0.7, 1, 1.11759e-08, 0.0713859, 0.119568, -5.68434e-14, 2.11758e-21, 1.44945e-21, 1, 1, 1, 1, 0.75, 1, 1.11759e-08, 0.0713859, 0.115648, 0, 0, 1.44945e-21, 1, 1, 1, 1, 0.8, 1, 1.11759e-08, 0.0713859, 0.109626, -5.68434e-14, 2.11758e-21, 1.44945e-21, 1, 1, 1, 1, 1.1, 1, 1.11759e-08, 0.0713859, 0.0602832, -5.68434e-14, 2.11758e-21, 1.44945e-21, 1, 1, 1, 1, 1.15, 1, 1.11759e-08, 0.0713859, 0.05529, -4.26326e-14, 4.23516e-22, 1.44945e-21, 1, 1, 1, 1, 1.2, 1, 1.11759e-08, 0.0713859, 0.0522077, -2.84217e-14, -4.23516e-22, 1.44945e-21, 1, 1, 1, 1, 1.25, 1, 1.11759e-08, 0.0713859, 0.0510914, -4.26326e-14, 4.23516e-22, 1.44945e-21, 1, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="168"> 0, 1, 5.71157e-15, -1.62345e-08, 8.9407e-08, 0, 0, 2.44616e-35, 1, 1, 1, 1, 0.05, 1, 5.75176e-15, -1.64873e-08, 8.9407e-08, 0.000214909, 1.42979e-18, -2.11758e-22, 1, 1, 1, 1, 0.1, 1, 4.06271e-15, -5.26452e-09, 8.9407e-08, 0.000808293, -3.04932e-19, 2.465e-22, 1, 1, 1, 1, 0.15, 1, 1.54246e-15, 1.14859e-08, 8.9407e-08, 0.00176961, 6.63395e-18, -1.17394e-20, 0.999998, 1, 1, 1, 0.5, 1, 4.42376e-15, -1.05373e-09, -2.98023e-08, 0.0124283, 2.20213e-20, -2.77954e-22, 0.999923, 1, 1, 1, 0.55, 1, 4.56489e-15, -1.94163e-09, 8.9407e-08, 0.0131829, 1.00996e-17, -7.10618e-15, 0.999913, 1, 1, 1, 0.65, 1, 1.79332e-15, -2.38573e-09, 8.9407e-08, 0.0135603, 1.03769e-16, -1.40726e-18, 0.999908, 1, 1, 1, 0.7, 1, 4.56489e-15, -1.94163e-09, 8.9407e-08, 0.0131829, -1.18256e-16, 1.5591e-18, 0.999913, 1, 1, 1, 0.75, 1, 4.42376e-15, -1.05373e-09, -2.98023e-08, 0.0124282, 2.20246e-20, -2.77954e-22, 0.999923, 1, 1, 1, 0.8, 1, 4.20699e-15, 3.1009e-10, -2.98023e-08, 0.011269, -6.2751e-17, 7.07106e-19, 0.999937, 1, 1, 1, 1.1, 1, 1.54246e-15, 1.14859e-08, 8.9407e-08, 0.00176961, 7.93788e-18, -7.10545e-15, 0.999998, 1, 1, 1, 1.15, 1, 4.06271e-15, -5.26452e-09, 8.9407e-08, 0.000808293, -3.04932e-19, 2.465e-22, 1, 1, 1, 1, 1.2, 1, 5.75176e-15, -1.64874e-08, 8.9407e-08, 0.00021491, -2.03966e-18, 4.23517e-22, 1, 1, 1, 1, 1.25, 1, 5.71157e-15, -1.62345e-08, 8.9407e-08, 3.83187e-10, 0, 1.22308e-35, 1, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="156"> 0, 1, 7.24544e-18, 1.86265e-08, 5.96046e-08, 0, 0, -1.33383e-23, 1, 1, 1, 1, 0.05, 1, -3.76414e-18, 3.72529e-09, 0, 0.00110099, -2.41201e-19, -1.97577e-17, 0.999999, 1, 1, 1, 0.1, 1, 9.18675e-18, 1.49012e-08, -1.19209e-07, 0.00410119, -8.96205e-19, -7.35977e-17, 0.999992, 1, 1, 1, 0.15, 1, 1.76552e-17, 7.45058e-09, -5.96046e-08, 0.00875896, -1.91283e-18, -1.57184e-16, 0.999962, 1, 1, 1, 0.3, 1, 1.31081e-17, -1.11759e-08, 0, 0.0255569, -5.58266e-18, -4.58633e-16, 0.999673, 1, 1, 1, 0.35, 1, 1.99653e-17, -1.49012e-08, -5.96046e-08, 0.0290738, -6.35135e-18, -5.21745e-16, 0.999577, 1, 1, 1, 0.4, 1, 1.92772e-17, 1.11759e-08, 1.19209e-07, 0.0307265, -6.71273e-18, -5.51404e-16, 0.999528, 1, 1, 1, 0.5, 1, 4.47552e-17, 1.11759e-08, 5.96046e-08, 0.0303143, -6.6203e-18, -5.44008e-16, 0.99954, 1, 1, 1, 0.55, 1, 1.08083e-17, 2.23517e-08, -5.96046e-08, 0.0292103, -6.38065e-18, -5.24195e-16, 0.999573, 1, 1, 1, 0.6, 1, -3.34373e-18, -1.11759e-08, -2.98023e-07, 0.0276344, -6.03606e-18, -4.95914e-16, 0.999618, 1, 1, 1, 1.15, 1, 9.18674e-18, 1.49012e-08, -1.19209e-07, 0.0010327, -2.26125e-19, -1.85323e-17, 0.999999, 1, 1, 1, 1.2, 1, -3.7641e-18, 0, 0, 0.000274137, -6.02241e-20, -4.91966e-18, 1, 1, 1, 1, 1.25, 1, 7.24539e-18, 1.86265e-08, 5.96046e-08, 0, 0, 1.31315e-23, 1, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="24"> 0, 1, -1.13687e-13, -1.49012e-08, -3.57628e-07, 1.17383e-27, 2.13163e-14, 5.50671e-14, 1, 1, 1, 1, 1.25, 1, -1.13687e-13, -1.49012e-08, -3.57628e-07, -2.46125e-27, 2.13163e-14, -1.77636e-15, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="180"> 0, 1, -2.16716e-13, 2.38419e-07, -1.20141e-07, 0.00540576, -3.97061e-09, 4.73012e-08, 0.999985, 1, 1, 1, 0.05, 1, 1.42109e-14, -6.85453e-07, -5.96046e-08, 0.00687155, -3.90174e-09, 4.73059e-08, 0.999976, 1, 1, 1, 0.1, 1, -1.06581e-13, -3.57628e-07, 4.65661e-09, 0.0108835, -3.7136e-09, 4.73184e-08, 0.999941, 1, 1, 1, 0.15, 1, 2.4869e-14, -7.15256e-07, -2.79397e-09, 0.0171898, -3.41769e-09, 4.73365e-08, 0.999852, 1, 1, 1, 0.35, 1, 5.68434e-14, -4.76837e-07, -2.16532e-08, 0.0482761, -1.95634e-09, 4.7399e-08, 0.998834, 1, 1, 1, 0.4, 1, 1.3145e-13, -4.76837e-07, 1.39698e-08, 0.0525864, -1.75345e-09, 4.74044e-08, 0.998616, 1, 1, 1, 0.45, 1, -7.10543e-15, -2.98023e-07, -2.23517e-08, 0.0549628, -1.64161e-09, 4.74072e-08, 0.998488, 1, 1, 1, 0.5, 1, 8.88178e-14, -4.47035e-07, -5.75092e-08, 0.056151, -1.58539e-09, 4.74086e-08, 0.998422, 1, 1, 1, 0.55, 1, -1.06581e-14, -7.15256e-07, -1.09896e-07, 0.0561279, -1.58659e-09, 4.74089e-08, 0.998424, 1, 1, 1, 0.6, 1, 1.49214e-13, -5.36442e-07, 8.3819e-09, 0.0550227, -1.63855e-09, 4.74081e-08, 0.998485, 1, 1, 1, 0.65, 1, 1.42109e-13, -5.66244e-07, -2.72412e-08, 0.0528693, -1.73995e-09, 4.74061e-08, 0.998601, 1, 1, 1, 0.7, 1, 1.27898e-13, -9.83477e-07, 2.23517e-08, 0.0497256, -1.88791e-09, 4.74026e-08, 0.998763, 1, 1, 1, 1.15, 1, 4.61853e-14, -2.68221e-07, -1.44821e-07, 0.00768525, -3.86364e-09, 4.73087e-08, 0.99997, 1, 1, 1, 1.2, 1, -4.61853e-14, -2.38419e-07, -9.12696e-08, 0.00601107, -3.94226e-09, 4.73032e-08, 0.999982, 1, 1, 1, 1.25, 1, -2.16716e-13, 2.38419e-07, -1.20141e-07, 0.00540581, -3.97061e-09, 4.73011e-08, 0.999985, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="156"> 0, 1, -1.11494e-13, -1.15717e-07, -2.08616e-07, 7.45058e-09, 8.88178e-15, 0, 1, 1, 1, 1, 0.05, 1, 1.80868e-10, 1.36495e-05, 0.000901487, 1.49012e-08, 1.77636e-14, -2.13163e-14, 1, 1, 1, 1, 0.1, 1, 6.8149e-10, 5.12244e-05, 0.00339634, 7.45058e-09, 1.77636e-15, -2.13163e-14, 1, 1, 1, 1, 0.15, 1, 1.5005e-09, 0.00011289, 0.00747763, 7.45058e-09, 7.10543e-15, -7.10543e-15, 1, 1, 1, 1, 0.2, 1, 2.6273e-09, 0.000197746, 0.0130927, 7.45058e-09, -5.32907e-15, 7.10543e-15, 1, 1, 1, 1, 0.75, 1, 2.00072e-08, 0.00150619, 0.0996987, 7.45058e-09, 3.55271e-15, -1.42109e-14, 1, 1, 1, 1, 0.8, 1, 2.03706e-08, 0.00153358, 0.10151, 1.49012e-08, 3.55271e-15, -1.42109e-14, 1, 1, 1, 1, 0.85, 1, 2.02794e-08, 0.00152671, 0.101055, 1.49012e-08, -5.32907e-15, 7.10543e-15, 1, 1, 1, 1, 0.9, 1, 1.91881e-08, 0.00144463, 0.0956172, 7.45058e-09, -7.10543e-15, 0, 1, 1, 1, 1, 0.95, 1, 1.68664e-08, 0.00126975, 0.084048, 1.49012e-08, 1.77636e-15, -2.13163e-14, 1, 1, 1, 1, 1.15, 1, 2.70661e-09, 0.000203704, 0.0134885, 7.45058e-09, -5.32907e-15, 7.10543e-15, 1, 1, 1, 1, 1.2, 1, 7.26606e-10, 5.46668e-05, 0.00362133, 7.45058e-09, 2.13163e-14, -1.42109e-14, 1, 1, 1, 1, 1.25, 1, -1.10217e-13, -1.15717e-07, -2.02097e-07, 7.45058e-09, -5.32907e-15, 7.10543e-15, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="24"> 0, 1, 4.48581e-08, 0.00292328, 0.204329, 1.04774e-09, -4.44089e-15, 5.58928e-15, 1, 1, 1, 1, 1.25, 1, 4.48581e-08, 0.00292328, 0.204329, 1.74623e-09, -6.21725e-15, 3.40058e-14, 1, 1, 1, 1 </real_array>
-
- </resource>
- <resource type="Animation" path="local://8">
- <string name="resource/name"> "shooting" </string>
- <real name="length"> 0.416667 </real>
- <bool name="loop"> False </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="108"> 0, 1, 2.98023e-07, 3.57628e-07, 2.38419e-07, 0.177354, -0.316176, -0.0334956, 0.931373, 1, 1, 1, 0.05, 1, 5.36442e-07, -1.19209e-07, 5.06639e-07, 0.188185, -0.332103, -0.0311768, 0.923754, 1, 1, 1, 0.1, 1, 7.15256e-07, -3.57628e-07, 5.66244e-07, 0.204001, -0.354515, -0.0276657, 0.912106, 1, 1, 1, 0.15, 1, 6.25849e-07, -1.19209e-07, 4.76837e-07, 0.207621, -0.359465, -0.0268362, 0.909372, 1, 1, 1, 0.2, 1, 4.47035e-07, -1.19209e-07, 4.76837e-07, 0.203765, -0.354216, -0.0277227, 0.912273, 1, 1, 1, 0.35, 1, 6.85453e-07, -3.57628e-07, 5.36442e-07, 0.181322, -0.322103, -0.0326568, 0.928604, 1, 1, 1, 0.4, 1, 5.36442e-07, -1.19209e-07, 4.76837e-07, 0.177926, -0.317037, -0.0333752, 0.930976, 1, 1, 1, 0.45, 1, 2.98023e-07, 3.57628e-07, 2.38419e-07, 0.177354, -0.316176, -0.0334956, 0.931373, 1, 1, 1, 1.25, 1, 2.98023e-07, 3.57628e-07, 2.38419e-07, 0.177354, -0.316176, -0.0334956, 0.931373, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="108"> 0, 1, -4.47035e-07, -2.98023e-07, 0, 0.00444313, -0.215306, 0.0125622, 0.976456, 1, 1, 1, 0.05, 1, -2.08616e-07, -4.17233e-07, -2.98023e-07, 0.00305205, -0.21031, 0.0121764, 0.977554, 1, 1, 1, 0.1, 1, 2.08616e-07, -3.57628e-07, -3.57628e-07, 0.000634907, -0.201765, 0.0115128, 0.979366, 1, 0.999999, 1, 0.15, 1, 1.19209e-07, -1.19209e-07, -4.17233e-07, 2.2336e-05, -0.199561, 0.0113313, 0.97982, 1, 1, 1, 0.2, 1, 2.98023e-07, -8.9407e-08, -4.17233e-07, 0.000688273, -0.201948, 0.0115275, 0.979328, 1, 1, 1, 0.3, 1, -1.78814e-07, -2.68221e-07, -5.96046e-08, 0.00309916, -0.210458, 0.0121876, 0.977522, 1, 1, 1, 0.35, 1, 2.98023e-07, -5.96046e-07, -4.17233e-07, 0.00397812, -0.213611, 0.0124303, 0.976832, 1, 1, 1, 0.4, 1, -2.68221e-07, -4.47035e-07, -1.78814e-07, 0.00437828, -0.215068, 0.0125436, 0.976509, 1, 1, 1, 1.25, 1, -4.47035e-07, -2.98023e-07, 0, 0.00444313, -0.215306, 0.0125622, 0.976456, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="108"> 0, 1, -5.66244e-07, 0, 2.68221e-07, -0.666114, -0.365882, 0.129948, 0.636817, 1, 1, 1, 0.05, 1, -5.96046e-07, -4.76837e-07, 4.76837e-07, -0.656623, -0.392941, 0.132853, 0.629916, 1, 1, 0.999999, 0.1, 1, -1.04308e-06, -5.96046e-07, 7.45058e-07, -0.641339, -0.431274, 0.137762, 0.619442, 1, 1, 1, 0.15, 1, -1.04308e-06, -7.15256e-07, 8.9407e-07, -0.637616, -0.439805, 0.139013, 0.617003, 1, 1, 0.999999, 0.2, 1, 2.98023e-08, 0, 3.27826e-07, -0.641587, -0.430741, 0.137654, 0.61958, 1, 1, 0.999999, 0.35, 1, -2.38419e-07, -3.57628e-07, 1.49012e-07, -0.662747, -0.375915, 0.130927, 0.634281, 1, 1, 0.999999, 0.4, 1, -5.66244e-07, -1.19209e-07, 3.57628e-07, -0.665636, -0.367338, 0.130084, 0.636451, 1, 1, 1, 0.45, 1, -5.66244e-07, 0, 2.68221e-07, -0.666114, -0.365882, 0.129948, 0.636817, 1, 1, 1, 1.25, 1, -5.66244e-07, 0, 2.68221e-07, -0.666114, -0.365882, 0.129948, 0.636817, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="108"> 0, 1, 2.98023e-08, -5.96046e-07, -4.17233e-07, -0.130784, -0.271804, -0.0853016, 0.949601, 1.3, 1.3, 1.3, 0.05, 1, 1.49012e-07, -6.55651e-07, -5.96046e-07, -0.133062, -0.270527, -0.0774246, 0.950324, 1.3, 1.3, 1.3, 0.1, 1, 2.68221e-07, -5.96046e-07, -2.38419e-07, -0.136329, -0.26867, -0.0661281, 0.95124, 1.3, 1.3, 1.3, 0.15, 1, -8.9407e-08, -8.04663e-07, -7.15256e-07, -0.137063, -0.26825, -0.0635932, 0.951426, 1.3, 1.3, 1.3, 0.2, 1, -8.9407e-08, -6.85453e-07, -7.15256e-07, -0.136283, -0.268695, -0.0662837, 0.951229, 1.3, 1.3, 1.3, 0.35, 1, -1.78814e-07, -5.66244e-07, -4.76837e-07, -0.131626, -0.271333, -0.0823877, 0.949876, 1.3, 1.3, 1.3, 0.4, 1, 5.96046e-08, -5.96046e-07, -3.57628e-07, -0.130906, -0.271736, -0.0848797, 0.949641, 1.3, 1.3, 1.3, 0.45, 1, 2.98023e-08, -5.96046e-07, -4.17233e-07, -0.130784, -0.271804, -0.0853016, 0.949601, 1.3, 1.3, 1.3, 1.25, 1, 2.98023e-08, -5.96046e-07, -4.17233e-07, -0.130784, -0.271804, -0.0853016, 0.949601, 1.3, 1.3, 1.3 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="24"> 0, 1, 0, 1.63913e-07, 1.93715e-07, -0.283345, 0.0300071, -0.0426225, 0.957601, 1, 1, 1, 1.25, 1, 0, 1.63913e-07, 1.93715e-07, -0.283345, 0.0300071, -0.0426225, 0.957601, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="24"> 0, 1, 2.29338e-08, 8.9407e-08, 5.36442e-07, -0.369097, -0.0505305, 0.00260278, 0.928013, 1, 1, 1, 1.25, 1, 2.29338e-08, 8.9407e-08, 5.36442e-07, -0.369097, -0.0505305, 0.00260278, 0.928013, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="24"> 0, 1, 1.49012e-08, 0, -5.21541e-08, 0.163945, 0.140221, -0.046324, 0.975354, 1, 1, 1, 1.25, 1, 1.49012e-08, 0, -5.21541e-08, 0.163945, 0.140221, -0.046324, 0.975354, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="24"> 0, 1, 0, 2.08616e-07, 1.49012e-08, 0.284249, 0.0874448, 0.000525696, 0.954754, 1, 1, 1, 1.25, 1, 0, 2.08616e-07, 1.49012e-08, 0.284249, 0.0874448, 0.000525696, 0.954754, 1, 1, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="24"> 0, 1, -6.98492e-10, -2.98023e-08, 4.76837e-07, -0.32359, -0.0556479, 0.000232734, 0.94456, 1, 1, 1, 1.25, 1, -6.98492e-10, -2.98023e-08, 4.76837e-07, -0.32359, -0.0556479, 0.000232734, 0.94456, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="24"> 0, 1, 2.23517e-08, 1.19209e-07, 7.45058e-09, -0.260411, 0.0677016, 0.0123204, 0.963042, 1, 1, 1, 1.25, 1, 2.23517e-08, 1.19209e-07, 7.45058e-09, -0.260411, 0.0677016, 0.0123204, 0.963042, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="24"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="24"> 0, 1, -5.68434e-14, 0, 0.994808, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -5.68434e-14, 0, 0.994808, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="24"> 0, 1, -0.142338, -0.593751, 0.041427, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.142338, -0.593751, 0.041427, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="24"> 0, 1, 0.133965, 1.12742, 1.35169, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.133965, 1.12742, 1.35169, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="24"> 0, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="24"> 0, 1, -0.0204011, -0.122407, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.0204011, -0.122407, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="24"> 0, 1, -0.868295, 0.288818, -0.834593, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.868295, 0.288818, -0.834593, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="24"> 0, 1, 1.73339, 0.895247, 5.13844, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 1.73339, 0.895247, 5.13844, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="24"> 0, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="24"> 0, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="24"> 0, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 1.25, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="24"> 0, 1, 7.45059e-09, -5.21541e-08, 2.38419e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1, 1.25, 1, 7.45059e-09, -5.21541e-08, 2.38419e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="108"> 0, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, 4.95597e-09, 0.00666624, -0.163159, 0.986577, 1, 1, 1, 0.05, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, -0.00988221, 0.00482982, -0.145309, 0.989325, 1, 1, 1, 0.1, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, -0.0244913, 0.00210965, -0.118794, 0.992615, 1, 1, 1, 0.15, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, -0.0278586, 0.00148179, -0.112662, 0.993242, 1, 1, 1, 0.2, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, -0.0242687, 0.00215113, -0.1192, 0.992571, 1, 1, 1, 0.35, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, -0.00360581, 0.00599648, -0.156654, 0.987629, 1, 1, 1, 0.4, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, -0.000519651, 0.00656974, -0.162222, 0.986732, 1, 1, 1, 0.45, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, 4.95597e-09, 0.00666624, -0.163159, 0.986577, 1, 1, 1, 1.25, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, 4.95597e-09, 0.00666624, -0.163159, 0.986577, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="24"> 0, 1, -2.91038e-08, -1.78814e-07, -9.53674e-07, -7.45058e-09, 2.57076e-09, -2.87348e-09, 1, 1, 1, 1, 1.25, 1, -2.91038e-08, -1.78814e-07, -9.53674e-07, -7.45058e-09, 2.57076e-09, -2.87348e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="108"> 0, 1, 1.05648e-08, -8.34465e-07, 8.61473e-09, 0.067043, -0.15676, 0.0458898, 0.984289, 1, 1, 1, 0.05, 1, -2.68221e-08, -7.7486e-07, -7.12462e-08, 0.0563978, -0.14039, 0.0396845, 0.987692, 1, 1, 1, 0.1, 1, 2.66356e-08, -1.78814e-07, -1.87429e-07, 0.0407343, -0.116242, 0.0305639, 0.991915, 1, 1, 1, 0.15, 1, -1.30386e-08, -3.57628e-07, -7.72998e-08, 0.0371396, -0.110688, 0.0284725, 0.992753, 1, 1, 1, 0.2, 1, 2.57045e-08, -5.96046e-07, -9.05711e-08, 0.0409678, -0.116604, 0.0306994, 0.991858, 1, 1, 1, 0.35, 1, 4.0076e-08, -1.78814e-07, -5.26197e-08, 0.0631478, -0.150775, 0.0436179, 0.985584, 1, 1, 1, 0.4, 1, 3.32831e-08, -5.36442e-07, 3.95812e-09, 0.0664811, -0.155897, 0.045562, 0.98448, 1, 1, 1, 0.45, 1, 1.05648e-08, -8.34465e-07, 8.61473e-09, 0.067043, -0.15676, 0.0458898, 0.984289, 1, 1, 1, 1.25, 1, 1.05648e-08, -8.34465e-07, 8.61473e-09, 0.067043, -0.15676, 0.0458898, 0.984289, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="24"> 0, 1, -7.38021e-13, 4.70318e-08, 9.16189e-08, -1.036e-25, -3.37508e-14, -8.17124e-13, 1, 1, 1, 1, 1.25, 1, -7.38021e-13, 4.70318e-08, 9.16189e-08, -1.036e-25, -3.37508e-14, -8.17124e-13, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="24"> 0, 1, 4.48982e-08, 0.00292331, 0.204329, 8.84756e-09, -3.8014e-13, 5.94471e-12, 1, 1, 1, 1, 1.25, 1, 4.48982e-08, 0.00292331, 0.204329, 8.84756e-09, -3.8014e-13, 5.94471e-12, 1, 1, 1, 1 </real_array>
-
- </resource>
- <resource type="Animation" path="local://9">
- <string name="resource/name"> "jump-up-cycle" </string>
- <real name="length"> 0.416667 </real>
- <bool name="loop"> True </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="120"> 0, 1, 6.55651e-07, -3.57628e-07, 5.66244e-07, 0.208387, -0.176945, -0.0164982, 0.961766, 1, 1, 1, 0.05, 1, 6.85453e-07, -2.38419e-07, 4.17233e-07, 0.211256, -0.175803, -0.0179009, 0.961324, 1, 1, 1, 0.1, 1, 6.55651e-07, -2.38419e-07, 3.27826e-07, 0.216682, -0.174684, -0.0207438, 0.960263, 1, 1, 1, 0.15, 1, 6.25849e-07, -3.57628e-07, 6.25849e-07, 0.219812, -0.176984, -0.0232576, 0.959072, 1, 1, 1, 0.25, 1, 1.3113e-06, -9.53674e-07, 9.23872e-07, 0.223631, -0.219998, -0.0262768, 0.949157, 1, 1, 1, 0.3, 1, 8.9407e-07, -4.76837e-07, 6.85453e-07, 0.220416, -0.21329, -0.0232336, 0.951517, 1, 1, 1, 0.35, 1, 8.34465e-07, -3.57628e-07, 6.25849e-07, 0.214429, -0.195082, -0.0193009, 0.956865, 1, 1, 1, 0.4, 1, 8.34465e-07, -3.57628e-07, 6.25849e-07, 0.209436, -0.180062, -0.0169379, 0.960951, 1, 1, 1, 0.45, 1, 6.55651e-07, -3.57628e-07, 5.66244e-07, 0.208387, -0.176945, -0.0164982, 0.961766, 1, 1, 1, 1.25, 1, 6.55651e-07, -3.57628e-07, 5.66244e-07, 0.208387, -0.176945, -0.0164982, 0.961766, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="108"> 0, 1, 5.06639e-07, -8.64267e-07, -8.9407e-07, -0.0797867, 0.0313898, -0.00372185, 0.996311, 1, 1, 1, 0.05, 1, -5.96046e-08, -4.76837e-07, -3.57628e-07, -0.0735466, 0.0175489, -0.00298843, 0.997133, 1, 1, 1, 0.2, 1, 2.98023e-07, -9.83477e-07, -5.36442e-07, -0.0401349, -0.0767179, 0.000985969, 0.996244, 1, 1, 1, 0.25, 1, -2.98023e-08, -6.25849e-07, -4.17233e-07, -0.0324823, -0.0976145, 0.00230383, 0.994691, 1, 1, 1, 0.3, 1, 2.08616e-07, -9.53674e-07, -6.55651e-07, -0.0445163, -0.0629722, 0.000635031, 0.997022, 1, 0.999999, 1, 0.35, 1, -1.49012e-07, -8.34465e-07, -4.17233e-07, -0.0633553, -0.0111982, -0.0018671, 0.997926, 1, 1, 1, 0.4, 1, 2.38419e-07, -8.64267e-07, -7.7486e-07, -0.0770585, 0.0244395, -0.00342743, 0.996721, 1, 1, 1, 0.45, 1, 5.06639e-07, -8.64267e-07, -8.9407e-07, -0.0797867, 0.0313898, -0.00372185, 0.996311, 1, 1, 1, 1.25, 1, 5.06639e-07, -8.64267e-07, -8.9407e-07, -0.0797867, 0.0313898, -0.00372185, 0.996311, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="132"> 0, 1, -1.19209e-07, -5.96046e-07, 5.36442e-07, -0.488489, -0.631801, -0.249807, 0.547542, 1, 1, 1, 0.05, 1, -1.49012e-07, -7.15256e-07, 5.96046e-07, -0.474017, -0.625071, -0.244485, 0.569931, 1, 1, 0.999999, 0.1, 1, -5.96046e-07, -3.57628e-07, 6.25849e-07, -0.454842, -0.607865, -0.232791, 0.607805, 1, 1, 0.999999, 0.15, 1, -6.25849e-07, -4.76837e-07, 6.85453e-07, -0.465321, -0.582319, -0.222366, 0.628437, 1, 1, 1, 0.2, 1, -3.8743e-07, -5.96046e-07, 6.25849e-07, -0.510621, -0.547625, -0.217789, 0.626052, 1, 1, 1, 0.25, 1, -5.96046e-07, -7.15256e-07, 2.98023e-07, -0.546434, -0.526096, -0.217482, 0.614275, 1, 1, 1, 0.3, 1, -3.57628e-07, -5.96046e-07, 6.85453e-07, -0.543207, -0.547611, -0.225218, 0.595252, 1, 1, 0.999999, 0.35, 1, -5.06639e-07, -5.96046e-07, 7.7486e-07, -0.516521, -0.594071, -0.238908, 0.568514, 1, 1, 1, 0.4, 1, -3.27826e-07, -5.96046e-07, 7.15256e-07, -0.493183, -0.625944, -0.248106, 0.550825, 1, 1, 1, 0.45, 1, -1.19209e-07, -5.96046e-07, 5.36442e-07, -0.488489, -0.631801, -0.249807, 0.547542, 1, 1, 1, 1.25, 1, -1.19209e-07, -5.96046e-07, 5.36442e-07, -0.488489, -0.631801, -0.249807, 0.547542, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="132"> 0, 1, -8.9407e-08, -5.96046e-07, -2.38419e-07, 0.170167, 0.120493, -0.091473, 0.973734, 1, 1, 1, 0.05, 1, -5.96046e-08, -5.36442e-07, -2.98023e-07, 0.191507, 0.15179, -0.0881411, 0.965669, 1, 1, 1, 0.1, 1, -2.98023e-08, -5.06639e-07, -1.19209e-07, 0.225056, 0.198248, -0.0838434, 0.950273, 1, 1, 1, 0.15, 1, -1.78814e-07, -6.85453e-07, -2.38419e-07, 0.242609, 0.209269, -0.0881917, 0.94317, 1, 1, 1, 0.2, 1, -3.27826e-07, -5.36442e-07, -1.19209e-07, 0.246276, 0.185328, -0.105902, 0.945403, 1, 1, 1, 0.25, 1, -4.76837e-07, -5.06639e-07, -7.7486e-07, 0.240434, 0.157542, -0.120519, 0.950183, 1, 1, 1, 0.3, 1, -8.9407e-08, -6.85453e-07, -2.98023e-07, 0.22081, 0.140399, -0.117544, 0.957974, 1, 0.999999, 1, 0.35, 1, -1.19209e-07, -7.7486e-07, -2.98023e-07, 0.191979, 0.127301, -0.104336, 0.967498, 1, 1, 1, 0.4, 1, -8.9407e-08, -6.55651e-07, -2.98023e-07, 0.173508, 0.121415, -0.0935976, 0.972827, 1, 1, 1, 0.45, 1, -8.9407e-08, -5.96046e-07, -2.38419e-07, 0.170167, 0.120493, -0.091473, 0.973734, 1, 1, 1, 1.25, 1, -8.9407e-08, -5.96046e-07, -2.38419e-07, 0.170167, 0.120493, -0.091473, 0.973734, 1, 1, 1 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="120"> 0, 1, 0, 1.63913e-07, 1.93715e-07, -0.731646, -0.0455606, -0.00930311, 0.680097, 1, 1, 1, 0.05, 1, -8.9407e-08, 5.96046e-08, -3.57628e-07, -0.699019, -0.0340935, -0.0129449, 0.714172, 1, 1, 1, 0.1, 1, -8.9407e-08, 1.41561e-07, -2.83122e-07, -0.643626, -0.015991, -0.0189581, 0.764938, 1, 1, 1, 0.15, 1, -8.9407e-08, 3.72529e-08, -5.06639e-07, -0.617849, -0.00879986, -0.0226563, 0.785921, 1, 1, 1, 0.2, 1, -5.96046e-08, 9.68575e-08, 7.45058e-08, -0.628974, -0.00984708, -0.0265256, 0.776912, 1, 1, 1, 0.25, 1, -5.96046e-08, 9.68575e-08, -4.47035e-07, -0.653197, -0.0153019, -0.02661, 0.756565, 1, 1, 1, 0.35, 1, -2.98023e-08, 2.98023e-08, 2.98023e-07, -0.712225, -0.0376632, -0.0133416, 0.700813, 1, 1, 1, 0.4, 1, -2.98023e-08, 1.04308e-07, 1.63913e-07, -0.728798, -0.0444052, -0.00986262, 0.683216, 1, 1, 1, 0.45, 1, 0, 1.63913e-07, 1.93715e-07, -0.731646, -0.0455606, -0.00930311, 0.680097, 1, 1, 1, 1.25, 1, 0, 1.63913e-07, 1.93715e-07, -0.731646, -0.0455606, -0.00930311, 0.680097, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="120"> 0, 1, -0.0436297, 0.0381679, -0.243318, 0.903835, 0.221183, 0.00392365, -0.366258, 1, 1, 1, 0.05, 1, -0.0436298, 0.0381678, -0.243318, 0.894017, 0.213358, 0.00409072, -0.393949, 1, 1, 1, 0.1, 1, -0.0436297, 0.0381675, -0.243318, 0.873591, 0.198684, 0.00402625, -0.444239, 1, 1, 1, 0.15, 1, -0.0436297, 0.0381679, -0.243318, 0.86099, 0.194348, 0.00472605, -0.470004, 1, 1, 1, 0.2, 1, -0.0436298, 0.038168, -0.243318, 0.866453, 0.209209, 0.00740134, -0.453251, 1, 1, 1, 0.25, 1, -0.0436297, 0.0381682, -0.243318, 0.877278, 0.223532, 0.00901692, -0.42466, 1, 1, 1, 0.35, 1, -0.0436297, 0.0381675, -0.243318, 0.89824, 0.222872, 0.00544398, -0.378765, 1, 1, 1, 0.4, 1, -0.0436297, 0.0381677, -0.243318, 0.90306, 0.22143, 0.0041485, -0.368015, 1, 1, 1, 0.45, 1, -0.0436297, 0.0381679, -0.243318, 0.903835, 0.221183, 0.00392365, -0.366258, 1, 1, 1, 1.25, 1, -0.0436297, 0.0381679, -0.243318, 0.903835, 0.221183, 0.00392365, -0.366258, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="108"> 0, 1, 7.45058e-08, 1.19209e-07, -3.72529e-09, -0.278586, 0.162913, 0.049835, 0.94518, 1, 1, 1, 0.05, 1, 5.21541e-08, -1.19209e-07, 4.47035e-08, -0.263884, 0.163221, 0.0462377, 0.949519, 1, 1, 1, 0.15, 1, 3.72529e-08, 0, 2.98023e-08, -0.191844, 0.164134, 0.02867, 0.967178, 1, 1, 1, 0.2, 1, 9.68575e-08, 0, -7.45058e-09, -0.173312, 0.164214, 0.0241673, 0.970779, 1, 1, 1, 0.25, 1, 8.9407e-08, -3.57628e-07, 2.6077e-08, -0.181008, 0.164188, 0.0260364, 0.96933, 1, 1, 1, 0.35, 1, 7.45058e-08, 3.57628e-07, 7.45058e-09, -0.253238, 0.163417, 0.0436354, 0.952503, 1, 1, 1, 0.4, 1, 8.19564e-08, 2.38419e-07, 2.6077e-08, -0.274832, 0.162996, 0.0489163, 0.946312, 1, 1, 1, 0.45, 1, 7.45058e-08, 1.19209e-07, -3.72529e-09, -0.278586, 0.162913, 0.049835, 0.94518, 1, 1, 1, 1.25, 1, 7.45058e-08, 1.19209e-07, -3.72529e-09, -0.278586, 0.162913, 0.049835, 0.94518, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="120"> 0, 1, 0, 2.08616e-07, 1.49012e-08, 0.318341, 0.0708015, -0.00441775, 0.945318, 1, 1, 1, 0.05, 1, 0, 1.93715e-07, 3.42727e-07, 0.307147, 0.068999, -0.0035256, 0.949151, 1, 1, 1, 0.1, 1, 2.98023e-08, 2.01166e-07, 4.47035e-08, 0.292292, 0.0665824, -0.00232838, 0.954006, 1, 1, 1, 0.15, 1, 5.96046e-08, 1.04308e-07, -1.93715e-07, 0.272221, 0.0650766, -0.00188312, 0.96003, 1, 1, 1, 0.2, 1, 2.98023e-08, 2.23517e-08, -1.78814e-07, 0.232486, 0.0650023, -0.00182597, 0.970424, 1, 1, 1, 0.25, 1, 5.96046e-08, -1.49012e-08, -1.04308e-07, 0.226129, 0.0676028, -0.00263455, 0.971745, 1, 1, 1, 0.35, 1, -2.98023e-08, 5.21541e-08, 1.63913e-07, 0.288667, 0.069411, -0.00418897, 0.954901, 1, 1, 1, 0.4, 1, -2.98023e-08, 1.41561e-07, 1.93715e-07, 0.312853, 0.0704368, -0.0043685, 0.947176, 1, 1, 1, 0.45, 1, 0, 2.08616e-07, 1.49012e-08, 0.318341, 0.0708015, -0.00441775, 0.945318, 1, 1, 1, 1.25, 1, 0, 2.08616e-07, 1.49012e-08, 0.318341, 0.0708015, -0.00441775, 0.945318, 1, 1, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="108"> 0, 1, 5.78584e-08, 5.96046e-08, 2.38419e-07, -0.0511448, -0.0112637, 0.00107338, 0.998627, 1, 1, 1, 0.05, 1, -2.94531e-08, -8.19564e-08, 1.78814e-07, -0.0669256, -0.012717, 0.000882011, 0.997677, 1, 1, 1, 0.1, 1, -3.07336e-08, -2.98023e-08, 3.57628e-07, -0.0875047, -0.0145704, 0.000627808, 0.996057, 1, 1, 1, 0.15, 1, 1.66474e-08, -8.9407e-08, 2.38419e-07, -0.12177, -0.0175352, 0.000386084, 0.992403, 1, 1, 1, 0.2, 1, 1.28057e-08, -1.49012e-08, 1.19209e-07, -0.196391, -0.0229446, -2.58925e-05, 0.980257, 1, 1, 1, 0.25, 1, -7.91624e-08, 8.9407e-08, 0, -0.21572, -0.0236374, -9.3472e-05, 0.976169, 1, 1, 1, 0.4, 1, 2.95695e-08, 6.70552e-08, 1.19209e-07, -0.060964, -0.012162, 0.00100229, 0.998065, 1, 1, 1, 0.45, 1, 5.78584e-08, 5.96046e-08, 2.38419e-07, -0.0511448, -0.0112637, 0.00107338, 0.998627, 1, 1, 1, 1.25, 1, 5.78584e-08, 5.96046e-08, 2.38419e-07, -0.0511448, -0.0112637, 0.00107338, 0.998627, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="108"> 0, 1, 5.21541e-08, 1.19209e-07, -1.9744e-07, -0.285587, 0.0658082, 0.0159816, 0.955957, 1, 1, 1, 0.05, 1, 7.45058e-09, 1.19209e-07, -1.08033e-07, -0.295281, 0.0650349, 0.017475, 0.953034, 1, 1, 1, 0.15, 1, -2.23517e-08, 1.19209e-07, 2.98023e-08, -0.341727, 0.0611981, 0.0246725, 0.93748, 1, 1, 1, 0.2, 1, 5.21541e-08, 1.19209e-07, -1.19209e-07, -0.353427, 0.0601963, 0.0264969, 0.933147, 1, 1, 1, 0.25, 1, -1.49012e-08, 2.38419e-07, -4.84288e-08, -0.348577, 0.0606133, 0.0257401, 0.934964, 1, 1, 1, 0.35, 1, -7.45058e-09, 1.19209e-07, -7.45058e-09, -0.302251, 0.0644732, 0.0185506, 0.950865, 1, 1, 1, 0.4, 1, 5.21541e-08, 1.19209e-07, -8.19564e-08, -0.28807, 0.065611, 0.0163638, 0.955219, 1, 1, 1, 0.45, 1, 5.21541e-08, 1.19209e-07, -1.9744e-07, -0.285587, 0.0658082, 0.0159816, 0.955957, 1, 1, 1, 1.25, 1, 5.21541e-08, 1.19209e-07, -1.9744e-07, -0.285587, 0.0658082, 0.0159816, 0.955957, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="24"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="108"> 0, 1, 1.37965e-08, 0.0913706, -0.0102687, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 1.37965e-08, 0.0913706, 0.0826712, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, 1.37965e-08, 0.0913706, 0.527418, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, 1.37965e-08, 0.0913706, 0.640416, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.25, 1, 1.37965e-08, 0.0913706, 0.59344, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, 1.37965e-08, 0.0913706, 0.149321, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.4, 1, 1.37965e-08, 0.0913706, 0.0135775, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, 1.37965e-08, 0.0913706, -0.0102687, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 1.37965e-08, 0.0913706, -0.0102687, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="108"> 0, 1, -0.142338, -0.579062, 1.09897, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.142338, -0.574357, 1.07628, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, -0.142338, -0.551601, 0.966619, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, -0.142338, -0.545802, 0.938678, 0, 0, 0, 1, 1, 1, 1, 0.25, 1, -0.142338, -0.54821, 0.950281, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, -0.142338, -0.570965, 1.05993, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, -0.142338, -0.577858, 1.09316, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.142338, -0.579062, 1.09897, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.142338, -0.579062, 1.09897, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="108"> 0, 1, 0.133965, 0.921787, 0.705414, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.133965, 0.88632, 0.724279, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, 0.133965, 0.833892, 0.752174, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, 0.133965, 0.821796, 0.758611, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, 0.133965, 0.834697, 0.751748, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, 0.133965, 0.908846, 0.712298, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, 0.133965, 0.919922, 0.706406, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, 0.133965, 0.921787, 0.705414, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.133965, 0.921787, 0.705414, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="24"> 0, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="24"> 0, 1, -0.0204011, -0.122407, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.0204011, -0.122407, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="120"> 0, 1, -0.868295, 0.267668, -0.820401, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.868295, 0.253357, -0.761204, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -0.868295, 0.216179, -0.653431, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, -0.868295, 0.157463, -0.585229, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, -0.868295, 0.102061, -0.562116, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, -0.868295, 0.10969, -0.583242, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, -0.868295, 0.226187, -0.758093, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -0.868295, 0.261497, -0.811129, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.868295, 0.267668, -0.820401, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.868295, 0.267668, -0.820401, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="108"> 0, 1, 2.08906, 2.18272, 3.23967, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 2.08906, 2.16545, 3.23967, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, 2.08906, 2.08198, 3.23967, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, 2.08906, 2.06071, 3.23967, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, 2.08906, 2.06954, 3.23967, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, 2.08906, 2.15301, 3.23967, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, 2.08906, 2.1783, 3.23967, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, 2.08906, 2.18272, 3.23967, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 2.08906, 2.18272, 3.23967, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="24"> 0, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="132"> 0, 1, -0.495073, -1.94554, 0.375148, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.529633, -1.94554, 0.375148, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -0.616933, -1.94554, 0.375148, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, -0.726325, -1.94554, 0.375148, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, -0.813485, -1.94554, 0.375148, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, -0.847955, -1.94554, 0.375148, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, -0.773744, -1.94554, 0.375148, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.35, 1, -0.620743, -1.94554, 0.375148, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -0.514687, -1.94554, 0.375148, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.495073, -1.94554, 0.375148, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.495073, -1.94554, 0.375148, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="132"> 0, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.05, 1, 0.050238, 0.727833, 0.0877454, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.1, 1, 0.050238, 0.772783, 0.0577767, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.15, 1, 0.050238, 0.78451, 0.0674334, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.2, 1, 0.050238, 0.778496, 0.13139, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.25, 1, 0.050238, 0.766398, 0.174636, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.3, 1, 0.050238, 0.744412, 0.160603, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.35, 1, 0.050238, 0.716858, 0.131686, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.4, 1, 0.050238, 0.700317, 0.111698, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.45, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 1.25, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="24"> 0, 1, 7.45059e-09, -5.21541e-08, 2.38419e-07, 0.126301, -0.0110499, -0.0864524, 0.988156, 1, 1, 1, 1.25, 1, 7.45059e-09, -5.21541e-08, 2.38419e-07, 0.126301, -0.0110499, -0.0864524, 0.988156, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="24"> 0, 1, -2.26918e-09, 5.21541e-08, -1.78814e-07, 0.0237758, -0.0135633, -0.0860939, 0.995911, 1, 1, 1, 1.25, 1, -2.26918e-09, 5.21541e-08, -1.78814e-07, 0.0237758, -0.0135633, -0.0860939, 0.995911, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="24"> 0, 1, -1.11758e-08, -2.23517e-07, -1.43051e-06, -7.45058e-09, -4.4605e-10, 4.26538e-09, 1, 1, 1, 1, 1.25, 1, -1.11758e-08, -2.23517e-07, -1.43051e-06, -7.45058e-09, -4.4605e-10, 4.26538e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="108"> 0, 1, 1.02445e-08, -4.47035e-07, -1.05007e-07, 0.287287, -0.0941088, 0.0255168, 0.952869, 1, 1, 1, 0.05, 1, -2.68222e-08, -2.98023e-08, -7.10133e-08, 0.277009, -0.0944548, 0.024506, 0.9559, 1, 1, 1, 0.15, 1, -2.42144e-08, -3.57628e-07, -3.39933e-08, 0.229614, -0.0956923, 0.0198279, 0.968363, 1, 1, 1, 0.2, 1, -1.22934e-08, -1.78814e-07, 1.30385e-08, 0.224057, -0.0957887, 0.0192787, 0.969665, 1, 1, 1, 0.25, 1, -3.91156e-08, 1.19209e-07, -4.79631e-08, 0.233664, -0.0955615, 0.0202274, 0.967399, 1, 1, 1, 0.35, 1, -3.35279e-09, -3.27826e-07, -4.61005e-08, 0.274341, -0.0944949, 0.024241, 0.956671, 1, 1, 1, 0.4, 1, -1.67641e-09, -2.68221e-07, -8.21892e-08, 0.285395, -0.0941665, 0.0253304, 0.953436, 1, 1, 1, 0.45, 1, 1.02445e-08, -4.47035e-07, -1.05007e-07, 0.287287, -0.0941088, 0.0255168, 0.952869, 1, 1, 1, 1.25, 1, 1.02445e-08, -4.47035e-07, -1.05007e-07, 0.287287, -0.0941088, 0.0255168, 0.952869, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="24"> 0, 1, -7.74519e-09, -9.56934e-08, 3.16533e-07, 7.45058e-09, 3.37575e-10, -1.99442e-09, 1, 1, 1, 1, 1.25, 1, -7.74519e-09, -9.56934e-08, 3.16533e-07, 7.45058e-09, 3.37575e-10, -1.99442e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="24"> 0, 1, 3.38022e-08, 0.00292349, 0.20433, 6.98492e-10, 2.45226e-11, 6.71222e-11, 1, 1, 1, 1, 1.25, 1, 3.38022e-08, 0.00292349, 0.20433, 6.98492e-10, 2.45226e-11, 6.71222e-11, 1, 1, 1, 1 </real_array>
-
- </resource>
- <resource type="Animation" path="local://10">
- <string name="resource/name"> "shooting_standing" </string>
- <real name="length"> 0.416667 </real>
- <bool name="loop"> False </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="132"> 0, 1, 5.96046e-07, -1.19209e-07, 4.47035e-07, -0.206314, 0.709894, -0.150643, 0.656348, 1, 1, 1, 0.05, 1, 1.07288e-06, -4.76837e-07, 8.34465e-07, -0.199825, 0.723236, -0.14911, 0.644023, 1, 1, 1, 0.1, 1, 4.47035e-07, -1.19209e-07, 3.27826e-07, -0.186028, 0.74616, -0.147051, 0.622106, 1, 1, 1, 0.15, 1, 4.47035e-07, -1.19209e-07, 1.49012e-07, -0.168011, 0.761016, -0.149525, 0.608497, 1, 1, 1, 0.2, 1, 2.38419e-07, 1.19209e-07, -1.19209e-07, -0.141127, 0.777642, -0.158168, 0.591895, 1, 1, 1, 0.25, 1, 7.15256e-07, -2.38419e-07, 2.68221e-07, -0.129783, 0.779527, -0.165304, 0.590059, 1, 1, 1, 0.3, 1, 6.25849e-07, -1.19209e-07, 2.08616e-07, -0.152097, 0.757922, -0.164122, 0.612768, 1, 1, 1, 0.35, 1, 8.9407e-07, -4.76837e-07, 8.34465e-07, -0.183836, 0.730436, -0.157254, 0.638701, 1, 1, 1, 0.4, 1, 7.45058e-07, -3.57628e-07, 5.66244e-07, -0.202964, 0.713054, -0.151716, 0.653714, 1, 1, 1, 0.45, 1, 5.96046e-07, -1.19209e-07, 4.47035e-07, -0.206314, 0.709894, -0.150643, 0.656348, 1, 1, 1, 1.25, 1, 5.96046e-07, -1.19209e-07, 4.47035e-07, -0.206314, 0.709894, -0.150643, 0.656348, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="120"> 0, 1, 0, -4.76837e-07, -7.7486e-07, 0.0490264, -0.364254, 0.0100564, 0.929954, 1, 1, 1, 0.05, 1, 1.19209e-07, -4.47035e-07, -4.76837e-07, 0.0346734, -0.325178, 0.00768963, 0.944986, 1, 1, 1, 0.1, 1, 1.19209e-07, -5.06639e-07, -3.57628e-07, 0.00822793, -0.255634, 0.00344931, 0.966732, 1, 1, 1, 0.15, 1, 2.98023e-08, -7.15256e-07, -5.96046e-07, -0.00893206, -0.219161, 0.00118009, 0.975647, 1, 1, 1, 0.2, 1, 1.49012e-07, -4.47035e-07, -5.96046e-07, -0.0220165, -0.204408, 0.000203021, 0.978638, 1, 1, 1, 0.25, 1, 4.17233e-07, -4.76837e-07, -5.36442e-07, -0.0204464, -0.223283, 0.00158917, 0.974538, 1, 1, 1, 0.35, 1, 1.19209e-07, -6.85453e-07, -2.98023e-07, 0.0295549, -0.331584, 0.00842644, 0.942925, 1, 1, 1, 0.4, 1, 0, -6.55651e-07, -6.55651e-07, 0.0460614, -0.359518, 0.00983853, 0.931949, 1, 1, 1, 0.45, 1, 0, -4.76837e-07, -7.7486e-07, 0.0490264, -0.364254, 0.0100564, 0.929954, 1, 1, 1, 1.25, 1, 0, -4.76837e-07, -7.7486e-07, 0.0490264, -0.364254, 0.0100564, 0.929954, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="132"> 0, 1, -4.17233e-07, -3.57628e-07, 4.47035e-07, -0.474516, -0.584521, 0.0340579, 0.657274, 1, 1, 1, 0.05, 1, -7.45058e-07, -3.57628e-07, 5.36442e-07, -0.46761, -0.58693, 0.0339523, 0.660076, 1, 1, 1, 0.1, 1, -4.76837e-07, -2.38419e-07, 2.98023e-07, -0.452786, -0.591715, 0.0339493, 0.666112, 1, 1, 1, 0.15, 1, -6.55651e-07, -3.57628e-07, 2.98023e-07, -0.443727, -0.588057, 0.0337848, 0.675392, 1, 1, 1, 0.2, 1, 2.98023e-08, 1.19209e-07, -3.27826e-07, -0.450408, -0.563251, 0.0324613, 0.691973, 1, 1, 1, 0.25, 1, -5.96046e-07, -3.57628e-07, 2.98023e-07, -0.461281, -0.543778, 0.0314456, 0.700383, 1, 1, 1, 0.3, 1, -4.17233e-07, 0, 1.78814e-07, -0.469244, -0.550688, 0.0318109, 0.689595, 1, 1, 1, 0.35, 1, -7.7486e-07, -2.38419e-07, 4.76837e-07, -0.473462, -0.569016, 0.0329517, 0.671542, 1, 1, 1, 0.4, 1, -6.25849e-07, -3.57628e-07, 5.96046e-07, -0.474439, -0.5821, 0.0338759, 0.659485, 1, 1, 1, 0.45, 1, -4.17233e-07, -3.57628e-07, 4.47035e-07, -0.474516, -0.584521, 0.0340579, 0.657274, 1, 1, 1, 1.25, 1, -4.17233e-07, -3.57628e-07, 4.47035e-07, -0.474516, -0.584521, 0.0340579, 0.657274, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="96"> 0, 1, 1.78814e-07, 2.98023e-08, -3.57628e-07, -0.156054, -0.257929, 9.29801e-05, 0.953478, 1.3, 1.3, 1.3, 0.05, 1, -8.9407e-08, -9.23872e-07, -2.98023e-07, -0.156186, -0.25785, 0.000491834, 0.953477, 1.3, 1.3, 1.3, 0.1, 1, 0, -5.06639e-07, -2.98023e-07, -0.156442, -0.257682, 0.00128265, 0.95348, 1.3, 1.3, 1.3, 0.15, 1, -2.08616e-07, -5.36442e-07, -5.96046e-08, -0.156528, -0.257623, 0.00155313, 0.953481, 1.3, 1.3, 1.3, 0.25, 1, 2.98023e-08, -5.36442e-07, -3.57628e-07, -0.155874, -0.258131, -0.000583909, 0.953452, 1.3, 1.3, 1.3, 0.35, 1, 2.98023e-08, -4.76837e-07, -3.57628e-07, -0.15592, -0.258051, -0.000371468, 0.953467, 1.3, 1.3, 1.3, 0.4, 1, 1.49012e-07, -2.68221e-07, -2.98023e-07, -0.156032, -0.257949, 1.56283e-05, 0.953476, 1.3, 1.3, 1.3, 1.25, 1, 1.78814e-07, 2.98023e-08, -3.57628e-07, -0.156054, -0.257929, 9.29801e-05, 0.953478, 1.3, 1.3, 1.3 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="120"> 0, 1, 5.96046e-08, 2.23517e-08, -1.3411e-07, 0.301601, -0.0701581, -0.00864293, 0.95081, 1, 1, 1, 0.05, 1, 5.96046e-08, 2.98023e-08, -1.04308e-07, 0.248345, -0.0620849, -0.00736271, 0.966652, 1, 1, 1, 0.1, 1, 8.9407e-08, 6.70552e-08, -1.04308e-07, 0.175365, -0.0511626, -0.00552639, 0.983158, 1, 1, 1, 0.15, 1, 8.9407e-08, 4.47035e-08, -1.04308e-07, 0.153891, -0.0497144, -0.00660778, 0.986814, 1, 1, 1, 0.2, 1, 5.96046e-08, -2.98023e-08, -1.49012e-08, 0.151238, -0.0561188, -0.0117034, 0.986834, 1, 1, 1, 0.25, 1, 2.98023e-08, -1.49012e-08, -1.04308e-07, 0.168743, -0.0655087, -0.0152581, 0.983362, 1, 1, 1, 0.35, 1, 2.98023e-08, 2.23517e-08, -1.63913e-07, 0.26593, -0.072486, -0.0117415, 0.961192, 1, 1, 1, 0.4, 1, 5.96046e-08, 7.45058e-09, -1.78814e-07, 0.296131, -0.070636, -0.00916634, 0.952488, 1, 1, 1, 0.45, 1, 5.96046e-08, 2.23517e-08, -1.3411e-07, 0.301601, -0.0701581, -0.00864293, 0.95081, 1, 1, 1, 1.25, 1, 5.96046e-08, 2.23517e-08, -1.3411e-07, 0.301601, -0.0701581, -0.00864293, 0.95081, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="120"> 0, 1, -4.31901e-08, -7.45058e-08, 7.7486e-07, -0.33852, 0.053398, -0.0152903, 0.939319, 1, 1, 1, 0.05, 1, 5.6345e-08, -2.23517e-08, 6.55651e-07, -0.403989, 0.0628472, -0.0146608, 0.912484, 1, 1, 1, 0.1, 1, 5.02914e-08, -1.49012e-08, 5.36442e-07, -0.486228, 0.0751824, -0.0137902, 0.870483, 1, 1, 1, 0.15, 1, 1.11642e-07, 5.96046e-08, 5.96046e-07, -0.506485, 0.0840018, -0.0142775, 0.858028, 1, 1, 1, 0.2, 1, 1.23633e-07, 8.19564e-08, 5.36442e-07, -0.500531, 0.103313, -0.0168649, 0.859367, 1, 1, 1, 0.25, 1, 9.58098e-08, 1.49012e-08, 6.55651e-07, -0.475505, 0.111896, -0.0189746, 0.872361, 1, 1, 1, 0.35, 1, 7.84639e-08, 9.68575e-08, 5.96046e-07, -0.376662, 0.0699087, -0.0169347, 0.923554, 1, 1, 1, 0.4, 1, -1.16415e-09, -7.45058e-09, 7.15256e-07, -0.344524, 0.0558207, -0.0155573, 0.936987, 1, 1, 1, 0.45, 1, -4.31901e-08, -7.45058e-08, 7.7486e-07, -0.33852, 0.053398, -0.0152903, 0.939319, 1, 1, 1, 1.25, 1, -4.31901e-08, -7.45058e-08, 7.7486e-07, -0.33852, 0.053398, -0.0152903, 0.939319, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="108"> 0, 1, 1.19209e-07, 0, 1.82539e-07, -0.218034, -0.0651501, 0.015764, 0.973637, 1, 1, 1, 0.05, 1, 5.21541e-08, 0, -9.31323e-08, -0.206333, -0.0662009, 0.0171463, 0.976089, 1, 1, 1, 0.1, 1, 2.98023e-08, -1.19209e-07, -7.45058e-08, -0.188973, -0.0677374, 0.0191861, 0.979455, 1, 1, 1, 0.15, 1, 0, 0, -4.84288e-08, -0.184958, -0.0680889, 0.0196559, 0.980188, 1, 1, 1, 0.2, 1, 5.96046e-08, 0, -1.19209e-07, -0.189238, -0.0677142, 0.019155, 0.979406, 1, 1, 1, 0.35, 1, 8.19564e-08, 1.19209e-07, 3.72529e-08, -0.213767, -0.0655347, 0.0162687, 0.974548, 1, 1, 1, 0.4, 1, 1.04308e-07, 0, 5.21541e-08, -0.217419, -0.0652056, 0.0158368, 0.973769, 1, 1, 1, 0.45, 1, 1.19209e-07, 0, 1.82539e-07, -0.218034, -0.0651501, 0.015764, 0.973637, 1, 1, 1, 1.25, 1, 1.19209e-07, 0, 1.82539e-07, -0.218034, -0.0651501, 0.015764, 0.973637, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="132"> 0, 1, -5.96046e-08, -1.2666e-07, 1.04308e-07, -0.633392, 0.109953, 0.00349885, 0.765972, 1, 1, 1, 0.05, 1, 0, -4.47035e-08, 1.3411e-07, -0.628866, 0.106487, 0.00414994, 0.770176, 1, 1, 1, 0.1, 1, -2.98023e-08, 4.47035e-08, 1.49012e-07, -0.619935, 0.101098, 0.00522767, 0.778095, 1, 1, 1, 0.15, 1, -2.98023e-08, 5.96046e-08, 1.49012e-07, -0.616185, 0.108634, 0.00550208, 0.780054, 1, 1, 1, 0.2, 1, 5.96046e-08, 4.47035e-08, 2.5332e-07, -0.613177, 0.141231, 0.00523592, 0.7772, 1, 1, 1, 0.25, 1, 0, 0, 1.49012e-07, -0.612177, 0.164991, 0.00476259, 0.773301, 1, 1, 1, 0.3, 1, 5.96046e-08, -7.45058e-09, 1.3411e-07, -0.619021, 0.155086, 0.00421746, 0.769898, 1, 1, 1, 0.35, 1, 2.98023e-08, 7.45058e-09, 7.45058e-08, -0.627679, 0.130628, 0.00377015, 0.767425, 1, 1, 1, 0.4, 1, -2.98023e-08, -1.3411e-07, 7.45058e-08, -0.632568, 0.11319, 0.0035387, 0.766181, 1, 1, 1, 0.45, 1, -5.96046e-08, -1.2666e-07, 1.04308e-07, -0.633392, 0.109953, 0.00349885, 0.765972, 1, 1, 1, 1.25, 1, -5.96046e-08, -1.2666e-07, 1.04308e-07, -0.633392, 0.109953, 0.00349885, 0.765972, 1, 1, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="120"> 0, 1, -4.07454e-08, -1.11759e-07, 0, -0.55604, 0.155102, 0.00378888, 0.816547, 1, 1, 1, 0.05, 1, 7.60192e-08, -8.9407e-08, 1.19209e-07, -0.534898, 0.148998, 0.00358481, 0.831668, 1, 1, 1, 0.1, 1, -1.0326e-07, -1.49012e-08, 2.38419e-07, -0.500235, 0.139173, 0.00323174, 0.854626, 1, 1, 1, 0.15, 1, 6.41448e-08, 4.47035e-08, 1.78814e-07, -0.492131, 0.143377, 0.00332103, 0.858626, 1, 1, 1, 0.25, 1, -6.58911e-08, -8.19564e-08, 1.78814e-07, -0.517192, 0.191548, 0.00473312, 0.834146, 1, 1, 1, 0.3, 1, 3.0268e-08, 1.49012e-08, 1.19209e-07, -0.534465, 0.187415, 0.00465677, 0.824136, 1, 1, 1, 0.35, 1, 3.11993e-08, -5.21541e-08, 2.38419e-07, -0.548296, 0.170437, 0.0042049, 0.818722, 1, 1, 1, 0.4, 1, 2.51457e-08, -9.68575e-08, 1.19209e-07, -0.554953, 0.157536, 0.00385503, 0.81682, 1, 1, 1, 0.45, 1, -4.07454e-08, -1.11759e-07, 0, -0.55604, 0.155102, 0.00378888, 0.816547, 1, 1, 1, 1.25, 1, -4.07454e-08, -1.11759e-07, 0, -0.55604, 0.155102, 0.00378888, 0.816547, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="108"> 0, 1, 7.45058e-08, 1.19209e-07, 3.72529e-09, -0.143967, -0.0951747, 0.00523759, 0.984981, 1, 1, 1, 0.05, 1, 7.45058e-09, 2.38419e-07, 3.35276e-08, -0.157581, -0.0952617, 0.00367365, 0.982894, 1, 1, 1, 0.1, 1, -2.23517e-08, 1.19209e-07, -1.11759e-08, -0.17766, -0.0953568, 0.00135921, 0.97946, 1, 1, 1, 0.15, 1, -3.72529e-08, 1.19209e-07, 4.84288e-08, -0.182282, -0.0953731, 0.000825106, 0.97861, 1, 1, 1, 0.2, 1, 1.49012e-08, 1.19209e-07, -5.21541e-08, -0.177354, -0.0953557, 0.00139453, 0.979516, 1, 1, 1, 0.35, 1, 4.47035e-08, 0, 5.96046e-08, -0.148938, -0.0952085, 0.00466699, 0.984241, 1, 1, 1, 0.4, 1, 5.21541e-08, 1.19209e-07, -4.09782e-08, -0.144684, -0.0951797, 0.00515536, 0.984876, 1, 1, 1, 0.45, 1, 7.45058e-08, 1.19209e-07, 3.72529e-09, -0.143967, -0.0951747, 0.00523759, 0.984981, 1, 1, 1, 1.25, 1, 7.45058e-08, 1.19209e-07, 3.72529e-09, -0.143967, -0.0951747, 0.00523759, 0.984981, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="24"> 0, 1, 0, 1.36988, -1.03377e-07, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0, 1.36988, -1.03377e-07, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="108"> 0, 1, 8.64522e-08, 0.572547, -4.76837e-07, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 8.64522e-08, 0.572548, 0.471507, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, 8.64522e-08, 0.572548, 1.12029, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.15, 1, 8.64522e-08, 0.572548, 1.26782, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, 8.64522e-08, 0.572548, 1.10411, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.35, 1, 8.64522e-08, 0.572548, 0.166984, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.4, 1, 8.64522e-08, 0.572547, 0.024261, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, 8.64522e-08, 0.572547, -4.76837e-07, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 8.64522e-08, 0.572547, -4.76837e-07, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="108"> 0, 1, -0.0366479, -0.0811065, 0.809552, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.0366479, -0.0811065, 0.816585, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, -0.0366479, -0.0811065, 0.826986, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, -0.0366479, -0.0811065, 0.829386, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, -0.0366479, -0.0811065, 0.826827, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, -0.0366479, -0.0811065, 0.812119, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, -0.0366479, -0.0811065, 0.809922, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.0366479, -0.0811065, 0.809552, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.0366479, -0.0811065, 0.809552, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="24"> 0, 1, 0.0611181, -2.75446, 0.0815672, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.0611181, -2.75446, 0.0815672, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="24"> 0, 1, 0.0798243, -0.0543702, -2.95838, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.0798243, -0.0543702, -2.95838, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="24"> 0, 1, 0.183564, 0.0305935, -3.02205, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.183564, 0.0305935, -3.02205, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="24"> 0, 1, -2.74884, 1.12805, 3.06242, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -2.74884, 1.12805, 3.06242, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="24"> 0, 1, 1.73339, 0.895247, 5.13844, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 1.73339, 0.895247, 5.13844, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="24"> 0, 1, 0.101768, -0.813356, 5.76642, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.101768, -0.813356, 5.76642, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="24"> 0, 1, -0.849557, -0.741664, 5.51935, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.849557, -0.741664, 5.51935, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="132"> 0, 1, 2.65402e-07, 1.83685, 0.489514, -5.25643e-15, 1.43922e-08, -0.0635436, 0.997979, 1, 1, 1, 0.05, 1, 2.56992e-07, 1.7811, 0.489514, -1.96073e-14, 1.43922e-08, -0.0635436, 0.997979, 1, 1, 1, 0.1, 1, 2.44553e-07, 1.69876, 0.489514, -1.94961e-14, 1.43922e-08, -0.0635436, 0.997979, 1, 1, 1, 0.15, 1, 2.41683e-07, 1.67977, 0.489514, -4.43536e-14, 1.60316e-08, -0.070782, 0.997492, 1, 1, 1, 0.2, 1, 2.44743e-07, 1.70003, 0.489514, -3.42428e-14, 2.17962e-08, -0.0962332, 0.995359, 1, 1, 1, 0.25, 1, 2.50383e-07, 1.73738, 0.489514, -5.58716e-16, 2.56855e-08, -0.113405, 0.993549, 1, 1, 1, 0.3, 1, 2.57035e-07, 1.78143, 0.489514, -6.36206e-15, 2.33115e-08, -0.102924, 0.994689, 1, 1, 1, 0.35, 1, 2.62333e-07, 1.81652, 0.489514, -1.06935e-14, 1.84103e-08, -0.0812848, 0.996691, 1, 1, 1, 0.4, 1, 2.6496e-07, 1.83392, 0.489514, -2.45344e-14, 1.50179e-08, -0.0663065, 0.997799, 1, 1, 1, 0.45, 1, 2.65402e-07, 1.83685, 0.489514, -5.25643e-15, 1.43922e-08, -0.0635436, 0.997979, 1, 1, 1, 1.25, 1, 2.65402e-07, 1.83685, 0.489514, -5.25643e-15, 1.43922e-08, -0.0635436, 0.997979, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="120"> 0, 1, -4.65684e-10, 7.57313e-10, 0, -8.93894e-16, 2.55708e-08, -0.112898, 0.993607, 1, 1, 1, 0.05, 1, -4.18389e-09, 6.71868e-09, -2.98023e-08, -0.00385828, -0.000945429, -0.112898, 0.993599, 1, 1, 1, 0.1, 1, -2.6989e-09, 6.71803e-09, -2.98023e-08, -0.0118093, -0.00289381, -0.11289, 0.993533, 1, 1, 1, 0.15, 1, -1.65698e-09, 6.19854e-09, -1.19209e-07, -0.0173041, -0.00424031, -0.112881, 0.993449, 1, 1, 1, 0.2, 1, 6.17568e-09, 2.79554e-08, -1.78814e-07, -0.0174121, -0.00426678, -0.11288, 0.993447, 1, 1, 1, 0.25, 1, -9.69976e-10, -3.44268e-09, -2.98023e-08, -0.013893, -0.00340444, -0.112887, 0.993505, 1, 1, 1, 0.35, 1, 8.55826e-09, 2.92274e-08, -2.98023e-08, -0.00310744, -0.000761444, -0.112898, 0.993601, 1, 1, 1, 0.4, 1, 2.05826e-09, 1.24848e-08, 0, -0.000452603, -0.000110883, -0.112898, 0.993606, 1, 1, 1, 0.45, 1, -4.65684e-10, 7.57313e-10, 0, -8.93894e-16, 2.55708e-08, -0.112898, 0.993607, 1, 1, 1, 1.25, 1, -4.65684e-10, 7.57313e-10, 0, -8.93894e-16, 2.55708e-08, -0.112898, 0.993607, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="108"> 0, 1, -7.51303e-09, 2.23517e-08, -2.38419e-07, 2.43554e-09, -0.00270918, 0.0663084, 0.997796, 1, 1, 1, 0.05, 1, -5.41336e-11, 3.72529e-09, -2.38419e-07, -0.00158657, -0.00317713, 0.0662892, 0.997794, 1, 1, 1, 0.15, 1, -3.26683e-10, 0, 5.96046e-08, -0.00925885, -0.00543992, 0.0661937, 0.997749, 1, 1, 1, 0.2, 1, -2.06055e-09, 1.49012e-08, -2.38419e-07, -0.0112141, -0.00601653, 0.0661687, 0.997727, 1, 1, 1, 0.25, 1, 1.76951e-08, -3.72529e-09, -1.78814e-07, -0.0104022, -0.00577711, 0.0661791, 0.997737, 1, 1, 1, 0.35, 1, 7.20902e-09, 7.45058e-09, -1.19209e-07, -0.00273, -0.00351437, 0.0662752, 0.997791, 1, 1, 1, 0.4, 1, 4.13622e-10, 3.72529e-09, -1.78814e-07, -0.000405934, -0.00282891, 0.0663035, 0.997795, 1, 1, 1, 0.45, 1, -7.51303e-09, 2.23517e-08, -2.38419e-07, 2.43554e-09, -0.00270918, 0.0663084, 0.997796, 1, 1, 1, 1.25, 1, -7.51303e-09, 2.23517e-08, -2.38419e-07, 2.43554e-09, -0.00270918, 0.0663084, 0.997796, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="24"> 0, 1, 4.48992e-09, -1.3411e-07, -1.07288e-06, -1.49012e-08, 7.81341e-10, 2.3736e-09, 1, 1, 1, 1, 1.25, 1, 4.48992e-09, -1.3411e-07, -1.07288e-06, -1.49012e-08, 7.81341e-10, 2.3736e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="120"> 0, 1, -1.54592e-09, -2.38419e-07, -3.32948e-08, 0.0746069, -0.101992, 0.0306522, 0.99151, 1, 1, 1, 0.05, 1, -1.11768e-09, -1.19209e-07, -9.73232e-08, 0.0219469, -0.103542, 0.0251775, 0.994064, 1, 1, 1, 0.1, 1, 3.72477e-10, -2.98023e-07, -7.61356e-08, -0.0560921, -0.105311, 0.0169133, 0.992712, 1, 1, 1, 0.15, 1, 1.49005e-09, -3.8743e-07, -9.8953e-08, -0.0807068, -0.112423, 0.0155536, 0.990255, 1, 1, 1, 0.2, 1, 9.68555e-09, -1.78814e-07, -2.06754e-07, -0.0663987, -0.135548, 0.0221852, 0.988294, 1, 1, 1, 0.25, 1, 1.86265e-08, -2.68221e-07, -1.18744e-08, -0.0319373, -0.150579, 0.0303761, 0.987615, 1, 1, 1, 0.35, 1, 7.26442e-09, -6.85453e-07, 3.81842e-08, 0.0516026, -0.119052, 0.0329235, 0.990999, 1, 1, 1, 0.4, 1, -1.48637e-09, -2.38419e-07, -5.07571e-08, 0.0712567, -0.10465, 0.03106, 0.991467, 1, 1, 1, 0.45, 1, -1.54592e-09, -2.38419e-07, -3.32948e-08, 0.0746069, -0.101992, 0.0306522, 0.99151, 1, 1, 1, 1.25, 1, -1.54592e-09, -2.38419e-07, -3.32948e-08, 0.0746069, -0.101992, 0.0306522, 0.99151, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="24"> 0, 1, 3.53794e-09, -1.25496e-07, -8.33534e-08, 2.23517e-08, 1.01485e-10, -1.43572e-10, 1, 1, 1, 1, 1.25, 1, 3.53794e-09, -1.25496e-07, -8.33534e-08, 2.23517e-08, 1.01485e-10, -1.43572e-10, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="24"> 0, 1, 1.23685e-09, 2.38419e-07, -5.96046e-07, -2.32831e-09, -1.31362e-12, 1.19249e-11, 1, 1, 1, 1, 1.25, 1, 1.23685e-09, 2.38419e-07, -5.96046e-07, -2.32831e-09, -1.31362e-12, 1.19249e-11, 1, 1, 1, 1 </real_array>
-
- </resource>
- <resource type="Animation" path="local://11">
- <string name="resource/name"> "falling-cycle" </string>
- <real name="length"> 0.416667 </real>
- <bool name="loop"> True </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="132"> 0, 1, 2.98023e-08, 1.19209e-07, -2.98023e-08, -0.336022, 0.262721, 0.175267, 0.887326, 1, 1, 1, 0.05, 1, 7.45058e-07, -3.57628e-07, 5.36442e-07, -0.336851, 0.262046, 0.173695, 0.887521, 1, 1, 1, 0.1, 1, 8.34465e-07, -5.96046e-07, 7.15256e-07, -0.33853, 0.260365, 0.16952, 0.888184, 1, 1, 1, 0.15, 1, 8.9407e-07, -3.57628e-07, 8.9407e-07, -0.338209, 0.258327, 0.163568, 0.890015, 1, 1, 1, 0.2, 1, 5.96046e-07, -3.57628e-07, 7.45058e-07, -0.333363, 0.256341, 0.157703, 0.89347, 1, 1, 1, 0.25, 1, 1.43051e-06, -8.34465e-07, 1.3113e-06, -0.339001, 0.253177, 0.158008, 0.892196, 1, 1, 0.999999, 0.3, 1, 5.96046e-07, -1.19209e-07, 2.98023e-07, -0.348081, 0.252511, 0.164449, 0.887713, 1, 1, 1, 0.35, 1, 1.07288e-06, -5.96046e-07, 7.45058e-07, -0.343056, 0.25799, 0.170697, 0.886914, 1, 1, 1, 0.4, 1, 3.27826e-07, 0, 2.38419e-07, -0.337258, 0.26196, 0.174599, 0.887214, 1, 1, 1, 0.45, 1, 2.98023e-08, 1.19209e-07, -2.98023e-08, -0.336022, 0.262721, 0.175267, 0.887326, 1, 1, 1, 1.25, 1, 2.98023e-08, 1.19209e-07, -2.98023e-08, -0.336022, 0.262721, 0.175267, 0.887326, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="120"> 0, 1, 3.27826e-07, -6.55651e-07, -4.17233e-07, 0.46904, -0.387773, 0.0221851, 0.793184, 1, 1, 1, 0.05, 1, -1.49012e-07, -8.34465e-07, -5.36442e-07, 0.467449, -0.38757, 0.0209387, 0.794256, 1, 0.999999, 1, 0.15, 1, 8.9407e-08, -8.34465e-07, -2.38419e-07, 0.457674, -0.38779, 0.0142454, 0.799969, 1, 1, 1, 0.2, 1, -1.19209e-07, -9.53674e-07, -5.96046e-07, 0.453414, -0.391376, 0.0115749, 0.800692, 1, 1, 1, 0.25, 1, -2.98023e-08, -8.64267e-07, -5.96046e-07, 0.455951, -0.392917, 0.0127032, 0.798476, 1, 1, 1, 0.3, 1, -2.68221e-07, -5.96046e-07, -3.57628e-07, 0.461696, -0.389009, 0.0167183, 0.797013, 1, 1, 1, 0.35, 1, 5.96046e-08, -9.23872e-07, -5.96046e-07, 0.465445, -0.38698, 0.0198743, 0.795747, 1, 1, 1, 0.4, 1, 2.68221e-07, -8.64267e-07, -6.55651e-07, 0.4685, -0.387548, 0.0218417, 0.793623, 1, 1, 1, 0.45, 1, 3.27826e-07, -6.55651e-07, -4.17233e-07, 0.46904, -0.387773, 0.0221851, 0.793184, 1, 1, 1, 1.25, 1, 3.27826e-07, -6.55651e-07, -4.17233e-07, 0.46904, -0.387773, 0.0221851, 0.793184, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="132"> 0, 1, -2.98023e-08, 1.19209e-07, -2.98023e-08, -0.326141, -0.23441, -0.185472, 0.896819, 1, 1, 1, 0.05, 1, -9.53674e-07, -4.76837e-07, 5.66244e-07, -0.309655, -0.239675, -0.179325, 0.902503, 1, 1, 1, 0.1, 1, -8.64267e-07, -4.76837e-07, 7.15256e-07, -0.27681, -0.251556, -0.166111, 0.912416, 1, 1, 1, 0.15, 1, -8.64267e-07, -3.57628e-07, 8.04663e-07, -0.254018, -0.264552, -0.15679, 0.917008, 1, 1, 1, 0.2, 1, -4.76837e-07, -3.57628e-07, 4.47035e-07, -0.251196, -0.272504, -0.156931, 0.915431, 1, 1, 1, 0.25, 1, -1.13249e-06, -7.15256e-07, 8.9407e-07, -0.279016, -0.258742, -0.169921, 0.909027, 1, 1, 1, 0.3, 1, -7.15256e-07, 1.19209e-07, 5.06639e-07, -0.316679, -0.238757, -0.183476, 0.89947, 1, 1, 1, 0.35, 1, -6.25849e-07, -1.19209e-07, 3.57628e-07, -0.327726, -0.235686, -0.18601, 0.895795, 1, 1, 1, 0.4, 1, -2.68221e-07, 0, 1.49012e-07, -0.326797, -0.234512, -0.185665, 0.896514, 1, 1, 1, 0.45, 1, -2.98023e-08, 1.19209e-07, -2.98023e-08, -0.326141, -0.23441, -0.185472, 0.896819, 1, 1, 1, 1.25, 1, -2.98023e-08, 1.19209e-07, -2.98023e-08, -0.326141, -0.23441, -0.185472, 0.896819, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="120"> 0, 1, -2.08616e-07, -1.54972e-06, -1.19209e-07, 0.47174, 0.366267, -0.0198596, 0.80182, 1, 1, 1, 0.05, 1, -2.98023e-08, -6.25849e-07, 0, 0.468656, 0.375596, -0.0166676, 0.799382, 1, 1, 1, 0.1, 1, -8.9407e-08, -2.68221e-07, -5.96046e-08, 0.459943, 0.392089, -0.0107327, 0.79662, 1, 1, 1, 0.15, 1, -2.08616e-07, -2.08616e-07, -2.38419e-07, 0.451048, 0.400355, -0.00696642, 0.797636, 1, 1, 1, 0.2, 1, -2.38419e-07, -7.7486e-07, 0, 0.448637, 0.398723, -0.00658308, 0.799813, 1, 1, 1, 0.3, 1, -5.96046e-08, -2.98023e-07, -4.17233e-07, 0.465357, 0.361793, -0.0151844, 0.807662, 1, 1, 1, 0.35, 1, -1.49012e-07, -5.36442e-07, -3.57628e-07, 0.468536, 0.360417, -0.0183993, 0.806372, 1, 1, 1, 0.4, 1, -5.96046e-08, -8.64267e-07, -1.78814e-07, 0.471244, 0.365087, -0.0196777, 0.802654, 1, 1, 1, 0.45, 1, -2.08616e-07, -1.54972e-06, -1.19209e-07, 0.47174, 0.366267, -0.0198596, 0.80182, 1, 1, 1, 1.25, 1, -2.08616e-07, -1.54972e-06, -1.19209e-07, 0.47174, 0.366267, -0.0198596, 0.80182, 1, 1, 1 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="132"> 0, 1, 0, 7.45058e-09, -1.3411e-07, -0.0625169, 0.00920125, -0.00328561, 0.997996, 1, 1, 1, 0.05, 1, 5.96046e-08, 8.9407e-08, -6.10948e-07, -0.0877092, 0.00901381, -0.00306586, 0.996101, 1, 1, 1, 0.1, 1, 5.96046e-08, -2.23517e-08, -1.19209e-07, -0.138998, 0.00794913, -0.00288258, 0.990257, 1, 1, 1, 0.15, 1, 5.96046e-08, 1.49012e-08, -4.02331e-07, -0.178155, 0.00579277, -0.00296187, 0.983981, 1, 1, 1, 0.2, 1, 8.9407e-08, 0, 1.78814e-07, -0.18648, 0.0038127, -0.0029159, 0.982447, 1, 1, 1, 0.25, 1, 5.96046e-08, 5.21541e-08, -1.93715e-07, -0.189861, 0.00940162, -0.00299906, 0.981761, 1, 1, 1, 0.3, 1, 5.96046e-08, -5.96046e-08, 2.83122e-07, -0.170763, 0.015059, -0.00307746, 0.985192, 1, 1, 1, 0.35, 1, 0, -7.45058e-09, -1.3411e-07, -0.115285, 0.0123617, -0.00312517, 0.993251, 1, 1, 1, 0.4, 1, 0, 7.45058e-09, -1.3411e-07, -0.0713277, 0.00977016, -0.00325209, 0.9974, 1, 1, 1, 0.45, 1, 0, 7.45058e-09, -1.3411e-07, -0.0625169, 0.00920125, -0.00328561, 0.997996, 1, 1, 1, 1.25, 1, 0, 7.45058e-09, -1.3411e-07, -0.0625169, 0.00920125, -0.00328561, 0.997996, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="120"> 0, 1, 4.42378e-08, -8.19564e-08, 1.78814e-07, -0.407694, 0.0277893, 0.000765211, 0.912696, 1, 1, 1, 0.05, 1, 1.89757e-08, -5.21541e-08, 6.55651e-07, -0.435809, 0.0297697, 0.000893482, 0.899546, 1, 1, 1, 0.1, 1, 1.42027e-08, 6.70552e-08, 7.15256e-07, -0.489147, 0.0339313, 0.00115069, 0.871541, 1, 1, 1, 0.15, 1, 1.13854e-07, 0, 5.96046e-07, -0.523927, 0.0370339, 0.00133512, 0.850957, 1, 1, 1, 0.2, 1, 1.29221e-07, -3.72529e-08, 4.17233e-07, -0.526448, 0.0372296, 0.00134975, 0.849391, 1, 1, 1, 0.25, 1, 1.6077e-07, -2.68221e-07, 4.76837e-07, -0.538369, 0.0372441, 0.00135905, 0.841885, 1, 1, 1, 0.3, 1, 6.17001e-09, -1.04308e-07, 7.15256e-07, -0.530237, 0.0358611, 0.00127618, 0.84709, 1, 1, 1, 0.4, 1, 2.08383e-08, -2.23517e-08, 4.17233e-07, -0.418447, 0.0284447, 0.00080823, 0.907795, 1, 1, 1, 0.45, 1, 4.42378e-08, -8.19564e-08, 1.78814e-07, -0.407694, 0.0277893, 0.000765211, 0.912696, 1, 1, 1, 1.25, 1, 4.42378e-08, -8.19564e-08, 1.78814e-07, -0.407694, 0.0277893, 0.000765211, 0.912696, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="24"> 0, 1, 1.04308e-07, -1.19209e-07, 6.70552e-08, -1.11759e-08, 1.16415e-09, 7.45058e-09, 1, 1, 1, 1, 1.25, 1, 1.04308e-07, -1.19209e-07, 6.70552e-08, -1.11759e-08, 1.16415e-09, 7.45058e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="120"> 0, 1, -2.98023e-08, 1.49012e-08, 1.19209e-07, -0.630421, -0.0882657, 0.00990556, 0.771155, 1, 1, 1, 0.05, 1, 8.9407e-08, 9.68575e-08, -2.38419e-07, -0.641086, -0.0918399, 0.00914405, 0.7619, 1, 1, 1, 0.15, 1, 5.96046e-08, 2.23517e-08, -1.3411e-07, -0.695929, -0.109196, 0.0054072, 0.70974, 1, 1, 1, 0.2, 1, 0, 7.45058e-09, 4.61936e-07, -0.716484, -0.115048, 0.00471066, 0.688035, 0.999999, 1, 1, 0.25, 1, 2.98023e-08, 5.21541e-08, 7.45058e-08, -0.742062, -0.116709, 0.0109015, 0.660003, 1, 1, 1, 0.3, 1, -5.96046e-08, -6.70552e-08, 5.51343e-07, -0.738131, -0.110711, 0.0165993, 0.665304, 0.999999, 1, 1, 0.35, 1, -2.98023e-08, -1.49012e-08, 1.19209e-07, -0.683291, -0.098194, 0.0131016, 0.723395, 1, 1, 1, 0.4, 1, -2.98023e-08, 1.49012e-08, 1.19209e-07, -0.638973, -0.0897534, 0.0103931, 0.763904, 1, 1, 1, 0.45, 1, -2.98023e-08, 1.49012e-08, 1.19209e-07, -0.630421, -0.0882657, 0.00990556, 0.771155, 1, 1, 1, 1.25, 1, -2.98023e-08, 1.49012e-08, 1.19209e-07, -0.630421, -0.0882657, 0.00990556, 0.771155, 1, 1, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="120"> 0, 1, 4.48199e-08, -1.11759e-07, 1.78814e-07, -0.822993, -0.106344, -0.00540277, 0.557982, 1, 1, 1, 0.05, 1, 4.30737e-09, -2.08616e-07, -1.19209e-07, -0.827005, -0.107477, -0.00546779, 0.551799, 1, 1, 1, 0.1, 1, 8.84756e-09, -1.19209e-07, 1.19209e-07, -0.836608, -0.110063, -0.00562015, 0.536601, 1, 1, 1, 0.2, 1, -2.91038e-08, 1.19209e-07, 0, -0.857806, -0.115929, -0.00596456, 0.500693, 1, 1, 1, 0.25, 1, 7.33417e-09, 0, 5.96046e-08, 0.876669, 0.123709, 0.00633999, -0.464874, 1, 1, 1, 0.3, 1, -4.38886e-08, -1.3411e-07, -1.19209e-07, 0.881066, 0.125876, 0.00641456, -0.455891, 1, 1, 1, 0.35, 1, 9.66247e-09, 0, -5.96046e-08, -0.853515, -0.11545, -0.00587343, 0.508083, 1, 1, 1, 0.4, 1, 2.17697e-08, -3.72529e-08, 5.96046e-08, -0.828218, -0.107764, -0.00547631, 0.549921, 1, 1, 1, 0.45, 1, 4.48199e-08, -1.11759e-07, 1.78814e-07, -0.822993, -0.106344, -0.00540277, 0.557982, 1, 1, 1, 1.25, 1, 4.48199e-08, -1.11759e-07, 1.78814e-07, -0.822993, -0.106344, -0.00540277, 0.557982, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="24"> 0, 1, 7.45058e-09, -2.38419e-07, -8.19564e-08, -1.86265e-08, -1.28057e-09, 3.72529e-09, 1, 1, 1, 1, 1.25, 1, 7.45058e-09, -2.38419e-07, -8.19564e-08, -1.86265e-08, -1.28057e-09, 3.72529e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="24"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="108"> 0, 1, -5.68434e-14, 0, 2.81136, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -5.68434e-14, 0, 2.88275, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, 5.68434e-14, 4.76837e-07, 3.22584, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, 5.68434e-14, 4.76837e-07, 3.31311, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.25, 1, 5.68434e-14, 4.76837e-07, 3.27685, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, -5.68434e-14, 0, 2.93405, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.4, 1, -5.68434e-14, 0, 2.82965, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, -5.68434e-14, 0, 2.81136, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -5.68434e-14, 0, 2.81136, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="120"> 0, 1, -5.96046e-08, 0.623878, 0.831837, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -5.96046e-08, 0.623878, 0.85661, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, -5.96046e-08, 0.623878, 0.907642, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, -5.96046e-08, 0.623878, 0.942906, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, -5.96046e-08, 0.623878, 0.943599, 0, 0, 0, 1, 1, 1, 1, 0.25, 1, -5.96046e-08, 0.623878, 0.921011, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, -5.96046e-08, 0.623878, 0.851786, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, -5.96046e-08, 0.623878, 0.834743, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, -5.96046e-08, 0.623878, 0.831837, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -5.96046e-08, 0.623878, 0.831837, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="132"> 0, 1, -1.19209e-07, 1.00668e-07, 1.33339, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -1.19209e-07, 1.01535e-07, 1.34488, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, -1.19209e-07, 1.0373e-07, 1.37395, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, -1.19209e-07, 1.06482e-07, 1.41041, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, -1.19209e-07, 1.08677e-07, 1.43947, 0, 0, 0, 1, 1, 1, 1, 0.25, 1, -1.19209e-07, 1.09544e-07, 1.45096, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, -1.19209e-07, 1.07675e-07, 1.4262, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, -1.19209e-07, 1.03822e-07, 1.37517, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, -1.19209e-07, 1.01159e-07, 1.33989, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, -1.19209e-07, 1.00668e-07, 1.33339, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -1.19209e-07, 1.00668e-07, 1.33339, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="24"> 0, 1, -2.98023e-08, 1.19209e-07, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -2.98023e-08, 1.19209e-07, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="24"> 0, 1, 2.98023e-08, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 2.98023e-08, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="132"> 0, 1, -1.39671, 2.72686, 1.19541, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -1.39671, 2.70532, 1.19971, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -1.39671, 2.65088, 1.2106, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, -1.39671, 2.5826, 1.22425, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, -1.39671, 2.52819, 1.23514, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, -1.39671, 2.50668, 1.23944, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, -1.39671, 2.55303, 1.23017, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.35, 1, -1.39671, 2.64856, 1.21105, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -1.39671, 2.71466, 1.19784, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -1.39671, 2.72686, 1.19541, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -1.39671, 2.72686, 1.19541, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="120"> 0, 1, 1.27388, 2.72686, 1.19541, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 1.27388, 2.68042, 1.20468, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, 1.27388, 2.58486, 1.2238, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, 1.27388, 2.51885, 1.23701, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, 1.27388, 2.51756, 1.23727, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, 1.27388, 2.55985, 1.22881, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, 1.27388, 2.68948, 1.20288, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, 1.27388, 2.72141, 1.19649, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, 1.27388, 2.72686, 1.19541, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 1.27388, 2.72686, 1.19541, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="24"> 0, 1, 0.59069, -0.00390959, 0.736489, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.59069, -0.00390959, 0.736489, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="24"> 0, 1, -0.59069, -0.00390959, 0.736489, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.59069, -0.00390959, 0.736489, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="120"> 0, 1, -9.25123e-16, 1.16368e-07, -0.513782, -0.068257, 1.03065e-08, 8.40178e-15, 0.997668, 1, 1, 1, 0.05, 1, -0.00604435, -0.0171726, -0.516875, -0.068257, 1.03065e-08, 1.59689e-14, 0.997668, 1, 1, 1, 0.15, 1, -0.0352723, -0.100186, -0.531832, -0.068257, 1.03065e-08, 8.79127e-15, 0.997668, 1, 1, 1, 0.2, 1, -0.0427212, -0.121339, -0.535645, -0.068257, 1.03065e-08, 1.59689e-14, 0.997668, 1, 1, 1, 0.25, 1, -0.0251165, -0.102747, -0.494262, -0.068257, 1.03065e-08, 8.40178e-15, 0.997668, 1, 1, 1, 0.3, 1, -0.00387635, -0.0612733, -0.455449, -0.068257, 1.03065e-08, 8.79127e-15, 0.997668, 1, 1, 1, 0.35, 1, -0.000906605, -0.0266833, -0.479965, -0.068257, 1.03065e-08, 1.59689e-14, 0.997668, 1, 1, 1, 0.4, 1, -5.88306e-05, -0.00401501, -0.507859, -0.068257, 1.03065e-08, 8.79127e-15, 0.997668, 1, 1, 1, 0.45, 1, -9.25123e-16, 1.16368e-07, -0.513782, -0.068257, 1.03065e-08, 8.40178e-15, 0.997668, 1, 1, 1, 1.25, 1, -9.25123e-16, 1.16368e-07, -0.513782, -0.068257, 1.03065e-08, 8.40178e-15, 0.997668, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="108"> 0, 1, -5.25618e-15, 1.49011e-08, -1.49012e-07, 0.0904093, -6.07213e-16, 7.18977e-15, 0.995905, 1, 1, 1, 0.05, 1, -2.67973e-10, 2.32644e-08, -5.96046e-08, 0.0920949, -3.47794e-16, 7.16792e-15, 0.99575, 1, 1, 1, 0.15, 1, 2.52298e-09, 2.61876e-08, -2.98023e-08, 0.100243, -1.17281e-15, 7.25956e-15, 0.994963, 1, 1, 1, 0.2, 1, -5.62989e-10, 3.32728e-08, -1.49012e-07, 0.102318, -1.15767e-15, 7.26199e-15, 0.994752, 1, 1, 1, 0.25, 1, -1.24048e-09, 3.35948e-08, -8.9407e-08, 0.101456, -6.3375e-16, 7.20691e-15, 0.99484, 1, 1, 1, 0.35, 1, 8.229e-13, 2.99392e-08, -1.49012e-07, 0.0933096, -3.39049e-16, 7.16834e-15, 0.995637, 1, 1, 1, 0.4, 1, -3.31995e-12, 2.53408e-08, -1.49012e-07, 0.0908406, -1.44454e-15, 1.31767e-16, 0.995865, 1, 1, 1, 0.45, 1, -5.25618e-15, 1.49011e-08, -1.49012e-07, 0.0904093, -6.07213e-16, 7.18977e-15, 0.995905, 1, 1, 1, 1.25, 1, -5.25618e-15, 1.49011e-08, -1.49012e-07, 0.0904093, -6.07213e-16, 7.18977e-15, 0.995905, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="108"> 0, 1, -1.31025e-21, 7.45058e-09, -1.78814e-07, 0.0570428, -7.52314e-16, -1.03276e-15, 0.998372, 1, 1, 1, 0.05, 1, -6.93196e-14, 7.45058e-09, 0, 0.0590419, -0.00284152, 0.000283556, 0.998251, 1, 1, 1, 0.15, 1, 7.44988e-10, -3.72529e-09, 0, 0.0686997, -0.0165823, 0.00165476, 0.997498, 1, 1, 1, 0.2, 1, -7.04617e-14, -7.45058e-09, -5.96046e-08, 0.0711578, -0.0200834, 0.00200414, 0.997261, 1, 1, 1, 0.25, 1, -6.96491e-14, -3.72529e-09, -5.96046e-08, 0.0701373, -0.0186297, 0.00185908, 0.997362, 1, 1, 1, 0.35, 1, 6.97804e-11, 7.45058e-09, -1.78814e-07, 0.0604823, -0.00488944, 0.000487919, 0.998157, 1, 1, 1, 0.4, 1, -2.75782e-14, 1.11759e-08, -2.38419e-07, 0.0575543, -0.000727023, 7.25494e-05, 0.998342, 1, 1, 1, 0.45, 1, -1.31025e-21, 7.45058e-09, -1.78814e-07, 0.0570428, -7.52314e-16, -1.03276e-15, 0.998372, 1, 1, 1, 1.25, 1, -1.31025e-21, 7.45058e-09, -1.78814e-07, 0.0570428, -7.52314e-16, -1.03276e-15, 0.998372, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="24"> 0, 1, -8.52651e-14, -4.47035e-08, -4.76837e-07, -7.45058e-09, 2.13163e-14, -1.77636e-15, 1, 1, 1, 1, 1.25, 1, -8.52651e-14, -4.47035e-08, -4.76837e-07, -7.45058e-09, 2.13163e-14, -1.77636e-15, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="120"> 0, 1, 1.77636e-14, -4.17233e-07, -3.53903e-08, -0.197724, -1.34662e-08, 4.54456e-08, 0.980258, 1, 1, 1, 0.05, 1, -1.95943e-09, -5.06639e-07, -6.40284e-08, -0.199636, 0.000196518, -0.00285815, 0.979866, 1, 1, 1, 0.15, 1, -2.19083e-08, -2.38419e-07, -5.75092e-08, -0.207914, 0.00144056, -0.0167025, 0.978003, 1, 1, 1, 0.2, 1, 6.08469e-09, -3.8743e-07, -6.33299e-08, -0.209803, 0.00183038, -0.0202351, 0.977533, 1, 1, 1, 0.25, 1, -4.45088e-08, -8.64267e-07, -5.21541e-08, -0.20649, 0.000358444, -0.0190238, 0.978264, 1, 1, 1, 0.3, 1, 7.56265e-09, -8.34465e-07, -4.84288e-08, -0.200537, -0.000986884, -0.0126263, 0.979604, 1, 1, 1, 0.35, 1, 3.42126e-11, -4.17233e-07, -2.37487e-08, -0.198104, -0.000490507, -0.00505109, 0.980168, 1, 1, 1, 0.4, 1, 3.9655e-10, -3.57628e-07, -3.05008e-08, -0.197722, -8.26043e-05, -0.000750033, 0.980258, 1, 1, 1, 0.45, 1, 1.77636e-14, -4.17233e-07, -3.53903e-08, -0.197724, -1.34662e-08, 4.54456e-08, 0.980258, 1, 1, 1, 1.25, 1, 1.77636e-14, -4.17233e-07, -3.53903e-08, -0.197724, -1.34662e-08, 4.54456e-08, 0.980258, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="24"> 0, 1, 2.81164e-14, 2.468e-08, 3.32249e-07, 2.23517e-08, -5.32907e-15, 7.10543e-15, 1, 1, 1, 1, 1.25, 1, 2.81164e-14, 2.468e-08, 3.32249e-07, 2.23517e-08, -5.32907e-15, 7.10543e-15, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="24"> 0, 1, 7.99361e-14, 1.49012e-07, -8.34465e-07, 2.43308e-08, 6.21725e-15, -8.59209e-15, 1, 1, 1, 1, 1.25, 1, 7.99361e-14, 1.49012e-07, -8.34465e-07, 2.43308e-08, 6.21725e-15, -8.59209e-15, 1, 1, 1, 1 </real_array>
-
- </resource>
- <resource type="Animation" path="local://12">
- <string name="resource/name"> "walk-cycle" </string>
- <real name="length"> 1.041667 </real>
- <bool name="loop"> True </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="228"> 0, 1, 7.7486e-07, -3.57628e-07, 5.66244e-07, 0.132777, -0.115851, -0.0857195, 0.980613, 1, 1, 1, 0.05, 1, 4.17233e-07, 1.19209e-07, 3.27826e-07, 0.136218, -0.113975, -0.0877542, 0.980181, 1, 1, 1, 0.1, 1, 5.06639e-07, -2.38419e-07, 2.98023e-07, 0.144837, -0.108331, -0.0933223, 0.97907, 1, 1, 1, 0.15, 1, 5.36442e-07, -3.57628e-07, 3.57628e-07, 0.15539, -0.0990044, -0.102617, 0.977508, 1, 0.999999, 1, 0.2, 1, 7.15256e-07, -3.57628e-07, 4.47035e-07, 0.162073, -0.0835771, -0.115431, 0.976434, 1, 1, 1, 0.25, 1, 6.25849e-07, -3.57628e-07, 4.17233e-07, 0.160674, -0.0537521, -0.128708, 0.977102, 1, 1, 1, 0.3, 1, 6.85453e-07, -3.57628e-07, 2.98023e-07, 0.144844, 0.00232148, -0.137246, 0.979887, 1, 1, 1, 0.45, 1, 9.53674e-07, -7.15256e-07, 6.85453e-07, 0.0267683, 0.215793, -0.138386, 0.966212, 1, 1, 1, 0.5, 1, 7.7486e-07, -3.57628e-07, 4.17233e-07, -0.00441569, 0.255036, -0.137846, 0.957045, 1, 1, 1, 0.55, 1, 8.34465e-07, -5.96046e-07, 5.36442e-07, -0.00986276, 0.263176, -0.137756, 0.954811, 1, 1, 1, 0.6, 1, 4.76837e-07, 0, 3.8743e-07, 0.0174093, 0.245944, -0.13741, 0.959337, 1, 1, 1, 0.7, 1, 3.27826e-07, -1.19209e-07, 2.68221e-07, 0.12402, 0.181155, -0.127036, 0.967297, 1, 1, 1, 0.75, 1, 7.45058e-07, 0, 4.47035e-07, 0.157369, 0.166922, -0.11544, 0.96646, 1, 1, 1, 0.8, 1, 8.34465e-07, -1.19209e-07, 4.47035e-07, 0.166665, 0.143487, -0.108193, 0.969499, 1, 1, 1, 0.85, 1, 2.98023e-07, 0, 1.49012e-07, 0.164004, 0.0866041, -0.105149, 0.977009, 1, 0.999999, 1, 0.95, 1, 4.76837e-07, 0, 2.38419e-07, 0.144168, -0.0621538, -0.0938402, 0.983131, 1, 1, 1, 1, 1, 8.64267e-07, -4.76837e-07, 6.85453e-07, 0.135099, -0.105557, -0.0876091, 0.98129, 1, 1, 1, 1.05, 1, 7.7486e-07, -3.57628e-07, 5.66244e-07, 0.132777, -0.115851, -0.0857195, 0.980613, 1, 1, 1, 1.25, 1, 7.7486e-07, -3.57628e-07, 5.66244e-07, 0.132777, -0.115851, -0.0857195, 0.980613, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="228"> 0, 1, 7.45058e-07, -8.04663e-07, -8.34465e-07, -0.0607703, -0.240987, 0.00892511, 0.968583, 1, 1, 1, 0.05, 1, -2.98023e-07, -3.57628e-07, 1.78814e-07, -0.0608664, -0.247441, 0.00903588, 0.966947, 1, 0.999999, 1, 0.1, 1, -1.78814e-07, -7.45058e-07, -1.19209e-07, -0.0607357, -0.265635, 0.00908754, 0.962116, 1, 1, 1, 0.15, 1, 4.17233e-07, -8.64267e-07, -4.17233e-07, -0.0586521, -0.298966, 0.00880687, 0.952419, 1, 1, 1, 0.25, 1, 3.8743e-07, -5.96046e-07, -2.98023e-07, -0.0404347, -0.402042, 0.00443354, 0.914717, 1, 1, 1, 0.3, 1, -2.98023e-08, -6.85453e-07, -2.38419e-07, -0.0222657, -0.438743, -0.00390802, 0.898328, 1, 1, 1, 0.35, 1, -3.27826e-07, -2.68221e-07, -1.78814e-07, -0.001747, -0.450439, -0.0151044, 0.892678, 1, 0.999999, 1, 0.4, 1, -2.98023e-08, -3.57628e-07, -4.76837e-07, 0.0165229, -0.440184, -0.0247739, 0.897414, 1, 1, 1, 0.5, 1, 2.98023e-08, -3.27826e-07, 0, 0.0357718, -0.396841, -0.0343986, 0.916545, 1, 1, 1, 0.55, 1, 1.49012e-07, -6.25849e-07, -1.78814e-07, 0.0355214, -0.39013, -0.0350975, 0.919405, 1, 1, 1, 0.6, 1, 1.78814e-07, -5.06639e-07, -5.36442e-07, 0.01977, -0.384514, -0.0345495, 0.92226, 1, 1, 1, 0.65, 1, -1.19209e-07, -4.17233e-07, -2.38419e-07, -0.0162325, -0.357154, -0.033198, 0.933314, 1, 0.999999, 1, 0.75, 1, -2.98023e-08, -3.57628e-07, -2.98023e-07, -0.0986698, -0.203446, -0.0321126, 0.973572, 1, 0.999999, 1, 0.8, 1, 5.96046e-08, -7.45058e-07, -2.38419e-07, -0.110421, -0.161891, -0.0281555, 0.980207, 1, 1, 1, 0.85, 1, 4.76837e-07, -8.04663e-07, -8.34465e-07, -0.104832, -0.172931, -0.0183971, 0.979166, 1, 0.999999, 1, 0.95, 1, 0, -6.55651e-07, -5.96046e-07, -0.0743493, -0.227469, 0.00271093, 0.970939, 1, 1, 1, 1, 1, -2.98023e-08, -3.57628e-07, -2.38419e-07, -0.0636988, -0.238854, 0.00790001, 0.968932, 1, 1, 1, 1.05, 1, 7.45058e-07, -8.04663e-07, -8.34465e-07, -0.0607703, -0.240987, 0.00892511, 0.968583, 1, 1, 1, 1.25, 1, 7.45058e-07, -8.04663e-07, -8.34465e-07, -0.0607703, -0.240987, 0.00892511, 0.968583, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="216"> 0, 1, -7.45058e-07, -4.76837e-07, 4.47035e-07, -0.0127337, -0.264935, 0.137763, 0.954289, 1, 1, 1, 0.05, 1, -3.8743e-07, 0, 2.38419e-07, 0.0104992, -0.248758, 0.137429, 0.958709, 1, 1, 1, 0.15, 1, -5.66244e-07, -1.19209e-07, 4.47035e-07, 0.119317, -0.176495, 0.127478, 0.968691, 1, 1, 1, 0.2, 1, -5.06639e-07, -1.19209e-07, 3.27826e-07, 0.156208, -0.160784, 0.115735, 0.967653, 1, 1, 1, 0.25, 1, -4.17233e-07, -1.19209e-07, 2.68221e-07, 0.170588, -0.146234, 0.10696, 0.968543, 1, 0.999999, 1, 0.3, 1, -8.34465e-07, -3.57628e-07, 8.9407e-07, 0.16899, -0.106962, 0.104274, 0.974232, 1, 1, 1, 0.45, 1, -9.23872e-07, -5.96046e-07, 7.7486e-07, 0.141826, 0.058077, 0.0901382, 0.984067, 1, 1, 1, 0.5, 1, -7.7486e-07, -5.96046e-07, 2.98023e-07, 0.134623, 0.0959315, 0.0862667, 0.982462, 1, 1, 1, 0.55, 1, -7.45058e-07, -3.57628e-07, 6.25849e-07, 0.133233, 0.11842, 0.0861958, 0.980202, 1, 1, 1, 0.6, 1, -4.76837e-07, 0, 4.47035e-07, 0.137596, 0.131505, 0.0903706, 0.977551, 1, 1, 1, 0.65, 1, -6.55651e-07, -3.57628e-07, 5.36442e-07, 0.146837, 0.135484, 0.0990691, 0.974817, 1, 1, 1, 0.7, 1, -5.96046e-07, -3.57628e-07, 6.25849e-07, 0.15676, 0.127354, 0.111789, 0.972991, 1, 1, 1, 0.75, 1, -4.17233e-07, 0, 3.8743e-07, 0.161767, 0.101349, 0.126219, 0.973462, 1, 1, 1, 0.8, 1, -6.85453e-07, -3.57628e-07, 5.06639e-07, 0.154473, 0.0449621, 0.136756, 0.977453, 1, 1, 1, 0.95, 1, -6.55651e-07, -2.38419e-07, 4.76837e-07, 0.0363447, -0.203514, 0.138296, 0.968574, 1, 1, 1, 1, 1, -5.96046e-07, -3.57628e-07, 3.57628e-07, -0.00218869, -0.252498, 0.137778, 0.957735, 1, 1, 1, 1.05, 1, -7.45058e-07, -4.76837e-07, 4.47035e-07, -0.0127337, -0.264935, 0.137763, 0.954289, 1, 1, 1, 1.25, 1, -7.45058e-07, -4.76837e-07, 4.47035e-07, -0.0127337, -0.264935, 0.137763, 0.954289, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="192"> 0, 1, 3.57628e-07, -5.96046e-07, -3.57628e-07, 0.0370915, 0.39046, 0.0351404, 0.919201, 1, 1, 1, 0.05, 1, -1.49012e-07, -5.96046e-07, -2.38419e-07, 0.0247868, 0.388139, 0.0345456, 0.92062, 1, 1, 1, 0.1, 1, -3.57628e-07, -5.66244e-07, -4.76837e-07, -0.00839952, 0.367653, 0.0329431, 0.929342, 1, 1, 1, 0.15, 1, -1.78814e-07, -5.66244e-07, -7.7486e-07, -0.0538019, 0.307417, 0.0309853, 0.949547, 1, 1, 1, 0.2, 1, 0, -3.8743e-07, -4.17233e-07, -0.0934157, 0.21941, 0.0316565, 0.970634, 1, 1, 1, 0.25, 1, -1.49012e-07, -7.7486e-07, -3.57628e-07, -0.112029, 0.160435, 0.0303507, 0.980198, 1, 1, 1, 0.3, 1, 1.19209e-07, -7.15256e-07, -2.38419e-07, -0.111906, 0.1565, 0.0231637, 0.981045, 1, 1, 1, 0.35, 1, 2.68221e-07, -5.06639e-07, -2.38419e-07, -0.104709, 0.167819, 0.0144275, 0.980135, 1, 1, 1, 0.6, 1, 2.38419e-07, -3.57628e-07, -2.98023e-07, -0.0540049, 0.274564, -0.0119163, 0.959977, 1, 1, 1, 0.65, 1, 2.68221e-07, -2.68221e-07, 5.96046e-08, -0.0496356, 0.312827, -0.0136146, 0.948415, 1, 1, 1, 0.8, 1, 1.78814e-07, -3.8743e-07, -2.38419e-07, -0.0228587, 0.449632, -0.00310725, 0.892916, 1, 1, 1, 0.85, 1, -2.08616e-07, -6.25849e-07, -5.36442e-07, -0.00418434, 0.463526, 0.00969348, 0.886021, 1, 1, 1, 0.9, 1, -2.68221e-07, -6.85453e-07, -1.19209e-07, 0.0143603, 0.452468, 0.0218435, 0.891397, 1, 1, 1, 1, 1, 8.9407e-08, -5.96046e-07, -5.36442e-07, 0.0356796, 0.398885, 0.0342096, 0.915668, 1, 1, 1, 1.05, 1, 3.57628e-07, -5.96046e-07, -3.57628e-07, 0.0370915, 0.39046, 0.0351404, 0.919201, 1, 1, 1, 1.25, 1, 3.57628e-07, -5.96046e-07, -3.57628e-07, 0.0370915, 0.39046, 0.0351404, 0.919201, 1, 1, 1 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="180"> 0, 1, -5.96046e-08, 7.45058e-09, -1.3411e-07, -0.47466, -0.0131527, -0.012987, 0.879975, 1, 1, 1, 0.05, 1, 2.98023e-08, 2.23517e-08, -2.23517e-07, -0.410091, -0.00379406, -0.0158917, 0.911898, 1, 1, 1, 0.25, 1, -1.19209e-07, 1.11759e-07, -5.21541e-07, 0.0997313, 0.0337367, -0.0261638, 0.994098, 1, 1, 1, 0.3, 1, 8.9407e-08, 4.47035e-08, -4.02331e-07, 0.122513, 0.0214196, -0.0200121, 0.992034, 1, 1, 1, 0.45, 1, 1.19209e-07, 7.45058e-09, -3.27826e-07, 0.229705, -0.0511077, 0.00301582, 0.971913, 1, 1, 1, 0.5, 1, 0, 3.72529e-08, -3.72529e-07, 0.236488, -0.0697987, 0.00859063, 0.969086, 1, 1, 1, 0.55, 1, 0, 2.98023e-08, -2.5332e-07, 0.206064, -0.0732532, 0.0100766, 0.975741, 1, 1, 1, 0.6, 1, -2.98023e-08, 4.47035e-08, -2.68221e-07, 0.118009, -0.0599028, 0.00750554, 0.991176, 1, 1, 1, 0.65, 1, -8.9407e-08, 2.23517e-08, -2.83122e-07, -0.0368129, -0.031384, 0.00214083, 0.998827, 1, 1, 1, 0.8, 1, -5.96046e-08, 2.23517e-08, -3.42727e-07, -0.634332, 0.0354032, -0.00990766, 0.772186, 1, 1, 1, 0.85, 1, 0, 2.23517e-08, -5.51343e-07, -0.746229, 0.0185993, -0.00698883, 0.665393, 1, 1, 1, 0.9, 1, 2.98023e-08, 1.49012e-08, -3.72529e-07, -0.740985, -0.00577112, -0.000829951, 0.671497, 1, 1, 1, 1, 1, 0, 2.98023e-08, -2.68221e-07, -0.523042, -0.0161244, -0.00986391, 0.852097, 1, 1, 1, 1.05, 1, -5.96046e-08, 7.45058e-09, -1.3411e-07, -0.47466, -0.0131527, -0.012987, 0.879975, 1, 1, 1, 1.25, 1, -5.96046e-08, 7.45058e-09, -1.3411e-07, -0.47466, -0.0131527, -0.012987, 0.879975, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="216"> 0, 1, 9.0804e-08, -5.21541e-08, 5.36442e-07, -0.373219, -0.0555838, 8.64882e-05, 0.926077, 1, 1, 1, 0.05, 1, 2.50293e-08, 1.3411e-07, 5.96046e-07, -0.322099, -0.0481091, 0.000521386, 0.945483, 1, 1, 1, 0.1, 1, 1.20257e-07, -1.49012e-07, 7.15256e-07, -0.224139, -0.0330777, 0.00125387, 0.973995, 1, 1, 1, 0.15, 1, 3.94648e-08, -1.3411e-07, 6.55651e-07, -0.165692, -0.0218823, 0.00143977, 0.985934, 1, 1, 1, 0.2, 1, 1.33412e-07, -1.56462e-07, 5.36442e-07, -0.09297, -0.0104596, 0.00125276, 0.995613, 1, 1, 1, 0.25, 1, 3.55067e-08, 4.47035e-08, 1.78814e-07, -0.0411288, -0.0028586, 0.000542978, 0.99915, 1, 1, 1, 0.35, 1, 9.26666e-08, 5.96046e-08, 6.55651e-07, -0.159491, 0.00874812, -0.00126692, 0.98716, 1, 1, 1, 0.45, 1, 3.87663e-08, 0, 4.76837e-07, -0.233894, 0.0318884, -0.00310529, 0.971734, 1, 1, 1, 0.5, 1, -3.53903e-08, -7.45058e-08, 5.96046e-07, -0.280896, 0.0453351, -0.00364749, 0.95866, 1, 1, 1, 0.55, 1, 1.59489e-08, 4.47035e-08, 5.96046e-07, -0.352331, 0.0592861, -0.00363569, 0.933989, 1, 1, 1, 0.6, 1, 2.16532e-08, 1.3411e-07, 6.55651e-07, -0.469209, 0.0766892, -0.00261066, 0.879747, 1, 1, 1, 0.75, 1, 9.51113e-08, -2.01166e-07, 7.15256e-07, -0.846575, 0.0999882, 0.00219129, 0.522789, 1, 1, 1, 0.8, 1, 3.77186e-08, -1.49012e-07, 6.55651e-07, 0.900504, -0.0754152, -0.00223886, -0.428252, 1, 1, 1, 0.85, 1, 4.92437e-08, 1.49012e-07, 6.55651e-07, 0.906482, -0.0264902, -0.00126108, -0.42141, 1, 1, 1, 0.9, 1, -2.71248e-08, 1.63913e-07, 5.36442e-07, -0.830638, -0.0316768, -0.000334372, 0.555911, 1, 1, 1, 1, 1, 2.87546e-08, 4.84288e-07, 7.7486e-07, -0.453335, -0.0623349, -0.000381388, 0.889158, 1, 1, 1, 1.05, 1, 9.0804e-08, -5.21541e-08, 5.36442e-07, -0.373219, -0.0555838, 8.64882e-05, 0.926077, 1, 1, 1, 1.25, 1, 9.0804e-08, -5.21541e-08, 5.36442e-07, -0.373219, -0.0555838, 8.64882e-05, 0.926077, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="168"> 0, 1, 5.21541e-08, -1.19209e-07, 9.31323e-08, 0.00219921, 0.118787, -0.0237834, 0.992633, 1, 1, 1, 0.05, 1, 5.96046e-08, 0, -5.58794e-08, 0.00569734, 0.111426, -0.0235639, 0.993477, 1, 1, 1, 0.1, 1, 4.47035e-08, -1.19209e-07, 3.35276e-08, 0.015864, 0.0910374, -0.022104, 0.995476, 1, 1, 1, 0.25, 1, 2.98023e-08, 1.19209e-07, -5.58794e-08, 0.0701794, 0.000367211, 0.000696922, 0.997534, 1, 1, 1, 0.35, 1, 8.19564e-08, -1.19209e-07, -1.11759e-08, 0.121501, -0.050768, 0.0840024, 0.987727, 1, 1, 1, 0.4, 1, 7.45058e-08, 1.19209e-07, 1.04308e-07, 0.115586, -0.0703619, 0.0928345, 0.986444, 1, 1, 1, 0.45, 1, 7.45058e-08, 1.19209e-07, 3.72529e-08, 0.0659214, -0.0866695, 0.0774413, 0.991033, 1, 1, 1, 0.5, 1, -5.96046e-08, 1.19209e-07, -1.11759e-07, 0.0031081, -0.0968864, 0.054063, 0.993821, 1, 1, 1, 0.55, 1, 5.96046e-08, 0, -6.70552e-08, -0.0166663, -0.0982007, 0.0374834, 0.994321, 1, 1, 1, 0.6, 1, 5.96046e-08, 1.19209e-07, -4.84288e-08, -0.0148445, -0.0906634, 0.0264974, 0.995418, 1, 1, 1, 0.65, 1, 0, 0, 4.09782e-08, -0.0108355, -0.0727448, 0.0177847, 0.997133, 1, 1, 1, 1, 1, 6.70552e-08, 0, 7.07805e-08, 0.00219189, 0.11394, -0.0230367, 0.993218, 1, 1, 1, 1.05, 1, 5.21541e-08, -1.19209e-07, 9.31323e-08, 0.00219921, 0.118787, -0.0237834, 0.992633, 1, 1, 1, 1.25, 1, 5.21541e-08, -1.19209e-07, 9.31323e-08, 0.00219921, 0.118787, -0.0237834, 0.992633, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="144"> 0, 1, 2.98023e-08, 2.98023e-08, 1.04308e-07, 0.217295, 0.0746597, -0.0103365, 0.973192, 1, 0.999999, 1, 0.05, 1, -8.9407e-08, 1.49012e-08, 1.49012e-08, 0.151772, 0.0624666, -0.00777083, 0.986409, 1, 1, 1, 0.1, 1, -2.98023e-08, 2.98023e-08, -8.9407e-08, -0.00391929, 0.0335048, -0.00214722, 0.999429, 1, 0.999999, 1, 0.3, 1, 0, 3.72529e-08, -1.49012e-07, -0.748933, -0.0405244, 0.0112371, 0.66131, 1, 1, 1, 0.35, 1, 5.96046e-08, 7.45058e-09, -3.12924e-07, -0.802758, -0.0149771, 0.00481471, 0.596097, 1, 1, 1, 0.4, 1, 0, 7.45058e-09, -1.78814e-07, -0.770121, 0.00992629, -0.000335305, 0.63782, 1, 1, 1, 0.8, 1, -5.96046e-08, 5.21541e-08, -1.04308e-07, 0.0878935, -0.0301616, 0.023494, 0.995396, 1, 1, 1, 0.85, 1, 2.98023e-08, 5.21541e-08, -2.98023e-07, 0.0819817, -0.0162162, 0.0156585, 0.996379, 1, 0.999999, 1, 0.9, 1, -5.96046e-08, 7.45058e-09, -1.3411e-07, 0.0980511, 0.00664153, 0.00756362, 0.99513, 1, 0.999999, 1, 1, 1, -5.96046e-08, 2.98023e-08, -2.98023e-08, 0.201153, 0.0660118, -0.00800331, 0.9773, 1, 0.999999, 1, 1.05, 1, 2.98023e-08, 2.98023e-08, 1.04308e-07, 0.217295, 0.0746597, -0.0103365, 0.973192, 1, 0.999999, 1, 1.25, 1, 2.98023e-08, 2.98023e-08, 1.04308e-07, 0.217295, 0.0746597, -0.0103365, 0.973192, 1, 0.999999, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="228"> 0, 1, 4.19095e-08, 1.41561e-07, 2.98023e-07, -0.33502, -0.0565195, 0.00376308, 0.940507, 1, 1, 1, 0.05, 1, 2.82889e-08, 1.86265e-07, 0, -0.412041, -0.0666523, 0.00293558, 0.908719, 1, 1, 1, 0.2, 1, -7.12462e-08, -1.2666e-07, 5.96046e-08, -0.831864, -0.10996, -0.00255585, 0.543972, 1, 1, 1, 0.25, 1, 2.32831e-09, -1.04308e-07, 5.96046e-08, 0.89602, 0.0970023, 0.00298318, -0.433277, 1, 1, 1, 0.3, 1, 1.9907e-08, 3.65078e-07, 2.98023e-07, 0.921569, 0.0590099, 0.00230107, -0.383696, 1, 1, 1, 0.35, 1, -8.28877e-08, -1.93715e-07, 2.38419e-07, 0.901128, 0.00554219, 0.000798309, -0.433517, 1, 1, 1, 0.4, 1, -7.53207e-08, 5.21541e-08, 1.19209e-07, -0.81758, 0.0439972, 0.000730356, 0.574132, 1, 1, 1, 0.5, 1, -2.91038e-09, 1.41561e-07, 2.38419e-07, -0.503688, 0.068707, 0.00074972, 0.861149, 1, 1, 1, 0.55, 1, 6.1933e-08, 8.19564e-08, 5.96046e-08, -0.352333, 0.0527461, -0.000239235, 0.934387, 1, 1, 1, 0.6, 1, -2.95695e-08, 1.04308e-07, 1.78814e-07, -0.244271, 0.03738, -0.00103017, 0.968986, 1, 1, 1, 0.65, 1, 9.54606e-09, 3.50177e-07, 1.78814e-07, -0.200824, 0.0283491, -0.00130918, 0.979216, 1, 1, 1, 0.7, 1, 2.01399e-08, 2.23517e-08, 0, -0.167963, 0.0193272, -0.0011918, 0.985603, 1, 1, 1, 0.75, 1, -2.47965e-08, -2.23517e-07, 1.19209e-07, -0.0847999, 0.00700657, -0.000838314, 0.996373, 1, 1, 1, 0.8, 1, -4.88944e-08, -7.45058e-09, 0, -0.073705, 0.000793342, 3.27131e-05, 0.99728, 1, 1, 1, 0.9, 1, -5.50644e-08, 0, 1.19209e-07, -0.297998, -0.0240387, 0.0012853, 0.954263, 1, 1, 1, 0.95, 1, -1.08266e-08, -2.98023e-08, 1.19209e-07, -0.340478, -0.0423349, 0.0021981, 0.939296, 1, 1, 1, 1, 1, 5.07571e-08, -1.63913e-07, 0, -0.339784, -0.0539663, 0.00332048, 0.938948, 1, 1, 1, 1.05, 1, 4.19095e-08, 1.41561e-07, 2.98023e-07, -0.33502, -0.0565195, 0.00376308, 0.940507, 1, 1, 1, 1.25, 1, 4.19095e-08, 1.41561e-07, 2.98023e-07, -0.33502, -0.0565195, 0.00376308, 0.940507, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="192"> 0, 1, -3.72529e-08, 0, 8.19564e-08, -0.0168517, 0.0989445, -0.0394225, 0.994169, 1, 1, 1, 0.05, 1, 6.70552e-08, 1.19209e-07, -4.47035e-08, -0.0168456, 0.0944203, -0.0381151, 0.99466, 1, 1, 1, 0.1, 1, 1.49012e-08, 1.19209e-07, -3.35276e-08, -0.0167772, 0.0819293, -0.034504, 0.995899, 1, 1, 1, 0.15, 1, -7.45058e-09, 1.19209e-07, -1.3411e-07, -0.0165494, 0.0617975, -0.0286797, 0.997539, 1, 1, 1, 0.4, 1, -2.23517e-08, 0, 2.6077e-08, -0.00864448, -0.0855905, 0.0141105, 0.996193, 1, 1, 1, 0.45, 1, 7.45058e-09, 2.38419e-07, -7.45058e-08, -0.00528641, -0.10464, 0.0196597, 0.994302, 1, 1, 1, 0.5, 1, -1.49012e-08, 1.19209e-07, 7.45058e-09, -0.00140908, -0.115976, 0.0229639, 0.992986, 1, 1, 1, 0.55, 1, 1.49012e-08, 2.38419e-07, 3.72529e-08, 0.00315788, -0.117918, 0.023482, 0.992741, 1, 1, 1, 0.6, 1, -2.98023e-08, 1.19209e-07, -1.49012e-08, 0.00993965, -0.108994, 0.0205203, 0.993781, 1, 1, 1, 0.65, 1, 1.49012e-08, 0, 1.86265e-08, 0.0206495, -0.0875135, 0.0140912, 0.99585, 1, 1, 1, 0.8, 1, -2.23517e-08, 1.19209e-07, -3.72529e-09, 0.0751354, 0.00445886, 0.00173853, 0.997162, 1, 1, 1, 0.9, 1, 0, 0, -2.98023e-08, 0.131833, 0.0617586, 0.0448617, 0.988329, 1, 1, 1, 0.95, 1, 3.72529e-08, 0, -6.70552e-08, 0.10712, 0.0825392, 0.0325464, 0.99028, 1, 1, 1, 1, 1, 1.49012e-08, 2.38419e-07, -4.84288e-08, 0.0202877, 0.0962194, -0.0179372, 0.994992, 1, 1, 1, 1.05, 1, -3.72529e-08, 0, 8.19564e-08, -0.0168517, 0.0989445, -0.0394225, 0.994169, 1, 1, 1, 1.25, 1, -3.72529e-08, 0, 8.19564e-08, -0.0168517, 0.0989445, -0.0394225, 0.994169, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="24"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="216"> 0, 1, -5.68434e-14, 0, 0.850875, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -5.68434e-14, 0, 0.888268, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, -5.68434e-14, 0, 0.982704, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.15, 1, -5.68434e-14, 0, 1.10101, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, -5.68434e-14, 0, 1.19526, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.25, 1, -5.68434e-14, 0, 1.23253, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, -5.68434e-14, 0, 1.20497, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.35, 1, -5.68434e-14, 0, 1.13278, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.45, 1, -5.68434e-14, 0, 0.935015, 0, 0, 0, 1, 1, 1, 1, 0.5, 1, -5.68434e-14, 0, 0.868188, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -5.68434e-14, 0, 0.85559, 0, 0, 0, 1, 1, 1, 1, 0.6, 1, -5.68434e-14, 0, 0.901897, 0, 0, 0, 1, 1, 1, 1, 0.75, 1, -5.68434e-14, 0, 1.20896, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -5.68434e-14, 0, 1.22782, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.85, 1, -5.68434e-14, 0, 1.18155, 0, 0, 0, 1, 1, 1, 1, 1, 1, -5.68434e-14, 0, 0.874524, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, -5.68434e-14, 0, 0.850875, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -5.68434e-14, 0, 0.850875, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="180"> 0, 1, -0.142338, -0.946415, 0.217759, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.142333, -0.853172, 0.14976, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, -0.142326, -0.626394, 0.0493819, 0, 0, 0, 1, 1, 1, 1, 0.25, 1, -0.142324, 0.323052, 0.113333, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.139402, 1.42157, 0.666575, 0, 0, 0, 1, 1, 1, 1, 0.5, 1, -0.136793, 1.55206, 0.805069, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -0.131841, 1.57295, 0.911952, 0, 0, 0, 1, 1, 1, 1, 0.6, 1, -0.113377, 1.47151, 1.00452, 0, 0, 0, 1, 1, 1, 1, 0.65, 1, -0.077946, 1.23249, 1.08549, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -0.0017584, 0.265596, 1.17195, 0, 0, 0, 1, 1, 1, 1, 0.85, 1, -0.0190262, -0.03908, 1.05516, 0, 0, 0, 1, 1, 1, 1, 0.95, 1, -0.100589, -0.692012, 0.50379, 0, 0, 0, 1, 1, 1, 1, 1, 1, -0.133542, -0.895383, 0.278588, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, -0.142338, -0.946415, 0.217759, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.142338, -0.946415, 0.217759, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="192"> 0, 1, 0.133965, 1.58294, 0.896163, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.120869, 1.49689, 0.924311, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, 0.0877482, 1.26696, 0.995435, 0, 0, 0, 1, 1, 1, 1, 0.25, 1, 0, 0.313476, 1.18387, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, 0.0102771, 0.0502403, 1.13241, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, 0.0744684, -0.535892, 0.782828, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, 0.110957, -0.769809, 0.54983, 0, 0, 0, 1, 1, 1, 1, 0.5, 1, 0.13588, -0.912113, 0.342608, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, 0.142337, -0.934969, 0.197995, 0, 0, 0, 1, 1, 1, 1, 0.6, 1, 0.142331, -0.819832, 0.0904105, 0, 0, 0, 1, 1, 1, 1, 0.65, 1, 0.142325, -0.584709, 0.0345853, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, 0.14222, 0.375652, 0.134472, 0, 0, 0, 1, 1, 1, 1, 0.95, 1, 0.136416, 1.34572, 0.707882, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0.134481, 1.53602, 0.857536, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, 0.133965, 1.58294, 0.896163, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.133965, 1.58294, 0.896163, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="192"> 0, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.098364, 0.655731, -0.762274, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.1, 1, 0.092555, 0.616937, -0.717148, 4.1297e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.15, 1, 0.0832335, 0.55472, -0.644792, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.4, 1, 0.0154476, 0.102931, -0.119635, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.45, 1, 0.00660282, 0.0440027, -0.051146, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.5, 1, 0.00131494, 0.00876498, -0.0101888, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, 0.000308841, 0.00205886, -0.00239307, 7.10993e-08, 6.08666e-15, -4.32757e-22, 1, 1, 1, 1, 0.6, 1, 0.00340915, 0.0227199, -0.0264083, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.65, 1, 0.0108188, 0.0720865, -0.0837842, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.7, 1, 0.0221942, 0.14786, -0.171845, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.9, 1, 0.0824287, 0.549322, -0.638501, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.95, 1, 0.0927294, 0.618084, -0.718475, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 1, 1, 0.0989292, 0.659501, -0.766658, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="192"> 0, 1, 2.98023e-08, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.00210956, 0.0140947, -0.0163979, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.1, 1, -0.00791863, 0.0528884, -0.0615235, 4.1297e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.15, 1, -0.0172402, 0.115105, -0.13388, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.4, 1, -0.085026, 0.566894, -0.659037, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.45, 1, -0.0938708, 0.625823, -0.727526, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.5, 1, -0.0991587, 0.66106, -0.768483, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -0.100165, 0.667766, -0.776279, 7.10993e-08, 6.08666e-15, -4.32757e-22, 1, 1, 1, 1, 0.6, 1, -0.0970645, 0.647105, -0.752263, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.65, 1, -0.0896548, 0.597739, -0.694888, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.7, 1, -0.0782794, 0.521965, -0.606827, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.9, 1, -0.0180449, 0.120504, -0.14017, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.95, 1, -0.00774428, 0.0517416, -0.0601966, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 1, 1, -0.00154439, 0.0103241, -0.0120134, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, 2.98023e-08, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 2.98023e-08, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="180"> 0, 1, -0.868295, -0.434147, -0.728793, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.894115, -0.429589, -0.685758, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -0.965105, -0.417039, -0.56775, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, -1.07881, -0.396902, -0.379345, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -1.9017, -0.250463, 0.973224, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -2.00893, -0.231348, 1.14912, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, -2.07309, -0.219917, 1.25447, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -2.08428, -0.222594, 1.27283, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.6, 1, -2.0356, -0.276793, 1.19246, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.65, 1, -1.92036, -0.39421, 1.00266, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.75, 1, -1.5939, -0.636021, 0.464508, 0, 0, 0, 1, 1, 1, 1, 0.95, 1, -0.989962, -0.50147, -0.527541, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1, 1, -0.8923, -0.448337, -0.688738, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, -0.868295, -0.434147, -0.728793, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.868295, -0.434147, -0.728793, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="180"> 0, 1, 2.08906, -0.217074, 1.28073, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 2.04863, -0.260861, 1.21323, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, 1.93875, -0.371377, 1.03141, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, 1.47813, -0.663608, 0.273554, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, 0.953814, -0.514624, -0.588262, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, 0.884829, -0.464922, -0.701557, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, 0.872045, -0.428974, -0.722627, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.6, 1, 0.909668, -0.39768, -0.660821, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.65, 1, 0.999508, -0.365756, -0.513451, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.7, 1, 1.13734, -0.334072, -0.287612, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.9, 1, 1.86856, -0.237138, 0.914287, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.95, 1, 1.99427, -0.225258, 1.12276, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1, 1, 2.07012, -0.218627, 1.24908, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, 2.08906, -0.217074, 1.28073, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 2.08906, -0.217074, 1.28073, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="192"> 0, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.429983, 0.0015192, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, 0.498118, 0.0057025, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, 0.607264, 0.0124156, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, 1.39747, 0.061233, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, 1.50046, 0.0676029, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, 1.56207, 0.0714109, 0, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, 1.5738, 0.0721354, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.6, 1, 1.53767, 0.0699027, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.65, 1, 1.45139, 0.0645664, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.7, 1, 1.31902, 0.0563741, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.9, 1, 0.616836, 0.0129952, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.95, 1, 0.496168, 0.00557709, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1, 1, 0.423375, 0.00111222, 0, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="192"> 0, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -1.55262, 0.0708387, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -1.48449, 0.0666554, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, -1.37534, 0.0599422, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -0.585136, 0.0111248, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.482148, 0.00475502, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, -0.420538, 0.000946999, 0, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -0.408805, 0.000222445, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.6, 1, -0.444934, 0.00245523, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.65, 1, -0.531212, 0.00779152, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.7, 1, -0.663587, 0.0159838, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.9, 1, -1.36577, 0.0593629, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.95, 1, -1.48644, 0.0667808, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 1, 1, -1.55923, 0.0712457, 0, 0, 0, 0, 1, 1, 1, 1, 1.05, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="276"> 0, 1, 0.0502379, 0.036174, 0.108012, 7.74552e-15, -1.97402e-08, 0.0871557, 0.996195, 1, 1, 1, 0.05, 1, 0.0469382, 0.0509099, 0.094259, -3.35906e-14, -1.89171e-08, 0.0835209, 0.996506, 1, 1, 1, 0.1, 1, 0.0379226, 0.088175, 0.0594788, -4.57539e-14, -1.66467e-08, 0.0734954, 0.997296, 1, 1, 1, 0.15, 1, 0.0249111, 0.134917, 0.0158529, -3.14989e-14, -1.29934e-08, 0.0573644, 0.998353, 1, 1, 1, 0.2, 1, 0.0112907, 0.17217, -0.0189178, -1.3373e-14, -8.15547e-09, 0.0360035, 0.999352, 1, 1, 1, 0.25, 1, 2.27588e-08, 0.186899, -0.0326645, -1.50375e-14, -2.49281e-09, 0.0110021, 0.99994, 1, 1, 1, 0.3, 1, -0.0104418, 0.176016, -0.0225072, -7.05369e-14, 3.45387e-09, -0.0152525, 0.999884, 1, 1, 1, 0.35, 1, -0.0222285, 0.147506, 0.00410175, -3.23609e-14, 9.01354e-09, -0.039798, 0.999208, 1, 1, 1, 0.4, 1, -0.0338161, 0.108041, 0.0409362, -3.84007e-14, 1.36964e-08, -0.0604725, 0.99817, 1, 1, 1, 0.45, 1, -0.043192, 0.0694027, 0.0769985, -3.85801e-14, 1.71613e-08, -0.0757699, 0.997125, 1, 1, 1, 0.5, 1, -0.0488776, 0.0430113, 0.10163, -7.13117e-15, 1.92273e-08, -0.084891, 0.99639, 1, 1, 1, 0.55, 1, -0.049846, 0.0380361, 0.106274, -6.66418e-14, 1.96198e-08, -0.0866238, 0.996241, 1, 1, 1, 0.6, 1, -0.0458462, 0.0563236, 0.0892055, -1.43694e-14, 1.84095e-08, -0.0812805, 0.996691, 1, 1, 1, 0.65, 1, -0.0363638, 0.0959547, 0.0522163, -5.40282e-14, 1.5511e-08, -0.0684838, 0.997652, 1, 1, 1, 0.7, 1, -0.0231681, 0.1427, 0.0085876, -3.25683e-14, 1.10473e-08, -0.0487772, 0.99881, 1, 1, 1, 0.75, 1, -0.00951665, 0.177588, -0.0239747, 1.83932e-15, 5.34013e-09, -0.0235807, 0.999722, 1, 1, 1, 0.8, 1, 0.00190332, 0.185037, -0.0309267, -4.07805e-14, -1.06814e-09, 0.00471147, 0.999989, 1, 1, 1, 0.85, 1, 0.0140465, 0.166752, -0.0138602, -8.20187e-14, -7.29738e-09, 0.0322142, 0.999481, 1, 1, 1, 0.9, 1, 0.0278208, 0.127127, 0.0231235, -3.37482e-14, -1.26773e-08, 0.0559684, 0.998433, 1, 1, 1, 0.95, 1, 0.0402532, 0.080384, 0.0667505, -4.05783e-14, -1.67149e-08, 0.0737966, 0.997273, 1, 1, 1, 1, 1, 0.0482781, 0.0454891, 0.0993183, 1.00279e-15, -1.91378e-08, 0.0844954, 0.996424, 1, 1, 1, 1.05, 1, 0.0502379, 0.036174, 0.108012, 7.74552e-15, -1.97402e-08, 0.0871557, 0.996195, 1, 1, 1, 1.25, 1, 0.0502379, 0.036174, 0.108012, 7.74552e-15, -1.97402e-08, 0.0871557, 0.996195, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="192"> 0, 1, 4.1909e-09, -2.55596e-10, -3.57628e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1, 0.05, 1, 3.53838e-09, 6.53649e-11, -5.96046e-08, 0.0550183, -0.0046113, -0.0833935, 0.994986, 1, 1, 1, 0.1, 1, -5.60775e-10, -7.51698e-09, -2.98023e-08, 0.0550619, -0.00405785, -0.0733833, 0.995774, 1, 1, 1, 0.15, 1, -2.23866e-09, -1.11867e-08, -1.49012e-07, 0.0551203, -0.00316731, -0.0572769, 0.996831, 1, 1, 1, 0.4, 1, -2.04997e-09, -2.75862e-09, 1.78814e-07, 0.0551102, 0.00333869, 0.0603803, 0.996647, 1, 1, 1, 0.45, 1, 2.0486e-09, 4.35754e-10, 5.96046e-08, 0.0550525, 0.00418331, 0.0756543, 0.995605, 1, 1, 1, 0.5, 1, -5.1223e-09, 2.12108e-09, 1.19209e-07, 0.0550119, 0.00468692, 0.0847616, 0.994871, 1, 1, 1, 0.55, 1, 9.31448e-11, -6.0701e-10, 0, 0.0550037, 0.00478259, 0.0864917, 0.994722, 1, 1, 1, 0.6, 1, -8.38328e-10, -2.70165e-09, 0, 0.0550285, 0.00448757, 0.0811565, 0.995171, 1, 1, 1, 0.65, 1, -5.5956e-10, 2.044e-09, 2.98023e-08, 0.0550816, 0.00378102, 0.0683793, 0.996131, 1, 1, 1, 0.7, 1, -1.88318e-10, -1.00538e-08, -1.49012e-07, 0.0551455, 0.00269294, 0.0487028, 0.997286, 1, 1, 1, 0.9, 1, -2.42557e-09, -9.9462e-09, 1.19209e-07, 0.0551247, -0.00309027, -0.055883, 0.99691, 1, 1, 1, 0.95, 1, 2.79174e-09, -8.13951e-09, 0, 0.0550607, -0.00407449, -0.073684, 0.995752, 1, 1, 1, 1, 1, -4.66262e-10, 1.71346e-09, 0, 0.0550138, -0.0046651, -0.0843665, 0.994904, 1, 1, 1, 1.05, 1, 4.1909e-09, -2.55596e-10, -3.57628e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1, 1.25, 1, 4.1909e-09, -2.55596e-10, -3.57628e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="192"> 0, 1, 4.20218e-09, -1.49012e-08, 0, 0.0550026, -0.0108562, -0.086477, 0.994675, 1, 1, 1, 0.05, 1, 6.60681e-10, -7.45058e-09, -5.96046e-08, 0.0550197, -0.0104035, -0.0828704, 0.994986, 1, 1, 1, 0.1, 1, 1.42138e-09, -7.45058e-09, 1.19209e-07, 0.0550633, -0.00915483, -0.072923, 0.995774, 1, 1, 1, 0.15, 1, -1.4402e-10, -1.86265e-08, -5.96046e-08, 0.0551217, -0.00714571, -0.0569177, 0.99683, 1, 1, 1, 0.4, 1, -2.54046e-09, 7.45058e-09, -1.78814e-07, 0.0551116, 0.00753235, 0.0600015, 0.996647, 1, 1, 1, 0.45, 1, -2.31643e-09, 1.86265e-08, -1.78814e-07, 0.0550539, 0.00943788, 0.0751797, 0.995604, 1, 1, 1, 0.5, 1, -3.16026e-09, 1.49012e-08, 5.96046e-08, 0.0550134, 0.0105741, 0.0842299, 0.99487, 1, 1, 1, 0.55, 1, -4.35034e-09, 2.23517e-08, -1.78814e-07, 0.0550051, 0.0107899, 0.0859492, 0.994722, 1, 1, 1, 0.6, 1, -1.53961e-09, -7.45058e-09, 5.96046e-08, 0.05503, 0.0101243, 0.0806475, 0.995171, 1, 1, 1, 0.65, 1, -1.47879e-09, -1.86265e-08, -5.96046e-08, 0.055083, 0.00853027, 0.0679504, 0.996131, 1, 1, 1, 0.7, 1, -2.07954e-09, 2.6077e-08, -2.38419e-07, 0.0551469, 0.00607548, 0.0483973, 0.997286, 1, 1, 1, 0.9, 1, -1.29246e-09, -2.6077e-08, 5.96046e-08, 0.0551261, -0.00697189, -0.0555325, 0.99691, 1, 1, 1, 0.95, 1, 2.48766e-09, -7.45058e-09, 5.96046e-08, 0.0550621, -0.00919238, -0.0732219, 0.995752, 1, 1, 1, 1, 1, -1.94411e-09, -7.45058e-09, -1.19209e-07, 0.0550152, -0.0105248, -0.0838373, 0.994904, 1, 1, 1, 1.05, 1, 4.20218e-09, -1.49012e-08, 0, 0.0550026, -0.0108562, -0.086477, 0.994675, 1, 1, 1, 1.25, 1, 4.20218e-09, -1.49012e-08, 0, 0.0550026, -0.0108562, -0.086477, 0.994675, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="24"> 0, 1, 1.58195e-10, -1.19209e-07, -8.34465e-07, -1.49012e-08, 2.17021e-10, 8.15234e-10, 1, 1, 1, 1, 1.25, 1, 1.58195e-10, -1.19209e-07, -8.34465e-07, -1.49012e-08, 2.17021e-10, 8.15234e-10, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="144"> 0, 1, 8.86136e-10, -2.38419e-07, -4.91273e-08, 0.0549542, -0.0952446, 0.00487296, 0.993924, 1, 1, 1, 0.05, 1, 2.18506e-09, -1.78814e-07, -5.65778e-08, 0.0504772, -0.0912067, 0.0042631, 0.994543, 1, 1, 1, 0.1, 1, 5.53928e-10, -4.17233e-07, -3.67872e-08, 0.0390059, -0.0800384, 0.00284171, 0.996024, 1, 1, 1, 0.45, 1, -5.1797e-09, -8.04663e-07, -5.82077e-08, 0.0448447, 0.08285, -0.00340957, 0.995547, 1, 1, 1, 0.5, 1, 3.73723e-09, 3.57628e-07, -5.28526e-08, 0.052893, 0.0927872, -0.00455309, 0.99427, 1, 1, 1, 0.55, 1, 3.81474e-09, -2.98023e-08, -4.30737e-08, 0.0543919, 0.0946615, -0.00479041, 0.994011, 1, 1, 1, 0.6, 1, 5.97727e-09, -1.01328e-06, -7.35745e-08, 0.0488359, 0.0887913, -0.00401032, 0.994844, 1, 1, 1, 0.65, 1, -3.89822e-10, -6.25849e-07, -7.96281e-08, 0.0366099, 0.0746935, -0.00247956, 0.996531, 1, 1, 1, 0.95, 1, -4.46247e-09, 1.19209e-07, -6.96164e-08, 0.0414353, -0.080551, 0.00304791, 0.995884, 1, 1, 1, 1, 1, 2.64143e-09, -5.96046e-07, -7.72998e-08, 0.052136, -0.0923283, 0.0044599, 0.994353, 1, 1, 1, 1.05, 1, 8.86136e-10, -2.38419e-07, -4.91273e-08, 0.0549542, -0.0952446, 0.00487296, 0.993924, 1, 1, 1, 1.25, 1, 8.86136e-10, -2.38419e-07, -4.91273e-08, 0.0549542, -0.0952446, 0.00487296, 0.993924, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="24"> 0, 1, -3.08853e-09, 1.69966e-08, 3.98955e-07, 4.70848e-20, -1.3217e-10, -5.67425e-10, 1, 1, 1, 1, 1.25, 1, -3.08853e-09, 1.69966e-08, 3.98955e-07, 4.70848e-20, -1.3217e-10, -5.67425e-10, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="24"> 0, 1, 5.17831e-08, 0.00292331, 0.204329, 3.25963e-09, -2.17324e-11, 3.00563e-10, 1, 1, 1, 1, 1.25, 1, 5.17831e-08, 0.00292331, 0.204329, 3.25963e-09, -2.17324e-11, 3.00563e-10, 1, 1, 1, 1 </real_array>
-
- </resource>
- <resource type="Animation" path="local://13">
- <string name="resource/name"> "run-cycle" </string>
- <real name="length"> 0.833333 </real>
- <bool name="loop"> True </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="192"> 0, 1, 9.23872e-07, -3.57628e-07, 5.66244e-07, 0.222344, -0.226466, -0.0274315, 0.947905, 1, 1, 1, 0.05, 1, 6.55651e-07, -1.19209e-07, 2.98023e-07, 0.251975, -0.208305, -0.0408158, 0.944167, 1, 1, 1, 0.15, 1, 1.07288e-06, -3.57628e-07, 5.36442e-07, 0.379887, -0.057225, -0.102903, 0.917509, 1, 1, 1, 0.2, 1, 6.25849e-07, -3.57628e-07, 7.45058e-07, 0.418674, -0.00696497, -0.113328, 0.901011, 1, 1, 1, 0.25, 1, 8.64267e-07, -3.57628e-07, 3.8743e-07, 0.413182, 0.0386478, -0.0801881, 0.906287, 1, 1, 1, 0.3, 1, 9.53674e-07, -4.76837e-07, 5.96046e-07, 0.315261, 0.124735, -0.0152523, 0.940648, 1, 1, 1, 0.4, 1, 6.25849e-07, -3.57628e-07, 4.17233e-07, -0.151881, 0.360683, -0.0357324, 0.919545, 1, 1, 0.999999, 0.45, 1, 6.25849e-07, -3.57628e-07, 7.45058e-07, -0.172392, 0.343529, -0.046079, 0.922034, 1, 1, 0.999999, 0.55, 1, 6.55651e-07, -3.57628e-07, 5.36442e-07, 0.168352, 0.0191591, -0.0776353, 0.982478, 1, 1, 1, 0.6, 1, 9.53674e-07, -3.57628e-07, 3.27826e-07, 0.182793, -0.0233152, -0.109476, 0.976759, 1, 1, 1, 0.65, 1, 4.17233e-07, 0, 1.78814e-07, 0.138039, -0.0157468, -0.121765, 0.982787, 1, 1, 1, 0.7, 1, 6.25849e-07, -2.38419e-07, 1.78814e-07, 0.121673, -0.0809579, -0.109793, 0.983152, 1, 1, 1, 0.75, 1, 9.23872e-07, -3.57628e-07, 7.45058e-07, 0.131274, -0.176942, -0.0767055, 0.972407, 1, 1, 1, 0.8, 1, 5.66244e-07, -1.19209e-07, 5.96046e-07, 0.13073, -0.218021, -0.0501677, 0.965847, 1, 1, 1, 0.85, 1, 2.98023e-08, 0, -5.96046e-08, 0.129118, -0.224691, -0.0428281, 0.964888, 1, 1, 1, 1.25, 1, 2.98023e-08, 0, -5.96046e-08, 0.129118, -0.224691, -0.0428281, 0.964888, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="180"> 0, 1, 0, -4.17233e-07, -3.57628e-07, -0.0379169, -0.0715942, 0.00193508, 0.996711, 1, 1, 1, 0.05, 1, -1.78814e-07, -5.96046e-07, -4.17233e-07, -0.000241383, -0.109076, 0.00379063, 0.994026, 1, 1, 1, 0.1, 1, 8.9407e-08, -6.55651e-07, -6.55651e-07, 0.0679255, -0.167209, 0.00334064, 0.983573, 1, 0.999999, 1, 0.25, 1, -1.19209e-07, -3.8743e-07, 0, 0.158727, -0.350464, 0.00627285, 0.923007, 1, 1, 1, 0.3, 1, -3.27826e-07, -6.85453e-07, 1.78814e-07, 0.146536, -0.393807, 0.00119701, 0.907437, 1, 1, 1, 0.35, 1, -8.9407e-08, -6.55651e-07, -3.57628e-07, 0.153485, -0.416977, -0.0128296, 0.895772, 1, 1, 1, 0.4, 1, 8.9407e-08, -9.83477e-07, -5.36442e-07, 0.172873, -0.368078, -0.014432, 0.913469, 1, 0.999999, 1, 0.45, 1, 0, -9.83477e-07, -1.19209e-07, 0.191151, -0.391536, -0.0140892, 0.899979, 1, 1, 1, 0.5, 1, 8.9407e-08, -5.96046e-07, -6.55651e-07, 0.210133, -0.527231, -0.0202225, 0.823081, 1, 1, 1, 0.55, 1, 2.68221e-07, -6.25849e-07, -4.17233e-07, 0.159334, -0.589231, -0.00909611, 0.792046, 1, 1, 1, 0.65, 1, -1.19209e-07, -6.85453e-07, -7.15256e-07, 0.0168538, -0.43832, 0.0104639, 0.8986, 1, 1, 1, 0.7, 1, 1.78814e-07, -5.36442e-07, -1.78814e-07, -0.00524541, -0.376783, 0.0174757, 0.926122, 1, 1, 1, 0.8, 1, -5.96046e-08, -7.15256e-07, -5.36442e-07, 0.00762745, -0.243737, 0.014512, 0.969703, 1, 1, 1, 0.85, 1, 1.19209e-07, -6.85453e-07, -7.7486e-07, 0.00858928, -0.221202, 0.0126834, 0.975108, 1, 1, 1, 1.25, 1, 1.19209e-07, -6.85453e-07, -7.7486e-07, 0.00858928, -0.221202, 0.0126834, 0.975108, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="228"> 0, 1, -9.53674e-07, -5.96046e-07, 4.76837e-07, -0.211109, -0.378307, 0.04716, 0.900052, 1, 1, 1, 0.05, 1, -9.53674e-07, 1.19209e-07, 3.57628e-07, -0.122361, -0.307485, 0.0444022, 0.942608, 1, 1, 1, 0.1, 1, -6.85453e-07, -2.38419e-07, 5.96046e-07, 0.0655243, -0.124344, 0.0558387, 0.988497, 1, 1, 1, 0.15, 1, -7.7486e-07, -1.19209e-07, 5.66244e-07, 0.17223, 0.0168325, 0.088774, 0.980904, 1, 1, 1, 0.2, 1, -5.36442e-07, -3.57628e-07, 5.36442e-07, 0.151153, 0.0193605, 0.111763, 0.981981, 1, 1, 1, 0.25, 1, -6.25849e-07, -3.57628e-07, 5.96046e-07, 0.105831, 0.0199286, 0.119921, 0.986925, 1, 1, 1, 0.3, 1, -1.19209e-06, -5.96046e-07, 6.25849e-07, 0.11, 0.117841, 0.0973986, 0.982103, 1, 1, 1, 0.35, 1, -5.36442e-07, -1.19209e-07, 4.47035e-07, 0.163427, 0.213955, 0.0590648, 0.961263, 1, 1, 1, 0.4, 1, -6.85453e-07, -3.57628e-07, 5.06639e-07, 0.212517, 0.23167, 0.0327435, 0.948733, 1, 1, 1, 0.45, 1, -8.04663e-07, -2.38419e-07, 5.66244e-07, 0.240572, 0.207043, 0.0320326, 0.947751, 1, 1, 1, 0.5, 1, -9.23872e-07, 0, 8.04663e-07, 0.292283, 0.151342, 0.0529747, 0.942794, 1, 1, 1, 0.55, 1, -6.85453e-07, -3.57628e-07, 3.57628e-07, 0.354424, 0.0696654, 0.0852169, 0.928584, 1, 1, 1, 0.6, 1, -5.66244e-07, -2.38419e-07, 2.98023e-07, 0.397207, 0.0175472, 0.104303, 0.911614, 1, 1, 1, 0.65, 1, -8.34465e-07, -2.38419e-07, 4.47035e-07, 0.407225, -0.0166533, 0.0875941, 0.908965, 1, 1, 1, 0.7, 1, -1.2517e-06, -1.19209e-07, 6.55651e-07, 0.349327, -0.0813931, 0.0308211, 0.93295, 1, 1, 1, 0.75, 1, -1.19209e-07, 1.19209e-07, 2.08616e-07, 0.214708, -0.14004, -0.012317, 0.966508, 1, 1, 1, 0.8, 1, -6.55651e-07, -1.19209e-07, 2.98023e-07, -0.00140518, -0.171137, -0.0177305, 0.985087, 1, 1, 1, 0.85, 1, -4.76837e-07, -3.57628e-07, 3.8743e-07, -0.0925096, -0.171599, -0.011185, 0.98075, 1, 1, 1, 1.25, 1, -4.76837e-07, -3.57628e-07, 3.8743e-07, -0.0925096, -0.171599, -0.011185, 0.98075, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="180"> 0, 1, 2.08616e-07, -2.98023e-08, -5.96046e-07, 0.176871, 0.346752, 0.0115369, 0.921058, 1, 1, 1, 0.05, 1, -1.49012e-07, -4.76837e-07, -2.38419e-07, 0.1969, 0.431458, 0.0161118, 0.880236, 1, 1, 1, 0.1, 1, -3.57628e-07, -8.04663e-07, -4.76837e-07, 0.196923, 0.556224, 0.0152519, 0.80722, 1, 1, 1, 0.15, 1, -2.68221e-07, -4.17233e-07, -2.98023e-07, 0.134905, 0.568169, 0.00154346, 0.811777, 1, 1, 1, 0.2, 1, -1.49012e-07, -6.25849e-07, -4.17233e-07, 0.0562878, 0.484209, -0.00707307, 0.873111, 1, 1, 1, 0.25, 1, -2.98023e-08, -8.04663e-07, -3.57628e-07, 0.0047636, 0.406038, -0.0121859, 0.913763, 1, 1, 1, 0.3, 1, 5.96046e-08, -7.7486e-07, -1.78814e-07, -0.011494, 0.345751, -0.0179636, 0.938084, 1, 0.999999, 1, 0.4, 1, 5.36442e-07, -5.36442e-07, -1.19209e-07, -0.0325058, 0.107107, -0.00429871, 0.993707, 1, 0.999999, 1, 0.45, 1, 2.08616e-07, -8.34465e-07, -1.78814e-07, -0.0177273, 0.0767786, -0.00241131, 0.996888, 1, 1, 1, 0.65, 1, -5.96046e-08, -6.55651e-07, -1.07288e-06, 0.154364, 0.318848, -0.0046877, 0.935139, 1, 1, 1, 0.7, 1, 5.96046e-08, -9.23872e-07, -1.01328e-06, 0.155566, 0.376204, -0.00401138, 0.913375, 1, 1, 1, 0.75, 1, 0, -8.9407e-07, -4.17233e-07, 0.173064, 0.444685, 0.00561718, 0.87879, 1, 1, 1, 0.8, 1, 3.27826e-07, -6.55651e-07, -4.17233e-07, 0.251551, 0.464674, 0.00544377, 0.848982, 1, 1, 1, 0.85, 1, 8.9407e-08, -7.15256e-07, -9.53674e-07, 0.280639, 0.447823, -0.00246765, 0.848935, 1, 1, 1, 1.25, 1, 8.9407e-08, -7.15256e-07, -9.53674e-07, 0.280639, 0.447823, -0.00246765, 0.848935, 1, 1, 1 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="192"> 0, 1, 0, 1.63913e-07, 1.93715e-07, -0.283345, 0.0300071, -0.0426225, 0.957601, 1, 1, 1, 0.05, 1, 8.9407e-08, 1.93715e-07, -5.06639e-07, -0.221388, 0.0587497, -0.0627932, 0.971387, 1, 1, 1, 0.15, 1, 5.96046e-08, 6.70552e-08, -1.3411e-07, 0.127996, 0.137739, -0.113256, 0.975612, 1, 1, 1, 0.2, 1, -5.96046e-08, -7.45058e-09, -7.45058e-07, 0.264976, 0.121823, -0.100248, 0.951261, 1, 1, 1, 0.25, 1, 2.98023e-08, -2.01166e-07, -4.91738e-07, 0.314522, 0.0998354, -0.077727, 0.94078, 1, 1, 1, 0.3, 1, 1.49012e-07, 1.3411e-07, 1.3411e-07, 0.306548, 0.0507913, -0.0454783, 0.949411, 1, 1, 1, 0.35, 1, 8.9407e-08, 7.45058e-09, -2.83122e-07, 0.297828, -0.0187708, -0.0207563, 0.954209, 1, 1, 1, 0.4, 1, 8.9407e-08, 4.47035e-08, -2.98023e-07, 0.287784, -0.0733564, -0.00467344, 0.95487, 1, 1, 1, 0.45, 1, 2.98023e-08, 2.23517e-08, -2.5332e-07, 0.170166, -0.0854042, 0.00266015, 0.981704, 1, 1, 1, 0.6, 1, 0, 1.04308e-07, 0, -0.531982, -0.0722138, 0.0220251, 0.843383, 1, 1, 1, 0.65, 1, 0, 1.3411e-07, -3.12924e-07, -0.652152, -0.0747176, 0.0102306, 0.754328, 1, 1, 1, 0.7, 1, -2.98023e-08, 0, 1.49012e-07, -0.686637, -0.0649825, 0.00231536, 0.724087, 1, 1, 1, 0.75, 1, 2.98023e-08, -1.56462e-07, -2.38419e-07, -0.638385, -0.0394346, -0.00259775, 0.768702, 1, 1, 1, 0.8, 1, 1.49012e-07, -8.9407e-08, -1.93715e-07, -0.432358, 0.00843852, -0.0248422, 0.90132, 1, 1, 1, 0.85, 1, 0, 1.63913e-07, 1.93715e-07, -0.283345, 0.0300071, -0.0426225, 0.957601, 1, 1, 1, 1.25, 1, 0, 1.63913e-07, 1.93715e-07, -0.283345, 0.0300071, -0.0426225, 0.957601, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="216"> 0, 1, 2.29338e-08, 8.9407e-08, 5.36442e-07, -0.369097, -0.0505305, 0.00260278, 0.928013, 1, 1, 1, 0.05, 1, 8.26549e-08, 1.93715e-07, 4.76837e-07, -0.32656, -0.0387365, 0.00230976, 0.94438, 1, 1, 1, 0.15, 1, 4.78467e-08, -7.45058e-09, 7.7486e-07, -0.04833, 0.013837, -0.00331139, 0.99873, 1, 1, 1, 0.2, 1, 1.44588e-07, 0, 7.15256e-07, 0.0174433, 0.00914093, -0.00369525, 0.999799, 1, 1, 1, 0.25, 1, 4.49363e-08, 1.63913e-07, 2.38419e-07, -0.0309752, 0.0174032, -0.00233819, 0.999366, 1, 1, 1, 0.3, 1, 6.06524e-08, -7.45058e-08, 6.55651e-07, -0.161344, 0.031869, -0.00095907, 0.986383, 1, 1, 1, 0.35, 1, 6.23986e-08, 1.11759e-07, 5.36442e-07, -0.258604, 0.043227, -0.000463765, 0.965016, 1, 1, 1, 0.4, 1, 2.66591e-08, 1.11759e-07, 5.96046e-07, -0.311843, 0.0531668, -0.000274837, 0.948645, 1, 1, 1, 0.45, 1, -0.000736501, 0.00352155, -0.0507002, -0.471618, 0.0737067, 0.000546333, 0.878717, 1, 1, 1, 0.5, 1, -0.00351399, 0.0168005, -0.241486, -0.74573, 0.0999092, 7.49679e-05, 0.658714, 1, 1, 1, 0.55, 1, -0.00736267, 0.0352004, -0.505227, 0.896291, -0.0831834, 0.00513814, -0.435565, 1, 1, 1, 0.6, 1, -0.0098056, 0.0468799, -0.672563, 0.946677, -0.0409485, 0.00588309, -0.319519, 1, 1, 1, 0.65, 1, -0.0098056, 0.0468801, -0.672652, 0.947809, 0.0057637, 0.00256107, -0.318776, 1, 1, 1, 0.7, 1, -0.00736268, 0.0352004, -0.505962, 0.888767, 0.0669386, 0.000245982, -0.453445, 1, 1, 1, 0.75, 1, -0.003514, 0.016801, -0.242868, -0.757574, -0.0924392, -0.000540428, 0.64617, 1, 1, 1, 0.8, 1, -0.000736581, 0.0035219, -0.0512407, -0.527405, -0.0678553, 0.00109702, 0.846899, 1, 1, 1, 0.85, 1, 2.29338e-08, 8.9407e-08, 5.36442e-07, -0.369097, -0.0505305, 0.00260278, 0.928013, 1, 1, 1, 1.25, 1, 2.29338e-08, 8.9407e-08, 5.36442e-07, -0.369097, -0.0505305, 0.00260278, 0.928013, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="216"> 0, 1, 1.49012e-08, 0, -5.21541e-08, 0.163945, 0.140221, -0.046324, 0.975354, 1, 1, 1, 0.05, 1, 9.68575e-08, 0, 7.82311e-08, 0.163142, 0.147087, -0.0386578, 0.974811, 1, 1, 1, 0.1, 1, 7.45058e-08, 0, 1.11759e-08, 0.154504, 0.157524, -0.0272069, 0.974974, 1, 1, 1, 0.15, 1, 8.9407e-08, 0, 3.72529e-08, 0.106593, 0.145246, -0.0455539, 0.982581, 1, 1, 1, 0.2, 1, 3.72529e-08, 0, 0, 0.00306457, 0.0975244, -0.0887594, 0.991263, 1, 1, 1, 0.3, 1, 4.47035e-08, 1.19209e-07, -1.60187e-07, -0.165764, -0.00244496, -0.0619073, 0.984217, 1, 1, 1, 0.35, 1, 3.72529e-08, -1.19209e-07, -1.2666e-07, -0.225564, -0.0444232, -0.0320188, 0.972688, 1, 1, 1, 0.4, 1, -2.98023e-08, -1.19209e-07, 1.3411e-07, -0.254966, -0.0644888, -0.0152293, 0.964677, 1, 1, 1, 0.45, 1, 5.96046e-08, 1.19209e-07, -3.72529e-09, -0.263415, -0.0674915, -0.0129876, 0.962231, 1, 1, 1, 0.5, 1, 7.45058e-08, 0, -2.98023e-08, -0.26682, -0.065605, -0.0157537, 0.961382, 1, 1, 1, 0.55, 1, 5.96046e-08, 0, 3.35276e-08, -0.268414, -0.0578826, -0.0205736, 0.961343, 1, 1, 1, 0.6, 1, 2.23517e-08, -1.19209e-07, 1.49012e-07, -0.268984, -0.0431783, -0.0254932, 0.961839, 1, 1, 1, 0.65, 1, 3.72529e-08, 0, -1.11759e-08, -0.205247, -0.0144598, -0.0301062, 0.97814, 1, 1, 1, 0.7, 1, 7.45058e-08, -1.19209e-07, -5.58794e-08, 0.0302446, 0.0427142, -0.0345553, 0.998031, 1, 1, 1, 0.75, 1, 8.9407e-08, 0, -1.11759e-07, 0.187052, 0.0967062, -0.0379775, 0.97684, 1, 1, 1, 0.8, 1, 8.19564e-08, -1.19209e-07, 2.23517e-08, 0.173053, 0.130372, -0.0438442, 0.975261, 1, 1, 1, 0.85, 1, 1.49012e-08, 0, -5.21541e-08, 0.163945, 0.140221, -0.046324, 0.975354, 1, 1, 1, 1.25, 1, 1.49012e-08, 0, -5.21541e-08, 0.163945, 0.140221, -0.046324, 0.975354, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="204"> 0, 1, 0, 2.08616e-07, 1.49012e-08, 0.284249, 0.0874448, 0.000525696, 0.954754, 1, 1, 1, 0.05, 1, 0, 1.11759e-07, -1.63913e-07, 0.0840381, 0.068345, -0.00156289, 0.994115, 1, 1, 1, 0.15, 1, 0, -9.68575e-08, -1.19209e-07, -0.428198, 0.103089, -0.0309307, 0.897253, 1, 1, 1, 0.2, 1, 2.98023e-08, 0, -2.5332e-07, -0.585268, 0.121806, -0.0264258, 0.801203, 1, 1, 1, 0.25, 1, -5.96046e-08, -2.68221e-07, -1.93715e-07, -0.68271, 0.117151, -0.00691618, 0.721203, 1, 1, 1, 0.3, 1, 5.96046e-08, 5.21541e-08, 3.57628e-07, -0.675843, 0.0951763, -0.00368054, 0.730865, 1, 1, 1, 0.35, 1, -5.96046e-08, -8.9407e-08, -1.04308e-07, -0.577504, 0.0522321, 0.00297164, 0.81471, 1, 1, 1, 0.4, 1, 0, 7.45058e-09, 1.63913e-07, -0.36481, -0.00958558, 0.0300626, 0.930547, 1, 1, 1, 0.45, 1, -1.19209e-07, 7.45058e-08, 1.49012e-07, -0.214962, -0.0628985, 0.0719756, 0.971933, 1, 1, 1, 0.5, 1, 0, 7.45058e-09, -7.15256e-07, -0.0924244, -0.113076, 0.110988, 0.983033, 1, 1, 1, 0.6, 1, 2.98023e-08, 3.72529e-08, 7.30157e-07, 0.212199, -0.104928, 0.0711089, 0.968971, 1, 1, 1, 0.65, 1, 8.9407e-08, 1.49012e-08, -1.63913e-07, 0.280374, -0.0786743, 0.0551762, 0.955069, 1, 1, 1, 0.7, 1, 0, 1.11759e-07, 2.5332e-07, 0.288443, -0.0349057, 0.033278, 0.956282, 1, 1, 1, 0.75, 1, -2.98023e-08, -1.3411e-07, -6.85453e-07, 0.285487, 0.0289713, 0.0136411, 0.957847, 1, 1, 1, 0.8, 1, -5.96046e-08, 8.9407e-08, -3.27826e-07, 0.284867, 0.0752772, 0.00313844, 0.955602, 1, 1, 1, 0.85, 1, 0, 2.08616e-07, 1.49012e-08, 0.284249, 0.0874448, 0.000525696, 0.954754, 1, 1, 1, 1.25, 1, 0, 2.08616e-07, 1.49012e-08, 0.284249, 0.0874448, 0.000525696, 0.954754, 1, 1, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="216"> 0, 1, -6.98492e-10, -2.98023e-08, 4.76837e-07, -0.32359, -0.0556479, 0.000232734, 0.94456, 1, 1, 1, 0.05, 1, 0.0014394, 0.00688202, -0.0998148, -0.562955, -0.0817876, -0.000658042, 0.82243, 1, 1, 1, 0.1, 1, 0.00484604, 0.0231691, -0.333955, -0.80836, -0.0993527, 0.00161956, 0.580241, 1, 1, 1, 0.15, 1, 0.00839999, 0.04016, -0.576718, 0.916395, 0.0904963, -0.00581601, -0.389867, 1, 1, 1, 0.2, 1, 0.010174, 0.048641, -0.697832, 0.949699, 0.0597103, -0.00558806, -0.307368, 1, 1, 1, 0.25, 1, 0.00943748, 0.0451194, -0.647324, 0.940565, -0.00539416, -0.00131091, -0.339569, 1, 1, 1, 0.3, 1, 0.00617793, 0.0295368, -0.424059, -0.852217, 0.0810981, 0.000142268, 0.516865, 1, 1, 1, 0.35, 1, 0.00247674, 0.0118409, -0.170242, -0.686673, 0.0913182, 0.000156236, 0.721208, 1, 1, 1, 0.4, 1, 0.000368256, 0.00176083, -0.02535, -0.450712, 0.0617424, -0.0017981, 0.89053, 1, 1, 1, 0.45, 1, -3.27127e-08, -2.23517e-08, 0, -0.320919, 0.0402711, -0.00287403, 0.946246, 1, 1, 1, 0.5, 1, -3.65544e-08, 2.6077e-07, 0, -0.222093, 0.0121194, -0.000893378, 0.97495, 1, 1, 1, 0.55, 1, -7.85803e-08, -5.21541e-08, 5.96046e-08, -0.085227, -0.0121138, 0.00211304, 0.996286, 1, 1, 1, 0.6, 1, -9.66247e-09, -1.93715e-07, -5.96046e-08, -0.0204391, -0.0111085, 0.00211107, 0.999727, 1, 1, 1, 0.65, 1, -1.47847e-08, -7.45058e-09, 1.19209e-07, -0.0461144, -0.0137229, 0.00155832, 0.998841, 1, 1, 1, 0.75, 1, 9.77889e-08, -8.9407e-08, 0, -0.259445, -0.0379664, 0.000355786, 0.965011, 1, 1, 1, 0.8, 1, -3.06172e-08, -1.19209e-07, 1.19209e-07, -0.311223, -0.0514541, 0.000257438, 0.948943, 1, 1, 1, 0.85, 1, -6.98492e-10, -2.98023e-08, 4.76837e-07, -0.32359, -0.0556479, 0.000232734, 0.94456, 1, 1, 1, 1.25, 1, -6.98492e-10, -2.98023e-08, 4.76837e-07, -0.32359, -0.0556479, 0.000232734, 0.94456, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="204"> 0, 1, 2.23517e-08, 1.19209e-07, 7.45058e-09, -0.260411, 0.0677016, 0.0123204, 0.963042, 1, 1, 1, 0.05, 1, 1.49012e-08, 1.19209e-07, -6.33299e-08, -0.261291, 0.0586691, 0.0123934, 0.963396, 1, 1, 1, 0.1, 1, 1.49012e-08, 1.19209e-07, 3.35276e-08, -0.262834, 0.0342669, 0.0126709, 0.964149, 1, 1, 1, 0.2, 1, 1.49012e-08, 0, 1.86265e-08, -0.260355, -0.0293857, 0.0140367, 0.964964, 1, 1, 1, 0.25, 1, -6.70552e-08, 0, -2.49594e-07, -0.153196, -0.0556389, 0.0191204, 0.986443, 1, 1, 1, 0.3, 1, 7.45058e-09, 2.38419e-07, 3.35276e-08, 0.102501, -0.0807205, 0.0313849, 0.990956, 1, 1, 1, 0.35, 1, -1.49012e-08, 1.19209e-07, -1.11759e-08, 0.182765, -0.105332, 0.0403985, 0.976663, 1, 1, 1, 0.4, 1, 0, 2.38419e-07, 2.98023e-08, 0.1689, -0.131443, 0.0454069, 0.975773, 1, 1, 1, 0.45, 1, -2.23517e-08, 1.19209e-07, 1.11759e-08, 0.162548, -0.163949, 0.0367097, 0.972292, 1, 1, 1, 0.5, 1, -7.45058e-09, 1.19209e-07, -6.70552e-08, 0.160675, -0.186181, 0.0223394, 0.969031, 1, 1, 1, 0.55, 1, 0, 2.38419e-07, -4.09782e-08, 0.121712, -0.123055, 0.0340729, 0.984318, 1, 1, 1, 0.65, 1, -2.23517e-08, 2.38419e-07, -4.84288e-08, -0.0909908, -0.00331438, 0.030867, 0.995368, 1, 1, 1, 0.7, 1, -2.98023e-08, 0, -1.86265e-08, -0.167009, 0.0327264, 0.0253347, 0.985086, 1, 1, 1, 0.75, 1, -1.49012e-08, 2.38419e-07, -9.31323e-08, -0.225897, 0.0565391, 0.0182554, 0.972338, 1, 1, 1, 0.8, 1, 7.45058e-09, 0, 1.41561e-07, -0.254123, 0.0658906, 0.0135391, 0.96483, 1, 1, 1, 0.85, 1, 2.23517e-08, 1.19209e-07, 7.45058e-09, -0.260411, 0.0677016, 0.0123204, 0.963042, 1, 1, 1, 1.25, 1, 2.23517e-08, 1.19209e-07, 7.45058e-09, -0.260411, 0.0677016, 0.0123204, 0.963042, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="24"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="192"> 0, 1, -5.68434e-14, 0, 0.994808, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -5.68434e-14, 0, 0.908378, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, -5.68434e-14, 0, 0.865919, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.15, 1, -5.68434e-14, 0, 0.952043, 0, 0, 0, 1, 1, 1, 1, 0.25, 1, -5.68434e-14, 0, 1.23636, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, -5.68434e-14, 0, 1.26452, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.35, 1, -5.68434e-14, 0, 1.17812, 0, 0, -7.10543e-15, 1, 1, 1, 1, 0.45, 1, -5.68434e-14, 0, 0.917901, 0, 0, 0, 1, 1, 1, 1, 0.5, 1, -5.68434e-14, 0, 0.850875, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -5.68434e-14, 0, 0.90967, 0, 0, 0, 1, 1, 1, 1, 0.65, 1, -5.68434e-14, 0, 1.19399, 0, 0, 0, 1, 1, 1, 1, 0.7, 1, -5.68434e-14, 0, 1.26645, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.75, 1, -5.68434e-14, 0, 1.20667, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -5.68434e-14, 0, 1.04898, 0, 0, 7.10543e-15, 1, 1, 1, 1, 0.85, 1, -5.68434e-14, 0, 0.994808, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -5.68434e-14, 0, 0.994808, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="192"> 0, 1, -0.142338, -0.593751, 0.041427, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.141891, -0.466314, 0.0666584, 0, 0, 0, 1, 1, 1, 1, 0.1, 1, -0.140854, -0.18721, 0.16679, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, -0.135712, 0.882052, 1.08263, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, -0.134593, 1.04285, 1.23903, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, -0.134052, 1.11594, 1.33052, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.134139, 1.01025, 1.37488, 0, 0, 0, 1, 1, 1, 1, 0.5, 1, -0.134864, 0.561422, 1.40083, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -0.136154, -0.107091, 1.41207, 0, 0, 0, 1, 1, 1, 1, 0.6, 1, -0.137517, -0.627938, 1.41499, 0, 0, 0, 1, 1, 1, 1, 0.65, 1, -0.138802, -0.880369, 1.32217, 0, 0, 0, 1, 1, 1, 1, 0.7, 1, -0.140187, -0.97361, 0.946171, 0, 0, 0, 1, 1, 1, 1, 0.75, 1, -0.141374, -0.990009, 0.507478, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -0.142135, -0.753522, 0.166703, 0, 0, 0, 1, 1, 1, 1, 0.85, 1, -0.142338, -0.593751, 0.041427, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.142338, -0.593751, 0.041427, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="192"> 0, 1, 0.133965, 1.12742, 1.35169, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.134319, 0.88137, 1.36048, 0, 0, 0, 1, 1, 1, 1, 0.15, 1, 0.136624, -0.318866, 1.4031, 0, 0, 0, 1, 1, 1, 1, 0.2, 1, 0.13794, -0.745207, 1.41408, 0, 0, 0, 1, 1, 1, 1, 0.25, 1, 0.139237, -0.932173, 1.26013, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, 0.140615, -0.985177, 0.795642, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, 0.141658, -0.933265, 0.382912, 0, 0, 0, 1, 1, 1, 1, 0.4, 1, 0.142236, -0.69551, 0.103281, 0, 0, 0, 1, 1, 1, 1, 0.45, 1, 0.142112, -0.449542, 0.0515677, 0, 0, 0, 1, 1, 1, 1, 0.5, 1, 0.141234, -0.239295, 0.11699, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, 0.140074, 0.0127278, 0.285218, 0, 0, 0, 1, 1, 1, 1, 0.7, 1, 0.136158, 0.812955, 1.03336, 0, 0, 0, 1, 1, 1, 1, 0.75, 1, 0.134866, 1.00553, 1.22614, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, 0.13414, 1.10444, 1.32777, 0, 0, 0, 1, 1, 1, 1, 0.85, 1, 0.133965, 1.12742, 1.35169, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.133965, 1.12742, 1.35169, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="180"> 0, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.0953997, 0.642052, -0.742965, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.1, 1, 0.0823101, 0.56581, -0.648221, 4.1297e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.35, 1, 0.0243976, -0.0441461, -0.063019, 4.1297e-08, 2.53394e-15, -7.10543e-15, 1, 1, 1, 1, 0.4, 1, 0.020945, -0.11126, -0.00892317, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.45, 1, 0.0214889, -0.0993756, -0.1204, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.5, 1, 0.0261557, -0.00703263, -0.571036, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, 0.0350212, 0.144668, -1.19143, 7.10993e-08, 6.08666e-15, -4.32757e-22, 1, 1, 1, 1, 0.6, 1, 0.0452013, 0.286137, -1.58564, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.65, 1, 0.056361, 0.396596, -1.62736, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.7, 1, 0.0713525, 0.504199, -1.41721, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.75, 1, 0.0877976, 0.602767, -1.08603, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, 0.097935, 0.656912, -0.843801, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.85, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.100474, 0.669825, -0.778672, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="180"> 0, 1, -0.0204011, -0.122407, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.0226399, -0.0760723, -0.246171, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.15, 1, -0.0384328, 0.195889, -1.36473, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.2, 1, -0.0485586, 0.325533, -1.64571, 7.10993e-08, 9.63937e-15, -6.85353e-22, 1, 1, 1, 1, 0.25, 1, -0.0604436, 0.430887, -1.61593, 0, 0, 0, 1, 1, 1, 1, 0.3, 1, -0.0768237, 0.538687, -1.39129, 7.10993e-08, 2.53394e-15, -2.11758e-22, 1, 1, 1, 1, 0.35, 1, -0.0915991, 0.623227, -1.09587, 4.1297e-08, 2.53394e-15, -7.10543e-15, 1, 1, 1, 1, 0.4, 1, -0.0992045, 0.663389, -0.847581, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.45, 1, -0.0979352, 0.656214, -0.687419, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.5, 1, -0.0877979, 0.599371, -0.580202, 0, 0, 0, 1, 1, 1, 1, 0.65, 1, -0.0452008, 0.276356, -0.334939, 7.10993e-08, 2.53395e-15, 7.10543e-15, 1, 1, 1, 1, 0.75, 1, -0.0261556, -0.010167, -0.0897738, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -0.0214889, -0.0999783, -0.0177123, 7.10993e-08, 6.08666e-15, 7.10543e-15, 1, 1, 1, 1, 0.85, 1, -0.0204011, -0.122407, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.0204011, -0.122407, 5.96046e-08, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="168"> 0, 1, -0.868295, 0.288818, -0.834593, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -0.920336, 0.223441, -0.675278, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -1.0611, 0.0535004, -0.268795, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.3, 1, -1.81549, -0.572945, 1.93497, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.35, 1, -1.97521, -0.260334, 2.42549, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -2.07242, 0.0952058, 2.72719, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -2.06152, 0.134094, 2.70055, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, -1.94935, -0.00418663, 2.38214, 0, 0, 0, 1, 1, 1, 1, 0.6, 1, -1.5659, -0.316463, 1.27531, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.65, 1, -1.39564, -0.31023, 0.768786, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.75, 1, -1.01032, 0.0728607, -0.380929, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -0.896442, 0.243316, -0.739858, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.85, 1, -0.868295, 0.288818, -0.834593, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -0.868295, 0.288818, -0.834593, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="168"> 0, 1, 2.08906, 0.170859, 2.78004, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 2.03311, 0.0989122, 2.61048, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, 1.88529, -0.0705678, 2.18507, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, 1.50915, -0.334755, 1.10648, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, 1.33866, -0.287646, 0.593788, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, 0.966909, 0.137533, -0.532556, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, 0.882217, 0.266322, -0.791318, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, 0.89374, 0.256562, -0.760212, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, 0.999084, 0.126561, -0.459517, 0, 0, 0, 1, 1, 1, 1, 0.7, 1, 1.75712, -0.595706, 1.75783, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.75, 1, 1.92686, -0.424236, 2.27222, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, 2.0556, 0.0151663, 2.66931, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.85, 1, 2.08906, 0.170859, 2.78004, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 2.08906, 0.170859, 2.78004, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="156"> 0, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, 0.341349, -0.264663, 0.0556155, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.15, 1, 0.0336542, -1.45692, 0.323532, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.2, 1, -0.0452293, -1.75482, 0.391734, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.25, 1, 0.0926713, -1.62165, 0.363375, 0, 0, 0, 1, 1, 1, 1, 0.35, 1, 1.18685, -0.378264, 0.0954279, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, 1.51909, 0.00473738, 0.0141962, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, 1.55064, 0.0706801, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, 1.44211, 0.0639179, 0, 0, 0, 0, 1, 1, 1, 1, 0.75, 1, 0.54098, 0.00832748, 0, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, 0.432091, 0.00163841, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.85, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, 0.405204, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="168"> 0, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1, 0.05, 1, -1.5235, 0.0690539, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.1, 1, -1.38104, 0.0602572, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.4, 1, -0.448482, 0.0061903, 0, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.45, 1, -0.312683, -0.140136, 0.0283925, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.5, 1, -0.161211, -0.627825, 0.135386, 0, 0, 0, 1, 1, 1, 1, 0.55, 1, -0.030728, -1.28144, 0.283529, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.6, 1, 0.0389389, -1.69292, 0.377552, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.65, 1, -0.0330012, -1.68882, 0.377568, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.7, 1, -0.409697, -1.26443, 0.283661, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.75, 1, -1.00503, -0.588506, 0.135634, 0, 0, 0, 1, 1, 1, 1, 0.8, 1, -1.45325, -0.0721812, 0.0284887, -5.1658e-08, 0, 0, 1, 1, 1, 1, 0.85, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1, 1.25, 1, -1.5774, 0.0723579, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="216"> 0, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 0.05, 1, 0.0669454, 0.729981, 0.0847113, 0.0751978, 0.000902196, 0.0773167, 0.994166, 1, 1, 1, 0.15, 1, 0.147711, 0.887191, -0.02789, 0.103321, 0.0347243, 0.0196114, 0.993848, 1, 1, 1, 0.2, 1, 0.168294, 0.927241, -0.0565808, 0.110419, 0.0433374, -0.00845134, 0.992904, 1, 1, 1, 0.25, 1, 0.154709, 0.910602, -0.0446639, 0.107418, 0.0422538, -0.0318613, 0.992804, 1, 1, 1, 0.3, 1, 0.0960078, 0.836978, 0.00806546, 0.0942701, 0.034167, -0.0564973, 0.993355, 1, 1, 1, 0.35, 1, 0.021745, 0.753374, 0.0679436, 0.0793445, 0.0222103, -0.0760792, 0.993692, 1, 1, 1, 0.4, 1, -0.035471, 0.705747, 0.102054, 0.07085, 0.00995431, -0.0854402, 0.993771, 1, 1, 1, 0.45, 1, -0.0674228, 0.714066, 0.0960958, 0.0723594, -0.00257329, -0.0821245, 0.993989, 1, 1, 1, 0.5, 1, -0.0866932, 0.776805, 0.0511615, 0.0836199, -0.0185098, -0.0626717, 0.994353, 1, 1, 1, 0.55, 1, -0.0950061, 0.863738, -0.0110998, 0.0991637, -0.0338542, -0.0304325, 0.994029, 1, 1, 1, 0.6, 1, -0.0971422, 0.918921, -0.0506222, 0.108957, -0.0424157, -6.6921e-05, 0.993141, 1, 1, 1, 0.65, 1, -0.0894483, 0.918925, -0.0506237, 0.108927, -0.0421963, 0.0241723, 0.99286, 1, 1, 1, 0.7, 1, -0.0546535, 0.863773, -0.0111129, 0.0990954, -0.0332032, 0.0485143, 0.99334, 1, 1, 1, 0.75, 1, 0.000162542, 0.776872, 0.051137, 0.0835711, -0.0190219, 0.071275, 0.993768, 1, 1, 1, 0.8, 1, 0.0397389, 0.714092, 0.0960863, 0.072346, -0.00878352, 0.08392, 0.993804, 1, 1, 1, 0.85, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1, 1.25, 1, 0.050238, 0.697428, 0.108012, 0.0693673, -0.00606888, 0.0869442, 0.993777, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="180"> 0, 1, 7.45059e-09, -5.21541e-08, 2.38419e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1, 0.05, 1, -2.16067e-08, -1.49015e-09, 1.19209e-07, 0.0607085, -0.00428583, -0.0791363, 0.995004, 1, 1, 1, 0.1, 1, -2.23518e-09, 4.61936e-08, 1.49012e-07, 0.0742298, -0.00290666, -0.0580589, 0.995545, 1, 1, 1, 0.2, 1, -1.22934e-08, -7.00588e-08, 1.49012e-07, 0.0953622, 0.000412438, -0.00409159, 0.995434, 1, 1, 1, 0.25, 1, -1.86265e-08, 1.39698e-08, -1.49012e-07, 0.0924473, 0.00171257, 0.0202586, 0.99551, 1, 1, 1, 0.35, 1, -1.56462e-08, 3.1013e-08, 0, 0.0648424, 0.00419923, 0.0731356, 0.995203, 1, 1, 1, 0.4, 1, 2.23523e-09, -2.84985e-08, 1.19209e-07, 0.0564666, 0.00472734, 0.0850757, 0.994762, 1, 1, 1, 0.45, 1, -4.47039e-09, 2.23518e-08, -8.9407e-08, 0.0579181, 0.00454757, 0.0830774, 0.994848, 1, 1, 1, 0.5, 1, 8.43755e-15, -5.58794e-08, 8.9407e-08, 0.0689504, 0.00348495, 0.0670145, 0.995361, 1, 1, 1, 0.6, 1, 5.5879e-09, -7.60309e-08, -2.98023e-08, 0.0939097, 5.69107e-05, 0.0121633, 0.995506, 1, 1, 1, 0.65, 1, 1.78815e-08, -2.31898e-08, 3.27826e-07, 0.0939129, -0.00128467, -0.0120988, 0.995506, 1, 1, 1, 0.75, 1, -1.86265e-09, 3.11993e-08, -2.98023e-08, 0.0689717, -0.00392611, -0.0670089, 0.995358, 1, 1, 1, 0.8, 1, 1.49013e-09, 4.80559e-08, 0, 0.0579302, -0.00464071, -0.0830884, 0.994846, 1, 1, 1, 0.85, 1, 7.45059e-09, -5.21541e-08, 2.38419e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1, 1.25, 1, 7.45059e-09, -5.21541e-08, 2.38419e-07, 0.0550011, -0.00481196, -0.0870228, 0.994675, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="168"> 0, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, 0.0947232, -0.00739035, -0.0868418, 0.991681, 1, 1, 1, 0.05, 1, 9.31322e-10, 7.07805e-08, 5.96046e-08, 0.0947233, -0.00739035, -0.0868419, 0.991681, 1, 1, 1, 0.1, 1, 6.51926e-10, 7.07805e-08, 5.96046e-08, 0.0949443, -0.00694628, -0.0757376, 0.992573, 1, 1, 1, 0.15, 1, 3.7253e-10, -2.6077e-08, -2.38419e-07, 0.0959905, -0.00433497, -0.0114678, 0.995307, 1, 1, 1, 0.25, 1, 1.86265e-08, 2.23517e-08, 1.19209e-07, 0.0965992, 0.00494126, 0.201269, 0.974749, 1, 1, 1, 0.3, 1, -7.68343e-10, 7.45058e-09, 1.78814e-07, 0.0963173, 0.00675391, 0.221794, 0.970301, 1, 1, 1, 0.4, 1, -1.56574e-10, 7.82311e-08, -1.78814e-07, 0.0949654, 0.0073896, 0.100605, 0.990356, 1, 1, 1, 0.45, 1, 3.30057e-09, 1.08033e-07, -5.96046e-08, 0.0947232, 0.00739035, 0.0868418, 0.991681, 1, 1, 1, 0.5, 1, -3.25963e-09, -9.31323e-08, 5.96046e-08, 0.0947232, 0.00739035, 0.0868418, 0.991681, 1, 1, 1, 0.55, 1, -2.10027e-08, 7.45058e-08, -1.78814e-07, 0.0955253, 0.00546829, 0.0431828, 0.994475, 1, 1, 1, 0.65, 1, 1.26195e-08, -4.84288e-08, -2.38419e-07, 0.0967914, -0.0040173, -0.170015, 0.980668, 1, 1, 1, 0.7, 1, 1.23865e-08, -8.19564e-08, -5.96046e-08, 0.0964064, -0.00640121, -0.223121, 0.969991, 1, 1, 1, 0.75, 1, 1.86265e-09, -7.07805e-08, -2.98023e-07, 0.0963505, -0.00664593, -0.228565, 0.968726, 1, 1, 1, 1.25, 1, -1.93979e-09, 3.72529e-08, -1.78814e-07, 0.0963505, -0.00664594, -0.228565, 0.968726, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="24"> 0, 1, -1.95579e-08, -1.49012e-08, -9.53674e-07, -7.45058e-09, -2.48375e-09, 8.87174e-09, 1, 1, 1, 1, 1.25, 1, -6.51927e-08, -7.45058e-08, -9.53674e-07, 6.80667e-18, 2.71908e-09, -1.56593e-08, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="204"> 0, 1, 2.79375e-09, -5.96046e-07, -2.50526e-07, 0.174741, -0.0963796, 0.0144345, 0.97978, 1, 1, 1, 0.05, 1, -3.7254e-09, -2.08616e-07, -1.22236e-07, 0.195715, -0.0950264, 0.0238173, 0.975755, 1, 1, 1, 0.1, 1, 4.54485e-08, -7.15256e-07, -7.68341e-08, 0.229373, -0.0816785, 0.0404464, 0.969062, 1, 1, 1, 0.15, 1, -1.49012e-08, -6.85453e-07, -8.59145e-08, 0.25499, -0.0176933, 0.0391946, 0.965987, 1, 1, 1, 0.25, 1, 1.4901e-08, -1.49012e-07, -1.78115e-07, 0.23692, 0.192561, -0.0167461, 0.952108, 1, 1, 1, 0.3, 1, -4.61937e-08, -4.47035e-07, -1.46218e-07, 0.20349, 0.220566, -0.0253329, 0.953573, 1, 1, 1, 0.35, 1, 8.94071e-09, -2.68221e-07, -1.97906e-08, 0.179164, 0.172369, -0.0185073, 0.968425, 1, 1, 1, 0.4, 1, 2.23509e-09, -3.57628e-07, -9.56934e-08, 0.17384, 0.110352, -0.0138213, 0.978474, 1, 1, 1, 0.45, 1, -2.75671e-08, -7.45058e-07, 2.63099e-08, 0.188123, 0.0930304, -0.0247279, 0.977417, 1, 1, 1, 0.5, 1, -9.31436e-10, 4.47035e-07, -6.37956e-08, 0.217624, 0.0872372, -0.0441829, 0.971122, 1, 1, 1, 0.55, 1, 1.04306e-08, -2.38419e-07, -1.33412e-07, 0.247766, 0.0401273, -0.0490683, 0.966744, 1, 1, 1, 0.65, 1, 3.27827e-08, -4.47035e-07, -6.26314e-08, 0.245106, -0.170404, 0.00637661, 0.954382, 1, 1, 1, 0.7, 1, 3.27823e-08, -1.49012e-07, -6.70552e-08, 0.212986, -0.224596, 0.0272969, 0.950499, 1, 1, 1, 0.75, 1, -7.45057e-08, 0, 6.33299e-08, 0.183845, -0.233119, 0.0392625, 0.954104, 1, 1, 1, 0.8, 1, -6.7055e-08, -5.96046e-07, -5.00586e-08, 0.175853, -0.235075, 0.0484733, 0.954707, 1, 1, 1, 0.85, 1, 7.45066e-09, -6.55651e-07, 6.75209e-09, 0.174943, -0.235515, 0.051072, 0.95463, 1, 1, 1, 1.25, 1, 7.45066e-09, -6.55651e-07, 6.75209e-09, 0.174943, -0.235515, 0.051072, 0.95463, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="24"> 0, 1, -1.25867e-08, -4.23752e-08, -2.57976e-07, 2.23517e-08, 3.7017e-10, 7.60394e-10, 1, 1, 1, 1, 1.25, 1, 1.23749e-08, -2.09548e-09, 2.43308e-07, 2.23517e-08, -2.79233e-10, -7.29088e-11, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="24"> 0, 1, 5.20962e-08, 0.00292337, 0.204329, -7.21775e-09, 1.1358e-11, -7.03732e-10, 1, 1, 1, 1, 1.25, 1, 4.12186e-08, 0.00292328, 0.20433, -8.14907e-09, 9.21561e-11, 1.63806e-10, 1, 1, 1, 1 </real_array>
-
- </resource>
- <resource type="Animation" path="local://14">
- <string name="resource/name"> "default" </string>
- <real name="length"> 1.25 </real>
- <bool name="loop"> False </bool>
- <real name="step"> 0.1 </real>
- <string name="tracks/0/type"> "transform" </string>
- <node_path name="tracks/0/path"> "Armature/Skeleton:r-arm" </node_path>
- <int name="tracks/0/interp"> 1 </int>
- <real_array name="tracks/0/keys" len="12"> 0, 1, 5.06639e-07, -1.19209e-07, 3.57628e-07, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/1/type"> "transform" </string>
- <node_path name="tracks/1/path"> "Armature/Skeleton:r-forearm" </node_path>
- <int name="tracks/1/interp"> 1 </int>
- <real_array name="tracks/1/keys" len="12"> 0, 1, 1.19209e-07, -8.9407e-07, -1.19209e-07, -3.72529e-08, -1.49012e-08, 2.23517e-08, 1, 1, 1, 1 </real_array>
- <string name="tracks/2/type"> "transform" </string>
- <node_path name="tracks/2/path"> "Armature/Skeleton:l-arm" </node_path>
- <int name="tracks/2/interp"> 1 </int>
- <real_array name="tracks/2/keys" len="12"> 0, 1, -5.06639e-07, -1.19209e-07, 3.57628e-07, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/3/type"> "transform" </string>
- <node_path name="tracks/3/path"> "Armature/Skeleton:l-forearm" </node_path>
- <int name="tracks/3/interp"> 1 </int>
- <real_array name="tracks/3/keys" len="12"> 0, 1, -1.19209e-07, -8.9407e-07, -1.19209e-07, -3.72529e-08, 1.49012e-08, -2.23517e-08, 1, 1, 1, 1 </real_array>
- <string name="tracks/4/type"> "transform" </string>
- <node_path name="tracks/4/path"> "Armature/Skeleton:r-thigh" </node_path>
- <int name="tracks/4/interp"> 1 </int>
- <real_array name="tracks/4/keys" len="12"> 0, 1, 0, 2.98023e-08, -2.5332e-07, 0, 5.20417e-18, -2.79397e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/5/type"> "transform" </string>
- <node_path name="tracks/5/path"> "Armature/Skeleton:r-leg" </node_path>
- <int name="tracks/5/interp"> 1 </int>
- <real_array name="tracks/5/keys" len="12"> 0, 1, 2.10712e-08, -7.45058e-09, 5.96046e-07, 7.45058e-09, 3.60887e-09, 3.91446e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/6/type"> "transform" </string>
- <node_path name="tracks/6/path"> "Armature/Skeleton:r-foot" </node_path>
- <int name="tracks/6/interp"> 1 </int>
- <real_array name="tracks/6/keys" len="12"> 0, 1, 6.70552e-08, 1.19209e-07, 0, 3.72529e-09, 1.16415e-09, 3.72529e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/7/type"> "transform" </string>
- <node_path name="tracks/7/path"> "Armature/Skeleton:l-thigh" </node_path>
- <int name="tracks/7/interp"> 1 </int>
- <real_array name="tracks/7/keys" len="12"> 0, 1, 0, 2.98023e-08, -1.49012e-08, 1.86265e-09, 7.45058e-09, 2.09548e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/8/type"> "transform" </string>
- <node_path name="tracks/8/path"> "Armature/Skeleton:l-leg" </node_path>
- <int name="tracks/8/interp"> 1 </int>
- <real_array name="tracks/8/keys" len="12"> 0, 1, 1.74623e-08, -2.98023e-08, 2.98023e-07, 3.72529e-09, 7.45058e-09, -1.17143e-09, 1, 1, 1, 1 </real_array>
- <string name="tracks/9/type"> "transform" </string>
- <node_path name="tracks/9/path"> "Armature/Skeleton:l-foot" </node_path>
- <int name="tracks/9/interp"> 1 </int>
- <real_array name="tracks/9/keys" len="12"> 0, 1, 1.49012e-08, 0, 0, 0, -1.39698e-09, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/10/type"> "transform" </string>
- <node_path name="tracks/10/path"> "Armature/Skeleton:MASTER" </node_path>
- <int name="tracks/10/interp"> 1 </int>
- <real_array name="tracks/10/keys" len="12"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/11/type"> "transform" </string>
- <node_path name="tracks/11/path"> "Armature/Skeleton:HEAD" </node_path>
- <int name="tracks/11/interp"> 1 </int>
- <real_array name="tracks/11/keys" len="12"> 0, 1, -5.68434e-14, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/12/type"> "transform" </string>
- <node_path name="tracks/12/path"> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <int name="tracks/12/interp"> 1 </int>
- <real_array name="tracks/12/keys" len="12"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/13/type"> "transform" </string>
- <node_path name="tracks/13/path"> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <int name="tracks/13/interp"> 1 </int>
- <real_array name="tracks/13/keys" len="12"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/14/type"> "transform" </string>
- <node_path name="tracks/14/path"> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <int name="tracks/14/interp"> 1 </int>
- <real_array name="tracks/14/keys" len="12"> 0, 1, -2.98023e-08, 1.19209e-07, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/15/type"> "transform" </string>
- <node_path name="tracks/15/path"> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <int name="tracks/15/interp"> 1 </int>
- <real_array name="tracks/15/keys" len="12"> 0, 1, 2.98023e-08, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/16/type"> "transform" </string>
- <node_path name="tracks/16/path"> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <int name="tracks/16/interp"> 1 </int>
- <real_array name="tracks/16/keys" len="12"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/17/type"> "transform" </string>
- <node_path name="tracks/17/path"> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <int name="tracks/17/interp"> 1 </int>
- <real_array name="tracks/17/keys" len="12"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/18/type"> "transform" </string>
- <node_path name="tracks/18/path"> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <int name="tracks/18/interp"> 1 </int>
- <real_array name="tracks/18/keys" len="12"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/19/type"> "transform" </string>
- <node_path name="tracks/19/path"> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <int name="tracks/19/interp"> 1 </int>
- <real_array name="tracks/19/keys" len="12"> 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 </real_array>
- <string name="tracks/20/type"> "transform" </string>
- <node_path name="tracks/20/path"> "Armature/Skeleton:hip" </node_path>
- <int name="tracks/20/interp"> 1 </int>
- <real_array name="tracks/20/keys" len="12"> 0, 1, 0, -2.84217e-14, 0, 0, 0, 1.44945e-21, 1, 1, 1, 1 </real_array>
- <string name="tracks/21/type"> "transform" </string>
- <node_path name="tracks/21/path"> "Armature/Skeleton:waist" </node_path>
- <int name="tracks/21/interp"> 1 </int>
- <real_array name="tracks/21/keys" len="12"> 0, 1, -6.35275e-21, 2.84217e-14, 0, 0, 0, 2.44616e-35, 1, 1, 1, 1 </real_array>
- <string name="tracks/22/type"> "transform" </string>
- <node_path name="tracks/22/path"> "Armature/Skeleton:chest" </node_path>
- <int name="tracks/22/interp"> 1 </int>
- <real_array name="tracks/22/keys" len="12"> 0, 1, -3.38813e-21, 0, 0, 0, 0, -1.33383e-23, 1, 1, 1, 1 </real_array>
- <string name="tracks/23/type"> "transform" </string>
- <node_path name="tracks/23/path"> "Armature/Skeleton:neck" </node_path>
- <int name="tracks/23/interp"> 1 </int>
- <real_array name="tracks/23/keys" len="12"> 0, 1, -8.52651e-14, -5.96046e-08, -7.15256e-07, 1.17383e-27, 2.13163e-14, 5.50671e-14, 1, 1, 1, 1 </real_array>
- <string name="tracks/24/type"> "transform" </string>
- <node_path name="tracks/24/path"> "Armature/Skeleton:headtracker" </node_path>
- <int name="tracks/24/interp"> 1 </int>
- <real_array name="tracks/24/keys" len="12"> 0, 1, -1.77636e-13, 5.96046e-08, -5.98375e-08, 7.45058e-09, 1.04639e-13, -2.13163e-14, 1, 1, 1, 1 </real_array>
- <string name="tracks/25/type"> "transform" </string>
- <node_path name="tracks/25/path"> "Armature/Skeleton:head" </node_path>
- <int name="tracks/25/interp"> 1 </int>
- <real_array name="tracks/25/keys" len="12"> 0, 1, -2.30926e-14, -1.22469e-07, 2.39583e-07, -2.52436e-28, 7.10543e-15, -7.10543e-15, 1, 1, 1, 1 </real_array>
- <string name="tracks/26/type"> "transform" </string>
- <node_path name="tracks/26/path"> "Armature/Skeleton:vent" </node_path>
- <int name="tracks/26/interp"> 1 </int>
- <real_array name="tracks/26/keys" len="12"> 0, 1, 3.55271e-15, 5.96046e-08, -7.15256e-07, 1.97906e-09, -2.66454e-15, 5.59448e-15, 1, 1, 1, 1 </real_array>
-
- </resource>
- <main_resource>
- <dictionary name="_bundled" shared="false">
- <string> "names" </string>
- <string_array len="249">
- <string> "player" </string>
- <string> "RigidBody" </string>
- <string> "shape_count" </string>
- <string> "shapes/0/shape" </string>
- <string> "shapes/0/transform" </string>
- <string> "shapes/0/trigger" </string>
- <string> "shapes/1/shape" </string>
- <string> "shapes/1/transform" </string>
- <string> "shapes/1/trigger" </string>
- <string> "mode" </string>
- <string> "mass" </string>
- <string> "friction" </string>
- <string> "bounce" </string>
- <string> "custom_integrator" </string>
- <string> "continuous_cd" </string>
- <string> "contacts_reported" </string>
- <string> "contact_monitor" </string>
- <string> "active" </string>
- <string> "can_sleep" </string>
- <string> "velocity/linear" </string>
- <string> "velocity/angular" </string>
- <string> "script/script" </string>
- <string> "__meta__" </string>
- <string> "collision_capsule" </string>
- <string> "CollisionShape" </string>
- <string> "transform/local" </string>
- <string> "shape" </string>
- <string> "trigger" </string>
- <string> "collision_ray" </string>
- <string> "target" </string>
- <string> "Spatial" </string>
- <string> "camera" </string>
- <string> "Camera" </string>
- <string> "projection" </string>
- <string> "fov" </string>
- <string> "near" </string>
- <string> "far" </string>
- <string> "vaspect" </string>
- <string> "current" </string>
- <string> "visible_layers" </string>
- <string> "environment" </string>
- <string> "min_distance" </string>
- <string> "max_distance" </string>
- <string> "angle_v_adjust" </string>
- <string> "autoturn_ray_aperture" </string>
- <string> "autoturn_speed" </string>
- <string> "Armature" </string>
- <string> "Skeleton" </string>
- <string> "bones/0/name" </string>
- <string> "bones/0/parent" </string>
- <string> "bones/0/rest" </string>
- <string> "bones/0/enabled" </string>
- <string> "bones/0/bound_childs" </string>
- <string> "bones/1/name" </string>
- <string> "bones/1/parent" </string>
- <string> "bones/1/rest" </string>
- <string> "bones/1/enabled" </string>
- <string> "bones/1/bound_childs" </string>
- <string> "bones/2/name" </string>
- <string> "bones/2/parent" </string>
- <string> "bones/2/rest" </string>
- <string> "bones/2/enabled" </string>
- <string> "bones/2/bound_childs" </string>
- <string> "bones/3/name" </string>
- <string> "bones/3/parent" </string>
- <string> "bones/3/rest" </string>
- <string> "bones/3/enabled" </string>
- <string> "bones/3/bound_childs" </string>
- <string> "bones/4/name" </string>
- <string> "bones/4/parent" </string>
- <string> "bones/4/rest" </string>
- <string> "bones/4/enabled" </string>
- <string> "bones/4/bound_childs" </string>
- <string> "bones/5/name" </string>
- <string> "bones/5/parent" </string>
- <string> "bones/5/rest" </string>
- <string> "bones/5/enabled" </string>
- <string> "bones/5/bound_childs" </string>
- <string> "bones/6/name" </string>
- <string> "bones/6/parent" </string>
- <string> "bones/6/rest" </string>
- <string> "bones/6/enabled" </string>
- <string> "bones/6/bound_childs" </string>
- <string> "bones/7/name" </string>
- <string> "bones/7/parent" </string>
- <string> "bones/7/rest" </string>
- <string> "bones/7/enabled" </string>
- <string> "bones/7/bound_childs" </string>
- <string> "bones/8/name" </string>
- <string> "bones/8/parent" </string>
- <string> "bones/8/rest" </string>
- <string> "bones/8/enabled" </string>
- <string> "bones/8/bound_childs" </string>
- <string> "bones/9/name" </string>
- <string> "bones/9/parent" </string>
- <string> "bones/9/rest" </string>
- <string> "bones/9/enabled" </string>
- <string> "bones/9/bound_childs" </string>
- <string> "bones/10/name" </string>
- <string> "bones/10/parent" </string>
- <string> "bones/10/rest" </string>
- <string> "bones/10/enabled" </string>
- <string> "bones/10/bound_childs" </string>
- <string> "bones/11/name" </string>
- <string> "bones/11/parent" </string>
- <string> "bones/11/rest" </string>
- <string> "bones/11/enabled" </string>
- <string> "bones/11/bound_childs" </string>
- <string> "bones/12/name" </string>
- <string> "bones/12/parent" </string>
- <string> "bones/12/rest" </string>
- <string> "bones/12/enabled" </string>
- <string> "bones/12/bound_childs" </string>
- <string> "bones/13/name" </string>
- <string> "bones/13/parent" </string>
- <string> "bones/13/rest" </string>
- <string> "bones/13/enabled" </string>
- <string> "bones/13/bound_childs" </string>
- <string> "bones/14/name" </string>
- <string> "bones/14/parent" </string>
- <string> "bones/14/rest" </string>
- <string> "bones/14/enabled" </string>
- <string> "bones/14/bound_childs" </string>
- <string> "bones/15/name" </string>
- <string> "bones/15/parent" </string>
- <string> "bones/15/rest" </string>
- <string> "bones/15/enabled" </string>
- <string> "bones/15/bound_childs" </string>
- <string> "bones/16/name" </string>
- <string> "bones/16/parent" </string>
- <string> "bones/16/rest" </string>
- <string> "bones/16/enabled" </string>
- <string> "bones/16/bound_childs" </string>
- <string> "bones/17/name" </string>
- <string> "bones/17/parent" </string>
- <string> "bones/17/rest" </string>
- <string> "bones/17/enabled" </string>
- <string> "bones/17/bound_childs" </string>
- <string> "bones/18/name" </string>
- <string> "bones/18/parent" </string>
- <string> "bones/18/rest" </string>
- <string> "bones/18/enabled" </string>
- <string> "bones/18/bound_childs" </string>
- <string> "bones/19/name" </string>
- <string> "bones/19/parent" </string>
- <string> "bones/19/rest" </string>
- <string> "bones/19/enabled" </string>
- <string> "bones/19/bound_childs" </string>
- <string> "bones/20/name" </string>
- <string> "bones/20/parent" </string>
- <string> "bones/20/rest" </string>
- <string> "bones/20/enabled" </string>
- <string> "bones/20/bound_childs" </string>
- <string> "bones/21/name" </string>
- <string> "bones/21/parent" </string>
- <string> "bones/21/rest" </string>
- <string> "bones/21/enabled" </string>
- <string> "bones/21/bound_childs" </string>
- <string> "bones/22/name" </string>
- <string> "bones/22/parent" </string>
- <string> "bones/22/rest" </string>
- <string> "bones/22/enabled" </string>
- <string> "bones/22/bound_childs" </string>
- <string> "bones/23/name" </string>
- <string> "bones/23/parent" </string>
- <string> "bones/23/rest" </string>
- <string> "bones/23/enabled" </string>
- <string> "bones/23/bound_childs" </string>
- <string> "bones/24/name" </string>
- <string> "bones/24/parent" </string>
- <string> "bones/24/rest" </string>
- <string> "bones/24/enabled" </string>
- <string> "bones/24/bound_childs" </string>
- <string> "bones/25/name" </string>
- <string> "bones/25/parent" </string>
- <string> "bones/25/rest" </string>
- <string> "bones/25/enabled" </string>
- <string> "bones/25/bound_childs" </string>
- <string> "bones/26/name" </string>
- <string> "bones/26/parent" </string>
- <string> "bones/26/rest" </string>
- <string> "bones/26/enabled" </string>
- <string> "bones/26/bound_childs" </string>
- <string> "robot" </string>
- <string> "MeshInstance" </string>
- <string> "layers" </string>
- <string> "geometry/visible" </string>
- <string> "geometry/material_override" </string>
- <string> "geometry/cast_shadow" </string>
- <string> "geometry/receive_shadows" </string>
- <string> "geometry/range_begin" </string>
- <string> "geometry/range_end" </string>
- <string> "geometry/billboard" </string>
- <string> "geometry/billboard_y" </string>
- <string> "geometry/depth_scale" </string>
- <string> "geometry/visible_in_all_rooms" </string>
- <string> "mesh/mesh" </string>
- <string> "bullet" </string>
- <string> "Position3D" </string>
- <string> "sfx" </string>
- <string> "SpatialSamplePlayer" </string>
- <string> "params/volume_db" </string>
- <string> "params/pitch_scale" </string>
- <string> "params/attenuation/min_distance" </string>
- <string> "params/attenuation/max_distance" </string>
- <string> "params/attenuation/distance_exp" </string>
- <string> "params/emission_cone/degrees" </string>
- <string> "params/emission_cone/attenuation_db" </string>
- <string> "config/polyphony" </string>
- <string> "config/samples" </string>
- <string> "AnimationPlayer" </string>
- <string> "playback/process_mode" </string>
- <string> "playback/default_blend_time" </string>
- <string> "root/root" </string>
- <string> "speed" </string>
- <string> "anims/idle" </string>
- <string> "anims/shooting" </string>
- <string> "anims/jump-up-cycle" </string>
- <string> "anims/shooting_standing" </string>
- <string> "anims/falling-cycle" </string>
- <string> "anims/walk-cycle" </string>
- <string> "anims/run-cycle" </string>
- <string> "anims/default" </string>
- <string> "blend_times" </string>
- <string> "autoplay" </string>
- <string> "AnimationTreePlayer" </string>
- <string> "process/process" </string>
- <string> "base_path" </string>
- <string> "master_player" </string>
- <string> "data" </string>
- <string> "fwd" </string>
- <string> "TouchScreenButton" </string>
- <string> "process/input" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/on_top" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
- <string> "normal" </string>
- <string> "pressed" </string>
- <string> "bitmask" </string>
- <string> "passby_press" </string>
- <string> "action" </string>
- <string> "visibility_mode" </string>
- <string> "bwd" </string>
- <string> "left" </string>
- <string> "right" </string>
- </string_array>
- <string> "version" </string>
- <int> 1 </int>
- <string> "conn_count" </string>
- <int> 0 </int>
- <string> "node_count" </string>
- <int> 16 </int>
- <string> "variants" </string>
- <array len="121" shared="false">
- <int> 2 </int>
- <resource resource_type="CapsuleShape" path="local://1"> </resource>
- <transform> 1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0.954765, 0 </transform>
- <bool> False </bool>
- <resource resource_type="RayShape" path="local://2"> </resource>
- <transform> 1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 1.01236, 0 </transform>
- <real> 1 </real>
- <real> 0 </real>
- <bool> True </bool>
- <int> 3 </int>
- <vector3> 0, 0, 0 </vector3>
- <resource resource_type="GDScript" path="res://player.*"> </resource>
- <dictionary shared="false">
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 1 </int>
- <string> "sources" </string>
- <array len="2" shared="false">
- <string> "res://follow_camera.gd" </string>
- <string> "res://player.gd" </string>
- </array>
- </dictionary>
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "zoom" </string>
- <real> 1 </real>
- <string> "ofs" </string>
- <vector2> -241, -19 </vector2>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "fov" </string>
- <real> 400 </real>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 2.161076 </real>
- <string> "x_rot" </string>
- <real> 0.520797 </real>
- <string> "y_rot" </string>
- <real> 26.741669 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> -0.415811, 0.486899, 0.089334 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- </dictionary>
- </array>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "znear" </string>
- <real> 0.1 </real>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
- <string> "__editor_plugin_screen__" </string>
- <string> "Script" </string>
- </dictionary>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.95244, 0 </transform>
- <transform> 1, 0, 0, 0, 0.871263, 0.490817, 0, -0.490817, 0.871263, 0, 2.59805, 1.25672 </transform>
- <int> 0 </int>
- <real> 70 </real>
- <real> 0.1 </real>
- <real> 100 </real>
- <int> -1 </int>
- <resource name=""></resource> <resource resource_type="GDScript" path="res://follow_camera.*"> </resource>
- <real> 3 </real>
- <int> 25 </int>
- <int> 50 </int>
- <transform> 0.3, 0, 0, 0, 0.3, 0, 0, 0, 0.3, 0, 0, 0 </transform>
- <string> "MASTER" </string>
- <transform> 1, 0, -0, 0, 7.54979e-08, 1, -0, -1, 7.54979e-08, 0, -0.011277, -0 </transform>
- <array len="0" shared="false">
- </array>
- <string> "hip" </string>
- <transform> 1, -1.50996e-07, -3.60002e-14, -1.50996e-07, -1, -3.01992e-07, 9.59926e-15, 3.01992e-07, -1, -3.38813e-21, 2.58363e-07, 2.10612 </transform>
- <string> "waist" </string>
- <int> 1 </int>
- <transform> 1, 1.50996e-07, 1.80001e-14, -1.50996e-07, 1, 0, -1.80001e-14, 0, 1, 3.38813e-21, 2.84217e-14, -0.384614 </transform>
- <string> "chest" </string>
- <transform> 1, -7.31455e-16, 4.86029e-17, 7.28861e-16, 0.999166, 0.040823, -7.84198e-17, -0.040823, 0.999166, 0, 4.84022e-11, -0.8217 </transform>
- <string> "neck" </string>
- <transform> -1, -1.10548e-06, -9.37766e-09, 1.08766e-06, -0.985328, 0.170671, -1.97913e-07, 0.170671, 0.985328, -1.64727e-13, 5.96046e-08, -1.24906 </transform>
- <string> "headtracker" </string>
- <int> 4 </int>
- <transform> 1, 9.87793e-08, -1.09789e-06, 1.09743e-06, 0.00449866, 0.99999, 1.03717e-07, -0.99999, 0.00449866, 0, 5.96046e-08, -0.491774 </transform>
- <string> "head" </string>
- <int> 5 </int>
- <transform> -1, 2.36978e-07, 1.97097e-07, -2.5035e-07, -0.25144, -0.967873, -1.79807e-07, -0.967873, 0.25144, -2.94648e-10, 4.76837e-07, 0.00400549 </transform>
- <string> "vent" </string>
- <int> 6 </int>
- <transform> 1, -2.54965e-07, -1.4699e-08, 2.55005e-07, 0.999996, 0.00282324, 1.39791e-08, -0.00282325, 0.999996, -7.04808e-08, 0.270992, -1.2429 </transform>
- <string> "r-arm" </string>
- <transform> 0.11477, -0.699489, -0.705367, -0.802661, -0.483653, 0.349021, -0.585289, 0.526113, -0.616961, 0.940786, 0.107144, -0.773564 </transform>
- <string> "r-forearm" </string>
- <int> 8 </int>
- <transform> -0.859542, 0.0564943, 0.507934, 0.107631, -0.951571, 0.287973, 0.499604, 0.302194, 0.811834, 2.38419e-07, -4.76837e-07, -0.935513 </transform>
- <string> "l-arm" </string>
- <transform> 0.11477, 0.699489, 0.705367, 0.802661, -0.483653, 0.349021, 0.585289, 0.526113, -0.616961, -0.940786, 0.107144, -0.773564 </transform>
- <string> "l-forearm" </string>
- <int> 10 </int>
- <transform> -0.859542, -0.0564943, -0.507934, -0.107631, -0.951571, 0.287973, -0.499604, 0.302194, 0.811834, -2.38419e-07, -4.76837e-07, -0.935513 </transform>
- <string> "r-thigh" </string>
- <transform> 0.994883, -0.0545632, -0.085028, -0.0580629, -0.997541, -0.0392442, -0.0826777, 0.0439804, -0.995605, 0.349652, 0.0628238, -0.163877 </transform>
- <string> "r-leg" </string>
- <int> 12 </int>
- <transform> -0.999508, -0.031366, -0.000870243, 0.0312939, -0.994411, -0.100835, 0.00229738, -0.100812, 0.994903, 5.96046e-08, 5.96046e-08, -0.644636 </transform>
- <string> "r-foot" </string>
- <int> 13 </int>
- <transform> 0.996208, -0.0766666, -0.0411273, -0.0442384, -0.0393329, -0.998246, 0.0749145, 0.996281, -0.0425754, -5.96046e-08, 4.19095e-09, -1.43073 </transform>
- <string> "l-thigh" </string>
- <transform> 0.994883, 0.0545632, 0.085028, 0.0580633, -0.997541, -0.0392452, 0.0826776, 0.0439813, -0.995606, -0.349652, 0.0628238, -0.163877 </transform>
- <string> "l-leg" </string>
- <int> 15 </int>
- <transform> -0.999508, 0.0313662, 0.000870456, -0.0312941, -0.994411, -0.100836, -0.00229725, -0.100814, 0.994903, 0, 1.49012e-08, -0.644636 </transform>
- <string> "l-foot" </string>
- <int> 16 </int>
- <transform> 0.996208, 0.0766668, 0.0411275, 0.0442386, -0.0393327, -0.998246, -0.0749147, 0.996281, -0.0425752, 0, -8.3819e-09, -1.43073 </transform>
- <string> "HEAD" </string>
- <transform> 1, -1.50996e-07, -0, -1.50996e-07, -1, 0, 0, 0, -1, 5.68434e-14, -5.79659, 6.35228 </transform>
- <string> "r-LEGCONTROL" </string>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.518863, 3.72276e-07, 0.204768 </transform>
- <string> "l-LEGCONTROL" </string>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, -0.518863, 3.72276e-07, 0.204768 </transform>
- <string> "r-LEGORIENT" </string>
- <transform> -1, -1.50996e-07, -5.03577e-15, -3.75647e-14, 2.15429e-07, 1, -1.50996e-07, 1, -2.15429e-07, 0.411677, -0.66395, 1.62881 </transform>
- <string> "l-LEGORIENT" </string>
- <transform> -1, -1.50996e-07, -5.03577e-15, -3.75647e-14, 2.15429e-07, 1, -1.50996e-07, 1, -2.15429e-07, -0.411677, -0.66395, 1.62881 </transform>
- <string> "r-ARMCONTROL" </string>
- <transform> 1, 0, 0, 0, 7.54979e-08, -1, 0, 1, 7.54979e-08, 2.62535, -0.186879, 2.59016 </transform>
- <string> "l-ARMCONTROL" </string>
- <transform> 1, 0, 0, 0, 7.54979e-08, -1, 0, 1, 7.54979e-08, -2.62535, -0.186879, 2.59016 </transform>
- <string> "r-ARMORIENT" </string>
- <transform> 1, 0, 0, 0, 7.54979e-08, -1, 0, 1, 7.54979e-08, 1.57185, 0.510255, 3.44768 </transform>
- <string> "l-ARMORIENT" </string>
- <transform> 1, 0, 0, 0, 7.54979e-08, -1, 0, 1, 7.54979e-08, -1.57185, 0.510255, 3.44768 </transform>
- <resource resource_type="Mesh" path="local://5"> </resource>
- <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, -1.94071, 3.64079, 3.3802 </transform>
- <real> 180 </real>
- <real> -6 </real>
- <resource resource_type="SampleLibrary" path="local://6"> </resource>
- <node_path> ".." </node_path>
- <resource resource_type="Animation" path="local://7"> </resource>
- <resource resource_type="Animation" path="local://8"> </resource>
- <resource resource_type="Animation" path="local://9"> </resource>
- <resource resource_type="Animation" path="local://10"> </resource>
- <resource resource_type="Animation" path="local://11"> </resource>
- <resource resource_type="Animation" path="local://12"> </resource>
- <resource resource_type="Animation" path="local://13"> </resource>
- <resource resource_type="Animation" path="local://14"> </resource>
- <string> "" </string>
- <node_path> "../AnimationPlayer" </node_path>
- <dictionary shared="false">
- <string> "connections" </string>
- <array len="27" shared="false">
- <string> "walk" </string>
- <string> "scale" </string>
- <int> 0 </int>
- <string> "scale" </string>
- <string> "state" </string>
- <int> 0 </int>
- <string> "anim 3" </string>
- <string> "state" </string>
- <int> 1 </int>
- <string> "anim 4" </string>
- <string> "state" </string>
- <int> 2 </int>
- <string> "gun" </string>
- <string> "out" </string>
- <int> 0 </int>
- <string> "state" </string>
- <string> "gun" </string>
- <int> 0 </int>
- <string> "anim 5" </string>
- <string> "gun" </string>
- <int> 1 </int>
- <string> "anim" </string>
- <string> "walk" </string>
- <int> 0 </int>
- <string> "anim 2" </string>
- <string> "walk" </string>
- <int> 1 </int>
- </array>
- <string> "master" </string>
- <node_path> "../AnimationPlayer" </node_path>
- <string> "active" </string>
- <bool> True </bool>
- <string> "nodes" </string>
- <array len="10" shared="false">
- <dictionary shared="false">
- <string> "id" </string>
- <string> "scale" </string>
- <string> "scale" </string>
- <real> 1.2 </real>
- <string> "pos" </string>
- <vector2> 247, 68 </vector2>
- <string> "type" </string>
- <string> "timescale" </string>
- </dictionary>
- <dictionary shared="false">
- <string> "id" </string>
- <string> "state" </string>
- <string> "transitions" </string>
- <array len="3" shared="false">
- <dictionary shared="false">
- <string> "auto_advance" </string>
- <bool> False </bool>
- </dictionary>
- <dictionary shared="false">
- <string> "auto_advance" </string>
- <bool> False </bool>
- </dictionary>
- <dictionary shared="false">
- <string> "auto_advance" </string>
- <bool> False </bool>
- </dictionary>
- </array>
- <string> "xfade" </string>
- <real> 0.1 </real>
- <string> "type" </string>
- <string> "transition" </string>
- <string> "pos" </string>
- <vector2> 359, 132 </vector2>
- </dictionary>
- <dictionary shared="false">
- <string> "from" </string>
- <string> "idle" </string>
- <string> "id" </string>
- <string> "anim" </string>
- <string> "pos" </string>
- <vector2> 7, 70 </vector2>
- <string> "type" </string>
- <string> "animation" </string>
- </dictionary>
- <dictionary shared="false">
- <string> "id" </string>
- <string> "out" </string>
- <string> "type" </string>
- <string> "output" </string>
- <string> "pos" </string>
- <vector2> 579, 114 </vector2>
- </dictionary>
- <dictionary shared="false">
- <string> "from" </string>
- <string> "jump-up-cycle" </string>
- <string> "id" </string>
- <string> "anim 3" </string>
- <string> "pos" </string>
- <vector2> 143, 144 </vector2>
- <string> "type" </string>
- <string> "animation" </string>
- </dictionary>
- <dictionary shared="false">
- <string> "from" </string>
- <string> "shooting_standing" </string>
- <string> "id" </string>
- <string> "anim 5" </string>
- <string> "pos" </string>
- <vector2> 331, 242 </vector2>
- <string> "type" </string>
- <string> "animation" </string>
- </dictionary>
- <dictionary shared="false">
- <string> "from" </string>
- <string> "walk-cycle" </string>
- <string> "id" </string>
- <string> "anim 2" </string>
- <string> "pos" </string>
- <vector2> 7, 152 </vector2>
- <string> "type" </string>
- <string> "animation" </string>
- </dictionary>
- <dictionary shared="false">
- <string> "id" </string>
- <string> "gun" </string>
- <string> "blend" </string>
- <real> 1 </real>
- <string> "filter" </string>
- <array len="22" shared="false">
- <node_path> "Armature/Skeleton:MASTER" </node_path>
- <node_path> "Armature/Skeleton:l-thigh" </node_path>
- <node_path> "Armature/Skeleton:headtracker" </node_path>
- <node_path> "Armature/Skeleton:r-leg" </node_path>
- <node_path> "Armature/Skeleton:r-foot" </node_path>
- <node_path> "Armature/Skeleton:r-LEGORIENT" </node_path>
- <node_path> "Armature/Skeleton:r-LEGCONTROL" </node_path>
- <node_path> "Armature/Skeleton:r-ARMORIENT" </node_path>
- <node_path> "Armature/Skeleton:r-ARMCONTROL" </node_path>
- <node_path> "Armature/Skeleton:waist" </node_path>
- <node_path> "Armature/Skeleton:neck" </node_path>
- <node_path> "Armature/Skeleton:l-leg" </node_path>
- <node_path> "Armature/Skeleton:l-foot" </node_path>
- <node_path> "Armature/Skeleton:hip" </node_path>
- <node_path> "Armature/Skeleton:head" </node_path>
- <node_path> "Armature/Skeleton:HEAD" </node_path>
- <node_path> "Armature/Skeleton:l-LEGORIENT" </node_path>
- <node_path> "Armature/Skeleton:l-LEGCONTROL" </node_path>
- <node_path> "Armature/Skeleton:l-ARMORIENT" </node_path>
- <node_path> "Armature/Skeleton:l-ARMCONTROL" </node_path>
- <node_path> "Armature" </node_path>
- <node_path> "Armature/Skeleton:r-thigh" </node_path>
- </array>
- <string> "type" </string>
- <string> "blend2" </string>
- <string> "pos" </string>
- <vector2> 469, 127 </vector2>
- </dictionary>
- <dictionary shared="false">
- <string> "from" </string>
- <string> "falling-cycle" </string>
- <string> "id" </string>
- <string> "anim 4" </string>
- <string> "pos" </string>
- <vector2> 141, 230 </vector2>
- <string> "type" </string>
- <string> "animation" </string>
- </dictionary>
- <dictionary shared="false">
- <string> "id" </string>
- <string> "walk" </string>
- <string> "blend" </string>
- <real> 1 </real>
- <string> "filter" </string>
- <array len="0" shared="false">
- </array>
- <string> "type" </string>
- <string> "blend2" </string>
- <string> "pos" </string>
- <vector2> 148, 46 </vector2>
- </dictionary>
- </array>
- </dictionary>
- <vector2> 72, 301 </vector2>
- <vector2> 1, 1 </vector2>
- <resource resource_type="ImageTexture" path="res://osb_up.*"> </resource>
- <string> "move_forward" </string>
- <vector2> 72, 365 </vector2>
- <resource resource_type="ImageTexture" path="res://osb_down.*"> </resource>
- <string> "move_backwards" </string>
- <vector2> 29, 332 </vector2>
- <resource resource_type="ImageTexture" path="res://osb_left.*"> </resource>
- <string> "move_left" </string>
- <vector2> 108, 327 </vector2>
- <resource resource_type="ImageTexture" path="res://osb_right.*"> </resource>
- <string> "move_right" </string>
- </array>
- <string> "nodes" </string>
- <int_array len="662"> -1, -1, 1, 0, -1, 21, 2, 0, 3, 1, 4, 2, 5, 3, 6, 4, 7, 5, 8, 3, 9, 0, 10, 6, 11, 7, 12, 7, 13, 8, 14, 3, 15, 9, 16, 8, 17, 8, 18, 8, 19, 10, 20, 10, 21, 11, 22, 12, 0, 0, 0, 24, 23, -1, 3, 25, 2, 26, 1, 27, 3, 0, 0, 0, 24, 28, -1, 3, 25, 5, 26, 4, 27, 3, 0, 0, 0, 30, 29, -1, 1, 25, 13, 0, 3, 0, 32, 31, -1, 15, 25, 14, 33, 15, 34, 16, 35, 17, 36, 18, 37, 3, 38, 3, 39, 19, 40, 20, 21, 21, 41, 6, 42, 22, 43, 7, 44, 23, 45, 24, 0, 0, 0, 30, 46, -1, 1, 25, 25, 0, 5, 0, 47, 47, -1, 135, 48, 26, 49, 19, 50, 27, 51, 8, 52, 28, 53, 29, 54, 15, 55, 30, 56, 8, 57, 28, 58, 31, 59, 32, 60, 33, 61, 8, 62, 28, 63, 34, 64, 0, 65, 35, 66, 8, 67, 28, 68, 36, 69, 9, 70, 37, 71, 8, 72, 28, 73, 38, 74, 39, 75, 40, 76, 8, 77, 28, 78, 41, 79, 42, 80, 43, 81, 8, 82, 28, 83, 44, 84, 45, 85, 46, 86, 8, 87, 28, 88, 47, 89, 9, 90, 48, 91, 8, 92, 28, 93, 49, 94, 50, 95, 51, 96, 8, 97, 28, 98, 52, 99, 9, 100, 53, 101, 8, 102, 28, 103, 54, 104, 55, 105, 56, 106, 8, 107, 28, 108, 57, 109, 32, 110, 58, 111, 8, 112, 28, 113, 59, 114, 60, 115, 61, 116, 8, 117, 28, 118, 62, 119, 63, 120, 64, 121, 8, 122, 28, 123, 65, 124, 32, 125, 66, 126, 8, 127, 28, 128, 67, 129, 68, 130, 69, 131, 8, 132, 28, 133, 70, 134, 71, 135, 72, 136, 8, 137, 28, 138, 73, 139, 15, 140, 74, 141, 8, 142, 28, 143, 75, 144, 15, 145, 76, 146, 8, 147, 28, 148, 77, 149, 15, 150, 78, 151, 8, 152, 28, 153, 79, 154, 15, 155, 80, 156, 8, 157, 28, 158, 81, 159, 15, 160, 82, 161, 8, 162, 28, 163, 83, 164, 15, 165, 84, 166, 8, 167, 28, 168, 85, 169, 15, 170, 86, 171, 8, 172, 28, 173, 87, 174, 15, 175, 88, 176, 8, 177, 28, 178, 89, 179, 15, 180, 90, 181, 8, 182, 28, 0, 6, 0, 184, 183, -1, 12, 185, 32, 186, 8, 187, 20, 188, 8, 189, 8, 190, 7, 191, 7, 192, 3, 193, 3, 194, 3, 195, 3, 196, 91, 0, 5, 0, 198, 197, -1, 1, 25, 92, 0, 0, 0, 200, 199, -1, 9, 201, 7, 202, 6, 203, 6, 204, 18, 205, 6, 206, 93, 207, 94, 208, 32, 209, 95, 0, 0, 0, 210, 210, -1, 14, 211, 32, 212, 7, 213, 96, 214, 6, 215, 97, 216, 98, 217, 99, 218, 100, 219, 101, 220, 102, 221, 103, 222, 104, 223, 28, 224, 105, 0, 0, 0, 225, 225, -1, 4, 226, 8, 227, 96, 228, 106, 229, 107, 0, 0, 0, 231, 230, -1, 14, 232, 8, 233, 8, 234, 6, 235, 6, 236, 8, 237, 108, 238, 7, 239, 109, 240, 110, 241, 20, 242, 20, 243, 8, 244, 111, 245, 32, 0, 0, 0, 231, 246, -1, 14, 232, 8, 233, 8, 234, 6, 235, 6, 236, 8, 237, 112, 238, 7, 239, 109, 240, 113, 241, 20, 242, 20, 243, 8, 244, 114, 245, 32, 0, 0, 0, 231, 247, -1, 14, 232, 8, 233, 8, 234, 6, 235, 6, 236, 8, 237, 115, 238, 7, 239, 109, 240, 116, 241, 20, 242, 20, 243, 8, 244, 117, 245, 32, 0, 0, 0, 231, 248, -1, 14, 232, 8, 233, 8, 234, 6, 235, 6, 236, 8, 237, 118, 238, 7, 239, 109, 240, 119, 241, 20, 242, 20, 243, 8, 244, 120, 245, 32, 0 </int_array>
- <string> "conns" </string>
- <int_array len="0"> </int_array>
- </dictionary>
-
- </main_resource>
-</resource_file> \ No newline at end of file
diff --git a/demos/viewport/3d_in_2d/player_2d.scn b/demos/viewport/3d_in_2d/player_2d.scn
index eb6a09ae82..edb6c080c1 100644
--- a/demos/viewport/3d_in_2d/player_2d.scn
+++ b/demos/viewport/3d_in_2d/player_2d.scn
Binary files differ
diff --git a/demos/viewport/3d_in_2d/player_3d.scn b/demos/viewport/3d_in_2d/player_3d.scn
index 1dfd35adf4..c8bba5e460 100644
--- a/demos/viewport/3d_in_2d/player_3d.scn
+++ b/demos/viewport/3d_in_2d/player_3d.scn
Binary files differ
diff --git a/demos/viewport/gui_in_3d/gui.scn b/demos/viewport/gui_in_3d/gui.scn
index 4d665226b7..d7daa30340 100644
--- a/demos/viewport/gui_in_3d/gui.scn
+++ b/demos/viewport/gui_in_3d/gui.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 c2a9df0069..b93c17521d 100644
--- a/demos/viewport/gui_in_3d/gui_3d.gd
+++ b/demos/viewport/gui_in_3d/gui_3d.gd
@@ -1,45 +1,37 @@
extends Spatial
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-var prev_pos=null
-
-
-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)
-
-
-#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)
-
-
+# Member variables
+var prev_pos = null
+
+
+func _input(event):
+ # All other (non-mouse) events
+ if (not event.type in [InputEvent.MOUSE_BUTTON, InputEvent.MOUSE_MOTION, InputEvent.SCREEN_DRAG, InputEvent.SCREEN_TOUCH]):
+ get_node("viewport").input(event)
+
+
+# Mouse events for Area
+func _on_area_input_event(camera, event, 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
+ event.pos = pos
+ event.global_pos = pos
+ if (prev_pos == null):
+ prev_pos = pos
+ if (event.type == InputEvent.MOUSE_MOTION):
+ event.relative_pos = pos - prev_pos
+ prev_pos = pos
+ # Send the event to the viewport
+ get_node("viewport").input(event)
+
func _ready():
- # Initalization here
- get_node("area/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 c69d4dc73f..0541e7b142 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/demos/viewport/screen_capture/screen_capture.gd b/demos/viewport/screen_capture/screen_capture.gd
index 69f16fa498..9867d95452 100644
--- a/demos/viewport/screen_capture/screen_capture.gd
+++ b/demos/viewport/screen_capture/screen_capture.gd
@@ -1,27 +1,16 @@
extends Control
-# member variables here, example:
-# var a=2
-# var b="textvar"
-
-func _ready():
- # Initialization here
- pass
-
-
-
func _on_button_pressed():
get_viewport().queue_screen_capture()
- #let two frames pass to make sure the screen was aptured
- yield(get_tree(),"idle_frame")
- yield(get_tree(),"idle_frame")
- #retrieve the captured image
+ # Let two frames pass to make sure the screen was captured
+ yield(get_tree(), "idle_frame")
+ yield(get_tree(), "idle_frame")
+ # Retrieve the captured image
var img = get_viewport().get_screen_capture()
- #create a texture for it
+ # Create a texture for it
var tex = ImageTexture.new()
tex.create_from_image(img)
- #set it to the capture node
+ # Set it to the capture node
get_node("capture").set_texture(tex)
- pass # replace with function body
diff --git a/demos/viewport/screen_capture/screen_capture.scn b/demos/viewport/screen_capture/screen_capture.scn
index d204e3b67e..ee847fbe62 100644
--- a/demos/viewport/screen_capture/screen_capture.scn
+++ b/demos/viewport/screen_capture/screen_capture.scn
Binary files differ
diff --git a/Doxyfile b/doc/Doxyfile
index 4268ed8c7d..c1904f17c9 100644
--- a/Doxyfile
+++ b/doc/Doxyfile
@@ -51,14 +51,14 @@ PROJECT_BRIEF = "Game Engine MIT"
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
-PROJECT_LOGO = ./logo_small.png
+PROJECT_LOGO = ../logo.png
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
-OUTPUT_DIRECTORY = ./doc/doxygen/
+OUTPUT_DIRECTORY = ./_build/doxygen/
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
@@ -768,7 +768,7 @@ WARN_LOGFILE =
# spaces.
# Note: If this tag is empty the current directory is searched.
-INPUT = ./core/ ./main/ ./scene/
+INPUT = ../core/ ../main/ ../scene/
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000000..286a5162af
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,47 @@
+BASEDIR = $(CURDIR)
+CLASSES = $(BASEDIR)/base/classes.xml
+OUTPUTDIR = $(BASEDIR)/_build
+TOOLSDIR = $(BASEDIR)/tools
+
+.ONESHELL:
+
+clean:
+ rm -rf $(OUTPUTDIR)
+
+doku:
+ rm -rf $(OUTPUTDIR)/doku
+ mkdir -p $(OUTPUTDIR)/doku
+ pushd $(OUTPUTDIR)/doku
+ python2 $(TOOLSDIR)/makedoku.py $(CLASSES)
+ popd
+
+doxygen:
+ rm -rf $(OUTPUTDIR)/doxygen
+ mkdir -p $(OUTPUTDIR)/doxygen
+ doxygen Doxyfile
+
+html:
+ rm -rf $(OUTPUTDIR)/html
+ mkdir -p $(OUTPUTDIR)/html
+ pushd $(OUTPUTDIR)/html
+ python2 $(TOOLSDIR)/makehtml.py -multipage $(CLASSES)
+ popd
+
+markdown:
+ rm -rf $(OUTPUTDIR)/markdown
+ mkdir -p $(OUTPUTDIR)/markdown
+ pushd $(OUTPUTDIR)/markdown
+ python2 $(TOOLSDIR)/makemd.py $(CLASSES)
+ popd
+
+rst:
+ rm -rf $(OUTPUTDIR)/rst
+ mkdir -p $(OUTPUTDIR)/rst
+ pushd $(OUTPUTDIR)/rst
+ echo "TODO"
+ popd
+
+textile:
+ rm -rf $(OUTPUTDIR)/textile
+ mkdir -p $(OUTPUTDIR)/textile
+ python3 $(TOOLSDIR)/makedocs.py --input $(CLASSES) --output $(OUTPUTDIR)/textile
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index fd5df945ba..8128771b6a 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -432,7 +432,7 @@
<method name="convert">
<return type="Object">
</return>
- <argument index="0" name="what" type="var">
+ <argument index="0" name="what" type="Variant">
</argument>
<argument index="1" name="type" type="int">
</argument>
@@ -443,9 +443,9 @@
<method name="str">
<return type="String">
</return>
- <argument index="0" name="what" type="var">
+ <argument index="0" name="what" type="Variant">
</argument>
- <argument index="1" name="..." type="var">
+ <argument index="1" name="..." type="Variant">
</argument>
<description>
Convert one or more arguments to strings in the best way possible.
@@ -454,9 +454,9 @@
<method name="str">
<return type="String">
</return>
- <argument index="0" name="what" type="var">
+ <argument index="0" name="what" type="Variant">
</argument>
- <argument index="1" name="..." type="var">
+ <argument index="1" name="..." type="Variant">
</argument>
<description>
Convert one or more arguments to strings in the best way possible.
@@ -465,9 +465,9 @@
<method name="print">
<return type="Nil">
</return>
- <argument index="0" name="what" type="var">
+ <argument index="0" name="what" type="Variant">
</argument>
- <argument index="1" name="..." type="var">
+ <argument index="1" name="..." type="Variant">
</argument>
<description>
Print one or more arguments to strings in the best way possible to a console line.
@@ -476,9 +476,9 @@
<method name="printt">
<return type="Nil">
</return>
- <argument index="0" name="what" type="var">
+ <argument index="0" name="what" type="Variant">
</argument>
- <argument index="1" name="..." type="var">
+ <argument index="1" name="..." type="Variant">
</argument>
<description>
Print one or more arguments to the console with a tab between each argument.
@@ -487,9 +487,9 @@
<method name="prints">
<return type="Nil">
</return>
- <argument index="0" name="what" type="var">
+ <argument index="0" name="what" type="Variant">
</argument>
- <argument index="1" name="..." type="var">
+ <argument index="1" name="..." type="Variant">
</argument>
<description>
</description>
@@ -497,9 +497,9 @@
<method name="printerr">
<return type="Nil">
</return>
- <argument index="0" name="what" type="var">
+ <argument index="0" name="what" type="Variant">
</argument>
- <argument index="1" name="..." type="var">
+ <argument index="1" name="..." type="Variant">
</argument>
<description>
Print one or more arguments to strings in the best way possible to standard error line.
@@ -508,9 +508,9 @@
<method name="printraw">
<return type="Nil">
</return>
- <argument index="0" name="what" type="var">
+ <argument index="0" name="what" type="Variant">
</argument>
- <argument index="1" name="..." type="var">
+ <argument index="1" name="..." type="Variant">
</argument>
<description>
Print one or more arguments to strings in the best way possible to console. No newline is added at the end.
@@ -519,25 +519,40 @@
<method name="var2str">
<return type="String">
</return>
- <argument index="0" name="var" type="var">
+ <argument index="0" name="var" type="Variant">
</argument>
<description>
Converts the value of a variable to a String.
</description>
</method>
- <method name="str2var:var">
- <return type="Nil">
+ <method name="str2var">
+ <return type="Variant">
</return>
<argument index="0" name="string" type="String">
</argument>
<description>
- Converts the value of a String to a variable.
+ </description>
+ </method>
+ <method name="var2bytes">
+ <return type="RawArray">
+ </return>
+ <argument index="0" name="var" type="Variant">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="bytes2var">
+ <return type="Variant">
+ </return>
+ <argument index="0" name="bytes" type="RawArray">
+ </argument>
+ <description>
</description>
</method>
<method name="range">
<return type="Array">
</return>
- <argument index="0" name="..." type="var">
+ <argument index="0" name="..." type="Variant">
</argument>
<description>
Return an array with the given range. Range can be 1 argument N (0 to N-1), two arguments (initial, final-1) or three arguments (initial,final-1,increment).
@@ -573,12 +588,26 @@
<method name="hash">
<return type="int">
</return>
- <argument index="0" name="var:var" type="var">
+ <argument index="0" name="var:Variant" type="Variant">
</argument>
<description>
Hashes the variable passed and returns an integer.
</description>
</method>
+ <method name="Color8">
+ <return type="Color">
+ </return>
+ <argument index="0" name="r8" type="int">
+ </argument>
+ <argument index="1" name="g8" type="int">
+ </argument>
+ <argument index="2" name="b8" type="int">
+ </argument>
+ <argument index="3" name="a8" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="print_stack">
<return type="Nil">
</return>
@@ -1371,6 +1400,10 @@
</constant>
<constant name="JOY_ANALOG_2_Y" value="5">
</constant>
+ <constant name="JOY_ANALOG_L2" value="6">
+ </constant>
+ <constant name="JOY_ANALOG_R2" value="7">
+ </constant>
<constant name="OK" value="0">
Functions that return [Error] return OK when everything went ok. Most functions don't return error anyway and/or just print errors to stdout.
</constant>
@@ -1849,6 +1882,8 @@
</description>
</method>
<method name="register_text_enter">
+ <return type="LineEdit">
+ </return>
<argument index="0" name="line_edit" type="Object">
</argument>
<description>
@@ -2412,7 +2447,7 @@
</class>
<class name="AnimationPlayer" inherits="Node" category="Core">
<brief_description>
- Container and player of [Animaton] resources.
+ Container and player of [Animation] resources.
</brief_description>
<description>
An animation player is used for general purpose playback of [Animation] resources. It contains a dictionary of animations (referenced by name) and custom blend times between their transitions. Additionally, animations can be played and blended in diferent channels.
@@ -3257,6 +3292,12 @@
<argument index="0" name="enable" type="int">
</argument>
<description>
+ Set the space override mode. This mode controls how an area affects gravity and damp.
+ AREA_SPACE_OVERRIDE_DISABLED: This area does not affect gravity/damp. These are generally areas that exist only to detect collisions, and objects entering or exiting them.
+ AREA_SPACE_OVERRIDE_COMBINE: This area adds its gravity/damp values to whatever has been calculated so far. This way, many overlapping areas can combine their physics to make interesting effects.
+ AREA_SPACE_OVERRIDE_COMBINE_REPLACE: This area adds its gravity/damp values to whatever has been calculated so far. Then stops taking into account the rest of the areas, even the default one.
+ AREA_SPACE_OVERRIDE_REPLACE: This area replaces any gravity/damp, even the default one, and stops taking into account the rest of the areas.
+ AREA_SPACE_OVERRIDE_REPLACE_COMBINE: This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one.
</description>
</method>
<method name="get_space_override_mode" qualifiers="const">
@@ -3481,133 +3522,162 @@
</class>
<class name="Area2D" inherits="CollisionObject2D" category="Core">
<brief_description>
- General purpose area detection and influence for 2D Phisics.
+ General purpose area detection and influence for 2D physics.
</brief_description>
<description>
- General purpose area detection for 2D Phisics. Areas can be used for detection of objects that enter/exit them, as well as overriding space parameters (changing gravity, damping, etc). An Area2D can be set as a children to a RigidBody2D to generate a custom gravity field. For this, use SPACE_OVERRIDE_COMBINE and point gravity at the center of mass.
+ General purpose area detection for 2D physics. Areas can be used for detection of objects that enter/exit them, as well as overriding space parameters (changing gravity, damping, etc). For this, use any space override different from AREA_SPACE_OVERRIDE_DISABLE and point gravity at the center of mass.
</description>
<methods>
<method name="set_space_override_mode">
<argument index="0" name="enable" type="int">
</argument>
<description>
+ Set the space override mode. This mode controls how an area affects gravity and damp.
+ AREA_SPACE_OVERRIDE_DISABLED: This area does not affect gravity/damp. These are generally areas that exist only to detect collisions, and objects entering or exiting them.
+ AREA_SPACE_OVERRIDE_COMBINE: This area adds its gravity/damp values to whatever has been calculated so far. This way, many overlapping areas can combine their physics to make interesting effects.
+ AREA_SPACE_OVERRIDE_COMBINE_REPLACE: This area adds its gravity/damp values to whatever has been calculated so far. Then stops taking into account the rest of the areas, even the default one.
+ AREA_SPACE_OVERRIDE_REPLACE: This area replaces any gravity/damp, even the default one, and stops taking into account the rest of the areas.
+ AREA_SPACE_OVERRIDE_REPLACE_COMBINE: This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one.
</description>
</method>
<method name="get_space_override_mode" qualifiers="const">
<return type="int">
</return>
<description>
+ Return the space override mode.
</description>
</method>
<method name="set_gravity_is_point">
<argument index="0" name="enable" type="bool">
</argument>
<description>
- When overriding space parameters, areas can have a center of gravity as a point.
+ When overriding space parameters, this method sets whether this area has a center of gravity. To set/get the location of the center of gravity, use [method set_gravity_vector]/[method get_gravity_vector].
</description>
</method>
<method name="is_gravity_a_point" qualifiers="const">
<return type="bool">
</return>
<description>
- Return if gravity is a point. When overriding space parameters, areas can have a center of gravity as a point.
+ Return whether gravity is a point. A point gravity will attract objects towards it, as opposed to a gravity vector, which moves them in a given direction.
</description>
</method>
<method name="set_gravity_distance_scale">
<argument index="0" name="distance_scale" type="float">
</argument>
<description>
+ Set the falloff factor for point gravity. The greater this value is, the faster the strength of gravity decreases with the square of distance.
</description>
</method>
<method name="get_gravity_distance_scale" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the falloff factor for point gravity.
</description>
</method>
<method name="set_gravity_vector">
<argument index="0" name="vector" type="Vector2">
</argument>
<description>
- Set gravity vector. If gravity is a point, this will be the attraction center.
+ Set the gravity vector. This vector does not have to be normalized.
+ If gravity is a point (see [method is_gravity_a_point]), this will be the attraction center.
</description>
</method>
<method name="get_gravity_vector" qualifiers="const">
<return type="Vector2">
</return>
<description>
+ Return the gravity vector. If gravity is a point (see [method is_gravity_a_point]), this will be the attraction center.
</description>
</method>
<method name="set_gravity">
<argument index="0" name="gravity" type="float">
</argument>
<description>
+ Set the gravity intensity. This is useful to alter the force of gravity without altering its direction.
+ This value multiplies the gravity vector, whether it is the given vector ([method set_gravity_vector]), or a calculated one (when using a center of gravity).
</description>
</method>
<method name="get_gravity" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the gravity intensity.
</description>
</method>
<method name="set_linear_damp">
<argument index="0" name="linear_damp" type="float">
</argument>
<description>
+ Set the rate at which objects stop moving in this area, if there are not any other forces moving it. The value is a fraction of its current speed, lost per second. Thus, a value of 1.0 should mean stopping immediately, and 0.0 means the object never stops.
+ In practice, as the fraction of speed lost gets smaller with each frame, a value of 1.0 does not mean the object will stop in exactly one second. Only when the physics calculations are done at 1 frame per second, it does stop in a second.
</description>
</method>
<method name="get_linear_damp" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the linear damp rate.
</description>
</method>
<method name="set_angular_damp">
<argument index="0" name="angular_damp" type="float">
</argument>
<description>
+ Set the rate at which objects stop spinning in this area, if there are not any other forces making it spin. The value is a fraction of its current speed, lost per second. Thus, a value of 1.0 should mean stopping immediately, and 0.0 means the object never stops.
+ In practice, as the fraction of speed lost gets smaller with each frame, a value of 1.0 does not mean the object will stop in exactly one second. Only when the physics calculations are done at 1 frame per second, it does stop in a second.
</description>
</method>
<method name="get_angular_damp" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the angular damp rate.
</description>
</method>
<method name="set_priority">
<argument index="0" name="priority" type="float">
</argument>
<description>
+ Set the order in which the area is processed. Greater values mean the area gets processed first. This is useful for areas which have an space override different from AREA_SPACE_OVERRIDE_DISABLED or AREA_SPACE_OVERRIDE_COMBINE, as they replace values, and are thus order-dependent.
+ Areas with the same priority value get evaluated in an unpredictable order, and should be differentiated if evaluation order is to be important.
</description>
</method>
<method name="get_priority" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the processing order of this area.
</description>
</method>
<method name="set_collision_mask">
<argument index="0" name="collision_mask" type="int">
</argument>
<description>
+ Set the physics layers this area can scan for collisions.
</description>
</method>
<method name="get_collision_mask" qualifiers="const">
<return type="int">
</return>
<description>
+ Return the physics layers this area can scan for collisions.
</description>
</method>
<method name="set_layer_mask">
<argument index="0" name="layer_mask" type="int">
</argument>
<description>
+ Set the physics layers this area is in.
+ Collidable objects can exist in any of 32 different layers. These layers are not visual, but more of a tagging system instead. A collidable can use these layers/tags to select with which objects it can collide, using [method set_collision_mask].
+ A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A.
</description>
</method>
<method name="get_layer_mask" qualifiers="const">
<return type="int">
</return>
<description>
+ Return the physics layer this area is in.
</description>
</method>
<method name="set_collision_mask_bit">
@@ -3616,6 +3686,7 @@
<argument index="1" name="value" type="bool">
</argument>
<description>
+ Set/clear individual bits on the collision mask. This makes selecting the areas scanned easier.
</description>
</method>
<method name="get_collision_mask_bit" qualifiers="const">
@@ -3624,6 +3695,7 @@
<argument index="0" name="bit" type="int">
</argument>
<description>
+ Return an individual bit on the collision mask.
</description>
</method>
<method name="set_layer_mask_bit">
@@ -3632,6 +3704,7 @@
<argument index="1" name="value" type="bool">
</argument>
<description>
+ Set/clear individual bits on the layer mask. This makes getting an area in/out of only one layer easier.
</description>
</method>
<method name="get_layer_mask_bit" qualifiers="const">
@@ -3640,42 +3713,49 @@
<argument index="0" name="bit" type="int">
</argument>
<description>
+ Return an individual bit on the layer mask.
</description>
</method>
<method name="set_enable_monitoring">
<argument index="0" name="enable" type="bool">
</argument>
<description>
+ Set whether this area can detect bodies/areas entering/exiting it.
</description>
</method>
<method name="is_monitoring_enabled" qualifiers="const">
<return type="bool">
</return>
<description>
+ Return whether this area detects bodies/areas entering/exiting it.
</description>
</method>
<method name="set_monitorable">
<argument index="0" name="enable" type="bool">
</argument>
<description>
+ Set whether this area can be detected by other, monitoring, areas. Only areas need to be marked as monitorable. Bodies are always so.
</description>
</method>
<method name="is_monitorable" qualifiers="const">
<return type="bool">
</return>
<description>
+ Set whether this area can be detected by other, monitoring, areas.
</description>
</method>
<method name="get_overlapping_bodies" qualifiers="const">
<return type="Array">
</return>
<description>
+ Return a list of the bodies ([PhysicsBody2D]) that are totally or partially inside this area.
</description>
</method>
<method name="get_overlapping_areas" qualifiers="const">
<return type="Array">
</return>
<description>
+ Return a list of the areas that are totally or partially inside this area.
</description>
</method>
<method name="overlaps_body" qualifiers="const">
@@ -3684,6 +3764,7 @@
<argument index="0" name="body" type="Object">
</argument>
<description>
+ Return whether the body passed is totally or partially inside this area.
</description>
</method>
<method name="overlaps_area" qualifiers="const">
@@ -3692,6 +3773,7 @@
<argument index="0" name="area" type="Object">
</argument>
<description>
+ Return whether the area passed is totally or partially inside this area.
</description>
</method>
</methods>
@@ -3700,6 +3782,7 @@
<argument index="0" name="body" type="Object">
</argument>
<description>
+ This signal is triggered only once when a body enters this area. The only parameter passed is the body that entered this area.
</description>
</signal>
<signal name="body_enter_shape">
@@ -3712,12 +3795,14 @@
<argument index="3" name="area_shape" type="int">
</argument>
<description>
+ This signal triggers only once when a body enters this area. The first parameter is the body's [RID]. The second one is the body as an object. The third one is the index of the shape of the body that entered this area, and the fourth one is the index of the shape in this area that repored the entering.
</description>
</signal>
<signal name="area_enter">
<argument index="0" name="area" type="Object">
</argument>
<description>
+ This signal is triggered only once when an area enters this area. The only parameter passed is the area that entered this area.
</description>
</signal>
<signal name="area_enter_shape">
@@ -3730,12 +3815,14 @@
<argument index="3" name="area_shape" type="int">
</argument>
<description>
+ This signal triggers only once when an area enters this area. The first parameter is the area's [RID]. The second one is the area as an object. The third one is the index of the shape entering this area, and the fourth one is the index of the shape in this area that reported the entering.
</description>
</signal>
<signal name="body_exit">
<argument index="0" name="body" type="Object">
</argument>
<description>
+ This signal is triggered only once when a body exits this area. The only parameter passed is the body that exited this area.
</description>
</signal>
<signal name="body_exit_shape">
@@ -3748,12 +3835,14 @@
<argument index="3" name="area_shape" type="int">
</argument>
<description>
+ This signal triggers only once when a body exits this area. The first parameter is the body's [RID]. The second one is the body as an object. The third one is the index of the shape exiting this area, and the fourth one is the index of the shape in this area that reported the exit.
</description>
</signal>
<signal name="area_exit">
<argument index="0" name="area" type="Object">
</argument>
<description>
+ This signal is triggered only once when an area exits this area. The only parameter passed is the area that exited this area.
</description>
</signal>
<signal name="area_exit_shape">
@@ -3766,6 +3855,7 @@
<argument index="3" name="area_shape" type="int">
</argument>
<description>
+ This signal triggers only once when an area exits this area. The first parameter is the area's [RID]. The second one is the area as an object. The third one is the index of the shape entering this area, and the fourth one is the index of the shape in this area that reported the entering.
</description>
</signal>
</signals>
@@ -3843,6 +3933,14 @@
Get whether this is a shared array instance.
</description>
</method>
+ <method name="pop_back">
+ <description>
+ </description>
+ </method>
+ <method name="pop_front">
+ <description>
+ </description>
+ </method>
<method name="push_back">
<argument index="0" name="value" type="var">
</argument>
@@ -3850,6 +3948,12 @@
Append an element at the end of the array.
</description>
</method>
+ <method name="push_front">
+ <argument index="0" name="value" type="var">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="remove">
<argument index="0" name="pos" type="int">
</argument>
@@ -4016,7 +4120,8 @@
<argument index="2" name="length" type="int">
</argument>
<description>
- Create an audio sample, return a [RID] referencing it. The sample will be created with a given format (from the SAMPLE_FORMAT_* enum), a total length (in frames, not samples or bytes), in either stereo or mono.
+ Create an audio sample, return a [RID] referencing it. The sample will be created with a given format (from the SAMPLE_FORMAT_* enum), a total length (in samples, not bytes), in either stereo or mono.
+ Even if a stereo sample consists of a left sample and a right sample, it still counts as one sample for length purposes.
</description>
</method>
<method name="sample_set_description">
@@ -4033,8 +4138,6 @@
</return>
<argument index="0" name="sample" type="RID">
</argument>
- <argument index="1" name="arg1" type="String">
- </argument>
<description>
Return the description of an audio sample. Mainly used for organization.
</description>
@@ -4054,7 +4157,7 @@
<argument index="0" name="sample" type="RID">
</argument>
<description>
- Return wether the sample is stereo (2 channels)
+ Return whether the sample is stereo (2 channels).
</description>
</method>
<method name="sample_get_length" qualifiers="const">
@@ -4063,7 +4166,7 @@
<argument index="0" name="sample" type="RID">
</argument>
<description>
- Return the length in frames of the audio sample (not samples or bytes).
+ Return the length in samples (not bytes) of the audio sample. Even if a stereo sample consists of a left sample and a right sample, it still counts as one sample for length purposes.
</description>
</method>
<method name="sample_set_signed_data">
@@ -4073,15 +4176,21 @@
</argument>
<description>
Set the sample data for a given sample as an array of floats. The length must be equal to the sample lenght or an error will be produced.
+ For this method, a stereo sample is made from two samples. Thus, in case of a stereo sample, the array length must be twice the length returned by [method sample_get_length].
+ Trying to alter a SAMPLE_FORMAT_IMA_ADPCM sample is not supported. It will throw an error to the console, but will not alter the sample data.
</description>
</method>
<method name="sample_set_data">
<argument index="0" name="sample" type="RID">
</argument>
- <argument index="1" name="arg1" type="RawArray">
+ <argument index="1" name="data" type="RawArray">
</argument>
<description>
- Set the sample data for a given sample as an array of bytes. The length must be equal to the sample lenght expected in bytes or an error will be produced.
+ Set the sample data for a given sample as an array of bytes. The length must be equal to the sample lenght expected in bytes or an error will be produced. The byte length can be calculated as follows:
+ Get the sample length ([method get_sample_length]).
+ If the sample format is SAMPLE_FORMAT_PCM16, multiply it by 2.
+ If the sample format is SAMPLE_FORMAT_IMA_ADPCM, divide it by 2 (rounding any fraction up), then add 4.
+ If the sample is stereo ([method sample_is_stereo]), multiply it by 2.
</description>
</method>
<method name="sample_get_data" qualifiers="const">
@@ -4396,24 +4505,28 @@
<argument index="0" name="scale" type="float">
</argument>
<description>
+ Set global scale for all voices (not including streams). Default is 1.0.
</description>
</method>
<method name="get_fx_global_volume_scale" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the global scale for all voices.
</description>
</method>
<method name="set_event_voice_global_volume_scale">
<argument index="0" name="scale" type="float">
</argument>
<description>
+ Set global scale for event-based stream ([EventStream]) playback. Default is 1.0.
</description>
</method>
<method name="get_event_voice_global_volume_scale" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the global scale for event-based stream playback.
</description>
</method>
</methods>
@@ -4422,7 +4535,7 @@
Sample format is 8 bits, signed.
</constant>
<constant name="SAMPLE_FORMAT_PCM16" value="1">
- Sample format is 16 bits, signed.
+ Sample format is 16 bits, little-endian, signed.
</constant>
<constant name="SAMPLE_FORMAT_IMA_ADPCM" value="2">
Sample format is IMA-ADPCM compressed.
@@ -4470,8 +4583,11 @@
</class>
<class name="AudioServerSW" inherits="AudioServer" category="Core">
<brief_description>
+ Software implementation of [AudioServer].
</brief_description>
<description>
+ This is a software audio server. It does not use any kind of hardware acceleration.
+ This class does not expose any new method.
</description>
<methods>
</methods>
@@ -5891,7 +6007,7 @@
</description>
</method>
<method name="set_zoom">
- <argument index="0" name="arg0" type="Vector2">
+ <argument index="0" name="zoom" type="Vector2">
</argument>
<description>
</description>
@@ -5914,6 +6030,18 @@
<description>
</description>
</method>
+ <method name="set_enable_follow_smoothing">
+ <argument index="0" name="follow_smoothing" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="is_follow_smoothing_enabled" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="force_update_scroll">
<description>
Force the camera to update scroll immediately.
@@ -6006,6 +6134,12 @@
Hide the CanvasItem currently visible.
</description>
</method>
+ <method name="set_hidden">
+ <argument index="0" name="hidden" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="update">
<description>
Queue the CanvasItem for update. NOTIFICATION_DRAW will be called on idle time to request redraw.
@@ -6131,6 +6265,8 @@
</argument>
<argument index="1" name="pos" type="Vector2">
</argument>
+ <argument index="2" name="modulate" type="Color" default="Color(1,1,1,1)">
+ </argument>
<description>
Draw a texture at a given position.
</description>
@@ -6969,7 +7105,7 @@
Base node for 2D collisionables.
</brief_description>
<description>
- CollisionObject2D is the base class for 2D physics collisionables. They can hold any number of 2D collision shapes. Usually, they are edited by placing [CollisionBody2D] and [CollisionPolygon2D] nodes as children. Such nodes are for reference and not present outside the editor, so code should use the regular shape API.
+ CollisionObject2D is the base class for 2D physics collisionables. They can hold any number of 2D collision shapes. Usually, they are edited by placing [CollisionShape2D] and/or [CollisionPolygon2D] nodes as children. Such nodes are for reference and not present outside the editor, so code should use the regular shape API.
</description>
<methods>
<method name="_input_event" qualifiers="virtual">
@@ -6980,6 +7116,7 @@
<argument index="2" name="shape_idx" type="int">
</argument>
<description>
+ This method can be used to override normal input processing. The first parameter is the viewport where the event took place. The second holds the input event received, and the third the shape of this object where it happened.
</description>
</method>
<method name="add_shape">
@@ -6995,7 +7132,7 @@
<return type="int">
</return>
<description>
- Return the amount of shapes in the collision body.
+ Return the amount of shapes in the collision body. Because a [CollisionPolygon2D] can generate more than one [Shape2D], the amount returned does not have to match the sum of [CollisionShape2D] and [CollisionPolygon2D].
</description>
</method>
<method name="set_shape">
@@ -7022,6 +7159,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ Set whether a shape is a trigger. A trigger shape detects collisions, but is otherwise unaffected by physics (i.e. colliding objects will not get blocked).
</description>
</method>
<method name="get_shape" qualifiers="const">
@@ -7048,6 +7186,7 @@
<argument index="0" name="shape_idx" type="int">
</argument>
<description>
+ Return whether a shape is a trigger. A trigger shape detects collisions, but is otherwise unaffected by physics (i.e. colliding objects will not get blocked).
</description>
</method>
<method name="remove_shape">
@@ -7066,25 +7205,28 @@
<return type="RID">
</return>
<description>
- Return the RID of the object.
+ Return the RID of this object.
</description>
</method>
<method name="set_pickable">
<argument index="0" name="enabled" type="bool">
</argument>
<description>
+ Set whether this object is pickable. A pickable object can detect the mouse pointer enter/leave it and, if the mouse is inside it, report input events.
</description>
</method>
<method name="is_pickable" qualifiers="const">
<return type="bool">
</return>
<description>
+ Return whether this object is pickable.
</description>
</method>
</methods>
<signals>
<signal name="mouse_enter">
<description>
+ This event fires only once when the mouse pointer enters any shape of this object.
</description>
</signal>
<signal name="input_event">
@@ -7095,10 +7237,12 @@
<argument index="2" name="shape_idx" type="int">
</argument>
<description>
+ This signal triggers when an input event fires over a shape. The first parameter is the viewport where the event took place. The second holds the input event received, and the third the shape of this object where it happened.
</description>
</signal>
<signal name="mouse_exit">
<description>
+ This event fires only once when the mouse pointer exits all shapes of this object.
</description>
</signal>
</signals>
@@ -7112,7 +7256,7 @@
</description>
<methods>
<method name="set_build_mode">
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="build_mode" type="int">
</argument>
<description>
</description>
@@ -7187,7 +7331,7 @@
</description>
</method>
<method name="set_build_mode">
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="build_mode" type="int">
</argument>
<description>
Set whether the polygon is to be a [ConvexPolygon2D] ([code]build_mode[/code]=0), or a [ConcavePolygon2D] ([code]build_mode[/code]=1).
@@ -7201,7 +7345,7 @@
</description>
</method>
<method name="set_trigger">
- <argument index="0" name="arg0" type="bool">
+ <argument index="0" name="trigger" type="bool">
</argument>
<description>
Set whether this polygon is a trigger. A trigger polygon detects collisions, but is otherwise unaffected by physics (i.e. colliding objects will not get blocked).
@@ -7241,7 +7385,7 @@
</description>
<methods>
<method name="resource_changed">
- <argument index="0" name="arg0" type="Object">
+ <argument index="0" name="resource" type="Object">
</argument>
<description>
</description>
@@ -7464,6 +7608,14 @@
</member>
<member name="v" type="float">
</member>
+ <member name="r8" type="int">
+ </member>
+ <member name="g8" type="int">
+ </member>
+ <member name="b8" type="int">
+ </member>
+ <member name="a8" type="int">
+ </member>
</members>
<constants>
</constants>
@@ -7671,6 +7823,66 @@
<description>
</description>
<methods>
+ <method name="add_point">
+ <argument index="0" name="offset" type="float">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="remove_point">
+ <argument index="0" name="offset" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_offset">
+ <argument index="0" name="point" type="int">
+ </argument>
+ <argument index="1" name="offset" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_offset" qualifiers="const">
+ <return type="float">
+ </return>
+ <argument index="0" name="point" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_color">
+ <argument index="0" name="point" type="int">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_color" qualifiers="const">
+ <return type="Color">
+ </return>
+ <argument index="0" name="point" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="interpolate">
+ <return type="Color">
+ </return>
+ <argument index="0" name="offset" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_point_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="set_offsets">
<argument index="0" name="offsets" type="RealArray">
</argument>
@@ -7811,6 +8023,8 @@
</argument>
<argument index="1" name="key" type="String">
</argument>
+ <argument index="2" name="default" type="var" default="NULL">
+ </argument>
<description>
</description>
</method>
@@ -7841,7 +8055,7 @@
<method name="get_section_keys" qualifiers="const">
<return type="StringArray">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="section" type="String">
</argument>
<description>
</description>
@@ -8087,6 +8301,18 @@
Move the Control to a new position, relative to the top-left corner of the [i]window[/i] Control, and without changing current anchor mode. (see [method set_margin]).
</description>
</method>
+ <method name="set_rotation">
+ <argument index="0" name="rotation" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_scale">
+ <argument index="0" name="scale" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="get_margin" qualifiers="const">
<return type="float">
</return>
@@ -8123,6 +8349,18 @@
Returns the size of the Control, computed from all margins, however the size returned will [b]never be smaller than the minimum size reported by [method get_minimum_size][/b]. This means that even if end position of the Control rectangle is smaller than the begin position, the Control will still display and interact correctly. (see description, [method get_minimum_size], [method set_margin], [method set_anchor]).
</description>
</method>
+ <method name="get_rotation" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_scale" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_custom_minimum_size" qualifiers="const">
<return type="Vector2">
</return>
@@ -9539,7 +9777,7 @@ This approximation makes straight segments between each point, then subdivides t
</description>
</method>
<method name="set_show_hidden_files">
- <argument index="0" name="arg0" type="bool">
+ <argument index="0" name="show" type="bool">
</argument>
<description>
</description>
@@ -10006,172 +10244,204 @@ This approximation makes straight segments between each point, then subdivides t
</class>
<class name="EventPlayer" inherits="Node" category="Core">
<brief_description>
+ Class for event stream playback.
</brief_description>
<description>
+ Class for event stream playback. Event streams are music expressed as a series of events (note on, note off, instrument change...), as opposed to audio streams, which are just audio data. Examples of event-based streams are MIDI files, or MOD music.
+ Currently, only MOD, S3M, IT, and XM music is supported.
</description>
<methods>
<method name="set_stream">
<argument index="0" name="stream" type="EventStream">
</argument>
<description>
+ Set the [EventStream] this player will play.
</description>
</method>
<method name="get_stream" qualifiers="const">
<return type="EventStream">
</return>
<description>
+ Return the currently assigned stream.
</description>
</method>
<method name="play">
<description>
+ Play the currently assigned stream.
</description>
</method>
<method name="stop">
<description>
+ Stop playing.
</description>
</method>
<method name="is_playing" qualifiers="const">
<return type="bool">
</return>
<description>
+ Return whether this player is playing.
</description>
</method>
<method name="set_paused">
<argument index="0" name="paused" type="bool">
</argument>
<description>
+ Pause stream playback.
</description>
</method>
<method name="is_paused" qualifiers="const">
<return type="bool">
</return>
<description>
+ Return whether the playback is currently paused.
</description>
</method>
<method name="set_loop">
<argument index="0" name="enabled" type="bool">
</argument>
<description>
+ Set whether the stream will be restarted at the end.
</description>
</method>
<method name="has_loop" qualifiers="const">
<return type="bool">
</return>
<description>
+ Return whether this player will be restart the playback at the end.
</description>
</method>
<method name="set_volume">
<argument index="0" name="volume" type="float">
</argument>
<description>
+ Set the playback volume for this player. This is a float between 0.0 (silent) and 1.0 (full volume). Values over 1.0 may amplify sound even more, but may introduce distortion. Negative values may just invert the output waveform, which produces no audible difference.
+ The effect of these special values uiltimately depends on the low-level implementation of the file format being played.
</description>
</method>
<method name="get_volume" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the playback volume for this player.
</description>
</method>
<method name="set_pitch_scale">
<argument index="0" name="pitch_scale" type="float">
</argument>
<description>
+ Set the pitch multiplier for all sounds coming from this stream. A value of 2.0 shifts all pitches one octave up, and a value of 0.5 shifts pitches one octave down.
</description>
</method>
<method name="get_pitch_scale" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the pitch scale factor for this player.
</description>
</method>
<method name="set_tempo_scale">
<argument index="0" name="tempo_scale" type="float">
</argument>
<description>
+ Set the tempo multiplier. This allows to slow down or speed up the music, without affecting its pitch.
</description>
</method>
<method name="get_tempo_scale" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the tempo multiplier.
</description>
</method>
<method name="set_volume_db">
<argument index="0" name="db" type="float">
</argument>
<description>
+ Set the playback volume for this player, in decibels. This is a float between -80.0 (silent) and 0.0 (full volume). Values under -79.0 get truncated to -80, but values over 0.0 do not, so the warnings for overamplifying (see [set_volume]) still apply.
</description>
</method>
<method name="get_volume_db" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the playback volume for this player, in decibels.
</description>
</method>
<method name="get_stream_name" qualifiers="const">
<return type="String">
</return>
<description>
+ Return the name of the currently assigned stream. This is not the file name, but a field inside the file. If no stream is assigned, if returns "&lt;No Stream&gt;".
</description>
</method>
<method name="get_loop_count" qualifiers="const">
<return type="int">
</return>
<description>
+ Return the number of times the playback has looped.
</description>
</method>
<method name="get_pos" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the playback position. May be in seconds, but depends on the stream type.
</description>
</method>
<method name="seek_pos">
<argument index="0" name="time" type="float">
</argument>
<description>
+ Set the playback position. May be in seconds, but depends on the stream type.
+ </description>
+ </method>
+ <method name="get_length" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ Return the song length. May be in seconds, but depends on the stream type.
</description>
</method>
<method name="set_autoplay">
<argument index="0" name="enabled" type="bool">
</argument>
<description>
+ Set whether this player will start playing as soon as it enters the scene tree.
</description>
</method>
<method name="has_autoplay" qualifiers="const">
<return type="bool">
</return>
<description>
+ Return whether this player will start playing as soon as it enters the scene tree.
</description>
</method>
<method name="set_channel_volume">
- <argument index="0" name="idx" type="int">
+ <argument index="0" name="channel" type="int">
</argument>
<argument index="1" name="channel_volume" type="float">
</argument>
<description>
+ Set the volume scale for an individual channel of the stream, with the same value range as [methid set_volume]. The channel number depends on the stream format. For example, MIDIs range from 0 to 15, and MODs from 0 to 63.
+ Many stream formats are multichannel, so this allows to affect only a part of the music.
</description>
</method>
- <method name="get_channel_volumeidx" qualifiers="const">
+ <method name="get_channel_volume" qualifiers="const">
<return type="float">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="channel" type="int">
</argument>
<description>
- </description>
- </method>
- <method name="get_length" qualifiers="const">
- <return type="float">
- </return>
- <description>
+ Return the volume scale for an individual channel of the stream.
</description>
</method>
<method name="get_channel_last_note_time" qualifiers="const">
<return type="float">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="channel" type="int">
</argument>
<description>
+ Return the time at which the last note of a given channel in the stream plays.
</description>
</method>
</methods>
@@ -10180,8 +10450,11 @@ This approximation makes straight segments between each point, then subdivides t
</class>
<class name="EventStream" inherits="Resource" category="Core">
<brief_description>
+ Base class for all event-based stream drivers.
</brief_description>
<description>
+ Base class for all event-based stream drivers. Event streams are music expressed as a series of events (note on, note off, instrument change...), as opposed to audio streams, which are just audio data. Examples of event-based streams are MIDI files, of MOD music.
+ This class exposes no methods.
</description>
<methods>
</methods>
@@ -10190,8 +10463,15 @@ This approximation makes straight segments between each point, then subdivides t
</class>
<class name="EventStreamChibi" inherits="EventStream" category="Core">
<brief_description>
+ Driver for MOD playback.
</brief_description>
<description>
+ This driver plays MOD music. MOD music, as all event-based streams, is a music format defined by note events ocurring at defined moments, instead of a stream of audio samples.
+ Currently, this driver supports the MOD, S3M, IT, and XM formats.
+ This class exposes no methods.
+ This class can return its playback positon in seconds, but does not allow to set it, failing with only a console warning.
+ This class can not return its song length, returning 1.0 when queried.
+ This class does not limit its volume settings, allowing for overflow/distortion and wave inversion.
</description>
<methods>
</methods>
@@ -10556,7 +10836,7 @@ This approximation makes straight segments between each point, then subdivides t
</description>
</method>
<method name="set_show_hidden_files">
- <argument index="0" name="arg0" type="bool">
+ <argument index="0" name="show" type="bool">
</argument>
<description>
</description>
@@ -10618,6 +10898,8 @@ This approximation makes straight segments between each point, then subdivides t
</theme_item>
<theme_item name="folder" type="Texture">
</theme_item>
+ <theme_item name="reload" type="Texture">
+ </theme_item>
</theme_items>
</class>
<class name="FixedMaterial" inherits="Material" category="Core">
@@ -10856,9 +11138,9 @@ This approximation makes straight segments between each point, then subdivides t
<method name="get_kerning_pair" qualifiers="const">
<return type="int">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="char_a" type="int">
</argument>
- <argument index="1" name="arg1" type="int">
+ <argument index="1" name="char_b" type="int">
</argument>
<description>
Return a kerning pair as a difference. Kerning pairs are special cases where a typeface advance is determined by the next character.
@@ -10969,6 +11251,18 @@ This approximation makes straight segments between each point, then subdivides t
Draw character "char" into a canvas item using the font at a given "pos" position, with "modulate" color, and optionally kerning if "next" is apassed. clipping the width. "pos" specifies te baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis. The width used by the character is returned, making this function useful for drawing strings character by character.
</description>
</method>
+ <method name="set_fallback">
+ <argument index="0" name="fallback" type="Object">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_fallback" qualifiers="const">
+ <return type="Object">
+ </return>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
@@ -11026,6 +11320,8 @@ This approximation makes straight segments between each point, then subdivides t
</description>
<methods>
<method name="resume">
+ <return type="Variant">
+ </return>
<argument index="0" name="arg" type="var" default="NULL">
</argument>
<description>
@@ -11632,7 +11928,7 @@ This approximation makes straight segments between each point, then subdivides t
<method name="has_singleton" qualifiers="const">
<return type="bool">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="name" type="String">
</argument>
<description>
</description>
@@ -11640,7 +11936,7 @@ This approximation makes straight segments between each point, then subdivides t
<method name="get_singleton" qualifiers="const">
<return type="Object">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="name" type="String">
</argument>
<description>
</description>
@@ -11648,7 +11944,7 @@ This approximation makes straight segments between each point, then subdivides t
<method name="load_resource_pack">
<return type="bool">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="pack" type="String">
</argument>
<description>
</description>
@@ -11656,7 +11952,7 @@ This approximation makes straight segments between each point, then subdivides t
<method name="save_custom">
<return type="int">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="file" type="String">
</argument>
<description>
</description>
@@ -12172,7 +12468,7 @@ This approximation makes straight segments between each point, then subdivides t
</description>
</method>
<method name="resource_changed">
- <argument index="0" name="arg0" type="Object">
+ <argument index="0" name="resource" type="Object">
</argument>
<description>
</description>
@@ -13147,6 +13443,21 @@ returns:= "username=user&amp;password=pass"
<description>
</description>
</method>
+ <method name="Image">
+ <return type="Image">
+ </return>
+ <argument index="0" name="width" type="int">
+ </argument>
+ <argument index="1" name="height" type="int">
+ </argument>
+ <argument index="2" name="mipmaps" type="bool">
+ </argument>
+ <argument index="3" name="format" type="int">
+ </argument>
+ <description>
+ Create an empty image of a specific size and format.
+ </description>
+ </method>
</methods>
<constants>
<constant name="COMPRESS_BC" value="0">
@@ -13291,6 +13602,10 @@ returns:= "username=user&amp;password=pass"
<description>
</description>
</method>
+ <method name="shrink_x2_and_keep_size">
+ <description>
+ </description>
+ </method>
<method name="set_size_override">
<argument index="0" name="size" type="Vector2">
</argument>
@@ -13409,6 +13724,7 @@ returns:= "username=user&amp;password=pass"
<argument index="1" name="button" type="int">
</argument>
<description>
+ Returns true if the joystick button at the given index is currently pressed. Returns false otherwise. (see JOY_* constans in [InputEvent])
</description>
</method>
<method name="is_action_pressed">
@@ -13419,6 +13735,31 @@ returns:= "username=user&amp;password=pass"
<description>
</description>
</method>
+ <method name="add_joy_mapping">
+ <argument index="0" name="mapping" type="String">
+ </argument>
+ <argument index="1" name="update_existing" type="bool" default="false">
+ </argument>
+ <description>
+ Add a new mapping entry (in SDL2 format) to the mapping database. Optionally update already connected devices.
+ </description>
+ </method>
+ <method name="remove_joy_mapping">
+ <argument index="0" name="guid" type="String">
+ </argument>
+ <description>
+ Removes all mappings from the internal db that match the given uid.
+ </description>
+ </method>
+ <method name="is_joy_known">
+ <return type="bool">
+ </return>
+ <argument index="0" name="device" type="int">
+ </argument>
+ <description>
+ Returns true if the specified device is known by the system. This means that it sets all button and axis indices exactly as defined in [InputEvent]. Unknown joysticks are not expected to match these constants, but you can still retrieve events from them.
+ </description>
+ </method>
<method name="get_joy_axis">
<return type="float">
</return>
@@ -13427,6 +13768,7 @@ returns:= "username=user&amp;password=pass"
<argument index="1" name="axis" type="int">
</argument>
<description>
+ Returns the current value of the joystick axis at given index (see JOY_* enum in [InputEvent])
</description>
</method>
<method name="get_joy_name">
@@ -13435,6 +13777,16 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="device" type="int">
</argument>
<description>
+ Returns the name of the joystick at the specified device index
+ </description>
+ </method>
+ <method name="get_joy_guid" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="device" type="int">
+ </argument>
+ <description>
+ Returns a SDL2 compatible device guid on platforms that use gamepad remapping. Returns "Default Gamepad" otherwise.
</description>
</method>
<method name="get_accelerometer">
@@ -13474,13 +13826,13 @@ returns:= "username=user&amp;password=pass"
</description>
</method>
<method name="action_press">
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="action" type="String">
</argument>
<description>
</description>
</method>
<method name="action_release">
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="action" type="String">
</argument>
<description>
</description>
@@ -14960,6 +15312,18 @@ returns:= "username=user&amp;password=pass"
<description>
</description>
</method>
+ <method name="set_exclude_nodes_from_collision">
+ <argument index="0" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_exclude_nodes_from_collision" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
@@ -14976,7 +15340,7 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="node" type="NodePath">
</argument>
<description>
- Set the path to the A node for the joint. Must be of type PhysicsBody2D.
+ Set the path to the A node for the joint. Must be of type [PhysicsBody2D].
</description>
</method>
<method name="get_node_a" qualifiers="const">
@@ -14990,7 +15354,7 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="node" type="NodePath">
</argument>
<description>
- Set the path to the B node for the joint. Must be of type PhysicsBody2D.
+ Set the path to the B node for the joint. Must be of type [PhysicsBody2D].
</description>
</method>
<method name="get_node_b" qualifiers="const">
@@ -15012,6 +15376,18 @@ returns:= "username=user&amp;password=pass"
<description>
</description>
</method>
+ <method name="set_exclude_nodes_from_collision">
+ <argument index="0" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_exclude_nodes_from_collision" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
@@ -15038,14 +15414,13 @@ returns:= "username=user&amp;password=pass"
<description>
</description>
</method>
- <method name="can_move_to">
+ <method name="can_teleport_to">
<return type="bool">
</return>
<argument index="0" name="position" type="Vector3">
</argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
<description>
+ Returns whether the KinematicBody can be teleported to the destination given as an argument, checking all collision shapes of the body against potential colliders at the destination.
</description>
</method>
<method name="is_colliding" qualifiers="const">
@@ -15073,6 +15448,8 @@ returns:= "username=user&amp;password=pass"
</description>
</method>
<method name="get_collider" qualifiers="const">
+ <return type="Object">
+ </return>
<description>
</description>
</method>
@@ -15148,8 +15525,12 @@ returns:= "username=user&amp;password=pass"
</class>
<class name="KinematicBody2D" inherits="PhysicsBody2D" category="Core">
<brief_description>
+ Kinematic body 2D node.
</brief_description>
<description>
+ Kinematic bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all (to other types of bodies, such a character or a rigid body, these are the same as a static body). They have however, two main uses:
+ Simulated Motion: When these bodies are moved manually, either from code or from an AnimationPlayer (with process mode set to fixed), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc).
+ Kinematic Characters: KinematicBody2D also has an api for moving objects (the [method move] method) while performing collision tests. This makes them really useful to implement characters that collide against a world, but that don't require advanced physics.
</description>
<methods>
<method name="move">
@@ -15158,6 +15539,7 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="rel_vec" type="Vector2">
</argument>
<description>
+ Move the body in the given direction, stopping if there is an obstacle.
</description>
</method>
<method name="move_to">
@@ -15166,6 +15548,7 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="position" type="Vector2">
</argument>
<description>
+ Move the body to the given position. This is not a teleport, and the body will stop if there is an obstacle.
</description>
</method>
<method name="test_move">
@@ -15174,66 +15557,82 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="rel_vec" type="Vector2">
</argument>
<description>
+ Return true if there would be a collision if the body moved in the given direction.
</description>
</method>
<method name="get_travel" qualifiers="const">
<return type="Vector2">
</return>
<description>
+ Return the last movement done by the body.
</description>
</method>
<method name="revert_motion">
<description>
+ Undo the last movement done by the body.
</description>
</method>
<method name="is_colliding" qualifiers="const">
<return type="bool">
</return>
<description>
+ Return whether the body is colliding with another.
</description>
</method>
<method name="get_collision_pos" qualifiers="const">
<return type="Vector2">
</return>
<description>
+ Return the point in space where the body is touching another. If there is no collision, this method will return (0,0), so collisions must be checked first with [method is_colliding].
</description>
</method>
<method name="get_collision_normal" qualifiers="const">
<return type="Vector2">
</return>
<description>
+ Return the normal of the surface the body collided with. This is useful to implement sliding along a surface.
</description>
</method>
<method name="get_collider_velocity" qualifiers="const">
<return type="Vector2">
</return>
<description>
+ Return the velocity of the body that collided with this one.
</description>
</method>
<method name="get_collider" qualifiers="const">
+ <return type="Object">
+ </return>
<description>
+ Return the body that collided with this one.
</description>
</method>
<method name="get_collider_shape" qualifiers="const">
<return type="int">
</return>
<description>
+ Return the shape index from the body that collided with this one. If there is no collision, this method will return 0, so collisions must be checked first with [method is_colliding].
</description>
</method>
<method name="get_collider_metadata" qualifiers="const">
+ <return type="Variant">
+ </return>
<description>
+ Return the metadata of the shape that collided with this body. If there is no collision, it will return 0, so collisions must be checked first with [method is_colliding]. Aditionally, this metadata can not be set with [method Object.set_meta], it must be set with [method Physics2DServer.body_set_shape_metadata].
</description>
</method>
<method name="set_collision_margin">
<argument index="0" name="pixels" type="float">
</argument>
<description>
+ Set the collision margin for this object. A collision margin is an amount (in pixels) that all shapes will grow when computing collisions, to account for numerical imprecision.
</description>
</method>
<method name="get_collision_margin" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the collision margin for this object.
</description>
</method>
</methods>
@@ -15538,7 +15937,7 @@ returns:= "username=user&amp;password=pass"
<method name="get_parameter" qualifiers="const">
<return type="float">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="variable" type="int">
</argument>
<description>
</description>
@@ -15554,7 +15953,7 @@ returns:= "username=user&amp;password=pass"
<method name="get_color" qualifiers="const">
<return type="Color">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="color" type="int">
</argument>
<description>
</description>
@@ -15891,6 +16290,8 @@ returns:= "username=user&amp;password=pass"
</constant>
<constant name="MODE_MIX" value="2">
</constant>
+ <constant name="MODE_MASK" value="3">
+ </constant>
</constants>
</class>
<class name="LightOccluder2D" inherits="Node2D" category="Core">
@@ -16255,6 +16656,8 @@ returns:= "username=user&amp;password=pass"
</description>
</method>
<method name="base64_to_variant">
+ <return type="Variant">
+ </return>
<argument index="0" name="base64_str" type="String">
</argument>
<description>
@@ -16843,9 +17246,9 @@ returns:= "username=user&amp;password=pass"
</argument>
<argument index="1" name="arrays" type="Array">
</argument>
- <argument index="2" name="morph_arrays" type="Array">
+ <argument index="2" name="morph_arrays" type="Array" default="Array()">
</argument>
- <argument index="3" name="arg3" type="bool" default="Array()">
+ <argument index="3" name="alphasort" type="bool" default="false">
</argument>
<description>
Create a new surface ([method get_surface_count] that will become surf_idx for this.
@@ -17518,7 +17921,7 @@ returns:= "username=user&amp;password=pass"
</description>
</method>
<method name="set_instance_count">
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="count" type="int">
</argument>
<description>
Set the amount of instnces that is going to be drawn. Changing this number will erase all the existing instance transform and color data.
@@ -17532,9 +17935,9 @@ returns:= "username=user&amp;password=pass"
</description>
</method>
<method name="set_instance_transform">
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="instance" type="int">
</argument>
- <argument index="1" name="arg1" type="Transform">
+ <argument index="1" name="transform" type="Transform">
</argument>
<description>
Set the transform for a specific instance.
@@ -17543,16 +17946,16 @@ returns:= "username=user&amp;password=pass"
<method name="get_instance_transform" qualifiers="const">
<return type="Transform">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="instance" type="int">
</argument>
<description>
Return the transform of a specific instance.
</description>
</method>
<method name="set_instance_color">
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="instance" type="int">
</argument>
- <argument index="1" name="arg1" type="Color">
+ <argument index="1" name="color" type="Color">
</argument>
<description>
Set the color of a specific instance.
@@ -17561,14 +17964,14 @@ returns:= "username=user&amp;password=pass"
<method name="get_instance_color" qualifiers="const">
<return type="Color">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="instance" type="int">
</argument>
<description>
Get the color of a specific instance.
</description>
</method>
<method name="set_aabb">
- <argument index="0" name="arg0" type="AABB">
+ <argument index="0" name="visibility_aabb" type="AABB">
</argument>
<description>
Set the visibility AABB. If not provided, MultiMesh will not be visible.
@@ -18269,8 +18672,11 @@ returns:= "username=user&amp;password=pass"
<method name="add_child">
<argument index="0" name="node" type="Node">
</argument>
+ <argument index="1" name="legible_unique_name" type="bool" default="false">
+ </argument>
<description>
Add a child [Node]. Nodes can have as many children as they want, but every child must have a unique name. Children nodes are automatically deleted when the parent node is deleted, so deleting a whole scene is performed by deleting its topmost node.
+ The optional boolean argument enforces creating child node with human-readable names, based on the name of node being instanced instead of its type only.
</description>
</method>
<method name="remove_child">
@@ -18412,7 +18818,7 @@ returns:= "username=user&amp;password=pass"
<method name="add_to_group">
<argument index="0" name="group" type="String">
</argument>
- <argument index="1" name="arg1" type="bool" default="false">
+ <argument index="1" name="persistent" type="bool" default="false">
</argument>
<description>
Add a node to a group. Groups are helpers to name and organize group of nodes, like for example: "Enemies", "Collectables", etc. A [Node] can be in any number of groups. Nodes can be assigned a group at any time, but will not be added to it until they are inside the scene tree (see [method is_inside_scene]).
@@ -18701,6 +19107,8 @@ returns:= "username=user&amp;password=pass"
</constant>
<constant name="NOTIFICATION_UNPAUSED" value="15">
</constant>
+ <constant name="NOTIFICATION_INSTANCED" value="20">
+ </constant>
<constant name="PAUSE_MODE_INHERIT" value="0">
</constant>
<constant name="PAUSE_MODE_STOP" value="1">
@@ -18863,15 +19271,15 @@ returns:= "username=user&amp;password=pass"
</description>
</method>
<method name="edit_set_pivot">
- <argument index="0" name="arg0" type="Vector2">
+ <argument index="0" name="pivot" type="Vector2">
</argument>
<description>
</description>
</method>
- <method name="get_relative_transform" qualifiers="const">
+ <method name="get_relative_transform_to_parent" qualifiers="const">
<return type="Matrix32">
</return>
- <argument index="0" name="arg0" type="Object">
+ <argument index="0" name="parent" type="Object">
</argument>
<description>
</description>
@@ -19151,6 +19559,19 @@ returns:= "username=user&amp;password=pass"
<description>
</description>
</method>
+ <method name="set_keep_screen_on">
+ <argument index="0" name="enabled" type="bool">
+ </argument>
+ <description>
+ Set keep screen on if true, or goes to sleep by device setting if false. (for Android/iOS)
+ </description>
+ </method>
+ <method name="is_keep_screen_on" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="set_iterations_per_second">
<argument index="0" name="iterations_per_second" type="int">
</argument>
@@ -19340,7 +19761,7 @@ returns:= "username=user&amp;password=pass"
</description>
</method>
<method name="set_icon">
- <argument index="0" name="arg0" type="Image">
+ <argument index="0" name="icon" type="Image">
</argument>
<description>
</description>
@@ -19505,7 +19926,7 @@ returns:= "username=user&amp;password=pass"
</description>
</method>
<method name="print_resources_by_type">
- <argument index="0" name="arg0" type="StringArray">
+ <argument index="0" name="types" type="StringArray">
</argument>
<description>
</description>
@@ -19513,13 +19934,13 @@ returns:= "username=user&amp;password=pass"
<method name="native_video_play">
<return type="int">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="path" type="String">
</argument>
- <argument index="1" name="arg1" type="float">
+ <argument index="1" name="volume" type="float">
</argument>
- <argument index="2" name="arg2" type="String">
+ <argument index="2" name="audio_track" type="String">
</argument>
- <argument index="3" name="arg3" type="String">
+ <argument index="3" name="subtitle_track" type="String">
</argument>
<description>
</description>
@@ -19746,7 +20167,7 @@ returns:= "username=user&amp;password=pass"
<method name="notification">
<argument index="0" name="what" type="int">
</argument>
- <argument index="1" name="arg1" type="bool" default="false">
+ <argument index="1" name="reversed" type="bool" default="false">
</argument>
<description>
Notify the object of something.
@@ -19884,6 +20305,8 @@ returns:= "username=user&amp;password=pass"
</description>
</method>
<method name="callv">
+ <return type="Variant">
+ </return>
<argument index="0" name="method" type="String">
</argument>
<argument index="1" name="arg_array" type="Array">
@@ -19894,7 +20317,7 @@ returns:= "username=user&amp;password=pass"
<method name="has_method" qualifiers="const">
<return type="bool">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="method" type="String">
</argument>
<description>
</description>
@@ -19906,6 +20329,14 @@ returns:= "username=user&amp;password=pass"
Return the list of signals as an array of dictionaries.
</description>
</method>
+ <method name="get_signal_connection_list" qualifiers="const">
+ <return type="Array">
+ </return>
+ <argument index="0" name="signal" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="connect">
<return type="int">
</return>
@@ -20222,7 +20653,7 @@ returns:= "username=user&amp;password=pass"
</description>
</method>
<method name="select">
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="idx" type="int">
</argument>
<description>
Select an item by index and make it the current item.
@@ -20321,7 +20752,7 @@ returns:= "username=user&amp;password=pass"
<method name="flush">
<return type="int">
</return>
- <argument index="0" name="arg0" type="bool">
+ <argument index="0" name="verbose" type="bool">
</argument>
<description>
</description>
@@ -20437,7 +20868,7 @@ returns:= "username=user&amp;password=pass"
<method name="put_var">
<return type="int">
</return>
- <argument index="0" name="var" type="var">
+ <argument index="0" name="var" type="Variant">
</argument>
<description>
</description>
@@ -20658,7 +21089,7 @@ returns:= "username=user&amp;password=pass"
</description>
</method>
<method name="set_ignore_camera_zoom">
- <argument index="0" name="arg0" type="bool">
+ <argument index="0" name="ignore" type="bool">
</argument>
<description>
</description>
@@ -20921,7 +21352,7 @@ returns:= "username=user&amp;password=pass"
<method name="get_randomness" qualifiers="const">
<return type="float">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="variable" type="int">
</argument>
<description>
Return the randomness for a specific variable of the particle system. Randomness produces small changes from the default each time a particle is emitted.
@@ -20978,7 +21409,7 @@ returns:= "username=user&amp;password=pass"
</description>
</method>
<method name="set_emit_timeout">
- <argument index="0" name="arg0" type="float">
+ <argument index="0" name="timeout" type="float">
</argument>
<description>
</description>
@@ -21168,6 +21599,8 @@ returns:= "username=user&amp;password=pass"
</description>
</method>
<method name="set_texture">
+ <return type="Texture">
+ </return>
<argument index="0" name="texture" type="Object">
</argument>
<description>
@@ -21192,6 +21625,8 @@ returns:= "username=user&amp;password=pass"
</description>
</method>
<method name="set_color_ramp">
+ <return type="ColorRamp">
+ </return>
<argument index="0" name="color_ramp" type="Object">
</argument>
<description>
@@ -21325,6 +21760,10 @@ returns:= "username=user&amp;password=pass"
<description>
</description>
</method>
+ <method name="reset">
+ <description>
+ </description>
+ </method>
<method name="set_use_local_space">
<argument index="0" name="enable" type="bool">
</argument>
@@ -22070,6 +22509,8 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="get_contact_collider_shape_metadata" qualifiers="const">
+ <return type="Variant">
+ </return>
<argument index="0" name="contact_idx" type="int">
</argument>
<description>
@@ -22484,11 +22925,11 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="area_set_monitor_callback">
- <argument index="0" name="receiver" type="RID">
+ <argument index="0" name="area" type="RID">
</argument>
- <argument index="1" name="method" type="Object">
+ <argument index="1" name="receiver" type="Object">
</argument>
- <argument index="2" name="arg2" type="String">
+ <argument index="2" name="method" type="String">
</argument>
<description>
</description>
@@ -22798,9 +23239,9 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="body_set_one_way_collision_direction">
- <argument index="0" name="normal" type="RID">
+ <argument index="0" name="body" type="RID">
</argument>
- <argument index="1" name="arg1" type="Vector2">
+ <argument index="1" name="normal" type="Vector2">
</argument>
<description>
</description>
@@ -22808,15 +23249,15 @@ This method controls whether the position between two cached points is interpola
<method name="body_get_one_way_collision_direction" qualifiers="const">
<return type="Vector2">
</return>
- <argument index="0" name="arg0" type="RID">
+ <argument index="0" name="body" type="RID">
</argument>
<description>
</description>
</method>
<method name="body_set_one_way_collision_max_depth">
- <argument index="0" name="normal" type="RID">
+ <argument index="0" name="body" type="RID">
</argument>
- <argument index="1" name="arg1" type="float">
+ <argument index="1" name="depth" type="float">
</argument>
<description>
</description>
@@ -22824,7 +23265,7 @@ This method controls whether the position between two cached points is interpola
<method name="body_get_one_way_collision_max_depth" qualifiers="const">
<return type="float">
</return>
- <argument index="0" name="arg0" type="RID">
+ <argument index="0" name="body" type="RID">
</argument>
<description>
</description>
@@ -22852,7 +23293,7 @@ This method controls whether the position between two cached points is interpola
</argument>
<argument index="2" name="method" type="String">
</argument>
- <argument index="3" name="arg3" type="var">
+ <argument index="3" name="userdata" type="var" default="NULL">
</argument>
<description>
</description>
@@ -22976,7 +23417,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_process_info">
<return type="int">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="process_info" type="int">
</argument>
<description>
</description>
@@ -23015,11 +23456,20 @@ This method controls whether the position between two cached points is interpola
</constant>
<constant name="AREA_PARAM_PRIORITY" value="7">
</constant>
+ <constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0">
+ This area does not affect gravity/damp. These are generally areas that exist only to detect collisions, and objects entering or exiting them.
+ </constant>
<constant name="AREA_SPACE_OVERRIDE_COMBINE" value="1">
+ This area adds its gravity/damp values to whatever has been calculated so far. This way, many overlapping areas can combine their physics to make interesting effects.
</constant>
- <constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0">
+ <constant name="AREA_SPACE_OVERRIDE_COMBINE_REPLACE" value="2">
+ This area adds its gravity/damp values to whatever has been calculated so far. Then stops taking into account the rest of the areas, even the default one.
</constant>
- <constant name="AREA_SPACE_OVERRIDE_REPLACE" value="2">
+ <constant name="AREA_SPACE_OVERRIDE_REPLACE" value="3">
+ This area replaces any gravity/damp, even the default one, and stops taking into account the rest of the areas.
+ </constant>
+ <constant name="AREA_SPACE_OVERRIDE_REPLACE_COMBINE" value="4">
+ This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one.
</constant>
<constant name="BODY_MODE_STATIC" value="0">
</constant>
@@ -23307,7 +23757,7 @@ This method controls whether the position between two cached points is interpola
</class>
<class name="PhysicsBody" inherits="CollisionObject" category="Core">
<brief_description>
- Base class for differnt types of Physics bodies.
+ Base class for different types of Physics bodies.
</brief_description>
<description>
PhysicsBody is an abstract base class for implementing a physics body. All PhysicsBody types inherit from it.
@@ -23343,32 +23793,40 @@ This method controls whether the position between two cached points is interpola
</class>
<class name="PhysicsBody2D" inherits="CollisionObject2D" category="Core">
<brief_description>
+ Base class for all objects affected by physics.
</brief_description>
<description>
+ PhysicsBody2D is an abstract base class for implementing a physics body. All [i]x[/i]Body2D types inherit from it.
</description>
<methods>
<method name="set_layer_mask">
<argument index="0" name="mask" type="int">
</argument>
<description>
+ Set the physics layers this area is in.
+ Collidable objects can exist in any of 32 different layers. These layers are not visual, but more of a tagging system instead. A collidable can use these layers/tags to select with which objects it can collide, using [method set_collision_mask].
+ A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A.
</description>
</method>
<method name="get_layer_mask" qualifiers="const">
<return type="int">
</return>
<description>
+ Return the physics layer this area is in.
</description>
</method>
<method name="set_collision_mask">
<argument index="0" name="mask" type="int">
</argument>
<description>
+ Set the physics layers this area can scan for collisions.
</description>
</method>
<method name="get_collision_mask" qualifiers="const">
<return type="int">
</return>
<description>
+ Return the physics layers this area can scan for collisions.
</description>
</method>
<method name="set_collision_mask_bit">
@@ -23377,6 +23835,7 @@ This method controls whether the position between two cached points is interpola
<argument index="1" name="value" type="bool">
</argument>
<description>
+ Set/clear individual bits on the collision mask. This makes selecting the areas scanned easier.
</description>
</method>
<method name="get_collision_mask_bit" qualifiers="const">
@@ -23385,6 +23844,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="bit" type="int">
</argument>
<description>
+ Return an individual bit on the collision mask.
</description>
</method>
<method name="set_layer_mask_bit">
@@ -23393,6 +23853,7 @@ This method controls whether the position between two cached points is interpola
<argument index="1" name="value" type="bool">
</argument>
<description>
+ Set/clear individual bits on the layer mask. This makes getting a body in/out of only one layer easier.
</description>
</method>
<method name="get_layer_mask_bit" qualifiers="const">
@@ -23401,42 +23862,49 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="bit" type="int">
</argument>
<description>
+ Return an individual bit on the collision mask.
</description>
</method>
<method name="set_one_way_collision_direction">
<argument index="0" name="dir" type="Vector2">
</argument>
<description>
+ Set a direction in which bodies can go through this one. If this value is different from (0,0), any movement within 90 degrees of this vector is considered a valid movement. Set this direction to (0,0) to disable one-way collisions.
</description>
</method>
<method name="get_one_way_collision_direction" qualifiers="const">
<return type="Vector2">
</return>
<description>
+ Return the direction used for one-way collision detection.
</description>
</method>
<method name="set_one_way_collision_max_depth">
<argument index="0" name="depth" type="float">
</argument>
<description>
+ Set how far a body can go through this one, when it allows one-way collisions (see [method set_one_way_collision_detection]).
</description>
</method>
<method name="get_one_way_collision_max_depth" qualifiers="const">
<return type="float">
</return>
<description>
+ Return how far a body can go through this one, when it allows one-way collisions.
</description>
</method>
<method name="add_collision_exception_with">
<argument index="0" name="body" type="PhysicsBody2D">
</argument>
<description>
+ Adds a body to the collision exception list. This list contains bodies that this body will not collide with.
</description>
</method>
<method name="remove_collision_exception_with">
<argument index="0" name="body" type="PhysicsBody2D">
</argument>
<description>
+ Removes a body from the collision exception list.
</description>
</method>
</methods>
@@ -23974,11 +24442,11 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="area_set_monitor_callback">
- <argument index="0" name="receiver" type="RID">
+ <argument index="0" name="area" type="RID">
</argument>
- <argument index="1" name="method" type="Object">
+ <argument index="1" name="receiver" type="Object">
</argument>
- <argument index="2" name="arg2" type="String">
+ <argument index="2" name="method" type="String">
</argument>
<description>
</description>
@@ -24038,8 +24506,6 @@ This method controls whether the position between two cached points is interpola
</return>
<argument index="0" name="body" type="RID">
</argument>
- <argument index="1" name="arg1" type="int">
- </argument>
<description>
</description>
</method>
@@ -24584,7 +25050,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_process_info">
<return type="int">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="process_info" type="int">
</argument>
<description>
</description>
@@ -24751,11 +25217,20 @@ This method controls whether the position between two cached points is interpola
</constant>
<constant name="AREA_PARAM_PRIORITY" value="7">
</constant>
+ <constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0">
+ This area does not affect gravity/damp. These are generally areas that exist only to detect collisions, and objects entering or exiting them.
+ </constant>
<constant name="AREA_SPACE_OVERRIDE_COMBINE" value="1">
+ This area adds its gravity/damp values to whatever has been calculated so far. This way, many overlapping areas can combine their physics to make interesting effects.
</constant>
- <constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0">
+ <constant name="AREA_SPACE_OVERRIDE_COMBINE_REPLACE" value="2">
+ This area adds its gravity/damp values to whatever has been calculated so far. Then stops taking into account the rest of the areas, even the default one.
</constant>
- <constant name="AREA_SPACE_OVERRIDE_REPLACE" value="2">
+ <constant name="AREA_SPACE_OVERRIDE_REPLACE" value="3">
+ This area replaces any gravity/damp, even the default one, and stops taking into account the rest of the areas.
+ </constant>
+ <constant name="AREA_SPACE_OVERRIDE_REPLACE_COMBINE" value="4">
+ This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one.
</constant>
<constant name="BODY_MODE_STATIC" value="0">
</constant>
@@ -25566,7 +26041,7 @@ This method controls whether the position between two cached points is interpola
<method name="set_item_checked">
<argument index="0" name="idx" type="int">
</argument>
- <argument index="1" name="arg1" type="bool">
+ <argument index="1" name="checked" type="bool">
</argument>
<description>
Set the checkstate status of the item at index "idx".
@@ -26254,12 +26729,6 @@ This method controls whether the position between two cached points is interpola
Return value mapped to 0 to 1 (unit) range.
</description>
</method>
- <method name="get_rounded_values" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
<method name="set_val">
<argument index="0" name="value" type="float">
</argument>
@@ -26307,11 +26776,17 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="set_rounded_values">
- <argument index="0" name="arg0" type="bool">
+ <argument index="0" name="enabled" type="bool">
</argument>
<description>
</description>
</method>
+ <method name="is_rounded_values" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="set_exp_unit_value">
<argument index="0" name="enabled" type="bool">
</argument>
@@ -26945,7 +27420,7 @@ This method controls whether the position between two cached points is interpola
Lazy (non-greedy) quantifiers [code]*?[/code]
Begining [code]^[/code] and end [code]$[/code] anchors
Alternation [code]|[/code]
- Backreferences [code]\1[/code] to [code]\9[/code]
+ Backreferences [code]\1[/code] and [code]\g{1}[/code]
POSIX character classes [code][[:alnum:]][/code]
Lookahead [code](?=)[/code], [code](?!)[/code] and lookbehind [code](?&lt;=)[/code], [code](?&lt;!)[/code]
ASCII [code]\xFF[/code] and Unicode [code]\uFFFF[/code] code points (in a style similar to Python)
@@ -26957,9 +27432,10 @@ This method controls whether the position between two cached points is interpola
</return>
<argument index="0" name="pattern" type="String">
</argument>
- <argument index="1" name="expanded" type="bool" default="true">
+ <argument index="1" name="capture" type="int" default="9">
</argument>
<description>
+ Compiles and assign the regular expression pattern to use. The limit on the number of capturing groups can be specified or made unlimited if negative.
</description>
</method>
<method name="find" qualifiers="const">
@@ -27110,7 +27586,7 @@ This method controls whether the position between two cached points is interpola
<method name="duplicate">
<return type="Object">
</return>
- <argument index="0" name="arg0" type="bool" default="false">
+ <argument index="0" name="subresources" type="bool" default="false">
</argument>
<description>
</description>
@@ -27299,7 +27775,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_dependencies">
<return type="StringArray">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="path" type="String">
</argument>
<description>
</description>
@@ -27307,7 +27783,7 @@ This method controls whether the position between two cached points is interpola
<method name="has">
<return type="bool">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="path" type="String">
</argument>
<description>
</description>
@@ -27393,7 +27869,7 @@ This method controls whether the position between two cached points is interpola
</argument>
<argument index="1" name="resource" type="Resource">
</argument>
- <argument index="2" name="arg2" type="int" default="0">
+ <argument index="2" name="flags" type="int" default="0">
</argument>
<description>
Save a resource to disk, to a given path.
@@ -27488,6 +27964,26 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
+ <method name="push_table">
+ <argument index="0" name="columns" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_table_column_expand">
+ <argument index="0" name="column" type="int">
+ </argument>
+ <argument index="1" name="expand" type="bool">
+ </argument>
+ <argument index="2" name="ratio" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="push_cell">
+ <description>
+ </description>
+ </method>
<method name="pop">
<description>
</description>
@@ -27539,7 +28035,7 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="scroll_to_line">
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="line" type="int">
</argument>
<description>
</description>
@@ -27652,7 +28148,7 @@ This method controls whether the position between two cached points is interpola
</constant>
<constant name="LIST_DOTS" value="2">
</constant>
- <constant name="ITEM_MAIN" value="0">
+ <constant name="ITEM_FRAME" value="0">
</constant>
<constant name="ITEM_TEXT" value="1">
</constant>
@@ -27672,10 +28168,14 @@ This method controls whether the position between two cached points is interpola
</constant>
<constant name="ITEM_LIST" value="9">
</constant>
- <constant name="ITEM_META" value="10">
+ <constant name="ITEM_META" value="11">
</constant>
</constants>
<theme_items>
+ <theme_item name="table_vseparation" type="int">
+ </theme_item>
+ <theme_item name="table_hseparation" type="int">
+ </theme_item>
<theme_item name="line_separation" type="int">
</theme_item>
<theme_item name="default_color" type="Color">
@@ -27989,7 +28489,7 @@ This method controls whether the position between two cached points is interpola
Rigid body 2D node.
</brief_description>
<description>
- Rigid body 2D node. This node is used for placing rigid bodies in the scene. It can contain a number of shapes, and also shift state between regular Rigid Body to Character or even Static.
+ Rigid body 2D node. This node is used for placing rigid bodies in the scene. It can contain a number of shapes, and also shift state between regular Rigid body, Kinematic, Character or Static.
Character mode forbids the node from being rotated. This node can have a custom force integrator function, for writing complex physics motion behavior per node.
As a warning, don't change this node position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop will yield strange behavior.
</description>
@@ -28012,7 +28512,7 @@ This method controls whether the position between two cached points is interpola
<return type="int">
</return>
<description>
- Return the current body mode, see [set_mode].
+ Return the current body mode, see [method set_mode].
</description>
</method>
<method name="set_mass">
@@ -28033,14 +28533,14 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="weight" type="float">
</argument>
<description>
- Set the body mass given standard earth-weight (gravity 9.8). Not really useful for 2D since most measures for this node are in pixels.
+ Set the body weight given standard earth-weight (gravity 9.8). Not really useful for 2D since most measures for this node are in pixels.
</description>
</method>
<method name="get_weight" qualifiers="const">
<return type="float">
</return>
<description>
- Return the body mass given standard earth-weight (gravity 9.8).
+ Return the body weight given standard earth-weight (gravity 9.8).
</description>
</method>
<method name="set_friction">
@@ -28061,7 +28561,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="bounce" type="float">
</argument>
<description>
- Set the body bounciness, from 0 (no bounce) to 1 (bounce).
+ Set the body bounciness, from 0 (no bounce) to 1 (full bounce).
</description>
</method>
<method name="get_bounce" qualifiers="const">
@@ -28075,36 +28575,42 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="gravity_scale" type="float">
</argument>
<description>
+ Set The gravity factor. This factor multiplies gravity intensity just for this body.
</description>
</method>
<method name="get_gravity_scale" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the gravity factor.
</description>
</method>
<method name="set_linear_damp">
<argument index="0" name="linear_damp" type="float">
</argument>
<description>
+ Set the linear damp for this body. If this value is different from -1, any linear damp derived from the world or areas will be overriden.
</description>
</method>
<method name="get_linear_damp" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the linear damp for this body.
</description>
</method>
<method name="set_angular_damp">
<argument index="0" name="angular_damp" type="float">
</argument>
<description>
+ Set the angular damp for this body. If this value is different from -1, any angular damp derived from the world or areas will be overriden.
</description>
</method>
<method name="get_angular_damp" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the angular damp for this body.
</description>
</method>
<method name="set_linear_velocity">
@@ -28118,7 +28624,7 @@ This method controls whether the position between two cached points is interpola
<return type="Vector2">
</return>
<description>
- Return the body linear velocity. This changes by physics granularity. See [set_linear_velocity].
+ Return the body linear velocity. This changes by physics granularity. See [method set_linear_velocity].
</description>
</method>
<method name="set_angular_velocity">
@@ -28132,7 +28638,7 @@ This method controls whether the position between two cached points is interpola
<return type="float">
</return>
<description>
- Return the body angular velocity. This changes by physics granularity. See [set_angular_velocity].
+ Return the body angular velocity. This changes by physics granularity. See [method set_angular_velocity].
</description>
</method>
<method name="set_max_contacts_reported">
@@ -28146,14 +28652,14 @@ This method controls whether the position between two cached points is interpola
<return type="int">
</return>
<description>
- Return the maximum contacts that can be reported. See [set_max_contacts_reported].
+ Return the maximum contacts that can be reported. See [method set_max_contacts_reported].
</description>
</method>
<method name="set_use_custom_integrator">
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Set to true if the body shall not do any internal force integration at all (like gravity or air friction). Only the [_integrate_forces] will be able to integrate them if overrided.
+ Set to true if the body shall not do any internal force integration at all (like gravity or air friction). Only the [method _integrate_forces] will be able to integrate them if overrided.
</description>
</method>
<method name="is_using_custom_integrator">
@@ -28167,7 +28673,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="enabled" type="bool">
</argument>
<description>
- Enable contact monitoring. (the signals to notify when a body entered/exited collision).
+ Enable contact monitoring. This allows the body to emit signals when it collides with another.
</description>
</method>
<method name="is_contact_monitor_enabled" qualifiers="const">
@@ -28181,19 +28687,22 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="mode" type="int">
</argument>
<description>
+ Set the continuous collision detection mode from the enum CCD_MODE_*.
+ Coninuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. The first is more precise, and misses less impacts by small, fast-moving objects. The second is faster to compute, but can miss small, fat-moving objects.
</description>
</method>
<method name="get_continuous_collision_detection_mode" qualifiers="const">
<return type="int">
</return>
<description>
+ Return whether this body is using continuous collision detection.
</description>
</method>
<method name="set_axis_velocity">
<argument index="0" name="axis_velocity" type="Vector2">
</argument>
<description>
- Set an axis velocity. The velocity in the given vector axis will be set as the given vector length. (This is useful for jumping behavior).
+ Set an axis velocity. The velocity in the given vector axis will be set as the given vector length. This is useful for jumping behavior.
</description>
</method>
<method name="apply_impulse">
@@ -28202,31 +28711,35 @@ This method controls whether the position between two cached points is interpola
<argument index="1" name="impulse" type="Vector2">
</argument>
<description>
- Apply a positioned impulse (which will be affected by the body mass and shape).
+ Apply a positioned impulse (which will be affected by the body mass and shape). This is the equivalent of hitting a billiard ball with a cue: a force that is applied once, and only once.
</description>
</method>
<method name="set_applied_force">
<argument index="0" name="force" type="Vector2">
</argument>
<description>
+ Set the applied force vector. This is the equivalent of pushing a box over the ground: the force applied is applied constantly.
</description>
</method>
<method name="get_applied_force" qualifiers="const">
<return type="Vector2">
</return>
<description>
+ Return the applied force vector.
</description>
</method>
<method name="set_sleeping">
<argument index="0" name="sleeping" type="bool">
</argument>
<description>
+ Set whether a body is isleeping or not. Sleeping bodies are not affected by forces until a collision or an [method apply_impulse]/[method set_applied_force] wakes them up. Until then, they behave like a static body.
</description>
</method>
<method name="is_sleeping" qualifiers="const">
<return type="bool">
</return>
<description>
+ Return whether the body is sleeping.
</description>
</method>
<method name="set_can_sleep">
@@ -28234,13 +28747,14 @@ This method controls whether the position between two cached points is interpola
</argument>
<description>
Set the body ability to fall asleep when not moving. This saves an enormous amount of processor time when there are plenty of rigid bodies (non static) in a scene.
+ Sleeping bodies are not affected by forces until a collision or an [method apply_impulse]/[method set_applied_force] wakes them up. Until then, they behave like a static body.
</description>
</method>
<method name="is_able_to_sleep" qualifiers="const">
<return type="bool">
</return>
<description>
- Return true if the body has the ability to fall asleep when not moving. See [set_can_sleep].
+ Return true if the body has the ability to fall asleep when not moving. See [method set_can_sleep].
</description>
</method>
<method name="test_motion">
@@ -28253,12 +28767,14 @@ This method controls whether the position between two cached points is interpola
<argument index="2" name="result" type="Physics2DTestMotionResult" default="NULL">
</argument>
<description>
+ Return whether the body would collide, if it tried to move in the given vector. This method allows two extra parameters: A margin, which increases slightly the size of the shapes involved in the collision detection, and an object of type [Physics2DTestMotionResult], which will store additional information about the collision (should there be one).
</description>
</method>
<method name="get_colliding_bodies" qualifiers="const">
<return type="Array">
</return>
<description>
+ Return a list of the bodies colliding with this one.
</description>
</method>
</methods>
@@ -28267,7 +28783,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="body" type="Object">
</argument>
<description>
- Emitted when a new body enters into contact with this one. Contact monitor and contacts reported must be enabled for this to work.
+ Emitted when a body enters into contact with this one. Contact monitor and contacts reported must be enabled for this to work.
</description>
</signal>
<signal name="body_enter_shape">
@@ -28280,7 +28796,8 @@ This method controls whether the position between two cached points is interpola
<argument index="3" name="local_shape" type="int">
</argument>
<description>
- Emitted when a new body sub-shape enters into contact with this one. Contact monitor and contacts reported must be enabled for this to work.
+ Emitted when a body enters into contact with this one. Contact monitor and contacts reported must be enabled for this to work.
+ This signal not only receives the body that collided with this one, but also its [RID] (body_id), the shape index from the colliding body (body_shape), and the shape index from this body (local_shape) the other body collided with.
</description>
</signal>
<signal name="body_exit">
@@ -28301,26 +28818,31 @@ This method controls whether the position between two cached points is interpola
</argument>
<description>
Emitted when a body shape exits contact with this one. Contact monitor and contacts reported must be enabled for this to work.
+ This signal not only receives the body that stopped colliding with this one, but also its [RID] (body_id), the shape index from the colliding body (body_shape), and the shape index from this body (local_shape) the other body stopped colliding with.
</description>
</signal>
</signals>
<constants>
<constant name="MODE_STATIC" value="1">
- Static mode (does not move, can't be moved).
+ Static mode. The body behaves like a [StaticBody2D], and can only move by user code.
</constant>
<constant name="MODE_KINEMATIC" value="3">
+ Kinematic body. The body behaves like a [KinematicBody2D], and can only move by user code.
</constant>
<constant name="MODE_RIGID" value="0">
- Rigid body, can move and rotate.
+ Rigid body. This is the "natural" state of a rigid body. It is affected by forces, and can move, rotate, and be affected by user code.
</constant>
<constant name="MODE_CHARACTER" value="2">
- Character body, can move but not rotate.
+ Character body. This behaves like a rigid body, but can not rotate.
</constant>
<constant name="CCD_MODE_DISABLED" value="0">
+ Disables continuous collision detection. This is the fastest way to detect body collisions, but can miss small, fast-moving objects.
</constant>
<constant name="CCD_MODE_CAST_RAY" value="1">
+ Enables continuous collision detection by raycasting. It is faster than shapecasting, but less precise.
</constant>
<constant name="CCD_MODE_CAST_SHAPE" value="2">
+ Enables continuous collision detection by shapecasting. It is the slowest CCD method, and the most precise.
</constant>
</constants>
</class>
@@ -28422,8 +28944,8 @@ This method controls whether the position between two cached points is interpola
<argument index="2" name="length" type="int">
</argument>
<description>
- Create new data for the sample, with format (see FORMAT_* constants), stereo hint, and length in frames (not samples or bytes!).
- Calling this method overrides previously existing data. Stereo samples are interleaved pairs of left and right points (in that order).
+ Create new data for the sample, with format (see FORMAT_* constants), stereo hint, and length in samples (not bytes).
+ Calling this method overrides previously existing data. Stereo samples are interleaved pairs of left and right points (in that order), but count as one sample for length purposes.
</description>
</method>
<method name="get_format" qualifiers="const">
@@ -28444,15 +28966,18 @@ This method controls whether the position between two cached points is interpola
<return type="int">
</return>
<description>
- Return the sample length in frames.
+ Return the sample length in samples. Stereo samples count as one, even if they are made of a left and a right sample.
</description>
</method>
<method name="set_data">
<argument index="0" name="data" type="RawArray">
</argument>
<description>
- Set sample data. Data must be little endian, no matter the host platform, and exactly as long as to fit all frames.
- For example, if data is stereo, 16 bits, 256 frames, it will be 1024 bytes long.
+ Set sample data. Data must be little endian, no matter the host platform, and exactly as long as to fit all samples. The length of this array can be calculated as follows:
+ Get the sample length ([method get_length]).
+ If the sample format is FORMAT_PCM16, multiply it by 2.
+ If the sample format is FORMAT_IMA_ADPCM, divide it by 2 (rounding any fraction up), then add 4.
+ If the sample is stereo ([method is_stereo]), multiply it by 2.
</description>
</method>
<method name="get_data" qualifiers="const">
@@ -28521,7 +29046,7 @@ This method controls whether the position between two cached points is interpola
</methods>
<constants>
<constant name="FORMAT_PCM8" value="0">
- 8-bits signed little endian PCM audio.
+ 8-bits signed PCM audio.
</constant>
<constant name="FORMAT_PCM16" value="1">
16-bits signed little endian PCM audio.
@@ -29261,7 +29786,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_nodes_in_group">
<return type="Array">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="group" type="String">
</argument>
<description>
</description>
@@ -29272,6 +29797,14 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
+ <method name="has_group" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_auto_accept_quit">
<argument index="0" name="enabled" type="bool">
</argument>
@@ -29866,13 +30399,13 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
- <method name="scalar_const_node_get_value">
+ <method name="scalar_const_node_get_value" qualifiers="const">
+ <return type="float">
+ </return>
<argument index="0" name="shader_type" type="int">
</argument>
<argument index="1" name="id" type="int">
</argument>
- <argument index="2" name="arg2" type="float">
- </argument>
<description>
</description>
</method>
@@ -29886,13 +30419,13 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
- <method name="vec_const_node_get_value">
+ <method name="vec_const_node_get_value" qualifiers="const">
+ <return type="Vector3">
+ </return>
<argument index="0" name="shader_type" type="int">
</argument>
<argument index="1" name="id" type="int">
</argument>
- <argument index="2" name="arg2" type="Vector3">
- </argument>
<description>
</description>
</method>
@@ -29906,13 +30439,13 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
- <method name="rgb_const_node_get_value">
+ <method name="rgb_const_node_get_value" qualifiers="const">
+ <return type="Color">
+ </return>
<argument index="0" name="shader_type" type="int">
</argument>
<argument index="1" name="id" type="int">
</argument>
- <argument index="2" name="arg2" type="Color">
- </argument>
<description>
</description>
</method>
@@ -29926,13 +30459,13 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
- <method name="xform_const_node_get_value">
+ <method name="xform_const_node_get_value" qualifiers="const">
+ <return type="Transform">
+ </return>
<argument index="0" name="shader_type" type="int">
</argument>
<argument index="1" name="id" type="int">
</argument>
- <argument index="2" name="arg2" type="Transform">
- </argument>
<description>
</description>
</method>
@@ -29946,13 +30479,13 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
- <method name="texture_node_get_filter_size">
+ <method name="texture_node_get_filter_size" qualifiers="const">
+ <return type="int">
+ </return>
<argument index="0" name="shader_type" type="int">
</argument>
<argument index="1" name="id" type="int">
</argument>
- <argument index="2" name="arg2" type="int">
- </argument>
<description>
</description>
</method>
@@ -29966,13 +30499,13 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
- <method name="texture_node_get_filter_strength">
+ <method name="texture_node_get_filter_strength" qualifiers="const">
+ <return type="float">
+ </return>
<argument index="0" name="shader_type" type="int">
</argument>
<argument index="1" name="id" type="float">
</argument>
- <argument index="2" name="arg2" type="float">
- </argument>
<description>
</description>
</method>
@@ -30399,6 +30932,8 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="node_get_state" qualifiers="const">
+ <return type="Variant">
+ </return>
<argument index="0" name="shader_type" type="int">
</argument>
<argument index="1" name="id" type="int">
@@ -30661,12 +31196,14 @@ This method controls whether the position between two cached points is interpola
<method name="set_shader_param">
<argument index="0" name="param" type="String">
</argument>
- <argument index="1" name="value" type="var">
+ <argument index="1" name="value" type="Variant">
</argument>
<description>
</description>
</method>
<method name="get_shader_param" qualifiers="const">
+ <return type="Variant">
+ </return>
<argument index="0" name="param" type="String">
</argument>
<description>
@@ -30742,6 +31279,8 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="collide_and_get_contacts">
+ <return type="Variant">
+ </return>
<argument index="0" name="local_xform" type="Matrix32">
</argument>
<argument index="1" name="with_shape" type="Shape2D">
@@ -30754,6 +31293,8 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="collide_with_motion_and_get_contacts">
+ <return type="Variant">
+ </return>
<argument index="0" name="local_xform" type="Matrix32">
</argument>
<argument index="1" name="local_motion" type="Vector2">
@@ -31308,6 +31849,12 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
+ <method name="set_hidden">
+ <argument index="0" name="hidden" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_notify_local_transform">
<argument index="0" name="enable" type="bool">
</argument>
@@ -31596,7 +32143,7 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="play">
- <argument index="0" name="arg0" type="float" default="0">
+ <argument index="0" name="offset" type="float" default="0">
</argument>
<description>
</description>
@@ -32429,7 +32976,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="vel" type="Vector2">
</argument>
<description>
- Set a constant linear velocity for the body.
+ Set a constant linear velocity for the body. This does not move the body, but affects other bodies touching it, as if it was moving.
</description>
</method>
<method name="set_constant_angular_velocity">
@@ -32443,7 +32990,7 @@ This method controls whether the position between two cached points is interpola
<return type="Vector2">
</return>
<description>
- Return the constant linear velocity for the body.
+ Return the constant linear velocity for the body. This does not rotate the body, but affects other bodies touching it, as if it was rotating.
</description>
</method>
<method name="get_constant_angular_velocity" qualifiers="const">
@@ -32457,24 +33004,28 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="friction" type="float">
</argument>
<description>
+ Set the body friction, from 0 (frictionless) to 1 (full friction).
</description>
</method>
<method name="get_friction" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the body friction.
</description>
</method>
<method name="set_bounce">
<argument index="0" name="bounce" type="float">
</argument>
<description>
+ Set the body bounciness, from 0 (not bouncy) to 1 (bouncy).
</description>
</method>
<method name="get_bounce" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the body bounciness.
</description>
</method>
</methods>
@@ -32525,6 +33076,178 @@ This method controls whether the position between two cached points is interpola
Return a chunk data with the received bytes. The amount of bytes to be received can be requested in the "bytes" argument. If not enough bytes are available, the function will return how many were actually received. This function returns two values, an [Error] code, and a data array.
</description>
</method>
+ <method name="get_available_bytes" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="set_big_endian">
+ <argument index="0" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="is_big_endian_enabled" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="put_8">
+ <argument index="0" name="val" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="put_u8">
+ <argument index="0" name="val" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="put_16">
+ <argument index="0" name="val" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="put_u16">
+ <argument index="0" name="val" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="put_32">
+ <argument index="0" name="val" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="put_u32">
+ <argument index="0" name="val" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="put_64">
+ <argument index="0" name="val" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="put_u64">
+ <argument index="0" name="val" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="put_float">
+ <argument index="0" name="val" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="put_double">
+ <argument index="0" name="val" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="put_utf8_string">
+ <argument index="0" name="val" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="put_var">
+ <argument index="0" name="val" type="Variant">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_8">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_u8">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_16">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_u16">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_32">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_u32">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_64">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_u64">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_float">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_double">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_string">
+ <return type="String">
+ </return>
+ <argument index="0" name="bytes" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_utf8_string">
+ <return type="String">
+ </return>
+ <argument index="0" name="bytes" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_var">
+ <return type="Variant">
+ </return>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
@@ -32647,145 +33370,177 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="stream" type="Stream">
</argument>
<description>
+ Set the [EventStream] this player will play.
</description>
</method>
<method name="get_stream" qualifiers="const">
<return type="Stream">
</return>
<description>
+ Return the currently assigned stream.
</description>
</method>
<method name="play">
- <argument index="0" name="arg0" type="float" default="0">
+ <argument index="0" name="offset" type="float" default="0">
</argument>
<description>
+ Play the currently assigned stream, starting from a given position (in seconds).
</description>
</method>
<method name="stop">
<description>
+ Stop the playback.
</description>
</method>
<method name="is_playing" qualifiers="const">
<return type="bool">
</return>
<description>
+ Return whether this player is playing.
</description>
</method>
<method name="set_paused">
<argument index="0" name="paused" type="bool">
</argument>
<description>
+ Pause stream playback.
</description>
</method>
<method name="is_paused" qualifiers="const">
<return type="bool">
</return>
<description>
+ Return whether the playback is currently paused.
</description>
</method>
<method name="set_loop">
<argument index="0" name="enabled" type="bool">
</argument>
<description>
+ Set whether the stream will be restarted at the end.
</description>
</method>
<method name="has_loop" qualifiers="const">
<return type="bool">
</return>
<description>
+ Return whether the stream will be restarted at the end.
</description>
</method>
<method name="set_volume">
<argument index="0" name="volume" type="float">
</argument>
<description>
+ Set the playback volume for this player. This is a float between 0.0 (silent) and 1.0 (full volume). Values over 1.0 will amplify sound even more, but may introduce distortion. Negative values will just invert the output waveform, which produces no audible difference.
</description>
</method>
<method name="get_volume" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the playback volume for this player.
</description>
</method>
<method name="set_volume_db">
<argument index="0" name="db" type="float">
</argument>
<description>
+ Set the playback volume for this player, in decibels. This is a float between -80.0 (silent) and 0.0 (full volume). Values under -79.0 get truncated to -80, but values over 0.0 do not, so the warnings for overamplifying (see [set_volume]) still apply.
</description>
</method>
<method name="get_volume_db" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the playback volume for this player, in decibels.
</description>
</method>
<method name="set_buffering_msec">
<argument index="0" name="msec" type="int">
</argument>
<description>
+ Set the size (in milliseconds) of the audio buffer. A long audio buffer protects better against slowdowns, but responds worse to changes (in volume, stream played...). A shorter buffer takes less time to respond to changes, but may stutter if the application suffers some slowdown.
+ Default is 500 milliseconds.
</description>
</method>
<method name="get_buffering_msec" qualifiers="const">
<return type="int">
</return>
<description>
+ Return the size of the audio buffer.
</description>
</method>
<method name="set_loop_restart_time">
<argument index="0" name="secs" type="float">
</argument>
<description>
+ Set the point in time the stream will rewind to, when looping.
</description>
</method>
<method name="get_loop_restart_time" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the point in time the stream will rewind to, when looping.
</description>
</method>
<method name="get_stream_name" qualifiers="const">
<return type="String">
</return>
<description>
+ Return the name of the currently assigned stream. This is not the file name, but a field inside the file. If no stream is assigned, if returns "&lt;No Stream&gt;".
</description>
</method>
<method name="get_loop_count" qualifiers="const">
<return type="int">
</return>
<description>
+ Return the number of times the playback has looped.
</description>
</method>
<method name="get_pos" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the playback position, in seconds.
</description>
</method>
<method name="seek_pos">
<argument index="0" name="time" type="float">
</argument>
<description>
+ Set the playback position, in seconds.
</description>
</method>
<method name="set_autoplay">
<argument index="0" name="enabled" type="bool">
</argument>
<description>
+ Set whether this player will start playing as soon as it enters the scene tree.
</description>
</method>
<method name="has_autoplay" qualifiers="const">
<return type="bool">
</return>
<description>
+ Return whether this player will start playing as soon as it enters the scene tree.
</description>
</method>
<method name="get_length" qualifiers="const">
<return type="float">
</return>
<description>
+ Return the length of the stream, in seconds.
</description>
</method>
</methods>
+ <signals>
+ <signal name="finished">
+ <description>
+ This signal triggers when the player stops playing. It will not trigger on each loop.
+ </description>
+ </signal>
+ </signals>
<constants>
</constants>
</class>
@@ -33335,9 +34090,9 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="draw" qualifiers="const">
- <argument index="0" name="arg0" type="RID">
+ <argument index="0" name="canvas_item" type="RID">
</argument>
- <argument index="1" name="arg1" type="Rect2">
+ <argument index="1" name="rect" type="Rect2">
</argument>
<description>
</description>
@@ -33490,7 +34245,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_expand_margin_size" qualifiers="const">
<return type="float">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="margin" type="int">
</argument>
<description>
Return the expand margin size (from enum MARGIN_*). Parts of the image below the size of the margin (and in the direction of the margin) will not expand.
@@ -33531,7 +34286,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_margin_size" qualifiers="const">
<return type="float">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="margin" type="int">
</argument>
<description>
</description>
@@ -33547,7 +34302,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_expand_margin_size" qualifiers="const">
<return type="float">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="margin" type="int">
</argument>
<description>
</description>
@@ -34018,6 +34773,14 @@ This method controls whether the position between two cached points is interpola
</theme_item>
<theme_item name="font_color_fg" type="Color">
</theme_item>
+ <theme_item name="increment_hilite" type="Texture">
+ </theme_item>
+ <theme_item name="decrement_hilite" type="Texture">
+ </theme_item>
+ <theme_item name="increment" type="Texture">
+ </theme_item>
+ <theme_item name="decrement" type="Texture">
+ </theme_item>
<theme_item name="font" type="Font">
</theme_item>
<theme_item name="tab_fg" type="StyleBox">
@@ -34081,7 +34844,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_line" qualifiers="const">
<return type="String">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="line" type="int">
</argument>
<description>
Return the text of a specific line.
@@ -34090,7 +34853,7 @@ This method controls whether the position between two cached points is interpola
<method name="cursor_set_column">
<argument index="0" name="column" type="int">
</argument>
- <argument index="1" name="arg1" type="bool">
+ <argument index="1" name="adjust_viewport" type="bool" default="false">
</argument>
<description>
</description>
@@ -34098,7 +34861,7 @@ This method controls whether the position between two cached points is interpola
<method name="cursor_set_line">
<argument index="0" name="line" type="int">
</argument>
- <argument index="1" name="arg1" type="bool">
+ <argument index="1" name="adjust_viewport" type="bool" default="false">
</argument>
<description>
</description>
@@ -34440,7 +35203,7 @@ This method controls whether the position between two cached points is interpola
</argument>
<argument index="2" name="modulate" type="Color" default="Color(1,1,1,1)">
</argument>
- <argument index="3" name="arg3" type="bool" default="false">
+ <argument index="3" name="transpose" type="bool" default="false">
</argument>
<description>
</description>
@@ -34454,7 +35217,7 @@ This method controls whether the position between two cached points is interpola
</argument>
<argument index="3" name="modulate" type="Color" default="Color(1,1,1,1)">
</argument>
- <argument index="4" name="arg4" type="bool" default="false">
+ <argument index="4" name="transpose" type="bool" default="false">
</argument>
<description>
</description>
@@ -34468,7 +35231,7 @@ This method controls whether the position between two cached points is interpola
</argument>
<argument index="3" name="modulate" type="Color" default="Color(1,1,1,1)">
</argument>
- <argument index="4" name="arg4" type="bool" default="false">
+ <argument index="4" name="transpose" type="bool" default="false">
</argument>
<description>
</description>
@@ -34543,7 +35306,7 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
- <method name="set_scale">
+ <method name="set_texture_scale">
<argument index="0" name="scale" type="Vector2">
</argument>
<description>
@@ -34591,7 +35354,7 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
- <method name="get_scale" qualifiers="const">
+ <method name="get_texture_scale" qualifiers="const">
<return type="Vector2">
</return>
<description>
@@ -34813,7 +35576,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_icon_list" qualifiers="const">
<return type="StringArray">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="type" type="String">
</argument>
<description>
</description>
@@ -34859,7 +35622,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_stylebox_list" qualifiers="const">
<return type="StringArray">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="type" type="String">
</argument>
<description>
</description>
@@ -34905,7 +35668,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_font_list" qualifiers="const">
<return type="StringArray">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="type" type="String">
</argument>
<description>
</description>
@@ -34951,7 +35714,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_color_list" qualifiers="const">
<return type="StringArray">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="type" type="String">
</argument>
<description>
</description>
@@ -34997,7 +35760,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_constant_list" qualifiers="const">
<return type="StringArray">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="type" type="String">
</argument>
<description>
</description>
@@ -35017,7 +35780,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_type_list" qualifiers="const">
<return type="StringArray">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="type" type="String">
</argument>
<description>
</description>
@@ -35063,6 +35826,16 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="wait_to_finish">
+ <return type="Variant">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="set_name">
+ <return type="Error">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
<description>
</description>
</method>
@@ -35302,6 +36075,18 @@ This method controls whether the position between two cached points is interpola
Return the collision bounce parameter.
</description>
</method>
+ <method name="set_occluder_light_mask">
+ <argument index="0" name="mask" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_occluder_light_mask" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="set_cell">
<argument index="0" name="x" type="int">
</argument>
@@ -36167,19 +36952,19 @@ This method controls whether the position between two cached points is interpola
<method name="translate" qualifiers="const">
<return type="String">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="message" type="String">
</argument>
<description>
</description>
</method>
<method name="add_translation">
- <argument index="0" name="arg0" type="Object">
+ <argument index="0" name="translation" type="Translation">
</argument>
<description>
</description>
</method>
<method name="remove_translation">
- <argument index="0" name="arg0" type="Object">
+ <argument index="0" name="translation" type="Translation">
</argument>
<description>
</description>
@@ -36217,17 +37002,17 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="set_column_min_width">
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="column" type="int">
</argument>
- <argument index="1" name="arg1" type="int">
+ <argument index="1" name="min_width" type="int">
</argument>
<description>
</description>
</method>
<method name="set_column_expand">
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="column" type="int">
</argument>
- <argument index="1" name="arg1" type="bool">
+ <argument index="1" name="expand" type="bool">
</argument>
<description>
</description>
@@ -36235,13 +37020,13 @@ This method controls whether the position between two cached points is interpola
<method name="get_column_width" qualifiers="const">
<return type="int">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="column" type="int">
</argument>
<description>
</description>
</method>
<method name="set_hide_root">
- <argument index="0" name="arg0" type="bool">
+ <argument index="0" name="enable" type="bool">
</argument>
<description>
</description>
@@ -36701,6 +37486,8 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="remove_child">
+ <return type="TreeItem">
+ </return>
<argument index="0" name="child" type="Object">
</argument>
<description>
@@ -36799,7 +37586,7 @@ This method controls whether the position between two cached points is interpola
</argument>
<argument index="1" name="button" type="Texture">
</argument>
- <argument index="2" name="arg2" type="int">
+ <argument index="2" name="button_idx" type="int">
</argument>
<description>
</description>
@@ -37323,7 +38110,7 @@ This method controls whether the position between two cached points is interpola
</argument>
<argument index="1" name="property" type="String">
</argument>
- <argument index="2" name="value" type="var">
+ <argument index="2" name="value" type="Variant">
</argument>
<description>
</description>
@@ -37333,7 +38120,7 @@ This method controls whether the position between two cached points is interpola
</argument>
<argument index="1" name="property" type="String">
</argument>
- <argument index="2" name="value" type="var">
+ <argument index="2" name="value" type="Variant">
</argument>
<description>
</description>
@@ -38361,6 +39148,12 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
+ <method name="get_video_texutre">
+ <return type="Texture">
+ </return>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
@@ -38691,7 +39484,7 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="set_render_target_to_screen_rect">
- <argument index="0" name="arg0" type="Rect2">
+ <argument index="0" name="rect" type="Rect2">
</argument>
<description>
</description>
@@ -40163,6 +40956,14 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
+ <method name="canvas_item_set_z">
+ <argument index="0" name="arg0" type="RID">
+ </argument>
+ <argument index="1" name="arg1" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="canvas_item_add_line">
<argument index="0" name="arg0" type="RID">
</argument>
@@ -40608,6 +41409,8 @@ This method controls whether the position between two cached points is interpola
</description>
<methods>
<method name="get_ref" qualifiers="const">
+ <return type="Object">
+ </return>
<description>
</description>
</method>
@@ -40819,7 +41622,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_attribute_name" qualifiers="const">
<return type="String">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="idx" type="int">
</argument>
<description>
</description>
@@ -40827,7 +41630,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_attribute_value" qualifiers="const">
<return type="String">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="idx" type="int">
</argument>
<description>
</description>
@@ -40835,7 +41638,7 @@ This method controls whether the position between two cached points is interpola
<method name="has_attribute" qualifiers="const">
<return type="bool">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="name" type="String">
</argument>
<description>
</description>
@@ -40843,7 +41646,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_named_attribute_value" qualifiers="const">
<return type="String">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="name" type="String">
</argument>
<description>
</description>
@@ -40851,7 +41654,7 @@ This method controls whether the position between two cached points is interpola
<method name="get_named_attribute_value_safe" qualifiers="const">
<return type="String">
</return>
- <argument index="0" name="arg0" type="String">
+ <argument index="0" name="name" type="String">
</argument>
<description>
</description>
@@ -40875,7 +41678,7 @@ This method controls whether the position between two cached points is interpola
<method name="seek">
<return type="int">
</return>
- <argument index="0" name="arg0" type="int">
+ <argument index="0" name="pos" type="int">
</argument>
<description>
</description>
diff --git a/doc/core_classes.xml b/doc/core_classes.xml
deleted file mode 100644
index c37b50f122..0000000000
--- a/doc/core_classes.xml
+++ /dev/null
@@ -1,2654 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<doc version="1.0" name="Core Types">
-<class category="Core" name="Vector3">
- <brief_description>
- Vector class, which performs basic 3D vector math operations.
- </brief_description>
- <description>
- Vector3 is one of the core classes of the engine, and includes several built-in helper functions to perform basic vecor math operations.
- </description>
- <methods>
- <method name="operator+">
- <argument index="0" name="b" type="Vector3">
- </argument>
- <return type="Vector3">
- Sum.
- </return>
- <description>
- Add two vectors.
- </description>
- </method>
- <method name="operator-">
- <argument index="0" name="b" type="Vector3">
- </argument>
- <return type="Vector3">
- Difference.
- </return>
- <description>
- Substract two vectors.
- </description>
- </method>
- <method name="operator/">
- <argument index="0" name="b" type="Vector3">
- </argument>
- <return type="Vector3">
- Quotient.
- </return>
- <description>
- Divide two vectors (component wise).
- </description>
- </method>
- <method name="operator*">
- <argument index="0" name="b" type="Vector3">
- </argument>
- <return type="Vector3">
- Product.
- </return>
- <description>
- Multiply two vectors (components wise).
- </description>
- </method>
- <method name="set_axis">
- <argument index="0" name="axis" type="int">
- Axis Index.
- </argument>
- <argument index="1" name="value" type="real">
- Value.
- </argument>
- <description>
- Set an individual axis (0 is X, 1 is Y and 2 is Z). the enum constants Vector.AXIS_X, Vector.AXIS_Y, and Vector.AXIS_Z, are also valid. This is specially useful for for-loops.
- </description>
- </method>
- <method name="get_axis">
- <argument index="0" name="axis" type="int">
- Axis Index.
- </argument>
- <return type="real">
- Value.
- </return>
- <description>
- Set an individual axis (0 is X, 1 is Y and 2 is Z). the enum constants Vector.AXIS_X, Vector.AXIS_Y, and Vector.AXIS_Z, are also valid. This is specially useful for for-loops.
- </description>
- </method>
- <method name="length">
- <return type="real">
- Length: sqrt(x^2+y^2+z^2)
- </return>
- <description>
- Return the length of the vector.
- </description>
- </method>
- <method name="length_squared">
- <return type="real">
- Squared Length: x^2+y^2+z^2.
- </return>
- <description>
- Return the length of the vector, without the square root step.
- </description>
- </method>
- <method name="normalize">
- <description>
- Normalize the vector to unit length. This is the same as v = v / v.length()
- </description>
- </method>
- <method name="normalized">
- <return type="Vector3">
- </return>
- <description>
- Return a copy of the normalized vector to unit length. This is the same as v / v.length()
- </description>
- </method>
- <method name="inverse">
- <return type="Vector3">
- Inverse: 1/v
- </return>
- <description>
- Returns the inverse of the vector. this is the same as Vector3( 1.0 / v.x, 1.0 / v.y, 1.0 / v.z )
- </description>
- </method>
- <method name="zero">
- <description>
- Set x,y and z to 0.
- </description>
- </method>
- <method name="snap">
- <argument index="0" name="snap" type="real">
- </argument>
- <description>
- Snap the vector in each axis the the lowest nearest multiple. ie: 4,5,7 snapped to 2 equals 4,4,6.
- </description>
- </method>
- <method name="snapped">
- <argument index="0" name="snap" type="real">
- </argument>
- <return type="Vector3">
- Snapped copy.
- </return>
- <description>
- Return a copy of the vector, snapped to the lowest neared multiple.
- </description>
- </method>
- <method name="linear_interpolate">
- <argument index="0" name="b" type="Vector3">
- </argument>
- <argument index="1" name="i" type="real">
- </argument>
- <return type="Vector3">
- </return>
- <description>
- Linearly interpolates the vector to a given one (b), by the given amount (i)
- </description>
- </method>
- <method name="cubic_interpolate">
- <argument index="0" name="a" type="Vector3">
- </argument>
- <argument index="1" name="c" type="Vector3">
- </argument>
- <argument index="2" name="d" type="Vector3">
- </argument>
- <argument index="3" name="i" type="real">
- </argument>
- <return type="Vector3">
- </return>
- <description>
- Perform a cubic interpolation between vectors a,b,c,d (b is current), by the given amount (i).
- </description>
- </method>
- <method name="cross">
- <argument index="0" name="b" type="Vector3">
- </argument>
- <return type="Vector3">
- Cross product.
- </return>
- <description>
- Return the cross product with b.
- </description>
- </method>
- <method name="dot">
- <argument index="0" name="b" type="Vector3">
- </argument>
- <return type="real">
- </return>
- <description>
- Return the dot product with b.
- </description>
- </method>
- <method name="distance_to">
- <argument index="0" name="b" type="Vector3">
- </argument>
- <return type="real">
- </return>
- <description>
- Return the distance to b.
- </description>
- </method>
- <method name="distance_squared_to">
- <argument index="0" name="b" type="Vector3">
- </argument>
- <return type="real">
- </return>
- <description>
- Return the squared distance (distance minus the last square root) to b.
- </description>
- </method>
- </methods>
- <constants>
- <constant name="AXIS_X" value="0">
- </constant>
- <constant name="AXIS_Y" value="1">
- </constant>
- <constant name="AXIS_Z" value="2">
- </constant>
- </constants>
- <members>
- <member name="x" type="real">
- </member>
- <member name="y" type="real">
- </member>
- <member name="z" type="real">
- </member>
- </members>
-</class>
-<class category="Core" name="AABB">
- <brief_description>
- Axis-Aligned-Bounding-Box.
- </brief_description>
- <description>
- AABB stands for "Axis Aligned Bounding Box". It consits of a position and a size, which for an box that is always aligned to the x, y and z axis, which goes from "pos" to "pos+size".
- </description>
- <methods>
- <method name="has_no_area">
- <return type="bool">
- </return>
- <description>
- Returns true if the AABB volume is empty (even if it has a surface). Holds true if size.x,y or z is 0.
- </description>
- </method>
- <method name="has_no_surface">
- <return type="bool">
- </return>
- <description>
- Return true if size is 0,0,0.
- </description>
- </method>
- <method name="area">
- <return type="real">
- </return>
- <description>
- Compute the volume of the AABB.
- </description>
- </method>
- <method name="intersects">
- <argument index="0" name="b" type="AABB">
- </argument>
- <return type="bool">
- </return>
- <description>
- Returns true if this AABB shares a portion of space with b.
- </description>
- </method>
- <method name="encloses">
- <argument index="0" name="b" type="AABB">
- </argument>
- <return type="bool">
- </return>
- <description>
- Returns true if this AABB completely encloses b.
- </description>
- </method>
- <method name="merge_with">
- <argument index="0" name="b" type="AABB">
- </argument>
- <description>
- Expand this AABB to also enclose the area of b.
- </description>
- </method>
- <method name="intersection_with">
- <argument index="0" name="b" type="AABB">
- </argument>
- <return type="AABB">
- </return>
- <description>
- Return the shared portion of space with b (empty if they don't intersect).
- </description>
- </method>
- <method name="intersects_segment">
- <argument index="0" name="a" type="Vector3">
- </argument>
- <argument index="1" name="b" type="Vector3">
- </argument>
- <argument index="2" name="@r" type="Vector3">
- result (if they intersect)
- </argument>
- <argument index="3" name="@n" type="Vector3">
- normal (if they intersect)
- </argument>
- <return type="bool">
- </return>
- <description>
- Returns true if this AABB intersects segment "a" towards "b". Also, return the point and normal of intersection.
- </description>
- </method>
- <method name="intersects_plane">
- <argument index="0" name="p" type="Plane">
- </argument>
- <return type="bool">
- </return>
- <description>
- Returns true if this AABB intersects the plane b.
- </description>
- </method>
- <method name="has_point">
- <argument index="0" name="p" type="Vector3">
- </argument>
- <return type="bool">
- </return>
- <description>
- Return true if this AABB contains point "p".
- </description>
- </method>
- <method name="get_longest_axis">
- <return type="Vector3">
- Axis direction
- </return>
- <description>
- Get the normal of the longest axis in this AABB.
- </description>
- </method>
- <method name="get_longest_axis_index">
- <return type="int">
- </return>
- <description>
- Get the index of the longest axis in this AABB.
- </description>
- </method>
- <method name="get_longest_axis_size">
- <return type="real">
- Get the length of the longest axis in this AABB.
- </return>
- <description>
- </description>
- </method>
- <method name="get_edge">
- <argument index="0" name="@ra" type="Vector3">
- </argument>
- <argument index="1" name="@rb" type="Vector3">
- </argument>
- <description>
- Get one of the edges (0 to 11) of this AABB in "ra" and "rb".
- </description>
- </method>
- <method name="grow_by">
- <argument index="0" name="s" type="real">
- </argument>
- <description>
- Grow this AABB, by expanding its margin, by "s".
- </description>
- </method>
- <method name="expand_to">
- <argument index="0" name="p" type="Vector3">
- </argument>
- <description>
- Expand this AABB to contain point "p".
- </description>
- </method>
- </methods>
- <members>
- <member name="pos" type="Vector3">
- Position of the AABB.
- </member>
- <member name="size" type="Vector3">
- Suze of the AABB (should always be positive).
- </member>
- </members>
-</class>
-<class category="Core" name="Plane">
- <brief_description>
- Plane in hessian form.
- </brief_description>
- <description>
- Plane represents a normalized plane equation. Basically, "normal" is the normal of the plane (a,b,c normalized), and "d" is the distance from the origin to the plane (in the direction of "normal"). "Over" or "Above" the plane is considered the side of the plane towards where the normal is pointing.
- </description>
- <methods>
- <method name="normalize">
- <description>
- Normalize the plane (although it will be often normalized already).
- </description>
- </method>
- <method name="normalized">
- <return type="Plane">
- </return>
- <description>
- Returns a copy of the plane, normalized.
- </description>
- </method>
- <method name="is_point_over">
- <argument index="0" name="p" type="Vector3">
- </argument>
- <return type="bool">
- </return>
- <description>
- Returns true if "p" is located above the plane.
- </description>
- </method>
- <method name="distance">
- <argument index="0" name="p" type="Vector3">
- </argument>
- <return type="real">
- </return>
- <description>
- Returns the orthogonal distance from "p" to the plane. If positive, "p" is above, if negative, "p" is below.
- </description>
- </method>
- <method name="has_point">
- <argument index="0" name="p" type="Vector3">
- </argument>
- <return type="bool">
- </return>
- <description>
- Returns true if "p" is inside the plane (by a very minimum treshold).
- </description>
- </method>
- <method name="intersect_3">
- <argument index="0" name="a" type="Plane">
- </argument>
- <argument index="1" name="b" type="Plane">
- </argument>
- <argument index="2" name="@r" type="Vector3">
- </argument>
- <return type="bool">
- </return>
- <description>
- Returns true if this plane intersects with planes "a" and "b". The resulting intersectin is placed in "r".
- </description>
- </method>
- <method name="intersects_ray">
- <argument index="0" name="p" type="Vector3">
- </argument>
- <argument index="1" name="d" type="Vector3">
- </argument>
- <argument index="2" name="@r" type="Vector3">
- </argument>
- <return type="bool">
- </return>
- <description>
- Returns true if ray consiting of position "p" and direction normal "d" intersects this plane. If true, the result is placed in "r".
- </description>
- </method>
- <method name="intersects_segment">
- <argument index="0" name="sa" type="Vector3">
- </argument>
- <argument index="1" name="sb" type="Vector3">
- </argument>
- <argument index="2" name="@r" type="Vector3">
- </argument>
- <return type="bool">
- </return>
- <description>
- Returns true if segment from position "sa" to position "sb" intersects this plane. If true, the result is placed in "r".
-
- </description>
- </method>
- <method name="project">
- <argument index="0" name="p" type="Vector3">
- </argument>
- <return type="Vector3">
- </return>
- <description>
- Returns the orthogonal projection of point "p" into a point in the plane.
- </description>
- </method>
- <method name="is_almost_like">
- <argument index="0" name="b" type="plane">
- </argument>
- <return type="bool">
- </return>
- <description>
- Returns true if plane "b" is very similar to this one.
- </description>
- </method>
- </methods>
- <members>
- <member name="normal" type="Vector3">
- Plane normal vector (a,c and d in the plane equation normalized).
- </member>
- <member name="d" type="real">
- Plane distance (d in the plane equation).
- </member>
- </members>
-</class>
-<class category="Core" name="Quat">
- <brief_description>
- Quaternion.
- </brief_description>
- <description>
- Quaternion is a 4 dimensional vector that is used to represet a rotation. It mainly exists to perform SLERP (spherical-linear interpolation) between to rotations obtained by a Matrix3 cheaply. Adding quaternions also cheaply adds the rotations, however quaternions need to be often normalized, or else they suffer from precision issues.
- </description>
- <methods>
- <method name="length">
- <return type="real">
- </return>
- <description>
- Returns the length of the quaternion.
- </description>
- </method>
- <method name="length_squared">
- <return type="real">
- </return>
- <description>
- Returns the length of the quaternion, minus the square root.
- </description>
- </method>
- <method name="normalize">
- <description>
- Normalize the quaternion to unit length.
- </description>
- </method>
- <method name="normalized">
- <return type="Quat">
- </return>
- <description>
- Returns a copy of the quaternion, normalized to unit length.
- </description>
- </method>
- <method name="inverse">
- <return type="Quat">
- </return>
- <description>
- Returns the inverse of the quaternion (applies to the inverse rotatio too).
- </description>
- </method>
- <method name="dot">
- <argument index="0" name="b" type="Quat">
- </argument>
- <return type="real">
- </return>
- <description>
- Returns the dot product between two quaternions.
- </description>
- </method>
- <method name="set_euler">
- <argument index="0" name="e" type="Vector3">
- </argument>
- <description>
- Create a quaternion from euler rotation "e", as yaw, pitch, roll.
- </description>
- </method>
- <method name="slerp">
- <argument index="0" name="b" type="Quat">
- </argument>
- <argument index="1" name="i" type="real">
- </argument>
- <return type="Quat">
- </return>
- <description>
- Perform a spherical-linear interpolation with another quaternion.
- </description>
- </method>
- <method name="operator*">
- <argument index="0" name="arg1" type="Quat">
- </argument>
- <return type="Quat">
- </return>
- <description>
- Peform multiplication between two quaternions.
- </description>
- </method>
- </methods>
- <members>
- <member name="x" type="real">
- x-axis
- </member>
- <member name="y" type="real">
- y-axis
- </member>
- <member name="z" type="real">
- z-axis
- </member>
- <member name="w" type="real">
- w-axis
- </member>
- </members>
-</class>
-<class category="Core" name="Matrix3">
- <brief_description>
- 3x3 Matrix.
- </brief_description>
- <description>
- Matrix represent a 3x3 (3 rows by 3 columns) transformation matrix. it is used mainly to represent and accumulate transformations such as rotation or scale when used as an OCS (oriented coordinate system).
- </description>
- <methods>
- <method name="invert">
- <description>
- Invert the matrix (transformations are reversed).
- </description>
- </method>
- <method name="transpose">
- <description>
- Transpose the matrix (transformations are reversed only for orthogonal matrices).
- </description>
- </method>
- <method name="inverse">
- <return type="Matrix3">
- </return>
- <description>
- Returns the inverse of the matrix.
- </description>
- </method>
- <method name="transposed">
- <return type="Matrix3">
- </return>
- <description>
- Returns the transposition of the matrix.
- </description>
- </method>
- <method name="rotate">
- <argument index="0" name="axis" type="Vector3">
- </argument>
- <argument index="1" name="phi" type="real">
- </argument>
- <description>
- Rotates the matrix in normalized "axis" by amount "phi" in radians. (This is equivalent to glRotate from OpenGL).
- </description>
- </method>
- <method name="scale">
- <argument index="0" name="s" type="Vector3">
- </argument>
- <description>
- Scale each axis of the rotated matrix by 's".
- </description>
- </method>
- <method name="get_scale">
- <return type="Vector3">
- </return>
- <description>
- Get the scale of the matrix.
- </description>
- </method>
- <method name="set_euler">
- <argument index="0" name="e" type="Vector3">
- </argument>
- <description>
- Create an orthogonal matrix from euler angles "e", as yaw, pitch, roll.
- </description>
- </method>
- <method name="get_euler">
- <return type="Vector3">
- </return>
- <description>
- Computes and returns the euler engles for an orthogonal matrix, as yaw, pitch, roll.
- </description>
- </method>
- <method name="tdotx">
- <argument index="0" name="v" type="Vector3">
- </argument>
- <return type="Vector3">
- </return>
- <description>
- Computes and returns a dot product with transposed axis x.
- </description>
- </method>
- <method name="tdoty">
- <argument index="0" name="v" type="Vector3">
- </argument>
- <return type="Vector3">
- </return>
- <description>
- Computes and returns a dot product with transposed axis y.
- </description>
- </method>
- <method name="tdotz">
- <argument index="0" name="arg1" type="Vector3">
- </argument>
- <return type="Vector3">
- </return>
- <description>
- Computes and returns a dot product with transposed axis z.
- </description>
- </method>
- <method name="xform">
- <argument index="0" name="v" type="Vector3">
- </argument>
- <return type="Vector3">
- </return>
- <description>
- Transforms vector "v" by this matrix (as M x V) and returns the result.
- </description>
- </method>
- <method name="xform_inv">
- <argument index="0" name="v" type="Vector3">
- </argument>
- <return type="Vector3">
- </return>
- <description>
- Inverse-transforms vector "v" by this matrix (as V x M) and returns the result.
- </description>
- </method>
- <method name="get_axis">
- <argument index="0" name="axis" type="int">
- </argument>
- <return type="Vector3">
- </return>
- <description>
- Get an axis of the OCS. (0 is X, 1 is Y and 2 is Z). The enum constants Vector.AXIS_X, Vector.AXIS_Y, and Vector.AXIS_Z, are also valid. This is equivalent to get_column().
- </description>
- </method>
- <method name="set_axis">
- <argument index="0" name="axis" type="int">
- </argument>
- <argument index="1" name="v" type="Vector3">
- </argument>
- <description>
- Set an axis of the OCS. (0 is X, 1 is Y and 2 is Z). The enum constants Vector.AXIS_X, Vector.AXIS_Y, and Vector.AXIS_Z, are also valid. This is equivalent to set_column()
- </description>
- </method>
- <method name="get_row">
- <argument index="0" name="i" type="int">
- </argument>
- <return type="Vector3">
- </return>
- <description>
- Get a matrix row.
- </description>
- </method>
- <method name="set_row">
- <argument index="0" name="i" type="int">
- </argument>
- <argument index="1" name="v" type="Vector3">
- </argument>
- <description>
- Set a matrix row.
- </description>
- </method>
- <method name="get_column">
- <argument index="0" name="axis" type="int">
- </argument>
- <return type="Vector3">
- </return>
- <description>
- Get a matrix column. This is equivalent to get_axis()
- </description>
- </method>
- <method name="set_column">
- <argument index="0" name="axis" type="int">
- </argument>
- <argument index="1" name="av" type="Vector3">
- </argument>
- Set a matrix column. This is equivalent to set_axis
- <description>
- </description>
- </method>
- <method name="operator*">
- <argument index="0" name="N" type="Matrix3">
- </argument>
- <return type="Matrix3">
- </return>
- <description>
- Perform a matrix multiplication (M x N) and return the result.
- </description>
- </method>
- <method name="transpose_xform">
- <argument index="0" name="arg1" type="Matrix3">
- </argument>
- <return type="Matrix3">
- </return>
- <description>
- Perform a transposed-matrix multiplication (Mt x N) and return the result.
- </description>
- </method>
- </methods>
- <members>
- <member name="xx" type="real">
- </member>
- <member name="xy" type="real">
- </member>
- <member name="xz" type="real">
- </member>
- <member name="yx" type="real">
- </member>
- <member name="yy" type="real">
- </member>
- <member name="yz" type="real">
- </member>
- <member name="zx" type="real">
- </member>
- <member name="zy" type="real">
- </member>
- <member name="zz" type="real">
- </member>
- </members>
-</class>
-<class category="Core" name="Transform">
- <brief_description>
- Transformation.
- </brief_description>
- <description>
- Transform is used to store transformations, including translations. It consists of a Matrix3 "basis" and Vector3 "origin". Transform is used to represent transformations of any object in space. It is similar to a 4x3 matrix.
- </description>
- <methods>
- <method name="invert">
- <description>
- Invert the transform.
- </description>
- </method>
-
- <method name="inverse">
- <return type="Transform">
- </return>
- <description>
- Returns the inverse of the transform.
- </description>
- </method>
- <method name="rotate">
- <argument index="0" name="axis" type="Vector3">
- </argument>
- <argument index="1" name="phi" type="real">
- </argument>
- <description>
- Rotates the transform in normalized "axis" by amount "phi" in radians. (This is equivalent to glRotate from OpenGL).
- </description>
- </method>
- <method name="scale">
- <argument index="0" name="s" type="Vector3">
- </argument>
- <description>
- Scales the whole transform by "s" (including the origin)
- </description>
- </method>
- <method name="get_basis">
- <return type="Matrix3">
- </return>
- <description>
- Get the basis.
- </description>
- </method>
- <method name="translate">
- <argument index="0" name="v" type="Vector3">
- </argument>
- <description>
- Translate the transform by "v".
- </description>
- </method>
- <method name="set_look_at">
- <argument index="0" name="eye" type="Vector3">
- "Eye" Position.
- </argument>
- <argument index="1" name="target" type="Vector3">
- "Target" Position.
- </argument>
- <argument index="2" name="up" type="Vector3">
- "Up" Normal Vector.
- </argument>
- <description>
- Creates a transform positioned at "eye", looking towards "target". "up" represents the direction where "up" is. This function is useful for setting up cameras.
- </description>
- </method>
- <method name="xform">
- <argument index="0" name="v" type="Vector3">
- </argument>
- <return type="Vector3">
- </return>
- <description>
- Transforms vector "v" by this transform.
- </description>
- </method>
- <method name="xform_inv">
- <argument index="0" name="arg1" type="Vector3">
- </argument>
- <return type="Vector3">
- </return>
- <description>
- Inverse-transforms vector "v" by this transform.
- </description>
- </method>
- <method name="xform_aabb">
- <argument index="0" name="a" type="AABB">
- </argument>
- <return type="AABB">
- </return>
- <description>
- Transforms AABB "a" by this transform. The resulting aabb will often be larger, so succesive transforms are not recommended.
- </description>
- </method>
- <method name="xform_aabb_inv">
- <argument index="0" name="a" type="AABB">
- </argument>
- <return type="AABB">
- </return>
- <description>
- Inverse-transforms AABB "a" by this transform. The resulting aabb will often be larger, so succesive transforms are not recommended.
- </description>
- </method>
- <method name="xform_plane">
- <argument index="0" name="p" type="Plane">
- </argument>
- <return type="Plane">
- </return>
- <description>
- Transform plane "p" by this transform.
- </description>
- </method>
- <method name="xform_plane_inv">
- <argument index="0" name="p" type="Plane">
- </argument>
- <return type="Plane">
- </return>
- <description>
- Inverse-transforms plane "p" by this transform.
- </description>
- </method>
- </methods>
- <members>
- <member name="basis" type="Matrix3">
- Transform "basis" or OCS.
- </member>
- <member name="origin" type="Vector3">
- Transform origin.
- </member>
- <member name="xx" type="real">
- </member>
- <member name="xy" type="real">
- </member>
- <member name="xz" type="real">
- </member>
- <member name="yx" type="real">
- </member>
- <member name="yy" type="real">
- </member>
- <member name="yz" type="real">
- </member>
- <member name="zx" type="real">
- </member>
- <member name="zy" type="real">
- </member>
- <member name="zz" type="real">
- </member>
- <member name="tx" type="real">
- </member>
- <member name="ty" type="real">
- </member>
- <member name="tz" type="real">
- </member>
-
- </members>
-</class>
-<class category="Core" name="Vector2">
- <brief_description>
- Vector used for 2D Math.
- </brief_description>
- <description>
- Vector class, which performs basic 2D vector math operations.
- </description>
- <methods>
- <method name="operator+">
- <argument index="0" name="b" type="Vector2">
- </argument>
- <return type="Vector2">
- </return>
- <description>
- Add two vectors.
- </description>
- </method>
- <method name="operator-">
- <argument index="0" name="b" type="Vector2">
- </argument>
- <return type="Vector2">
- </return>
- <description>
- Substract two vectors.
- </description>
- </method>
- <method name="operator/">
- <argument index="0" name="b" type="Vector2">
- </argument>
- <return type="Vector2">
- </return>
- <description>
- Divide two vectors.
- </description>
- </method>
- <method name="operator*">
- <argument index="0" name="b" type="Vector2">
- </argument>
- <return type="Vector2">
- </return>
- <description>
- Multiply two vectors.
- </description>
- </method>
- <method name="length">
- <return type="real">
- </return>
- <description>
- Returns the length of the vector.
- </description>
- </method>
- <method name="length_squared">
- <return type="real">
- </return>
- <description>
- Returns the squared length of the vector.
- </description>
- </method>
- <method name="normalize">
- <description>
- Normalizes the vector to unit length.
- </description>
- </method>
- <method name="normalized">
- <return type="Vector2">
- </return>
- <description>
- Returns a normalized vector to unit length.
- </description>
- </method>
- <method name="zero">
- <description>
- Sets x and y to 0.
- </description>
- </method>
- <method name="linear_interpolate">
- <argument index="0" name="b" type="Vector2">
- </argument>
- <argument index="1" name="i" type="real">
- </argument>
- <return type="Vector2">
- </return>
- <description>
- Returns the result of the linear interpolation between this vector and "b", by amount "i".
- </description>
- </method>
- <method name="dot">
- <argument index="0" name="b" type="Vector2">
- </argument>
- <return type="real">
- </return>
- <description>
- Returns the dot product with vector "b".
- </description>
- </method>
- <method name="distance_to">
- <argument index="0" name="b" type="Vector2">
- </argument>
- <return type="real">
- </return>
- <description>
- Returns the distance to vector "b".
- </description>
- </method>
- <method name="floor">
- <return type="Vector2">
- </return>
- <description>
- Remove the fractional part of x and y.
- </description>
- </method>
- </methods>
-
- <members>
- <member name="x" type="real">
- </member>
- <member name="y" type="real">
- </member>
-
- </members>
-</class>
-<class category="Core" name="Rect2">
- <brief_description>
- Positioned rectangle in 2D.
- </brief_description>
- <description>
- Rect2 represets a positioned rectangle of position "pos" and "size".
- </description>
- <methods>
- <method name="has_no_area">
- <return type="bool">
- </return>
- <description>
- Returns "true" if the rectangle has no area.
- </description>
- </method>
- <method name="has_point">
- <argument index="0" name="v" type="Vector2">
- </argument>
- <return type="bool">
- </return>
- <description>
- Returns true if v is contained within the rectangle.
- </description>
- </method>
- <method name="merge">
- <argument index="0" name="b" type="Rect2">
- </argument>
- <description>
- Extend the rectangle to enclose "b".
- </description>
- </method>
- <method name="clip">
- <argument index="0" name="b" type="Rect2">
- </argument>
- <return type="Rect2">
- </return>
- <description>
- Return the interection with rectangle "b"
- </description>
- </method>
- <method name="grow">
- <argument index="0" name="m" type="Vector2">
- </argument>
- <description>
- Extend the rectangle margin by "m".
- </description>
- </method>
- </methods>
- <members>
- <member name="pos" type="Vector2">
- Position of the rectangle.
- </member>
- <member name="size" type="Vector2">
- Size of the rectangle.
- </member>
- <member name="x" type="real">
- </member>
- <member name="y" type="real">
- </member>
- <member name="size_x" type="real">
- </member>
- <member name="size_y" type="real">
- </member>
- </members>
-</class>
-
-<class category="Core" name="Color">
- <brief_description>
- Color in RGBA format.
- </brief_description>
- <description>
- A color is represented as red, green and blue (r,g,b) components. Additionally, "a" represents the alpha component, often used for transparency.
- </description>
- <methods>
- <method name="to_32">
- <return type="real">
- </return>
- <description>
- Convert the color to a 32 its integer (each byte represets a RGBA).
- </description>
- </method>
- <method name="gray">
- <return type="real">
- </return>
- <description>
- Convert the color to gray.
- </description>
- </method>
- <method name="get_h">
- <return type="real">
- </return>
- <description>
- Compute the "hue" of the color.
- </description>
- </method>
- <method name="get_s">
- <return type="real">
- </return>
- <description>
- Compute the "saturation" of the color.
- </description>
- </method>
- <method name="get_v">
- <return type="real">
- </return>
- <description>
- Compute the "value" of the color.
- </description>
- </method>
- <method name="set_hsv">
- <argument index="0" name="h" type="real">
- </argument>
- <argument index="1" name="s" type="real">
- </argument>
- <argument index="2" name="v" type="real">
- </argument>
- <description>
- Set the color from the HSV format.
- </description>
- </method>
- <method name="invert">
- <description>
- Invert the color.
- </description>
- </method>
- <method name="contrast">
- <description>
- Contrast the color.
- </description>
- </method>
- <method name="interpolate">
- <argument index="0" name="c" type="Vector3">
- </argument>
- <argument index="1" name="i" type="real">
- (0 to 1)
- </argument>
- <description>
- Linearly blend with color "c", by amount "i".
- </description>
- </method>
- </methods>
- <members>
- <member name="r" type="real">
- Red.
- </member>
- <member name="g" type="real">
- Green.
- </member>
- <member name="b" type="real">
- Blue.
- </member>
- <member name="a" type="real">
- Alpha.
- </member>
- </members>
-</class>
-<class category="Core" name="Image">
- <brief_description>
- Two Dimensional Image.
- </brief_description>
- <description>
- Image represents a two-dimensional representation of an image, composed by a color per pixel.
- </description>
- <methods>
- <method name="get_width">
- <return type="real">
- </return>
- <description>
- Returns the width of the image (in pixels).
- </description>
- </method>
- <method name="get_height">
- <return type="real">
- </return>
- <description>
- Returns the height of the image (in pixels).
- </description>
- </method>
- <method name="get_pixel">
- <argument index="0" name="x" type="int">
- </argument>
- <argument index="1" name="y" type="int">
- </argument>
- <return type="Color">
- </return>
- <description>
- Get the color of the pixel at position (x,y).
- </description>
- </method>
- <method name="put_pixel">
- <argument index="0" name="x" type="int">
- </argument>
- <argument index="1" name="y" type="int">
- </argument>
- <argument index="2" name="color" type="Color">
- </argument>
- <description>
- Sets the color of the pixel at position (x,y).
- </description>
- </method>
- <method name="convert">
- <argument index="0" name="format" type="int">
- </argument>
- <description>
- Convert the image to a new format (valid values in the FORMAT_* enumeration).
- </description>
- </method>
- <method name="get_format">
- <return type="int">
- </return>
- <description>
- Get the image format (valid values in the FORMAT_* enumeration).
- </description>
- </method>
- <method name="resize">
- <argument index="0" name="width" type="int">
- </argument>
- <argument index="1" name="height" type="int">
- </argument>
- <description>
- Resize the image to a new pixel resolution given by width,height.
- </description>
- </method>
- <method name="crop">
- <argument index="0" name="width" type="int">
- </argument>
- <argument index="1" name="height" type="int">
- </argument>
- <description>
- Crop the image to a new pixel resolution given by width,height.
- </description>
- </method>
- <method name="flip_x">
- <description>
- Flip the X axis of the image.
- </description>
- </method>
- <method name="flip_y">
- <description>
- Flip the Y axis of the image.
- </description>
- </method>
- <method name="make_mipmap">
- <argument index="0" name="source" type="Image">
- </argument>
- <description>
- Create a mipmap from "source" image.
- </description>
- </method>
- <method name="make_normalmap">
- <argument index="0" name="height_scale" type="real">
- </argument>
- <description>
- Create a normalmap from "height_scale" image.
- </description>
- </method>
- <method name="create">
- <argument index="0" name="width" type="int">
- </argument>
- <argument index="1" name="height" type="int">
- </argument>
- <argument index="2" name="format" type="int">
- </argument>
- <description>
- Create a new image of size width, height and format.
- </description>
- </method>
- <method name="import">
- <argument index="0" name="width" type="int">
- </argument>
- <argument index="1" name="height" type="int">
- </argument>
- <argument index="2" name="format" type="int">
- </argument>
- <argument index="3" name="data" type="RawArray">
- </argument>
- <description>
- Import an image from raw data, given a specific format.
- </description>
- </method>
- <method name="empty">
- <return type="bool">
- </return>
- <description>
- Returns true if the image is empty.
- </description>
- </method>
- <method name="load">
- <argument index="0" name="path" type="String">
- </argument>
- <return type="Error">
- </return>
- <description>
- Load an image from a file in "path".
- </description>
- </method>
- </methods>
- <constants>
- <constant name="FORMAT_GRAYSCALE" value="0">
- </constant>
- <constant name="FORMAT_INTENSITY" value="1">
- </constant>
- <constant name="FORMAT_GRAYSCALE_ALPHA" value="2">
- </constant>
- <constant name="FORMAT_RGB" value="3">
- </constant>
- <constant name="FORMAT_RGBA" value="4">
- </constant>
- <constant name="FORMAT_INDEXED" value="5">
- </constant>
- <constant name="FORMAT_INDEXED_ALPHA" value="6">
- </constant>
- </constants>
-</class>
-<class category="Core" name="RID">
- <brief_description>
- Resource ID.
- </brief_description>
- <description>
- RID references a resource, typically created in a server.
- </description>
- <methods>
- <method name="is_valid">
- <return type="bool">
- </return>
- <description>
- Returns true if the resource is valid.
- </description>
- </method>
- </methods>
-</class>
-<class category="Core" name="InputEvent">
- <brief_description>
- A struct containing information fron an input device.
- </brief_description>
- <description>
- A struct containing information fron an input event, such as mouse, keyboard, joystick, etc. Valid event types are:<br></br>
- <list>
- <li> InputEvent.NONE </li>
- <li> InputEvent.KEY </li>
- <li> InputEvent.MOUSE_BUTTON </li>
- <li> InputEvent.MOUSE_MOTION </li>
- <li> InputEvent.JOYSTICK_MOTION </li>
- <li> InputEvent.JOYSTICK_BUTTON </li>
- </list>
-
- </description>
- <members>
- <member name="ID" type="int">
- Event ID. Every event as a unique ID.
- </member>
- <member name="type" type="int">
- Event type (check description).
- </member>
- <member name="device" type="int">
- Device that originated the event.
- </member>
- <member name="mouse_x" type="int">
- Mouse x position (for mouse events).
- </member>
- <member name="mouse_y" type="int">
- Mouse y position (for mouse events).
- </member>
- <member name="mouse_button_mask" type="int">
- State of the mouse buttons as a bitmask (for key and mouse events)
- </member>
- <member name="mouse_global_x" type="int">
- Global mouse x position (used in GUI Controls).
- </member>
- <member name="mouse_global_y" type="int">
- Global mouse y position (used in GUI Controls).
- </member>
- <member name="mouse_pressed" type="bool">
- if MOUSE_BUTTON was a press, this value is true.
- </member>
- <member name="mouse_doubleclick" type="bool">
- if MOUSE_BUTTON was a doubleclick, this value is true.
- </member>
- <member name="mouse_button_index" type="int">
- Index of the clicked button (mouse button event).
- </member>
- <member name="mouse_motion_x" type="int">
- Relative x motion of the mouse (mouse motion event).
- </member>
- <member name="mouse_motion_y" type="int">
- Relative y motion of the mouse (mouse motion event).
- </member>
- <member name="mod_alt" type="bool">
- If ALT modifier is pressed, this is true (mouse and key events).
- </member>
- <member name="mod_shift" type="bool">
- If SHIFT modifier is pressed, this is true (mouse and key events).
- </member>
- <member name="mod_control" type="bool">
- If CONTROL modifier is pressed, this is true (mouse and key events).
- </member>
- <member name="mod_meta" type="bool">
- If META modifier (win/apple/etc keys) is pressed, this is true (mouse and key events).
- </member>
- <member name="key_pressed" type="bool">
- if a KEY event originated from a keypress, this is true.
- </member>
- <member name="key_echo" type="bool">
- if a KEY event originated from an echo key, this is true.
- </member>
- <member name="key_unicode" type="int">
- Unicode value of a key pressed (key event).
- </member>
- <member name="key_scancode" type="Key">
- Scancode of a key pressed (check the KEY_* enumeration) (key event).
- </member>
- <member name="joy_button_index" type="int">
- Joystick button index (joy button event).
- </member>
- <member name="joy_button_pressed" type="bool">
- If joystick button was pressed, this is true (joy button event).
- </member>
- <member name="joy_button_index" type="int">
- Index of the pressed/released joystick button.
- </member>
- <member name="joy_axis" type="int">
- Axis of a joystick (joy axis event).
- </member>
- <member name="joy_axis_value" type="real">
- Axis value a joystick, from -1 to 1 (joy axis event).
- </member>
- </members>
- <constants>
- <constant name="NONE" value="0">
- Empty input event.
- </constant>
- <constant name="KEY" value="1">
- Key pressed/released event.
- </constant>
- <constant name="MOUSE_BUTTON" value="2">
- Mouse button pressed/released event.
- </constant>
- <constant name="JOYSTICK_MOTION" value="3">
- Joystick axis motion event.
- </constant>
- <constant name="JOYSTICK_BUTTON" value="4">
- Joystick button press/release event.
- </constant>
- </constants>
-
-</class>
-<class category="Core" name="FileAccess">
- <brief_description>
- File Access Interface.
- </brief_description>
- <description>
- FileAccess provides access to files in the host platform (remote access to files in webserver in the web plugin, as web plugin does not access the local filesystem).
- </description>
- <methods>
- <method name="open">
- <argument index="0" name="path" type="String">
- Path to a file
- </argument>
- <argument index="1" name="mode" type="int">
- Open mode: FileAccess.READ, FileAccess.WRITE or FileAccess.READ_WRITE
- </argument>
- <return type="Error">
- Error value (check the ERR_ macro for the meaning of the values)
- </return>
- <description>
- Open a file in a given path. Error is returned if the file can't be opened, is nt found, etc.
- </description>
- </method>
- <method name="close">
- <description>
- Closes a currently open file.
- </description>
- </method>
- <method name="is_open">
- <return type="bool">
- </return>
- <description>
- Returns true if a file is currently open.
- </description>
- </method>
- <method name="seek">
- <argument index="0" name="pos" type="int">
- </argument>
- <description>
- Seek to a given position (in bytes) in the file.
- </description>
- </method>
- <method name="seek_end">
- <argument index="0" name="pos" type="int">
- </argument>
- <description>
- Seek to a given position (in bytes) in the file, from the end of the file.
- </description>
- </method>
- <method name="get_pos">
- <return type="int">
- </return>
- <description>
- Get the current position in the file.
- </description>
- </method>
- <method name="get_len">
- <return type="int">
- </return>
- <description>
- Get the open file size (in bytes).
- </description>
- </method>
- <method name="eof_reached">
- <return type="bool">
- </return>
- <description>
- Returns true if EOF was reached (read past end of file).
- </description>
- </method>
- <method name="get_8">
- <return type="int">
- </return>
- <description>
- Read a byte from the file.
- </description>
- </method>
- <method name="get_16">
- <return type="int">
- </return>
- <description>
- Read a 16-bits unsigned integer from the file, in little/big endian format.
- </description>
- </method>
- <method name="get_32">
- <return type="int">
- </return>
- <description>
- Read a 32-bits unsigned integer from the file, in little/big endian format.
- </description>
- </method>
- <method name="set_endian_swap">
- <argument index="0" name="swap" type="bool">
- </argument>
- <description>
- Change the endian mode for reading sizes larger than a byte (read big endian files).
- </description>
- </method>
- <method name="get_endian_swap">
- <return type="bool">
- </return>
- <description>
- Return the status of the endian swap.
- </description>
- </method>
- <method name="store_8">
- <argument index="0" name="byte" type="int">
- </argument>
- <description>
- Store a byte in the file.
- </description>
- </method>
- <method name="store_16">
- <argument index="0" name="word" type="int">
- </argument>
- <description>
- Store a 16-bits integer in the file.
- </description>
- </method>
- <method name="store_32">
- <argument index="0" name="dword" type="int">
- </argument>
- <description>
- Store a 32 bits integer in the file.
- </description>
- </method>
- <method name="file_exists">
- <argument index="0" name="path" type="String">
- </argument>
- <return type="bool">
- </return>
- <description>
- Returns true if a given file (in path) exist.
- </description>
- </method>
- </methods>
- <constants>
- <constant name="READ" value="1">
- </constant>
- <constant name="WRITE" value="2">
- </constant>
- <constant name="READ_WRITE" value="4">
- </constant>
-
- </constants>
-</class>
-<class category="Core" name="Dir">
- <brief_description>
- Directory Tree Access Interface.
- </brief_description>
- <description>
- Dir provides access to directories in the host platform (remote access to files in webserver in the web plugin, as web plugin does not access the local filesystem).
- </description>
- <methods>
- <method name="list_dir_begin">
- <return type="bool">
- true if an error ocurred.
- </return>
- <description>
- Begin a directory listing. This is done iteratively due to the positility of directories with a large amount of entries.
- </description>
- </method>
- <method name="get_next">
- <return type="String">
- </return>
- <description>
- Get the next item. If the return value is empty (""), then the end of the directory has been reached.
- </description>
- </method>
- <method name="current_is_dir">
- <return type="bool">
- </return>
- <description>
- Returns true if the current item is a directory (not a file).
- </description>
- </method>
- <method name="list_dir_end">
- <description>
- End the directory listing.
- </description>
- </method>
- <method name="get_drive_count">
- <return type="int">
- </return>
- <description>
- Get the amount of drives (windows only, returns 0 on other platforms).
- </description>
- </method>
- <method name="get_drive">
- <argument index="0" name="di" type="int">
- </argument>
- <return type="String">
- </return>
- <description>
- Get the string (or character) representing the drive (such as "C","D",etc).
- </description>
- </method>
- <method name="change_dir">
- <argument index="0" name="dir" type="String">
- </argument>
- <return type="bool">
- </return>
- <description>
- Change the current directory of the dir access. "dir" can be either absolute or relative.
- </description>
- </method>
- <method name="get_current_dir">
- <return type="String">
- </return>
- <description>
- Get the full path of the current dir.
- </description>
- </method>
- <method name="get_dir_separator">
- <return type="String">
- </return>
- <description>
- Get the string or character most commonly used as drive separator in the host OS.
- </description>
- </method>
- <method name="make_dir">
- <argument index="0" name="name" type="String">
- </argument>
- <return type="bool">
- true on error.
- </return>
- <description>
- Create a new directory. "name" can be either absolute or relative.
- </description>
- </method>
- <method name="file_exists">
- <argument index="0" name="path" type="String">
- </argument>
- <return type="bool">
- </return>
- <description>
- Returns true if a file exist. "path" can be either absolute or relative.
- </description>
- </method>
- <method name="get_space_left">
- <return type="int">
- </return>
- <description>
- Return the space left on the device, in kilobytes.
- </description>
- </method>
- </methods>
-</class>
-<class category="Core" name="VideoMode">
- <brief_description>
- Video Mode structure.
- </brief_description>
- <description>
- Describes a video mode.
- </description>
- <members>
- <member name="width" type="int">
- </member>
- <member name="height" type="int">
- </member>
- <member name="fullscreen" type="bool">
- "true" if the video mode is full scren.
- </member>
- <member name="resizable" type="bool">
- "true" if the video mode can be resized to another video mode.
- </member>
- </members>
-</class>
-<class category="Core" name="Date">
- <brief_description>
- Date structure.
- </brief_description>
- <description>
- Describes a date.
- </description>
- <members>
- <member name="year" type="int">
- year (integer)
- </member>
- <member name="day" type="int">
- day of the year
- </member>
- <member name="weekday" type="int">
- day of the week (0 to 6)
- </member>
- <member name="month" type="int">
- month of the year (0 to 11)
- </member>
- <member name="dst" type="bool">
- "true" if daylight savings is enabled.
- </member>
- </members>
-</class>
-<class category="Core" name="Time">
- <brief_description>
- Current Time.
- </brief_description>
- <description>
- Describes the current time.
- </description>
- <members>
- <member name="hour" type="int">
- (0 to 11)
- </member>
- <member name="min" type="int">
- (0 to 59)
- </member>
- <member name="sec" type="int">
- (0 to 59)
- </member>
- </members>
-</class>
-<class category="Core" name="OS">
- <brief_description>
- Operating System common functions.
- </brief_description>
- <description>
- OS provides access to common host OS functions. "OS" Must not be instanced. All members are static (called like OS.get_name() ).
- </description>
- <methods>
- <method name="alert">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- Produce an alert. On OSs such as windows or mac, this may result in a popup dialog.
- </description>
- </method>
- <method name="set_mouse_show">
- <argument index="0" name="show" type="bool">
- </argument>
- <description>
- Determine the hardware cursor visibility (if available).
- </description>
- </method>
- <method name="set_mouse_grab">
- <argument index="0" name="grab" type="bool">
- </argument>
- <description>
- Capture the hardware cursor (if available).
- </description>
- </method>
- <method name="is_mouse_grab_enabled">
- <return type="bool">
- </return>
- <description>
- Returns true if the application is capturing the hardware cursor.
- </description>
- </method>
- <method name="get_name">
- <return type="String">
- </return>
- <description>
- Get the name of the host OS or Platform.
- </description>
- </method>
- <method name="set_video_mode">
- <argument index="0" name="mode" type="VideoMode">
- </argument>
- <description>
- Change the current videomode (if available).
- </description>
- </method>
- <method name="get_video_mode">
- <return type="VideoMode">
- </return>
- <description>
- Get the current videomode.
- </description>
- </method>
- <method name="get_date">
- <return type="Date">
- </return>
- <description>
- Get the current date.
- </description>
- </method>
- <method name="get_time">
- <return type="Time">
- </return>
- <description>
- Get the current time.
- </description>
- </method>
- <method name="get_ticks_msec">
- <return type="int">
- </return>
- <description>
- Get the amount of milliseconds since the app started.
- </description>
- </method>
- <method name="delay_usec">
- <argument index="0" name="usec" type="int">
- </argument>
- <description>
- Suspend the calling thread for "usec" milliseconds
- </description>
- </method>
- </methods>
-</class>
-<class category="Core" name="Math">
- <brief_description>
- Common math functions.
- </brief_description>
- <description>
- Math provides implementations of commonly used math functions."Math" shouldt not be instanced since all members are static (called like Math.cos() ).
- </description>
- <methods>
- <method name="sin">
- <argument index="0" name="rad" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="cos">
- <argument index="0" name="rad" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="tan">
- <argument index="0" name="rad" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="asin">
- <argument index="0" name="s" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="acos">
- <argument index="0" name="s" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="atan2">
- <argument index="0" name="x" type="real">
- </argument>
- <argument index="1" name="y" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="deg2rad">
- <argument index="0" name="deg" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- Degrees to Radians conversion.
- </description>
- </method>
- <method name="sqrt">
- <argument index="0" name="s" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="pow">
- <argument index="0" name="base" type="real">
- </argument>
- <argument index="1" name="power" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="exp">
- <argument index="0" name="s" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="log">
- <argument index="0" name="s" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="fmod">
- <argument index="0" name="x" type="real">
- </argument>
- <argument index="1" name="y" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="stepify">
- <argument index="0" name="x" type="real">
- </argument>
- <argument index="1" name="step" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- Round to nearest (lowest) value in given step.
- </description>
- </method>
- <method name="floor">
- <argument index="0" name="s" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="round">
- <argument index="0" name="s" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="decimals">
- <argument index="0" name="s" type="real">
- </argument>
- <return type="int">
- </return>
- <description>
- Returns the amount of decimals used by "s".
- </description>
- </method>
- <method name="randf">
- <return type="real">
- </return>
- <description>
- Returns a random number fro 0 to 1
- </description>
- </method>
- <method name="random">
- <argument index="0" name="min" type="real">
- </argument>
- <argument index="1" name="max" type="real">
- </argument>
- <return type="real">
- </return>
- <description>
- Returns a random number between "min" and "max"
- </description>
- </method>
- </methods>
- <constants>
- <constant name="PI" value="3.14159265358979323846">
- </constant>
- </constants>
-
-</class>
-<class category="Core" name="Shell">
- <brief_description>
- Shell Execution interface.
- </brief_description>
- <description>
- Shell allows the application to open a given URL in the host OS. It can be anything the host OS understands, from a web page to a media file.
- </description>
- <methods>
- <method name="exec">
- <argument index="0" name="url" type="String">
- </argument>
- <description>
- Open any URL the host OS understands.
- </description>
- </method>
- </methods>
-</class>
-<class category="Core" name="ResourceLoader">
- <brief_description>
- Resource Loader.
- </brief_description>
- <description>
- ResourceLoader loads resources from disk and returns a resource object.
- </description>
- <methods>
- <method name="load">
- <argument index="0" name="path" type="String">
- </argument>
- <return type="Resource">
- null on failure.
- </return>
- <description>
- Open a resource in the given path.
- </description>
- </method>
- </methods>
-</class>
-<class category="Core" name="SceneLoader">
- <brief_description>
- Scene Loader
- </brief_description>
- <description>
- SceneLoader loads scenes from disk and returns a scene node.
- </description>
- <methods>
- <method name="load">
- <argument index="0" name="path" type="String">
- </argument>
- <return type="Node">
- A scene node, null on error.
- </return>
- <description>
- Load a scene from disk at given "path" and return a node object.
- </description>
- </method>
- </methods>
-</class>
-<class category="Core" name="Object">
- <brief_description>
- Base class for the Object Model.
- </brief_description>
- <description>
- Object is the building block of most of the high level engine interfaces. The "Object" interface contains a reference to an actual internal Object.
- Usually, Object memory should not be managed by the API, as resources will be fred automatically when not in use and nodes are deleted by their parent nodes.
- </description>
- <methods>
- <method name="free">
- <description>
- Free the Object reference. This should not be used with nodes inside a scene tree, as they are removed by their parent node. This function can also be used to unreference resources.
- </description>
- </method>
- <method name="get_type">
- <return type="String">
- </return>
- <description>
- Get a string with the type name of the object.
- </description>
- </method>
- <method name="has_instance">
- <return type="bool">
- </return>
- <description>
- Returns true if the Object datatype contains a reference to an actual object instance.
- </description>
- </method>
- <method name="get_instance_ID">
- <return type="bool">
- </return>
- <description>
- Return the instance ID of the object. Every Object has a unique instance ID.
- </description>
- </method>
- <method name="is_type" qualifiers="const" >
- <return type="bool" >
- </return>
- <argument index="0" name="type" type="String" >
- </argument>
- <description>
- Return true if the type of the object class (or any base clases) match "type.
- </description>
- </method>
- <method name="set" >
- <argument index="0" name="property" type="String" >
- </argument>
- <argument index="1" name="value" type="var" >
- </argument>
- <description>
- Set a property "property", with any value "value. This function can be inherited with "_set" (but base class "_set" will still be called).
- </description>
- </method>
- <method name="get" qualifiers="const" >
- <return type="var" >
- </return>
- <argument index="0" name="property" type="String" >
- </argument>
- <description>
- Return a property "property". This function can be inherited with "_get" (but base class "_get" will still be called).
- </description>
- </method>
- <method name="notification" >
- <argument index="0" name="what" type="int" >
- </argument>
- <argument index="1" name="reverse" type="bool" default="false" >
- </argument>
- <description>
- Perform a notification. Notifications are quick ways to tell an Object that something happened or changed regarding it's state and surroundings. This function can be inherited with "_notification" (but base class "_notification" will still be called).
- </description>
- </method>
- <method name="set_script" >
- <argument index="0" name="script" type="RefPtr" >
- </argument>
- <description>
- Set the script of the object. Any object can contain a script. Scripts behave as if they inherited the object they are set to
- </description>
- </method>
- <method name="get_script" qualifiers="const" >
- <return type="RefPtr" >
- </return>
- <description>
- Return the script of the object. Any object can contain a script. Scripts behave as if they inherited the object they are set to
- </description>
- </method>
- <method name="set_meta" >
- <argument index="0" name="name" type="String" >
- </argument>
- <description>
- Set a meta property. Meta properties are just containers for setting and retrieving any custom data to an object. Metaproperties are also saved with the object.
- </description>
- </method>
- <method name="get_meta" qualifiers="const" >
- <argument index="0" name="name" type="String" >
- </argument>
- <description>
- Return a meta property. Meta properties are just containers for setting and retrieving any custom data to an object. Metaproperties are also saved with the object.
- </description>
- </method>
- <method name="has_meta" qualifiers="const" >
- <return type="bool" >
- </return>
- <argument index="0" name="name" type="String" >
- </argument>
- <description>
- Return wether an object has a meta property. Meta properties are just containers for setting and retrieving any custom data to an object. Metaproperties are also saved with the object.
- </description>
- </method>
- <method name="get_meta_list" qualifiers="const" >
- <return type="StringArray" >
- </return>
- <description>
- Return the list of meta properties in the object. Meta properties are just containers for setting and retrieving any custom data to an object. Metaproperties are also saved with the object.
- </description>
- </method>
- <method name="call" >
- <argument index="0" name="method" type="String" >
- </argument>
- <description>
- Call any method in the object (syntax: call("method", .. arguments..).
- </description>
- </method>
- </methods>
- <constants>
- <constant name="NOTIFICATION_POSTINITIALIZE" value="0">
- This notification is called right after the object is done initializing
- </constant>
- <constant name="NOTIFICATION_PREDELETE" value="1">
- This notification is called right before the object will e deleted.
- </constant>
- </constants>
-</class>
-<class category="Core" name="Key">
- <brief_description>
- All Symbolic Key Names
- </brief_description>
- <description>
- Key is an enumaration containing the constants for all the symbolic key names. They are used directly (not with Key. prefix). This value is used in the "scancode" field of the "KEY" InputEvent.
- </description>
- <constants>
- <constant name="SPKEY">Special Key Mask</constant>
- <constant name="KEY_ESCAPE"></constant>
- <constant name="KEY_TAB"></constant>
- <constant name="KEY_BACKTAB"></constant>
- <constant name="KEY_BACKSPACE"></constant>
- <constant name="KEY_RETURN"></constant>
- <constant name="KEY_ENTER"></constant>
- <constant name="KEY_INSERT"></constant>
- <constant name="KEY_DELETE"></constant>
- <constant name="KEY_PAUSE"></constant>
- <constant name="KEY_PRINT"></constant>
- <constant name="KEY_SYSREQ"></constant>
- <constant name="KEY_CLEAR"></constant>
- <constant name="KEY_HOME"></constant>
- <constant name="KEY_END"></constant>
- <constant name="KEY_LEFT"></constant>
- <constant name="KEY_UP"></constant>
- <constant name="KEY_RIGHT"></constant>
- <constant name="KEY_DOWN"></constant>
- <constant name="KEY_PAGEUP"></constant>
- <constant name="KEY_PAGEDOWN"></constant>
- <constant name="KEY_SHIFT"></constant>
- <constant name="KEY_CONTROL"></constant>
- <constant name="KEY_META"></constant>
- <constant name="KEY_ALT"></constant>
- <constant name="KEY_CAPSLOCK"></constant>
- <constant name="KEY_NUMLOCK"></constant>
- <constant name="KEY_SCROLLLOCK"></constant>
- <constant name="KEY_F1"></constant>
- <constant name="KEY_F2"></constant>
- <constant name="KEY_F3"></constant>
- <constant name="KEY_F4"></constant>
- <constant name="KEY_F5"></constant>
- <constant name="KEY_F6"></constant>
- <constant name="KEY_F7"></constant>
- <constant name="KEY_F8"></constant>
- <constant name="KEY_F9"></constant>
- <constant name="KEY_F10"></constant>
- <constant name="KEY_F11"></constant>
- <constant name="KEY_F12"></constant>
- <constant name="KEY_F13"></constant>
- <constant name="KEY_F14"></constant>
- <constant name="KEY_F15"></constant>
- <constant name="KEY_F16"></constant>
- <constant name="KEY_KP_ENTER"></constant>
- <constant name="KEY_KP_MULTIPLY"></constant>
- <constant name="KEY_KP_DIVIDE"></constant>
- <constant name="KEY_KP_SUBSTRACT"></constant>
- <constant name="KEY_KP_PERIOD"></constant>
- <constant name="KEY_KP_ADD"></constant>
- <constant name="KEY_KP_0"></constant>
- <constant name="KEY_KP_1"></constant>
- <constant name="KEY_KP_2"></constant>
- <constant name="KEY_KP_3"></constant>
- <constant name="KEY_KP_4"></constant>
- <constant name="KEY_KP_5"></constant>
- <constant name="KEY_KP_6"></constant>
- <constant name="KEY_KP_7"></constant>
- <constant name="KEY_KP_8"></constant>
- <constant name="KEY_KP_9"></constant>
- <constant name="KEY_SUPER_L"></constant>
- <constant name="KEY_SUPER_R"></constant>
- <constant name="KEY_MENU"></constant>
- <constant name="KEY_HYPER_L"></constant>
- <constant name="KEY_HYPER_R"></constant>
- <constant name="KEY_HELP"></constant>
- <constant name="KEY_DIRECTION_L"></constant>
- <constant name="KEY_DIRECTION_R"></constant>
- <constant name="KEY_BACK"></constant>
- <constant name="KEY_FORWARD"></constant>
- <constant name="KEY_STOP"></constant>
- <constant name="KEY_REFRESH"></constant>
- <constant name="KEY_VOLUMEDOWN"></constant>
- <constant name="KEY_VOLUMEMUTE"></constant>
- <constant name="KEY_VOLUMEUP"></constant>
- <constant name="KEY_BASSBOOST"></constant>
- <constant name="KEY_BASSUP"></constant>
- <constant name="KEY_BASSDOWN"></constant>
- <constant name="KEY_TREBLEUP"></constant>
- <constant name="KEY_TREBLEDOWN"></constant>
- <constant name="KEY_MEDIAPLAY"></constant>
- <constant name="KEY_MEDIASTOP"></constant>
- <constant name="KEY_MEDIAPREVIOUS"></constant>
- <constant name="KEY_MEDIANEXT"></constant>
- <constant name="KEY_MEDIARECORD"></constant>
- <constant name="KEY_HOMEPAGE"></constant>
- <constant name="KEY_FAVORITES"></constant>
- <constant name="KEY_SEARCH"></constant>
- <constant name="KEY_STANDBY"></constant>
- <constant name="KEY_OPENURL"></constant>
- <constant name="KEY_LAUNCHMAIL"></constant>
- <constant name="KEY_LAUNCHMEDIA"></constant>
- <constant name="KEY_LAUNCH0"></constant>
- <constant name="KEY_LAUNCH1"></constant>
- <constant name="KEY_LAUNCH2"></constant>
- <constant name="KEY_LAUNCH3"></constant>
- <constant name="KEY_LAUNCH4"></constant>
- <constant name="KEY_LAUNCH5"></constant>
- <constant name="KEY_LAUNCH6"></constant>
- <constant name="KEY_LAUNCH7"></constant>
- <constant name="KEY_LAUNCH8"></constant>
- <constant name="KEY_LAUNCH9"></constant>
- <constant name="KEY_LAUNCHA"></constant>
- <constant name="KEY_LAUNCHB"></constant>
- <constant name="KEY_LAUNCHC"></constant>
- <constant name="KEY_LAUNCHD"></constant>
- <constant name="KEY_LAUNCHE"></constant>
- <constant name="KEY_LAUNCHF"></constant>
-
- <constant name="KEY_UNKNOWN"></constant>
- <constant name="KEY_SPACE"></constant>
- <constant name="KEY_EXCLAM"></constant>
- <constant name="KEY_QUOTEDBL"></constant>
- <constant name="KEY_NUMBERSIGN"></constant>
- <constant name="KEY_DOLLAR"></constant>
- <constant name="KEY_PERCENT"></constant>
- <constant name="KEY_AMPERSAND"></constant>
- <constant name="KEY_APOSTROPHE"></constant>
- <constant name="KEY_PARENLEFT"></constant>
- <constant name="KEY_PARENRIGHT"></constant>
- <constant name="KEY_ASTERISK"></constant>
- <constant name="KEY_PLUS"></constant>
- <constant name="KEY_COMMA"></constant>
- <constant name="KEY_MINUS"></constant>
- <constant name="KEY_PERIOD"></constant>
- <constant name="KEY_SLASH"></constant>
- <constant name="KEY_0"></constant>
- <constant name="KEY_1"></constant>
- <constant name="KEY_2"></constant>
- <constant name="KEY_3"></constant>
- <constant name="KEY_4"></constant>
- <constant name="KEY_5"></constant>
- <constant name="KEY_6"></constant>
- <constant name="KEY_7"></constant>
- <constant name="KEY_8"></constant>
- <constant name="KEY_9"></constant>
- <constant name="KEY_COLON"></constant>
- <constant name="KEY_SEMICOLON"></constant>
- <constant name="KEY_LESS"></constant>
- <constant name="KEY_EQUAL"></constant>
- <constant name="KEY_GREATER"></constant>
- <constant name="KEY_QUESTION"></constant>
- <constant name="KEY_AT"></constant>
- <constant name="KEY_A"></constant>
- <constant name="KEY_B"></constant>
- <constant name="KEY_C"></constant>
- <constant name="KEY_D"></constant>
- <constant name="KEY_E"></constant>
- <constant name="KEY_F"></constant>
- <constant name="KEY_G"></constant>
- <constant name="KEY_H"></constant>
- <constant name="KEY_I"></constant>
- <constant name="KEY_J"></constant>
- <constant name="KEY_K"></constant>
- <constant name="KEY_L"></constant>
- <constant name="KEY_M"></constant>
- <constant name="KEY_N"></constant>
- <constant name="KEY_O"></constant>
- <constant name="KEY_P"></constant>
- <constant name="KEY_Q"></constant>
- <constant name="KEY_R"></constant>
- <constant name="KEY_S"></constant>
- <constant name="KEY_T"></constant>
- <constant name="KEY_U"></constant>
- <constant name="KEY_V"></constant>
- <constant name="KEY_W"></constant>
- <constant name="KEY_X"></constant>
- <constant name="KEY_Y"></constant>
- <constant name="KEY_Z"></constant>
- <constant name="KEY_BRACKETLEFT"></constant>
- <constant name="KEY_BACKSLASH"></constant>
- <constant name="KEY_BRACKETRIGHT"></constant>
- <constant name="KEY_ASCIICIRCUM"></constant>
- <constant name="KEY_UNDERSCORE"></constant>
- <constant name="KEY_QUOTELEFT"></constant>
- <constant name="KEY_BRACELEFT"></constant>
- <constant name="KEY_BAR"></constant>
- <constant name="KEY_BRACERIGHT"></constant>
- <constant name="KEY_ASCIITILDE"></constant>
- <constant name="KEY_NOBREAKSPACE"></constant>
- <constant name="KEY_EXCLAMDOWN"></constant>
- <constant name="KEY_CENT"></constant>
- <constant name="KEY_STERLING"></constant>
- <constant name="KEY_CURRENCY"></constant>
- <constant name="KEY_YEN"></constant>
- <constant name="KEY_BROKENBAR"></constant>
- <constant name="KEY_SECTION"></constant>
- <constant name="KEY_DIAERESIS"></constant>
- <constant name="KEY_COPYRIGHT"></constant>
- <constant name="KEY_ORDFEMININE"></constant>
- <constant name="KEY_GUILLEMOTLEFT"></constant>
- <constant name="KEY_NOTSIGN"></constant>
- <constant name="KEY_HYPHEN"></constant>
- <constant name="KEY_REGISTERED"></constant>
- <constant name="KEY_MACRON"></constant>
- <constant name="KEY_DEGREE"></constant>
- <constant name="KEY_PLUSMINUS"></constant>
- <constant name="KEY_TWOSUPERIOR"></constant>
- <constant name="KEY_THREESUPERIOR"></constant>
- <constant name="KEY_ACUTE"></constant>
- <constant name="KEY_MU"></constant>
- <constant name="KEY_PARAGRAPH"></constant>
- <constant name="KEY_PERIODCENTERED"></constant>
- <constant name="KEY_CEDILLA"></constant>
- <constant name="KEY_ONESUPERIOR"></constant>
- <constant name="KEY_MASCULINE"></constant>
- <constant name="KEY_GUILLEMOTRIGHT"></constant>
- <constant name="KEY_ONEQUARTER"></constant>
- <constant name="KEY_ONEHALF"></constant>
- <constant name="KEY_THREEQUARTERS"></constant>
- <constant name="KEY_QUESTIONDOWN"></constant>
- <constant name="KEY_AGRAVE"></constant>
- <constant name="KEY_AACUTE"></constant>
- <constant name="KEY_ACIRCUMFLEX"></constant>
- <constant name="KEY_ATILDE"></constant>
- <constant name="KEY_ADIAERESIS"></constant>
- <constant name="KEY_ARING"></constant>
- <constant name="KEY_AE"></constant>
- <constant name="KEY_CCEDILLA"></constant>
- <constant name="KEY_EGRAVE"></constant>
- <constant name="KEY_EACUTE"></constant>
- <constant name="KEY_ECIRCUMFLEX"></constant>
- <constant name="KEY_EDIAERESIS"></constant>
- <constant name="KEY_IGRAVE"></constant>
- <constant name="KEY_IACUTE"></constant>
- <constant name="KEY_ICIRCUMFLEX"></constant>
- <constant name="KEY_IDIAERESIS"></constant>
- <constant name="KEY_ETH"></constant>
- <constant name="KEY_NTILDE"></constant>
- <constant name="KEY_OGRAVE"></constant>
- <constant name="KEY_OACUTE"></constant>
- <constant name="KEY_OCIRCUMFLEX"></constant>
- <constant name="KEY_OTILDE"></constant>
- <constant name="KEY_ODIAERESIS"></constant>
- <constant name="KEY_MULTIPLY"></constant>
- <constant name="KEY_OOBLIQUE"></constant>
- <constant name="KEY_UGRAVE"></constant>
- <constant name="KEY_UACUTE"></constant>
- <constant name="KEY_UCIRCUMFLEX"></constant>
- <constant name="KEY_UDIAERESIS"></constant>
- <constant name="KEY_YACUTE"></constant>
- <constant name="KEY_THORN"></constant>
- <constant name="KEY_SSHARP"></constant>
-
- <constant name="KEY_DIVISION"></constant>
- <constant name="KEY_YDIAERESIS"></constant>
-
- <constant name="KEY_CODE_MASK"></constant>
- <constant name="KEY_MODIFIER_MASK"></constant>
-
- <constant name="KEY_MASK_SHIFT"></constant>
- <constant name="KEY_MASK_ALT"></constant>
- <constant name="KEY_MASK_META"></constant>
- <constant name="KEY_MASK_CTRL"></constant>
- <constant name="KEY_MASK_KPAD"></constant>
- <constant name="KEY_MASK_GROUP_SWITCH"></constant>
-
- </constants>
-</class>
-<class category="Core" name="PropertyHint">
- <brief_description>
- Property Hints.
- </brief_description>
- <description>
- PropertyHint hints editors on how to edit a property. In many cases, hint_string (in the PropertyInfo) will contain extra data. These constants are used globally ("PropertyHint" class doesn't exist").
- </description>
- <constants>
- <constant name="PROPERTY_HINT_NONE"></constant>
- <constant name="PROPERTY_HINT_RANGE">Hint_string defined as "min,max,step
- "</constant>
- <constant name="PROPERTY_HINT_ENUM">Values such as 0,1,2 are represented in hint_string as "A,B,C"</constant>
- <constant name="PROPERTY_HINT_LENGTH">hint_string is the length of an array type.</constant>
- <constant name="PROPERTY_HINT_FLAGS">Flags names are in hint_string from MSB to LSB as "flag8,fla7,flag6,,,,flag1"</constant>
- <constant name="PROPERTY_HINT_PATH">Property is a path.</constant>
- <constant name="PROPERTY_HINT_FILE">Property is a path to a file.</constant>
- <constant name="PROPERTY_HINT_DIR">Property is a path to a dir.</constant>
- <constant name="PROPERTY_HINT_RESOURCE_TYPE">hint_string contains the valid resource types the property accept (separated by ",").</constant>
- </constants>
-</class>
-<class category="Core" name="PropertyUsage">
- <brief_description>
- Usage for an object property.
- </brief_description>
- <description>
- PropertyUsage defines a list of (inclusive) usages that can be ORed together to specify how the property will be treated in different scenarios. These constants are used globally ("PropertyUsage" class doesn't exist").
- </description>
- <constants>
- <constant name="PROPERTY_USAGE_STORAGE"> Property is Saved/Loaded from disk.</constant>
- <constant name="PROPERTY_USAGE_EDITOR">Property is visible in editor (for editing).</constant>
- <constant name="PROPERTY_USAGE_NETWORK">Property can be syncronized on network.</constant>
- <constant name="PROPERTY_USAGE_DEFAULT">Default usage.</constant>
- </constants>
-</class>
-<class category="Core" name="Type">
- <brief_description>
- Valid Data Types.
- </brief_description>
- <description>
- Type consists of a list of valid types. It is usually used for property type hinting. These constants are used globally ("Type" class doesn't exist").
- </description>
- <constants>
- <constant name="TYPE_NIL"></constant>
- <constant name="TYPE_BOOL"></constant>
- <constant name="TYPE_INT"></constant>
- <constant name="TYPE_REAL"></constant>
- <constant name="TYPE_STRING"></constant>
- <constant name="TYPE_VECTOR2"></constant>
- <constant name="TYPE_RECT2"></constant>
- <constant name="TYPE_VECTOR3"></constant>
- <constant name="TYPE_PLANE"></constant>
- <constant name="TYPE_QUAT"></constant>
- <constant name="TYPE_AABB"></constant>
- <constant name="TYPE_MATRIX3"></constant>
- <constant name="TYPE_TRANSFORM"></constant>
- <constant name="TYPE_COLOR"></constant>
- <constant name="TYPE_IMAGE"></constant>
- <constant name="TYPE_NODE_PATH"></constant>
- <constant name="TYPE_RESOURCE"></constant>
- <constant name="TYPE_RID"></constant>
- <constant name="TYPE_OBJECT"></constant>
- <constant name="TYPE_INPUT_EVENT"></constant>
- <constant name="TYPE_DICTIONARY"></constant>
- <constant name="TYPE_ARRAY"></constant>
- <constant name="TYPE_RAW_ARRAY"></constant>
- <constant name="TYPE_INT_ARRAY"></constant>
- <constant name="TYPE_REAL_ARRAY"></constant>
- <constant name="TYPE_STRING_ARRAY"></constant>
- <constant name="TYPE_VECTOR3_ARRAY"></constant>
- <constant name="TYPE_COLOR_ARRAY"></constant>
- </constants>
-</class>
-
-
-<class category="Core" name="Error">
- <brief_description>
- List of generic errors.
- </brief_description>
- <description>
- Error is a list of generic errors
- </description>
- <constants>
- <constant name="OK"></constant>
- <constant name="FAILED"> Generic fail error</constant>
- <constant name="ERR_UNAVAILABLE"> What is requested is unsupported/unavailable</constant>
- <constant name="ERR_UNCONFIGURED"> The object being used hasnt been properly set up yet</constant>
- <constant name="ERR_UNAUTHORIZED"> Missing credentials for requested resource</constant>
- <constant name="ERR_PARAMETER_RANGE_ERROR"> Parameter given out of range</constant>
- <constant name="ERR_OUT_OF_MEMORY"> Out of memory</constant>
- <constant name="ERR_FILE_NOT_FOUND"></constant>
- <constant name="ERR_FILE_BAD_DRIVE"></constant>
- <constant name="ERR_FILE_BAD_PATH"></constant>
- <constant name="ERR_FILE_NO_PERMISSION"></constant>
- <constant name="ERR_FILE_ALREADY_IN_USE"></constant>
- <constant name="ERR_FILE_CANT_OPEN"></constant>
- <constant name="ERR_FILE_CANT_WRITE"></constant>
- <constant name="ERR_FILE_CANT_READ"></constant>
- <constant name="ERR_FILE_UNRECOGNIZED"></constant>
- <constant name="ERR_FILE_CORRUPT"></constant>
- <constant name="ERR_FILE_EOF"></constant>
- <constant name="ERR_CANT_OPEN"> Can't open a resource/socket/file</constant>
- <constant name="ERR_CANT_CREATE"></constant>
- <constant name="ERROR_QUERY_FAILED"></constant>
- <constant name="ERR_ALREADY_IN_USE"></constant>
- <constant name="ERR_LOCKED"> resource is locked</constant>
- <constant name="ERR_TIMEOUT"></constant>
- <constant name="ERR_CANT_AQUIRE_RESOURCE"></constant>
- <constant name="ERR_INVALID_DATA"> Data passed is invalid</constant>
- <constant name="ERR_INVALID_PARAMETER"> Parameter passed is invalid</constant>
- <constant name="ERR_ALREADY_EXISTS"> When adding"> item already exists</constant>
- <constant name="ERR_DOES_NOT_EXIST"> When retrieving/erasing"> it item does not exist</constant>
- <constant name="ERR_DATABASE_CANT_READ"> database is full</constant>
- <constant name="ERR_DATABASE_CANT_WRITE"> database is full</constant>
- <constant name="ERR_COMPILATION_FAILED"></constant>
- <constant name="ERR_METHOD_NOT_FOUND"></constant>
- <constant name="ERR_LINK_FAILED"></constant>
- <constant name="ERR_SCRIPT_FAILED"></constant>
- <constant name="ERR_CYCLIC_LINK"></constant>
- <constant name="ERR_BUSY"></constant>
- <constant name="ERR_HELP"> user requested help!!</constant>
- <constant name="ERR_BUG"> a bug in the software certainly happeneddue to a double check failing or unexpected behavior.</constant>
- <constant name="ERR_WTF "> an impossible to trigger check due to paranoid programmer was triggered</constant>
- </constants>
-</class>
-</doc>
-
-
diff --git a/doc/deferred_format.txt b/doc/deferred_format.txt
deleted file mode 100644
index 76a158a3ce..0000000000
--- a/doc/deferred_format.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-deferred:
-
-ar ag ab gl - accumulation RGB + glow
-
-nx ny mx my? - normal, motion
-dr dg db sm - diffuse, shademodel
-sr sg sb sp - specular OR shadeparams
-
-ar ag ab gl
-nx ny sp sp
-dr dg db se
-444 6
-se can be 6 bits, 2 for shade model
-
-shade models:
-
-0 - none
-1 - wrap
-2 - toon
-3 - fresne
-
-
-
-sp: 2 bits what - 6 bits param
-
-16
-
-
-
-
-
-
-
diff --git a/doc/demos.txt b/doc/demos.txt
deleted file mode 100644
index cf56a5cbc6..0000000000
--- a/doc/demos.txt
+++ /dev/null
@@ -1,40 +0,0 @@
--Oceano
--Portales
--Grilla
--Personaje
--Auto (?)
--Fisica
--Fisica Idle
--Low level APIS (Server)
--Sonido Posicional
--Custom Shaders
--HDR
--Trees Waving
--luces
--fixed material
--shader material
--synctoaudio speech and speex
--particulas con gif animados para mostrar que es cada parametro
--soporte de syntax hilight de gdscript para editores mas comunes
--instanciar enemigos usando duplicate
--simulated motion con animacion
--animation player controla otro animation player (tipo camina de lugar a otro y saluda)
--corutinas y loops con yield para animation, audio, etc
--CCD (bullets)
-
--custom gizmos, editor plugins en script
-
-Clases que necesitan tutorial.
-
-Animation/AnimationPlayer
-Area2D (space override, notifications)
-custom container demo
-custon drawing in a canvas item
-ignore mouse on top of button
-input in a game, with _unhandled_input
-demo containers
-Control, anchors e input event handling
-lots of 2D physics examples
-dictionary and array doc of passing by reference?
-
-
diff --git a/doc/engine_classes.xml b/doc/engine_classes.xml
deleted file mode 100644
index 43602e26e9..0000000000
--- a/doc/engine_classes.xml
+++ /dev/null
@@ -1,17940 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<doc version="0.99.2555-pre-beta" name="Engine Types">
-<class name="AcceptDialog" inherits="WindowDialog" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_ok">
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_label">
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_hide_on_ok">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_hide_on_ok" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="add_button">
- <return type="Button">
- </return>
- <argument index="0" name="text" type="String" default="&quot;&quot;">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_cancel">
- <return type="Button">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="register_text_enter">
- <argument index="0" name="line_edit" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_text">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_text" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="confirmed">
- <description>
- </description>
- </signal>
- <signal name="custom_action">
- <argument index="0" name="action" type="String">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="Animation" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_track">
- <return type="int">
- </return>
- <argument index="0" name="type" type="int">
- </argument>
- <argument index="1" name="at_pos" type="int" default="-1">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_track">
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_track_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="track_get_type" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_get_path" qualifiers="const">
- <return type="NodePath">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_set_path">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="path" type="NodePath">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_move_up">
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_move_down">
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transform_track_insert_key">
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="time" type="real">
- </argument>
- <argument index="2" name="loc" type="Vector3">
- </argument>
- <argument index="3" name="rot" type="Quat">
- </argument>
- <argument index="4" name="scale" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_insert_key">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="time" type="real">
- </argument>
- <argument index="2" name="key" type="var">
- </argument>
- <argument index="3" name="transition" type="real" default="1">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_remove_key">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="key_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_remove_key_at_pos">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="pos" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_set_key_value">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="key" type="int">
- </argument>
- <argument index="2" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_set_key_transition">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="key_idx" type="int">
- </argument>
- <argument index="2" name="transition" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_get_key_transition" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="key_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_get_key_count" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_get_key_value" qualifiers="const">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="key_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_get_key_time" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="key_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_find_key" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="time" type="real">
- </argument>
- <argument index="2" name="exact" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_set_interpolation_type">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="interpolation" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_get_interpolation_type" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transform_track_interpolate" qualifiers="const">
- <return type="Array">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="time_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="value_track_set_continuous">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="continuous" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="value_track_is_continuous" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="value_track_get_key_indices" qualifiers="const">
- <return type="IntArray">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="time_sec" type="real">
- </argument>
- <argument index="2" name="delta" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="method_track_get_key_indices" qualifiers="const">
- <return type="IntArray">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="time_sec" type="real">
- </argument>
- <argument index="2" name="delta" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="method_track_get_name" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="key_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="method_track_get_params" qualifiers="const">
- <return type="Array">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="key_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_length">
- <argument index="0" name="time_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_length" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_loop">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_loop" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="clear">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="TYPE_TRANSFORM" value="0">
- </constant>
- <constant name="TYPE_VALUE" value="1">
- </constant>
- <constant name="TYPE_METHOD" value="2">
- </constant>
- <constant name="INTERPOLATION_NEAREST" value="0">
- </constant>
- <constant name="INTERPOLATION_LINEAR" value="1">
- </constant>
- <constant name="INTERPOLATION_CUBIC" value="2">
- </constant>
- </constants>
-</class>
-<class name="AnimationPlayer" inherits="Node" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_animation">
- <return type="int">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="animation" type="Animation">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_animation">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="rename_animation">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="newname" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_animation" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_animation" qualifiers="const">
- <return type="Animation">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_animation_list" qualifiers="const">
- <return type="StringArray">
- </return>
- <description>
- </description>
- </method>
- <method name="set_blend_time">
- <argument index="0" name="anim_from" type="String">
- </argument>
- <argument index="1" name="anim_to" type="String">
- </argument>
- <argument index="2" name="sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_blend_time" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="anim_from" type="String">
- </argument>
- <argument index="1" name="anim_to" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="play">
- <argument index="0" name="name" type="String" default="&quot;&quot;">
- </argument>
- <description>
- </description>
- </method>
- <method name="stop">
- <description>
- </description>
- </method>
- <method name="stop_all">
- <description>
- </description>
- </method>
- <method name="is_playing" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_current_animation">
- <argument index="0" name="anim" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_current_animation" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="queue">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_pause">
- <argument index="0" name="paused" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_paused" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_speed">
- <argument index="0" name="speed" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_speed" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_autoplay">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_autoplay" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="seek">
- <argument index="0" name="pos_sec" type="real">
- </argument>
- <argument index="1" name="update" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_pos" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="find_animation" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="animation" type="Animation">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_caches">
- <description>
- </description>
- </method>
- <method name="set_animation_process_mode">
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_animation_process_mode" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="finished">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="ANIMATION_PROCESS_FIXED" value="0">
- </constant>
- <constant name="ANIMATION_PROCESS_IDLE" value="1">
- </constant>
- </constants>
-</class>
-<class name="AnimationTreePlayer" inherits="Node" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_node">
- <argument index="0" name="type" type="int">
- </argument>
- <argument index="1" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_node_id" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="node_set_name">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="node_get_name" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="node_get_type" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="node_get_input_count" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="animation_node_set_animation">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="animation" type="Animation">
- </argument>
- <description>
- </description>
- </method>
- <method name="animation_node_get_animation" qualifiers="const">
- <return type="Animation">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_set_fadein_time">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="time_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_get_fadein_time" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_set_fadeout_time">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="time_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_get_fadeout_time" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_set_autorestart">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_set_autorestart_delay">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="delay_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_set_autorestart_random_delay">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="rand_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_has_autorestart" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_get_autorestart_delay" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_get_autorestart_random_delay" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_start">
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_stop">
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_is_active" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mix_node_set_amount">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="ratio" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="mix_node_get_amount" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="blend2_node_set_amount">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="blend" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="blend2_node_get_amount" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="blend3_node_set_amount">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="blend" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="blend3_node_get_amount" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="blend4_node_set_amount">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="blend" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="blend4_node_get_amount" qualifiers="const">
- <return type="Vector2">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="timescale_node_set_scale">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="scale" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="timescale_node_get_scale" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="timeseek_node_seek">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="pos_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_set_input_count">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="count" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_get_input_count" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_delete_input">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="input_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_set_input_auto_advance">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="input_idx" type="int">
- </argument>
- <argument index="2" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_has_input_auto_advance" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="input_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_set_xfade_time">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="time_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_get_xfade_time" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_set_current">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="input_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_get_current" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="node_set_pos">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="screen_pos" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="node_get_pos" qualifiers="const">
- <return type="Vector2">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_node">
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="connect">
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="dst_id" type="int">
- </argument>
- <argument index="2" name="dst_input_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_connected" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="dst_id" type="int">
- </argument>
- <argument index="2" name="dst_input_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="disconnect">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="dst_input_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_active">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_active" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_base_path">
- <argument index="0" name="path" type="NodePath">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_base_path" qualifiers="const">
- <return type="NodePath">
- </return>
- <description>
- </description>
- </method>
- <method name="get_node_list">
- <return type="IntArray">
- </return>
- <description>
- </description>
- </method>
- <method name="reset">
- <description>
- </description>
- </method>
- <method name="recompute_caches">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="NODE_OUTPUT" value="0">
- </constant>
- <constant name="NODE_ANIMATION" value="1">
- </constant>
- <constant name="NODE_ONESHOT" value="2">
- </constant>
- <constant name="NODE_MIX" value="3">
- </constant>
- <constant name="NODE_BLEND2" value="4">
- </constant>
- <constant name="NODE_BLEND3" value="5">
- </constant>
- <constant name="NODE_BLEND4" value="6">
- </constant>
- <constant name="NODE_TIMESCALE" value="7">
- </constant>
- <constant name="NODE_TIMESEEK" value="8">
- </constant>
- <constant name="NODE_TRANSITION" value="9">
- </constant>
- </constants>
-</class>
-<class name="Area2D" inherits="CollisionObject2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_override_space_params">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_overriding_space_params" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_gravity_is_point">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_gravity_a_point" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_gravity_vector">
- <argument index="0" name="vector" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_gravity_vector" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_gravity">
- <argument index="0" name="gravity" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_gravity" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_density">
- <argument index="0" name="density" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_density" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_priority">
- <argument index="0" name="priority" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_priority" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_enable_monitoring">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_monitoring_enabled" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="body_enter">
- <argument index="0" name="body_id" type="int">
- </argument>
- <argument index="1" name="body" type="Object">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="body_enter_shape">
- <argument index="0" name="body_id" type="int">
- </argument>
- <argument index="1" name="body" type="Object">
- </argument>
- <argument index="2" name="body_shape" type="int">
- </argument>
- <argument index="3" name="area_shape" type="int">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="body_exit">
- <argument index="0" name="body_id" type="int">
- </argument>
- <argument index="1" name="body" type="Object">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="body_exit_shape">
- <argument index="0" name="body_id" type="int">
- </argument>
- <argument index="1" name="body" type="Object">
- </argument>
- <argument index="2" name="body_shape" type="int">
- </argument>
- <argument index="3" name="area_shape" type="int">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="AudioServer" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="sample_create">
- <return type="RID">
- </return>
- <argument index="0" name="format" type="int">
- </argument>
- <argument index="1" name="stereo" type="bool">
- </argument>
- <argument index="2" name="length" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_set_description">
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="description" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_description" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_format" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_is_stereo" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_length" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_set_signed_data">
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="data" type="RealArray">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_set_data">
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RawArray">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_data" qualifiers="const">
- <return type="RawArray">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_set_mix_rate">
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="mix_rate" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_mix_rate" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_set_loop_format">
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="loop_format" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_loop_format" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_set_loop_begin">
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="pos" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_loop_begin" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_set_loop_end">
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="pos" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_loop_end" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="voice_play">
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_volume">
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="volume" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_pan">
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="pan" type="real">
- </argument>
- <argument index="2" name="depth" type="real" default="0">
- </argument>
- <argument index="3" name="height" type="real" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_filter">
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="type" type="int">
- </argument>
- <argument index="2" name="cutoff" type="real">
- </argument>
- <argument index="3" name="resonance" type="real">
- </argument>
- <argument index="4" name="gain" type="real" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_chorus">
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="chorus" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_reverb">
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="room" type="int">
- </argument>
- <argument index="2" name="reverb" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_mix_rate">
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="rate" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_positional">
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_volume" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_pan" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_pan_height" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_pan_depth" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_filter_type" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_filter_cutoff" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_filter_resonance" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_chorus" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_reverb_type" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_reverb" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_mix_rate" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_is_positional" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_stop">
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="free_rid">
- <argument index="0" name="rid" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_stream_global_volume_scale">
- <argument index="0" name="scale" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_stream_global_volume_scale" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_mixer_global_volume_scale">
- <argument index="0" name="scale" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_mixer_global_volume_scale" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="SAMPLE_FORMAT_PCM8" value="0">
- </constant>
- <constant name="SAMPLE_FORMAT_PCM16" value="1">
- </constant>
- <constant name="SAMPLE_FORMAT_IMA_ADPCM" value="2">
- </constant>
- <constant name="SAMPLE_LOOP_NONE" value="0">
- </constant>
- <constant name="SAMPLE_LOOP_FORWARD" value="1">
- </constant>
- <constant name="SAMPLE_LOOP_PING_PONG" value="2">
- </constant>
- <constant name="FILTER_NONE" value="0">
- </constant>
- <constant name="FILTER_LOWPASS" value="1">
- </constant>
- <constant name="FILTER_BANDPASS" value="2">
- </constant>
- <constant name="FILTER_HIPASS" value="3">
- </constant>
- <constant name="FILTER_NOTCH" value="4">
- </constant>
- <constant name="FILTER_BANDLIMIT" value="6">
- </constant>
- <constant name="REVERB_SMALL" value="0">
- </constant>
- <constant name="REVERB_MEDIUM" value="1">
- </constant>
- <constant name="REVERB_LARGE" value="2">
- </constant>
- <constant name="REVERB_HALL" value="3">
- </constant>
- </constants>
-</class>
-<class name="AudioServerSW" inherits="AudioServer" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="AudioStream" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="play">
- <description>
- </description>
- </method>
- <method name="stop">
- <description>
- </description>
- </method>
- <method name="is_playing" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_loop">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_loop" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_stream_name" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_loop_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="seek_pos">
- <argument index="0" name="pos" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_pos" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_length" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_update_mode" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="update">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="UPDATE_NONE" value="0">
- </constant>
- <constant name="UPDATE_IDLE" value="1">
- </constant>
- <constant name="UPDATE_THREAD" value="2">
- </constant>
- </constants>
-</class>
-<class name="AudioStreamGibberish" inherits="AudioStream" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_phonemes">
- <argument index="0" name="phonemes" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_phonemes" qualifiers="const">
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_pitch_scale">
- <argument index="0" name="pitch_scale" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_pitch_scale" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_pitch_random_scale">
- <argument index="0" name="pitch_random_scale" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_pitch_random_scale" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_xfade_time">
- <argument index="0" name="sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_xfade_time" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="AudioStreamMPC" inherits="AudioStreamResampled" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_file">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_file" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="AudioStreamOGGVorbis" inherits="AudioStreamResampled" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="AudioStreamResampled" inherits="AudioStream" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="AudioStreamSpeex" inherits="AudioStreamResampled" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_file">
- <argument index="0" name="file" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_file" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="BCSFX" inherits="ScenarioFX" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="BGColorFX" inherits="ScenarioFX" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="BGImageFX" inherits="ScenarioFX" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="BaseButton" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_pressed">
- <argument index="0" name="pressed" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_pressed" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_toggle_mode">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_toggle_mode" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_disabled">
- <argument index="0" name="disabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_disabled" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_click_on_press">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_click_on_press" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="toggled">
- <argument index="0" name="pressed" type="bool">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="pressed">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="BodyShape" inherits="Spatial" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="BoxContainer" inherits="Container" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="BoxShape" inherits="Shape" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_extents">
- <argument index="0" name="extents" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_extents" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Button" inherits="BaseButton" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_text">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_text" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_icon">
- <argument index="0" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_icon" qualifiers="const">
- <return type="Texture">
- </return>
- <description>
- </description>
- </method>
- <method name="set_flat">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_clip_text">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_clip_text" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="is_flat" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ButtonArray" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_button">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_icon_button">
- <argument index="0" name="icon" type="Object">
- </argument>
- <argument index="1" name="text" type="String" default="&quot;&quot;">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_button_text">
- <argument index="0" name="button" type="int">
- </argument>
- <argument index="1" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_button_icon">
- <argument index="0" name="button" type="int">
- </argument>
- <argument index="1" name="icon" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_button_text" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="button" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_button_icon" qualifiers="const">
- <return type="Object">
- </return>
- <argument index="0" name="button" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_button_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selected" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_hovered" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_selected">
- <argument index="0" name="button" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="erase_button">
- <argument index="0" name="button" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear">
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="button_selected">
- <argument index="0" name="button" type="int">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="ALIGN_BEGIN" value="0">
- </constant>
- <constant name="ALIGN_CENTER" value="1">
- </constant>
- <constant name="ALIGN_END" value="2">
- </constant>
- <constant name="ALIGN_FILL" value="3">
- </constant>
- <constant name="ALIGN_EXPAND_FILL" value="4">
- </constant>
- </constants>
-</class>
-<class name="ButtonGroup" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_pressed_button" qualifiers="const">
- <return type="BaseButton">
- </return>
- <description>
- </description>
- </method>
- <method name="get_pressed_button_index" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_focused_button" qualifiers="const">
- <return type="BaseButton">
- </return>
- <description>
- </description>
- </method>
- <method name="get_button_list" qualifiers="const">
- <return type="Array">
- </return>
- <description>
- </description>
- </method>
- <method name="set_pressed_button">
- <argument index="0" name="button" type="BaseButton">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Camera" inherits="Spatial" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="project_ray_normal" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="screen_point" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="project_local_ray_normal" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="screen_point" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="project_ray_origin" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="screen_point" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="unproject_position" qualifiers="const">
- <return type="Vector2">
- </return>
- <argument index="0" name="world_point" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="project_position" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="screen_point" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_perspective">
- <argument index="0" name="fov" type="real">
- </argument>
- <argument index="1" name="z_near" type="real">
- </argument>
- <argument index="2" name="z_far" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_orthogonal">
- <argument index="0" name="size" type="real">
- </argument>
- <argument index="1" name="z_near" type="real">
- </argument>
- <argument index="2" name="z_far" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="make_current">
- <description>
- </description>
- </method>
- <method name="clear_current">
- <description>
- </description>
- </method>
- <method name="is_current" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_camera_transform" qualifiers="const">
- <return type="Transform">
- </return>
- <description>
- </description>
- </method>
- <method name="get_fov" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_size" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_zfar" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_znear" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_projection" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="PROJECTION_PERSPECTIVE" value="0">
- </constant>
- <constant name="PROJECTION_ORTHOGONAL" value="1">
- </constant>
- </constants>
-</class>
-<class name="Camera2D" inherits="ScreenProximity2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_offset">
- <argument index="0" name="offset" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_offset" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_centered">
- <argument index="0" name="centered" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_centered" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="make_current">
- <description>
- </description>
- </method>
- <method name="is_current" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_limit">
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="limit" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_limit" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="margin" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_drag_margin">
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="drag_margin" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_drag_margin" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="margin" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_camera_pos" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="force_update_scroll">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="CanvasItem" inherits="Node" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="edit_set_state">
- <argument index="0" name="state" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="edit_get" qualifiers="const">
- <description>
- </description>
- </method>
- <method name="edit_set_rect">
- <argument index="0" name="rect" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- <method name="edit_rotate">
- <argument index="0" name="degrees" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_rect" qualifiers="const">
- <return type="Rect2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_canvas_item" qualifiers="const">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="is_visible" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="is_hidden" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="show">
- <description>
- </description>
- </method>
- <method name="hide">
- <description>
- </description>
- </method>
- <method name="update">
- <description>
- </description>
- </method>
- <method name="set_as_toplevel">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_set_as_toplevel" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_blend_mode">
- <argument index="0" name="blend_mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_blend_mode" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_opacity">
- <argument index="0" name="opacity" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_opacity" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_self_opacity">
- <argument index="0" name="self_opacity" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_self_opacity" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="draw_line">
- <argument index="0" name="from" type="Vector2">
- </argument>
- <argument index="1" name="to" type="Vector2">
- </argument>
- <argument index="2" name="color" type="Color">
- </argument>
- <argument index="3" name="width" type="real" default="1">
- </argument>
- <description>
- </description>
- </method>
- <method name="draw_rect">
- <argument index="0" name="rect" type="Rect2">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="draw_circle">
- <argument index="0" name="pos" type="Vector2">
- </argument>
- <argument index="1" name="radius" type="real">
- </argument>
- <argument index="2" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="draw_texture">
- <argument index="0" name="texture" type="Texture">
- </argument>
- <argument index="1" name="pos" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="draw_texture_rect">
- <argument index="0" name="texture" type="Texture">
- </argument>
- <argument index="1" name="rect" type="Rect2">
- </argument>
- <argument index="2" name="tile" type="bool" default="false">
- </argument>
- <argument index="3" name="modulate" type="Color" default="Color(1,1,1,1)">
- </argument>
- <argument index="4" name="transpose" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="draw_texture_rect_region">
- <argument index="0" name="texture" type="Texture">
- </argument>
- <argument index="1" name="rect" type="Rect2">
- </argument>
- <argument index="2" name="src_rect" type="Rect2">
- </argument>
- <argument index="3" name="modulate" type="Color" default="Color(1,1,1,1)">
- </argument>
- <argument index="4" name="transpose" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="draw_style_box">
- <argument index="0" name="style_box" type="StyleBox">
- </argument>
- <argument index="1" name="rect" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- <method name="draw_primitive">
- <argument index="0" name="points" type="Vector2Array">
- </argument>
- <argument index="1" name="colors" type="ColorArray">
- </argument>
- <argument index="2" name="uvs" type="Vector2Array" default="Array()">
- </argument>
- <argument index="3" name="texture" type="Texture" default="Object()">
- </argument>
- <argument index="4" name="width" type="real" default="1">
- </argument>
- <description>
- </description>
- </method>
- <method name="draw_polygon">
- <argument index="0" name="points" type="Vector2Array">
- </argument>
- <argument index="1" name="colors" type="ColorArray">
- </argument>
- <argument index="2" name="uvs" type="Vector2Array">
- </argument>
- <argument index="3" name="texture" type="Texture" default="Array()">
- </argument>
- <argument index="4" name="arg4" type="real" default="Object()">
- </argument>
- <description>
- </description>
- </method>
- <method name="draw_colored_polygon">
- <argument index="0" name="points" type="Vector2Array">
- </argument>
- <argument index="1" name="color" type="ColorArray">
- </argument>
- <argument index="2" name="uvs" type="Vector2Array">
- </argument>
- <argument index="3" name="texture" type="Texture" default="Array()">
- </argument>
- <argument index="4" name="arg4" type="real" default="Object()">
- </argument>
- <description>
- </description>
- </method>
- <method name="draw_string">
- <argument index="0" name="font" type="Font">
- </argument>
- <argument index="1" name="pos" type="Vector2">
- </argument>
- <argument index="2" name="text" type="String">
- </argument>
- <argument index="3" name="modulate" type="Color" default="Color(1,1,1,1)">
- </argument>
- <argument index="4" name="clip_w" type="int" default="-1">
- </argument>
- <description>
- </description>
- </method>
- <method name="draw_char">
- <return type="real">
- </return>
- <argument index="0" name="font" type="Font">
- </argument>
- <argument index="1" name="pos" type="Vector2">
- </argument>
- <argument index="2" name="char" type="String">
- </argument>
- <argument index="3" name="next" type="String">
- </argument>
- <argument index="4" name="modulate" type="Color" default="Color(1,1,1,1)">
- </argument>
- <description>
- </description>
- </method>
- <method name="draw_set_transform">
- <argument index="0" name="pos" type="Vector2">
- </argument>
- <argument index="1" name="rot" type="real">
- </argument>
- <argument index="2" name="scale" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_transform_notify">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_transform_notify_enabled" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="item_rect_changed">
- <description>
- </description>
- </signal>
- <signal name="draw">
- <description>
- </description>
- </signal>
- <signal name="visibility_changed">
- <description>
- </description>
- </signal>
- <signal name="hide">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="BLEND_MODE_MIX" value="0">
- </constant>
- <constant name="BLEND_MODE_ADD" value="1">
- </constant>
- <constant name="BLEND_MODE_SUB" value="2">
- </constant>
- <constant name="BLEND_MODE_MUL" value="3">
- </constant>
- <constant name="NOTIFICATION_DRAW" value="30">
- </constant>
- <constant name="NOTIFICATION_VISIBILITY_CHANGED" value="31">
- </constant>
- <constant name="NOTIFICATION_ENTER_CANVAS" value="32">
- </constant>
- <constant name="NOTIFICATION_EXIT_CANVAS" value="33">
- </constant>
- <constant name="NOTIFICATION_TRANSFORM_CHANGED" value="34">
- </constant>
- </constants>
-</class>
-<class name="CanvasLayer" inherits="Node" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_layer">
- <argument index="0" name="layer" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_layer" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_transform">
- <argument index="0" name="transform" type="Matrix32">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_transform" qualifiers="const">
- <return type="Matrix32">
- </return>
- <description>
- </description>
- </method>
- <method name="set_offset">
- <argument index="0" name="offset" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_offset" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_rotation">
- <argument index="0" name="rotation" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_rotation" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_scale">
- <argument index="0" name="scale" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_scale" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_canvas" qualifiers="const">
- <return type="Canvas">
- </return>
- <description>
- </description>
- </method>
- <method name="get_viewport" qualifiers="const">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="CapsuleShape" inherits="Shape" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_radius">
- <argument index="0" name="radius" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_radius" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_height">
- <argument index="0" name="height" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_height" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="CapsuleShape2D" inherits="Shape2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_radius">
- <argument index="0" name="radius" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_radius" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_height">
- <argument index="0" name="height" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_height" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="CenterContainer" inherits="Container" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="CheckButton" inherits="BaseButton" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_text">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_text" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="CircleShape2D" inherits="Shape2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_radius">
- <argument index="0" name="radius" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_radius" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="CollisionObject2D" inherits="Node2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_shape">
- <argument index="0" name="shape" type="Shape2D">
- </argument>
- <argument index="1" name="transform" type="Matrix32" default="1,0, 0,1, 0,0">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shape_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_shape">
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <argument index="1" name="shape" type="Shape">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_shape_transform">
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <argument index="1" name="transform" type="Matrix32">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shape" qualifiers="const">
- <return type="Shape2D">
- </return>
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shape_transform" qualifiers="const">
- <return type="Matrix32">
- </return>
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_shape">
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_shapes">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="CollisionPolygon2D" inherits="Node2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="CollisionShape2D" inherits="Node2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ColorPicker" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_color">
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color" qualifiers="const">
- <return type="Color">
- </return>
- <description>
- </description>
- </method>
- <method name="set_show_alpha">
- <argument index="0" name="show" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_showing_alpha" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="color_changed">
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="ConcavePolygonShape" inherits="Shape" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_faces">
- <argument index="0" name="faces" type="Vector3Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_faces" qualifiers="const">
- <return type="Vector3Array">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ConcavePolygonShape2D" inherits="Shape2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_segments">
- <argument index="0" name="segments" type="Vector2Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_segments" qualifiers="const">
- <return type="Vector2Array">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ConfirmationDialog" inherits="AcceptDialog" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_cancel">
- <return type="Button">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Container" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="queue_sort">
- <description>
- </description>
- </method>
- <method name="fit_child_in_rect">
- <argument index="0" name="child" type="Control">
- </argument>
- <argument index="1" name="rect" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="sort_children">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="NOTIFICATION_SORT_CHILDREN" value="50">
- </constant>
- </constants>
-</class>
-<class name="Control" inherits="CanvasItem" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="accept_event">
- <description>
- </description>
- </method>
- <method name="get_minimum_size" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="is_window" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_window" qualifiers="const">
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_anchor">
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="anchor_mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_anchor" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="margin" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_margin">
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="offset" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_anchor_and_margin">
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="anchor_mode" type="int">
- </argument>
- <argument index="2" name="offset" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_begin">
- <argument index="0" name="pos" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_end">
- <argument index="0" name="pos" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_pos">
- <argument index="0" name="pos" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_size">
- <argument index="0" name="size" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_global_pos">
- <argument index="0" name="pos" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_margin" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="margin" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_begin" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_end" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_pos" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_size" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_parent_area_size" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_global_pos" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_rect" qualifiers="const">
- <return type="Rect2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_global_rect" qualifiers="const">
- <return type="Rect2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_area_as_parent_rect">
- <argument index="0" name="margin" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="show_modal">
- <argument index="0" name="exclusive" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_focus_mode">
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_focus" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="grab_focus">
- <description>
- </description>
- </method>
- <method name="release_focus">
- <description>
- </description>
- </method>
- <method name="get_focus_owner" qualifiers="const">
- <return type="Control">
- </return>
- <description>
- </description>
- </method>
- <method name="set_h_size_flags">
- <argument index="0" name="flags" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_h_size_flags" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_stretch_ratio">
- <argument index="0" name="ratio" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_stretch_ratio" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_v_size_flags">
- <argument index="0" name="flags" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_v_size_flags" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_theme">
- <argument index="0" name="theme" type="Theme">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_theme" qualifiers="const">
- <return type="Theme">
- </return>
- <description>
- </description>
- </method>
- <method name="add_icon_override">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_style_override">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="stylebox" type="StyleBox">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_font_override">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="font" type="Font">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_color_override">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_constant_override">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="constant" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_icon" qualifiers="const">
- <return type="Texture">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String" default="&quot;&quot;">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_stylebox" qualifiers="const">
- <return type="StyleBox">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String" default="&quot;&quot;">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_font" qualifiers="const">
- <return type="Font">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String" default="&quot;&quot;">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color" qualifiers="const">
- <return type="Color">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String" default="&quot;&quot;">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_constant" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String" default="&quot;&quot;">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_parent_control" qualifiers="const">
- <return type="Control">
- </return>
- <description>
- </description>
- </method>
- <method name="set_tooltip">
- <argument index="0" name="tooltip" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_tooltip" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="atpos" type="Vector2" default="Vector2(0,0)">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_cursor_shape">
- <argument index="0" name="shape" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_default_cursor_shape" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_cursor_shape" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="pos" type="Vector2" default="Vector2(0,0)">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_focus_neighbour">
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="neighbour" type="NodePath">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_focus_neighbour" qualifiers="const">
- <return type="NodePath">
- </return>
- <argument index="0" name="margin" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_ignore_mouse">
- <argument index="0" name="ignore" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_ignoring_mouse" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="focus_enter">
- <description>
- </description>
- </signal>
- <signal name="mouse_enter">
- <description>
- </description>
- </signal>
- <signal name="resized">
- <description>
- </description>
- </signal>
- <signal name="minimum_size_changed">
- <description>
- </description>
- </signal>
- <signal name="size_flags_changed">
- <description>
- </description>
- </signal>
- <signal name="focus_exit">
- <description>
- </description>
- </signal>
- <signal name="input_event">
- <description>
- </description>
- </signal>
- <signal name="mouse_exit">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="ANCHOR_BEGIN" value="0">
- </constant>
- <constant name="ANCHOR_END" value="1">
- </constant>
- <constant name="ANCHOR_RATIO" value="2">
- </constant>
- <constant name="FOCUS_NONE" value="0">
- </constant>
- <constant name="FOCUS_CLICK" value="1">
- </constant>
- <constant name="FOCUS_ALL" value="2">
- </constant>
- <constant name="NOTIFICATION_RESIZED" value="34">
- </constant>
- <constant name="NOTIFICATION_MOUSE_ENTER" value="35">
- </constant>
- <constant name="NOTIFICATION_MOUSE_EXIT" value="36">
- </constant>
- <constant name="NOTIFICATION_FOCUS_ENTER" value="37">
- </constant>
- <constant name="NOTIFICATION_FOCUS_EXIT" value="38">
- </constant>
- <constant name="NOTIFICATION_THEME_CHANGED" value="39">
- </constant>
- <constant name="NOTIFICATION_MODAL_CLOSE" value="40">
- </constant>
- <constant name="CURSOR_ARROW" value="0">
- </constant>
- <constant name="CURSOR_IBEAM" value="1">
- </constant>
- <constant name="CURSOR_POINTING_HAND" value="2">
- </constant>
- <constant name="CURSOR_CROSS" value="3">
- </constant>
- <constant name="CURSOR_WAIT" value="4">
- </constant>
- <constant name="CURSOR_BUSY" value="5">
- </constant>
- <constant name="CURSOR_DRAG" value="6">
- </constant>
- <constant name="CURSOR_CAN_DROP" value="7">
- </constant>
- <constant name="CURSOR_FORBIDDEN" value="8">
- </constant>
- <constant name="CURSOR_VSIZE" value="9">
- </constant>
- <constant name="CURSOR_HSIZE" value="10">
- </constant>
- <constant name="CURSOR_BDIAGSIZE" value="11">
- </constant>
- <constant name="CURSOR_FDIAGSIZE" value="12">
- </constant>
- <constant name="CURSOR_MOVE" value="13">
- </constant>
- <constant name="CURSOR_VSPLIT" value="14">
- </constant>
- <constant name="CURSOR_HSPLIT" value="15">
- </constant>
- <constant name="CURSOR_HELP" value="16">
- </constant>
- </constants>
-</class>
-<class name="ConvexPolygonShape" inherits="Shape" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_planes">
- <argument index="0" name="planes" type="Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_planes" qualifiers="const">
- <return type="Array">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ConvexPolygonShape2D" inherits="Shape2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_points">
- <argument index="0" name="points" type="Vector2Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_points" qualifiers="const">
- <return type="Vector2Array">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="DOFBlurFX" inherits="ScenarioFX" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="DampedSpringJoint2D" inherits="Joint2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_length">
- <argument index="0" name="length" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_length" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_rest_length">
- <argument index="0" name="rest_length" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_rest_length" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_stiffness">
- <argument index="0" name="stiffness" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_stiffness" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_damping">
- <argument index="0" name="damping" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_damping" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="DirectionalLight" inherits="Light" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="DynamicBody" inherits="PhysicsBody" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_mass">
- <argument index="0" name="mass" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_friction">
- <argument index="0" name="friction" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_bounce">
- <argument index="0" name="bounce" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_mass" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_friction" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_bounce" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_linear_velocity">
- <argument index="0" name="linear_velocity" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_linear_velocity" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_angular_velocity">
- <argument index="0" name="angular_velocity" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_angular_velocity" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_sleeping">
- <argument index="0" name="sleeping" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_sleeping" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_applied_force">
- <argument index="0" name="applied_force" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_applied_force" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_applied_torque">
- <argument index="0" name="applied_torque" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_applied_torque" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="apply_local_impulse">
- <argument index="0" name="pos" type="Vector3">
- </argument>
- <argument index="1" name="impulse" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_axis_velocity">
- <argument index="0" name="axis_velocity" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_direct_state_control">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_direct_state_control_enabled" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_omit_force_integration">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_omitting_force_integration" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="DynamicCharacterBody" inherits="DynamicBody" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="DynamicCustomBody" inherits="DynamicBody" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_mode">
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="DynamicRigidBody" inherits="DynamicBody" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="EmptyControl" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_minsize">
- <argument index="0" name="minsize" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_minsize" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="_File" inherits="Reference" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="open">
- <return type="int">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <argument index="1" name="flags" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="close">
- <description>
- </description>
- </method>
- <method name="is_open" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="seek">
- <argument index="0" name="pos" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="seek_end">
- <argument index="0" name="pos" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_pos" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_len" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="eof_reached" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_8" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_16" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_32" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_64" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_float" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_double" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_real" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_buffer" qualifiers="const">
- <return type="RawArray">
- </return>
- <argument index="0" name="len" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_line" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_endian_swap">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_endian_swap">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_error" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_var" qualifiers="const">
- <description>
- </description>
- </method>
- <method name="store_8">
- <argument index="0" name="value" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="store_16">
- <argument index="0" name="value" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="store_32">
- <argument index="0" name="value" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="store_64">
- <argument index="0" name="value" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="store_float">
- <argument index="0" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="store_double">
- <argument index="0" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="store_real">
- <argument index="0" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="store_buffer">
- <argument index="0" name="buffer" type="RawArray">
- </argument>
- <description>
- </description>
- </method>
- <method name="store_line">
- <argument index="0" name="line" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="store_string">
- <argument index="0" name="string" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="store_var">
- <argument index="0" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="file_exists" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="READ" value="1">
- </constant>
- <constant name="WRITE" value="2">
- </constant>
- <constant name="READ_WRITE" value="3">
- </constant>
- </constants>
-</class>
-<class name="FileDialog" inherits="ConfirmationDialog" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="clear_filters">
- <description>
- </description>
- </method>
- <method name="add_filter">
- <argument index="0" name="filter" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_current_dir" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_current_file" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_current_path" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_current_dir">
- <argument index="0" name="dir" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_current_file">
- <argument index="0" name="file" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_current_path">
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_mode">
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_mode" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_vbox">
- <return type="VBoxContainer">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="dir_selected">
- <argument index="0" name="dir" type="String">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="file_selected">
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="MODE_OPEN_FILE" value="0">
- </constant>
- <constant name="MODE_OPEN_DIR" value="1">
- </constant>
- <constant name="MODE_SAVE_FILE" value="2">
- </constant>
- </constants>
-</class>
-<class name="FixedMaterial" inherits="Material" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_shader">
- <argument index="0" name="shader" type="Shader">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shader" qualifiers="const">
- <return type="Shader">
- </return>
- <description>
- </description>
- </method>
- <method name="set_parameter">
- <argument index="0" name="param" type="int">
- </argument>
- <argument index="1" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_parameter" qualifiers="const">
- <argument index="0" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_texture">
- <argument index="0" name="param" type="int">
- </argument>
- <argument index="1" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_texture" qualifiers="const">
- <return type="Texture">
- </return>
- <argument index="0" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_texgen_mode">
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_texgen_mode" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_texcoord_mode">
- <argument index="0" name="param" type="int">
- </argument>
- <argument index="1" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_texcoord_mode" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_uv_transform">
- <argument index="0" name="transform" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_uv_transform" qualifiers="const">
- <return type="Transform">
- </return>
- <description>
- </description>
- </method>
- <method name="set_detail_blend_mode">
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_detail_blend_mode" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="PARAM_DIFFUSE" value="0">
- </constant>
- <constant name="PARAM_DETAIL" value="1">
- </constant>
- <constant name="PARAM_SPECULAR" value="2">
- </constant>
- <constant name="PARAM_EMISSION" value="3">
- </constant>
- <constant name="PARAM_SPECULAR_EXP" value="4">
- </constant>
- <constant name="PARAM_GLOW" value="5">
- </constant>
- <constant name="PARAM_NORMAL" value="6">
- </constant>
- <constant name="PARAM_SHADE_PARAM" value="7">
- </constant>
- <constant name="PARAM_MAX" value="8">
- </constant>
- <constant name="TEXGEN_SPHERE" value="1">
- </constant>
- <constant name="TEXGEN_SCREEN" value="2">
- </constant>
- <constant name="TEXGEN_SCREENZ" value="3">
- </constant>
- <constant name="TEXGEN_LOCAL_XY" value="0">
- </constant>
- <constant name="TEXCOORD_TEXGEN" value="3">
- </constant>
- <constant name="TEXCOORD_UV" value="0">
- </constant>
- <constant name="TEXCOORD_UV_TRANSFORM" value="1">
- </constant>
- <constant name="TEXCOORD_UV2" value="2">
- </constant>
- </constants>
-</class>
-<class name="FogFX" inherits="ScenarioFX" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="FollowCamera" inherits="Camera" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_orbit">
- <argument index="0" name="orbit" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_orbit" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_orbit_x">
- <argument index="0" name="x" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_orbit_y">
- <argument index="0" name="y" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_min_orbit_x">
- <argument index="0" name="x" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_min_orbit_x" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_max_orbit_x">
- <argument index="0" name="x" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_max_orbit_x" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_height">
- <argument index="0" name="height" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_height" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_inclination">
- <argument index="0" name="inclination" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_inclination" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="rotate_orbit">
- <argument index="0" name="arg0" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_distance">
- <argument index="0" name="distance" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_distance" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_max_distance">
- <argument index="0" name="max_distance" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_max_distance" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_min_distance">
- <argument index="0" name="min_distance" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_min_distance" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_clip">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_clip" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_autoturn">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_autoturn" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_autoturn_tolerance">
- <argument index="0" name="degrees" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_autoturn_tolerance" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_autoturn_speed">
- <argument index="0" name="speed" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_autoturn_speed" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_smoothing">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_smoothing" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_rotation_smoothing">
- <argument index="0" name="amount" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_rotation_smoothing" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_translation_smoothing">
- <argument index="0" name="amount" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_translation_smoothing" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_use_lookat_target">
- <argument index="0" name="use" type="bool">
- </argument>
- <argument index="1" name="lookat" type="Vector3" default="Vector3(0, 0, 0)">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Font" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_height">
- <argument index="0" name="px" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_height" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_ascent">
- <argument index="0" name="px" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_ascent" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_descent" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="add_kerning_pair">
- <argument index="0" name="char_a" type="int">
- </argument>
- <argument index="1" name="char_b" type="int">
- </argument>
- <argument index="2" name="kerning" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_kerning_pair" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_texture">
- <argument index="0" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_char">
- <argument index="0" name="character" type="int">
- </argument>
- <argument index="1" name="texture" type="int">
- </argument>
- <argument index="2" name="rect" type="Rect2">
- </argument>
- <argument index="3" name="align" type="Vector2" default="Vector2(0,0)">
- </argument>
- <argument index="4" name="advance" type="real" default="-1">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_char_size" qualifiers="const">
- <return type="Vector2">
- </return>
- <argument index="0" name="char" type="int">
- </argument>
- <argument index="1" name="next" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_string_size" qualifiers="const">
- <return type="Vector2">
- </return>
- <argument index="0" name="string" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear">
- <description>
- </description>
- </method>
- <method name="draw" qualifiers="const">
- <argument index="0" name="canvas_item" type="RID">
- </argument>
- <argument index="1" name="pos" type="Vector2">
- </argument>
- <argument index="2" name="string" type="String">
- </argument>
- <argument index="3" name="modulate" type="Color" default="Color(1,1,1,1)">
- </argument>
- <argument index="4" name="clip_w" type="int" default="-1">
- </argument>
- <description>
- </description>
- </method>
- <method name="draw_char" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="canvas_item" type="RID">
- </argument>
- <argument index="1" name="pos" type="Vector2">
- </argument>
- <argument index="2" name="char" type="int">
- </argument>
- <argument index="3" name="next" type="int" default="-1">
- </argument>
- <argument index="4" name="modulate" type="Color" default="Color(1,1,1,1)">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="GDNativeClass" inherits="Reference" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="new">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="GDScript" inherits="Script" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="new">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="GammaFX" inherits="ScenarioFX" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="_Geometry" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="build_box_planes">
- <return type="Array">
- </return>
- <argument index="0" name="extents" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="build_cylinder_planes">
- <return type="Array">
- </return>
- <argument index="0" name="radius" type="real">
- </argument>
- <argument index="1" name="height" type="real">
- </argument>
- <argument index="2" name="sides" type="int">
- </argument>
- <argument index="3" name="axis" type="int" default="2">
- </argument>
- <description>
- </description>
- </method>
- <method name="build_capsule_planes">
- <return type="Array">
- </return>
- <argument index="0" name="radius" type="real">
- </argument>
- <argument index="1" name="height" type="real">
- </argument>
- <argument index="2" name="sides" type="int">
- </argument>
- <argument index="3" name="lats" type="int">
- </argument>
- <argument index="4" name="axis" type="int" default="2">
- </argument>
- <description>
- </description>
- </method>
- <method name="segment_intersects_circle">
- <return type="real">
- </return>
- <argument index="0" name="segment_from" type="Vector2">
- </argument>
- <argument index="1" name="segment_to" type="Vector2">
- </argument>
- <argument index="2" name="circle_pos" type="Vector2">
- </argument>
- <argument index="3" name="circle_radius" type="real">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="GeometryInstance" inherits="VisualInstance" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_visible">
- <argument index="0" name="visible" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_visible" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_material_override">
- <argument index="0" name="material" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_material_override" qualifiers="const">
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Globals" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="has" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_order">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="pos" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_order" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_persisting">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_persisting" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="localize_path" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="globalize_path" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="GlowFX" inherits="ScenarioFX" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="GridMap" inherits="Spatial" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_theme">
- <argument index="0" name="theme" type="MeshLibrary">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_theme" qualifiers="const">
- <return type="MeshLibrary">
- </return>
- <description>
- </description>
- </method>
- <method name="set_cell_size">
- <argument index="0" name="size" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_cell_size" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_octant_size">
- <argument index="0" name="size" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_octant_size" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_width">
- <argument index="0" name="width" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_width" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_height">
- <argument index="0" name="height" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_height" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_depth">
- <argument index="0" name="depth" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_depth" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_cell_item">
- <argument index="0" name="x" type="int">
- </argument>
- <argument index="1" name="y" type="int">
- </argument>
- <argument index="2" name="z" type="int">
- </argument>
- <argument index="3" name="item" type="int">
- </argument>
- <argument index="4" name="orientation" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_cell_item" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="x" type="int">
- </argument>
- <argument index="1" name="y" type="int">
- </argument>
- <argument index="2" name="z" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_cell_item_orientation" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="x" type="int">
- </argument>
- <argument index="1" name="y" type="int">
- </argument>
- <argument index="2" name="z" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="resource_changed">
- <argument index="0" name="arg0" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_center_x">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_center_x" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_center_y">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_center_y" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_center_z">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_center_z" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_clip">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <argument index="1" name="clipabove" type="bool" default="true">
- </argument>
- <argument index="2" name="floor" type="int" default="0">
- </argument>
- <argument index="3" name="axis" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="crate_area">
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="area" type="AABB">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_bounds" qualifiers="const">
- <return type="AABB">
- </return>
- <argument index="0" name="area" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_exterior_portal">
- <argument index="0" name="area" type="int">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_name">
- <argument index="0" name="area" type="int">
- </argument>
- <argument index="1" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_name" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="area" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_is_exterior_portal" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="area" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_portal_disable_distance">
- <argument index="0" name="area" type="int">
- </argument>
- <argument index="1" name="distance" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_portal_disable_distance" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="area" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_portal_disable_color">
- <argument index="0" name="area" type="int">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_portal_disable_color" qualifiers="const">
- <return type="Color">
- </return>
- <argument index="0" name="area" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="erase_area">
- <argument index="0" name="area" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_unused_area_id" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="INVALID_CELL_ITEM" value="-1">
- </constant>
- </constants>
-</class>
-<class name="GrooveJoint2D" inherits="Joint2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_length">
- <argument index="0" name="length" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_length" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_initial_offset">
- <argument index="0" name="offset" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_initial_offset" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="HBoxContainer" inherits="BoxContainer" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="HButtonArray" inherits="ButtonArray" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="HDRFX" inherits="ScenarioFX" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="HScrollBar" inherits="ScrollBar" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="HSeparator" inherits="Separator" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="HSlider" inherits="Slider" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="IP" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="resolve_hostname">
- <return type="String">
- </return>
- <argument index="0" name="host" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="resolve_hostname_queue_item">
- <return type="int">
- </return>
- <argument index="0" name="host" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_resolve_item_status" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_resolve_item_address" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="erase_resolve_item">
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="RESOLVER_STATUS_NONE" value="0">
- </constant>
- <constant name="RESOLVER_STATUS_WAITING" value="1">
- </constant>
- <constant name="RESOLVER_STATUS_DONE" value="2">
- </constant>
- <constant name="RESOLVER_STATUS_ERROR" value="3">
- </constant>
- <constant name="RESOLVER_MAX_QUERIES" value="32">
- </constant>
- <constant name="RESOLVER_INVALID_ID" value="-1">
- </constant>
- </constants>
-</class>
-<class name="IP_Unix" inherits="IP" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="InputMap" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="InterpolatedCamera" inherits="Camera" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_target_path">
- <argument index="0" name="target_path" type="NodePath">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_target_path" qualifiers="const">
- <return type="NodePath">
- </return>
- <description>
- </description>
- </method>
- <method name="set_target">
- <argument index="0" name="target" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_speed">
- <argument index="0" name="speed" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_speed" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_interpolation_enabled">
- <argument index="0" name="target_path" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_interpolation_enabled" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Joint2D" inherits="Node2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_node_a">
- <argument index="0" name="node" type="NodePath">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_node_a" qualifiers="const">
- <return type="NodePath">
- </return>
- <description>
- </description>
- </method>
- <method name="set_node_b">
- <argument index="0" name="node" type="NodePath">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_node_b" qualifiers="const">
- <return type="NodePath">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Label" inherits="Range" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_align">
- <argument index="0" name="align" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_align" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_valign">
- <argument index="0" name="valign" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_valign" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_text">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_text" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_autowrap">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_autowrap" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_line_height" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_line_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="ALIGN_LEFT" value="0">
- </constant>
- <constant name="ALIGN_CENTER" value="1">
- </constant>
- <constant name="ALIGN_RIGHT" value="2">
- </constant>
- <constant name="ALIGN_FILL" value="3">
- </constant>
- <constant name="VALIGN_TOP" value="0">
- </constant>
- <constant name="VALIGN_CENTER" value="1">
- </constant>
- <constant name="VALIGN_BOTTOM" value="2">
- </constant>
- <constant name="VALIGN_FILL" value="3">
- </constant>
- </constants>
-</class>
-<class name="Light" inherits="VisualInstance" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_parameter">
- <argument index="0" name="variable" type="int">
- </argument>
- <argument index="1" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_parameter" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_color">
- <argument index="0" name="color" type="int">
- </argument>
- <argument index="1" name="value" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color" qualifiers="const">
- <return type="Color">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_project_shadows">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_project_shadows" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_projector">
- <argument index="0" name="projector" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_projector" qualifiers="const">
- <return type="Texture">
- </return>
- <description>
- </description>
- </method>
- <method name="set_operator">
- <argument index="0" name="operator" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_operator" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="PARAM_RADIUS" value="2">
- </constant>
- <constant name="PARAM_ENERGY" value="3">
- </constant>
- <constant name="PARAM_ATTENUATION" value="4">
- </constant>
- <constant name="PARAM_SPOT_ANGLE" value="1">
- </constant>
- <constant name="PARAM_SPOT_ATTENUATION" value="4">
- </constant>
- <constant name="PARAM_SHADOW_DARKENING" value="5">
- </constant>
- <constant name="COLOR_AMBIENT" value="0">
- </constant>
- <constant name="COLOR_DIFFUSE" value="1">
- </constant>
- <constant name="COLOR_SPECULAR" value="2">
- </constant>
- </constants>
-</class>
-<class name="LineEdit" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="clear">
- <description>
- </description>
- </method>
- <method name="select_all">
- <description>
- </description>
- </method>
- <method name="set_text">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_text" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_cursor_pos">
- <argument index="0" name="pos" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_cursor_pos" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_max_length">
- <argument index="0" name="chars" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_max_length" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="append_at_cursor">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_editable">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_editable" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_secret">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_secret" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="select" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="text_entered">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="text_changed">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="LineShape2D" inherits="Shape2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_normal">
- <argument index="0" name="normal" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_normal" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_d">
- <argument index="0" name="d" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_d" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="MainLoop" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="input_event">
- <argument index="0" name="arg0" type="InputEvent">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="NOTIFICATION_WM_FOCUS_IN" value="5">
- </constant>
- <constant name="NOTIFICATION_WM_FOCUS_OUT" value="6">
- </constant>
- <constant name="NOTIFICATION_WM_QUIT_REQUEST" value="7">
- </constant>
- </constants>
-</class>
-<class name="MarginContainer" inherits="Container" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Material" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_flag">
- <argument index="0" name="flag" type="int">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_flag" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="flag" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_hint">
- <argument index="0" name="hint" type="int">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_hint" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="hint" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_blend_mode">
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_blend_mode" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_shade_model">
- <argument index="0" name="model" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shade_model" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_line_width">
- <argument index="0" name="width" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_line_width" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_shader_param">
- <argument index="0" name="param" type="String">
- </argument>
- <argument index="1" name="arg1" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shader_param" qualifiers="const">
- <argument index="0" name="arg0" type="String">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="FLAG_VISIBLE" value="0">
- </constant>
- <constant name="FLAG_DOUBLE_SIDED" value="1">
- </constant>
- <constant name="FLAG_INVERT_FACES" value="2">
- </constant>
- <constant name="FLAG_UNSHADED" value="3">
- </constant>
- <constant name="FLAG_ONTOP" value="4">
- </constant>
- <constant name="FLAG_WIREFRAME" value="5">
- </constant>
- <constant name="FLAG_BILLBOARD_TOGGLE" value="6">
- </constant>
- <constant name="FLAG_MAX" value="7">
- </constant>
- <constant name="HINT_DECAL" value="0">
- </constant>
- <constant name="HINT_OPAQUE_PRE_PASS" value="1">
- </constant>
- <constant name="HINT_NO_SHADOW" value="2">
- </constant>
- <constant name="HINT_NO_DEPTH_DRAW" value="3">
- </constant>
- <constant name="HINT_MAX" value="4">
- </constant>
- <constant name="SHADE_MODEL_LAMBERT" value="0">
- </constant>
- <constant name="SHADE_MODEL_LAMBERT_WRAP" value="1">
- </constant>
- <constant name="SHADE_MODEL_FRESNEL" value="2">
- </constant>
- <constant name="SHADE_MODEL_TOON" value="3">
- </constant>
- <constant name="SHADE_MODEL_CUSTOM_0" value="4">
- </constant>
- <constant name="SHADE_MODEL_CUSTOM_1" value="5">
- </constant>
- <constant name="SHADE_MODEL_CUSTOM_2" value="6">
- </constant>
- <constant name="SHADE_MODEL_CUSTOM_3" value="7">
- </constant>
- <constant name="BLEND_MODE_MIX" value="0">
- </constant>
- <constant name="BLEND_MODE_ADD" value="1">
- </constant>
- <constant name="BLEND_MODE_SUB" value="2">
- </constant>
- </constants>
-</class>
-<class name="MenuButton" inherits="Button" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_popup">
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="about_to_show">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="Mesh" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_morph_target">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_morph_target_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_morph_target_name" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="index" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_morph_targets">
- <description>
- </description>
- </method>
- <method name="set_morph_target_mode">
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_morph_target_mode" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="add_surface">
- <argument index="0" name="primitive" type="int">
- </argument>
- <argument index="1" name="format" type="int">
- </argument>
- <argument index="2" name="array_len" type="int">
- </argument>
- <argument index="3" name="index_array_len" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_surface_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="surface_remove">
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="surface_set_array">
- <return type="int">
- </return>
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <argument index="1" name="array" type="int">
- </argument>
- <argument index="2" name="data" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="surface_get_array" qualifiers="const">
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <argument index="1" name="array" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="surface_get_array_len" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="surface_get_array_index_len" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="surface_get_format" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="surface_get_primitive_type" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="surface_set_material">
- <argument index="0" name="surf_idx:Material" type="int">
- </argument>
- <argument index="1" name="arg1" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="surface_get_material" qualifiers="const">
- <return type="Material">
- </return>
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="NO_INDEX_ARRAY" value="-1">
- </constant>
- <constant name="ARRAY_WEIGHTS_SIZE" value="4">
- </constant>
- <constant name="ARRAY_VERTEX" value="0">
- </constant>
- <constant name="ARRAY_NORMAL" value="1">
- </constant>
- <constant name="ARRAY_TANGENT" value="2">
- </constant>
- <constant name="ARRAY_COLOR" value="3">
- </constant>
- <constant name="ARRAY_TEX_UV" value="4">
- </constant>
- <constant name="ARRAY_TEX_UV2" value="5">
- </constant>
- <constant name="ARRAY_BONES" value="6">
- </constant>
- <constant name="ARRAY_WEIGHTS" value="7">
- </constant>
- <constant name="ARRAY_INDEX" value="8">
- </constant>
- <constant name="ARRAY_FORMAT_VERTEX" value="1">
- </constant>
- <constant name="ARRAY_FORMAT_NORMAL" value="2">
- </constant>
- <constant name="ARRAY_FORMAT_TANGENT" value="4">
- </constant>
- <constant name="ARRAY_FORMAT_COLOR" value="8">
- </constant>
- <constant name="ARRAY_FORMAT_TEX_UV" value="16">
- </constant>
- <constant name="ARRAY_FORMAT_TEX_UV2" value="32">
- </constant>
- <constant name="ARRAY_FORMAT_BONES" value="64">
- </constant>
- <constant name="ARRAY_FORMAT_WEIGHTS" value="128">
- </constant>
- <constant name="ARRAY_FORMAT_INDEX" value="256">
- </constant>
- <constant name="PRIMITIVE_POINTS" value="0">
- </constant>
- <constant name="PRIMITIVE_LINES" value="1">
- </constant>
- <constant name="PRIMITIVE_LINE_STRIP" value="2">
- </constant>
- <constant name="PRIMITIVE_LINE_LOOP" value="3">
- </constant>
- <constant name="PRIMITIVE_TRIANGLES" value="4">
- </constant>
- <constant name="PRIMITIVE_TRIANGLE_STRIP" value="5">
- </constant>
- <constant name="PRIMITIVE_TRIANGLE_FAN" value="6">
- </constant>
- </constants>
-</class>
-<class name="MeshInstance" inherits="GeometryInstance" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_mesh">
- <argument index="0" name="mesh" type="Mesh">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_mesh" qualifiers="const">
- <return type="Mesh">
- </return>
- <description>
- </description>
- </method>
- <method name="get_aabb" qualifiers="const">
- <return type="AABB">
- </return>
- <description>
- </description>
- </method>
- <method name="create_trimesh_collision">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="MeshLibrary" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="create_item">
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_name">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_mesh">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="mesh" type="Mesh">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_shape">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="shape" type="Shape">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_name" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_mesh" qualifiers="const">
- <return type="Mesh">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_shape" qualifiers="const">
- <return type="Shape">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_item">
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear">
- <description>
- </description>
- </method>
- <method name="get_item_list" qualifiers="const">
- <return type="IntArray">
- </return>
- <description>
- </description>
- </method>
- <method name="get_last_unused_item_id" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="MultiMesh" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_mesh">
- <argument index="0" name="mesh" type="Mesh">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_mesh" qualifiers="const">
- <return type="Mesh">
- </return>
- <description>
- </description>
- </method>
- <method name="set_instance_count">
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_instance_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_instance_transform">
- <argument index="0" name="arg0" type="int">
- </argument>
- <argument index="1" name="arg1" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_instance_transform" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_instance_color">
- <argument index="0" name="arg0" type="int">
- </argument>
- <argument index="1" name="arg1" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_instance_color" qualifiers="const">
- <return type="Color">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_aabb">
- <argument index="0" name="arg0" type="AABB">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_aabb" qualifiers="const">
- <return type="AABB">
- </return>
- <description>
- </description>
- </method>
- <method name="generate_aabb">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="MultiMeshInstance" inherits="GeometryInstance" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_multimesh">
- <argument index="0" name="multimesh" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_multimesh" qualifiers="const">
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Node" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_name">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_name" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="add_child">
- <argument index="0" name="node" type="Node">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_child">
- <argument index="0" name="node" type="Node">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_and_delete_child">
- <argument index="0" name="node" type="Node">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_child_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_child" qualifiers="const">
- <return type="Node">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_node" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="path" type="NodePath">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_node" qualifiers="const">
- <return type="Node">
- </return>
- <argument index="0" name="path" type="NodePath">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_parent" qualifiers="const">
- <return type="Parent">
- </return>
- <description>
- </description>
- </method>
- <method name="has_node_and_resource" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="path" type="NodePath">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_node_and_resource">
- <return type="Array">
- </return>
- <argument index="0" name="path" type="NodePath">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_inside_scene" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="is_a_parent_of" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="node" type="Node">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_greater_than" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="node" type="Node">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_path" qualifiers="const">
- <return type="NodePath">
- </return>
- <description>
- </description>
- </method>
- <method name="get_path_to" qualifiers="const">
- <return type="NodePath">
- </return>
- <argument index="0" name="node" type="Node">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_to_group">
- <argument index="0" name="group" type="String">
- </argument>
- <argument index="1" name="arg1" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_from_group">
- <argument index="0" name="group" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_in_group" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="group" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="move_child">
- <argument index="0" name="child_node" type="Node">
- </argument>
- <argument index="1" name="to_pos" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="raise">
- <description>
- </description>
- </method>
- <method name="set_owner">
- <argument index="0" name="owner" type="Node">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_owner" qualifiers="const">
- <return type="Node">
- </return>
- <description>
- </description>
- </method>
- <method name="remove_and_skip">
- <description>
- </description>
- </method>
- <method name="get_index" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="print_tree">
- <description>
- </description>
- </method>
- <method name="set_filename">
- <argument index="0" name="filename" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_filename" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="propagate_notification">
- <argument index="0" name="what" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_process">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_process_time" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="is_processing" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_idle_process">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_idle_process_time" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="is_idle_processing" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_process_input">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_processing_input" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_process_unhandled_input">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_processing_unhandled_input" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_process_mode">
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_process_mode" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="can_process" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="print_stray_nodes">
- <description>
- </description>
- </method>
- <method name="set_world">
- <argument index="0" name="world" type="World">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_world" qualifiers="const">
- <return type="World">
- </return>
- <description>
- </description>
- </method>
- <method name="get_current_world" qualifiers="const">
- <return type="World">
- </return>
- <description>
- </description>
- </method>
- <method name="get_scene" qualifiers="const">
- <return type="SceneMainLoop">
- </return>
- <description>
- </description>
- </method>
- <method name="duplicate" qualifiers="const">
- <return type="Node">
- </return>
- <description>
- </description>
- </method>
- <method name="replace_by">
- <argument index="0" name="node" type="Node">
- </argument>
- <argument index="1" name="keep_data" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="enter_scene">
- <description>
- </description>
- </signal>
- <signal name="renamed">
- <description>
- </description>
- </signal>
- <signal name="exit_scene">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="NOTIFICATION_ENTER_SCENE" value="10">
- </constant>
- <constant name="NOTIFICATION_EXIT_SCENE" value="11">
- </constant>
- <constant name="NOTIFICATION_MOVED_IN_PARENT" value="12">
- </constant>
- <constant name="NOTIFICATION_CHILDREN_CONFIGURED" value="13">
- </constant>
- <constant name="NOTIFICATION_PROCESS" value="16">
- </constant>
- <constant name="NOTIFICATION_IDLE_PROCESS" value="17">
- </constant>
- <constant name="NOTIFICATION_PARENTED" value="18">
- </constant>
- <constant name="NOTIFICATION_UNPARENTED" value="19">
- </constant>
- <constant name="NOTIFICATION_ENTER_WORLD" value="20">
- </constant>
- <constant name="NOTIFICATION_EXIT_WORLD" value="21">
- </constant>
- <constant name="NOTIFICATION_PAUSED" value="14">
- </constant>
- <constant name="NOTIFICATION_UNPAUSED" value="15">
- </constant>
- <constant name="PROCESS_NORMAL" value="0">
- </constant>
- <constant name="PROCESS_PAUSE" value="1">
- </constant>
- <constant name="PROCESS_ALWAYS" value="2">
- </constant>
- </constants>
-</class>
-<class name="Node2D" inherits="CanvasItem" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_pos">
- <argument index="0" name="pos" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_rot">
- <argument index="0" name="rot" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_scale">
- <argument index="0" name="scale" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_pos" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_rot" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_scale" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_global_pos" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="_OS" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_mouse_show">
- <argument index="0" name="show" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_mouse_grab">
- <argument index="0" name="grab" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_mouse_grab_enabled" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_mouse_pos" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_clipboard">
- <argument index="0" name="clipboard" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_clipboard" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_video_mode">
- <argument index="0" name="size" type="Vector2">
- </argument>
- <argument index="1" name="fullscreen" type="bool">
- </argument>
- <argument index="2" name="resizable" type="bool">
- </argument>
- <argument index="3" name="screen" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_video_mode_size" qualifiers="const">
- <return type="Vector2">
- </return>
- <argument index="0" name="screen" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_video_mode_fullscreen" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="screen" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_video_mode_resizable" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="screen" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_fullscreen_mode_list" qualifiers="const">
- <return type="Array">
- </return>
- <argument index="0" name="screen" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_iterations_per_second">
- <argument index="0" name="iterations_per_second" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_iterations_per_second" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_low_processor_usage_mode">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_in_low_processor_usage_mode" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_executable_path" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="execute">
- <return type="int">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <argument index="1" name="arguments" type="StringArray">
- </argument>
- <argument index="2" name="blocking" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="kill">
- <return type="int">
- </return>
- <argument index="0" name="pid" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_environment" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="environment" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_environment" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="environment" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_name" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_cmdline_args">
- <return type="StringArray">
- </return>
- <description>
- </description>
- </method>
- <method name="get_main_loop" qualifiers="const">
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_date" qualifiers="const">
- <return type="Dictionary">
- </return>
- <description>
- </description>
- </method>
- <method name="get_time" qualifiers="const">
- <return type="Dictionary">
- </return>
- <description>
- </description>
- </method>
- <method name="delay_usec" qualifiers="const">
- <argument index="0" name="usec" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_ticks_msec" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_locale" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="can_draw" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_frames_drawn">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="is_stdout_verbose" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_mouse_button_state" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="dump_memory_to_file">
- <argument index="0" name="file" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="dump_resources_to_file">
- <argument index="0" name="file" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="print_resources_in_use">
- <argument index="0" name="short" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="print_all_resources">
- <argument index="0" name="tofile" type="String" default="&quot;&quot;">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_static_memory_usage" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_static_memory_peak_usage" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_dynamic_memory_usage" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="DAY_SUNDAY" value="0">
- </constant>
- <constant name="DAY_MONDAY" value="1">
- </constant>
- <constant name="DAY_TUESDAY" value="2">
- </constant>
- <constant name="DAY_WEDNESDAY" value="3">
- </constant>
- <constant name="DAY_THURSDAY" value="4">
- </constant>
- <constant name="DAY_FRIDAY" value="5">
- </constant>
- <constant name="DAY_SATURDAY" value="6">
- </constant>
- <constant name="MONTH_JANUARY" value="0">
- </constant>
- <constant name="MONTH_FEBRUARY" value="1">
- </constant>
- <constant name="MONTH_MARCH" value="2">
- </constant>
- <constant name="MONTH_APRIL" value="3">
- </constant>
- <constant name="MONTH_MAY" value="4">
- </constant>
- <constant name="MONTH_JUNE" value="5">
- </constant>
- <constant name="MONTH_JULY" value="6">
- </constant>
- <constant name="MONTH_AUGUST" value="7">
- </constant>
- <constant name="MONTH_SEPTEMBER" value="8">
- </constant>
- <constant name="MONTH_OCTOBER" value="9">
- </constant>
- <constant name="MONTH_NOVEMBER" value="10">
- </constant>
- <constant name="MONTH_DECEMBER" value="11">
- </constant>
- </constants>
-</class>
-<class name="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_type" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="is_type" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set">
- <argument index="0" name="property" type="String">
- </argument>
- <argument index="1" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="get" qualifiers="const">
- <argument index="0" name="property" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_property_list" qualifiers="const">
- <return type="Array">
- </return>
- <description>
- </description>
- </method>
- <method name="notification">
- <argument index="0" name="what" type="int">
- </argument>
- <argument index="1" name="arg1" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_instance_ID" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_script">
- <argument index="0" name="script" type="Script">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_script" qualifiers="const">
- <return type="Script">
- </return>
- <description>
- </description>
- </method>
- <method name="set_meta">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_meta" qualifiers="const">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_meta" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_meta_list" qualifiers="const">
- <return type="StringArray">
- </return>
- <description>
- </description>
- </method>
- <method name="call">
- <argument index="0" name="method" type="String">
- </argument>
- <argument index="1" name="arg1" type="var" default="NULL">
- </argument>
- <argument index="2" name="arg2" type="var" default="NULL">
- </argument>
- <argument index="3" name="arg3" type="var" default="NULL">
- </argument>
- <argument index="4" name="arg4" type="var" default="NULL">
- </argument>
- <description>
- </description>
- </method>
- <method name="call_deferred">
- <argument index="0" name="method" type="String">
- </argument>
- <argument index="1" name="arg1" type="var" default="NULL">
- </argument>
- <argument index="2" name="arg2" type="var" default="NULL">
- </argument>
- <argument index="3" name="arg3" type="var" default="NULL">
- </argument>
- <argument index="4" name="arg4" type="var" default="NULL">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_user_signal">
- <argument index="0" name="signal" type="String">
- </argument>
- <argument index="1" name="arguments" type="Array" default="Array()">
- </argument>
- <description>
- </description>
- </method>
- <method name="emit_signal">
- <argument index="0" name="signal" type="String">
- </argument>
- <argument index="1" name="arguments" type="Array" default="Array()">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_signal_list" qualifiers="const">
- <return type="Array">
- </return>
- <description>
- </description>
- </method>
- <method name="connect">
- <argument index="0" name="signal" type="String">
- </argument>
- <argument index="1" name="target" type="Object">
- </argument>
- <argument index="2" name="method" type="String">
- </argument>
- <argument index="3" name="binds" type="Array" default="Array()">
- </argument>
- <argument index="4" name="flags" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="disconnect">
- <argument index="0" name="signal" type="String">
- </argument>
- <argument index="1" name="target" type="Object">
- </argument>
- <argument index="2" name="method" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_connected" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="signal" type="String">
- </argument>
- <argument index="1" name="target" type="Object">
- </argument>
- <argument index="2" name="method" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_block_signals">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_blocking_signals" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_message_translation">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="can_translate_messages">
- <argument index="0" name="arg0" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="XL_MESSAGE" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="message" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="tr" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="message" type="String">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="NOTIFICATION_POSTINITIALIZE" value="0">
- </constant>
- <constant name="NOTIFICATION_PREDELETE" value="1">
- </constant>
- <constant name="CONNECT_DEFERRED" value="1">
- </constant>
- <constant name="CONNECT_PERSIST" value="2">
- </constant>
- <constant name="CONNECT_ONESHOT" value="4">
- </constant>
- </constants>
-</class>
-<class name="OmniLight" inherits="Light" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="OptimizedSaver" inherits="Reference" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_target_platform">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_target_platform" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_target_name">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_property">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="optimize_object">
- <return type="bool">
- </return>
- <argument index="0" name="obj" type="Object">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="OptionButton" inherits="Button" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_item">
- <argument index="0" name="label" type="String">
- </argument>
- <argument index="1" name="id" type="int" default="-1">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_icon_item">
- <argument index="0" name="texture" type="Texture">
- </argument>
- <argument index="1" name="label" type="String">
- </argument>
- <argument index="2" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_text">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_icon">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_disabled">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="disabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_ID">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_metadata">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="metadata" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_text" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_icon" qualifiers="const">
- <return type="Texture">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_ID" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_metadata" qualifiers="const">
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_item_disabled" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="add_separator">
- <description>
- </description>
- </method>
- <method name="clear">
- <description>
- </description>
- </method>
- <method name="select">
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_selected" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selected_ID" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selected_metadata" qualifiers="const">
- <description>
- </description>
- </method>
- <method name="remove_item">
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="item_selected">
- <argument index="0" name="ID" type="int">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="PHashTranslation" inherits="Translation" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PacketPeer" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PacketPeerStream" inherits="PacketPeer" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_stream_peer">
- <argument index="0" name="peer" type="StreamPeer">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Panel" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ParallaxBackground" inherits="CanvasLayer" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_scroll_offset">
- <argument index="0" name="ofs" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_scroll_offset" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_scroll_base_offset">
- <argument index="0" name="ofs" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_scroll_base_offset" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_scroll_base_scale">
- <argument index="0" name="scale" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_scroll_base_scale" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_limit_begin">
- <argument index="0" name="ofs" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_limit_begin" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_limit_end">
- <argument index="0" name="ofs" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_limit_end" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ParallaxLayer" inherits="Node2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_motion_scale">
- <argument index="0" name="scale" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_motion_scale" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_motion_wrap_begin">
- <argument index="0" name="wrap_begin" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_motion_wrap_begin" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_motion_wrap_end">
- <argument index="0" name="wrap_end" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_motion_wrap_end" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Particles" inherits="VisualInstance" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_amount">
- <argument index="0" name="amount" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_amount" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_emitting">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_emitting" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_visibility_aabb">
- <argument index="0" name="aabb" type="AABB">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_visibility_aabb" qualifiers="const">
- <return type="AABB">
- </return>
- <description>
- </description>
- </method>
- <method name="set_emission_half_extents">
- <argument index="0" name="half_extents" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_emission_half_extents" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_emission_base_velocity">
- <argument index="0" name="base_velocity" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_emission_base_velocity" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_emission_points">
- <argument index="0" name="points" type="Vector3Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_emission_points" qualifiers="const">
- <return type="Vector3Array">
- </return>
- <description>
- </description>
- </method>
- <method name="set_gravity_normal">
- <argument index="0" name="normal" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_gravity_normal" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_variable">
- <argument index="0" name="variable" type="int">
- </argument>
- <argument index="1" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_variable" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="variable" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_randomness">
- <argument index="0" name="variable" type="int">
- </argument>
- <argument index="1" name="randomness" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_randomness" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_color_phase_pos">
- <argument index="0" name="phase" type="int">
- </argument>
- <argument index="1" name="pos" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color_phase_pos" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="phase" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_color_phase_color">
- <argument index="0" name="phase" type="int">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color_phase_color" qualifiers="const">
- <return type="Color">
- </return>
- <argument index="0" name="phase" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_material">
- <argument index="0" name="material" type="Material">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_material" qualifiers="const">
- <return type="Material">
- </return>
- <description>
- </description>
- </method>
- <method name="set_emit_timeout">
- <argument index="0" name="arg0" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_emit_timeout" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_height_from_velocity">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_height_from_velocity" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_color_phases">
- <argument index="0" name="count" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color_phases" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="VAR_LIFETIME" value="0">
- </constant>
- <constant name="VAR_SPREAD" value="1">
- </constant>
- <constant name="VAR_GRAVITY" value="2">
- </constant>
- <constant name="VAR_LINEAR_VELOCITY" value="3">
- </constant>
- <constant name="VAR_ANGULAR_VELOCITY" value="4">
- </constant>
- <constant name="VAR_LINEAR_ACCELERATION" value="5">
- </constant>
- <constant name="VAR_DRAG" value="6">
- </constant>
- <constant name="VAR_TANGENTIAL_ACCELERATION" value="7">
- </constant>
- <constant name="VAR_INITIAL_SIZE" value="9">
- </constant>
- <constant name="VAR_FINAL_SIZE" value="10">
- </constant>
- <constant name="VAR_INITIAL_ANGLE" value="11">
- </constant>
- <constant name="VAR_HEIGHT" value="12">
- </constant>
- <constant name="VAR_HEIGHT_SPEED_SCALE" value="13">
- </constant>
- <constant name="VAR_MAX" value="14">
- </constant>
- </constants>
-</class>
-<class name="Particles2D" inherits="Node2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_emitting">
- <argument index="0" name="active" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_emitting" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_amount">
- <argument index="0" name="amount" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_amount" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_lifetime">
- <argument index="0" name="lifetime" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_lifetime" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_pre_process_time">
- <argument index="0" name="time" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_pre_process_time" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_emit_timeout">
- <argument index="0" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_emit_timeout" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_param">
- <argument index="0" name="param" type="int">
- </argument>
- <argument index="1" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_param" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_randomness">
- <argument index="0" name="param" type="int">
- </argument>
- <argument index="1" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_randomness" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_texture">
- <argument index="0" name="texture" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_texture" qualifiers="const">
- <return type="Texture">
- </return>
- <description>
- </description>
- </method>
- <method name="set_emissor_offset">
- <argument index="0" name="offset" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_emissor_offset" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_emission_half_extents">
- <argument index="0" name="extents" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_emission_half_extents" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_color_phases">
- <argument index="0" name="phases" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color_phases" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_color_phase_color">
- <argument index="0" name="phase" type="int">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color_phase_color" qualifiers="const">
- <return type="Color">
- </return>
- <argument index="0" name="phase" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_color_phase_pos">
- <argument index="0" name="phase" type="int">
- </argument>
- <argument index="1" name="pos" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color_phase_pos" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="phase" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="pre_process">
- <argument index="0" name="time" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_use_local_space">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_using_local_space" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_initial_velocity">
- <argument index="0" name="velocity" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_initial_velocity" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="testee">
- <argument index="0" name="arg0" type="int" default="0">
- </argument>
- <argument index="1" name="arg1" type="int" default="1">
- </argument>
- <argument index="2" name="arg2" type="int" default="2">
- </argument>
- <argument index="3" name="arg3" type="int" default="3">
- </argument>
- <argument index="4" name="arg4" type="int" default="4">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="PARAM_DIRECTION" value="0">
- </constant>
- <constant name="PARAM_SPREAD" value="1">
- </constant>
- <constant name="PARAM_LINEAR_VELOCITY" value="2">
- </constant>
- <constant name="PARAM_SPIN_VELOCITY" value="3">
- </constant>
- <constant name="PARAM_GRAVITY_DIRECTION" value="4">
- </constant>
- <constant name="PARAM_GRAVITY_STRENGTH" value="5">
- </constant>
- <constant name="PARAM_RADIAL_ACCEL" value="6">
- </constant>
- <constant name="PARAM_TANGENTIAL_ACCEL" value="7">
- </constant>
- <constant name="PARAM_INITIAL_SIZE" value="9">
- </constant>
- <constant name="PARAM_FINAL_SIZE" value="10">
- </constant>
- <constant name="PARAM_HUE_VARIATION" value="11">
- </constant>
- <constant name="PARAM_MAX" value="12">
- </constant>
- <constant name="MAX_COLOR_PHASES" value="4">
- </constant>
- </constants>
-</class>
-<class name="PathRemap" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_remap">
- <argument index="0" name="from" type="String">
- </argument>
- <argument index="1" name="to" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_remap">
- <argument index="0" name="path" type="String">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_remap" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="erase_remap">
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_remaps">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Physics2DDirectBodyState" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_total_gravity" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_total_density" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_inverse_mass" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_inverse_inertia" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_linear_velocity">
- <argument index="0" name="velocity" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_linear_velocity" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_angular_velocity">
- <argument index="0" name="velocity" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_angular_velocity" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_transform">
- <argument index="0" name="transform" type="Matrix32">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_transform" qualifiers="const">
- <return type="Matrix32">
- </return>
- <description>
- </description>
- </method>
- <method name="set_sleep_state">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_sleeping" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_contact_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_contact_local_pos" qualifiers="const">
- <return type="Vector2">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_local_normal" qualifiers="const">
- <return type="Vector2">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_local_shape" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider_pos" qualifiers="const">
- <return type="Vector2">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider_id" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider_object" qualifiers="const">
- <return type="Object">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider_shape" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider_velocity_at_pos" qualifiers="const">
- <return type="Vector2">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_step" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="integrate_forces">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Physics2DDirectBodyStateSW" inherits="Physics2DDirectBodyState" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Physics2DServer" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="shape_create">
- <return type="RID">
- </return>
- <argument index="0" name="type" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="shape_set_data">
- <argument index="0" name="shape" type="RID">
- </argument>
- <argument index="1" name="data" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="shape_get_type" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="shape" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="shape_get_data" qualifiers="const">
- <argument index="0" name="shape" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="space_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="space_set_active">
- <argument index="0" name="space" type="RID">
- </argument>
- <argument index="1" name="active" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="space_is_active" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="space" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="space_set_param">
- <argument index="0" name="space" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <argument index="2" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="space_get_param" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="space" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="area_set_space">
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="space" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_space" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_add_shape">
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="shape" type="int">
- </argument>
- <argument index="2" name="transform" type="RID" default="1,0, 0,1, 0,0">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_shape" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_shape_transform">
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <argument index="2" name="transform" type="Matrix32">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_shape_count" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_shape" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_shape_transform" qualifiers="const">
- <return type="Matrix32">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_remove_shape">
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_clear_shapes">
- <argument index="0" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_param" qualifiers="const">
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_transform" qualifiers="const">
- <return type="Matrix32">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_param" qualifiers="const">
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_transform" qualifiers="const">
- <return type="Matrix32">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_attach_object_instance_ID">
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_object_instance_ID" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_create">
- <return type="RID">
- </return>
- <argument index="0" name="mode" type="int" default="1">
- </argument>
- <argument index="1" name="init_sleeping" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_space">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="space" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_space" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_mode">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_mode" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_add_shape">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape" type="RID">
- </argument>
- <argument index="2" name="transform" type="Matrix32" default="1,0, 0,1, 0,0">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_shape">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <argument index="2" name="shape" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_shape_transform">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <argument index="2" name="transform" type="Matrix32">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_shape_count" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_shape" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_shape_transform" qualifiers="const">
- <return type="Matrix32">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_remove_shape">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_clear_shapes">
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_attach_object_instance_ID">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_object_instance_ID" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_enable_continuous_collision_detection">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_is_continuous_collision_detection_enabled" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_param">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <argument index="2" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_param" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_static_simulate_motion">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="new_xform" type="Matrix32">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_state">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="state" type="int">
- </argument>
- <argument index="2" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_state" qualifiers="const">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="state" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_apply_impulse">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="pos" type="Vector2">
- </argument>
- <argument index="2" name="impulse" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_axis_velocity">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="axis_velocity" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_add_collision_exception">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="excepted_body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_remove_collision_exception">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="excepted_body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_max_contacts_reported">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="amount" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_max_contacts_reported" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_omit_force_integration">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_is_omitting_force_integration" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="pin_joint_create">
- <return type="RID">
- </return>
- <argument index="0" name="anchor" type="Vector2">
- </argument>
- <argument index="1" name="body_a" type="RID">
- </argument>
- <argument index="2" name="body_b" type="RID" default="RID()">
- </argument>
- <description>
- </description>
- </method>
- <method name="groove_joint_create">
- <return type="RID">
- </return>
- <argument index="0" name="groove1_a" type="Vector2">
- </argument>
- <argument index="1" name="groove2_a" type="Vector2">
- </argument>
- <argument index="2" name="anchor_b" type="Vector2">
- </argument>
- <argument index="3" name="body_a" type="RID" default="RID()">
- </argument>
- <argument index="4" name="body_b" type="RID" default="RID()">
- </argument>
- <description>
- </description>
- </method>
- <method name="damped_spring_joint_create">
- <return type="RID">
- </return>
- <argument index="0" name="anchor_a" type="Vector2">
- </argument>
- <argument index="1" name="anchor_b" type="Vector2">
- </argument>
- <argument index="2" name="body_a" type="RID">
- </argument>
- <argument index="3" name="body_b" type="RID" default="RID()">
- </argument>
- <description>
- </description>
- </method>
- <method name="damped_string_joint_set_param">
- <argument index="0" name="joint" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <argument index="2" name="value" type="real" default="RID()">
- </argument>
- <description>
- </description>
- </method>
- <method name="damped_string_joint_get_param" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="joint" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="joint_get_type" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="joint" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_create">
- <return type="RID">
- </return>
- <argument index="0" name="receiver" type="Object">
- </argument>
- <argument index="1" name="callback" type="String">
- </argument>
- <argument index="2" name="userdata" type="var" default="NULL">
- </argument>
- <argument index="3" name="persist" type="bool" default="true">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_body_state">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_body_direct_state">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_area">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_intersection">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="space" type="RID">
- </argument>
- <argument index="2" name="notify_hint_only" type="bool" default="false">
- </argument>
- <argument index="3" name="exclude" type="Array" default="Array()">
- </argument>
- <argument index="4" name="usermask" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_intersection_ray">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="from" type="Vector2">
- </argument>
- <argument index="2" name="dir" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_intersection_segment">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="from" type="Vector2">
- </argument>
- <argument index="2" name="to" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_intersection_shape">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="shape" type="RID">
- </argument>
- <argument index="2" name="transform" type="Matrix32">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_clear">
- <argument index="0" name="query" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_get_type" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="query" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_get_target" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="query" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="free">
- <argument index="0" name="rid" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_active">
- <argument index="0" name="active" type="bool">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="SHAPE_LINE" value="0">
- </constant>
- <constant name="SHAPE_SEGMENT" value="1">
- </constant>
- <constant name="SHAPE_CIRCLE" value="2">
- </constant>
- <constant name="SHAPE_RECTANGLE" value="3">
- </constant>
- <constant name="SHAPE_CAPSULE" value="4">
- </constant>
- <constant name="SHAPE_CONVEX_POLYGON" value="5">
- </constant>
- <constant name="SHAPE_CONCAVE_POLYGON" value="6">
- </constant>
- <constant name="SHAPE_CUSTOM" value="7">
- </constant>
- <constant name="AREA_PARAM_OVERRIDE_PARAMS" value="0">
- </constant>
- <constant name="AREA_PARAM_GRAVITY" value="1">
- </constant>
- <constant name="AREA_PARAM_GRAVITY_VECTOR" value="2">
- </constant>
- <constant name="AREA_PARAM_GRAVITY_IS_POINT" value="3">
- </constant>
- <constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="4">
- </constant>
- <constant name="AREA_PARAM_DENSITY" value="5">
- </constant>
- <constant name="AREA_PARAM_PRIORITY" value="6">
- </constant>
- <constant name="BODY_MODE_STATIC" value="0">
- </constant>
- <constant name="BODY_MODE_RIGID" value="1">
- </constant>
- <constant name="BODY_MODE_CHARACTER" value="2">
- </constant>
- <constant name="BODY_PARAM_BOUNCE" value="0">
- </constant>
- <constant name="BODY_PARAM_FRICTION" value="1">
- </constant>
- <constant name="BODY_PARAM_MASS" value="2">
- </constant>
- <constant name="BODY_PARAM_MAX" value="3">
- </constant>
- <constant name="BODY_STATE_TRANSFORM" value="0">
- </constant>
- <constant name="BODY_STATE_LINEAR_VELOCITY" value="1">
- </constant>
- <constant name="BODY_STATE_ANGULAR_VELOCITY" value="2">
- </constant>
- <constant name="BODY_STATE_SLEEPING" value="3">
- </constant>
- <constant name="JOINT_PIN" value="0">
- </constant>
- <constant name="JOINT_GROOVE" value="1">
- </constant>
- <constant name="JOINT_DAMPED_SPRING" value="2">
- </constant>
- <constant name="DAMPED_STRING_REST_LENGTH" value="0">
- </constant>
- <constant name="DAMPED_STRING_STIFFNESS" value="1">
- </constant>
- <constant name="DAMPED_STRING_DAMPING" value="2">
- </constant>
- <constant name="TYPE_BODY" value="0">
- </constant>
- <constant name="TYPE_AREA" value="1">
- </constant>
- <constant name="AREA_BODY_ADDED" value="0">
- </constant>
- <constant name="AREA_BODY_REMOVED" value="1">
- </constant>
- <constant name="QUERY_NONE" value="0">
- </constant>
- <constant name="QUERY_BODY_STATE" value="1">
- </constant>
- <constant name="QUERY_BODY_DIRECT_STATE" value="2">
- </constant>
- <constant name="QUERY_AREA_MONITOR" value="3">
- </constant>
- <constant name="QUERY_INTERSECTION" value="4">
- </constant>
- </constants>
-</class>
-<class name="Physics2DServerSW" inherits="Physics2DServer" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PhysicsBody" inherits="Spatial" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_shape">
- <argument index="0" name="shape" type="Shape">
- </argument>
- <argument index="1" name="transform" type="Transform" default="Transform()">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shape_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_shape">
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <argument index="1" name="shape" type="Shape">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_shape_transform">
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <argument index="1" name="transform" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shape" qualifiers="const">
- <return type="Shape">
- </return>
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shape_transform" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_shape">
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_shapes">
- <description>
- </description>
- </method>
- <method name="get_body" qualifiers="const">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="set_max_contacts_reported">
- <argument index="0" name="contacts" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_max_contacts_reported" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_contacts_reported_depth_treshold">
- <argument index="0" name="depth" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contacts_reported_depth_treshold" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PhysicsBody2D" inherits="CollisionObject2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PhysicsDirectBodyState" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_total_gravity" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="get_total_density" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_inverse_mass" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_inverse_inertia_tensor" qualifiers="const">
- <return type="Matrix3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_linear_velocity">
- <argument index="0" name="velocity" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_linear_velocity" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_angular_velocity">
- <argument index="0" name="velocity" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_angular_velocity" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_transform">
- <argument index="0" name="transform" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_transform" qualifiers="const">
- <return type="Transform">
- </return>
- <description>
- </description>
- </method>
- <method name="set_sleep_state">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_sleeping" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_contact_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_contact_local_pos" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_local_normal" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_local_shape" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider_pos" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider_id" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider_shape" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider_velocity_at_pos" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PhysicsDirectBodyStateSW" inherits="PhysicsDirectBodyState" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PhysicsServer" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="shape_create">
- <return type="RID">
- </return>
- <argument index="0" name="shape_type" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="shape_set_data">
- <argument index="0" name="shape" type="RID">
- </argument>
- <argument index="1" name="data" type="var" default="-1">
- </argument>
- <description>
- </description>
- </method>
- <method name="shape_get_type" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="shape" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="shape_get_data" qualifiers="const">
- <argument index="0" name="shape" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="space_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="area_create">
- <return type="RID">
- </return>
- <argument index="0" name="space" type="int">
- </argument>
- <argument index="1" name="arg1" type="bool" default="RID()">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_param">
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <argument index="2" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_shape">
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="shape" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_bounds">
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="bounds" type="Dictionary">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_transform">
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="transform" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_param" qualifiers="const">
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_shape" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_bounds" qualifiers="const">
- <return type="Dictionary">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_transform" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_create">
- <return type="RID">
- </return>
- <argument index="0" name="space" type="int">
- </argument>
- <argument index="1" name="arg1" type="bool" default="RID()">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_mode">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_mode" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_add_shape">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape" type="RID">
- </argument>
- <argument index="2" name="transform" type="Transform" default="Transform()">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_shape">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <argument index="2" name="shape" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_shape_transform">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <argument index="2" name="transform" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_shape_count" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_shape" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_shape_transform" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_attach_object_instance_ID">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="ID" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_object_instance_ID" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_user_flags">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="user_flags" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_user_flags" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_param">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <argument index="2" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_param" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_static_simulate_motion">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="motion" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_state">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="state" type="int">
- </argument>
- <argument index="2" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_state" qualifiers="const">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="state" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_applied_force">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="applied_force" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_applied_force" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_applied_torque">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="applied_torque" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_applied_torque" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_axis_velocity">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="axis_velocity" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_apply_impulse">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="pos" type="Vector3">
- </argument>
- <argument index="2" name="impulse" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_add_collision_exception">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="against_body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_remove_collision_exception">
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="against_body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_create">
- <return type="RID">
- </return>
- <argument index="0" name="receiver" type="Object">
- </argument>
- <argument index="1" name="callback" type="String">
- </argument>
- <argument index="2" name="userdata" type="var">
- </argument>
- <argument index="3" name="persist" type="bool" default="true">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_body_state">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_body_direct_state">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_area">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_intersection">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="space" type="RID">
- </argument>
- <argument index="2" name="exclude" type="Array" default="Array()">
- </argument>
- <argument index="3" name="usermask" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_intersection_ray">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="origin" type="Vector3">
- </argument>
- <argument index="2" name="dir" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_intersection_segment">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="from" type="Vector3">
- </argument>
- <argument index="2" name="to" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_intersection_shape">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="shape" type="RID">
- </argument>
- <argument index="2" name="arg2" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_intersection_bounds">
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="bounds" type="Dictionary">
- </argument>
- <argument index="2" name="arg2" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_clear">
- <argument index="0" name="query" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_get_type" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="query" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_get_target" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="query" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="free">
- <argument index="0" name="rid" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_active">
- <argument index="0" name="active" type="bool">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="SHAPE_PLANE" value="0">
- </constant>
- <constant name="SHAPE_SPHERE" value="2">
- </constant>
- <constant name="SHAPE_BOX" value="3">
- </constant>
- <constant name="SHAPE_CAPSULE" value="4">
- </constant>
- <constant name="SHAPE_CONVEX_POLYGON" value="5">
- </constant>
- <constant name="SHAPE_CONCAVE_POLYGON" value="6">
- </constant>
- <constant name="SHAPE_HEIGHTMAP" value="7">
- </constant>
- <constant name="SHAPE_CUSTOM" value="8">
- </constant>
- <constant name="AREA_PARAM_OVERRIDE_PARAMS" value="0">
- </constant>
- <constant name="AREA_PARAM_GRAVITY" value="1">
- </constant>
- <constant name="AREA_PARAM_GRAVITY_VECTOR" value="2">
- </constant>
- <constant name="AREA_PARAM_GRAVITY_IS_POINT" value="3">
- </constant>
- <constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="4">
- </constant>
- <constant name="AREA_PARAM_DENSITY" value="5">
- </constant>
- <constant name="AREA_PARAM_PRIORITY" value="6">
- </constant>
- <constant name="BODY_MODE_STATIC" value="0">
- </constant>
- <constant name="BODY_MODE_RIGID" value="1">
- </constant>
- <constant name="BODY_MODE_CHARACTER" value="2">
- </constant>
- <constant name="BODY_PARAM_BOUNCE" value="0">
- </constant>
- <constant name="BODY_PARAM_FRICTION" value="1">
- </constant>
- <constant name="BODY_PARAM_MASS" value="2">
- </constant>
- <constant name="BODY_STATE_TRANSFORM" value="0">
- </constant>
- <constant name="BODY_STATE_LINEAR_VELOCITY" value="1">
- </constant>
- <constant name="BODY_STATE_ANGULAR_VELOCITY" value="2">
- </constant>
- <constant name="BODY_STATE_SLEEPING" value="3">
- </constant>
- <constant name="HINGE_VAR_ANGULAR_ONLY" value="0">
- </constant>
- <constant name="HINGE_VAR_LOWER_LIMIT" value="1">
- </constant>
- <constant name="HINGE_VAR_HIGHER_LIMIT" value="2">
- </constant>
- <constant name="HINGE_VAR_LIMIT_SOFTNESS" value="3">
- </constant>
- <constant name="HINGE_VAR_RELAXATION" value="4">
- </constant>
- <constant name="HINGE_VAR_MOTOR_ENABLED" value="5">
- </constant>
- <constant name="HINGE_VAR_MOTOR_TARGET_VELOCITY" value="6">
- </constant>
- <constant name="HINGE_VAR_MOTOR_IMPULSE" value="7">
- </constant>
- <constant name="CONE_TWIST_VAR_SWING_SPAN_LIMIT_1" value="0">
- </constant>
- <constant name="CONE_TWIST_VAR_SWING_SPAN_LIMIT_2" value="1">
- </constant>
- <constant name="CONE_TWIST_VAR_TWIST_SPAN_LIMIT" value="2">
- </constant>
- <constant name="CONE_TWIST_VAR_BIAS" value="3">
- </constant>
- <constant name="CONE_TWIST_VAR_RELAXATION" value="4">
- </constant>
- <constant name="TYPE_BODY" value="0">
- </constant>
- <constant name="TYPE_AREA" value="1">
- </constant>
- <constant name="QUERY_NONE" value="0">
- </constant>
- <constant name="QUERY_BODY_STATE" value="1">
- </constant>
- <constant name="QUERY_BODY_DIRECT_STATE" value="2">
- </constant>
- <constant name="QUERY_AREA_MONITOR" value="3">
- </constant>
- <constant name="QUERY_INTERSECTION" value="4">
- </constant>
- </constants>
-</class>
-<class name="PhysicsServerSW" inherits="PhysicsServer" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PinJoint2D" inherits="Joint2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PlaneShape" inherits="Shape" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_plane">
- <argument index="0" name="plane" type="Plane">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_plane" qualifiers="const">
- <return type="Plane">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Popup" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="popup_centered">
- <argument index="0" name="size" type="Vector2" default="Vector2(0,0)">
- </argument>
- <description>
- </description>
- </method>
- <method name="popup_centered_ratio">
- <argument index="0" name="ratio" type="real" default="0.75">
- </argument>
- <description>
- </description>
- </method>
- <method name="popup_centered_minsize">
- <argument index="0" name="minsize" type="Vector2" default="Vector2(0,0)">
- </argument>
- <description>
- </description>
- </method>
- <method name="popup">
- <description>
- </description>
- </method>
- <method name="set_exclusive">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_exclusive" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="about_to_show">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="NOTIFICATION_POST_POPUP" value="80">
- </constant>
- </constants>
-</class>
-<class name="PopupDialog" inherits="Popup" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PopupMenu" inherits="Popup" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_icon_item">
- <argument index="0" name="texture" type="Object">
- </argument>
- <argument index="1" name="label" type="String">
- </argument>
- <argument index="2" name="id" type="int" default="-1">
- </argument>
- <argument index="3" name="accel" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_item">
- <argument index="0" name="label" type="String">
- </argument>
- <argument index="1" name="id" type="int" default="-1">
- </argument>
- <argument index="2" name="accel" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_icon_check_item">
- <argument index="0" name="texture" type="Object">
- </argument>
- <argument index="1" name="label" type="String">
- </argument>
- <argument index="2" name="id" type="int" default="-1">
- </argument>
- <argument index="3" name="accel" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_check_item">
- <argument index="0" name="label" type="String">
- </argument>
- <argument index="1" name="id" type="int" default="-1">
- </argument>
- <argument index="2" name="accel" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_submenu_item">
- <argument index="0" name="label" type="String">
- </argument>
- <argument index="1" name="submenu" type="int">
- </argument>
- <argument index="2" name="id" type="int" default="-1">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_text">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_icon">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="icon" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_accelerator">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="accel" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_metadata">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="metadata" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_checked">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_disabled">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="disabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_submenu">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="submenu" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_as_separator">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_as_checkable">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_ID">
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_text" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_icon" qualifiers="const">
- <return type="Object">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_metadata" qualifiers="const">
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_accelerator" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_submenu" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_item_separator" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_item_checkable" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_item_checked" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_item_disabled" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_ID" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_index" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="add_separator">
- <description>
- </description>
- </method>
- <method name="remove_item">
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear">
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="item_pressed">
- <argument index="0" name="ID" type="int">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="PopupPanel" inherits="Popup" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Portal" inherits="VisualInstance" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_shape">
- <argument index="0" name="points" type="Vector2Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shape" qualifiers="const">
- <return type="Vector2Array">
- </return>
- <description>
- </description>
- </method>
- <method name="set_enabled">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_enabled" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_disable_distance">
- <argument index="0" name="distance" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_disable_distance" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_disabled_color">
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_disabled_color" qualifiers="const">
- <return type="Color">
- </return>
- <description>
- </description>
- </method>
- <method name="set_connect_range">
- <argument index="0" name="range" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_connect_range" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Position2D" inherits="Node2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Position3D" inherits="Spatial" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ProximityGroup" inherits="Spatial" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_group_name">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="broadcast">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="parameters" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_dispatch_mode">
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_grid_radius">
- <argument index="0" name="radius" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_grid_radius" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="broadcast">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="parameters" type="Array">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="ProximityGroup2D" inherits="Node2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_group_size">
- <argument index="0" name="size" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_group_size" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_group_notifym">
- <argument index="0" name="notify" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_group_notify" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="grouped">
- <argument index="0" name="pgroup" type="Object">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="ungrouped">
- <argument index="0" name="pgroup" type="Object">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="Range" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_val" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_value" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_min" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_max" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_step" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_page" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_unit_value" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_rounded_values" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_val">
- <argument index="0" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_value">
- <argument index="0" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_min">
- <argument index="0" name="minimum" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_max">
- <argument index="0" name="maximum" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_step">
- <argument index="0" name="step" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_page">
- <argument index="0" name="pagesize" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_unit_value">
- <argument index="0" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_rounded_values">
- <argument index="0" name="arg0" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_exp_unit_value">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_unit_value_exp" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="share">
- <argument index="0" name="with" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="unshare">
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="value_changed">
- <argument index="0" name="value" type="real">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="changed">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="RayShape" inherits="Shape" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_length">
- <argument index="0" name="length" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_length" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="RectangleShape2D" inherits="Shape2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_extents">
- <argument index="0" name="extents" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_extents" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Reference" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="init_ref">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="reference">
- <description>
- </description>
- </method>
- <method name="unreference">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ReferenceFrame" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Resource" inherits="Reference" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_path">
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_path" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_name">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_name" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_rid" qualifiers="const">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="changed">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="_ResourceLoader" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="load">
- <return type="Resource">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <argument index="1" name="type_hint" type="String" default="&quot;&quot;">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_recognized_extensions_for_type">
- <return type="StringArray">
- </return>
- <argument index="0" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ResourcePreloader" inherits="Node" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_resource">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="resource" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_resource">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="rename_resource">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="newname" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_resource" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_resource" qualifiers="const">
- <return type="Object">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_resource_list" qualifiers="const">
- <return type="StringArray">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="_ResourceSaver" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="save">
- <return type="int">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <argument index="1" name="resource" type="Resource">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_recognized_extensions">
- <return type="StringArray">
- </return>
- <argument index="0" name="type" type="Object">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="RichTextLabel" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_text">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_image">
- <argument index="0" name="image" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="newline">
- <description>
- </description>
- </method>
- <method name="push_font">
- <argument index="0" name="font" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="push_color">
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="push_align">
- <argument index="0" name="align" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="push_indent">
- <argument index="0" name="level" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="push_list">
- <argument index="0" name="type" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="push_meta">
- <argument index="0" name="data" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="push_underline">
- <description>
- </description>
- </method>
- <method name="pop">
- <description>
- </description>
- </method>
- <method name="clear">
- <description>
- </description>
- </method>
- <method name="set_meta_underline">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_meta_underlined" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_scroll_active">
- <argument index="0" name="active" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_scroll_active" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_scroll_follow">
- <argument index="0" name="follow" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_scroll_following" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_tab_size">
- <argument index="0" name="spaces" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_tab_size" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="meta_clicked">
- <argument index="0" name="meta" type="Nil">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="ALIGN_LEFT" value="0">
- </constant>
- <constant name="ALIGN_CENTER" value="1">
- </constant>
- <constant name="ALIGN_RIGHT" value="2">
- </constant>
- <constant name="ALIGN_FILL" value="3">
- </constant>
- <constant name="LIST_NUMBERS" value="0">
- </constant>
- <constant name="LIST_LETTERS" value="1">
- </constant>
- <constant name="LIST_DOTS" value="2">
- </constant>
- <constant name="ITEM_MAIN" value="0">
- </constant>
- <constant name="ITEM_TEXT" value="1">
- </constant>
- <constant name="ITEM_IMAGE" value="2">
- </constant>
- <constant name="ITEM_NEWLINE" value="3">
- </constant>
- <constant name="ITEM_FONT" value="4">
- </constant>
- <constant name="ITEM_COLOR" value="5">
- </constant>
- <constant name="ITEM_UNDERLINE" value="6">
- </constant>
- <constant name="ITEM_ALIGN" value="7">
- </constant>
- <constant name="ITEM_INDENT" value="8">
- </constant>
- <constant name="ITEM_LIST" value="9">
- </constant>
- <constant name="ITEM_META" value="10">
- </constant>
- </constants>
-</class>
-<class name="RigidBody2D" inherits="PhysicsBody2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_mode">
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_mode" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_mass">
- <argument index="0" name="mass" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_mass" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_weight">
- <argument index="0" name="weight" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_weight" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_friction">
- <argument index="0" name="friction" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_friction" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_bounce">
- <argument index="0" name="bounce" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_bounce" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_linear_velocity">
- <argument index="0" name="linear_velocity" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_linear_velocity" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_angular_velocity">
- <argument index="0" name="angular_velocity" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_angular_velocity" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_max_contacts_reported">
- <argument index="0" name="amount" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_max_contacts_reported" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_use_custom_integrator">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_using_custom_integrator">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_contact_monitor">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_contact_monitor_enabled" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_use_continuous_collision_detection">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_using_continuous_collision_detection" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_axis_velocity">
- <argument index="0" name="axis_velocity" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="apply_impulse">
- <argument index="0" name="pos" type="Vector2">
- </argument>
- <argument index="1" name="impulse" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_active">
- <argument index="0" name="active" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_active" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="body_enter">
- <argument index="0" name="body_id" type="int">
- </argument>
- <argument index="1" name="body" type="Object">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="body_enter_shape">
- <argument index="0" name="body_id" type="int">
- </argument>
- <argument index="1" name="body" type="Object">
- </argument>
- <argument index="2" name="body_shape" type="int">
- </argument>
- <argument index="3" name="local_shape" type="int">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="body_exit">
- <argument index="0" name="body_id" type="int">
- </argument>
- <argument index="1" name="body" type="Object">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="body_exit_shape">
- <argument index="0" name="body_id" type="int">
- </argument>
- <argument index="1" name="body" type="Object">
- </argument>
- <argument index="2" name="body_shape" type="int">
- </argument>
- <argument index="3" name="local_shape" type="int">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="MODE_STATIC" value="1">
- </constant>
- <constant name="MODE_RIGID" value="0">
- </constant>
- <constant name="MODE_CHARACTER" value="2">
- </constant>
- </constants>
-</class>
-<class name="Room" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_bounds">
- <argument index="0" name="bsp_tree" type="Dictionary">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_bounds" qualifiers="const">
- <return type="Dictionary">
- </return>
- <description>
- </description>
- </method>
- <method name="set_geometry_hint">
- <argument index="0" name="triangles" type="Vector3Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_geometry_hint" qualifiers="const">
- <return type="Vector3Array">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="RoomInstance" inherits="VisualInstance" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_room">
- <argument index="0" name="room" type="Room">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_room" qualifiers="const">
- <return type="Room">
- </return>
- <description>
- </description>
- </method>
- <method name="compute_room_from_subtree">
- <description>
- </description>
- </method>
- <method name="set_simulate_acoustics">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_simulating_acoustics" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SSAOFX" inherits="ScenarioFX" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Sample" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="create">
- <argument index="0" name="format" type="int">
- </argument>
- <argument index="1" name="stereo" type="bool">
- </argument>
- <argument index="2" name="length" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_format" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="is_stereo" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_length" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_data">
- <argument index="0" name="data" type="RawArray">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_data" qualifiers="const">
- <return type="RawArray">
- </return>
- <description>
- </description>
- </method>
- <method name="set_mix_rate">
- <argument index="0" name="hz" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_mix_rate" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_loop_format">
- <argument index="0" name="format" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_loop_format" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_loop_begin">
- <argument index="0" name="pos" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_loop_begin" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_loop_end">
- <argument index="0" name="pos" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_loop_end" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="FORMAT_PCM8" value="0">
- </constant>
- <constant name="FORMAT_PCM16" value="1">
- </constant>
- <constant name="FORMAT_IMA_ADPCM" value="2">
- </constant>
- <constant name="LOOP_NONE" value="0">
- </constant>
- <constant name="LOOP_FORWARD" value="1">
- </constant>
- <constant name="LOOP_PING_PONG" value="2">
- </constant>
- </constants>
-</class>
-<class name="SampleLibrary" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_sample">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="sample" type="Sample">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_sample" qualifiers="const">
- <return type="Sample">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_sample" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_sample">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SamplePlayer" inherits="Node" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_sample_library">
- <argument index="0" name="library" type="SampleLibrary">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_sample_library" qualifiers="const">
- <return type="SampleLibrary">
- </return>
- <description>
- </description>
- </method>
- <method name="set_voice_count">
- <argument index="0" name="max_voices" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_voice_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="play">
- <return type="int">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="unique" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="stop">
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="stop_all">
- <description>
- </description>
- </method>
- <method name="set_mix_rate">
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="hz" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_pitch_scale">
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="ratio" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_volume">
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="nrg" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_volume_db">
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="nrg" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_pan">
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="pan" type="real">
- </argument>
- <argument index="2" name="depth" type="real" default="0">
- </argument>
- <argument index="3" name="height" type="real" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_filter">
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="type" type="int">
- </argument>
- <argument index="2" name="cutoff_hz" type="real">
- </argument>
- <argument index="3" name="resonance" type="real">
- </argument>
- <argument index="4" name="gain" type="real" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_chorus">
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="send" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_reverb">
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="room_type" type="int">
- </argument>
- <argument index="2" name="send" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_mix_rate" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_pitch_scale" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_volume" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_volume_db" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_pan" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_pan_depth" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_pan_height" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_filter_type" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_filter_cutoff" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_filter_resonance" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_filter_gain" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_chorus" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_reverb_room" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_reverb" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_pitch_scale">
- <argument index="0" name="ratio" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_volume">
- <argument index="0" name="nrg" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_volume_db">
- <argument index="0" name="db" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_pan">
- <argument index="0" name="pan" type="real">
- </argument>
- <argument index="1" name="depth" type="real" default="0">
- </argument>
- <argument index="2" name="height" type="real" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_filter">
- <argument index="0" name="type" type="int">
- </argument>
- <argument index="1" name="cutoff_hz" type="real">
- </argument>
- <argument index="2" name="resonance" type="real">
- </argument>
- <argument index="3" name="gain" type="real" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_chorus">
- <argument index="0" name="send" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_reverb">
- <argument index="0" name="room_type" type="int">
- </argument>
- <argument index="1" name="send" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_default_pitch_scale" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_volume" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_volume_db" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_pan" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_pan_depth" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_pan_height" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_filter_type" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_filter_cutoff" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_filter_resonance" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_filter_gain" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_chorus" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_reverb_room" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_reverb" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="is_active" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="is_voice_active" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="FILTER_NONE" value="0">
- </constant>
- <constant name="FILTER_LOWPASS" value="1">
- </constant>
- <constant name="FILTER_BANDPASS" value="2">
- </constant>
- <constant name="FILTER_HIPASS" value="3">
- </constant>
- <constant name="FILTER_NOTCH" value="4">
- </constant>
- <constant name="FILTER_PEAK" value="5">
- </constant>
- <constant name="FILTER_BANDLIMIT" value="6">
- </constant>
- <constant name="FILTER_LOW_SHELF" value="7">
- </constant>
- <constant name="FILTER_HIGH_SHELF" value="8">
- </constant>
- <constant name="REVERB_SMALL" value="0">
- </constant>
- <constant name="REVERB_MEDIUM" value="1">
- </constant>
- <constant name="REVERB_LARGE" value="2">
- </constant>
- <constant name="REVERB_HALL" value="3">
- </constant>
- </constants>
-</class>
-<class name="ScenarioFX" inherits="Node" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SceneIO" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="load">
- <return type="Object">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="save">
- <return type="int">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <argument index="1" name="scene" type="Object">
- </argument>
- <argument index="2" name="flags" type="int" default="0">
- </argument>
- <argument index="3" name="optimizer" type="Object" default="Object()">
- </argument>
- <description>
- </description>
- </method>
- <method name="load_interactive">
- <return type="SceneInteractiveLoader">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SceneMainLoop" inherits="MainLoop" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_default_world" qualifiers="const">
- <return type="World">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_viewport" qualifiers="const">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_viewport_size" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_canvas" qualifiers="const">
- <return type="Canvas">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_space_2d" qualifiers="const">
- <return type="Space2D">
- </return>
- <description>
- </description>
- </method>
- <method name="notify_group">
- <argument index="0" name="call_flags" type="int">
- </argument>
- <argument index="1" name="group" type="String">
- </argument>
- <argument index="2" name="notification" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_group">
- <argument index="0" name="call_flags" type="int">
- </argument>
- <argument index="1" name="group" type="String">
- </argument>
- <argument index="2" name="property" type="String">
- </argument>
- <argument index="3" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_root_node">
- <return type="Node">
- </return>
- <description>
- </description>
- </method>
- <method name="set_root_node">
- <argument index="0" name="node" type="Node">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_auto_accept_quit">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_editor_hint">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_editor_hint" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_pause">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_paused" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_input_as_handled">
- <description>
- </description>
- </method>
- <method name="get_frame" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="quit">
- <description>
- </description>
- </method>
- <method name="call_group">
- <argument index="0" name="flags" type="int">
- </argument>
- <argument index="1" name="group" type="String">
- </argument>
- <argument index="2" name="method" type="String">
- </argument>
- <argument index="3" name="arg0" type="var" default="NULL">
- </argument>
- <argument index="4" name="arg1" type="var" default="NULL">
- </argument>
- <argument index="5" name="arg2" type="var" default="NULL">
- </argument>
- <argument index="6" name="arg3" type="var" default="NULL">
- </argument>
- <argument index="7" name="arg4" type="var" default="NULL">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="screen_resized">
- <description>
- </description>
- </signal>
- <signal name="node_removed">
- <argument index="0" name="node" type="Object">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="tree_changed">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="GROUP_CALL_DEFAULT" value="0">
- </constant>
- <constant name="GROUP_CALL_REVERSE" value="1">
- </constant>
- <constant name="GROUP_CALL_REALTIME" value="2">
- </constant>
- <constant name="GROUP_CALL_UNIQUE" value="4">
- </constant>
- </constants>
-</class>
-<class name="ScenePreloader" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="load_scene">
- <return type="int">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_scene_path" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="instance" qualifiers="const">
- <return type="Node">
- </return>
- <description>
- </description>
- </method>
- <method name="can_instance" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ScreenProximity2D" inherits="ProximityGroup2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="enter_screen">
- <description>
- </description>
- </method>
- <method name="exit_screen">
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="enter_screen">
- <description>
- </description>
- </signal>
- <signal name="exit_screen">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="Script" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="can_instance" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="instance_has" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="base_object" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_source_code" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_source_code" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_source_code">
- <argument index="0" name="source" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="reload">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ScrollBar" inherits="Range" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_custom_step">
- <argument index="0" name="step" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_custom_step" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SegmentShape2D" inherits="Shape2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_a">
- <argument index="0" name="a" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_a" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_b">
- <argument index="0" name="b" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_b" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Separator" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Shader" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_mode">
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_mode" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_vertex_code">
- <argument index="0" name="code" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_vertex_code" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_fragment_code">
- <argument index="0" name="code" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_fragment_code" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_use_world_transform">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_using_world_transform" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_param">
- <argument index="0" name="param" type="String">
- </argument>
- <argument index="1" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_param" qualifiers="const">
- <argument index="0" name="param" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_param_list" qualifiers="const">
- <return type="StringArray">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="MODE_MATERIAL" value="0">
- </constant>
- <constant name="MODE_POST_PROCESS" value="1">
- </constant>
- </constants>
-</class>
-<class name="ShaderMaterial" inherits="Material" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_shader">
- <argument index="0" name="shader" type="Shader">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shader" qualifiers="const">
- <return type="Shader">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Shape" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Shape2D" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Skeleton" inherits="Spatial" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_bone">
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="find_bone" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_bone_name" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_bone_parent" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_bone_parent">
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <argument index="1" name="parent_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_bone_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_bone_rest" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_bone_rest">
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <argument index="1" name="rest" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="bind_child_node_to_bone">
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <argument index="1" name="node" type="Node">
- </argument>
- <description>
- </description>
- </method>
- <method name="unbind_child_node_from_bone">
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <argument index="1" name="node" type="Node">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_bound_child_nodes_to_bone" qualifiers="const">
- <return type="Array">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_bones">
- <description>
- </description>
- </method>
- <method name="get_bone_pose" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_bone_pose">
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <argument index="1" name="pose" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_bone_custom_pose" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_bone_custom_pose">
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <argument index="1" name="custom_pose" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_bone_transform" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="NOTIFICATION_UPDATE_SKELETON" value="50">
- </constant>
- </constants>
-</class>
-<class name="SkyBoxFX" inherits="ScenarioFX" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Slider" inherits="Range" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_ticks">
- <argument index="0" name="count" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_ticks" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_ticks_on_borders" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_ticks_on_borders">
- <argument index="0" name="ticks_on_border" type="bool">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SoundRoomParams" inherits="Node" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_param">
- <argument index="0" name="param" type="int">
- </argument>
- <argument index="1" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_param" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_reverb_mode">
- <argument index="0" name="reverb_mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_reverb_mode" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_force_params_to_all_sources">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_forcing_params_to_all_sources">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Spatial" inherits="Node" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_transform">
- <argument index="0" name="local" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_transform" qualifiers="const">
- <return type="Transform">
- </return>
- <description>
- </description>
- </method>
- <method name="set_global_transform">
- <argument index="0" name="global" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_global_transform" qualifiers="const">
- <return type="Transform">
- </return>
- <description>
- </description>
- </method>
- <method name="get_parent_spatial" qualifiers="const">
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="update_gizmo">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="NOTIFICATION_UPDATE_GIZMO" value="43">
- </constant>
- <constant name="NOTIFICATION_TRANSFORM_CHANGED" value="40">
- </constant>
- <constant name="NOTIFICATION_SCENARIO_CHANGED" value="41">
- </constant>
- </constants>
-</class>
-<class name="SpatialPlayer" inherits="Spatial" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_param">
- <argument index="0" name="param" type="int">
- </argument>
- <argument index="1" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_param" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="PARAM_VOLUME_DB" value="0">
- </constant>
- <constant name="PARAM_PITCH_SCALE" value="1">
- </constant>
- <constant name="PARAM_ATTENUATION_MIN_DISTANCE" value="2">
- </constant>
- <constant name="PARAM_ATTENUATION_MAX_DISTANCE" value="3">
- </constant>
- <constant name="PARAM_ATTENUATION_DISTANCE_EXP" value="4">
- </constant>
- <constant name="PARAM_EMISSION_CONE_DEGREES" value="5">
- </constant>
- <constant name="PARAM_EMISSION_CONE_ATTENUATION_DB" value="6">
- </constant>
- <constant name="PARAM_MAX" value="7">
- </constant>
- </constants>
-</class>
-<class name="SpatialSamplePlayer" inherits="SpatialPlayer" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_sample_library">
- <argument index="0" name="library" type="SampleLibrary">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_sample_library" qualifiers="const">
- <return type="SampleLibrary">
- </return>
- <description>
- </description>
- </method>
- <method name="set_polyphony">
- <argument index="0" name="voices" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_polyphony" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="play">
- <return type="int">
- </return>
- <argument index="0" name="sample" type="String">
- </argument>
- <argument index="1" name="voice" type="int" default="-2">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_pitch_scale">
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="ratio" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_volume_scale_db">
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="db" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_voice_active" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="stop_voice">
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="stop_all">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="INVALID_VOICE" value="-1">
- </constant>
- <constant name="NEXT_VOICE" value="-2">
- </constant>
- </constants>
-</class>
-<class name="SpatialSoundServer" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SpatialSoundServerSW" inherits="SpatialSoundServer" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SpatialStreamPlayer" inherits="SpatialPlayer" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_stream">
- <argument index="0" name="stream" type="Stream">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_stream" qualifiers="const">
- <return type="Stream">
- </return>
- <description>
- </description>
- </method>
- <method name="play">
- <description>
- </description>
- </method>
- <method name="stop">
- <description>
- </description>
- </method>
- <method name="is_playing" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_loop">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_loop" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_stream_name" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_loop_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_pos" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="seek_pos">
- <argument index="0" name="time" type="real">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SphereShape" inherits="Shape" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_radius">
- <argument index="0" name="radius" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_radius" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SpinBox" inherits="Range" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_suffix">
- <argument index="0" name="suffix" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_suffix" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_prefix">
- <argument index="0" name="prefix" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_prefix" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_editable">
- <argument index="0" name="editable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_editable" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SpotLight" inherits="Light" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Sprite" inherits="Node2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_texture">
- <argument index="0" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_texture" qualifiers="const">
- <return type="Texture">
- </return>
- <description>
- </description>
- </method>
- <method name="set_centered">
- <argument index="0" name="centered" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_centered" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_flip_h">
- <argument index="0" name="flip_h" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_flipped_h" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_flip_v">
- <argument index="0" name="flip_v" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_flipped_v" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_region">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_region" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_region_rect">
- <argument index="0" name="rect" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_region_rect" qualifiers="const">
- <return type="Rect2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_frame">
- <argument index="0" name="frame" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_frame" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_vframes">
- <argument index="0" name="vframes" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_vframes" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_hframes">
- <argument index="0" name="hframes" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_hframes" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_modulate">
- <argument index="0" name="modulate" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_modulate" qualifiers="const">
- <return type="Color">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SquirrelScript" inherits="Script" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StaticBody" inherits="PhysicsBody" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_simulated_motion">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_simulating_motion" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="simulate_motion">
- <argument index="0" name="new_transform" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="create_shapes_from_child_meshes">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StaticBody2D" inherits="PhysicsBody2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_simulate_motion">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_simulating_motion" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_constant_linear_velocity">
- <argument index="0" name="vel" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_constant_angular_velocity">
- <argument index="0" name="vel" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_constant_linear_velocity" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_constant_angular_velocity" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StreamPeer" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="put_data">
- <return type="int">
- </return>
- <argument index="0" name="data" type="RawArray">
- </argument>
- <description>
- </description>
- </method>
- <method name="put_partial_data">
- <return type="Array">
- </return>
- <argument index="0" name="data" type="RawArray">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_data">
- <return type="Array">
- </return>
- <argument index="0" name="bytes" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_partial_data">
- <return type="Array">
- </return>
- <argument index="0" name="bytes" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StreamPeerTCP" inherits="StreamPeer" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="connect">
- <return type="int">
- </return>
- <argument index="0" name="host" type="String">
- </argument>
- <argument index="1" name="ip" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_connected" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_connected_host" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_connected_port" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="disconnect">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StreamPlayer" inherits="Node" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_stream">
- <argument index="0" name="stream" type="Stream">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_stream" qualifiers="const">
- <return type="Stream">
- </return>
- <description>
- </description>
- </method>
- <method name="play">
- <description>
- </description>
- </method>
- <method name="stop">
- <description>
- </description>
- </method>
- <method name="is_playing" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_paused">
- <argument index="0" name="paused" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_paused" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_loop">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_loop" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_volume">
- <argument index="0" name="volume" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_volume" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_volume_db">
- <argument index="0" name="db" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_volume_db" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_stream_name" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_loop_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_pos" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="seek_pos">
- <argument index="0" name="time" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_autoplay">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_autoplay" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_length" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StyleBox" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="test_mask" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="point" type="Vector2">
- </argument>
- <argument index="1" name="rect" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_margin">
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="offset" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_default_margin" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="margin" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_margin" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="margin" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_minimum_size" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_center_size" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_offset" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="draw" qualifiers="const">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StyleBoxEmpty" inherits="StyleBox" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StyleBoxFlat" inherits="StyleBox" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_bg_color">
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_bg_color" qualifiers="const">
- <return type="Color">
- </return>
- <description>
- </description>
- </method>
- <method name="set_light_color">
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_light_color" qualifiers="const">
- <return type="Color">
- </return>
- <description>
- </description>
- </method>
- <method name="set_dark_color">
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_dark_color" qualifiers="const">
- <return type="Color">
- </return>
- <description>
- </description>
- </method>
- <method name="set_border_size">
- <argument index="0" name="size" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_border_size" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_border_blend">
- <argument index="0" name="blend" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_border_blend" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_draw_center">
- <argument index="0" name="size" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_draw_center" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StyleBoxImageMask" inherits="StyleBox" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_image">
- <argument index="0" name="image" type="Image">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_image" qualifiers="const">
- <return type="Image">
- </return>
- <description>
- </description>
- </method>
- <method name="set_expand">
- <argument index="0" name="expand" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_expand" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_expand_margin_size">
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="size" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_expand_margin_size" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StyleBoxTexture" inherits="StyleBox" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_texture">
- <argument index="0" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_texture" qualifiers="const">
- <return type="Texture">
- </return>
- <description>
- </description>
- </method>
- <method name="set_margin_size">
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="size" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_margin_size" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_expand_margin_size">
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="size" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_expand_margin_size" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_draw_center">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_draw_center" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SurfaceTool" inherits="Reference" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="begin">
- <argument index="0" name="primitive" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_vertex">
- <argument index="0" name="vertex" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_color">
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_normal">
- <argument index="0" name="normal" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_tangent">
- <argument index="0" name="tangent" type="Plane">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_uv">
- <argument index="0" name="uv" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_uv2">
- <argument index="0" name="uv2" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_bones">
- <argument index="0" name="bones" type="IntArray">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_weights">
- <argument index="0" name="weights" type="RealArray">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_material">
- <argument index="0" name="material" type="Material">
- </argument>
- <description>
- </description>
- </method>
- <method name="index">
- <description>
- </description>
- </method>
- <method name="deindex">
- <description>
- </description>
- </method>
- <method name="generate_flat_normals">
- <description>
- </description>
- </method>
- <method name="generate_smooth_normals">
- <description>
- </description>
- </method>
- <method name="generate_tangents">
- <description>
- </description>
- </method>
- <method name="commit">
- <return type="Mesh">
- </return>
- <argument index="0" name="existing" type="Mesh" default="Object()">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="TCP_Server" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="listen">
- <return type="int">
- </return>
- <argument index="0" name="port" type="int">
- </argument>
- <argument index="1" name="accepted_hosts" type="StringArray" default="StringArray()">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_connection_available" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="take_connection">
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="stop">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="TabContainer" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_tab_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_current_tab">
- <argument index="0" name="tab_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_current_tab" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_tab_align">
- <argument index="0" name="align" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_tab_align" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_tabs_visible">
- <argument index="0" name="visible" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="are_tabs_visible" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_tab_title">
- <argument index="0" name="tab_idx" type="int">
- </argument>
- <argument index="1" name="title" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_tab_title" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="tab_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_tab_icon">
- <argument index="0" name="tab_idx" type="int">
- </argument>
- <argument index="1" name="icon" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_tab_icon" qualifiers="const">
- <return type="Texture">
- </return>
- <argument index="0" name="tab_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="tab_changed">
- <argument index="0" name="tab" type="int">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="TestCube" inherits="GeometryInstance" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="TextEdit" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_text">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="insert_text_at_cursor">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_line_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_text">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_line">
- <return type="String">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="cursor_set_column">
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="cursor_set_line">
- <argument index="0" name="line" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="cursor_get_column" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="cursor_get_line" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_readonly">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_wrap">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_max_chars">
- <argument index="0" name="amount" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="cut">
- <description>
- </description>
- </method>
- <method name="copy">
- <description>
- </description>
- </method>
- <method name="paste">
- <description>
- </description>
- </method>
- <method name="select_all">
- <description>
- </description>
- </method>
- <method name="select">
- <argument index="0" name="from_line" type="int">
- </argument>
- <argument index="1" name="from_column" type="int">
- </argument>
- <argument index="2" name="to_line" type="int">
- </argument>
- <argument index="3" name="to_column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_selection_active" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selection_from_line" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selection_from_column" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selection_to_line" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selection_to_column" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selection_text" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="search" qualifiers="const">
- <return type="IntArray">
- </return>
- <argument index="0" name="flags" type="String">
- </argument>
- <argument index="1" name="from_line" type="int">
- </argument>
- <argument index="2" name="from_column" type="int">
- </argument>
- <argument index="3" name="to_line" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="undo">
- <description>
- </description>
- </method>
- <method name="redo">
- <description>
- </description>
- </method>
- <method name="clear_undo_history">
- <description>
- </description>
- </method>
- <method name="set_syntax_coloring">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_syntax_coloring_enabled" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="add_keyword_color">
- <argument index="0" name="keyword" type="String">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_color_region">
- <argument index="0" name="begin_key" type="String">
- </argument>
- <argument index="1" name="end_key" type="String">
- </argument>
- <argument index="2" name="color" type="Color">
- </argument>
- <argument index="3" name="line_only" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_symbol_color">
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_custom_bg_color">
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_colors">
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="text_changed">
- <description>
- </description>
- </signal>
- <signal name="cursor_changed">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="SEARCH_MATCH_CASE" value="1">
- </constant>
- <constant name="SEARCH_WHOLE_WORDS" value="2">
- </constant>
- <constant name="SEARCH_BACKWARDS" value="4">
- </constant>
- </constants>
-</class>
-<class name="Texture" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="create">
- <argument index="0" name="width" type="int">
- </argument>
- <argument index="1" name="height" type="int">
- </argument>
- <argument index="2" name="format" type="int">
- </argument>
- <argument index="3" name="flags" type="int">
- </argument>
- <argument index="4" name="arg4" type="int" default="7">
- </argument>
- <description>
- </description>
- </method>
- <method name="create_from_image">
- <argument index="0" name="image" type="Image">
- </argument>
- <argument index="1" name="flags" type="int" default="7">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_flags">
- <argument index="0" name="flags" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_flags" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_format" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="load">
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_data">
- <argument index="0" name="image" type="Image">
- </argument>
- <argument index="1" name="cube_side" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_data" qualifiers="const">
- <return type="Image">
- </return>
- <argument index="0" name="cube_side" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_width" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_height" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_size" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_rid" qualifiers="const">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="has_alpha" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="draw" qualifiers="const">
- <argument index="0" name="canvas_item" type="RID">
- </argument>
- <argument index="1" name="pos" type="Vector2">
- </argument>
- <argument index="2" name="modulate" type="Color" default="Color(1,1,1,1)">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="FLAG_MIPMAPS" value="1">
- </constant>
- <constant name="FLAG_REPEAT" value="2">
- </constant>
- <constant name="FLAG_FILTER" value="4">
- </constant>
- <constant name="FLAG_CUBEMAP" value="8">
- </constant>
- <constant name="FLAG_VIDEO_SURFACE" value="16">
- </constant>
- <constant name="FLAGS_DEFAULT" value="7">
- </constant>
- <constant name="CUBEMAP_LEFT" value="0">
- </constant>
- <constant name="CUBEMAP_RIGHT" value="1">
- </constant>
- <constant name="CUBEMAP_BOTTOM" value="2">
- </constant>
- <constant name="CUBEMAP_TOP" value="3">
- </constant>
- <constant name="CUBEMAP_FRONT" value="4">
- </constant>
- <constant name="CUBEMAP_BACK" value="5">
- </constant>
- </constants>
-</class>
-<class name="TextureButton" inherits="BaseButton" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_normal_texture">
- <argument index="0" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_pressed_texture">
- <argument index="0" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_hover_texture">
- <argument index="0" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_disabled_texture">
- <argument index="0" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_focused_texture">
- <argument index="0" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_click_mask">
- <argument index="0" name="texture:Image" type="Image">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_normal_texture" qualifiers="const">
- <return type="Texture">
- </return>
- <description>
- </description>
- </method>
- <method name="get_pressed_texture" qualifiers="const">
- <return type="Texture">
- </return>
- <description>
- </description>
- </method>
- <method name="get_hover_texture" qualifiers="const">
- <return type="Texture">
- </return>
- <description>
- </description>
- </method>
- <method name="get_disabled_texture" qualifiers="const">
- <return type="Texture">
- </return>
- <description>
- </description>
- </method>
- <method name="get_focused_texture" qualifiers="const">
- <return type="Texture">
- </return>
- <description>
- </description>
- </method>
- <method name="get_click_mask" qualifiers="const">
- <return type="Image">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="TextureFrame" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_texture">
- <argument index="0" name="texture" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_texture" qualifiers="const">
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_expand">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_expand" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="TextureProgress" inherits="Range" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_under_texture">
- <argument index="0" name="tex" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_under_texture" qualifiers="const">
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_progress_texture">
- <argument index="0" name="tex" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_progress_texture" qualifiers="const">
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_over_texture">
- <argument index="0" name="tex" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_over_texture" qualifiers="const">
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Theme" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_icon">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <argument index="2" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_icon" qualifiers="const">
- <return type="Texture">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_icon" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_icon">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_icon_list" qualifiers="const">
- <return type="StringArray">
- </return>
- <argument index="0" name="arg0" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_stylebox">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <argument index="2" name="texture" type="StyleBox">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_stylebox" qualifiers="const">
- <return type="StyleBox">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_stylebox" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_stylebox">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_stylebox_list" qualifiers="const">
- <return type="StringArray">
- </return>
- <argument index="0" name="arg0" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_font">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <argument index="2" name="font" type="Font">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_font" qualifiers="const">
- <return type="Font">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_font" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_font">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_font_list" qualifiers="const">
- <return type="StringArray">
- </return>
- <argument index="0" name="arg0" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_color">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <argument index="2" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color" qualifiers="const">
- <return type="Color">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_color" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_color">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color_list" qualifiers="const">
- <return type="StringArray">
- </return>
- <argument index="0" name="arg0" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_constant">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <argument index="2" name="constant" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_constant" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_constant" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_constant">
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_constant_list" qualifiers="const">
- <return type="StringArray">
- </return>
- <argument index="0" name="arg0" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_type_list" qualifiers="const">
- <return type="StringArray">
- </return>
- <argument index="0" name="arg0" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="copy_default_theme">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="TileMap" inherits="Node2D" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_tileset">
- <argument index="0" name="tileset" type="TileSet">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_tileset" qualifiers="const">
- <return type="TileSet">
- </return>
- <description>
- </description>
- </method>
- <method name="set_cell_size">
- <argument index="0" name="size" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_cell_size" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_quadrant_size">
- <argument index="0" name="size" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_quadrant_size" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_center_x">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_center_x" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_center_y">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_center_y" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_cell">
- <argument index="0" name="x" type="int">
- </argument>
- <argument index="1" name="y" type="int">
- </argument>
- <argument index="2" name="tile" type="int">
- </argument>
- <argument index="3" name="flip_x" type="bool" default="false">
- </argument>
- <argument index="4" name="flip_y" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_cell" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="x" type="int">
- </argument>
- <argument index="1" name="y" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_cell_x_flipped" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="x" type="int">
- </argument>
- <argument index="1" name="y" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_cell_y_flipped" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="x" type="int">
- </argument>
- <argument index="1" name="y" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear">
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="INVALID_CELL" value="-1">
- </constant>
- </constants>
-</class>
-<class name="TileSet" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="create_tile">
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="tile_set_name">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="tile_get_name" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="tile_set_texture">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="tile_get_texture" qualifiers="const">
- <return type="Texture">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="tile_set_offset">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="offset" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="tile_get_offset" qualifiers="const">
- <return type="Vector2">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="tile_set_region">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="region" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- <method name="tile_get_region" qualifiers="const">
- <return type="Rect2">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="tile_set_shape">
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="shape" type="Shape2D">
- </argument>
- <description>
- </description>
- </method>
- <method name="tile_get_shape" qualifiers="const">
- <return type="Shape2D">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_tile">
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear">
- <description>
- </description>
- </method>
- <method name="get_last_unused_tile_id" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="find_tile_by_name" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_tiles_ids" qualifiers="const">
- <return type="Array">
- </return>
- <description>
-
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Timer" inherits="Node" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_wait_time">
- <argument index="0" name="time_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_wait_time" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_one_shot">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_one_shot" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_autostart">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_autostart" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="start">
- <description>
- </description>
- </method>
- <method name="stop">
- <description>
- </description>
- </method>
- <method name="get_time_left" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="timeout">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="Translation" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_locale">
- <argument index="0" name="locale" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_locale" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="add_message">
- <argument index="0" name="src_message" type="String">
- </argument>
- <argument index="1" name="xlated_message" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_message" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="src_message" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="erase_message">
- <argument index="0" name="src_message" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_message_list" qualifiers="const">
- <return type="StringArray">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="TranslationServer" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Tree" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="clear">
- <description>
- </description>
- </method>
- <method name="create_item">
- <return type="TreeItem">
- </return>
- <argument index="0" name="parent" type="TreeItem" default="Object()">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_root">
- <return type="TreeItem">
- </return>
- <description>
- </description>
- </method>
- <method name="set_column_min_width">
- <argument index="0" name="arg0" type="int">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_column_expand">
- <argument index="0" name="arg0" type="int">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_column_width" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_hide_root">
- <argument index="0" name="arg0" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_next_selected">
- <return type="TreeItem">
- </return>
- <argument index="0" name="from" type="TreeItem">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_selected" qualifiers="const">
- <return type="TreeItem">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selected_column" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_pressed_button" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_select_mode">
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_columns">
- <argument index="0" name="amount" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_columns" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_edited" qualifiers="const">
- <return type="TreeItem">
- </return>
- <description>
- </description>
- </method>
- <method name="get_edited_column" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_custom_popup_rect" qualifiers="const">
- <return type="Rect2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_item_area_rect" qualifiers="const">
- <return type="Rect2">
- </return>
- <argument index="0" name="item" type="TreeItem">
- </argument>
- <argument index="1" name="column" type="int" default="-1">
- </argument>
- <description>
- </description>
- </method>
- <method name="ensure_cursor_is_visible">
- <description>
- </description>
- </method>
- <method name="set_column_titles_visible">
- <argument index="0" name="visible" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="are_column_titles_visible" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_column_title">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="title" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_column_title" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_scroll" qualifiers="const">
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="item_activated">
- <description>
- </description>
- </signal>
- <signal name="multi_selected">
- <argument index="0" name="item" type="Object">
- </argument>
- <argument index="1" name="column" type="int">
- </argument>
- <argument index="2" name="selected" type="bool">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="custom_popup_edited">
- <argument index="0" name="arrow_clicked" type="bool">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="item_edited">
- <description>
- </description>
- </signal>
- <signal name="item_selected">
- <description>
- </description>
- </signal>
- <signal name="cell_selected">
- <description>
- </description>
- </signal>
- <signal name="button_pressed">
- <argument index="0" name="item" type="Object">
- </argument>
- <argument index="1" name="column" type="int">
- </argument>
- <argument index="2" name="id" type="int">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="SELECT_SINGLE" value="0">
- </constant>
- <constant name="SELECT_ROW" value="1">
- </constant>
- <constant name="SELECT_MULTI" value="2">
- </constant>
- </constants>
-</class>
-<class name="TreeItem" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_cell_mode">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_cell_mode" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_checked">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="checked" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_checked" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_text">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_text" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_icon">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="texture" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_icon" qualifiers="const">
- <return type="Texture">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_icon_region">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="region" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_icon_region" qualifiers="const">
- <return type="Rect2">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_icon_max_width">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="width" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_icon_max_width" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_range">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_range" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_range_config">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="min" type="real">
- </argument>
- <argument index="2" name="max" type="real">
- </argument>
- <argument index="3" name="step" type="real">
- </argument>
- <argument index="4" name="expr" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_range_config">
- <return type="Dictionary">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_metadata">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="meta" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_metadata" qualifiers="const">
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_collapsed">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_collapsed">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_next">
- <return type="TreeItem">
- </return>
- <description>
- </description>
- </method>
- <method name="get_prev">
- <return type="TreeItem">
- </return>
- <description>
- </description>
- </method>
- <method name="get_parent">
- <return type="TreeItem">
- </return>
- <description>
- </description>
- </method>
- <method name="get_children">
- <return type="TreeItem">
- </return>
- <description>
- </description>
- </method>
- <method name="get_next_visible">
- <return type="TreeItem">
- </return>
- <description>
- </description>
- </method>
- <method name="get_prev_visible">
- <return type="TreeItem">
- </return>
- <description>
- </description>
- </method>
- <method name="remove_child">
- <argument index="0" name="child" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_selectable">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="selectable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_selectable" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_selected">
- <return type="bool">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="select">
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="deselect">
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_editable">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_editable">
- <return type="bool">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_custom_color">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_custom_color">
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_custom_bg_color">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_custom_bg_color">
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_custom_bg_color" qualifiers="const">
- <return type="Color">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_button">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="button" type="Texture">
- </argument>
- <argument index="2" name="arg2" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_button_count" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_button" qualifiers="const">
- <return type="Texture">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="button_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="erase_button">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="button_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_tooltip">
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="tooltip" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_tooltip" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="CELL_MODE_STRING" value="0">
- </constant>
- <constant name="CELL_MODE_CHECK" value="1">
- </constant>
- <constant name="CELL_MODE_RANGE" value="2">
- </constant>
- <constant name="CELL_MODE_ICON" value="3">
- </constant>
- <constant name="CELL_MODE_CUSTOM" value="4">
- </constant>
- </constants>
-</class>
-<class name="VBoxContainer" inherits="BoxContainer" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="VButtonArray" inherits="ButtonArray" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="VScrollBar" inherits="ScrollBar" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="VSeparator" inherits="Separator" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="VSlider" inherits="Slider" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="VideoPlayer" inherits="Control" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_stream">
- <argument index="0" name="stream" type="Stream">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_stream" qualifiers="const">
- <return type="Stream">
- </return>
- <description>
- </description>
- </method>
- <method name="play">
- <description>
- </description>
- </method>
- <method name="stop">
- <description>
- </description>
- </method>
- <method name="is_playing" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_paused">
- <argument index="0" name="paused" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_paused" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_volume">
- <argument index="0" name="volume" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_volume" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_volume_db">
- <argument index="0" name="db" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_volume_db" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_stream_name" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_pos" qualifiers="const">
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_autoplay">
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_autoplay" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_expand">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_expand" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="VideoStream" inherits="AudioStreamResampled" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_pending_frame_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="pop_frame">
- <return type="Image">
- </return>
- <description>
- </description>
- </method>
- <method name="peek_frame" qualifiers="const">
- <return type="Image">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="VideoStreamTheora" inherits="VideoStream" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Viewport" inherits="Node" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_rect">
- <argument index="0" name="rect" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_rect" qualifiers="const">
- <return type="Rect2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_visible_rect" qualifiers="const">
- <return type="Rect2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_transparent_background">
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_transparent_background" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_viewport" qualifiers="const">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="VisualInstance" inherits="Spatial" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_base">
- <argument index="0" name="base" type="RID">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="VisualServer" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="texture_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="texture_create_from_image">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="Image">
- </argument>
- <argument index="1" name="arg1" type="int" default="7">
- </argument>
- <description>
- </description>
- </method>
- <method name="texture_set_flags">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="texture_get_flags" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="texture_get_width" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="texture_get_height" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_create">
- <return type="RID">
- </return>
- <argument index="0" name="mode" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_set_mode">
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_get_mode" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="shader" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_set_vertex_code">
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="code" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_get_vertex_code" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="shader" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_set_fragment_code">
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="code" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_get_fragment_code" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="shader" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_set_param">
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="param" type="String">
- </argument>
- <argument index="2" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_get_param" qualifiers="const">
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="param" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_get_param_list" qualifiers="const">
- <return type="StringArray">
- </return>
- <argument index="0" name="shader" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_set_use_world_transform">
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_is_using_world_transform" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="shader" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="material_set_shader">
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_get_shader" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_set_param">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <argument index="2" name="arg2" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_get_param" qualifiers="const">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_set_flag">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_get_flag" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_set_blend_mode">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_get_blend_mode" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_set_line_width">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_get_line_width" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_set_parameter">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_get_parameter" qualifiers="const">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_set_texture">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_get_texture" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_set_texgen_mode">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_get_texgen_mode" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_set_texcoord_mode">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_get_texcoord_mode" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_set_uv_transform">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_get_uv_transform" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="mesh_add_surface">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="int">
- </argument>
- <argument index="3" name="arg3" type="int">
- </argument>
- <argument index="4" name="arg4" type="int" default="-1">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_set_array">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="int">
- </argument>
- <argument index="3" name="arg3" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_get_array" qualifiers="const">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_set_material">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="RID">
- </argument>
- <argument index="3" name="arg3" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_get_material" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_get_array_len" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_get_array_index_len" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_get_format" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_get_primitive_type" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_erase_surface">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_get_surface_count" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="multimesh_set_mesh">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_set_aabb">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="AABB">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_instance_set_transform">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_instance_set_color">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_get_mesh" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_get_aabb" qualifiers="const">
- <return type="AABB">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="AABB">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_instance_get_transform" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_instance_get_color" qualifiers="const">
- <return type="Color">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="poly_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="poly_set_material">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <argument index="2" name="arg2" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="poly_clear">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="particles_set_amount">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_amount" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_emitting">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_is_emitting" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_visibility_aabb">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="AABB">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_visibility_aabb" qualifiers="const">
- <return type="AABB">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_variable">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_variable" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_randomness">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_randomness" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_color_phases">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_color_phases" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_color_phase_pos">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_color_phase_pos" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_color_phase_color">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_color_phase_color" qualifiers="const">
- <return type="Color">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_attractors">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_attractors" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_attractor_pos">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_attractor_pos" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_attractor_strength">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_attractor_strength" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_material">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <argument index="2" name="arg2" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_height_from_velocity">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_has_height_from_velocity" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_create">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_get_type" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_set_color">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_get_color" qualifiers="const">
- <return type="Color">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_set_shadow">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_has_shadow" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_set_volumetric">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_is_volumetric" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_set_projector">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_get_projector" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_set_var">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_get_var" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="skeleton_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="skeleton_resize">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="skeleton_get_bone_count" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="skeleton_bone_set_transform">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="skeleton_bone_get_transform">
- <return type="Transform">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="room_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="room_set_bounds">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Dictionary">
- </argument>
- <description>
- </description>
- </method>
- <method name="room_get_bounds" qualifiers="const">
- <return type="Dictionary">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="portal_set_shape">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Vector2Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_get_shape" qualifiers="const">
- <return type="Vector2Array">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_set_enabled">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_is_enabled" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_set_disable_distance">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_get_disable_distance" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_set_disabled_color">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_get_disabled_color" qualifiers="const">
- <return type="Color">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="camera_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="camera_set_perspective">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <argument index="3" name="arg3" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="camera_set_orthogonal">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <argument index="3" name="arg3" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="camera_set_transform">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="viewport_set_rect">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_get_rect" qualifiers="const">
- <return type="Rect2">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_attach_camera">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID" default="RID()">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_get_attached_camera" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_get_scenario" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_attach_canvas">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_remove_canvas">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="scenario_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="scenario_set_debug">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="scenario_fx_get_effects" qualifiers="const">
- <return type="StringArray">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="scenario_fx_set_active">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <argument index="2" name="arg2" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="scenario_fx_is_active" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="scenario_fx_get_effect_params" qualifiers="const">
- <return type="Array">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="scenario_fx_get_effect_param" qualifiers="const">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <argument index="2" name="arg2" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="scenario_fx_set_effect_param">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <argument index="2" name="arg2" type="String">
- </argument>
- <argument index="3" name="arg3" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="instance_get_base" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_get_base_aabb" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_set_transform">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_get_transform" qualifiers="const">
- <return type="Transform">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_attach_object_instance_ID">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_get_object_instance_ID" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_attach_skeleton">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_get_skeleton" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_set_room">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_get_room" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_set_exterior">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_is_exterior" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instances_cull_aabb" qualifiers="const">
- <return type="Array">
- </return>
- <argument index="0" name="arg0" type="AABB">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instances_cull_ray" qualifiers="const">
- <return type="Array">
- </return>
- <argument index="0" name="arg0" type="Vector3">
- </argument>
- <argument index="1" name="arg1" type="Vector3">
- </argument>
- <argument index="2" name="arg2" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instances_cull_convex" qualifiers="const">
- <return type="Array">
- </return>
- <argument index="0" name="arg0" type="Vector3">
- </argument>
- <argument index="1" name="arg1" type="Vector3">
- </argument>
- <argument index="2" name="arg2" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_geometry_set_visible">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_geometry_is_visible" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_geometry_override_material_param" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_geometry_get_material_param" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="canvas_item_create">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="canvas_item_set_parent">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_get_parent" qualifiers="const">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_set_transform">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Matrix32">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_set_custom_rect">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <argument index="2" name="arg2" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_set_clip">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_set_opacity">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_get_opacity" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_set_self_opacity">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_get_self_opacity" qualifiers="const">
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_add_line">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Vector2">
- </argument>
- <argument index="2" name="arg2" type="Vector2">
- </argument>
- <argument index="3" name="arg3" type="Color">
- </argument>
- <argument index="4" name="arg4" type="real" default="1">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_add_rect">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Rect2">
- </argument>
- <argument index="2" name="arg2" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_add_texture_rect">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Rect2">
- </argument>
- <argument index="2" name="arg2" type="RID">
- </argument>
- <argument index="3" name="arg3" type="bool">
- </argument>
- <argument index="4" name="arg4" type="Color" default="Color(1,1,1,1)">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_add_texture_rect_region">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Rect2">
- </argument>
- <argument index="2" name="arg2" type="RID">
- </argument>
- <argument index="3" name="arg3" type="Rect2">
- </argument>
- <argument index="4" name="arg4" type="Color" default="Color(1,1,1,1)">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_add_style_box">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Rect2">
- </argument>
- <argument index="2" name="arg2" type="RID">
- </argument>
- <argument index="3" name="arg3" type="RealArray">
- </argument>
- <argument index="4" name="arg4" type="Color" default="Color(1,1,1,1)">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_add_circle">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Vector2">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <argument index="3" name="arg3" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_set_canvas_transform">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <argument index="2" name="arg2" type="Matrix32">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_clear">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_raise">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="cursor_set_rotation">
- <argument index="0" name="arg0" type="real">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="cursor_set_texture">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Vector2">
- </argument>
- <argument index="2" name="arg2" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="cursor_set_visible">
- <argument index="0" name="arg0" type="bool">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="cursor_set_pos">
- <argument index="0" name="arg0" type="Vector2">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="make_sphere_mesh">
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_add_surface_from_planes">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="free">
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="NO_INDEX_ARRAY" value="-1">
- </constant>
- <constant name="CUSTOM_ARRAY_SIZE" value="8">
- </constant>
- <constant name="ARRAY_WEIGHTS_SIZE" value="4">
- </constant>
- <constant name="MAX_PARTICLE_COLOR_PHASES" value="4">
- </constant>
- <constant name="MAX_PARTICLE_ATTRACTORS" value="4">
- </constant>
- <constant name="MAX_CURSORS" value="8">
- </constant>
- <constant name="TEXTURE_FLAG_MIPMAPS" value="1">
- </constant>
- <constant name="TEXTURE_FLAG_REPEAT" value="2">
- </constant>
- <constant name="TEXTURE_FLAG_FILTER" value="4">
- </constant>
- <constant name="TEXTURE_FLAG_CUBEMAP" value="8">
- </constant>
- <constant name="TEXTURE_FLAGS_DEFAULT" value="7">
- </constant>
- <constant name="CUBEMAP_LEFT" value="0">
- </constant>
- <constant name="CUBEMAP_RIGHT" value="1">
- </constant>
- <constant name="CUBEMAP_BOTTOM" value="2">
- </constant>
- <constant name="CUBEMAP_TOP" value="3">
- </constant>
- <constant name="CUBEMAP_FRONT" value="4">
- </constant>
- <constant name="CUBEMAP_BACK" value="5">
- </constant>
- <constant name="SHADER_MATERIAL" value="0">
- </constant>
- <constant name="SHADER_POST_PROCESS" value="1">
- </constant>
- <constant name="MATERIAL_FLAG_VISIBLE" value="0">
- </constant>
- <constant name="MATERIAL_FLAG_DOUBLE_SIDED" value="1">
- </constant>
- <constant name="MATERIAL_FLAG_INVERT_FACES" value="2">
- </constant>
- <constant name="MATERIAL_FLAG_UNSHADED" value="3">
- </constant>
- <constant name="MATERIAL_FLAG_ONTOP" value="4">
- </constant>
- <constant name="MATERIAL_FLAG_WIREFRAME" value="5">
- </constant>
- <constant name="MATERIAL_FLAG_BILLBOARD" value="6">
- </constant>
- <constant name="MATERIAL_FLAG_MAX" value="7">
- </constant>
- <constant name="MATERIAL_BLEND_MODE_MIX" value="0">
- </constant>
- <constant name="MATERIAL_BLEND_MODE_ADD" value="1">
- </constant>
- <constant name="MATERIAL_BLEND_MODE_SUB" value="2">
- </constant>
- <constant name="MATERIAL_BLEND_MODE_MUL" value="3">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_DIFFUSE" value="0">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_DETAIL" value="1">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_SPECULAR" value="2">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_EMISSION" value="3">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_SPECULAR_EXP" value="4">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_GLOW" value="5">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_NORMAL" value="6">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_SHADE_PARAM" value="7">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_MAX" value="8">
- </constant>
- <constant name="FIXED_MATERIAL_TEXGEN_SPHERE" value="1">
- </constant>
- <constant name="FIXED_MATERIAL_TEXGEN_SCREEN" value="2">
- </constant>
- <constant name="FIXED_MATERIAL_TEXGEN_SCREENZ" value="3">
- </constant>
- <constant name="FIXED_MATERIAL_TEXGEN_LOCAL_XY" value="0">
- </constant>
- <constant name="FIXED_MATERIAL_TEXCOORD_TEXGEN" value="3">
- </constant>
- <constant name="FIXED_MATERIAL_TEXCOORD_UV" value="0">
- </constant>
- <constant name="FIXED_MATERIAL_TEXCOORD_UV_TRANSFORM" value="1">
- </constant>
- <constant name="FIXED_MATERIAL_TEXCOORD_UV2" value="2">
- </constant>
- <constant name="ARRAY_VERTEX" value="0">
- </constant>
- <constant name="ARRAY_NORMAL" value="1">
- </constant>
- <constant name="ARRAY_TANGENT" value="2">
- </constant>
- <constant name="ARRAY_COLOR" value="3">
- </constant>
- <constant name="ARRAY_TEX_UV" value="4">
- </constant>
- <constant name="ARRAY_BONES" value="6">
- </constant>
- <constant name="ARRAY_WEIGHTS" value="7">
- </constant>
- <constant name="ARRAY_INDEX" value="8">
- </constant>
- <constant name="ARRAY_MAX" value="9">
- </constant>
- <constant name="ARRAY_FORMAT_VERTEX" value="1">
- </constant>
- <constant name="ARRAY_FORMAT_NORMAL" value="2">
- </constant>
- <constant name="ARRAY_FORMAT_TANGENT" value="4">
- </constant>
- <constant name="ARRAY_FORMAT_COLOR" value="8">
- </constant>
- <constant name="ARRAY_FORMAT_TEX_UV" value="16">
- </constant>
- <constant name="ARRAY_FORMAT_BONES" value="64">
- </constant>
- <constant name="ARRAY_FORMAT_WEIGHTS" value="128">
- </constant>
- <constant name="ARRAY_FORMAT_INDEX" value="256">
- </constant>
- <constant name="PRIMITIVE_POINTS" value="0">
- </constant>
- <constant name="PRIMITIVE_LINES" value="1">
- </constant>
- <constant name="PRIMITIVE_LINE_STRIP" value="2">
- </constant>
- <constant name="PRIMITIVE_LINE_LOOP" value="3">
- </constant>
- <constant name="PRIMITIVE_TRIANGLES" value="4">
- </constant>
- <constant name="PRIMITIVE_TRIANGLE_STRIP" value="5">
- </constant>
- <constant name="PRIMITIVE_TRIANGLE_FAN" value="6">
- </constant>
- <constant name="PRIMITIVE_MAX" value="7">
- </constant>
- <constant name="PARTICLE_LIFETIME" value="0">
- </constant>
- <constant name="PARTICLE_SPREAD" value="1">
- </constant>
- <constant name="PARTICLE_GRAVITY" value="2">
- </constant>
- <constant name="PARTICLE_LINEAR_VELOCITY" value="3">
- </constant>
- <constant name="PARTICLE_ANGULAR_VELOCITY" value="4">
- </constant>
- <constant name="PARTICLE_LINEAR_ACCELERATION" value="5">
- </constant>
- <constant name="PARTICLE_RADIAL_ACCELERATION" value="6">
- </constant>
- <constant name="PARTICLE_TANGENTIAL_ACCELERATION" value="7">
- </constant>
- <constant name="PARTICLE_INITIAL_SIZE" value="9">
- </constant>
- <constant name="PARTICLE_FINAL_SIZE" value="10">
- </constant>
- <constant name="PARTICLE_INITIAL_ANGLE" value="11">
- </constant>
- <constant name="PARTICLE_HEIGHT" value="12">
- </constant>
- <constant name="PARTICLE_HEIGHT_SPEED_SCALE" value="13">
- </constant>
- <constant name="PARTICLE_VAR_MAX" value="14">
- </constant>
- <constant name="LIGHT_DIRECTIONAL" value="0">
- </constant>
- <constant name="LIGHT_OMNI" value="1">
- </constant>
- <constant name="LIGHT_SPOT" value="2">
- </constant>
- <constant name="LIGHT_COLOR_AMBIENT" value="0">
- </constant>
- <constant name="LIGHT_COLOR_DIFFUSE" value="1">
- </constant>
- <constant name="LIGHT_COLOR_SPECULAR" value="2">
- </constant>
- <constant name="LIGHT_VAR_SPOT_ATTENUATION" value="0">
- </constant>
- <constant name="LIGHT_VAR_SPOT_ANGLE" value="1">
- </constant>
- <constant name="LIGHT_VAR_RADIUS" value="2">
- </constant>
- <constant name="LIGHT_VAR_ENERGY" value="3">
- </constant>
- <constant name="LIGHT_VAR_ATTENUATION" value="4">
- </constant>
- <constant name="LIGHT_VAR_MAX" value="6">
- </constant>
- <constant name="SCENARIO_DEBUG_DISABLED" value="0">
- </constant>
- <constant name="SCENARIO_DEBUG_WIREFRAME" value="1">
- </constant>
- <constant name="SCENARIO_DEBUG_OVERDRAW" value="2">
- </constant>
- <constant name="INSTANCE_MESH" value="1">
- </constant>
- <constant name="INSTANCE_MULTIMESH" value="2">
- </constant>
- <constant name="INSTANCE_POLY" value="3">
- </constant>
- <constant name="INSTANCE_PARTICLES" value="4">
- </constant>
- <constant name="INSTANCE_LIGHT" value="5">
- </constant>
- <constant name="INSTANCE_ROOM" value="6">
- </constant>
- <constant name="INSTANCE_PORTAL" value="7">
- </constant>
- <constant name="INSTANCE_GEOMETRY_MASK" value="30">
- </constant>
- <constant name="INFO_OBJECTS_IN_FRAME" value="0">
- </constant>
- <constant name="INFO_MATERIAL_CHANGES_IN_FRAME" value="1">
- </constant>
- <constant name="INFO_USAGE_VIDEO_MEM_TOTAL" value="2">
- </constant>
- <constant name="INFO_VIDEO_MEM_USED" value="3">
- </constant>
- <constant name="INFO_TEXTURE_MEM_USED" value="4">
- </constant>
- <constant name="INFO_VERTEX_MEM_USED" value="5">
- </constant>
- </constants>
-</class>
-<class name="WindowDialog" inherits="Popup" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_title">
- <argument index="0" name="title" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_title" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_close_button">
- <return type="TextureButton">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="World" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_space" qualifiers="const">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="get_scenario" qualifiers="const">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="get_sound_space" qualifiers="const">
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-</doc>
diff --git a/doc/examples/physics/script/test_base.sq b/doc/examples/physics/script/test_base.sq
deleted file mode 100644
index 9d5451728f..0000000000
--- a/doc/examples/physics/script/test_base.sq
+++ /dev/null
@@ -1,295 +0,0 @@
-
-class PhysicsTestBase extends MainLoopScripted {
-
-
- bodies=[]
- type_mesh_map={}
- type_shape_map={}
- cameratr=Transform()
-
-
- function body_changed_transform(p_transform, p_velocity, p_angular_velocity,p_sleeping, p_visual_instance) {
-
- VisualServer.instance_set_transform(p_visual_instance,p_transform);
- }
-
-
- function create_body(p_shape, p_body_mode, p_location, p_active=true) {
-
- local mesh_instance = VisualServer.instance_create( type_mesh_map[p_shape] )
- local body = PhysicsServer.body_create(RID(),p_body_mode,!p_active)
- PhysicsServer.body_add_shape(body,type_shape_map[p_shape])
-
- local query = PhysicsServer.query_create(this,"body_changed_transform",mesh_instance)
- PhysicsServer.query_body_state(query, body)
-
- PhysicsServer.body_set_state( body, PhysicsServer.BODY_STATE_TRANSFORM, p_location )
- bodies.append( body )
- return body
-
- }
-
-
- function create_static_plane(p_plane) {
-
- local plane_shape = PhysicsServer.shape_create(PhysicsServer.SHAPE_PLANE)
- PhysicsServer.shape_set_data( plane_shape, p_plane );
-
- local b = PhysicsServer.body_create(RID(), PhysicsServer.BODY_MODE_STATIC );
- PhysicsServer.body_add_shape(b, plane_shape);
- return b;
- }
-
- function configure_body( p_body, p_mass, p_friction, p_bounce) {
-
- PhysicsServer.body_set_param( p_body, PhysicsServer.BODY_PARAM_MASS, p_mass );
- PhysicsServer.body_set_param( p_body, PhysicsServer.BODY_PARAM_FRICTION, p_friction );
- PhysicsServer.body_set_param( p_body, PhysicsServer.BODY_PARAM_BOUNCE, p_bounce );
-
- }
-
- function init_shapes() {
-
-
- /* SPHERE SHAPE */
- local sphere_mesh = VisualServer.make_sphere_mesh(10,20,1.0);
- local sphere_material = VisualServer.fixed_material_create();
- //VisualServer.material_set_flag( sphere_material, VisualServer.MATERIAL_FLAG_WIREFRAME, true );
- VisualServer.fixed_material_set_parameter( sphere_material, VisualServer.FIXED_MATERIAL_PARAM_DIFFUSE, Color(0.7,0.8,3.0) );
- VisualServer.mesh_surface_set_material( sphere_mesh, 0, sphere_material );
- type_mesh_map[PhysicsServer.SHAPE_SPHERE] <- sphere_mesh;
-
- local sphere_shape=PhysicsServer.shape_create(PhysicsServer.SHAPE_SPHERE);
- PhysicsServer.shape_set_data( sphere_shape, 1.0 );
- type_shape_map[PhysicsServer.SHAPE_SPHERE] <- sphere_shape;
-
- /* BOX SHAPE */
-
- local box_planes = GeometryUtils.build_box_planes(Vector3(0.5,0.5,0.5));
- local box_material = VisualServer.fixed_material_create();
- VisualServer.fixed_material_set_parameter( box_material, VisualServer.FIXED_MATERIAL_PARAM_DIFFUSE, Color(1.0,0.2,0.2) );
- local box_mesh = VisualServer.mesh_create();
-
- VisualServer.mesh_add_surface_from_planes(box_mesh,box_planes);
- VisualServer.mesh_surface_set_material( box_mesh, 0, box_material );
- type_mesh_map[PhysicsServer.SHAPE_BOX]<- box_mesh;
-
- local box_shape=PhysicsServer.shape_create(PhysicsServer.SHAPE_BOX);
- PhysicsServer.shape_set_data( box_shape, Vector3(0.5,0.5,0.5) );
- type_shape_map[PhysicsServer.SHAPE_BOX]<- box_shape;
-
- /* CYLINDER SHAPE */
-
- local cylinder_planes = GeometryUtils.build_cylinder_planes(0.5,1,12
- ,Vector3.AXIS_Z);
- local cylinder_material = VisualServer.fixed_material_create();
- VisualServer.fixed_material_set_parameter( cylinder_material, VisualServer.FIXED_MATERIAL_PARAM_DIFFUSE, Color(0.3,0.4,1.0) );
- local cylinder_mesh = VisualServer.mesh_create();
-
- VisualServer.mesh_add_surface_from_planes(cylinder_mesh,cylinder_planes);
- VisualServer.mesh_surface_set_material( cylinder_mesh, 0, cylinder_material );
- type_mesh_map[PhysicsServer.SHAPE_CYLINDER]<- cylinder_mesh;
-
- local cylinder_shape=PhysicsServer.shape_create(PhysicsServer.SHAPE_CYLINDER);
- local cylinder_params={}
- cylinder_params["radius"]<- 0.5;
- cylinder_params["height"]<- 2;
- PhysicsServer.shape_set_data( cylinder_shape, cylinder_params );
- type_shape_map[PhysicsServer.SHAPE_CYLINDER]<- cylinder_shape;
-
- /* CAPSULE SHAPE */
-
- local capsule_planes = GeometryUtils.build_capsule_planes(0.5,0.7,12,Vector3.AXIS_Z);
- local capsule_material = VisualServer.fixed_material_create();
- VisualServer.fixed_material_set_parameter( capsule_material, VisualServer.FIXED_MATERIAL_PARAM_DIFFUSE, Color(0.3,0.4,1.0) );
-
- local capsule_mesh = VisualServer.mesh_create();
-
- VisualServer.mesh_add_surface_from_planes(capsule_mesh,capsule_planes);
- VisualServer.mesh_surface_set_material( capsule_mesh, 0, capsule_material );
- type_mesh_map[PhysicsServer.SHAPE_CAPSULE]<-capsule_mesh;
-
- local capsule_shape=PhysicsServer.shape_create(PhysicsServer.SHAPE_CAPSULE);
- local capsule_params={}
- capsule_params["radius"]<- 0.5;
- capsule_params["height"]<- 1.4;
- PhysicsServer.shape_set_data( capsule_shape, capsule_params );
- type_shape_map[PhysicsServer.SHAPE_CAPSULE]<- capsule_shape;
-
- /* CONVEX SHAPE */
-
- local convex_planes = GeometryUtils.build_cylinder_planes(0.5,0.7,5,Vector3.AXIS_Z);
- local convex_material = VisualServer.fixed_material_create();
- VisualServer.fixed_material_set_parameter( convex_material, VisualServer.FIXED_MATERIAL_PARAM_DIFFUSE, Color(0.8,0.2,0.9));
-
- local convex_mesh = VisualServer.mesh_create();
- VisualServer.mesh_add_surface_from_planes(convex_mesh,convex_planes);
- VisualServer.mesh_surface_set_material( convex_mesh, 0, convex_material );
- type_mesh_map[PhysicsServer.SHAPE_CONVEX_POLYGON]<- convex_mesh;
-
- local convex_shape=PhysicsServer.shape_create(PhysicsServer.SHAPE_CONVEX_POLYGON);
- PhysicsServer.shape_set_data( convex_shape, convex_planes );
- type_shape_map[PhysicsServer.SHAPE_CONVEX_POLYGON]<- convex_shape;
-
- }
-
- function make_trimesh(p_faces,p_xform=Transform()) {
-
- local trimesh_shape = PhysicsServer.shape_create(PhysicsServer.SHAPE_CONCAVE_POLYGON);
- PhysicsServer.shape_set_data(trimesh_shape, p_faces);
- p_faces=PhysicsServer.shape_get_data(trimesh_shape); // optimized one
- normals=[]
-
- for (i=0;i<p_faces.length()/3;i++) {
-
- p=Plane( p_faces[i*3+0],p_faces[i*3+1], p_faces[i*3+2] );
- normals.append(p.normal);
- normals.append(p.normal);
- normals.append(p.normal);
- }
-
- local trimesh_mesh = VisualServer.mesh_create();
- VisualServer.mesh_add_surface(trimesh_mesh, VS::PRIMITIVE_TRIANGLES, VS::ARRAY_FORMAT_VERTEX|VS::ARRAY_FORMAT_NORMAL, p_faces.length() );
- VisualServer.mesh_surface_set_array(trimesh_mesh,0,VS::ARRAY_VERTEX, p_faces );
- VisualServer.mesh_surface_set_array(trimesh_mesh,0,VS::ARRAY_NORMAL, normals );
- local trimesh_mat = VisualServer.fixed_material_create();
- VisualServer.fixed_material_set_parameter( trimesh_mat, VisualServer.FIXED_MATERIAL_PARAM_DIFFUSE, Color(1.0,0.5,0.8));
- //VisualServer.material_set_flag( trimesh_mat, VisualServer.MATERIAL_FLAG_UNSHADED,true);
- VisualServer.mesh_surface_set_material( trimesh_mesh, 0, trimesh_mat );
-
- local triins = VisualServer.instance_create(trimesh_mesh);
-
-
- local tribody = PhysicsServer.body_create(RID(), PhysicsServer.BODY_MODE_STATIC);
- PhysicsServer.body_add_shape(tribody, trimesh_shape);
- tritrans = p_xform;
- PhysicsServer.body_set_state( tribody, PhysicsServer.BODY_STATE_TRANSFORM, tritrans );
- VisualServer.instance_set_transform( triins, tritrans );
- //RID trimesh_material = VisualServer.fixed_material_create();
- //VisualServer.material_generate( trimesh_material, Color(0.2,0.4,0.6) );
- //VisualServer.mesh_surface_set_material( trimesh_mesh, 0, trimesh_material );
-
- }
-
- function make_grid(p_width,p_height,p_cellsize,p_cellheight,p_xform=Transform()) {
-
- local grid = []
-
- for (local i =0;i<p_width;i++) {
-
- local row = []
-
- for (local j=0;j<p_height;j++) {
-
- local val = 1.0+Math.random(-p_cellheight, p_cellheight );
- row.append(val)
- }
- grid.append(row)
- }
-
- local faces=[]
-
- for (local i =1;i<p_width;i++) {
-
- for (local j=1;j<p_height;j++) {
-
- function MAKE_VERTEX(m_x,m_z) {
- local v= Vector3( (m_x-p_width/2)*p_cellsize, grid[m_x][m_z], (m_z-p_height/2)*p_cellsize )
- faces.push_back(v)
- }
-
-
- MAKE_VERTEX(i,j-1)
- MAKE_VERTEX(i,j)
- MAKE_VERTEX(i-1,j)
-
- MAKE_VERTEX(i-1,j-1)
- MAKE_VERTEX(i,j-1)
- MAKE_VERTEX(i-1,j)
-
- }
- }
-
- make_trimesh(faces,p_xform);
- }
-
- quit=false
-
- transform = Transform()
- camera=RID()
-
- function init_internal() {}
- function iteration_internal(time) {}
-//public
-
-
- function input_event(p_event) {
-
-
- }
-
- function request_quit() {
-
- quit=true;
- }
-
- function init() {
-
- init_shapes();
-
-
- /* LIGHT */
- local lightaux = VisualServer.light_create( VisualServer.LIGHT_DIRECTIONAL );
- //VisualServer.light_set_color( lightaux, VisualServer.LIGHT_COLOR_AMBIENT, Color(0.0,0.0,0.0) );
- VisualServer.light_set_shadow(lightaux,true);
- local light = VisualServer.instance_create( lightaux );
- local t=Transform()
- t.rotate(Vector3(1.0,0,0),0.6);
- VisualServer.instance_set_transform(light,t);
-
-
- /* CAMERA */
-
- camera = VisualServer.camera_create();
- local viewport = VisualServer.viewport_create();
- VisualServer.viewport_attach_camera( viewport, camera );
- VisualServer.viewport_set_parent(viewport, RID() );
-
- VisualServer.camera_set_perspective(camera,60,0.1,20.0);
- cameratr=Transform( Matrix3(), Vector3(0,2,8))
- VisualServer.camera_set_transform(camera,cameratr);
-
- quit=false;
-
- init_internal()
-
- }
-
-
- function iteration(p_time) {
-
- // VisualServer.camera_set_transform(camera,cameratr);
- iteration_internal(p_time)
-
- return quit;
- }
-
- function idle(p_time) {
-
- return quit;
- }
-
-
- function finish() {
-
- }
-
-
- constructor() {
- MainLoopScripted.constructor();
- }
-
-}
-
-
-return PhysicsTestBase;
diff --git a/doc/examples/physics/script/test_fall.sq b/doc/examples/physics/script/test_fall.sq
deleted file mode 100644
index 79526da8b4..0000000000
--- a/doc/examples/physics/script/test_fall.sq
+++ /dev/null
@@ -1,42 +0,0 @@
-
-include("test_base.sq")
-
-class TestFall extends PhysicsTestBase {
-
-
- fall_elements=10
-
- function init_internal() {
-
- for (local i=0;i<10;i++) {
-
- local shape_idx=[
- PhysicsServer.SHAPE_SPHERE,
- PhysicsServer.SHAPE_BOX,
- PhysicsServer.SHAPE_CAPSULE,
- PhysicsServer.SHAPE_CYLINDER,
- PhysicsServer.SHAPE_CONVEX_POLYGON
- ];
-
- local stype=shape_idx[i%5];
-// stype=PhysicsServer.SHAPE_SPHERE;
-
- local t=Transform()
- t.set_origin(Vector3(-0.7+0.0*i,3.5+4.1*i,0))
- t.rotate_basis(Vector3(1,0,0),Math.PI/4*i)
-
- local b = create_body(stype,PhysicsServer.BODY_MODE_RIGID,t);
-
- }
-
- create_static_plane( Plane( Vector3(0,1,0), -1) );
-
- }
-
- constructor() {
- PhysicsTestBase.constructor()
- }
-}
-
-
-return TestFall
diff --git a/doc/gdscript.lyx b/doc/gdscript.lyx
deleted file mode 100644
index a4b2230121..0000000000
--- a/doc/gdscript.lyx
+++ /dev/null
@@ -1,2531 +0,0 @@
-#LyX 2.0 created this file. For more info see http://www.lyx.org/
-\lyxformat 413
-\begin_document
-\begin_header
-\textclass article
-\use_default_options true
-\maintain_unincluded_children false
-\language english
-\language_package default
-\inputencoding auto
-\fontencoding global
-\font_roman default
-\font_sans default
-\font_typewriter default
-\font_default_family default
-\use_non_tex_fonts false
-\font_sc false
-\font_osf false
-\font_sf_scale 100
-\font_tt_scale 100
-
-\graphics default
-\default_output_format default
-\output_sync 0
-\bibtex_command default
-\index_command default
-\paperfontsize default
-\use_hyperref false
-\papersize default
-\use_geometry false
-\use_amsmath 1
-\use_esint 1
-\use_mhchem 1
-\use_mathdots 1
-\cite_engine basic
-\use_bibtopic false
-\use_indices false
-\paperorientation portrait
-\suppress_date false
-\use_refstyle 0
-\index Index
-\shortcut idx
-\color #008000
-\end_index
-\secnumdepth 3
-\tocdepth 3
-\paragraph_separation indent
-\paragraph_indentation default
-\quotes_language english
-\papercolumns 1
-\papersides 1
-\paperpagestyle default
-\tracking_changes false
-\output_changes false
-\html_math_output 0
-\html_css_as_file 0
-\html_be_strict false
-\end_header
-
-\begin_body
-
-\begin_layout Title
-GD Scripting Language (GDScript)
-\end_layout
-
-\begin_layout Section
-Introduction
-\end_layout
-
-\begin_layout Standard
-GDScript is a high level, dynamically typed programming language used to
- create content.
- It uses a syntax that is very similar to the Python language (blocks are
- indent-based) and it's goal is to be very optimal and tigthly integrated
- with the engine, allowing great flexibility for content creation and integratio
-n.
-
-\end_layout
-
-\begin_layout Section
-Example
-\end_layout
-
-\begin_layout Standard
-Some people can learn better by just taking a look at the syntax, so here's
- a simple example of how it looks.
-
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-#a file is a class!
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-#inheritance
-\end_layout
-
-\begin_layout Plain Layout
-
-extends BaseClass
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-#member variables
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-var a=5
-\end_layout
-
-\begin_layout Plain Layout
-
-var s="Hello"
-\end_layout
-
-\begin_layout Plain Layout
-
-var arr=[1,2,3]
-\end_layout
-
-\begin_layout Plain Layout
-
-var dict={"key":"value", 2:3}
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-#constants
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-const answer=42
-\end_layout
-
-\begin_layout Plain Layout
-
-const thename="Charly"
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-#built-in vector types
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-var v2 = Vector2(1,2)
-\end_layout
-
-\begin_layout Plain Layout
-
-var v3 = Vector3(1,2,3)
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-#function
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-func some_function(param1,param2):
-\end_layout
-
-\begin_layout Plain Layout
-
- var local_var=5
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
- if param1 < local_var:
-\end_layout
-
-\begin_layout Plain Layout
-
- print(param1)
-\end_layout
-
-\begin_layout Plain Layout
-
- elif param2 > 5:
-\end_layout
-
-\begin_layout Plain Layout
-
- print(param2)
-\end_layout
-
-\begin_layout Plain Layout
-
- else:
-\end_layout
-
-\begin_layout Plain Layout
-
- print("fail!")
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
- for i in range(20):
-\end_layout
-
-\begin_layout Plain Layout
-
- print(i)
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
- while(param2!=0):
-\end_layout
-
-\begin_layout Plain Layout
-
- param2-=1
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
- var local_var2 = param1+3
-\end_layout
-
-\begin_layout Plain Layout
-
- return local_var2
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-#subclass
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-class Something:
-\end_layout
-
-\begin_layout Plain Layout
-
- var a=10
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-#constructor
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-func _init():
-\end_layout
-
-\begin_layout Plain Layout
-
- print("constructed!")
-\end_layout
-
-\begin_layout Plain Layout
-
- var lv = Something.new()
-\end_layout
-
-\begin_layout Plain Layout
-
- print(lv.a)
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Language
-\end_layout
-
-\begin_layout Subsection
-Identifiers
-\end_layout
-
-\begin_layout Standard
-Any string that restricts itself to alphabetic characters ('a' to 'z' and
- 'A' to 'Z'), digits ('0' to '9') and '_' qualifies as an identifier.
- As an extra restriction, identifiers must not begin with a digit.
- Identifiers are case-sensitive ('foo' is different to 'FOO').
-\end_layout
-
-\begin_layout Subsection
-Keywords
-\end_layout
-
-\begin_layout Standard
-The following is the list of keywords supported by the language.
- Since keywords are reserved words (tokens), they can't be used as identifiers.
-\end_layout
-
-\begin_layout Subsection
-Operators
-\end_layout
-
-\begin_layout Standard
-The following is the list of supported operators and their precedence (TODO,
- change since this was made to reflect python operators)
-\end_layout
-
-\begin_layout Standard
-\begin_inset Tabular
-<lyxtabular version="3" rows="18" columns="2">
-<features tabularvalignment="middle">
-<column alignment="center" valignment="top" width="0">
-<column alignment="center" valignment="top" width="0">
-<row>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Operator
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Note
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-x[index]
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Subscription, Highest Priority
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-x.attribute
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Attribute Reference
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-extends
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Instance Type Checker
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-~
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Bitwise NOT
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
--x
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Negative
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-* / %
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Mult / Div / Remainder
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-+ -
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Addition / Substraction
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-<< >>
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Bit Shifting
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-&
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Bitwise AND
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-^
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Bitwise XOR
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-|
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Bitwise OR
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-< > == != >= <=
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Comparisons
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-in
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Content Test
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-! not
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Boolean NOT
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-and &&
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Boolean AND
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-or ||
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Boolean OR
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-= += -= *= /= ^= &= |=
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Assignment, Lowest Priority
-\end_layout
-
-\end_inset
-</cell>
-</row>
-</lyxtabular>
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Literals
-\end_layout
-
-\begin_layout Standard
-\begin_inset Tabular
-<lyxtabular version="3" rows="6" columns="2">
-<features tabularvalignment="middle">
-<column alignment="center" valignment="top" width="0">
-<column alignment="center" valignment="top" width="0">
-<row>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Literal
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Name
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-45
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Base 10 Integer
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-0x8F51
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Base 16 (hex) Integer
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-3.14, 58.1e-10
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Floating Point Number (real)
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-'Hello',
-\begin_inset Quotes eld
-\end_inset
-
-Hi
-\begin_inset Quotes erd
-\end_inset
-
-
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Strings
-\end_layout
-
-\end_inset
-</cell>
-</row>
-<row>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-@'Hello', @'Hi'
-\end_layout
-
-\end_inset
-</cell>
-<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
-\begin_inset Text
-
-\begin_layout Plain Layout
-Internationalized Strings
-\end_layout
-
-\end_inset
-</cell>
-</row>
-</lyxtabular>
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Comments
-\end_layout
-
-\begin_layout Standard
-Anything from a '#' to the end of the line is ignored and is considered
- a comment.
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-lstparams "language=Python"
-inline false
-status open
-
-\begin_layout Plain Layout
-
-# This is a comment
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Built-in Types
-\end_layout
-
-\begin_layout Subsection
-Basic Bult-In Types
-\end_layout
-
-\begin_layout Standard
-A variable in GDScript can be assigned many of several built-in types.
-
-\end_layout
-
-\begin_layout Subsubsection
-null
-\end_layout
-
-\begin_layout Standard
-'null' is a data type that contains no information, nothing assigned, and
- it's just empy.
- It can only be set to one value: 'null'.
-\end_layout
-
-\begin_layout Subsubsection
-bool
-\end_layout
-
-\begin_layout Standard
-Boolean data type, can only contain 'true' or 'false'.
-\end_layout
-
-\begin_layout Subsubsection
-int
-\end_layout
-
-\begin_layout Standard
-Integer data type, can only contain integer numbers, negative and positive.
-\end_layout
-
-\begin_layout Subsubsection
-float
-\end_layout
-
-\begin_layout Standard
-contains a floating point value (real).
-\end_layout
-
-\begin_layout Subsubsection
-String
-\end_layout
-
-\begin_layout Standard
-Sequence of characters in unicode format.
- Strings can contain the standard C escape sequences.
-\end_layout
-
-\begin_layout Subsection
-Vector Built-In Types
-\end_layout
-
-\begin_layout Subsubsection
-Vector2/Size2
-\end_layout
-
-\begin_layout Standard
-2D vector type, containing x and y fields.
- Can alternatively access fields as width and height for readability.
- Can also be accessed as array.
-\end_layout
-
-\begin_layout Subsubsection
-Rect2
-\end_layout
-
-\begin_layout Standard
-2D Rectangle type.
- Contains 2 vectors fields,
-\begin_inset Quotes eld
-\end_inset
-
-pos
-\begin_inset Quotes erd
-\end_inset
-
- and size
-\begin_inset Quotes erd
-\end_inset
-
-.
- Alternatively contains an
-\begin_inset Quotes eld
-\end_inset
-
-end
-\begin_inset Quotes erd
-\end_inset
-
- field which is
-\begin_inset Quotes eld
-\end_inset
-
-pos+size
-\begin_inset Quotes erd
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Subsubsection
-Vector3
-\end_layout
-
-\begin_layout Standard
-3D vector type.
- Contains x, y and z fields.
- Can also be accessed as array.
-\end_layout
-
-\begin_layout Subsubsection
-Matrix32
-\end_layout
-
-\begin_layout Standard
-3x2 matrix used for 2D transforms.
-\end_layout
-
-\begin_layout Subsubsection
-Plane
-\end_layout
-
-\begin_layout Standard
-3D Plane type in normalized form.
- Contains a
-\begin_inset Quotes eld
-\end_inset
-
-normal
-\begin_inset Quotes erd
-\end_inset
-
- vector field and a
-\begin_inset Quotes eld
-\end_inset
-
-d
-\begin_inset Quotes erd
-\end_inset
-
- scalar distance.
-\end_layout
-
-\begin_layout Subsubsection
-Quat
-\end_layout
-
-\begin_layout Standard
-Quaternion, datatype used for representing a 3D rotation.
- It's useful for interpolating rotations.
-\end_layout
-
-\begin_layout Subsubsection
-AABB/Box3
-\end_layout
-
-\begin_layout Standard
-Axis Aligned bounding box (or alternatively, 3D box).
- Contains 2 vectors fields,
-\begin_inset Quotes eld
-\end_inset
-
-pos
-\begin_inset Quotes erd
-\end_inset
-
- and size
-\begin_inset Quotes erd
-\end_inset
-
-.
- Alternatively contains an
-\begin_inset Quotes eld
-\end_inset
-
-end
-\begin_inset Quotes erd
-\end_inset
-
- field which is
-\begin_inset Quotes eld
-\end_inset
-
-pos+size
-\begin_inset Quotes erd
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Subsubsection
-Matrix3
-\end_layout
-
-\begin_layout Standard
-3x3 matrix used for 3D rotation and scale.
- Contains 3 vector fields x,y and z.
- Can also be accessed as array of 3D vectors.
-\end_layout
-
-\begin_layout Subsubsection
-Transform
-\end_layout
-
-\begin_layout Standard
-3D Transform, contains a Matrix3 field
-\begin_inset Quotes eld
-\end_inset
-
-basis
-\begin_inset Quotes erd
-\end_inset
-
- and a Vector3 field
-\begin_inset Quotes eld
-\end_inset
-
-origin
-\begin_inset Quotes erd
-\end_inset
-
-.
-\end_layout
-
-\begin_layout Subsection
-Engine Built-In Types
-\end_layout
-
-\begin_layout Subsubsection
-Color
-\end_layout
-
-\begin_layout Standard
-Color datatype, contains r,g,b,a fields.
- Can also be accessed as h,s,v for hue/saturation/value.
-\end_layout
-
-\begin_layout Subsubsection
-Image
-\end_layout
-
-\begin_layout Standard
-Contains a 2D Image of custom format and allows direct access to the pixels.
-\end_layout
-
-\begin_layout Subsubsection
-NodePath
-\end_layout
-
-\begin_layout Standard
-Compiled path to a node, used mainly in the scene system.
- Can be easily asigned from/to a String.
-\end_layout
-
-\begin_layout Subsubsection
-RID
-\end_layout
-
-\begin_layout Standard
-Resource ID (RID).
- Servers use generic RIDs to reference opaque data.
-\end_layout
-
-\begin_layout Subsubsection
-Object
-\end_layout
-
-\begin_layout Standard
-Base class for anything not a built-in type.
-
-\end_layout
-
-\begin_layout Subsubsection
-InputEvent
-\end_layout
-
-\begin_layout Standard
-Events from input devices are contained in very compact form in InputEvent
- objects.
- Due to fact they can be received in high amounts from frame to frame, they
- are optimized in their own datatype.
-
-\end_layout
-
-\begin_layout Subsection
-Container Built-In Types
-\end_layout
-
-\begin_layout Subsubsection
-Array
-\end_layout
-
-\begin_layout Standard
-Generic sequence of objects.
- It's size can be changed to anything and starts from index 0.
-
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-var arr=[]
-\end_layout
-
-\begin_layout Plain Layout
-
-arr=[1,2,3]
-\end_layout
-
-\begin_layout Plain Layout
-
-arr[0]="Hi!"
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Arrays are allocated linearly in memory, so they are fast, but very large
- arrays (more than tens of thousands of elements) may cause fragmentation.
- There are specialized arrays for some built-in datatypes which do not suffer
- from this and use much less memory.
-\end_layout
-
-\begin_layout Subsubsection
-Dictionary
-\end_layout
-
-\begin_layout Standard
-Associative container which contains values referenced by unique keys.
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-var dict={4:5, "a key":"a value", 28:[1,2,3]}
-\end_layout
-
-\begin_layout Plain Layout
-
-dict["Hi!"]=0
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsubsection
-ByteArray
-\end_layout
-
-\begin_layout Standard
-Array of bytes.
- Can only contains bytes (integers from 0 to 255).
- Optimized for memory usage, can't fragment the memory.
-\end_layout
-
-\begin_layout Subsubsection
-IntArray
-\end_layout
-
-\begin_layout Standard
-Array of integers.
- Can only contain integers.
- Optimized for memory usage, can't fragment the memory.
-\end_layout
-
-\begin_layout Subsubsection
-FloatArray
-\end_layout
-
-\begin_layout Standard
-Array of floats, can only contain floats.
- Optimized for memory usage, can't fragment the memory.
-\end_layout
-
-\begin_layout Subsubsection
-StringArray
-\end_layout
-
-\begin_layout Standard
-Array of strings, can only contain strings.
- Optimized for memory usage, can't fragment the memory.
-\end_layout
-
-\begin_layout Subsubsection
-Vector2Array
-\end_layout
-
-\begin_layout Standard
-Array of Vector2, can only contain 2D Vectors.
- Optimized for memory usage, can't fragment the memory.
-\end_layout
-
-\begin_layout Subsubsection
-Vector3Array
-\end_layout
-
-\begin_layout Standard
-Array of Vector3, can only contain 3D Vectors.
- Optimized for memory usage, can't fragment the memory.
-\end_layout
-
-\begin_layout Subsubsection
-ColorArray
-\end_layout
-
-\begin_layout Standard
-Array of Color, can only contains colors.
- Optimized for memory usage, can't fragment the memory.
-\end_layout
-
-\begin_layout Section
-Data
-\end_layout
-
-\begin_layout Subsection
-Variables
-\end_layout
-
-\begin_layout Standard
-Variables can exist as class members or local to functions.
- They are created with the
-\begin_inset Quotes eld
-\end_inset
-
-var
-\begin_inset Quotes erd
-\end_inset
-
- keyword and may be, optionally, be assigned a value upon initialization.
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-var a # datatype is null by default
-\end_layout
-
-\begin_layout Plain Layout
-
-var b = 5
-\end_layout
-
-\begin_layout Plain Layout
-
-var c = 3.8
-\end_layout
-
-\begin_layout Plain Layout
-
-var d = b+c # variables are always initialized in order
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Constants
-\end_layout
-
-\begin_layout Standard
-Constants are similar to variables, but must be constants or constant expression
-s and must be assigned on initialization.
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-const a = 5
-\end_layout
-
-\begin_layout Plain Layout
-
-const b = Vector2(20,20)
-\end_layout
-
-\begin_layout Plain Layout
-
-const c = 10+20 # constant expression
-\end_layout
-
-\begin_layout Plain Layout
-
-const d = Vector2(20,30).x # constant expression: 20
-\end_layout
-
-\begin_layout Plain Layout
-
-const e = [1,2,3,4][0] # constant expression: 1
-\end_layout
-
-\begin_layout Plain Layout
-
-const f = sin(20) # sin() can be used in constant expression
-\end_layout
-
-\begin_layout Plain Layout
-
-const g = x+20 # invalid, not a constant expression!
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Functions
-\end_layout
-
-\begin_layout Standard
-Functions always belong to a class.
- The scope priority for variable look-up is: local -> class member -> global.
-
-\begin_inset Quotes eld
-\end_inset
-
-self
-\begin_inset Quotes erd
-\end_inset
-
- is provided as an option for accessing class members but is not required
- always (and must
-\emph on
-not
-\emph default
- be defined as first parameter, like in Python).
- For performance reasons, functions are not considered class members, so
- they can't be referenced directly.
- A function can return at any point.
- The default return value is null.
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-func myfunction(a,b):
-\end_layout
-
-\begin_layout Plain Layout
-
- print(a)
-\end_layout
-
-\begin_layout Plain Layout
-
- print(b)
-\end_layout
-
-\begin_layout Plain Layout
-
- return a+b # return is optional, otherwise null is returned
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsubsection
-Statements and Control Flow
-\end_layout
-
-\begin_layout Standard
-Statements are standard, and can be assignments, function calls, control
- flow structures, etc (see below).
-
-\begin_inset Quotes eld
-\end_inset
-
-;
-\begin_inset Quotes erd
-\end_inset
-
- as separator is entirely optional.
-\end_layout
-
-\begin_layout Subsubsection
-if/else/elif
-\end_layout
-
-\begin_layout Standard
-Simple conditions are created by using the
-\emph on
-if/else/elif
-\emph default
- syntax.
- Parenthesis around statements is allowed but not requiered.
- Given the nature of the tab-based indentation, elif can be used instead
- of else:/if: to mantain a level of indentation.
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-if [expression]:
-\end_layout
-
-\begin_layout Plain Layout
-
- statement(s)
-\end_layout
-
-\begin_layout Plain Layout
-
-elif [expression]:
-\end_layout
-
-\begin_layout Plain Layout
-
- statement(s)
-\end_layout
-
-\begin_layout Plain Layout
-
-else:
-\end_layout
-
-\begin_layout Plain Layout
-
- statement(s)
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsubsection
-while
-\end_layout
-
-\begin_layout Standard
-Simple loops are created by using
-\emph on
-while
-\emph default
- syntax.
- Loops can be broken using
-\emph on
-break
-\emph default
-, or continued using
-\emph on
-continue
-\emph default
-:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-while [expression]:
-\end_layout
-
-\begin_layout Plain Layout
-
- statement(s)
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsubsection
-for
-\end_layout
-
-\begin_layout Standard
-To iterate a range, array or table a
-\emph on
-for
-\emph default
- loop is used.
- For loops store the index in the loop variable on each iteration.
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-for i in [0,1,2]:
-\end_layout
-
-\begin_layout Plain Layout
-
- statement # loop iterates 3 times, i being 0,1 and 2
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-var dict = {"a":0, "b":1, "c": 2}
-\end_layout
-
-\begin_layout Plain Layout
-
-for i in dict:
-\end_layout
-
-\begin_layout Plain Layout
-
- print(dict[i]) # loop iterates the keys, i being "a","b" and c".
- It prints 0, 1 and 2.
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-for i in range(3):
-\end_layout
-
-\begin_layout Plain Layout
-
- statement # similar to [0,1,2] but does not allocate an array
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-for i in range(1,3):
-\end_layout
-
-\begin_layout Plain Layout
-
- statement # similar to [1,2] but does not allocate an array
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-for i in range(2,8,2):
-\end_layout
-
-\begin_layout Plain Layout
-
- statement # similar to [2,4,6] but does not allocate an array
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Classes
-\end_layout
-
-\begin_layout Standard
-By default, the body of a script file is an unnamed class, and it can only
- be referenced externally as a resource or file.
- Class syntax is meant to be very compact and can only contain member variables
- or functions.
- Static functions are allowed, but not static members (in the spirit of
- thread safety, since scripts can be initialized in separate threads without
- the user knowing).
- In the same way, member variables (including arrays and dictionaries) are
- initialized every time an instance is created.
-
-\end_layout
-
-\begin_layout Subsection
-Class File Example
-\end_layout
-
-\begin_layout Standard
-Example of a class file, imagine it being stored in a file like myclass.gd.
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-var a=5
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-function print_value_of_a():
-\end_layout
-
-\begin_layout Plain Layout
-
- print(a)
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Inheritance
-\end_layout
-
-\begin_layout Standard
-A class-file can inherit from a global class, another file or a subclass
- inside another file.
- Multiple inheritance is not allowed.
- The
-\begin_inset Quotes eld
-\end_inset
-
-extends
-\begin_inset Quotes erd
-\end_inset
-
- syntax is used:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-# extend from some class (global)
-\end_layout
-
-\begin_layout Plain Layout
-
-extends SomeClass
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-# optionally, extend from another file
-\end_layout
-
-\begin_layout Plain Layout
-
-extends "somefile.gd"
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-# extend from a subclass in another file
-\end_layout
-
-\begin_layout Plain Layout
-
-extends "somefile.gd".Subclass
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Inheritance Testing
-\end_layout
-
-\begin_layout Standard
-It is possible to check if an instance inherits from a given class.
- For this the
-\begin_inset Quotes eld
-\end_inset
-
-extends
-\begin_inset Quotes erd
-\end_inset
-
- keyword can be used as an operator instead:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-static var enemy_class = preload("enemy.gd") # cache the enemy class
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-[..]
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-if ( entity extends enemy_class ):
-\end_layout
-
-\begin_layout Plain Layout
-
- entity.apply_damage()
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Constructor
-\end_layout
-
-\begin_layout Standard
-A class can have an optional constructor, a function named
-\begin_inset Quotes eld
-\end_inset
-
-_init
-\begin_inset Quotes erd
-\end_inset
-
- that is called when the class is instanced.
-\end_layout
-
-\begin_layout Subsection
-Sub Classes
-\end_layout
-
-\begin_layout Standard
-A class file can have subclasses.
- Syntax should be straightforward:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-class SomeSubClass:
-\end_layout
-
-\begin_layout Plain Layout
-
- var a=5
-\end_layout
-
-\begin_layout Plain Layout
-
- function print_value_of_a():
-\end_layout
-
-\begin_layout Plain Layout
-
- print(a)
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-function _init():
-\end_layout
-
-\begin_layout Plain Layout
-
- var sc = SomeSubClass.new() #instance by calling built-in new
-\end_layout
-
-\begin_layout Plain Layout
-
- sc.print_value_of_a()
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Classes as Objects
-\end_layout
-
-\begin_layout Standard
-It may be desired at some point to load a class from a file and then instance
- it.
- Since the global scope does not exist, classes must be loaded as a resource.
- Instancing is done by calling the
-\begin_inset Quotes eld
-\end_inset
-
-new
-\begin_inset Quotes erd
-\end_inset
-
- function in a class object:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-#load the class (loaded every time the script is instanced)
-\end_layout
-
-\begin_layout Plain Layout
-
-var MyClass = load("myclass.gd")
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-#alternatively, using the preload() function preloads the class at compile
- time
-\end_layout
-
-\begin_layout Plain Layout
-
-var MyClass2 = preload("myclass.gd")
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-function _init():
-\end_layout
-
-\begin_layout Plain Layout
-
- var a = MyClass.new()
-\end_layout
-
-\begin_layout Plain Layout
-
- a.somefunction()
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Exports
-\end_layout
-
-\begin_layout Standard
-Class members can be exported.
- This means their value gets saved along with a scene.
- If class members have initializers to constant expressions, they will be
- available for editing in the property editor.
- Exporting is done by using the export keyword:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-extends Button
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-export var data # value will be saved
-\end_layout
-
-\begin_layout Plain Layout
-
-export var number=5 # also available to the property editor
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-One of the fundamental benefits of exporting member variables is to have
- them visible in the property editor.
- This way artists and game designers can modify values that later influence
- how the program runs.
- For this, a special export syntax is provided for more detail in the exported
- variables:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-#if the exported value assigns a constant or constant expression, the type
- will be infered and used in the editor
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-export var number=5
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-#export can take a basic datatype as argument, which will be used in the
- editor
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-export(int) var number
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-#export can also take a resource type as hint
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-export(Texture) var character_face
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-#integers and strings hint enumerated values
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-export(int,"Warrior","Magician","Thief") var character_class # (editor will
- set them as 0,1 and 2)
-\end_layout
-
-\begin_layout Plain Layout
-
-export(String,"Rebecca","Mary","Leah") var character_name
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-#strings as paths
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-export(String,FILE) var f # string is a path to a file
-\end_layout
-
-\begin_layout Plain Layout
-
-export(String,DIR) var f # string is a path to a directory
-\end_layout
-
-\begin_layout Plain Layout
-
-export(String,FILE,"*.txt") var f # string is a path to a file, custom filter
- provided as hint
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-#integers and floats hint ranges
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-export(int,20) var i # 0 to 20 allowed
-\end_layout
-
-\begin_layout Plain Layout
-
-export(int,-10,20) var j # -10 to 20 allowed
-\end_layout
-
-\begin_layout Plain Layout
-
-export(float,-10,20,0.2) var k # -10 to 20 allowed, with stepping of 0.2
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-#color can hint availability of alpha
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-export(Color,RGB) var col # Color is RGB
-\end_layout
-
-\begin_layout Plain Layout
-
-export(Color,RGBA) var col # Color is RGBA
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-It must be noted that even if the script is not being run while at the editor,
- the exported properties are still editable (see below for
-\begin_inset Quotes eld
-\end_inset
-
-tool
-\begin_inset Quotes erd
-\end_inset
-
-).
-\end_layout
-
-\begin_layout Subsection
-Static Functions
-\end_layout
-
-\begin_layout Standard
-A function can be declared static.
- When static, it has no access to the instance member variables or
-\begin_inset Quotes eld
-\end_inset
-
-self
-\begin_inset Quotes erd
-\end_inset
-
-.
- This is mainly useful to make libraries of helper functions:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-static func sum2(a,b):
-\end_layout
-
-\begin_layout Plain Layout
-
- return a+b
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Asserting
-\end_layout
-
-\begin_layout Standard
-It is possible to assert a condition, which will cause a debugger break
- if false.
- Just use the built-in 'assert' function.
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-assert(a==2)
-\end_layout
-
-\begin_layout Plain Layout
-
-# if a is not 2, it will generate a debugger break
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Tool Mode
-\end_layout
-
-\begin_layout Standard
-Scripts by default don't run inside the editor, and only the exported properties
- can be changed.
- In some cases it is desired that they do (as long as they don't execute
- game code or manually avoid doing so).
- For this, the
-\begin_inset Quotes eld
-\end_inset
-
-tool
-\begin_inset Quotes erd
-\end_inset
-
- keyword exists, and must be placed at the top of the file:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-tool
-\end_layout
-
-\begin_layout Plain Layout
-
-extends Button
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-func _init():
-\end_layout
-
-\begin_layout Plain Layout
-
- print("Hello")
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Memory Management
-\end_layout
-
-\begin_layout Standard
-If a class inherits from
-\emph on
-Reference
-\emph default
-, then instances will be freed when no longer in use.
- No garbage collector exists, just simple reference counting.
- By default, all classes that don't define inheritance extend
-\emph on
-Reference
-\emph default
-.
- If this is not desired, then a class must inherit
-\emph on
-Object
-\emph default
- manually and must call instance.free().
- To avoid reference cycles that can't be freed, a weakref() function is
- provided for creating weak references.
-
-\end_layout
-
-\begin_layout Subsection
-Function References
-\end_layout
-
-\begin_layout Standard
-Functions can't be referenced because they are not treated as class members.
- There are two alternatives to this, though.
- The
-\begin_inset Quotes eld
-\end_inset
-
-call
-\begin_inset Quotes erd
-\end_inset
-
- function or the funcref() helper.
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-instance.call("funcname",args) # call a function by bane
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-var fr = funcref(instance,"funcname") #create a function ref
-\end_layout
-
-\begin_layout Plain Layout
-
-fr.exec(args)
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\end_body
-\end_document
diff --git a/doc/godot_splash.png b/doc/godot_splash.png
deleted file mode 100644
index da56fa15cc..0000000000
--- a/doc/godot_splash.png
+++ /dev/null
Binary files differ
diff --git a/doc/header.txt b/doc/header.txt
deleted file mode 100644
index 359949cc3b..0000000000
--- a/doc/header.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-/*************************************************/
-/* $filename */
-/*************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/*************************************************/
-/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
-/* All Rights Reserved. */
-/*************************************************/
-
-
diff --git a/doc/html/@GDScript.html b/doc/html/@GDScript.html
deleted file mode 100644
index 5d5d77ffbf..0000000000
--- a/doc/html/@GDScript.html
+++ /dev/null
@@ -1,93 +0,0 @@
-<html><link href="main.css" rel="stylesheet" type="text/css" /><body><table class="top_table"><tr><td class="top_table"><image src="images/logo.png" /></td><td class="top_table"><a href="index.html">Index</a></td><td class="top_table"><a href="alphabetical.html">Classes</a></td><td class="top_table"><a href="category.html">Categories</a></td><td><a href="inheritance.html">Inheritance</a></td></tr></table><hr /><div class="class"><a name="@GDScript"><h3 class="title class_title">@GDScript</h3></a><div class="description class_description">
- Built-in GDScript functions.
- </div><br /><div class="category"><span class="category">Category: </span><a class="category_ref" href="category.html#CATEGORY_Core">Core</a></div><h4>Public Methods:</h4><table class="method_list"><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_sin">sin</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_cos">cos</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_tan">tan</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_sinh">sinh</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_cosh">cosh</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_tanh">tanh</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_asin">asin</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_acos">acos</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_atan">atan</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_atan2">atan2</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>x</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>y</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_sqrt">sqrt</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_fmod">fmod</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>x</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>y</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_fposmod">fposmod</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>x</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>y</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_floor">floor</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_ceil">ceil</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_round">round</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_abs">abs</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_sign">sign</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_pow">pow</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>x</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>y</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_log">log</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_exp">exp</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_isnan">isnan</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_isinf">isinf</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_ease">ease</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>curve</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_decimals">decimals</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>step</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_stepify">stepify</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>step</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="int.html">int </a></td><td><span class="identifier funcdef"><a href="#@GDScript_rand">rand</a></span><span class="symbol"> (</span><span class="symbol">)</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_randf">randf</a></span><span class="symbol"> (</span><span class="symbol">)</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_rand_range">rand_range</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>from</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>to</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="Array.html">Array </a></td><td><span class="identifier funcdef"><a href="#@GDScript_rand_seed">rand_seed</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>seed</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_deg2rad">deg2rad</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>deg</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_rad2deg">rad2deg</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>rad</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_linear2db">linear2db</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>nrg</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_db2linear">db2linear</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>db</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_max">max</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>a</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>b</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_min">min</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>a</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>b</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="real.html">real </a></td><td><span class="identifier funcdef"><a href="#@GDScript_clamp">clamp</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>val</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>min</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>max</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="int.html">int </a></td><td><span class="identifier funcdef"><a href="#@GDScript_nearest_po2">nearest_po2</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="int.html">int </a><span>val</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="Object.html">Object </a></td><td><span class="identifier funcdef"><a href="#@GDScript_weakref">weakref</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="Object.html">Object </a><span>obj</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="Object.html">Object </a></td><td><span class="identifier funcdef"><a href="#@GDScript_convert">convert</a></span><span class="symbol"> (</span><span> </span><span class="datatype">var </span><span>what</span><span>, </span><a class="datatype_existing" href="int.html">int </a><span>type</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="String.html">String </a></td><td><span class="identifier funcdef"><a href="#@GDScript_str">str</a></span><span class="symbol"> (</span><span> </span><span class="datatype">var </span><span>what</span><span>, </span><span class="datatype">var </span><span>...</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="Nil.html">Nil </a></td><td><span class="identifier funcdef"><a href="#@GDScript_print">print</a></span><span class="symbol"> (</span><span> </span><span class="datatype">var </span><span>what</span><span>, </span><span class="datatype">var </span><span>...</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="Nil.html">Nil </a></td><td><span class="identifier funcdef"><a href="#@GDScript_printerr">printerr</a></span><span class="symbol"> (</span><span> </span><span class="datatype">var </span><span>what</span><span>, </span><span class="datatype">var </span><span>...</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="Nil.html">Nil </a></td><td><span class="identifier funcdef"><a href="#@GDScript_printraw">printraw</a></span><span class="symbol"> (</span><span> </span><span class="datatype">var </span><span>what</span><span>, </span><span class="datatype">var </span><span>...</span><span class="symbol"> )</span></td></tr><tr class="method"><td align="right"><a class="datatype_existing" href="Array.html">Array </a></td><td><span class="identifier funcdef"><a href="#@GDScript_range">range</a></span><span class="symbol"> (</span><span> </span><span class="datatype">var </span><span>...</span><span class="symbol"> )</span></td></tr></table><h4>Description:</h4><div class="description">
- This contains the list of built-in gdscript functions. Mostly math functions and other utilities. Everything else is expanded by objects.
- </div><h4>Method Documentation:</h4><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_sin">@GDScript::sin</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Standard sine function.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_cos">@GDScript::cos</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Standard cosine function.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_tan">@GDScript::tan</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Standard tangent function.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_sinh">@GDScript::sinh</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Hyperbolic sine.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_tanh">@GDScript::tanh</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Hyperbolic tangent.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_asin">@GDScript::asin</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Arc-sine.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_acos">@GDScript::acos</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Arc-cosine.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_atan">@GDScript::atan</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Arc-tangent.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_atan2">@GDScript::atan2</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>x</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>y</span><span class="symbol"> )</span></div><div class="description">
- Arc-tangent that takes a 2D vector as argument, retuns the full -pi to +pi range.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_sqrt">@GDScript::sqrt</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Square root.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_fmod">@GDScript::fmod</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>x</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>y</span><span class="symbol"> )</span></div><div class="description">
- Module (remainder of x/y).
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_fposmod">@GDScript::fposmod</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>x</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>y</span><span class="symbol"> )</span></div><div class="description">
- Module (remainder of x/y) that wraps equally in positive and negative.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_floor">@GDScript::floor</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Floor (rounds down to nearest integer).
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_ceil">@GDScript::ceil</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Ceiling (rounds up to nearest integer).
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_round">@GDScript::round</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Round to nearest integer.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_abs">@GDScript::abs</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Remove sign (works for integer and float).
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_sign">@GDScript::sign</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Return sign (-1 or +1).
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_pow">@GDScript::pow</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>x</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>y</span><span class="symbol"> )</span></div><div class="description">
- Power function, x elevate to y.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_log">@GDScript::log</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Natural logarithm.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_exp">@GDScript::exp</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Exponential logarithm.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_isnan">@GDScript::isnan</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Return true if the float is not a number.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_isinf">@GDScript::isinf</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span class="symbol"> )</span></div><div class="description">
- Return true if the float is infinite.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_ease">@GDScript::ease</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>curve</span><span class="symbol"> )</span></div><div class="description">
- Easing function, based on exponent. 0 is constant, 1 is linear, 0 to 1 is ease-in, 1+ is ease out. Negative values are in-out/out in.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_decimals">@GDScript::decimals</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>step</span><span class="symbol"> )</span></div><div class="description">
- Return the amount of decimals in the floating point value.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_stepify">@GDScript::stepify</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>s</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>step</span><span class="symbol"> )</span></div><div class="description">
- Snap float value to a given step.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="int.html">int </a><span class="funcdecl"><a name="@GDScript_rand">@GDScript::rand</a></span><span class="symbol"> (</span><span class="symbol">)</span></div><div class="description">
- Random value (integer).
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_randf">@GDScript::randf</a></span><span class="symbol"> (</span><span class="symbol">)</span></div><div class="description">
- Random value (0 to 1 float).
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_rand_range">@GDScript::rand_range</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>from</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>to</span><span class="symbol"> )</span></div><div class="description">
- Random range.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="Array.html">Array </a><span class="funcdecl"><a name="@GDScript_rand_seed">@GDScript::rand_seed</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>seed</span><span class="symbol"> )</span></div><div class="description">
- random from seed, pass a seed and an array with both number and new seed is returned.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_deg2rad">@GDScript::deg2rad</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>deg</span><span class="symbol"> )</span></div><div class="description">
- Convert from degrees to radians.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_rad2deg">@GDScript::rad2deg</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>rad</span><span class="symbol"> )</span></div><div class="description">
- Convert from radias to degrees.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_linear2db">@GDScript::linear2db</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>nrg</span><span class="symbol"> )</span></div><div class="description">
- Convert from linear energy to decibels (audio).
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_db2linear">@GDScript::db2linear</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>db</span><span class="symbol"> )</span></div><div class="description">
- Convert from decibels to linear energy (audio).
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_max">@GDScript::max</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>a</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>b</span><span class="symbol"> )</span></div><div class="description">
- Return the maximum of two values.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_min">@GDScript::min</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>a</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>b</span><span class="symbol"> )</span></div><div class="description">
- Return the minimum of two values.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="real.html">real </a><span class="funcdecl"><a name="@GDScript_clamp">@GDScript::clamp</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="real.html">real </a><span>val</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>min</span><span>, </span><a class="datatype_existing" href="real.html">real </a><span>max</span><span class="symbol"> )</span></div><div class="description">
- Clamp both values to a range.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="int.html">int </a><span class="funcdecl"><a name="@GDScript_nearest_po2">@GDScript::nearest_po2</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="int.html">int </a><span>val</span><span class="symbol"> )</span></div><div class="description">
- Return the nearest larger power of 2 for an integer.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="Object.html">Object </a><span class="funcdecl"><a name="@GDScript_weakref">@GDScript::weakref</a></span><span class="symbol"> (</span><span> </span><a class="datatype_existing" href="Object.html">Object </a><span>obj</span><span class="symbol"> )</span></div><div class="description">
- Return a weak reference to an object.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="Object.html">Object </a><span class="funcdecl"><a name="@GDScript_convert">@GDScript::convert</a></span><span class="symbol"> (</span><span> </span><span class="datatype">var </span><span>what</span><span>, </span><a class="datatype_existing" href="int.html">int </a><span>type</span><span class="symbol"> )</span></div><div class="description">
- Convert from a type to another in the best way possible. The "type" parameter uses the enum TYPE_* in Global Scope.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="String.html">String </a><span class="funcdecl"><a name="@GDScript_str">@GDScript::str</a></span><span class="symbol"> (</span><span> </span><span class="datatype">var </span><span>what</span><span>, </span><span class="datatype">var </span><span>...</span><span class="symbol"> )</span></div><div class="description">
- Convert one or more arguments to strings in the best way possible.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="Nil.html">Nil </a><span class="funcdecl"><a name="@GDScript_print">@GDScript::print</a></span><span class="symbol"> (</span><span> </span><span class="datatype">var </span><span>what</span><span>, </span><span class="datatype">var </span><span>...</span><span class="symbol"> )</span></div><div class="description">
- Print one or more arguments to strings in the best way possible to a console line.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="Nil.html">Nil </a><span class="funcdecl"><a name="@GDScript_printerr">@GDScript::printerr</a></span><span class="symbol"> (</span><span> </span><span class="datatype">var </span><span>what</span><span>, </span><span class="datatype">var </span><span>...</span><span class="symbol"> )</span></div><div class="description">
- Print one or more arguments to strings in the best way possible to standard error line.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="Nil.html">Nil </a><span class="funcdecl"><a name="@GDScript_printraw">@GDScript::printraw</a></span><span class="symbol"> (</span><span> </span><span class="datatype">var </span><span>what</span><span>, </span><span class="datatype">var </span><span>...</span><span class="symbol"> )</span></div><div class="description">
- Print one or more arguments to strings in the best way possible to console. No newline is added at the end.
- </div></div><div class="method_doc"><div class="method"><a class="datatype_existing" href="Array.html">Array </a><span class="funcdecl"><a name="@GDScript_range">@GDScript::range</a></span><span class="symbol"> (</span><span> </span><span class="datatype">var </span><span>...</span><span class="symbol"> )</span></div><div class="description">
- Return an array with the given range. Range can be 1 argument N (0 to N-1), two arguments (initial, final-1) or three arguments (initial,final-1,increment).
- </div></div></div><hr /><span>Copyright 2008-2010 Codenix SRL</span></body></html> \ No newline at end of file
diff --git a/doc/html/@Global Scope.html b/doc/html/@Global Scope.html
deleted file mode 100644
index 3324383c3d..0000000000
--- a/doc/html/@Global Scope.html
+++ /dev/null
@@ -1,459 +0,0 @@
-<html><link href="main.css" rel="stylesheet" type="text/css" /><body><table class="top_table"><tr><td class="top_table"><image src="images/logo.png" /></td><td class="top_table"><a href="index.html">Index</a></td><td class="top_table"><a href="alphabetical.html">Classes</a></td><td class="top_table"><a href="category.html">Categories</a></td><td><a href="inheritance.html">Inheritance</a></td></tr></table><hr /><div class="class"><a name="@Global Scope"><h3 class="title class_title">@Global Scope</h3></a><div class="description class_description">
- Global scope constants and variables.
- </div><br /><div class="category"><span class="category">Category: </span><a class="category_ref" href="category.html#CATEGORY_Core">Core</a></div><h4>Public Variables:</h4><div class="member_list"><li><div class="member"><a class="datatype_existing" href="Globals.html">Globals </a><span class="identifier member_name"> Globals </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="IP.html">IP </a><span class="identifier member_name"> IP </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="Geometry.html">Geometry </a><span class="identifier member_name"> Geometry </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="ResourceLoader.html">ResourceLoader </a><span class="identifier member_name"> ResourceLoader </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="ResourceSaver.html">ResourceSaver </a><span class="identifier member_name"> ResourceSaver </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="PathRemap.html">PathRemap </a><span class="identifier member_name"> PathRemap </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="OS.html">OS </a><span class="identifier member_name"> OS </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="TranslationServer.html">TranslationServer </a><span class="identifier member_name"> TranslationServer </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="TranslationServer.html">TranslationServer </a><span class="identifier member_name"> TS </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="SceneIO.html">SceneIO </a><span class="identifier member_name"> SceneIO </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="VisualServer.html">VisualServer </a><span class="identifier member_name"> VisualServer </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="VisualServer.html">VisualServer </a><span class="identifier member_name"> VS </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="AudioServer.html">AudioServer </a><span class="identifier member_name"> AudioServer </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="AudioServer.html">AudioServer </a><span class="identifier member_name"> AS </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="PhysicsServer.html">PhysicsServer </a><span class="identifier member_name"> PhysicsServer </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="PhysicsServer.html">PhysicsServer </a><span class="identifier member_name"> PS </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="Physics2DServer.html">Physics2DServer </a><span class="identifier member_name"> Physics2DServer </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="Physics2DServer.html">Physics2DServer </a><span class="identifier member_name"> PS2D </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="SpatialSound2DServer.html">SpatialSound2DServer </a><span class="identifier member_name"> SpatialSoundServer </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="SpatialSound2DServer.html">SpatialSound2DServer </a><span class="identifier member_name"> SS </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="SpatialSound2DServer.html">SpatialSound2DServer </a><span class="identifier member_name"> SpatialSound2DServer </span><span class="member_description">
- </span></div></li><li><div class="member"><a class="datatype_existing" href="SpatialSound2DServer.html">SpatialSound2DServer </a><span class="identifier member_name"> SS2D </span><span class="member_description">
- </span></div></li></div><h4>Constants:</h4><div class="constant_list"><li><div class="constant"><span class="identifier constant_name">MARGIN_LEFT </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">MARGIN_TOP </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">MARGIN_RIGHT </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">MARGIN_BOTTOM </span><span class="symbol">= </span><span class="constant_value">3 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">VERTICAL </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">HORIZONTAL </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">HALIGN_LEFT </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">HALIGN_CENTER </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">HALIGN_RIGHT </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">VALIGN_TOP </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">VALIGN_CENTER </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">VALIGN_BOTTOM </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">SPKEY </span><span class="symbol">= </span><span class="constant_value">16777216 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ESCAPE </span><span class="symbol">= </span><span class="constant_value">16777217 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_TAB </span><span class="symbol">= </span><span class="constant_value">16777218 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_BACKTAB </span><span class="symbol">= </span><span class="constant_value">16777219 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_BACKSPACE </span><span class="symbol">= </span><span class="constant_value">16777220 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_RETURN </span><span class="symbol">= </span><span class="constant_value">16777221 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ENTER </span><span class="symbol">= </span><span class="constant_value">16777222 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_INSERT </span><span class="symbol">= </span><span class="constant_value">16777223 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_DELETE </span><span class="symbol">= </span><span class="constant_value">16777224 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_PAUSE </span><span class="symbol">= </span><span class="constant_value">16777225 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_PRINT </span><span class="symbol">= </span><span class="constant_value">16777226 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_SYSREQ </span><span class="symbol">= </span><span class="constant_value">16777227 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_CLEAR </span><span class="symbol">= </span><span class="constant_value">16777228 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_HOME </span><span class="symbol">= </span><span class="constant_value">16777229 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_END </span><span class="symbol">= </span><span class="constant_value">16777230 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LEFT </span><span class="symbol">= </span><span class="constant_value">16777231 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_UP </span><span class="symbol">= </span><span class="constant_value">16777232 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_RIGHT </span><span class="symbol">= </span><span class="constant_value">16777233 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_DOWN </span><span class="symbol">= </span><span class="constant_value">16777234 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_PAGEUP </span><span class="symbol">= </span><span class="constant_value">16777235 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_PAGEDOWN </span><span class="symbol">= </span><span class="constant_value">16777236 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_SHIFT </span><span class="symbol">= </span><span class="constant_value">16777237 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_CONTROL </span><span class="symbol">= </span><span class="constant_value">16777238 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_META </span><span class="symbol">= </span><span class="constant_value">16777239 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ALT </span><span class="symbol">= </span><span class="constant_value">16777240 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_CAPSLOCK </span><span class="symbol">= </span><span class="constant_value">16777241 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_NUMLOCK </span><span class="symbol">= </span><span class="constant_value">16777242 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_SCROLLLOCK </span><span class="symbol">= </span><span class="constant_value">16777243 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F1 </span><span class="symbol">= </span><span class="constant_value">16777244 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F2 </span><span class="symbol">= </span><span class="constant_value">16777245 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F3 </span><span class="symbol">= </span><span class="constant_value">16777246 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F4 </span><span class="symbol">= </span><span class="constant_value">16777247 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F5 </span><span class="symbol">= </span><span class="constant_value">16777248 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F6 </span><span class="symbol">= </span><span class="constant_value">16777249 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F7 </span><span class="symbol">= </span><span class="constant_value">16777250 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F8 </span><span class="symbol">= </span><span class="constant_value">16777251 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F9 </span><span class="symbol">= </span><span class="constant_value">16777252 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F10 </span><span class="symbol">= </span><span class="constant_value">16777253 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F11 </span><span class="symbol">= </span><span class="constant_value">16777254 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F12 </span><span class="symbol">= </span><span class="constant_value">16777255 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F13 </span><span class="symbol">= </span><span class="constant_value">16777256 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F14 </span><span class="symbol">= </span><span class="constant_value">16777257 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F15 </span><span class="symbol">= </span><span class="constant_value">16777258 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F16 </span><span class="symbol">= </span><span class="constant_value">16777259 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_ENTER </span><span class="symbol">= </span><span class="constant_value">16777344 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_MULTIPLY </span><span class="symbol">= </span><span class="constant_value">16777345 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_DIVIDE </span><span class="symbol">= </span><span class="constant_value">16777346 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_SUBSTRACT </span><span class="symbol">= </span><span class="constant_value">16777347 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_PERIOD </span><span class="symbol">= </span><span class="constant_value">16777348 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_ADD </span><span class="symbol">= </span><span class="constant_value">16777349 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_0 </span><span class="symbol">= </span><span class="constant_value">16777350 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_1 </span><span class="symbol">= </span><span class="constant_value">16777351 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_2 </span><span class="symbol">= </span><span class="constant_value">16777352 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_3 </span><span class="symbol">= </span><span class="constant_value">16777353 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_4 </span><span class="symbol">= </span><span class="constant_value">16777354 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_5 </span><span class="symbol">= </span><span class="constant_value">16777355 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_6 </span><span class="symbol">= </span><span class="constant_value">16777356 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_7 </span><span class="symbol">= </span><span class="constant_value">16777357 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_8 </span><span class="symbol">= </span><span class="constant_value">16777358 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_KP_9 </span><span class="symbol">= </span><span class="constant_value">16777359 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_SUPER_L </span><span class="symbol">= </span><span class="constant_value">16777260 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_SUPER_R </span><span class="symbol">= </span><span class="constant_value">16777261 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MENU </span><span class="symbol">= </span><span class="constant_value">16777262 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_HYPER_L </span><span class="symbol">= </span><span class="constant_value">16777263 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_HYPER_R </span><span class="symbol">= </span><span class="constant_value">16777264 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_HELP </span><span class="symbol">= </span><span class="constant_value">16777265 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_DIRECTION_L </span><span class="symbol">= </span><span class="constant_value">16777266 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_DIRECTION_R </span><span class="symbol">= </span><span class="constant_value">16777267 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_BACK </span><span class="symbol">= </span><span class="constant_value">16777280 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_FORWARD </span><span class="symbol">= </span><span class="constant_value">16777281 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_STOP </span><span class="symbol">= </span><span class="constant_value">16777282 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_REFRESH </span><span class="symbol">= </span><span class="constant_value">16777283 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_VOLUMEDOWN </span><span class="symbol">= </span><span class="constant_value">16777284 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_VOLUMEMUTE </span><span class="symbol">= </span><span class="constant_value">16777285 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_VOLUMEUP </span><span class="symbol">= </span><span class="constant_value">16777286 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_BASSBOOST </span><span class="symbol">= </span><span class="constant_value">16777287 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_BASSUP </span><span class="symbol">= </span><span class="constant_value">16777288 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_BASSDOWN </span><span class="symbol">= </span><span class="constant_value">16777289 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_TREBLEUP </span><span class="symbol">= </span><span class="constant_value">16777290 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_TREBLEDOWN </span><span class="symbol">= </span><span class="constant_value">16777291 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MEDIAPLAY </span><span class="symbol">= </span><span class="constant_value">16777292 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MEDIASTOP </span><span class="symbol">= </span><span class="constant_value">16777293 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MEDIAPREVIOUS </span><span class="symbol">= </span><span class="constant_value">16777294 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MEDIANEXT </span><span class="symbol">= </span><span class="constant_value">16777295 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MEDIARECORD </span><span class="symbol">= </span><span class="constant_value">16777296 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_HOMEPAGE </span><span class="symbol">= </span><span class="constant_value">16777297 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_FAVORITES </span><span class="symbol">= </span><span class="constant_value">16777298 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_SEARCH </span><span class="symbol">= </span><span class="constant_value">16777299 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_STANDBY </span><span class="symbol">= </span><span class="constant_value">16777300 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_OPENURL </span><span class="symbol">= </span><span class="constant_value">16777301 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCHMAIL </span><span class="symbol">= </span><span class="constant_value">16777302 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCHMEDIA </span><span class="symbol">= </span><span class="constant_value">16777303 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCH0 </span><span class="symbol">= </span><span class="constant_value">16777304 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCH1 </span><span class="symbol">= </span><span class="constant_value">16777305 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCH2 </span><span class="symbol">= </span><span class="constant_value">16777306 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCH3 </span><span class="symbol">= </span><span class="constant_value">16777307 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCH4 </span><span class="symbol">= </span><span class="constant_value">16777308 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCH5 </span><span class="symbol">= </span><span class="constant_value">16777309 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCH6 </span><span class="symbol">= </span><span class="constant_value">16777310 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCH7 </span><span class="symbol">= </span><span class="constant_value">16777311 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCH8 </span><span class="symbol">= </span><span class="constant_value">16777312 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCH9 </span><span class="symbol">= </span><span class="constant_value">16777313 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCHA </span><span class="symbol">= </span><span class="constant_value">16777314 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCHB </span><span class="symbol">= </span><span class="constant_value">16777315 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCHC </span><span class="symbol">= </span><span class="constant_value">16777316 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCHD </span><span class="symbol">= </span><span class="constant_value">16777317 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCHE </span><span class="symbol">= </span><span class="constant_value">16777318 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LAUNCHF </span><span class="symbol">= </span><span class="constant_value">16777319 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_UNKNOWN </span><span class="symbol">= </span><span class="constant_value">33554431 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_SPACE </span><span class="symbol">= </span><span class="constant_value">32 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_EXCLAM </span><span class="symbol">= </span><span class="constant_value">33 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_QUOTEDBL </span><span class="symbol">= </span><span class="constant_value">34 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_NUMBERSIGN </span><span class="symbol">= </span><span class="constant_value">35 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_DOLLAR </span><span class="symbol">= </span><span class="constant_value">36 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_PERCENT </span><span class="symbol">= </span><span class="constant_value">37 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_AMPERSAND </span><span class="symbol">= </span><span class="constant_value">38 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_APOSTROPHE </span><span class="symbol">= </span><span class="constant_value">39 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_PARENLEFT </span><span class="symbol">= </span><span class="constant_value">40 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_PARENRIGHT </span><span class="symbol">= </span><span class="constant_value">41 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ASTERISK </span><span class="symbol">= </span><span class="constant_value">42 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_PLUS </span><span class="symbol">= </span><span class="constant_value">43 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_COMMA </span><span class="symbol">= </span><span class="constant_value">44 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MINUS </span><span class="symbol">= </span><span class="constant_value">45 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_PERIOD </span><span class="symbol">= </span><span class="constant_value">46 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_SLASH </span><span class="symbol">= </span><span class="constant_value">47 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_0 </span><span class="symbol">= </span><span class="constant_value">48 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_1 </span><span class="symbol">= </span><span class="constant_value">49 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_2 </span><span class="symbol">= </span><span class="constant_value">50 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_3 </span><span class="symbol">= </span><span class="constant_value">51 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_4 </span><span class="symbol">= </span><span class="constant_value">52 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_5 </span><span class="symbol">= </span><span class="constant_value">53 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_6 </span><span class="symbol">= </span><span class="constant_value">54 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_7 </span><span class="symbol">= </span><span class="constant_value">55 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_8 </span><span class="symbol">= </span><span class="constant_value">56 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_9 </span><span class="symbol">= </span><span class="constant_value">57 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_COLON </span><span class="symbol">= </span><span class="constant_value">58 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_SEMICOLON </span><span class="symbol">= </span><span class="constant_value">59 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_LESS </span><span class="symbol">= </span><span class="constant_value">60 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_EQUAL </span><span class="symbol">= </span><span class="constant_value">61 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_GREATER </span><span class="symbol">= </span><span class="constant_value">62 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_QUESTION </span><span class="symbol">= </span><span class="constant_value">63 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_AT </span><span class="symbol">= </span><span class="constant_value">64 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_A </span><span class="symbol">= </span><span class="constant_value">65 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_B </span><span class="symbol">= </span><span class="constant_value">66 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_C </span><span class="symbol">= </span><span class="constant_value">67 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_D </span><span class="symbol">= </span><span class="constant_value">68 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_E </span><span class="symbol">= </span><span class="constant_value">69 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_F </span><span class="symbol">= </span><span class="constant_value">70 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_G </span><span class="symbol">= </span><span class="constant_value">71 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_H </span><span class="symbol">= </span><span class="constant_value">72 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_I </span><span class="symbol">= </span><span class="constant_value">73 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_J </span><span class="symbol">= </span><span class="constant_value">74 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_K </span><span class="symbol">= </span><span class="constant_value">75 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_L </span><span class="symbol">= </span><span class="constant_value">76 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_M </span><span class="symbol">= </span><span class="constant_value">77 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_N </span><span class="symbol">= </span><span class="constant_value">78 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_O </span><span class="symbol">= </span><span class="constant_value">79 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_P </span><span class="symbol">= </span><span class="constant_value">80 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_Q </span><span class="symbol">= </span><span class="constant_value">81 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_R </span><span class="symbol">= </span><span class="constant_value">82 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_S </span><span class="symbol">= </span><span class="constant_value">83 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_T </span><span class="symbol">= </span><span class="constant_value">84 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_U </span><span class="symbol">= </span><span class="constant_value">85 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_V </span><span class="symbol">= </span><span class="constant_value">86 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_W </span><span class="symbol">= </span><span class="constant_value">87 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_X </span><span class="symbol">= </span><span class="constant_value">88 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_Y </span><span class="symbol">= </span><span class="constant_value">89 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_Z </span><span class="symbol">= </span><span class="constant_value">90 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_BRACKETLEFT </span><span class="symbol">= </span><span class="constant_value">91 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_BACKSLASH </span><span class="symbol">= </span><span class="constant_value">92 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_BRACKETRIGHT </span><span class="symbol">= </span><span class="constant_value">93 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ASCIICIRCUM </span><span class="symbol">= </span><span class="constant_value">94 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_UNDERSCORE </span><span class="symbol">= </span><span class="constant_value">95 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_QUOTELEFT </span><span class="symbol">= </span><span class="constant_value">96 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_BRACELEFT </span><span class="symbol">= </span><span class="constant_value">123 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_BAR </span><span class="symbol">= </span><span class="constant_value">124 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_BRACERIGHT </span><span class="symbol">= </span><span class="constant_value">125 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ASCIITILDE </span><span class="symbol">= </span><span class="constant_value">126 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_NOBREAKSPACE </span><span class="symbol">= </span><span class="constant_value">160 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_EXCLAMDOWN </span><span class="symbol">= </span><span class="constant_value">161 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_CENT </span><span class="symbol">= </span><span class="constant_value">162 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_STERLING </span><span class="symbol">= </span><span class="constant_value">163 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_CURRENCY </span><span class="symbol">= </span><span class="constant_value">164 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_YEN </span><span class="symbol">= </span><span class="constant_value">165 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_BROKENBAR </span><span class="symbol">= </span><span class="constant_value">166 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_SECTION </span><span class="symbol">= </span><span class="constant_value">167 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_DIAERESIS </span><span class="symbol">= </span><span class="constant_value">168 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_COPYRIGHT </span><span class="symbol">= </span><span class="constant_value">169 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ORDFEMININE </span><span class="symbol">= </span><span class="constant_value">170 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_GUILLEMOTLEFT </span><span class="symbol">= </span><span class="constant_value">171 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_NOTSIGN </span><span class="symbol">= </span><span class="constant_value">172 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_HYPHEN </span><span class="symbol">= </span><span class="constant_value">173 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_REGISTERED </span><span class="symbol">= </span><span class="constant_value">174 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MACRON </span><span class="symbol">= </span><span class="constant_value">175 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_DEGREE </span><span class="symbol">= </span><span class="constant_value">176 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_PLUSMINUS </span><span class="symbol">= </span><span class="constant_value">177 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_TWOSUPERIOR </span><span class="symbol">= </span><span class="constant_value">178 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_THREESUPERIOR </span><span class="symbol">= </span><span class="constant_value">179 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ACUTE </span><span class="symbol">= </span><span class="constant_value">180 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MU </span><span class="symbol">= </span><span class="constant_value">181 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_PARAGRAPH </span><span class="symbol">= </span><span class="constant_value">182 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_PERIODCENTERED </span><span class="symbol">= </span><span class="constant_value">183 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_CEDILLA </span><span class="symbol">= </span><span class="constant_value">184 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ONESUPERIOR </span><span class="symbol">= </span><span class="constant_value">185 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MASCULINE </span><span class="symbol">= </span><span class="constant_value">186 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_GUILLEMOTRIGHT </span><span class="symbol">= </span><span class="constant_value">187 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ONEQUARTER </span><span class="symbol">= </span><span class="constant_value">188 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ONEHALF </span><span class="symbol">= </span><span class="constant_value">189 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_THREEQUARTERS </span><span class="symbol">= </span><span class="constant_value">190 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_QUESTIONDOWN </span><span class="symbol">= </span><span class="constant_value">191 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_AGRAVE </span><span class="symbol">= </span><span class="constant_value">192 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_AACUTE </span><span class="symbol">= </span><span class="constant_value">193 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ACIRCUMFLEX </span><span class="symbol">= </span><span class="constant_value">194 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ATILDE </span><span class="symbol">= </span><span class="constant_value">195 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ADIAERESIS </span><span class="symbol">= </span><span class="constant_value">196 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ARING </span><span class="symbol">= </span><span class="constant_value">197 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_AE </span><span class="symbol">= </span><span class="constant_value">198 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_CCEDILLA </span><span class="symbol">= </span><span class="constant_value">199 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_EGRAVE </span><span class="symbol">= </span><span class="constant_value">200 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_EACUTE </span><span class="symbol">= </span><span class="constant_value">201 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ECIRCUMFLEX </span><span class="symbol">= </span><span class="constant_value">202 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_EDIAERESIS </span><span class="symbol">= </span><span class="constant_value">203 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_IGRAVE </span><span class="symbol">= </span><span class="constant_value">204 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_IACUTE </span><span class="symbol">= </span><span class="constant_value">205 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ICIRCUMFLEX </span><span class="symbol">= </span><span class="constant_value">206 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_IDIAERESIS </span><span class="symbol">= </span><span class="constant_value">207 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ETH </span><span class="symbol">= </span><span class="constant_value">208 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_NTILDE </span><span class="symbol">= </span><span class="constant_value">209 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_OGRAVE </span><span class="symbol">= </span><span class="constant_value">210 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_OACUTE </span><span class="symbol">= </span><span class="constant_value">211 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_OCIRCUMFLEX </span><span class="symbol">= </span><span class="constant_value">212 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_OTILDE </span><span class="symbol">= </span><span class="constant_value">213 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_ODIAERESIS </span><span class="symbol">= </span><span class="constant_value">214 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MULTIPLY </span><span class="symbol">= </span><span class="constant_value">215 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_OOBLIQUE </span><span class="symbol">= </span><span class="constant_value">216 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_UGRAVE </span><span class="symbol">= </span><span class="constant_value">217 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_UACUTE </span><span class="symbol">= </span><span class="constant_value">218 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_UCIRCUMFLEX </span><span class="symbol">= </span><span class="constant_value">219 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_UDIAERESIS </span><span class="symbol">= </span><span class="constant_value">220 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_YACUTE </span><span class="symbol">= </span><span class="constant_value">221 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_THORN </span><span class="symbol">= </span><span class="constant_value">222 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_SSHARP </span><span class="symbol">= </span><span class="constant_value">223 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_DIVISION </span><span class="symbol">= </span><span class="constant_value">247 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_YDIAERESIS </span><span class="symbol">= </span><span class="constant_value">255 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_CODE_MASK </span><span class="symbol">= </span><span class="constant_value">33554431 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MODIFIER_MASK </span><span class="symbol">= </span><span class="constant_value">-16777216 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MASK_SHIFT </span><span class="symbol">= </span><span class="constant_value">33554432 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MASK_ALT </span><span class="symbol">= </span><span class="constant_value">67108864 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MASK_META </span><span class="symbol">= </span><span class="constant_value">134217728 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MASK_CTRL </span><span class="symbol">= </span><span class="constant_value">268435456 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MASK_KPAD </span><span class="symbol">= </span><span class="constant_value">536870912 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">KEY_MASK_GROUP_SWITCH </span><span class="symbol">= </span><span class="constant_value">1073741824 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">BUTTON_LEFT </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">BUTTON_RIGHT </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">BUTTON_MIDDLE </span><span class="symbol">= </span><span class="constant_value">3 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">BUTTON_WHEEL_UP </span><span class="symbol">= </span><span class="constant_value">4 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">BUTTON_WHEEL_DOWN </span><span class="symbol">= </span><span class="constant_value">5 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">BUTTON_MASK_LEFT </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">BUTTON_MASK_RIGHT </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">BUTTON_MASK_MIDDLE </span><span class="symbol">= </span><span class="constant_value">4 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_0 </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_1 </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_2 </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_3 </span><span class="symbol">= </span><span class="constant_value">3 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_4 </span><span class="symbol">= </span><span class="constant_value">4 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_5 </span><span class="symbol">= </span><span class="constant_value">5 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_6 </span><span class="symbol">= </span><span class="constant_value">6 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_7 </span><span class="symbol">= </span><span class="constant_value">7 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_8 </span><span class="symbol">= </span><span class="constant_value">8 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_9 </span><span class="symbol">= </span><span class="constant_value">9 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_10 </span><span class="symbol">= </span><span class="constant_value">10 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_11 </span><span class="symbol">= </span><span class="constant_value">11 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_12 </span><span class="symbol">= </span><span class="constant_value">12 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_13 </span><span class="symbol">= </span><span class="constant_value">13 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_14 </span><span class="symbol">= </span><span class="constant_value">14 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_15 </span><span class="symbol">= </span><span class="constant_value">15 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_BUTTON_MAX </span><span class="symbol">= </span><span class="constant_value">16 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_SNES_A </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_SNES_B </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_SNES_X </span><span class="symbol">= </span><span class="constant_value">3 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_SNES_Y </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_SONY_CIRCLE </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_SONY_X </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_SONY_SQUARE </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_SONY_TRIANGLE </span><span class="symbol">= </span><span class="constant_value">3 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_SEGA_B </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_SEGA_A </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_SEGA_X </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_SEGA_Y </span><span class="symbol">= </span><span class="constant_value">3 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_XBOX_B </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_XBOX_A </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_XBOX_X </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_XBOX_Y </span><span class="symbol">= </span><span class="constant_value">3 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_DS_A </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_DS_B </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_DS_X </span><span class="symbol">= </span><span class="constant_value">3 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_DS_Y </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_SELECT </span><span class="symbol">= </span><span class="constant_value">10 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_START </span><span class="symbol">= </span><span class="constant_value">11 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_DPAD_UP </span><span class="symbol">= </span><span class="constant_value">12 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_DPAD_DOWN </span><span class="symbol">= </span><span class="constant_value">13 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_DPAD_LEFT </span><span class="symbol">= </span><span class="constant_value">14 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_DPAD_RIGHT </span><span class="symbol">= </span><span class="constant_value">15 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_L </span><span class="symbol">= </span><span class="constant_value">4 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_L2 </span><span class="symbol">= </span><span class="constant_value">6 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_L3 </span><span class="symbol">= </span><span class="constant_value">8 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_R </span><span class="symbol">= </span><span class="constant_value">5 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_R2 </span><span class="symbol">= </span><span class="constant_value">7 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_R3 </span><span class="symbol">= </span><span class="constant_value">9 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_AXIS_0 </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_AXIS_1 </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_AXIS_2 </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_AXIS_3 </span><span class="symbol">= </span><span class="constant_value">3 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_AXIS_4 </span><span class="symbol">= </span><span class="constant_value">4 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_AXIS_5 </span><span class="symbol">= </span><span class="constant_value">5 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_AXIS_6 </span><span class="symbol">= </span><span class="constant_value">6 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_AXIS_7 </span><span class="symbol">= </span><span class="constant_value">7 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_AXIS_MAX </span><span class="symbol">= </span><span class="constant_value">8 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_ANALOG_0_X </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_ANALOG_0_Y </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_ANALOG_1_X </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_ANALOG_1_Y </span><span class="symbol">= </span><span class="constant_value">3 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_ANALOG_2_X </span><span class="symbol">= </span><span class="constant_value">4 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">JOY_ANALOG_2_Y </span><span class="symbol">= </span><span class="constant_value">5 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">OK </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">FAILED </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_UNAVAILABLE </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_UNCONFIGURED </span><span class="symbol">= </span><span class="constant_value">3 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_UNAUTHORIZED </span><span class="symbol">= </span><span class="constant_value">4 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_PARAMETER_RANGE_ERROR </span><span class="symbol">= </span><span class="constant_value">5 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_OUT_OF_MEMORY </span><span class="symbol">= </span><span class="constant_value">6 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_FILE_NOT_FOUND </span><span class="symbol">= </span><span class="constant_value">7 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_FILE_BAD_DRIVE </span><span class="symbol">= </span><span class="constant_value">8 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_FILE_BAD_PATH </span><span class="symbol">= </span><span class="constant_value">9 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_FILE_NO_PERMISSION </span><span class="symbol">= </span><span class="constant_value">10 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_FILE_ALREADY_IN_USE </span><span class="symbol">= </span><span class="constant_value">11 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_FILE_CANT_OPEN </span><span class="symbol">= </span><span class="constant_value">12 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_FILE_CANT_WRITE </span><span class="symbol">= </span><span class="constant_value">13 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_FILE_CANT_READ </span><span class="symbol">= </span><span class="constant_value">14 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_FILE_UNRECOGNIZED </span><span class="symbol">= </span><span class="constant_value">15 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_FILE_CORRUPT </span><span class="symbol">= </span><span class="constant_value">16 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_FILE_EOF </span><span class="symbol">= </span><span class="constant_value">17 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_CANT_OPEN </span><span class="symbol">= </span><span class="constant_value">18 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_CANT_CREATE </span><span class="symbol">= </span><span class="constant_value">19 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERROR_QUERY_FAILED </span><span class="symbol">= </span><span class="constant_value">20 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_ALREADY_IN_USE </span><span class="symbol">= </span><span class="constant_value">21 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_LOCKED </span><span class="symbol">= </span><span class="constant_value">22 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_TIMEOUT </span><span class="symbol">= </span><span class="constant_value">23 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_CANT_AQUIRE_RESOURCE </span><span class="symbol">= </span><span class="constant_value">24 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_INVALID_DATA </span><span class="symbol">= </span><span class="constant_value">26 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_INVALID_PARAMETER </span><span class="symbol">= </span><span class="constant_value">27 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_ALREADY_EXISTS </span><span class="symbol">= </span><span class="constant_value">28 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_DOES_NOT_EXIST </span><span class="symbol">= </span><span class="constant_value">29 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_DATABASE_CANT_READ </span><span class="symbol">= </span><span class="constant_value">30 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_DATABASE_CANT_WRITE </span><span class="symbol">= </span><span class="constant_value">31 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_COMPILATION_FAILED </span><span class="symbol">= </span><span class="constant_value">32 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_METHOD_NOT_FOUND </span><span class="symbol">= </span><span class="constant_value">33 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_LINK_FAILED </span><span class="symbol">= </span><span class="constant_value">34 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_SCRIPT_FAILED </span><span class="symbol">= </span><span class="constant_value">35 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_CYCLIC_LINK </span><span class="symbol">= </span><span class="constant_value">36 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_BUSY </span><span class="symbol">= </span><span class="constant_value">40 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_HELP </span><span class="symbol">= </span><span class="constant_value">42 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_BUG </span><span class="symbol">= </span><span class="constant_value">43 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">ERR_WTF </span><span class="symbol">= </span><span class="constant_value">45 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">PROPERTY_HINT_NONE </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- No hint for edited property.
- </span></div></li><li><div class="constant"><span class="identifier constant_name">PROPERTY_HINT_RANGE </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">PROPERTY_HINT_EXP_RANGE </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- Hint string is an exponential range, defined as "min,max" or "min,max,step". This is valid for integers and floats.
- </span></div></li><li><div class="constant"><span class="identifier constant_name">PROPERTY_HINT_ENUM </span><span class="symbol">= </span><span class="constant_value">3 </span><span class="constant_description">
- Property hint is an enumerated value, like "Hello,Something,Else". This is valid for integers, floats and strings properties.
- </span></div></li><li><div class="constant"><span class="identifier constant_name">PROPERTY_HINT_LENGTH </span><span class="symbol">= </span><span class="constant_value">5 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">PROPERTY_HINT_FLAGS </span><span class="symbol">= </span><span class="constant_value">7 </span><span class="constant_description">
- Property hint is a bitmask description, for bits 0,1,2,3 abd 5 the hint would be like "Bit0,Bit1,Bit2,Bit3,,Bit5". Valid only for integers.
- </span></div></li><li><div class="constant"><span class="identifier constant_name">PROPERTY_HINT_FILE </span><span class="symbol">= </span><span class="constant_value">8 </span><span class="constant_description">
- String property is a file (so pop up a file dialog when edited). Hint string can be a set of wildcards like "*.doc".
- </span></div></li><li><div class="constant"><span class="identifier constant_name">PROPERTY_HINT_DIR </span><span class="symbol">= </span><span class="constant_value">9 </span><span class="constant_description">
- String property is a directory (so pop up a file dialog when edited).
- </span></div></li><li><div class="constant"><span class="identifier constant_name">PROPERTY_HINT_RESOURCE_TYPE </span><span class="symbol">= </span><span class="constant_value">10 </span><span class="constant_description">
- String property is a resource, so open the resource popup menu when edited.
- </span></div></li><li><div class="constant"><span class="identifier constant_name">PROPERTY_USAGE_STORAGE </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- Property will be used as storage (default).
- </span></div></li><li><div class="constant"><span class="identifier constant_name">PROPERTY_USAGE_STORAGE </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- Property will be used as storage (default).
- </span></div></li><li><div class="constant"><span class="identifier constant_name">PROPERTY_USAGE_EDITOR </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- Property will be visible in editor (default).
- </span></div></li><li><div class="constant"><span class="identifier constant_name">PROPERTY_USAGE_NETWORK </span><span class="symbol">= </span><span class="constant_value">4 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">PROPERTY_USAGE_DEFAULT </span><span class="symbol">= </span><span class="constant_value">7 </span><span class="constant_description">
- Default usage (storage and editor).
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_NIL </span><span class="symbol">= </span><span class="constant_value">0 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_BOOL </span><span class="symbol">= </span><span class="constant_value">1 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_INT </span><span class="symbol">= </span><span class="constant_value">2 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_REAL </span><span class="symbol">= </span><span class="constant_value">3 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_STRING </span><span class="symbol">= </span><span class="constant_value">4 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_VECTOR2 </span><span class="symbol">= </span><span class="constant_value">5 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_RECT2 </span><span class="symbol">= </span><span class="constant_value">6 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_VECTOR3 </span><span class="symbol">= </span><span class="constant_value">7 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_MATRIX32 </span><span class="symbol">= </span><span class="constant_value">8 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_PLANE </span><span class="symbol">= </span><span class="constant_value">9 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_QUAT </span><span class="symbol">= </span><span class="constant_value">10 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_AABB </span><span class="symbol">= </span><span class="constant_value">11 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_MATRIX3 </span><span class="symbol">= </span><span class="constant_value">12 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_TRANSFORM </span><span class="symbol">= </span><span class="constant_value">13 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_COLOR </span><span class="symbol">= </span><span class="constant_value">14 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_IMAGE </span><span class="symbol">= </span><span class="constant_value">15 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_NODE_PATH </span><span class="symbol">= </span><span class="constant_value">16 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_RID </span><span class="symbol">= </span><span class="constant_value">17 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_OBJECT </span><span class="symbol">= </span><span class="constant_value">18 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_INPUT_EVENT </span><span class="symbol">= </span><span class="constant_value">19 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_DICTIONARY </span><span class="symbol">= </span><span class="constant_value">20 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_ARRAY </span><span class="symbol">= </span><span class="constant_value">21 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_RAW_ARRAY </span><span class="symbol">= </span><span class="constant_value">22 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_INT_ARRAY </span><span class="symbol">= </span><span class="constant_value">23 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_REAL_ARRAY </span><span class="symbol">= </span><span class="constant_value">24 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_STRING_ARRAY </span><span class="symbol">= </span><span class="constant_value">25 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_VECTOR2_ARRAY </span><span class="symbol">= </span><span class="constant_value">26 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_VECTOR3_ARRAY </span><span class="symbol">= </span><span class="constant_value">27 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_COLOR_ARRAY </span><span class="symbol">= </span><span class="constant_value">28 </span><span class="constant_description">
- </span></div></li><li><div class="constant"><span class="identifier constant_name">TYPE_MAX </span><span class="symbol">= </span><span class="constant_value">29 </span><span class="constant_description">
- </span></div></li></div><h4>Description:</h4><div class="description">
- Global scope constants and variables. This is all that resides in the globals, constants regarding error codes, scancodes, property hints, etc. It's not much.
- Singletons are also documented here, since they can be accessed from anywhere.
- </div><h4>Method Documentation:</h4></div><hr /><span>Copyright 2008-2010 Codenix SRL</span></body></html> \ No newline at end of file
diff --git a/doc/html/@Squirrel.html b/doc/html/@Squirrel.html
deleted file mode 100644
index ad4aaa49d8..0000000000
--- a/doc/html/@Squirrel.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<html><link href="main.css" rel="stylesheet" type="text/css" /><body><table class="top_table"><tr><td class="top_table"><image src="images/logo.png" /></td><td class="top_table"><a href="index.html">Index</a></td><td class="top_table"><a href="alphabetical.html">Classes</a></td><td class="top_table"><a href="category.html">Categories</a></td><td><a href="inheritance.html">Inheritance</a></td></tr></table><hr /><div class="class"><a name="@Squirrel"><h3 class="title class_title">@Squirrel</h3></a><div class="description class_description">
- </div><br /><div class="category"><span class="category">Category: </span><a class="category_ref" href="category.html#CATEGORY_Core">Core</a></div><h4>Method Documentation:</h4></div><hr /><span>Copyright 2008-2010 Codenix SRL</span></body></html> \ No newline at end of file
diff --git a/doc/html/tutorial01/0_home_red_coding_godot_doc_math_position.png b/doc/html/tutorial01/0_home_red_coding_godot_doc_math_position.png
deleted file mode 100644
index df52c05462..0000000000
--- a/doc/html/tutorial01/0_home_red_coding_godot_doc_math_position.png
+++ /dev/null
Binary files differ
diff --git a/doc/html/tutorial01/1_home_red_coding_godot_doc_math_direction.png b/doc/html/tutorial01/1_home_red_coding_godot_doc_math_direction.png
deleted file mode 100644
index 5b58274bcb..0000000000
--- a/doc/html/tutorial01/1_home_red_coding_godot_doc_math_direction.png
+++ /dev/null
Binary files differ
diff --git a/doc/html/tutorial01/2_home_red_coding_godot_doc_math_normals.png b/doc/html/tutorial01/2_home_red_coding_godot_doc_math_normals.png
deleted file mode 100644
index 73681a58ce..0000000000
--- a/doc/html/tutorial01/2_home_red_coding_godot_doc_math_normals.png
+++ /dev/null
Binary files differ
diff --git a/doc/html/tutorial01/tutorial.css b/doc/html/tutorial01/tutorial.css
deleted file mode 100644
index a518c6dff7..0000000000
--- a/doc/html/tutorial01/tutorial.css
+++ /dev/null
@@ -1,128 +0,0 @@
-
-/* start css.sty */
-.cmr-7{font-size:70%;}
-.cmmi-7{font-size:70%;font-style: italic;}
-.cmmi-10{font-style: italic;}
-.ectt-1000{ font-family: monospace;}
-.ectt-1000{ font-family: monospace;}
-.ectt-1000{ font-family: monospace;}
-.ectt-1000{ font-family: monospace;}
-.ectt-1000{ font-family: monospace;}
-.ecti-1000{ font-style: italic;}
-.ecti-1000{ font-style: italic;}
-.ecti-1000{ font-style: italic;}
-.ecti-1000{ font-style: italic;}
-.ecti-1000{ font-style: italic;}
-.ecti-0700{font-size:70%; font-style: italic;}
-.ecti-0700{ font-style: italic;}
-.ecti-0700{ font-style: italic;}
-.ecti-0700{ font-style: italic;}
-.ecti-0700{ font-style: italic;}
-.ecrm-0700{font-size:70%;}
-p.noindent { text-indent: 0em }
-td p.noindent { text-indent: 0em; margin-top:0em; }
-p.nopar { text-indent: 0em; }
-p.indent{ text-indent: 1.5em }
-@media print {div.crosslinks {visibility:hidden;}}
-a img { border-top: 0; border-left: 0; border-right: 0; }
-center { margin-top:1em; margin-bottom:1em; }
-td center { margin-top:0em; margin-bottom:0em; }
-.Canvas { position:relative; }
-img.math{vertical-align:middle;}
-li p.indent { text-indent: 0em }
-.enumerate1 {list-style-type:decimal;}
-.enumerate2 {list-style-type:lower-alpha;}
-.enumerate3 {list-style-type:lower-roman;}
-.enumerate4 {list-style-type:upper-alpha;}
-div.newtheorem { margin-bottom: 2em; margin-top: 2em;}
-.obeylines-h,.obeylines-v {white-space: nowrap; }
-div.obeylines-v p { margin-top:0; margin-bottom:0; }
-.overline{ text-decoration:overline; }
-.overline img{ border-top: 1px solid black; }
-td.displaylines {text-align:center; white-space:nowrap;}
-.centerline {text-align:center;}
-.rightline {text-align:right;}
-div.verbatim {font-family: monospace; white-space: nowrap; text-align:left; clear:both; }
-.fbox {padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; }
-div.fbox {display:table}
-div.center div.fbox {text-align:center; clear:both; padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; }
-table.minipage{width:100%;}
-div.center, div.center div.center {text-align: center; margin-left:1em; margin-right:1em;}
-div.center div {text-align: left;}
-div.flushright, div.flushright div.flushright {text-align: right;}
-div.flushright div {text-align: left;}
-div.flushleft {text-align: left;}
-.underline{ text-decoration:underline; }
-.underline img{ border-bottom: 1px solid black; margin-bottom:1pt; }
-.framebox-c, .framebox-l, .framebox-r { padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; }
-.framebox-c {text-align:center;}
-.framebox-l {text-align:left;}
-.framebox-r {text-align:right;}
-span.thank-mark{ vertical-align: super }
-span.footnote-mark sup.textsuperscript, span.footnote-mark a sup.textsuperscript{ font-size:80%; }
-div.tabular, div.center div.tabular {text-align: center; margin-top:0.5em; margin-bottom:0.5em; }
-table.tabular td p{margin-top:0em;}
-table.tabular {margin-left: auto; margin-right: auto;}
-div.td00{ margin-left:0pt; margin-right:0pt; }
-div.td01{ margin-left:0pt; margin-right:5pt; }
-div.td10{ margin-left:5pt; margin-right:0pt; }
-div.td11{ margin-left:5pt; margin-right:5pt; }
-table[rules] {border-left:solid black 0.4pt; border-right:solid black 0.4pt; }
-td.td00{ padding-left:0pt; padding-right:0pt; }
-td.td01{ padding-left:0pt; padding-right:5pt; }
-td.td10{ padding-left:5pt; padding-right:0pt; }
-td.td11{ padding-left:5pt; padding-right:5pt; }
-table[rules] {border-left:solid black 0.4pt; border-right:solid black 0.4pt; }
-.hline hr, .cline hr{ height : 1px; margin:0px; }
-.tabbing-right {text-align:right;}
-span.TEX {letter-spacing: -0.125em; }
-span.TEX span.E{ position:relative;top:0.5ex;left:-0.0417em;}
-a span.TEX span.E {text-decoration: none; }
-span.LATEX span.A{ position:relative; top:-0.5ex; left:-0.4em; font-size:85%;}
-span.LATEX span.TEX{ position:relative; left: -0.4em; }
-div.float img, div.float .caption {text-align:center;}
-div.figure img, div.figure .caption {text-align:center;}
-.marginpar {width:20%; float:right; text-align:left; margin-left:auto; margin-top:0.5em; font-size:85%; text-decoration:underline;}
-.marginpar p{margin-top:0.4em; margin-bottom:0.4em;}
-table.equation {width:100%;}
-.equation td{text-align:center; }
-td.equation { margin-top:1em; margin-bottom:1em; }
-td.equation-label { width:5%; text-align:center; }
-td.eqnarray4 { width:5%; white-space: normal; }
-td.eqnarray2 { width:5%; }
-table.eqnarray-star, table.eqnarray {width:100%;}
-div.eqnarray{text-align:center;}
-div.array {text-align:center;}
-div.pmatrix {text-align:center;}
-table.pmatrix {width:100%;}
-span.pmatrix img{vertical-align:middle;}
-div.pmatrix {text-align:center;}
-table.pmatrix {width:100%;}
-img.cdots{vertical-align:middle;}
-.partToc a, .partToc, .likepartToc a, .likepartToc {line-height: 200%; font-weight:bold; font-size:110%;}
-.index-item, .index-subitem, .index-subsubitem {display:block}
-.caption td.id{font-weight: bold; white-space: nowrap; }
-table.caption {text-align:center;}
-h1.partHead{text-align: center}
-p.bibitem { text-indent: -2em; margin-left: 2em; margin-top:0.6em; margin-bottom:0.6em; }
-p.bibitem-p { text-indent: 0em; margin-left: 2em; margin-top:0.6em; margin-bottom:0.6em; }
-.paragraphHead, .likeparagraphHead { margin-top:2em; font-weight: bold;}
-.subparagraphHead, .likesubparagraphHead { font-weight: bold;}
-.quote {margin-bottom:0.25em; margin-top:0.25em; margin-left:1em; margin-right:1em; text-align:justify;}
-.verse{white-space:nowrap; margin-left:2em}
-div.maketitle {text-align:center;}
-h2.titleHead{text-align:center;}
-div.maketitle{ margin-bottom: 2em; }
-div.author, div.date {text-align:center;}
-div.thanks{text-align:left; margin-left:10%; font-size:85%; font-style:italic; }
-div.author{white-space: nowrap;}
-.quotation {margin-bottom:0.25em; margin-top:0.25em; margin-left:1em; }
-.abstract p {margin-left:5%; margin-right:5%;}
-table.abstract {width:100%;}
-.lstlisting .label{margin-right:0.5em; }
-div.lstlisting{font-family: monospace; white-space: nowrap; margin-top:0.5em; margin-bottom:0.5em; }
-div.lstinputlisting{ font-family: monospace; white-space: nowrap; }
-.lstinputlisting .label{margin-right:0.5em;}
-.figure img.graphics {margin-left:10%;}
-/* end css.sty */
-
diff --git a/doc/html/tutorial01/tutorial.html b/doc/html/tutorial01/tutorial.html
deleted file mode 100644
index 45c0258709..0000000000
--- a/doc/html/tutorial01/tutorial.html
+++ /dev/null
@@ -1,902 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-<html >
-<head><title></title>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-<meta name="generator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/)">
-<meta name="originator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/)">
-<!-- html -->
-<meta name="src" content="tutorial.tex">
-<meta name="date" content="2009-10-07 00:28:00">
-<link rel="stylesheet" type="text/css" href="tutorial.css">
-</head><body
->
- <h3 class="sectionHead"><span class="titlemark">1 </span> <a
- id="x1-10001"></a>Introduction to 3D Math</h3>
-<!--l. 27--><p class="noindent" >
- <h4 class="subsectionHead"><span class="titlemark">1.1 </span> <a
- id="x1-20001.1"></a>Introduction</h4>
-<!--l. 29--><p class="noindent" >There are many approaches to understanding the type of 3D math used in video
-games, modelling, ray-tracing, etc. The usual is through vector algebra, matrices, and
-linear transformations and, while they are not completely necesary to understand
-most of the aspects of 3D game programming (from the theorical point of view), they
-provide a common language to communicate with other programmers or
-engineers.
-<!--l. 36--><p class="indent" > This tutorial will focus on explaining all the basic concepts needed for a
-programmer to understand how to develop 3D games without getting too deep into
-algebra. Instead of a math-oriented language, code examples will be given instead
-when possible. The reason for this is that. while programmers may have
-different backgrounds or experience (be it scientific, engineering or self taught),
-code is the most familiar language and the lowest common denominator for
-understanding.
-<!--l. 45--><p class="noindent" >
- <h4 class="subsectionHead"><span class="titlemark">1.2 </span> <a
- id="x1-30001.2"></a>Vectors</h4>
-<!--l. 48--><p class="noindent" >
- <h5 class="subsubsectionHead"><span class="titlemark">1.2.1 </span> <a
- id="x1-40001.2.1"></a>Brief Introduction</h5>
-<!--l. 50--><p class="noindent" >When writing 2D games, interfaces and other applications, the typical convention is
-to define coordinates as an <span
-class="ecti-1000">x,y </span>pair, <span
-class="ecti-1000">x </span>representing the horizontal offset and <span
-class="ecti-1000">y </span>the
-vertical one. In most cases, the unit for both is <span
-class="ecti-1000">pixels</span>. This makes sense given the
-screen is just a rectangle in two dimensions.
-<!--l. 56--><p class="indent" > An <span
-class="ecti-1000">x,y </span>pair can be used for two purposes. It can be an absolute position (screen
-cordinate in the previous case), or a relative direction, if we trace an arrow from the
-origin (0,0 coordinates) to it&#8217;s position.
-<div class="center"
->
-<!--l. 60--><p class="noindent" >
-
-<div class="tabular">
- <table id="TBL-1" class="tabular"
-cellspacing="0" cellpadding="0"
-><colgroup id="TBL-1-1g"><col
-id="TBL-1-1"><col
-id="TBL-1-2"><col
-id="TBL-1-3"></colgroup><tr
- style="vertical-align:baseline;" id="TBL-1-1-"><td style="white-space:nowrap; text-align:center;" id="TBL-1-1-1"
-class="td11"><img
-src="tutorial0x.png" alt="PIC" class="graphics" width="100.375pt" height="100.375pt" ><!--tex4ht:graphics
-name="tutorial0x.png" src="0_home_red_coding_godot_doc_math_position.eps"
---></td><td style="white-space:nowrap; text-align:center;" id="TBL-1-1-2"
-class="td11"></td><td style="white-space:nowrap; text-align:center;" id="TBL-1-1-3"
-class="td11"><img
-src="tutorial1x.png" alt="PIC" class="graphics" width="100.375pt" height="100.375pt" ><!--tex4ht:graphics
-name="tutorial1x.png" src="1_home_red_coding_godot_doc_math_direction.eps"
---></td>
-</tr><tr
- style="vertical-align:baseline;" id="TBL-1-2-"><td style="white-space:nowrap; text-align:center;" id="TBL-1-2-1"
-class="td11"> <span
-class="ecti-0700">Position </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-1-2-2"
-class="td11"></td><td style="white-space:nowrap; text-align:center;" id="TBL-1-2-3"
-class="td11"> <span
-class="ecti-0700">Direction </span></td>
-</tr><tr
- style="vertical-align:baseline;" id="TBL-1-3-"><td style="white-space:nowrap; text-align:center;" id="TBL-1-3-1"
-class="td11"> </td>
-</tr></table></div>
-</div>
-<!--l. 67--><p class="indent" > When used as a direction, this pair is called a <span
-class="ecti-1000">vector</span>, and two properties can be
-observed: The first is the <span
-class="ecti-1000">magnitude </span>or <span
-class="ecti-1000">length </span>, and the second is the direction. In
-two dimensions, direction can be an angle. The <span
-class="ecti-1000">magnitude </span>or <span
-class="ecti-1000">length </span>can be computed
-by simply using Pithagoras theorem:
-<div class="center"
->
-<!--l. 73--><p class="noindent" >
-<div class="tabular"> <table id="TBL-2" class="tabular"
-cellspacing="0" cellpadding="0"
-><colgroup id="TBL-2-1g"><col
-id="TBL-2-1"><col
-id="TBL-2-2"></colgroup><tr
- style="vertical-align:baseline;" id="TBL-2-1-"><td style="white-space:nowrap; text-align:center;" id="TBL-2-1-1"
-class="td11"><img
-src="tutorial2x.png" alt="&#x2218;x2-+-y2-" class="sqrt" ></td><td style="white-space:nowrap; text-align:center;" id="TBL-2-1-2"
-class="td11"><img
-src="tutorial3x.png" alt="&#x2218;x2-+-y2 +-z2" class="sqrt" ></td>
-</tr><tr
- style="vertical-align:baseline;" id="TBL-2-2-"><td style="white-space:nowrap; text-align:center;" id="TBL-2-2-1"
-class="td11"> <span
-class="ecti-0700">2D </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-2-2-2"
-class="td11"> <span
-class="ecti-0700">3D </span></td>
-</tr><tr
- style="vertical-align:baseline;" id="TBL-2-3-"><td style="white-space:nowrap; text-align:center;" id="TBL-2-3-1"
-class="td11"> </td>
-</tr></table></div>
-</div>
-<!--l. 80--><p class="indent" > The direction can be an arbitrary angle from either the <span
-class="ecti-1000">x </span>or <span
-class="ecti-1000">y </span>axis, and could be
-computed by using trigonometry, or just using the usual <span
-class="ecti-1000">atan2 </span>function present in
-most math libraries. However, when dealing with 3D, the direction can&#8217;t be described
-as an angle. To separate magnitude and direction, 3D uses the concept of <span
-class="ecti-1000">normal</span>
-<span
-class="ecti-1000">vectors.</span>
-<!--l. 88--><p class="noindent" >
- <h5 class="subsubsectionHead"><span class="titlemark">1.2.2 </span> <a
- id="x1-50001.2.2"></a>Implementation</h5>
-<!--l. 90--><p class="noindent" >Vectors are implemented in Godot Engine as a class named <span
-class="ecti-1000">Vector3 </span>for 3D, and as
-both <span
-class="ecti-1000">Vector2</span>, <span
-class="ecti-1000">Point2 </span>or <span
-class="ecti-1000">Size2 </span>in 2D (they are all aliases). They are used for any
-purpose where a pair of 2D or 3D values (described as <span
-class="ecti-1000">x,y </span>or <span
-class="ecti-1000">x,y,z) </span>is needed. This is
-somewhat a standard in most libraries or engines. In the script API, they can be
-instanced like this:
- <!--l. 98-->
- <div class="lstlisting"><span class="label"><a
- id="x1-5001r1"></a></span>a&#x00A0;=&#x00A0;Vector3()&#x00A0;<br /><span class="label"><a
- id="x1-5002r2"></a></span>a&#x00A0;=&#x00A0;Vector2(&#x00A0;2.0,&#x00A0;3.4&#x00A0;)
- </div>
-
-<!--l. 104--><p class="indent" > Vectors also support the common operators <span
-class="ecti-1000">+, -, / and * </span>for addition,
-substraction, multiplication and division.
- <!--l. 108-->
- <div class="lstlisting"><span class="label"><a
- id="x1-5003r1"></a></span>a&#x00A0;=&#x00A0;Vector3(1,2,3)&#x00A0;<br /><span class="label"><a
- id="x1-5004r2"></a></span>b&#x00A0;=&#x00A0;Vector3(4,5,6)&#x00A0;<br /><span class="label"><a
- id="x1-5005r3"></a></span>c&#x00A0;=&#x00A0;Vector3()&#x00A0;<br /><span class="label"><a
- id="x1-5006r4"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-5007r5"></a></span>//&#x00A0;writing&#x00A0;<br /><span class="label"><a
- id="x1-5008r6"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-5009r7"></a></span>c&#x00A0;=&#x00A0;a&#x00A0;+&#x00A0;b&#x00A0;<br /><span class="label"><a
- id="x1-5010r8"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-5011r9"></a></span>//&#x00A0;is&#x00A0;the&#x00A0;same&#x00A0;as&#x00A0;writing&#x00A0;<br /><span class="label"><a
- id="x1-5012r10"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-5013r11"></a></span>c.x&#x00A0;=&#x00A0;a.x&#x00A0;+&#x00A0;b.x&#x00A0;<br /><span class="label"><a
- id="x1-5014r12"></a></span>c.y&#x00A0;=&#x00A0;a.y&#x00A0;+&#x00A0;b.y&#x00A0;<br /><span class="label"><a
- id="x1-5015r13"></a></span>c.z&#x00A0;=&#x00A0;a.z&#x00A0;+&#x00A0;b.z&#x00A0;<br /><span class="label"><a
- id="x1-5016r14"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-5017r15"></a></span>//&#x00A0;both&#x00A0;will&#x00A0;result&#x00A0;in&#x00A0;a&#x00A0;vector&#x00A0;containing&#x00A0;(5,7,9).&#x00A0;<br /><span class="label"><a
- id="x1-5018r16"></a></span>//&#x00A0;the&#x00A0;same&#x00A0;happens&#x00A0;for&#x00A0;the&#x00A0;rest&#x00A0;of&#x00A0;the&#x00A0;operators.
- </div>
-<!--l. 128--><p class="indent" > Vectors also can perform a wide variety of built-in functions, their most common
-usages will be explored next.
-<!--l. 132--><p class="noindent" >
- <h5 class="subsubsectionHead"><span class="titlemark">1.2.3 </span> <a
- id="x1-60001.2.3"></a>Normal Vectors</h5>
-<!--l. 134--><p class="noindent" >Two points ago, it was mentioned that 3D vectors can&#8217;t describe their direction as an
-agle (as 2D vectors can). Because of this, <span
-class="ecti-1000">normal vectors </span>become important for
-separating a vector between <span
-class="ecti-1000">direction </span>and <span
-class="ecti-1000">magnitude.</span>
-<!--l. 139--><p class="indent" > A <span
-class="ecti-1000">normal vector </span>is a vector with a <span
-class="ecti-1000">magnitude </span>of <span
-class="ecti-1000">1. </span>This means, no matter where
-the vector is pointing to, it&#8217;s length is always <span
-class="ecti-1000">1</span>.
- <div class="tabular">
- <table id="TBL-3" class="tabular"
-cellspacing="0" cellpadding="0"
-><colgroup id="TBL-3-1g"><col
-id="TBL-3-1"></colgroup><tr
- style="vertical-align:baseline;" id="TBL-3-1-"><td style="white-space:nowrap; text-align:center;" id="TBL-3-1-1"
-class="td11"><img
-src="tutorial4x.png" alt="PIC" class="graphics" width="100.375pt" height="100.375pt" ><!--tex4ht:graphics
-name="tutorial4x.png" src="2_home_red_coding_godot_doc_math_normals.eps"
---></td>
-</tr><tr
- style="vertical-align:baseline;" id="TBL-3-2-"><td style="white-space:nowrap; text-align:center;" id="TBL-3-2-1"
-class="td11"> <span
-class="ecrm-0700">Normal vectors aroud the origin. </span></td>
-</tr><tr
- style="vertical-align:baseline;" id="TBL-3-3-"><td style="white-space:nowrap; text-align:center;" id="TBL-3-3-1"
-class="td11"> </td> </tr></table>
-</div>
-<!--l. 148--><p class="indent" > Normal vectors have endless uses in 3D graphics programming, so it&#8217;s
-recommended to get familiar with them as much as possible.
-<!--l. 152--><p class="noindent" >
- <h5 class="subsubsectionHead"><span class="titlemark">1.2.4 </span> <a
- id="x1-70001.2.4"></a>Normalization</h5>
-<!--l. 154--><p class="noindent" >Normalization is the process through which normal vectors are obtained
-from regular vectors. In other words, normalization is used to reduce the
-<span
-class="ecti-1000">magnitude </span>of any vector to <span
-class="ecti-1000">1</span>. (except of course, unless the vector is (0,0,0)
-).
-<!--l. 159--><p class="indent" > To normalize a vector, it must be divided by its magnitude (which should be
-greater than zero):
- <!--l. 163-->
- <div class="lstlisting"><span class="label"><a
- id="x1-7001r1"></a></span><span
-class="ecti-1000">//</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">a</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">custom</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">vector</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">is</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">created</span>&#x00A0;<br /><span class="label"><a
- id="x1-7002r2"></a></span>a&#x00A0;=&#x00A0;Vector3(4,5,6)&#x00A0;<br /><span class="label"><a
- id="x1-7003r3"></a></span><span
-class="ecti-1000">//</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">&#8217;</span><span
-class="ecti-1000">l</span><span
-class="ecti-1000">&#8217;</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">is</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">a</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">single</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">real</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">number</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">(</span><span
-class="ecti-1000">or</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">scalar</span><span
-class="ecti-1000">)</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">containight</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">the</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">length</span>&#x00A0;<br /><span class="label"><a
- id="x1-7004r4"></a></span>l&#x00A0;=&#x00A0;Math.sqrt(&#x00A0;a.x<span
-class="cmsy-10">*</span>a.x&#x00A0;+&#x00A0;a.y<span
-class="cmsy-10">*</span>a.y&#x00A0;+&#x00A0;a.z<span
-class="cmsy-10">*</span>a.z&#x00A0;)&#x00A0;<br /><span class="label"><a
- id="x1-7005r5"></a></span><span
-class="ecti-1000">//</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">the</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">vector</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">&#8217;</span><span
-class="ecti-1000">a</span><span
-class="ecti-1000">&#8217;</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">is</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">divided</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">by</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">its</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">length</span><span
-class="ecti-1000">,</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">by</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">performing</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">scalar</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">divide</span>&#x00A0;<br /><span class="label"><a
- id="x1-7006r6"></a></span>a&#x00A0;=&#x00A0;a&#x00A0;/&#x00A0;l&#x00A0;<br /><span class="label"><a
- id="x1-7007r7"></a></span><span
-class="ecti-1000">//</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">which</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">is</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">the</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">same</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">as</span>&#x00A0;<br /><span class="label"><a
- id="x1-7008r8"></a></span>a.x&#x00A0;=&#x00A0;a.x&#x00A0;/&#x00A0;l&#x00A0;<br /><span class="label"><a
- id="x1-7009r9"></a></span>a.y&#x00A0;=&#x00A0;a.y&#x00A0;/&#x00A0;l&#x00A0;<br /><span class="label"><a
- id="x1-7010r10"></a></span>a.z&#x00A0;=&#x00A0;a.z&#x00A0;/&#x00A0;l
-
- </div>
-<!--l. 177--><p class="indent" > Vector3 contains two built in functions for normalization:
- <!--l. 180-->
- <div class="lstlisting"><span class="label"><a
- id="x1-7011r1"></a></span>a&#x00A0;=&#x00A0;Vector3(4,5,6)&#x00A0;<br /><span class="label"><a
- id="x1-7012r2"></a></span>a.normalize()&#x00A0;<span
-class="ecti-1000">//</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">in</span><span
-class="cmsy-10">-</span><span
-class="ecti-1000">place</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">normalization</span>&#x00A0;<br /><span class="label"><a
- id="x1-7013r3"></a></span>b&#x00A0;=&#x00A0;a.normalized()&#x00A0;<span
-class="ecti-1000">//</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">returns</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">a</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">copy</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">of</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">a</span><span
-class="ecti-1000">,</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">normalized</span>
- </div>
-<!--l. 188--><p class="noindent" >
- <h5 class="subsubsectionHead"><span class="titlemark">1.2.5 </span> <a
- id="x1-80001.2.5"></a>Dot Product</h5>
-<!--l. 190--><p class="noindent" >The dot product is, pheraps, the most useful operation that can be applied to 3D
-vectors. In the surface, it&#8217;s multiple usages are not very obvious, but in depth it can
-provide very useful information between two vectors (be it direction or just points in
-space).
-<!--l. 195--><p class="indent" > The dot product takes two vectors (<span
-class="ecti-1000">a </span>and <span
-class="ecti-1000">b </span>in the example) and returns a scalar
-(single real number):
-<div class="center"
->
-<!--l. 198--><p class="noindent" >
-<!--l. 199--><p class="noindent" ><span
-class="cmmi-10">a</span><sub><span
-class="cmmi-7">x</span></sub><span
-class="cmmi-10">b</span><sub><span
-class="cmmi-7">x</span></sub> <span
-class="cmr-10">+ </span><span
-class="cmmi-10">a</span><sub><span
-class="cmmi-7">y</span></sub><span
-class="cmmi-10">b</span><sub><span
-class="cmmi-7">y</span></sub> <span
-class="cmr-10">+ </span><span
-class="cmmi-10">a</span><sub><span
-class="cmmi-7">z</span></sub><span
-class="cmmi-10">b</span><sub><span
-class="cmmi-7">z</span></sub>
-</div>
-<!--l. 202--><p class="indent" > The same expressed in code:
- <!--l. 205-->
- <div class="lstlisting"><span class="label"><a
- id="x1-8001r1"></a></span>a&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
- id="x1-8002r2"></a></span>b&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
- id="x1-8003r3"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-8004r4"></a></span>c&#x00A0;=&#x00A0;a.x<span
-class="cmsy-10">*</span>b.x&#x00A0;+&#x00A0;a.y<span
-class="cmsy-10">*</span>b.y&#x00A0;+&#x00A0;a.z<span
-class="cmsy-10">*</span>b.z&#x00A0;<br /><span class="label"><a
- id="x1-8005r5"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-8006r6"></a></span><span
-class="ecti-1000">//</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">using</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">built</span><span
-class="cmsy-10">-</span><span
-class="ecti-1000">in</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">dot</span><span
-class="ecti-1000">()</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">function</span>&#x00A0;<br /><span class="label"><a
- id="x1-8007r7"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-8008r8"></a></span>c&#x00A0;=&#x00A0;a.dot(b)
- </div>
-<!--l. 218--><p class="indent" > The dot product presents several useful properties:
- <ul class="itemize1">
- <li class="itemize">If both <span
-class="ecti-1000">a </span>and <span
-class="ecti-1000">b </span>parameters to a <span
-class="ecti-1000">dot product </span>are direction vectors, dot
- product will return positive if both point towards the same direction,
- negative if both point towards opposite directions, and zero if they are
- orthogonal (one is perpendicular to the other).
- </li>
- <li class="itemize">If both <span
-class="ecti-1000">a </span>and <span
-class="ecti-1000">b </span>parameters to a <span
-class="ecti-1000">dot product </span>are <span
-class="ecti-1000">normalized </span>direction
- vectors, then the dot product will return the cosine of the angle between
- them (ranging from 1 if they are equal, 0 if they are orthogonal, and -1 if
- they are opposed (a == -b)).
- </li>
- <li class="itemize">If <span
-class="ecti-1000">a </span>is a <span
-class="ecti-1000">normalized </span>direction vector and <span
-class="ecti-1000">b </span>is a point, the dot product will
- return the distance from <span
-class="ecti-1000">b </span>to the plane passing through the origin, with
- normal <span
-class="ecti-1000">a (see item about planes)</span>
-
- </li>
- <li class="itemize">More uses will be presented later in this tutorial.</li></ul>
-<!--l. 236--><p class="noindent" >
- <h5 class="subsubsectionHead"><span class="titlemark">1.2.6 </span> <a
- id="x1-90001.2.6"></a>Cross Product</h5>
-<!--l. 238--><p class="noindent" >The <span
-class="ecti-1000">cross product </span>also takes two vectors <span
-class="ecti-1000">a </span>and <span
-class="ecti-1000">b</span>, but returns another vector <span
-class="ecti-1000">c </span>that is
-orthogonal to the two previous ones.
-<div class="center"
->
-<!--l. 242--><p class="noindent" >
-<!--l. 243--><p class="noindent" ><span
-class="cmmi-10">c</span><sub><span
-class="cmmi-7">x</span></sub> <span
-class="cmr-10">= </span><span
-class="cmmi-10">a</span><sub><span
-class="cmmi-7">x</span></sub><span
-class="cmmi-10">b</span><sub><span
-class="cmmi-7">z</span></sub> <span
-class="cmsy-10">- </span><span
-class="cmmi-10">a</span><sub><span
-class="cmmi-7">z</span></sub><span
-class="cmmi-10">b</span><sub><span
-class="cmmi-7">y</span></sub>
-</div>
-<div class="center"
->
-<!--l. 246--><p class="noindent" >
-<!--l. 247--><p class="noindent" ><span
-class="cmmi-10">c</span><sub><span
-class="cmmi-7">y</span></sub> <span
-class="cmr-10">= </span><span
-class="cmmi-10">a</span><sub><span
-class="cmmi-7">z</span></sub><span
-class="cmmi-10">b</span><sub><span
-class="cmmi-7">x</span></sub> <span
-class="cmsy-10">- </span><span
-class="cmmi-10">a</span><sub><span
-class="cmmi-7">x</span></sub><span
-class="cmmi-10">b</span><sub><span
-class="cmmi-7">z</span></sub>
-</div>
-<div class="center"
->
-<!--l. 250--><p class="noindent" >
-<!--l. 251--><p class="noindent" ><span
-class="cmmi-10">c</span><sub><span
-class="cmmi-7">z</span></sub> <span
-class="cmr-10">= </span><span
-class="cmmi-10">a</span><sub><span
-class="cmmi-7">x</span></sub><span
-class="cmmi-10">b</span><sub><span
-class="cmmi-7">y</span></sub> <span
-class="cmsy-10">- </span><span
-class="cmmi-10">a</span><sub><span
-class="cmmi-7">y</span></sub><span
-class="cmmi-10">b</span><sub><span
-class="cmmi-7">x</span></sub>
-</div>
-<!--l. 254--><p class="indent" > The same in code:
- <!--l. 257-->
- <div class="lstlisting"><span class="label"><a
- id="x1-9001r1"></a></span>a&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
- id="x1-9002r2"></a></span>b&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
- id="x1-9003r3"></a></span>c&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
- id="x1-9004r4"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-9005r5"></a></span>c.x&#x00A0;=&#x00A0;a.x<span
-class="cmsy-10">*</span>b.z&#x00A0;<span
-class="cmsy-10">-</span>&#x00A0;a.z<span
-class="cmsy-10">*</span>b.y&#x00A0;<br /><span class="label"><a
- id="x1-9006r6"></a></span>c.y&#x00A0;=&#x00A0;a.z<span
-class="cmsy-10">*</span>b.x&#x00A0;<span
-class="cmsy-10">-</span>&#x00A0;a.x<span
-class="cmsy-10">*</span>b.z&#x00A0;<br /><span class="label"><a
- id="x1-9007r7"></a></span>c.z&#x00A0;=&#x00A0;a.x<span
-class="cmsy-10">*</span>b.y&#x00A0;<span
-class="cmsy-10">-</span>&#x00A0;a.y<span
-class="cmsy-10">*</span>b.x&#x00A0;<br /><span class="label"><a
- id="x1-9008r8"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-9009r9"></a></span>//&#x00A0;or&#x00A0;using&#x00A0;the&#x00A0;built<span
-class="cmsy-10">-</span>in&#x00A0;function&#x00A0;<br /><span class="label"><a
- id="x1-9010r10"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-9011r11"></a></span>c&#x00A0;=&#x00A0;a.cross(b)
- </div>
-<!--l. 273--><p class="indent" > The <span
-class="ecti-1000">cross product </span>also presents several useful properties:
- <ul class="itemize1">
- <li class="itemize">As mentioned, the resulting vector <span
-class="ecti-1000">c </span>is orthogonal to the input vectors <span
-class="ecti-1000">a</span>
- and <span
-class="ecti-1000">b.</span>
- </li>
- <li class="itemize">Since the <span
-class="ecti-1000">cross product </span>is anticommutative, swapping <span
-class="ecti-1000">a </span>and <span
-class="ecti-1000">b </span>will result
- in a negated vector <span
-class="ecti-1000">c.</span>
-
- </li>
- <li class="itemize">if <span
-class="ecti-1000">a </span>and <span
-class="ecti-1000">b </span>are taken from two of the segmets <span
-class="ecti-1000">AB</span>, <span
-class="ecti-1000">BC </span>or <span
-class="ecti-1000">CA </span>that form a
- 3D triangle, the magnitude of the resulting vector divided by 2 is the area
- of that triangle.
- </li>
- <li class="itemize">The direction of the resulting vector <span
-class="ecti-1000">c </span>in the previous triangle example
- determines wether the points A,B and C are arranged in clocwise or
- counter-clockwise order.</li></ul>
-<!--l. 287--><p class="noindent" >
- <h4 class="subsectionHead"><span class="titlemark">1.3 </span> <a
- id="x1-100001.3"></a>Plane</h4>
-<!--l. 290--><p class="noindent" >
- <h5 class="subsubsectionHead"><span class="titlemark">1.3.1 </span> <a
- id="x1-110001.3.1"></a>Theory</h5>
-<!--l. 292--><p class="noindent" >A plane can be considered as an infinite, flat surface that splits space in two halves,
-usually one named positive and one named negative. In regular mathematics, a plane
-formula is described as:
-<div class="center"
->
-<!--l. 296--><p class="noindent" >
-<!--l. 297--><p class="noindent" ><span
-class="cmmi-10">ax </span><span
-class="cmr-10">+ </span><span
-class="cmmi-10">by </span><span
-class="cmr-10">+ </span><span
-class="cmmi-10">cz </span><span
-class="cmr-10">+ </span><span
-class="cmmi-10">d</span>
-</div>
-<!--l. 300--><p class="indent" > However, in 3D programming, this form alone is often of little use. For planes to
-become useful, they must be in normalized form.
-<!--l. 303--><p class="indent" > A normalized plane consists of a <span
-class="ecti-1000">normal vector n </span>and a <span
-class="ecti-1000">distance d. </span>To normalize
-a plane, a vector <span
-class="ecti-1000">n </span>and distance <span
-class="ecti-1000">d&#8217; </span>are created this way:
-<!--l. 307--><p class="indent" > <span
-class="cmmi-10">n</span><sub><span
-class="cmmi-7">x</span></sub> <span
-class="cmr-10">= </span><span
-class="cmmi-10">a</span>
-<!--l. 309--><p class="indent" > <span
-class="cmmi-10">n</span><sub><span
-class="cmmi-7">y</span></sub> <span
-class="cmr-10">= </span><span
-class="cmmi-10">b</span>
-<!--l. 311--><p class="indent" > <span
-class="cmmi-10">n</span><sub><span
-class="cmmi-7">z</span></sub> <span
-class="cmr-10">= </span><span
-class="cmmi-10">c</span>
-<!--l. 313--><p class="indent" > <span
-class="cmmi-10">d</span><span
-class="cmsy-10">&#x2032; </span><span
-class="cmr-10">= </span><span
-class="cmmi-10">d</span>
-<!--l. 315--><p class="indent" > Finally, both <span
-class="ecti-1000">n </span>and <span
-class="ecti-1000">d&#8217; </span>are both divided by the magnitude of n.
-<!--l. 318--><p class="indent" > In any case, normalizing planes is not often needed (this was mostly for
-explanation purposes), and normalized planes are useful because they can be created
-and used easily.
-<!--l. 322--><p class="indent" > A normalized plane could be visualized as a plane pointing towards normal <span
-class="ecti-1000">n,</span>
-offseted by <span
-class="ecti-1000">d </span>in the direction of <span
-class="ecti-1000">n</span>.
-<!--l. 325--><p class="indent" > In other words, take <span
-class="ecti-1000">n</span>, multiply it by scalar <span
-class="ecti-1000">d </span>and the resulting point will be part
-of the plane. This may need some thinking, so an example with a 2D normal vector
-(z is 0, so plane is orthogonal to it) is provided:
-<!--l. 330--><p class="indent" > Some operations can be done with normalized planes:
-
- <ul class="itemize1">
- <li class="itemize">Given any point <span
-class="ecti-1000">p</span>, the distance from it to a plane can be computed by
- doing: n.dot(p) - d
- </li>
- <li class="itemize">If the resulting distance in the previous point is negative, the point is
- below the plane.
- </li>
- <li class="itemize">Convex polygonal shapes can be defined by enclosing them in planes (the
- physics engine uses this property)</li></ul>
-<!--l. 340--><p class="noindent" >
- <h5 class="subsubsectionHead"><span class="titlemark">1.3.2 </span> <a
- id="x1-120001.3.2"></a>Implementation</h5>
-<!--l. 342--><p class="noindent" >Godot Engine implements normalized planes by using the <span
-class="ecti-1000">Plane </span>class.
- <!--l. 346-->
- <div class="lstlisting"><span class="label"><a
- id="x1-12001r1"></a></span>//creates&#x00A0;a&#x00A0;plane&#x00A0;with&#x00A0;normal&#x00A0;(0,1,0)&#x00A0;and&#x00A0;distance&#x00A0;5&#x00A0;<br /><span class="label"><a
- id="x1-12002r2"></a></span>p&#x00A0;=&#x00A0;Plane(&#x00A0;Vector3(0,1,0),&#x00A0;5&#x00A0;)&#x00A0;<br /><span class="label"><a
- id="x1-12003r3"></a></span>//&#x00A0;get&#x00A0;the&#x00A0;distance&#x00A0;to&#x00A0;a&#x00A0;point&#x00A0;<br /><span class="label"><a
- id="x1-12004r4"></a></span>d&#x00A0;=&#x00A0;p.distance(&#x00A0;Vector3(4,5,6)&#x00A0;)
- </div>
-<!--l. 355--><p class="noindent" >
- <h4 class="subsectionHead"><span class="titlemark">1.4 </span> <a
- id="x1-130001.4"></a>Matrices, Quaternions and Coordinate Systems</h4>
-<!--l. 357--><p class="noindent" >It is very often needed to store the location/rotation of something. In 2D, it is often
-enough to store an <span
-class="ecti-1000">x,y </span>location and maybe an angle as the rotation, as that should
-be enough to represent any posible position.
-<!--l. 362--><p class="indent" > In 3D this becomes a little more difficult, as there is nothing as simple as an angle
-to store a 3-axis rotation.
-<!--l. 365--><p class="indent" > The first think that may come to mind is to use 3 angles, one for x, one for y and
-one for z. However this suffers from the problem that it becomes very cumbersome to
-use, as the individual rotations in each axis need to be performed one after another
-(they can&#8217;t be performed at the same time), leading to a problem called &#8220;gimbal
-lock&#8221;. Also, it becomes impossible to accumulate rotations (add a rotation to an
-existing one).
-<!--l. 373--><p class="indent" > To solve this, there are two known diferent approaches that aid in solving
-rotation, <span
-class="ecti-1000">Quaternions </span>and <span
-class="ecti-1000">Oriented Coordinate Systems.</span>
-<!--l. 378--><p class="noindent" >
- <h5 class="subsubsectionHead"><span class="titlemark">1.4.1 </span> <a
- id="x1-140001.4.1"></a>Oriented Coordinate Systems</h5>
-<!--l. 380--><p class="noindent" ><span
-class="ecti-1000">Oriented Coordinate Systems </span>(<span
-class="ecti-1000">OCS</span>) are a way of representing a coordinate system
-inside the cartesian coordinate system. They are mainly composed of 3 Vectors, one
-for each axis. The first vector is the <span
-class="ecti-1000">x </span>axis, the second the <span
-class="ecti-1000">y </span>axis, and the third is the
-
-<span
-class="ecti-1000">z </span>axis. The OCS vectors can be rotated around freely as long as they are kept the
-same length (as changing the length of an axis changes its cale), and as long as they
-remain orthogonal to eachother (as in, the same as the default cartesian system,
-with <span
-class="ecti-1000">y </span>pointing up, <span
-class="ecti-1000">x </span>pointing left and <span
-class="ecti-1000">z </span>pointing front, but all rotated
-together).
-<!--l. 391--><p class="indent" > <span
-class="ecti-1000">Oriented Coordinate Systems </span>are represented in 3D programming as a 3x3 matrix,
-where each row (or column, depending on the implementation) contains one of the
-axis vectors. Transforming a Vector by a rotated OCS Matrix results in the rotation
-being applied to the resulting vector. OCS Matrices can also be multiplied to
-accumulate their transformations.
-<!--l. 397--><p class="indent" > Godot Engine implements OCS Matrices in the <span
-class="ecti-1000">Matrix3 </span>class:
- <!--l. 400-->
- <div class="lstlisting"><span class="label"><a
- id="x1-14001r1"></a></span><span
-class="ecti-1000">//</span><span
-class="ecti-1000">create</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">a</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">3</span><span
-class="ecti-1000">x3</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">matrix</span>&#x00A0;<br /><span class="label"><a
- id="x1-14002r2"></a></span>m&#x00A0;=&#x00A0;Matrix3()&#x00A0;<br /><span class="label"><a
- id="x1-14003r3"></a></span><span
-class="ecti-1000">//</span><span
-class="ecti-1000">rotate</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">the</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">matrix</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">in</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">the</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">y</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">axis</span><span
-class="ecti-1000">,</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">by</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">45</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">degrees</span>&#x00A0;<br /><span class="label"><a
- id="x1-14004r4"></a></span>m.rotate(&#x00A0;Vector3(0,1,0),&#x00A0;Math.deg2rad(45)&#x00A0;)&#x00A0;<br /><span class="label"><a
- id="x1-14005r5"></a></span><span
-class="ecti-1000">//</span><span
-class="ecti-1000">transform</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">a</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">vector</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">v</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">(</span><span
-class="ecti-1000">xform</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">method</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">is</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">used</span><span
-class="ecti-1000">)</span>&#x00A0;<br /><span class="label"><a
- id="x1-14006r6"></a></span>v&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
- id="x1-14007r7"></a></span>result&#x00A0;=&#x00A0;m.xform(&#x00A0;v&#x00A0;)
- </div>
-<!--l. 412--><p class="indent" > However, in most usage cases, one wants to store a translation together with the
-rotation. For this, an <span
-class="ecti-1000">origin </span>vector must be added to the OCS, thus transforming it
-into a 3x4 (or 4x3, depending on preference) matrix. Godot engine implements this
-functionality in the <span
-class="ecti-1000">Transform </span>class:
- <!--l. 419-->
- <div class="lstlisting"><span class="label"><a
- id="x1-14010r1"></a></span>t&#x00A0;=&#x00A0;Transform()&#x00A0;<br /><span class="label"><a
- id="x1-14011r2"></a></span>//rotate&#x00A0;the&#x00A0;transform&#x00A0;in&#x00A0;the&#x00A0;y&#x00A0;axis,&#x00A0;by&#x00A0;45&#x00A0;degrees&#x00A0;<br /><span class="label"><a
- id="x1-14012r3"></a></span>t.rotate(&#x00A0;Vector3(0,1,0),&#x00A0;Math.deg2rad(45)&#x00A0;)&#x00A0;<br /><span class="label"><a
- id="x1-14013r4"></a></span>//translate&#x00A0;the&#x00A0;transform&#x00A0;by&#x00A0;5&#x00A0;in&#x00A0;the&#x00A0;z&#x00A0;axis&#x00A0;<br /><span class="label"><a
- id="x1-14014r5"></a></span>t.translate(&#x00A0;Vector3(&#x00A0;0,0,5&#x00A0;)&#x00A0;)&#x00A0;<br /><span class="label"><a
- id="x1-14015r6"></a></span>//transform&#x00A0;a&#x00A0;vector&#x00A0;v&#x00A0;(xform&#x00A0;method&#x00A0;is&#x00A0;used)&#x00A0;<br /><span class="label"><a
- id="x1-14016r7"></a></span>v&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
- id="x1-14017r8"></a></span>result&#x00A0;=&#x00A0;t.xform(&#x00A0;v&#x00A0;)
- </div>
-<!--l. 431--><p class="indent" > Transform contains internally a Matrix3 &#8220;basis&#8221; and a Vector3 &#8220;origin&#8221; (which can
-be modified individually).
-<!--l. 435--><p class="noindent" >
- <h5 class="subsubsectionHead"><span class="titlemark">1.4.2 </span> <a
- id="x1-150001.4.2"></a>Transform Internals</h5>
-<!--l. 437--><p class="noindent" >Internally, the xform() process is quite simple, to apply a 3x3 transform to a vector,
-the transposed axis vectors are used (as using the regular axis vectors will result on
-an inverse of the desired transform):
- <!--l. 442-->
- <div class="lstlisting"><span class="label"><a
- id="x1-15001r1"></a></span>m&#x00A0;=&#x00A0;Matrix3(...)&#x00A0;<br /><span class="label"><a
- id="x1-15002r2"></a></span>v&#x00A0;=&#x00A0;Vector3(..)&#x00A0;<br /><span class="label"><a
- id="x1-15003r3"></a></span>result&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
- id="x1-15004r4"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-15005r5"></a></span>x_axis&#x00A0;=&#x00A0;m.get_axis(0)&#x00A0;<br /><span class="label"><a
- id="x1-15006r6"></a></span>y_axis&#x00A0;=&#x00A0;m.get_axis(1)&#x00A0;<br /><span class="label"><a
- id="x1-15007r7"></a></span>z_axis&#x00A0;=&#x00A0;m.get_axis(2)&#x00A0;<br /><span class="label"><a
- id="x1-15008r8"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-15009r9"></a></span>result.x&#x00A0;=&#x00A0;Vector3(x_axis.x,&#x00A0;y_axis.x,&#x00A0;z_axis.x).dot(v)&#x00A0;<br /><span class="label"><a
- id="x1-15010r10"></a></span>result.y&#x00A0;=&#x00A0;Vector3(x_axis.y,&#x00A0;y_axis.y,&#x00A0;z_axis.y).dot(v)&#x00A0;<br /><span class="label"><a
- id="x1-15011r11"></a></span>result.z&#x00A0;=&#x00A0;Vector3(x_axis.z,&#x00A0;y_axis.z,&#x00A0;z_axis.z).dot(v)&#x00A0;<br /><span class="label"><a
- id="x1-15012r12"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-15013r13"></a></span>//&#x00A0;is&#x00A0;the&#x00A0;same&#x00A0;as&#x00A0;doing&#x00A0;<br /><span class="label"><a
- id="x1-15014r14"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-15015r15"></a></span>result&#x00A0;=&#x00A0;m.xform(v)&#x00A0;<br /><span class="label"><a
- id="x1-15016r16"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-15017r17"></a></span>//&#x00A0;if&#x00A0;m&#x00A0;this&#x00A0;was&#x00A0;a&#x00A0;Transform(),&#x00A0;the&#x00A0;origin&#x00A0;would&#x00A0;be&#x00A0;added&#x00A0;<br /><span class="label"><a
- id="x1-15018r18"></a></span>//&#x00A0;like&#x00A0;this:&#x00A0;<br /><span class="label"><a
- id="x1-15019r19"></a></span>&#x00A0;<br /><span class="label"><a
- id="x1-15020r20"></a></span>result&#x00A0;=&#x00A0;result&#x00A0;+&#x00A0;t.get_origin()
- </div>
-<!--l. 468--><p class="noindent" >
- <h5 class="subsubsectionHead"><span class="titlemark">1.4.3 </span> <a
- id="x1-160001.4.3"></a>Using The Transform</h5>
-<!--l. 470--><p class="noindent" >So, it is often desired apply sucessive operations to a transformation. For example,
-let&#8217;s a assume that there is a turtle sitting at the origin (the turtle is a logo reference,
-
-for those familiar with it). The <span
-class="ecti-1000">y </span>axis is up, and the the turtle&#8217;s nose is pointing
-towards the <span
-class="ecti-1000">z </span>axis.
-<!--l. 476--><p class="indent" > The turtle (like many other animals, or vehicles!) can only walk towards the
-direction it&#8217;s looking at. So, moving the turtle around a little should be something
-like this:
- <!--l. 481-->
- <div class="lstlisting"><span class="label"><a
- id="x1-16001r1"></a></span><span
-class="ecti-1000">//</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">turtle</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">at</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">the</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">origin</span>&#x00A0;<br /><span class="label"><a
- id="x1-16002r2"></a></span>turtle&#x00A0;=&#x00A0;Transform()&#x00A0;<br /><span class="label"><a
- id="x1-16003r3"></a></span><span
-class="ecti-1000">//</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">turtle</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">will</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">walk</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">5</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">units</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">in</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">z</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">axis</span>&#x00A0;<br /><span class="label"><a
- id="x1-16004r4"></a></span>turtle.translate(&#x00A0;Vector3(0,0,5)&#x00A0;)&#x00A0;<br /><span class="label"><a
- id="x1-16005r5"></a></span><span
-class="ecti-1000">//</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">turtle</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">eyes</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">a</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">lettuce</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">3</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">units</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">away</span><span
-class="ecti-1000">,</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">will</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">rotate</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">45</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">degrees</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">right</span>&#x00A0;<br /><span class="label"><a
- id="x1-16006r6"></a></span>turtle.rotate(&#x00A0;Vector3(0,1,0),&#x00A0;Math.deg2rad(45)&#x00A0;)&#x00A0;<br /><span class="label"><a
- id="x1-16007r7"></a></span><span
-class="ecti-1000">//</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">turtle</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">approaches</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">the</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">lettuce</span>&#x00A0;<br /><span class="label"><a
- id="x1-16008r8"></a></span>turtle.translate(&#x00A0;Vector3(0,0,5)&#x00A0;)&#x00A0;<br /><span class="label"><a
- id="x1-16009r9"></a></span><span
-class="ecti-1000">//</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">happy</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">turtle</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">over</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">lettuce</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">is</span><span
-class="ecti-1000">&#x00A0;</span><span
-class="ecti-1000">at</span>&#x00A0;<br /><span class="label"><a
- id="x1-16010r10"></a></span>print(turtle.get_origin())
- </div>
-<!--l. 496--><p class="indent" > As can be seen, every new action the turtle takes is based on the previous one it
-took. Had the order of actions been different and the turtle would have never reached
-the lettuce.
-<!--l. 500--><p class="indent" > Transforms are just that, a mean of &#8220;accumulating&#8221; rotation, translation, scale,
-etc.
-<!--l. 504--><p class="noindent" >
- <h5 class="subsubsectionHead"><span class="titlemark">1.4.4 </span> <a
- id="x1-170001.4.4"></a>A Warning about Numerical Precision</h5>
-<!--l. 506--><p class="noindent" >Performing several actions over a transform will slowly and gradually lead to
-precision loss (objects that draw according to a transform may get jittery, bigger,
-smaller, skewed, etc). This happens due to the nature of floating point numbers. if
-transforms/matrices are created from other kind of values (like a position and
-some angular rotation) this is not needed, but if has been accumulating
-transformations and was never recreated, it can be normalized by calling the
-.orthonormalize() built-in function. This function has little cost and calling it every
-now and then will avoid the effects from precision loss to become visible.
-
-</body></html>
-
-
-
diff --git a/doc/html/tutorial01/tutorial0x.png b/doc/html/tutorial01/tutorial0x.png
deleted file mode 100644
index a0ed4f53ff..0000000000
--- a/doc/html/tutorial01/tutorial0x.png
+++ /dev/null
Binary files differ
diff --git a/doc/html/tutorial01/tutorial1x.png b/doc/html/tutorial01/tutorial1x.png
deleted file mode 100644
index 80f0d099f7..0000000000
--- a/doc/html/tutorial01/tutorial1x.png
+++ /dev/null
Binary files differ
diff --git a/doc/html/tutorial01/tutorial2x.png b/doc/html/tutorial01/tutorial2x.png
deleted file mode 100644
index 76c502b6da..0000000000
--- a/doc/html/tutorial01/tutorial2x.png
+++ /dev/null
Binary files differ
diff --git a/doc/html/tutorial01/tutorial3x.png b/doc/html/tutorial01/tutorial3x.png
deleted file mode 100644
index 8431e9d15c..0000000000
--- a/doc/html/tutorial01/tutorial3x.png
+++ /dev/null
Binary files differ
diff --git a/doc/html/tutorial01/tutorial4x.png b/doc/html/tutorial01/tutorial4x.png
deleted file mode 100644
index 1ce7a2bb45..0000000000
--- a/doc/html/tutorial01/tutorial4x.png
+++ /dev/null
Binary files differ
diff --git a/doc/make_doc.sh b/doc/make_doc.sh
deleted file mode 100644
index a76f568bfc..0000000000
--- a/doc/make_doc.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#! /bin/bash
-here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-godotHome=$(dirname "$here")
-docTarget=${here}/html/class_list
-toolsRoot=${godotHome}/tools
-
-throw() {
- echo "$@" >&2
- exit 1
-}
-
-[ -d "$docTarget" ] || mkdir -p "$docTarget" || throw "Could not create doc target $docTarget"
-
-cd "$docTarget"
-python ${toolsRoot}/docdump/makehtml.py -multipage ${here}/base/classes.xml
-cd "$here"
-
diff --git a/doc/notes.txt b/doc/notes.txt
deleted file mode 100644
index 39c03ca4c5..0000000000
--- a/doc/notes.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-
-in FileDialog file_selected -> file_activated
-focus script/shader editor when gaining focus
-detect if errors in editor and don't allow play
-
-
--tree of files (all recognized extensions)
-
-*export: *keep|export|bundle
-*options: [make binary for xnl], then options for each filetype (texture compress method, etc)
-
-
-config.h deberia teber varias cosas de plataforma
-
-_FORCE_INLINE_
-copymem
-ftoi
-defines de funciones matematicas
-
-
diff --git a/doc/phys_engine.png b/doc/phys_engine.png
deleted file mode 100644
index 15539d47d7..0000000000
--- a/doc/phys_engine.png
+++ /dev/null
Binary files differ
diff --git a/doc/squirrel.lyx b/doc/squirrel.lyx
deleted file mode 100644
index 05270c1b8f..0000000000
--- a/doc/squirrel.lyx
+++ /dev/null
@@ -1,984 +0,0 @@
-#LyX 2.0 created this file. For more info see http://www.lyx.org/
-\lyxformat 413
-\begin_document
-\begin_header
-\textclass article
-\use_default_options true
-\maintain_unincluded_children false
-\language english
-\language_package default
-\inputencoding auto
-\fontencoding global
-\font_roman default
-\font_sans default
-\font_typewriter default
-\font_default_family default
-\use_non_tex_fonts false
-\font_sc false
-\font_osf false
-\font_sf_scale 100
-\font_tt_scale 100
-
-\graphics default
-\default_output_format default
-\output_sync 0
-\bibtex_command default
-\index_command default
-\paperfontsize default
-\use_hyperref false
-\papersize default
-\use_geometry false
-\use_amsmath 1
-\use_esint 1
-\use_mhchem 1
-\use_mathdots 1
-\cite_engine basic
-\use_bibtopic false
-\use_indices false
-\paperorientation portrait
-\suppress_date false
-\use_refstyle 1
-\index Index
-\shortcut idx
-\color #008000
-\end_index
-\secnumdepth 3
-\tocdepth 3
-\paragraph_separation indent
-\paragraph_indentation default
-\quotes_language english
-\papercolumns 1
-\papersides 1
-\paperpagestyle default
-\tracking_changes false
-\output_changes false
-\html_math_output 0
-\html_css_as_file 0
-\html_be_strict false
-\end_header
-
-\begin_body
-
-\begin_layout Title
-Squirrel Usage in Godot
-\end_layout
-
-\begin_layout Section
-Introduction
-\end_layout
-
-\begin_layout Standard
-Squirrel is a nice scripting language.
- It's sort of a mix between Lua, Java and JavaScript and ends up being easy
- to learn for most programmers.
- It has more language features than GDScript but it's also slower, more
- limited and not as well integrated.
- This guide will explain how Squirrel is integrated to Godot and all the
- quirks that are needed to know in order to use it properly.
-\end_layout
-
-\begin_layout Section
-Enabling Squirrel
-\end_layout
-
-\begin_layout Standard
-Squirrel may not be enabled by default in a Godot build.
- To enable it, execute SCons with the following parameters:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-shell$ scons squirrel=yes <target_binary>
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Documentation
-\end_layout
-
-\begin_layout Standard
-Godot utilizes Squirrel 2.2.
- Documentation can be found at:
-\begin_inset CommandInset href
-LatexCommand href
-target "http://squirrel-lang.org/#documentation"
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Class Files
-\end_layout
-
-\begin_layout Standard
-Unless writing a library, Godot expects a class for scripting an object.
- Since a Squirrel source file can contain many classes, the main class must
- be returned.
- The following is an example of extending a button:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-class MyButton extends Button {
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
- constructor() {
-\end_layout
-
-\begin_layout Plain Layout
-
- // ALWAYS call parent constructor
-\end_layout
-
-\begin_layout Plain Layout
-
- Button.constructor()
-\end_layout
-
-\begin_layout Plain Layout
-
- }
-\end_layout
-
-\begin_layout Plain Layout
-
-}
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-return MyButton // main class returned
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Additionally, classes are all copied to the root table, so all class names
- in scripts must be different if they are attempted to be loaded simultaneously.
- The same can be said for any other globals declared in the script.
-
-\end_layout
-
-\begin_layout Standard
-Finally, squirrel scripts must be saved with the .nut or .sq extensions (both
- are recognized).
-\end_layout
-
-\begin_layout Section
-Including Other Scripts
-\end_layout
-
-\begin_layout Standard
-Other scripts can be included with the include() directive.
- Full and relative paths are supported.
- When included, the classes and globals are moved to the root table, so
- they become immediately available.
- Constants, however, are only inlined in the current class on load, so Squirrel
- does not make them available.
- Example of including scripts:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-include("my_button.nut") # // relative to current script, expected to be
- in the same path
-\end_layout
-
-\begin_layout Plain Layout
-
-include("res://buttons/my_button.nut") // using resource path
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Built-In Types
-\end_layout
-
-\begin_layout Standard
-There are some small differences between the Built-In types in Godot and
- the ones in Squirrel, so the documentation will not match.
- The differences are documented here.
-\end_layout
-
-\begin_layout Standard
-An attempt will be made to document everything here,but if in doubt about
- bindings on built-in types, you can always take a loot at the bindings
- source file in script/squirrel/sq_bind_types.cpp.
-\end_layout
-
-\begin_layout Standard
-Built-In Types in Squirrel are passed by reference (unlike by value like
- in GD).
- They also don't need to be freed.
-\end_layout
-
-\begin_layout Subsection
-AABB
-\end_layout
-
-\begin_layout Standard
-\begin_inset Quotes eld
-\end_inset
-
-pos
-\begin_inset Quotes erd
-\end_inset
-
-,
-\begin_inset Quotes eld
-\end_inset
-
-size
-\begin_inset Quotes erd
-\end_inset
-
- and
-\begin_inset Quotes eld
-\end_inset
-
-end
-\begin_inset Quotes erd
-\end_inset
-
- are not available Use get_pos()/set_pos and get_size()/set_size().
-\end_layout
-
-\begin_layout Subsection
-InputEvent
-\end_layout
-
-\begin_layout Standard
-InputEvent is a single datatype and contains everything.
- Use only the fields meant for the event type:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-//for mouse motion and button
-\end_layout
-
-\begin_layout Plain Layout
-
-int mouse_x
-\end_layout
-
-\begin_layout Plain Layout
-
-int mouse_y
-\end_layout
-
-\begin_layout Plain Layout
-
-int mouse_button_mask
-\end_layout
-
-\begin_layout Plain Layout
-
-int mouse_global_x
-\end_layout
-
-\begin_layout Plain Layout
-
-int mouse_global_y
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-//for mouse button
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-int mouse_button_index
-\end_layout
-
-\begin_layout Plain Layout
-
-bool mouse_button_pressed
-\end_layout
-
-\begin_layout Plain Layout
-
-bool mouse_button_doubleclick
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-//for mouse motion
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-int mouse_motion_x
-\end_layout
-
-\begin_layout Plain Layout
-
-int mouse_motion_y
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-//for keyboard
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-int key_scancode
-\end_layout
-
-\begin_layout Plain Layout
-
-int key_unicode
-\end_layout
-
-\begin_layout Plain Layout
-
-bool key_pressed
-\end_layout
-
-\begin_layout Plain Layout
-
-bool key_echo
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-//for keyboard and mouse
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-bool mod_alt
-\end_layout
-
-\begin_layout Plain Layout
-
-bool mod_shift
-\end_layout
-
-\begin_layout Plain Layout
-
-bool mod_meta
-\end_layout
-
-\begin_layout Plain Layout
-
-bool mod_control
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-//joy button
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-int joy_button_index
-\end_layout
-
-\begin_layout Plain Layout
-
-bool joy_button_pressed
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-//joy axis
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-int joy_axis
-\end_layout
-
-\begin_layout Plain Layout
-
-float joy_axis_value
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-//screen drag and touch
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-int screen_index
-\end_layout
-
-\begin_layout Plain Layout
-
-int screen_x
-\end_layout
-
-\begin_layout Plain Layout
-
-int screen_y
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-//screen touch
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-int screen_index
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-//action
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-int action_id
-\end_layout
-
-\begin_layout Plain Layout
-
-bool action_pressed
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Subsection
-Matrix3
-\end_layout
-
-\begin_layout Standard
-x,y,z member vectors are not available.
- Use get_row() and set_row() instead.
- Individual float values of the matrix are available as swizzle masks such
- as xxy, xyz, zzx, etc.
-\end_layout
-
-\begin_layout Standard
-Additional in-place versions of some functions are available: transpose(),
- invert(), rotate(), scale(), orthonormalize().
-\end_layout
-
-\begin_layout Subsection
-Transform
-\end_layout
-
-\begin_layout Standard
-\begin_inset Quotes eld
-\end_inset
-
-basis
-\begin_inset Quotes erd
-\end_inset
-
- and
-\begin_inset Quotes eld
-\end_inset
-
-origin
-\begin_inset Quotes erd
-\end_inset
-
- members are not available.
- Use get_basis()/set_basis() and get_origin()/set_origin() instead.
- Additional in-place versions of some functions are available: invert(),
- affine_invert(), orthonormalize(), rotate(), translate(), scale().
-\end_layout
-
-\begin_layout Standard
-Vector2
-\end_layout
-
-\begin_layout Subsection
-Plane
-\end_layout
-
-\begin_layout Standard
-\begin_inset Quotes eld
-\end_inset
-
-normal
-\begin_inset Quotes erd
-\end_inset
-
- member vector is not available.
- Use get_normal(), set_normal() instead.
-\end_layout
-
-\begin_layout Subsection
-Rect2
-\end_layout
-
-\begin_layout Standard
-\begin_inset Quotes eld
-\end_inset
-
-pos
-\begin_inset Quotes erd
-\end_inset
-
-,
-\begin_inset Quotes eld
-\end_inset
-
-size
-\begin_inset Quotes erd
-\end_inset
-
- and
-\begin_inset Quotes eld
-\end_inset
-
-end
-\begin_inset Quotes erd
-\end_inset
-
- are not available Use get_pos()/set_pos and get_size()/set_size().
-\end_layout
-
-\begin_layout Subsection
-Native Arrays
-\end_layout
-
-\begin_layout Standard
-Native arrays such as RawArray, IntArray,StringArray, etc are not supported.
- Use regular squirrel arrays instead, since conversion to/from them will
- happen automatically.
-\end_layout
-
-\begin_layout Subsection
-Math Functions
-\end_layout
-
-\begin_layout Standard
-Math functions are inside the Math namespace in Squirrel.
- For example Math.sin , Math.PI, Math.atan2().
-\end_layout
-
-\begin_layout Subsection
-Native Types
-\end_layout
-
-\begin_layout Standard
-Array, Dictionary and NodePath are not available.
- Use a native array, table and string respectively.
-\end_layout
-
-\begin_layout Section
-_get , _set
-\end_layout
-
-\begin_layout Standard
-_get and _set are reserved in Squirrel, for overriding Godot Object property
- getter/setter, use _get_property and _set_property.
-\end_layout
-
-\begin_layout Section
-Member Export
-\end_layout
-
-\begin_layout Standard
-Simple exporting of members (so far only integer, floating point and string
- are supported) is supported by the @export extension.
- It is used like this:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-class MyButton extends Button {
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
- aprop=1 // @export
-\end_layout
-
-\begin_layout Plain Layout
-
- bprop=2.0 // @export
-\end_layout
-
-\begin_layout Plain Layout
-
- cprop="3" // @export
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
- //these will be available to the property editor, and will be loaded/saved
- with the scene.
-\end_layout
-
-\begin_layout Plain Layout
-
-}
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Always Enabled Scripts
-\end_layout
-
-\begin_layout Standard
-Scripts are not enabled in the editor by default.
- To enable a script always, add an @always_enabled comment.
- Example:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-//@always_enabled
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-class MyButton extends Button {
-\end_layout
-
-\begin_layout Plain Layout
-
-\end_layout
-
-\begin_layout Plain Layout
-
-...
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Section
-Threads
-\end_layout
-
-\begin_layout Standard
-Thread support in Squirrel is very poor.
- This is because of the stack-based nature of the language implementation.
- Since godot can run in multiple threads, it will forcibily lock the whole
- VM when accessed from multiple threads, which will result in degraded performan
-ce.
- Creating user threads in Squirrel is definitely not recomended, as it may
- completely lock the main thread.
-\end_layout
-
-\begin_layout Section
-References
-\end_layout
-
-\begin_layout Standard
-Godot has a built-in reference counted type used in conjunction with a template
- (objects that inherit the
-\begin_inset Quotes eld
-\end_inset
-
-Reference
-\begin_inset Quotes erd
-\end_inset
-
- class).
- Since Squirrel also uses reference counting, it becomes impossible for
- such types in godot to contain a script, because it would result in an
- un-breakable reference cycle.
- To avoid this, a Ref() class was created in Squirrel.
-
-\end_layout
-
-\begin_layout Standard
-When calling Godot API functions, returned references are wrapped inside
- Ref() transparently, but the problem arises when creating a Reference-derived
- object from the code.
- In such cases, the reference must be wrapped manually like this:
-\end_layout
-
-\begin_layout Standard
-\begin_inset listings
-inline false
-status open
-
-\begin_layout Plain Layout
-
-local f = Ref( File() )
-\end_layout
-
-\begin_layout Plain Layout
-
-local err = f.open("hello.txt",File.READ)
-\end_layout
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-Anything not a reference that inherits from Object can be freed manually
- by calling .free(), just like in GDScript.
- Object classes are in itself weak references to engine objects, and their
- validity can be checked by calling the
-\begin_inset Quotes eld
-\end_inset
-
-has_instance()
-\begin_inset Quotes erd
-\end_inset
-
- built-in method.
-\end_layout
-
-\begin_layout Section
-Unicode
-\end_layout
-
-\begin_layout Standard
-Squirrel source code is supposed to support Unicode, but the implementation
- is very broken (Squirrel attempts to use 16 bit chars no matter what, making
- it incompatible when the host OS is 32 bit, like Linux).
- Squirrel source code is parsed as UTF-8, and strings also contain UTF-8.
- Wide char access in strings is not supported.
-\end_layout
-
-\begin_layout Section
-Debugging
-\end_layout
-
-\begin_layout Standard
-Squirrel is well integrated into the Godot debugger.
- To run the project in debug mode, execute the godot binary with the -debug
- argument.
- Godot will break on squirrel errors and allow the programmer to debug.
-\end_layout
-
-\begin_layout Section
-Utility Functions
-\end_layout
-
-\begin_layout Standard
-There are a few squirrel-only utility functions available:
-\end_layout
-
-\begin_layout Subsection
-print(value[,value])
-\end_layout
-
-\begin_layout Standard
-Print stuff to stdout.
-\end_layout
-
-\begin_layout Subsection
-dofile(path)
-\end_layout
-
-\begin_layout Standard
-Execute a squirrel script file and return whatever the file returns.
- Not recommended to use in production because it can't be optimized.
-\end_layout
-
-\begin_layout Subsection
-nativeref(var)
-\end_layout
-
-\begin_layout Standard
-Convert any squirrel type to an engine type.
- When this type returns to squirrel, it's converted back.
- This is useful to add to Godot callbacks to ensure that the datatype is
- not converted.
-\end_layout
-
-\begin_layout Subsection
-unicode_split(string)
-\end_layout
-
-\begin_layout Standard
-Split an unicode string (utf8) into an array of widechars.
- Useful since there is no wide char access from Squirrel.
-\end_layout
-
-\begin_layout Subsection
-breakpoint()
-\end_layout
-
-\begin_layout Standard
-Stop the debugger when reaches here (when run inside the debugger).
-\end_layout
-
-\begin_layout Subsection
-backtrace()
-\end_layout
-
-\begin_layout Standard
-Print a backtrace of the call stack.
-\end_layout
-
-\begin_layout Subsection
-tr(text)
-\end_layout
-
-\begin_layout Standard
-Translate text (use string lookup in Godot translation system).
-\end_layout
-
-\begin_layout Subsection
-printerr(text)
-\end_layout
-
-\begin_layout Standard
-Print a string to stderr.
-\end_layout
-
-\end_body
-\end_document
diff --git a/doc/todo.txt b/doc/todo.txt
deleted file mode 100644
index 511b5dbbe2..0000000000
--- a/doc/todo.txt
+++ /dev/null
@@ -1,39 +0,0 @@
--Fisica 2D
- *terminar constraints
- *terminar queries
- *desactivar on suspend
- -bugs supongo?
-
--Fisica 3D
- -portar engine 2D a 3D mayoritariamente (si puedo esperar, mejor)
- -hacer que skeletons se vuelvan ragdolls de alguna forma
- -hacer bien lo de enganchar cosas a huesos de esqueleto
-
--GUI
- - Tree necesita resizear desde los headers
-
--Escena 3D
- -Deshabilitar 3D (Opcional en compilacion)
- -Particulas 3D
- -Heightmaps
- -Arreglar fixed pipeline
- -arreglar glow y ssao
-
--Editor codigo
- -Editor de codigo (esta, pero esta lleno de bugs)
- -Debugger (esta, pero hay que integrar bien)
-
--UI General
- -Cambiar lugar el tema de resources porque es MUY poco intuitivo
- -Tal vez arreglar un poquito el theme y la estetica (para release, low priority)
- -Run deberia correr la escena main
- -new script deberia dar opcion de crear en disco
- -los scripts de deberian mantener abiertos al abrir otra escena
- -
-
--Settings
- -Hacer pantalla de optimizacion general del proyecto
-
--A futuro:
- -Scripting Propio
- -Portar a DX9/GL3 \ No newline at end of file
diff --git a/tools/docdump/doc_merge.py b/doc/tools/doc_merge.py
index 872f38ed87..6cc7019324 100644
--- a/tools/docdump/doc_merge.py
+++ b/doc/tools/doc_merge.py
@@ -1,3 +1,6 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
import sys
import xml.etree.ElementTree as ET
diff --git a/tools/docdump/locales/es/LC_MESSAGES/makedocs.mo b/doc/tools/locales/es/LC_MESSAGES/makedocs.mo
index 8d7ea2689e..8d7ea2689e 100644
--- a/tools/docdump/locales/es/LC_MESSAGES/makedocs.mo
+++ b/doc/tools/locales/es/LC_MESSAGES/makedocs.mo
Binary files differ
diff --git a/tools/docdump/locales/es/LC_MESSAGES/makedocs.po b/doc/tools/locales/es/LC_MESSAGES/makedocs.po
index 82115dd897..82115dd897 100644
--- a/tools/docdump/locales/es/LC_MESSAGES/makedocs.po
+++ b/doc/tools/locales/es/LC_MESSAGES/makedocs.po
diff --git a/doc/html/main.css b/doc/tools/main.css
index a76e6bbed8..a76e6bbed8 100644
--- a/doc/html/main.css
+++ b/doc/tools/main.css
diff --git a/tools/docdump/makedocs.pot b/doc/tools/makedocs.pot
index be3220f686..be3220f686 100644
--- a/tools/docdump/makedocs.pot
+++ b/doc/tools/makedocs.pot
diff --git a/tools/docdump/makedocs.py b/doc/tools/makedocs.py
index be57891abc..063ee29002 100644
--- a/tools/docdump/makedocs.py
+++ b/doc/tools/makedocs.py
@@ -3,7 +3,7 @@
#
# makedocs.py: Generate documentation for Open Project Wiki
-# Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur.
+# Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur.
# Contributor: Jorge Araya Navarro <elcorreo@deshackra.com>
#
@@ -24,7 +24,7 @@
# TODO:
# * Refactor code.
# * Adapt this script for generating content in other markup formats like
-# DokuWiki, Markdown, etc.
+# reStructuredText, Markdown, DokuWiki, etc.
#
# Also check other TODO entries in this script for more information on what is
# left to do.
diff --git a/tools/docdump/makedoku.py b/doc/tools/makedoku.py
index e8207715fe..1ab16841b1 100644
--- a/tools/docdump/makedoku.py
+++ b/doc/tools/makedoku.py
@@ -1,3 +1,6 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
import sys
import xml.etree.ElementTree as ET
@@ -8,7 +11,7 @@ for arg in sys.argv[1:]:
input_list.append(arg)
if len(input_list) < 1:
- print("usage: makedoku.py <class_list.xml>")
+ print("usage: makedoku.py <classes.xml>")
sys.exit(0)
diff --git a/tools/docdump/makehtml.py b/doc/tools/makehtml.py
index 9b9c62f33b..34db47e424 100644
--- a/tools/docdump/makehtml.py
+++ b/doc/tools/makehtml.py
@@ -1,3 +1,6 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
import sys
import xml.etree.ElementTree as ET
from xml.sax.saxutils import escape, unescape
@@ -29,7 +32,7 @@ for arg in sys.argv[1:]:
input_list.append(arg)
if len(input_list) < 1:
- print("usage: makehtml.py <class_list.xml>")
+ print("usage: makehtml.py <classes.xml>")
sys.exit(0)
diff --git a/tools/docdump/makemd.py b/doc/tools/makemd.py
index f85d145d5e..e012287b0e 100644
--- a/tools/docdump/makemd.py
+++ b/doc/tools/makemd.py
@@ -1,5 +1,6 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
+
import sys
import xml.etree.ElementTree as ET
@@ -9,7 +10,7 @@ for arg in sys.argv[1:]:
input_list.append(arg)
if len(input_list) < 1:
- print 'usage: makedoku.py <class_list.xml>'
+ print 'usage: makemd.py <classes.xml>'
sys.exit(0)
diff --git a/doc/tutorial/01 Getting Started.lyx b/doc/tutorial/01 Getting Started.lyx
deleted file mode 100644
index bdb4c7706d..0000000000
--- a/doc/tutorial/01 Getting Started.lyx
+++ /dev/null
@@ -1,557 +0,0 @@
-#LyX 1.6.5 created this file. For more info see http://www.lyx.org/
-\lyxformat 345
-\begin_document
-\begin_header
-\textclass article
-\use_default_options true
-\language english
-\inputencoding auto
-\font_roman default
-\font_sans default
-\font_typewriter default
-\font_default_family default
-\font_sc false
-\font_osf false
-\font_sf_scale 100
-\font_tt_scale 100
-
-\graphics default
-\paperfontsize default
-\use_hyperref false
-\papersize default
-\use_geometry false
-\use_amsmath 1
-\use_esint 1
-\cite_engine basic
-\use_bibtopic false
-\paperorientation portrait
-\secnumdepth 3
-\tocdepth 3
-\paragraph_separation indent
-\defskip medskip
-\quotes_language english
-\papercolumns 1
-\papersides 1
-\paperpagestyle default
-\tracking_changes false
-\output_changes false
-\author ""
-\author ""
-\end_header
-
-\begin_body
-
-\begin_layout Title
-01.
- Getting Started with Godot Engine
-\end_layout
-
-\begin_layout Section*
-Introduction:
-\end_layout
-
-\begin_layout Standard
-Godot Engine is designed to be useful.
- This may sound rather vague and is difficult to explain without repeating
- the same claims that every other engine does, but, as we progress through
- this (and the next) tutorials, hopefully it will be made clear what
-\begin_inset Quotes eld
-\end_inset
-
-useful
-\begin_inset Quotes erd
-\end_inset
-
- means.
-\end_layout
-
-\begin_layout Standard
-Godot Engine has many components, both high and low level, and is usually
- more abstract and complex than most other engines.
- This is, however, to the advantage of the user as complexity is presented
- in a way that it only needs to be discovered when more power needs to be
- untapped.
- This helps to provide an easy learning curve.
-\end_layout
-
-\begin_layout Standard
-Design wise, the whole API and set of components were created with a clear
- goal in mind, which is to allow for smooth integration of design ideas,
- code and assets.
- This is achieved by defining the following rules:
-\end_layout
-
-\begin_layout Itemize
-Implementing a game feature should never be too many steps away from an
- existing component.
-\end_layout
-
-\begin_layout Itemize
-More complex features should be leveraged by combining or extending existing
- components.
-\end_layout
-
-\begin_layout Itemize
-If the above fails, creating custom components should be extremely simple.
-\end_layout
-
-\begin_layout Standard
-Ultimately, Godot Engine provides an editor and tools that allows everyone
- to work with it:
-\end_layout
-
-\begin_layout Itemize
-Programmers can script and extend any component of the project.
-\end_layout
-
-\begin_layout Itemize
-Designers can tweak and animate any parameter from a friendly user interface.
-\end_layout
-
-\begin_layout Itemize
-Artists can import their art and models and tweak the look of everything
- in realtime.
-\end_layout
-
-\begin_layout Section*
-Editor:
-\end_layout
-
-\begin_layout Standard
-As mentioned before, Godot Engine is very abstract so projects consist of
- just a
-\emph on
-path
-\emph default
- (ie: C:
-\backslash
-games
-\backslash
-mygame5).
- Projects don't have to be specifically created, and many can be placed
- inside the same path (useful for not wasting folders on tests and experiments).
-
-\end_layout
-
-\begin_layout Standard
-In any case, to ease the management of projects, a graphical util exists.
-\end_layout
-
-\begin_layout Subsection*
-Running From The Project Manager
-\end_layout
-
-\begin_layout Standard
-Godot Engine includes a built-in project manager.
- This is installed by default on Windows and OSX and it allows for the creation
- and removal projects that will be remembered at the next startup:
-\end_layout
-
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename pm.png
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-To create a new project, the [Create] button must be pressed and a dialog
- will appear, prompting for a path and project name.
- Afterwards, the [Open] button will close the project manager and open the
- desired project.
-\end_layout
-
-\begin_layout Subsection*
-Running From the Command Line
-\end_layout
-
-\begin_layout Standard
-To create and manage projects, it is perfectly possible to use the command
- line.
- Many users prefer this way of working with project data.
-\end_layout
-
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename pmc.png
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-For ease of use, it is recommended that the
-\begin_inset Quotes eld
-\end_inset
-
-godot
-\begin_inset Quotes erd
-\end_inset
-
- binary exists in the path, so any project can be opened easily aywhere
- just by changing location to the projec and executing the editor.
-\end_layout
-
-\begin_layout Subsection*
-Godot Editor
-\end_layout
-
-\begin_layout Standard
-Godot Editor should have been opened by now, if not please check the previous
- steps again.
-\end_layout
-
-\begin_layout Standard
-Godot has a powerful buit-in editor.
- It uses the graphics toolkint within itself to display the UI, so it runs
- identical on any platform (even consoles or phones!).
-\end_layout
-
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename editor.png
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-In the above screenshots, a few regions are labelled to be explained as
- follows:
-\end_layout
-
-\begin_layout Subsubsection*
-Viewport
-\end_layout
-
-\begin_layout Standard
-The
-\emph on
-Viewport
-\emph default
- is the main space where the content is displayed.
- Content includes 3D Nodes or Graphical User Interface (GUI) controls.
- Other types of data spawn editors of their own when being edited.
- The default viewport is the 3D viewport, which can be panned, zoomed, etc.
-\end_layout
-
-\begin_layout Subsubsection*
-Scene Tree
-\end_layout
-
-\begin_layout Standard
-The
-\emph on
-Scene Tree
-\emph default
- is a small dock that displays the tree of the current scene being edited.
- A scene is a collection of nodes arranged in a tree-hierarchy (any node
- can have several owned children-nodes).
- The meaning of this ownership depends purely on the
-\emph on
-type
-\emph default
- of the node, but it will become clear after going through the examples.
- In a
-\emph on
-MVC
-\emph default
- pattern, the scene tree could be considered the
-\emph on
-View
-\emph default
-.
-\end_layout
-
-\begin_layout Subsubsection*
-Property Editor
-\end_layout
-
-\begin_layout Standard
-The
-\emph on
-Property Editor
-\emph default
- is another small dock.
- Every node contains a finite number of
-\emph on
-properties
-\emph default
-, which can be edited.
- Properties can be of several types, such as integers, strings, images,
- matrices, etc.
- Usually, changes to properties are reflected in the
-\emph on
-viewport
-\emph default
- in real time.
-\end_layout
-
-\begin_layout Section*
-Examples:
-\end_layout
-
-\begin_layout Standard
-From now, a few, simple examples will be presented that will help understand
- a little better how Godot Engine works.
-
-\end_layout
-
-\begin_layout Subsubsection*
-Hello, World!
-\end_layout
-
-\begin_layout Enumerate
-Open the editor
-\end_layout
-
-\begin_layout Enumerate
-Click on
-\begin_inset Quotes eld
-\end_inset
-
-Node
-\begin_inset Quotes erd
-\end_inset
-
- (Node Menu), then on
-\begin_inset Quotes eld
-\end_inset
-
-Create Root
-\begin_inset Quotes erd
-\end_inset
-
-
-\end_layout
-
-\begin_deeper
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename tute1_1.png
-
-\end_inset
-
-
-\end_layout
-
-\end_deeper
-\begin_layout Enumerate
-Create a node of type
-\emph on
-Label,
-\emph default
-then instruct the
-\emph on
-editor
-\emph default
-to switch to GUI editing mode.
- A few red squares will appear on the top left corner, don't mind them yet.
-\end_layout
-
-\begin_deeper
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename tute1_2.png
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename tute1_2b.png
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename tute1_3c.png
-
-\end_inset
-
-
-\end_layout
-
-\end_deeper
-\begin_layout Enumerate
-Select the
-\emph on
-Label
-\emph default
-node in the
-\emph on
-Scene Tree
-\emph default
- (if it's not selected yet), the properties of the selected node will appear
- in the
-\emph on
-Property Editor
-\end_layout
-
-\begin_deeper
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename tute1_3a.png
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename tute1_3b.png
-
-\end_inset
-
-
-\end_layout
-
-\end_deeper
-\begin_layout Enumerate
-Look for the
-\emph on
-Text
-\emph default
- property in the
-\emph on
-Property Editor
-\emph default
- and click the right column, so it becomes editable.
- Enter the text
-\begin_inset Quotes eld
-\end_inset
-
-Hello, World!
-\begin_inset Quotes erd
-\end_inset
-
-.
- A red square containing
-\begin_inset Quotes eld
-\end_inset
-
-Hello World!
-\begin_inset Quotes erd
-\end_inset
-
- will appear at the top left, move it to the center.
-\end_layout
-
-\begin_deeper
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename tute1_4a.png
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename tute1_4b.png
-
-\end_inset
-
-
-\end_layout
-
-\end_deeper
-\begin_layout Enumerate
-Save the scene.
-\end_layout
-
-\begin_deeper
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename tute1_5a.png
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename tute1_5b.png
-
-\end_inset
-
-
-\end_layout
-
-\end_deeper
-\begin_layout Enumerate
-Press PLAY.
- A new window will appear running the application.
-\end_layout
-
-\begin_deeper
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename tute1_6.png
-
-\end_inset
-
-
-\end_layout
-
-\begin_layout Standard
-\align center
-\begin_inset Graphics
- filename tute1_7.png
-
-\end_inset
-
-
-\end_layout
-
-\end_deeper
-\begin_layout Subsubsection*
-Hello World 2 (a little more complex)
-\end_layout
-
-\begin_layout Subsubsection*
-A 3D Cube in Space
-\end_layout
-
-\begin_layout Standard
-
-\end_layout
-
-\begin_layout Standard
-In many cases, nodes and other types of engine objects need to express changes
- in their state, such as a button being pressed, a scroll being dragged,
- or a projectile colliding against a tank.
- Godot Engine utilizes the concept of signals for this.
- Different types of nodes and objects can emit signals, and any other node
- or object can connect to them.
-
-\end_layout
-
-\end_body
-\end_document
diff --git a/doc/tutorial/editor.png b/doc/tutorial/editor.png
deleted file mode 100644
index 92255a6f17..0000000000
--- a/doc/tutorial/editor.png
+++ /dev/null
Binary files differ
diff --git a/doc/tutorial/pm.png b/doc/tutorial/pm.png
deleted file mode 100644
index 00d46d9a64..0000000000
--- a/doc/tutorial/pm.png
+++ /dev/null
Binary files differ
diff --git a/doc/tutorial/pmc.png b/doc/tutorial/pmc.png
deleted file mode 100644
index 847d32b3a2..0000000000
--- a/doc/tutorial/pmc.png
+++ /dev/null
Binary files differ
diff --git a/doc/tutorial/tute1_1.png b/doc/tutorial/tute1_1.png
deleted file mode 100644
index 82152c7255..0000000000
--- a/doc/tutorial/tute1_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/tutorial/tute1_2.png b/doc/tutorial/tute1_2.png
deleted file mode 100644
index 852015894c..0000000000
--- a/doc/tutorial/tute1_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/tutorial/tute1_2b.png b/doc/tutorial/tute1_2b.png
deleted file mode 100644
index e97a40b4c5..0000000000
--- a/doc/tutorial/tute1_2b.png
+++ /dev/null
Binary files differ
diff --git a/doc/tutorial/tute1_3a.png b/doc/tutorial/tute1_3a.png
deleted file mode 100644
index 5feef01e03..0000000000
--- a/doc/tutorial/tute1_3a.png
+++ /dev/null
Binary files differ
diff --git a/doc/tutorial/tute1_3b.png b/doc/tutorial/tute1_3b.png
deleted file mode 100644
index 1f2ded42bb..0000000000
--- a/doc/tutorial/tute1_3b.png
+++ /dev/null
Binary files differ
diff --git a/doc/tutorial/tute1_3c.png b/doc/tutorial/tute1_3c.png
deleted file mode 100644
index 2c52ccd780..0000000000
--- a/doc/tutorial/tute1_3c.png
+++ /dev/null
Binary files differ
diff --git a/doc/tutorial/tute1_4a.png b/doc/tutorial/tute1_4a.png
deleted file mode 100644
index 8d0d04ff6b..0000000000
--- a/doc/tutorial/tute1_4a.png
+++ /dev/null
Binary files differ
diff --git a/doc/tutorial/tute1_4b.png b/doc/tutorial/tute1_4b.png
deleted file mode 100644
index fff5f8d723..0000000000
--- a/doc/tutorial/tute1_4b.png
+++ /dev/null
Binary files differ
diff --git a/doc/tutorial/tute1_5a.png b/doc/tutorial/tute1_5a.png
deleted file mode 100644
index 37bea04570..0000000000
--- a/doc/tutorial/tute1_5a.png
+++ /dev/null
Binary files differ
diff --git a/doc/tutorial/tute1_5b.png b/doc/tutorial/tute1_5b.png
deleted file mode 100644
index df9a987ef3..0000000000
--- a/doc/tutorial/tute1_5b.png
+++ /dev/null
Binary files differ
diff --git a/doc/tutorial/tute1_6.png b/doc/tutorial/tute1_6.png
deleted file mode 100644
index bbe04c8547..0000000000
--- a/doc/tutorial/tute1_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/tutorial/tute1_7.png b/doc/tutorial/tute1_7.png
deleted file mode 100644
index 7653a89064..0000000000
--- a/doc/tutorial/tute1_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/undoredoapi.txt b/doc/undoredoapi.txt
deleted file mode 100644
index eb73b8ccff..0000000000
--- a/doc/undoredoapi.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-undo/redo api proposal
-
-
-
-o o o o o o o o
-
-
-undoredo.create_method();
-undoredo.add_do_method(node,"add_child",node_to_add);
-undoredo.add_undo_method(node,"remove_child",node_to_add);
-undoredo.add_add_data(node_to_add);
-undoredo.commit()
-
-undoredo.create_method();
-undoredo.add_do_method(node,"remove_node",node_to_remove);
-undoredo.add_undo_method(node,"add_node",node_to_remove);
-undoredo.add_remove_data(node_to_remove);
-undoredo.commit()
-
-
-undoredo.create_property();
-undoredo.add_do_set(node,"property",value);
-undoredo.add_undo_set(node,"property",previous_value);
-undoredo.add_remove_data(node_to_remove);
-undoredo.commit()
diff --git a/drivers/SCsub b/drivers/SCsub
index 8e241830f8..a00d7fc3f9 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -12,11 +12,13 @@ SConscript('windows/SCsub');
SConscript('gles2/SCsub');
SConscript('gl_context/SCsub');
SConscript('openssl/SCsub');
+SConscript('pnm/SCsub');
if (env["png"]=="yes"):
SConscript("png/SCsub");
if (env["jpg"]=="yes"):
- SConscript("jpg/SCsub");
+ #SConscript("jpg/SCsub");
+ SConscript("jpegd/SCsub");
if (env["webp"]=="yes"):
SConscript("webp/SCsub");
SConscript("dds/SCsub");
@@ -61,39 +63,42 @@ import string
if env['vsproj']=="yes":
env.AddToVSProject(env.drivers_sources)
-for f in env.drivers_sources:
- fname = ""
- if type(f) == type(""):
- fname = env.File(f).path
- else:
- fname = env.File(f)[0].path
- fname = fname.replace("\\", "/")
- base = string.join(fname.split("/")[:2], "/")
- if base != cur_base and len(list) > max_src:
- if num > 0:
- lib = env.Library("drivers"+str(num), list)
- lib_list.append(lib)
- list = []
- num = num+1
- cur_base = base
- list.append(f)
+if (False): #split drivers, this used to be needed for windows until separate builders for windows were created
-lib = env.Library("drivers"+str(num), list)
-lib_list.append(lib)
+ for f in env.drivers_sources:
+ fname = ""
+ if type(f) == type(""):
+ fname = env.File(f).path
+ else:
+ fname = env.File(f)[0].path
+ fname = fname.replace("\\", "/")
+ base = string.join(fname.split("/")[:2], "/")
+ if base != cur_base and len(list) > max_src:
+ if num > 0:
+ lib = env.Library("drivers"+str(num), list)
+ lib_list.append(lib)
+ list = []
+ num = num+1
+ cur_base = base
+ list.append(f)
-if len(lib_list) > 0:
- import os, sys
- if os.name=='posix' and sys.platform=='msys':
- env.Replace(ARFLAGS=['rcsT'])
+ lib = env.Library("drivers"+str(num), list)
+ lib_list.append(lib)
- lib = env.Library("drivers_collated", lib_list)
- lib_list = [lib]
+ if len(lib_list) > 0:
+ import os, sys
+ if os.name=='posix' and sys.platform=='msys':
+ env.Replace(ARFLAGS=['rcsT'])
-drivers_base=[]
-env.add_source_files(drivers_base,"*.cpp")
-lib_list.insert(0, env.Library("drivers", drivers_base))
+ lib = env.Library("drivers_collated", lib_list)
+ lib_list = [lib]
-env.Prepend(LIBS=lib_list)
+ drivers_base=[]
+ env.add_source_files(drivers_base,"*.cpp")
+ lib_list.insert(0, env.Library("drivers", drivers_base))
-#lib = env.Library("drivers",env.drivers_sources)
-#env.Prepend(LIBS=[lib])
+ env.Prepend(LIBS=lib_list)
+else:
+ env.add_source_files(env.drivers_sources,"*.cpp")
+ lib = env.Library("drivers",env.drivers_sources)
+ env.Prepend(LIBS=[lib])
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index 4bc35f86ee..6a3bd9bb22 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/alsa/audio_driver_alsa.h b/drivers/alsa/audio_driver_alsa.h
index 10f9298859..54fc8dccc9 100644
--- a/drivers/alsa/audio_driver_alsa.h
+++ b/drivers/alsa/audio_driver_alsa.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_config.h b/drivers/chibi/cp_config.h
index 9cd754ed47..2ad704ace7 100644
--- a/drivers/chibi/cp_config.h
+++ b/drivers/chibi/cp_config.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_envelope.cpp b/drivers/chibi/cp_envelope.cpp
index 6ed42a1167..fab8a68ada 100644
--- a/drivers/chibi/cp_envelope.cpp
+++ b/drivers/chibi/cp_envelope.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_envelope.h b/drivers/chibi/cp_envelope.h
index e01605ada3..d1ada53f7d 100644
--- a/drivers/chibi/cp_envelope.h
+++ b/drivers/chibi/cp_envelope.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_file_access_wrapper.cpp b/drivers/chibi/cp_file_access_wrapper.cpp
index d7c6c6d0b6..8ccde3735c 100644
--- a/drivers/chibi/cp_file_access_wrapper.cpp
+++ b/drivers/chibi/cp_file_access_wrapper.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_file_access_wrapper.h b/drivers/chibi/cp_file_access_wrapper.h
index c54ce5868d..5b361c0ea8 100644
--- a/drivers/chibi/cp_file_access_wrapper.h
+++ b/drivers/chibi/cp_file_access_wrapper.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_instrument.cpp b/drivers/chibi/cp_instrument.cpp
index 2e5af70565..7a732e33a4 100644
--- a/drivers/chibi/cp_instrument.cpp
+++ b/drivers/chibi/cp_instrument.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_instrument.h b/drivers/chibi/cp_instrument.h
index 8b434402c5..d8eb8333ee 100644
--- a/drivers/chibi/cp_instrument.h
+++ b/drivers/chibi/cp_instrument.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_loader.h b/drivers/chibi/cp_loader.h
index 7763c395b9..9d1074d1b8 100644
--- a/drivers/chibi/cp_loader.h
+++ b/drivers/chibi/cp_loader.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_loader_it.cpp b/drivers/chibi/cp_loader_it.cpp
index 74dd228437..20a3960a23 100644
--- a/drivers/chibi/cp_loader_it.cpp
+++ b/drivers/chibi/cp_loader_it.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_loader_it.h b/drivers/chibi/cp_loader_it.h
index 6ba605bf04..38a1cdd9c4 100644
--- a/drivers/chibi/cp_loader_it.h
+++ b/drivers/chibi/cp_loader_it.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_loader_it_info.cpp b/drivers/chibi/cp_loader_it_info.cpp
index 0cfd73f1e3..0360f7f9a4 100644
--- a/drivers/chibi/cp_loader_it_info.cpp
+++ b/drivers/chibi/cp_loader_it_info.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_loader_it_instruments.cpp b/drivers/chibi/cp_loader_it_instruments.cpp
index 6293be162c..ccb24bd81c 100644
--- a/drivers/chibi/cp_loader_it_instruments.cpp
+++ b/drivers/chibi/cp_loader_it_instruments.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_loader_it_patterns.cpp b/drivers/chibi/cp_loader_it_patterns.cpp
index c79dffc180..d951a91620 100644
--- a/drivers/chibi/cp_loader_it_patterns.cpp
+++ b/drivers/chibi/cp_loader_it_patterns.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_loader_it_samples.cpp b/drivers/chibi/cp_loader_it_samples.cpp
index 24d3a12781..ced7252a6c 100644
--- a/drivers/chibi/cp_loader_it_samples.cpp
+++ b/drivers/chibi/cp_loader_it_samples.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_loader_mod.cpp b/drivers/chibi/cp_loader_mod.cpp
index 98174ff9b1..f867b77914 100644
--- a/drivers/chibi/cp_loader_mod.cpp
+++ b/drivers/chibi/cp_loader_mod.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -446,18 +446,19 @@ CPLoader::Error CPLoader_MOD::load_song(const char *p_file,CPSong *p_song,bool p
if (sid.is_null()) {
continue; //empty sample, not stored?
}
-
+ sm->lock_data(sid);
+ uint8_t *dataptr = (uint8_t*)sm->get_data(sid);
+
int len=sm->get_size(sid);
for (int s=0;s<len;s++) {
uint8_t d=file->get_byte();
//d-=128; //convert to signed
int8_t*ds=(int8_t*)&d;
- int16_t d16=*ds;
- d16<<=8;
- sm->set_data( sid, s, d16 );
+ dataptr[s]=*ds;
}
+ sm->unlock_data(sid);
}
file->close();
diff --git a/drivers/chibi/cp_loader_mod.h b/drivers/chibi/cp_loader_mod.h
index 77245349b7..636f4f00f2 100644
--- a/drivers/chibi/cp_loader_mod.h
+++ b/drivers/chibi/cp_loader_mod.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_loader_s3m.cpp b/drivers/chibi/cp_loader_s3m.cpp
index c21f7bdd38..0fc15c1e2f 100644
--- a/drivers/chibi/cp_loader_s3m.cpp
+++ b/drivers/chibi/cp_loader_s3m.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -196,8 +196,12 @@ CPLoader::Error CPLoader_S3M::load_sample(CPSample *p_sample) {
if (id.is_null())
return FILE_OUT_OF_MEMORY;
+
+ sm->lock_data(id);
+ void *dataptr = sm->get_data(id);
- for (int c=0;c<(data_is_stereo?2:1);c++) {
+ int chans = (data_is_stereo?2:1);
+ for (int c=0;c<chans;c++) {
for (int i=0;i<sample_size;i++) {
if (data_is_16bits) {
@@ -206,7 +210,7 @@ CPLoader::Error CPLoader_S3M::load_sample(CPSample *p_sample) {
s-=32768; //toggle sign
int16_t *v=(int16_t*)&s;
- sm->set_data(id,i,*v,c);
+ ((int16_t*)dataptr)[i*chans+c]=*v;
} else {
@@ -214,16 +218,16 @@ CPLoader::Error CPLoader_S3M::load_sample(CPSample *p_sample) {
uint8_t s=file->get_byte();
s-=128; //toggle sign
v=(int8_t*)&s;
- int16_t v16=*v;
- v16<<=8;
- sm->set_data(id,i,v16,c);
-
+ ((int8_t*)dataptr)[i*chans+c]=*v;
+
}
-
-
+
}
}
+
+ sm->unlock_data(id);
+
sm->set_loop_begin( id, loop_begin );
sm->set_loop_end( id, loop_end );
diff --git a/drivers/chibi/cp_loader_s3m.h b/drivers/chibi/cp_loader_s3m.h
index 6fe9f0ca44..175e5e80fe 100644
--- a/drivers/chibi/cp_loader_s3m.h
+++ b/drivers/chibi/cp_loader_s3m.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_loader_xm.cpp b/drivers/chibi/cp_loader_xm.cpp
index 8bde6b673e..8ab6abc650 100644
--- a/drivers/chibi/cp_loader_xm.cpp
+++ b/drivers/chibi/cp_loader_xm.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -627,6 +627,10 @@ CPLoader::Error CPLoader_XM::load_instrument_internal(CPInstrument *p_instr,bool
CPSample *sample=song->get_sample(sample_index[j]);
CPSample_ID sid=sample->get_sample_data();
+ sm->lock_data(sid);
+
+ void*dataptr=sm->get_data(sid);
+
if (sm->is_16bits( sid)) {
int16_t old=0;
@@ -638,8 +642,9 @@ CPLoader::Error CPLoader_XM::load_instrument_internal(CPInstrument *p_instr,bool
int16_t sampleval=file->get_word();
newsample=sampleval+old;
old=newsample;
-
- sm->set_data( sid, k, newsample );
+
+ ((int16_t*)dataptr)[k]=newsample;
+ //sm->set_data( sid, k, newsample );
}
} else {
@@ -653,10 +658,15 @@ CPLoader::Error CPLoader_XM::load_instrument_internal(CPInstrument *p_instr,bool
newsample=sampleval+old;
old=newsample;
- sm->set_data( sid, k, (int16_t)newsample << 8 );
+ ((int8_t*)dataptr)[k]=newsample;
+
+ //sm->set_data( sid, k, (int16_t)newsample << 8 );
}
}
+
+ sm->unlock_data(sid);
+
}
for (int j=0;j<96;j++) {
diff --git a/drivers/chibi/cp_loader_xm.h b/drivers/chibi/cp_loader_xm.h
index 0a2465475f..9ae480cc8f 100644
--- a/drivers/chibi/cp_loader_xm.h
+++ b/drivers/chibi/cp_loader_xm.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_mixer.h b/drivers/chibi/cp_mixer.h
index bac2087edf..7ad22ac146 100644
--- a/drivers/chibi/cp_mixer.h
+++ b/drivers/chibi/cp_mixer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_note.h b/drivers/chibi/cp_note.h
index 5d2c01844a..5cfa3f11ec 100644
--- a/drivers/chibi/cp_note.h
+++ b/drivers/chibi/cp_note.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_order.h b/drivers/chibi/cp_order.h
index a20e202bde..03ecc00bba 100644
--- a/drivers/chibi/cp_order.h
+++ b/drivers/chibi/cp_order.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_pattern.cpp b/drivers/chibi/cp_pattern.cpp
index cc65833d68..83e165bf87 100644
--- a/drivers/chibi/cp_pattern.cpp
+++ b/drivers/chibi/cp_pattern.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_pattern.h b/drivers/chibi/cp_pattern.h
index 22611eabab..4065caa5e5 100644
--- a/drivers/chibi/cp_pattern.h
+++ b/drivers/chibi/cp_pattern.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_player_data.cpp b/drivers/chibi/cp_player_data.cpp
index 76d8f280d2..3f3e9a5202 100644
--- a/drivers/chibi/cp_player_data.cpp
+++ b/drivers/chibi/cp_player_data.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_player_data.h b/drivers/chibi/cp_player_data.h
index 36a27942cb..282592b8f4 100644
--- a/drivers/chibi/cp_player_data.h
+++ b/drivers/chibi/cp_player_data.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_player_data_control.cpp b/drivers/chibi/cp_player_data_control.cpp
index d5ca648fff..d9aaed904f 100644
--- a/drivers/chibi/cp_player_data_control.cpp
+++ b/drivers/chibi/cp_player_data_control.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_player_data_effects.cpp b/drivers/chibi/cp_player_data_effects.cpp
index eb62b8d962..3a52a3b91b 100644
--- a/drivers/chibi/cp_player_data_effects.cpp
+++ b/drivers/chibi/cp_player_data_effects.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_player_data_envelopes.cpp b/drivers/chibi/cp_player_data_envelopes.cpp
index 94378b8bf4..96af42d19f 100644
--- a/drivers/chibi/cp_player_data_envelopes.cpp
+++ b/drivers/chibi/cp_player_data_envelopes.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_player_data_events.cpp b/drivers/chibi/cp_player_data_events.cpp
index 7a7cfdf5bb..8122988516 100644
--- a/drivers/chibi/cp_player_data_events.cpp
+++ b/drivers/chibi/cp_player_data_events.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_player_data_filter.cpp b/drivers/chibi/cp_player_data_filter.cpp
index fd87e4ae7a..30db807eed 100644
--- a/drivers/chibi/cp_player_data_filter.cpp
+++ b/drivers/chibi/cp_player_data_filter.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_player_data_nna.cpp b/drivers/chibi/cp_player_data_nna.cpp
index 3960234f5e..844f043694 100644
--- a/drivers/chibi/cp_player_data_nna.cpp
+++ b/drivers/chibi/cp_player_data_nna.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_player_data_notes.cpp b/drivers/chibi/cp_player_data_notes.cpp
index ea3ba42e86..621be019e1 100644
--- a/drivers/chibi/cp_player_data_notes.cpp
+++ b/drivers/chibi/cp_player_data_notes.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_player_data_reserved.cpp b/drivers/chibi/cp_player_data_reserved.cpp
index 8d9439158b..a626ffd111 100644
--- a/drivers/chibi/cp_player_data_reserved.cpp
+++ b/drivers/chibi/cp_player_data_reserved.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_player_data_utils.cpp b/drivers/chibi/cp_player_data_utils.cpp
index 5294fc8139..170a849863 100644
--- a/drivers/chibi/cp_player_data_utils.cpp
+++ b/drivers/chibi/cp_player_data_utils.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_sample.cpp b/drivers/chibi/cp_sample.cpp
index bff24d4c4c..55c2c910a5 100644
--- a/drivers/chibi/cp_sample.cpp
+++ b/drivers/chibi/cp_sample.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_sample.h b/drivers/chibi/cp_sample.h
index 71b57aaa81..4b3d218106 100644
--- a/drivers/chibi/cp_sample.h
+++ b/drivers/chibi/cp_sample.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_sample_defs.h b/drivers/chibi/cp_sample_defs.h
index 32817efc7d..169963c98e 100644
--- a/drivers/chibi/cp_sample_defs.h
+++ b/drivers/chibi/cp_sample_defs.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_sample_manager.cpp b/drivers/chibi/cp_sample_manager.cpp
index 601db07acf..5c2988e3f9 100644
--- a/drivers/chibi/cp_sample_manager.cpp
+++ b/drivers/chibi/cp_sample_manager.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_sample_manager.h b/drivers/chibi/cp_sample_manager.h
index 2891034482..74bcafc0cf 100644
--- a/drivers/chibi/cp_sample_manager.h
+++ b/drivers/chibi/cp_sample_manager.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_song.cpp b/drivers/chibi/cp_song.cpp
index 956e2ee6d4..4aa1a4228d 100644
--- a/drivers/chibi/cp_song.cpp
+++ b/drivers/chibi/cp_song.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_song.h b/drivers/chibi/cp_song.h
index 6c35b43c76..da5d106a63 100644
--- a/drivers/chibi/cp_song.h
+++ b/drivers/chibi/cp_song.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_tables.cpp b/drivers/chibi/cp_tables.cpp
index 9f1ae30c9a..8c62150f31 100644
--- a/drivers/chibi/cp_tables.cpp
+++ b/drivers/chibi/cp_tables.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/cp_tables.h b/drivers/chibi/cp_tables.h
index 6c3c9271b0..ac7ee562b7 100644
--- a/drivers/chibi/cp_tables.h
+++ b/drivers/chibi/cp_tables.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/event_stream_chibi.cpp b/drivers/chibi/event_stream_chibi.cpp
index ecb5c3f22b..3449583d36 100644
--- a/drivers/chibi/event_stream_chibi.cpp
+++ b/drivers/chibi/event_stream_chibi.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/chibi/event_stream_chibi.h b/drivers/chibi/event_stream_chibi.h
index b564c16018..cc7b0ace86 100644
--- a/drivers/chibi/event_stream_chibi.h
+++ b/drivers/chibi/event_stream_chibi.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/convex_decomp/b2Polygon.cpp b/drivers/convex_decomp/b2Polygon.cpp
index 775f2adfe2..73955d3573 100644
--- a/drivers/convex_decomp/b2Polygon.cpp
+++ b/drivers/convex_decomp/b2Polygon.cpp
@@ -217,8 +217,8 @@ b2Polygon::b2Polygon(b2Triangle& t) {
void b2Polygon::Set(const b2Polygon& p) {
if (nVertices != p.nVertices){
nVertices = p.nVertices;
- if (x) delete[] x;
- if (y) delete[] y;
+ delete[] x;
+ delete[] y;
x = new float32[nVertices];
y = new float32[nVertices];
}
diff --git a/drivers/gl_context/context_gl.cpp b/drivers/gl_context/context_gl.cpp
index 82195cc6f6..c1bf6b38ea 100644
--- a/drivers/gl_context/context_gl.cpp
+++ b/drivers/gl_context/context_gl.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/drivers/gl_context/context_gl.h b/drivers/gl_context/context_gl.h
index 6b06ccdc37..1ea3662ada 100644
--- a/drivers/gl_context/context_gl.h
+++ b/drivers/gl_context/context_gl.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index 39b448d6e0..f0978228ff 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -929,6 +929,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I
texture->compressed=compressed;
texture->has_alpha=false; //by default it doesn't have alpha unless something with alpha is blitteds
texture->data_size=0;
+ texture->mipmaps=0;
glActiveTexture(GL_TEXTURE0);
@@ -1086,6 +1087,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
glGenerateMipmap(texture->target);
}
+ texture->mipmaps=mipmaps;
@@ -1269,11 +1271,14 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) {
p_flags&=VS::TEXTURE_FLAG_FILTER;//can change only filter
}
+ bool had_mipmaps = texture->flags&VS::TEXTURE_FLAG_MIPMAPS;
+
glActiveTexture(GL_TEXTURE0);
glBindTexture(texture->target, texture->tex_id);
uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP;
texture->flags=p_flags|cube; // can't remove a cube from being a cube
+
bool force_clamp_to_edge = !(p_flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) && (nearest_power_of_2(texture->alloc_height)!=texture->alloc_height || nearest_power_of_2(texture->alloc_width)!=texture->alloc_width);
if (!force_clamp_to_edge && (texture->flags&VS::TEXTURE_FLAG_REPEAT || texture->flags&VS::TEXTURE_FLAG_MIRRORED_REPEAT) && texture->target != GL_TEXTURE_CUBE_MAP) {
@@ -1304,9 +1309,13 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) {
}
}
- if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps)
+ if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) {
+ if (!had_mipmaps && texture->mipmaps==1) {
+ glGenerateMipmap(texture->target);
+ }
glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR);
- else{
+
+ } else{
if (texture->flags&VS::TEXTURE_FLAG_FILTER) {
glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
} else {
@@ -6746,7 +6755,13 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
if (e->instance->billboard) {
Vector3 scale = xf.basis.get_scale();
- xf.set_look_at(xf.origin,xf.origin+p_view_transform.get_basis().get_axis(2),p_view_transform.get_basis().get_axis(1));
+
+ if (current_rt && current_rt_vflip) {
+ xf.set_look_at(xf.origin, xf.origin + p_view_transform.get_basis().get_axis(2), -p_view_transform.get_basis().get_axis(1));
+ } else {
+ xf.set_look_at(xf.origin, xf.origin + p_view_transform.get_basis().get_axis(2), p_view_transform.get_basis().get_axis(1));
+ }
+
xf.basis.scale(scale);
}
material_shader.set_uniform(MaterialShaderGLES2::WORLD_TRANSFORM, xf);
@@ -8330,6 +8345,14 @@ void RasterizerGLES2::canvas_draw_rect(const Rect2& p_rect, int p_flags, const R
if ( texture ) {
+ bool untile=false;
+
+ if (p_flags&CANVAS_RECT_TILE && !(texture->flags&VS::TEXTURE_FLAG_REPEAT)) {
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+ untile=true;
+ }
+
if (!(p_flags&CANVAS_RECT_REGION)) {
Rect2 region = Rect2(0,0,texture->width,texture->height);
@@ -8340,6 +8363,12 @@ void RasterizerGLES2::canvas_draw_rect(const Rect2& p_rect, int p_flags, const R
_draw_textured_quad(p_rect, p_source, Size2(texture->width,texture->height),p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V,p_flags&CANVAS_RECT_TRANSPOSE);
}
+
+ if (untile) {
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ }
+
} else {
//glDisable(GL_TEXTURE_2D);
@@ -9169,10 +9198,23 @@ void RasterizerGLES2::_canvas_item_render_commands(CanvasItem *p_item,CanvasItem
//glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)),
//current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height);
- int x = current_clip->final_clip_rect.pos.x;
- int y = window_size.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.y);
- int w = current_clip->final_clip_rect.size.x;
- int h = current_clip->final_clip_rect.size.y;
+ int x;
+ int y;
+ int w;
+ int h;
+
+ if (current_rt) {
+ x = current_clip->final_clip_rect.pos.x;
+ y = current_clip->final_clip_rect.pos.y;
+ w = current_clip->final_clip_rect.size.x;
+ h = current_clip->final_clip_rect.size.y;
+ }
+ else {
+ x = current_clip->final_clip_rect.pos.x;
+ y = window_size.height - (current_clip->final_clip_rect.pos.y + current_clip->final_clip_rect.size.y);
+ w = current_clip->final_clip_rect.size.x;
+ h = current_clip->final_clip_rect.size.y;
+ }
glScissor(x,y,w,h);
@@ -9362,10 +9404,23 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
int w = current_clip->final_clip_rect.size.x;
int h = current_clip->final_clip_rect.size.y;
*/
- int x = current_clip->final_clip_rect.pos.x;
- int y = window_size.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.y);
- int w = current_clip->final_clip_rect.size.x;
- int h = current_clip->final_clip_rect.size.y;
+ int x;
+ int y;
+ int w;
+ int h;
+
+ if (current_rt) {
+ x = current_clip->final_clip_rect.pos.x;
+ y = current_clip->final_clip_rect.pos.y;
+ w = current_clip->final_clip_rect.size.x;
+ h = current_clip->final_clip_rect.size.y;
+ }
+ else {
+ x = current_clip->final_clip_rect.pos.x;
+ y = window_size.height - (current_clip->final_clip_rect.pos.y + current_clip->final_clip_rect.size.y);
+ w = current_clip->final_clip_rect.size.x;
+ h = current_clip->final_clip_rect.size.y;
+ }
glScissor(x,y,w,h);
@@ -9514,7 +9569,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_opacity = ci->final_opacity;
- if (unshaded || (p_modulate.a>0.001 && (!material || material->shading_mode!=VS::CANVAS_ITEM_SHADING_ONLY_LIGHT)))
+ if (unshaded || (p_modulate.a>0.001 && (!material || material->shading_mode!=VS::CANVAS_ITEM_SHADING_ONLY_LIGHT) && !ci->light_masked ))
_canvas_item_render_commands<false>(ci,current_clip,reclip);
if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light && !unshaded) {
@@ -9546,7 +9601,8 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
} break;
- case VS::CANVAS_LIGHT_MODE_MIX: {
+ case VS::CANVAS_LIGHT_MODE_MIX:
+ case VS::CANVAS_LIGHT_MODE_MASK: {
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -9594,6 +9650,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,Color(light->color.r*light->energy,light->color.g*light->energy,light->color.b*light->energy,light->color.a));
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT,light->height);
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX,light->xform_cache.affine_inverse());
+ canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_OUTSIDE_ALPHA,light->mode==VS::CANVAS_LIGHT_MODE_MASK?1.0:0.0);
if (has_shadow) {
@@ -9667,10 +9724,23 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
//glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)),
//current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height);
- int x = current_clip->final_clip_rect.pos.x;
- int y = window_size.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.y);
- int w = current_clip->final_clip_rect.size.x;
- int h = current_clip->final_clip_rect.size.y;
+ int x;
+ int y;
+ int w;
+ int h;
+
+ if (current_rt) {
+ x = current_clip->final_clip_rect.pos.x;
+ y = current_clip->final_clip_rect.pos.y;
+ w = current_clip->final_clip_rect.size.x;
+ h = current_clip->final_clip_rect.size.y;
+ }
+ else {
+ x = current_clip->final_clip_rect.pos.x;
+ y = window_size.height - (current_clip->final_clip_rect.pos.y + current_clip->final_clip_rect.size.y);
+ w = current_clip->final_clip_rect.size.x;
+ h = current_clip->final_clip_rect.size.y;
+ }
glScissor(x,y,w,h);
@@ -10265,6 +10335,8 @@ void RasterizerGLES2::_update_framebuffer() {
return;
int scale = GLOBAL_DEF("rasterizer/framebuffer_shrink",1);
+ if (scale<1)
+ scale=1;
int dwidth = OS::get_singleton()->get_video_mode().width/scale;
int dheight = OS::get_singleton()->get_video_mode().height/scale;
@@ -10353,6 +10425,13 @@ void RasterizerGLES2::_update_framebuffer() {
GLuint format_rgba = GL_RGBA;
GLuint format_rgb = use_fp16_fb?_GL_RGB16F_EXT:GL_RGB;
GLuint format_type = use_fp16_fb?_GL_HALF_FLOAT_OES:GL_UNSIGNED_BYTE;
+ GLuint format_internal=GL_RGBA;
+
+ if (use_16bits_fbo) {
+ format_type=GL_UNSIGNED_SHORT_5_6_5;
+ format_rgba=GL_RGB;
+ format_internal=GL_RGB;
+ }
/*GLuint format_luminance = use_fp16_fb?GL_RGB16F:GL_RGBA;
GLuint format_luminance_type = use_fp16_fb?(use_fu_GL_HALF_FLOAT_OES):GL_UNSIGNED_BYTE;
GLuint format_luminance_components = use_fp16_fb?GL_RGB:GL_RGBA;*/
@@ -10366,7 +10445,7 @@ void RasterizerGLES2::_update_framebuffer() {
glGenTextures(1, &framebuffer.color);
glBindTexture(GL_TEXTURE_2D, framebuffer.color);
- glTexImage2D(GL_TEXTURE_2D, 0, format_rgba, framebuffer.width, framebuffer.height, 0, GL_RGBA, format_type, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, format_rgba, framebuffer.width, framebuffer.height, 0, format_internal, format_type, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -10391,7 +10470,7 @@ void RasterizerGLES2::_update_framebuffer() {
framebuffer.fbo=0;
framebuffer.active=false;
//print_line("**************** NO FAMEBUFFEEEERRRR????");
- WARN_PRINT("Could not create framebuffer!!");
+ WARN_PRINT(String("Could not create framebuffer!!, code: "+itos(status)).ascii().get_data());
}
//sample
@@ -10400,7 +10479,7 @@ void RasterizerGLES2::_update_framebuffer() {
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.sample_fbo);
glGenTextures(1, &framebuffer.sample_color);
glBindTexture(GL_TEXTURE_2D, framebuffer.sample_color);
- glTexImage2D(GL_TEXTURE_2D, 0, format_rgba, framebuffer.width, framebuffer.height, 0, GL_RGBA, format_type, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, format_rgba, framebuffer.width, framebuffer.height, 0, format_internal, format_type, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -10460,7 +10539,7 @@ void RasterizerGLES2::_update_framebuffer() {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, format_rgba, size, size, 0,
- GL_RGBA, format_type, NULL);
+ format_internal, format_type, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, framebuffer.blur[i].color, 0);
@@ -11189,6 +11268,11 @@ RasterizerGLES2* RasterizerGLES2::get_singleton() {
int RasterizerGLES2::RenderList::max_elements=RenderList::DEFAULT_MAX_ELEMENTS;
+void RasterizerGLES2::set_force_16_bits_fbo(bool p_force) {
+
+ use_16bits_fbo=p_force;
+}
+
RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,bool p_default_fragment_lighting,bool p_use_reload_hooks) {
_singleton = this;
@@ -11250,6 +11334,7 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo
framebuffer.active=false;
tc0_id_cache=0;
tc0_idx=0;
+ use_16bits_fbo=false;
};
void RasterizerGLES2::restore_framebuffer() {
diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h
index d6d9593da8..0f70ceaa97 100644
--- a/drivers/gles2/rasterizer_gles2.h
+++ b/drivers/gles2/rasterizer_gles2.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -91,6 +91,7 @@ class RasterizerGLES2 : public Rasterizer {
bool srgb_supported;
bool float_supported;
bool float_linear_supported;
+ bool use_16bits_fbo;
ShadowFilterTechnique shadow_filter;
@@ -137,6 +138,8 @@ class RasterizerGLES2 : public Rasterizer {
StringName reloader_func;
Image image[6];
+ int mipmaps;
+
bool active;
GLuint tex_id;
@@ -158,6 +161,7 @@ class RasterizerGLES2 : public Rasterizer {
compressed=false;
total_data_size=0;
target=GL_TEXTURE_2D;
+ mipmaps=0;
reloader=0;
}
@@ -1705,6 +1709,8 @@ public:
static RasterizerGLES2* get_singleton();
+ virtual void set_force_16_bits_fbo(bool p_force);
+
RasterizerGLES2(bool p_compress_arrays=false,bool p_keep_ram_copy=true,bool p_default_fragment_lighting=true,bool p_use_reload_hooks=false);
virtual ~RasterizerGLES2();
};
diff --git a/drivers/gles2/rasterizer_instance_gles2.cpp b/drivers/gles2/rasterizer_instance_gles2.cpp
index a8d478c6e0..9d43ecb085 100644
--- a/drivers/gles2/rasterizer_instance_gles2.cpp
+++ b/drivers/gles2/rasterizer_instance_gles2.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/gles2/rasterizer_instance_gles2.h b/drivers/gles2/rasterizer_instance_gles2.h
index f5ac5f1fe2..c41bd71c15 100644
--- a/drivers/gles2/rasterizer_instance_gles2.h
+++ b/drivers/gles2/rasterizer_instance_gles2.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index f981529ee3..3be0fdab17 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h
index 46ef2e035f..688003ecf6 100644
--- a/drivers/gles2/shader_compiler_gles2.h
+++ b/drivers/gles2/shader_compiler_gles2.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp
index e94930fffb..d397323171 100644
--- a/drivers/gles2/shader_gles2.cpp
+++ b/drivers/gles2/shader_gles2.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -739,12 +739,12 @@ void ShaderGLES2::set_custom_shader(uint32_t p_code_id) {
void ShaderGLES2::free_custom_shader(uint32_t p_code_id) {
- if (! custom_code_map.has( p_code_id )) {
+ /* if (! custom_code_map.has( p_code_id )) {
print_line("no code id "+itos(p_code_id));
} else {
print_line("freed code id "+itos(p_code_id));
- }
+ }*/
ERR_FAIL_COND(! custom_code_map.has( p_code_id ));
if (conditional_version.code_version==p_code_id)
diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h
index 4604fd5501..68ae8af63f 100644
--- a/drivers/gles2/shader_gles2.h
+++ b/drivers/gles2/shader_gles2.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -205,6 +205,11 @@ private:
Plane val=p_value;
glUniform4f( p_uniform, val.normal.x,val.normal.y,val.normal.z,val.d );
} break;
+ case Variant::QUAT: {
+
+ Quat val=p_value;
+ glUniform4f( p_uniform, val.x,val.y,val.z,val.w );
+ } break;
case Variant::MATRIX32: {
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index e297b328cd..285abd30ff 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -155,6 +155,7 @@ uniform vec4 light_color;
uniform vec4 light_shadow_color;
uniform float light_height;
varying vec4 light_uv_interp;
+uniform float light_outside_alpha;
#if defined(NORMAL_USED)
varying vec4 local_rot;
@@ -195,7 +196,7 @@ void main() {
#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);
+ color.a = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance) * color.a;
#else
color *= texture2D( texture, uv_interp );
@@ -247,22 +248,27 @@ FRAGMENT_SHADER_CODE
vec4 shadow_color=vec4(0.0,0.0,0.0,0.0);
#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*=light_outside_alpha; //invisible
+
+ } else {
+
#if defined(USE_LIGHT_SHADER_CODE)
//light is written by the light shader
-{
- vec4 light_out=light*color;
+ {
+ vec4 light_out=light*color;
LIGHT_SHADER_CODE
- color=light_out;
-}
+ color=light_out;
+ }
#else
#if defined(NORMAL_USED)
- vec3 light_normal = normalize(vec3(light_vec,-light_height));
- light*=max(dot(-light_normal,normal),0.0);
+ vec3 light_normal = normalize(vec3(light_vec,-light_height));
+ light*=max(dot(-light_normal,normal),0.0);
#endif
- color*=light;
+ color*=light;
/*
#ifdef USE_NORMAL
color.xy=local_rot.xy;//normal.xy;
@@ -273,9 +279,6 @@ LIGHT_SHADER_CODE
//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
diff --git a/drivers/jpg/SCsub b/drivers/jpegd/SCsub
index df91b10a02..dfdb19402e 100644
--- a/drivers/jpg/SCsub
+++ b/drivers/jpegd/SCsub
@@ -2,9 +2,8 @@ Import('env')
jpg_sources = [
- "jpg/tinyjpeg.c",
- "jpg/jidctflt.c",
- "jpg/image_loader_jpg.cpp"
+ "jpegd/jpgd.cpp",
+ "jpegd/image_loader_jpegd.cpp"
]
env.drivers_sources+=jpg_sources
diff --git a/drivers/jpegd/image_loader_jpegd.cpp b/drivers/jpegd/image_loader_jpegd.cpp
new file mode 100644
index 0000000000..9d1263b81b
--- /dev/null
+++ b/drivers/jpegd/image_loader_jpegd.cpp
@@ -0,0 +1,108 @@
+/*************************************************/
+/* image_loader_jpg.cpp */
+/*************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/*************************************************/
+/* Source code within this file is: */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
+/* All Rights Reserved. */
+/*************************************************/
+
+#include "image_loader_jpegd.h"
+
+#include "print_string.h"
+#include "os/os.h"
+#include "jpgd.h"
+#include <string.h>
+
+
+Error ImageLoaderJPG::load_image(Image *p_image,FileAccess *f) {
+
+
+ DVector<uint8_t> src_image;
+ int src_image_len = f->get_len();
+ ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);
+ src_image.resize(src_image_len);
+
+ DVector<uint8_t>::Write w = src_image.write();
+
+ f->get_buffer(&w[0],src_image_len);
+
+ f->close();
+
+
+
+ jpgd::jpeg_decoder_mem_stream mem_stream(w.ptr(),src_image_len);
+
+ jpgd::jpeg_decoder decoder(&mem_stream);
+
+ if (decoder.get_error_code() != jpgd::JPGD_SUCCESS) {
+ return ERR_CANT_OPEN;
+ }
+
+ const int image_width = decoder.get_width();
+ const int image_height = decoder.get_height();
+ int comps = decoder.get_num_components();
+ if (comps==3)
+ comps=4; //weird
+
+ if (decoder.begin_decoding() != jpgd::JPGD_SUCCESS)
+ return ERR_FILE_CORRUPT;
+
+ const int dst_bpl = image_width * comps;
+
+ DVector<uint8_t> data;
+
+ data.resize(dst_bpl * image_height);
+
+ DVector<uint8_t>::Write dw = data.write();
+
+ jpgd::uint8 *pImage_data = (jpgd::uint8*)dw.ptr();
+
+ for (int y = 0; y < image_height; y++)
+ {
+ const jpgd::uint8* pScan_line;
+ jpgd::uint scan_line_len;
+ if (decoder.decode((const void**)&pScan_line, &scan_line_len) != jpgd::JPGD_SUCCESS)
+ {
+ return ERR_FILE_CORRUPT;
+ }
+
+ jpgd::uint8 *pDst = pImage_data + y * dst_bpl;
+ memcpy(pDst, pScan_line, dst_bpl);
+
+
+ }
+
+
+ //all good
+
+ Image::Format fmt;
+ if (comps==1)
+ fmt=Image::FORMAT_GRAYSCALE;
+ else
+ fmt=Image::FORMAT_RGBA;
+
+ dw = DVector<uint8_t>::Write();
+ w = DVector<uint8_t>::Write();
+
+ p_image->create(image_width,image_height,0,fmt,data);
+
+ return OK;
+
+}
+
+void ImageLoaderJPG::get_recognized_extensions(List<String> *p_extensions) const {
+
+ p_extensions->push_back("jpg");
+ p_extensions->push_back("jpeg");
+}
+
+
+ImageLoaderJPG::ImageLoaderJPG() {
+
+
+}
+
+
diff --git a/drivers/jpg/image_loader_jpg.h b/drivers/jpegd/image_loader_jpegd.h
index b1d5b8016f..1b2165ab47 100644
--- a/drivers/jpg/image_loader_jpg.h
+++ b/drivers/jpegd/image_loader_jpegd.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/drivers/jpegd/jpgd.cpp b/drivers/jpegd/jpgd.cpp
new file mode 100644
index 0000000000..fad9a37a9a
--- /dev/null
+++ b/drivers/jpegd/jpgd.cpp
@@ -0,0 +1,3172 @@
+// jpgd.cpp - C++ class for JPEG decompression.
+// Public domain, Rich Geldreich <richgel99@gmail.com>
+// Alex Evans: Linear memory allocator (taken from jpge.h).
+// v1.04, May. 19, 2012: Code tweaks to fix VS2008 static code analysis warnings (all looked harmless)
+//
+// Supports progressive and baseline sequential JPEG image files, and the most common chroma subsampling factors: Y, H1V1, H2V1, H1V2, and H2V2.
+//
+// Chroma upsampling quality: H2V2 is upsampled in the frequency domain, H2V1 and H1V2 are upsampled using point sampling.
+// Chroma upsampling reference: "Fast Scheme for Image Size Change in the Compressed Domain"
+// http://vision.ai.uiuc.edu/~dugad/research/dct/index.html
+
+#include "jpgd.h"
+#include <string.h>
+
+#include <assert.h>
+#define JPGD_ASSERT(x) assert(x)
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
+#endif
+
+// Set to 1 to enable freq. domain chroma upsampling on images using H2V2 subsampling (0=faster nearest neighbor sampling).
+// This is slower, but results in higher quality on images with highly saturated colors.
+#define JPGD_SUPPORT_FREQ_DOMAIN_UPSAMPLING 1
+
+#define JPGD_TRUE (1)
+#define JPGD_FALSE (0)
+
+#define JPGD_MAX(a,b) (((a)>(b)) ? (a) : (b))
+#define JPGD_MIN(a,b) (((a)<(b)) ? (a) : (b))
+
+namespace jpgd {
+
+static inline void *jpgd_malloc(size_t nSize) { return malloc(nSize); }
+static inline void jpgd_free(void *p) { free(p); }
+
+// DCT coefficients are stored in this sequence.
+static int g_ZAG[64] = { 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63 };
+
+enum JPEG_MARKER
+{
+ M_SOF0 = 0xC0, M_SOF1 = 0xC1, M_SOF2 = 0xC2, M_SOF3 = 0xC3, M_SOF5 = 0xC5, M_SOF6 = 0xC6, M_SOF7 = 0xC7, M_JPG = 0xC8,
+ M_SOF9 = 0xC9, M_SOF10 = 0xCA, M_SOF11 = 0xCB, M_SOF13 = 0xCD, M_SOF14 = 0xCE, M_SOF15 = 0xCF, M_DHT = 0xC4, M_DAC = 0xCC,
+ M_RST0 = 0xD0, M_RST1 = 0xD1, M_RST2 = 0xD2, M_RST3 = 0xD3, M_RST4 = 0xD4, M_RST5 = 0xD5, M_RST6 = 0xD6, M_RST7 = 0xD7,
+ M_SOI = 0xD8, M_EOI = 0xD9, M_SOS = 0xDA, M_DQT = 0xDB, M_DNL = 0xDC, M_DRI = 0xDD, M_DHP = 0xDE, M_EXP = 0xDF,
+ M_APP0 = 0xE0, M_APP15 = 0xEF, M_JPG0 = 0xF0, M_JPG13 = 0xFD, M_COM = 0xFE, M_TEM = 0x01, M_ERROR = 0x100, RST0 = 0xD0
+};
+
+enum JPEG_SUBSAMPLING { JPGD_GRAYSCALE = 0, JPGD_YH1V1, JPGD_YH2V1, JPGD_YH1V2, JPGD_YH2V2 };
+
+#define CONST_BITS 13
+#define PASS1_BITS 2
+#define SCALEDONE ((int32)1)
+
+#define FIX_0_298631336 ((int32)2446) /* FIX(0.298631336) */
+#define FIX_0_390180644 ((int32)3196) /* FIX(0.390180644) */
+#define FIX_0_541196100 ((int32)4433) /* FIX(0.541196100) */
+#define FIX_0_765366865 ((int32)6270) /* FIX(0.765366865) */
+#define FIX_0_899976223 ((int32)7373) /* FIX(0.899976223) */
+#define FIX_1_175875602 ((int32)9633) /* FIX(1.175875602) */
+#define FIX_1_501321110 ((int32)12299) /* FIX(1.501321110) */
+#define FIX_1_847759065 ((int32)15137) /* FIX(1.847759065) */
+#define FIX_1_961570560 ((int32)16069) /* FIX(1.961570560) */
+#define FIX_2_053119869 ((int32)16819) /* FIX(2.053119869) */
+#define FIX_2_562915447 ((int32)20995) /* FIX(2.562915447) */
+#define FIX_3_072711026 ((int32)25172) /* FIX(3.072711026) */
+
+#define DESCALE(x,n) (((x) + (SCALEDONE << ((n)-1))) >> (n))
+#define DESCALE_ZEROSHIFT(x,n) (((x) + (128 << (n)) + (SCALEDONE << ((n)-1))) >> (n))
+
+#define MULTIPLY(var, cnst) ((var) * (cnst))
+
+#define CLAMP(i) ((static_cast<uint>(i) > 255) ? (((~i) >> 31) & 0xFF) : (i))
+
+// Compiler creates a fast path 1D IDCT for X non-zero columns
+template <int NONZERO_COLS>
+struct Row
+{
+ static void idct(int* pTemp, const jpgd_block_t* pSrc)
+ {
+ // ACCESS_COL() will be optimized at compile time to either an array access, or 0.
+ #define ACCESS_COL(x) (((x) < NONZERO_COLS) ? (int)pSrc[x] : 0)
+
+ const int z2 = ACCESS_COL(2), z3 = ACCESS_COL(6);
+
+ const int z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+ const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
+ const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
+
+ const int tmp0 = (ACCESS_COL(0) + ACCESS_COL(4)) << CONST_BITS;
+ const int tmp1 = (ACCESS_COL(0) - ACCESS_COL(4)) << CONST_BITS;
+
+ const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2;
+
+ const int atmp0 = ACCESS_COL(7), atmp1 = ACCESS_COL(5), atmp2 = ACCESS_COL(3), atmp3 = ACCESS_COL(1);
+
+ const int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3;
+ const int bz5 = MULTIPLY(bz3 + bz4, FIX_1_175875602);
+
+ const int az1 = MULTIPLY(bz1, - FIX_0_899976223);
+ const int az2 = MULTIPLY(bz2, - FIX_2_562915447);
+ const int az3 = MULTIPLY(bz3, - FIX_1_961570560) + bz5;
+ const int az4 = MULTIPLY(bz4, - FIX_0_390180644) + bz5;
+
+ const int btmp0 = MULTIPLY(atmp0, FIX_0_298631336) + az1 + az3;
+ const int btmp1 = MULTIPLY(atmp1, FIX_2_053119869) + az2 + az4;
+ const int btmp2 = MULTIPLY(atmp2, FIX_3_072711026) + az2 + az3;
+ const int btmp3 = MULTIPLY(atmp3, FIX_1_501321110) + az1 + az4;
+
+ pTemp[0] = DESCALE(tmp10 + btmp3, CONST_BITS-PASS1_BITS);
+ pTemp[7] = DESCALE(tmp10 - btmp3, CONST_BITS-PASS1_BITS);
+ pTemp[1] = DESCALE(tmp11 + btmp2, CONST_BITS-PASS1_BITS);
+ pTemp[6] = DESCALE(tmp11 - btmp2, CONST_BITS-PASS1_BITS);
+ pTemp[2] = DESCALE(tmp12 + btmp1, CONST_BITS-PASS1_BITS);
+ pTemp[5] = DESCALE(tmp12 - btmp1, CONST_BITS-PASS1_BITS);
+ pTemp[3] = DESCALE(tmp13 + btmp0, CONST_BITS-PASS1_BITS);
+ pTemp[4] = DESCALE(tmp13 - btmp0, CONST_BITS-PASS1_BITS);
+ }
+};
+
+template <>
+struct Row<0>
+{
+ static void idct(int* pTemp, const jpgd_block_t* pSrc)
+ {
+#ifdef _MSC_VER
+ pTemp; pSrc;
+#endif
+ }
+};
+
+template <>
+struct Row<1>
+{
+ static void idct(int* pTemp, const jpgd_block_t* pSrc)
+ {
+ const int dcval = (pSrc[0] << PASS1_BITS);
+
+ pTemp[0] = dcval;
+ pTemp[1] = dcval;
+ pTemp[2] = dcval;
+ pTemp[3] = dcval;
+ pTemp[4] = dcval;
+ pTemp[5] = dcval;
+ pTemp[6] = dcval;
+ pTemp[7] = dcval;
+ }
+};
+
+// Compiler creates a fast path 1D IDCT for X non-zero rows
+template <int NONZERO_ROWS>
+struct Col
+{
+ static void idct(uint8* pDst_ptr, const int* pTemp)
+ {
+ // ACCESS_ROW() will be optimized at compile time to either an array access, or 0.
+ #define ACCESS_ROW(x) (((x) < NONZERO_ROWS) ? pTemp[x * 8] : 0)
+
+ const int z2 = ACCESS_ROW(2);
+ const int z3 = ACCESS_ROW(6);
+
+ const int z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+ const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
+ const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
+
+ const int tmp0 = (ACCESS_ROW(0) + ACCESS_ROW(4)) << CONST_BITS;
+ const int tmp1 = (ACCESS_ROW(0) - ACCESS_ROW(4)) << CONST_BITS;
+
+ const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2;
+
+ const int atmp0 = ACCESS_ROW(7), atmp1 = ACCESS_ROW(5), atmp2 = ACCESS_ROW(3), atmp3 = ACCESS_ROW(1);
+
+ const int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3;
+ const int bz5 = MULTIPLY(bz3 + bz4, FIX_1_175875602);
+
+ const int az1 = MULTIPLY(bz1, - FIX_0_899976223);
+ const int az2 = MULTIPLY(bz2, - FIX_2_562915447);
+ const int az3 = MULTIPLY(bz3, - FIX_1_961570560) + bz5;
+ const int az4 = MULTIPLY(bz4, - FIX_0_390180644) + bz5;
+
+ const int btmp0 = MULTIPLY(atmp0, FIX_0_298631336) + az1 + az3;
+ const int btmp1 = MULTIPLY(atmp1, FIX_2_053119869) + az2 + az4;
+ const int btmp2 = MULTIPLY(atmp2, FIX_3_072711026) + az2 + az3;
+ const int btmp3 = MULTIPLY(atmp3, FIX_1_501321110) + az1 + az4;
+
+ int i = DESCALE_ZEROSHIFT(tmp10 + btmp3, CONST_BITS+PASS1_BITS+3);
+ pDst_ptr[8*0] = (uint8)CLAMP(i);
+
+ i = DESCALE_ZEROSHIFT(tmp10 - btmp3, CONST_BITS+PASS1_BITS+3);
+ pDst_ptr[8*7] = (uint8)CLAMP(i);
+
+ i = DESCALE_ZEROSHIFT(tmp11 + btmp2, CONST_BITS+PASS1_BITS+3);
+ pDst_ptr[8*1] = (uint8)CLAMP(i);
+
+ i = DESCALE_ZEROSHIFT(tmp11 - btmp2, CONST_BITS+PASS1_BITS+3);
+ pDst_ptr[8*6] = (uint8)CLAMP(i);
+
+ i = DESCALE_ZEROSHIFT(tmp12 + btmp1, CONST_BITS+PASS1_BITS+3);
+ pDst_ptr[8*2] = (uint8)CLAMP(i);
+
+ i = DESCALE_ZEROSHIFT(tmp12 - btmp1, CONST_BITS+PASS1_BITS+3);
+ pDst_ptr[8*5] = (uint8)CLAMP(i);
+
+ i = DESCALE_ZEROSHIFT(tmp13 + btmp0, CONST_BITS+PASS1_BITS+3);
+ pDst_ptr[8*3] = (uint8)CLAMP(i);
+
+ i = DESCALE_ZEROSHIFT(tmp13 - btmp0, CONST_BITS+PASS1_BITS+3);
+ pDst_ptr[8*4] = (uint8)CLAMP(i);
+ }
+};
+
+template <>
+struct Col<1>
+{
+ static void idct(uint8* pDst_ptr, const int* pTemp)
+ {
+ int dcval = DESCALE_ZEROSHIFT(pTemp[0], PASS1_BITS+3);
+ const uint8 dcval_clamped = (uint8)CLAMP(dcval);
+ pDst_ptr[0*8] = dcval_clamped;
+ pDst_ptr[1*8] = dcval_clamped;
+ pDst_ptr[2*8] = dcval_clamped;
+ pDst_ptr[3*8] = dcval_clamped;
+ pDst_ptr[4*8] = dcval_clamped;
+ pDst_ptr[5*8] = dcval_clamped;
+ pDst_ptr[6*8] = dcval_clamped;
+ pDst_ptr[7*8] = dcval_clamped;
+ }
+};
+
+static const uint8 s_idct_row_table[] =
+{
+ 1,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0, 2,1,0,0,0,0,0,0, 2,1,1,0,0,0,0,0, 2,2,1,0,0,0,0,0, 3,2,1,0,0,0,0,0, 4,2,1,0,0,0,0,0, 4,3,1,0,0,0,0,0,
+ 4,3,2,0,0,0,0,0, 4,3,2,1,0,0,0,0, 4,3,2,1,1,0,0,0, 4,3,2,2,1,0,0,0, 4,3,3,2,1,0,0,0, 4,4,3,2,1,0,0,0, 5,4,3,2,1,0,0,0, 6,4,3,2,1,0,0,0,
+ 6,5,3,2,1,0,0,0, 6,5,4,2,1,0,0,0, 6,5,4,3,1,0,0,0, 6,5,4,3,2,0,0,0, 6,5,4,3,2,1,0,0, 6,5,4,3,2,1,1,0, 6,5,4,3,2,2,1,0, 6,5,4,3,3,2,1,0,
+ 6,5,4,4,3,2,1,0, 6,5,5,4,3,2,1,0, 6,6,5,4,3,2,1,0, 7,6,5,4,3,2,1,0, 8,6,5,4,3,2,1,0, 8,7,5,4,3,2,1,0, 8,7,6,4,3,2,1,0, 8,7,6,5,3,2,1,0,
+ 8,7,6,5,4,2,1,0, 8,7,6,5,4,3,1,0, 8,7,6,5,4,3,2,0, 8,7,6,5,4,3,2,1, 8,7,6,5,4,3,2,2, 8,7,6,5,4,3,3,2, 8,7,6,5,4,4,3,2, 8,7,6,5,5,4,3,2,
+ 8,7,6,6,5,4,3,2, 8,7,7,6,5,4,3,2, 8,8,7,6,5,4,3,2, 8,8,8,6,5,4,3,2, 8,8,8,7,5,4,3,2, 8,8,8,7,6,4,3,2, 8,8,8,7,6,5,3,2, 8,8,8,7,6,5,4,2,
+ 8,8,8,7,6,5,4,3, 8,8,8,7,6,5,4,4, 8,8,8,7,6,5,5,4, 8,8,8,7,6,6,5,4, 8,8,8,7,7,6,5,4, 8,8,8,8,7,6,5,4, 8,8,8,8,8,6,5,4, 8,8,8,8,8,7,5,4,
+ 8,8,8,8,8,7,6,4, 8,8,8,8,8,7,6,5, 8,8,8,8,8,7,6,6, 8,8,8,8,8,7,7,6, 8,8,8,8,8,8,7,6, 8,8,8,8,8,8,8,6, 8,8,8,8,8,8,8,7, 8,8,8,8,8,8,8,8,
+};
+
+static const uint8 s_idct_col_table[] = { 1, 1, 2, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 };
+
+void idct(const jpgd_block_t* pSrc_ptr, uint8* pDst_ptr, int block_max_zag)
+{
+ JPGD_ASSERT(block_max_zag >= 1);
+ JPGD_ASSERT(block_max_zag <= 64);
+
+ if (block_max_zag <= 1)
+ {
+ int k = ((pSrc_ptr[0] + 4) >> 3) + 128;
+ k = CLAMP(k);
+ k = k | (k<<8);
+ k = k | (k<<16);
+
+ for (int i = 8; i > 0; i--)
+ {
+ *(int*)&pDst_ptr[0] = k;
+ *(int*)&pDst_ptr[4] = k;
+ pDst_ptr += 8;
+ }
+ return;
+ }
+
+ int temp[64];
+
+ const jpgd_block_t* pSrc = pSrc_ptr;
+ int* pTemp = temp;
+
+ const uint8* pRow_tab = &s_idct_row_table[(block_max_zag - 1) * 8];
+ int i;
+ for (i = 8; i > 0; i--, pRow_tab++)
+ {
+ switch (*pRow_tab)
+ {
+ case 0: Row<0>::idct(pTemp, pSrc); break;
+ case 1: Row<1>::idct(pTemp, pSrc); break;
+ case 2: Row<2>::idct(pTemp, pSrc); break;
+ case 3: Row<3>::idct(pTemp, pSrc); break;
+ case 4: Row<4>::idct(pTemp, pSrc); break;
+ case 5: Row<5>::idct(pTemp, pSrc); break;
+ case 6: Row<6>::idct(pTemp, pSrc); break;
+ case 7: Row<7>::idct(pTemp, pSrc); break;
+ case 8: Row<8>::idct(pTemp, pSrc); break;
+ }
+
+ pSrc += 8;
+ pTemp += 8;
+ }
+
+ pTemp = temp;
+
+ const int nonzero_rows = s_idct_col_table[block_max_zag - 1];
+ for (i = 8; i > 0; i--)
+ {
+ switch (nonzero_rows)
+ {
+ case 1: Col<1>::idct(pDst_ptr, pTemp); break;
+ case 2: Col<2>::idct(pDst_ptr, pTemp); break;
+ case 3: Col<3>::idct(pDst_ptr, pTemp); break;
+ case 4: Col<4>::idct(pDst_ptr, pTemp); break;
+ case 5: Col<5>::idct(pDst_ptr, pTemp); break;
+ case 6: Col<6>::idct(pDst_ptr, pTemp); break;
+ case 7: Col<7>::idct(pDst_ptr, pTemp); break;
+ case 8: Col<8>::idct(pDst_ptr, pTemp); break;
+ }
+
+ pTemp++;
+ pDst_ptr++;
+ }
+}
+
+void idct_4x4(const jpgd_block_t* pSrc_ptr, uint8* pDst_ptr)
+{
+ int temp[64];
+ int* pTemp = temp;
+ const jpgd_block_t* pSrc = pSrc_ptr;
+
+ for (int i = 4; i > 0; i--)
+ {
+ Row<4>::idct(pTemp, pSrc);
+ pSrc += 8;
+ pTemp += 8;
+ }
+
+ pTemp = temp;
+ for (int i = 8; i > 0; i--)
+ {
+ Col<4>::idct(pDst_ptr, pTemp);
+ pTemp++;
+ pDst_ptr++;
+ }
+}
+
+// Retrieve one character from the input stream.
+inline uint jpeg_decoder::get_char()
+{
+ // Any bytes remaining in buffer?
+ if (!m_in_buf_left)
+ {
+ // Try to get more bytes.
+ prep_in_buffer();
+ // Still nothing to get?
+ if (!m_in_buf_left)
+ {
+ // Pad the end of the stream with 0xFF 0xD9 (EOI marker)
+ int t = m_tem_flag;
+ m_tem_flag ^= 1;
+ if (t)
+ return 0xD9;
+ else
+ return 0xFF;
+ }
+ }
+
+ uint c = *m_pIn_buf_ofs++;
+ m_in_buf_left--;
+
+ return c;
+}
+
+// Same as previous method, except can indicate if the character is a pad character or not.
+inline uint jpeg_decoder::get_char(bool *pPadding_flag)
+{
+ if (!m_in_buf_left)
+ {
+ prep_in_buffer();
+ if (!m_in_buf_left)
+ {
+ *pPadding_flag = true;
+ int t = m_tem_flag;
+ m_tem_flag ^= 1;
+ if (t)
+ return 0xD9;
+ else
+ return 0xFF;
+ }
+ }
+
+ *pPadding_flag = false;
+
+ uint c = *m_pIn_buf_ofs++;
+ m_in_buf_left--;
+
+ return c;
+}
+
+// Inserts a previously retrieved character back into the input buffer.
+inline void jpeg_decoder::stuff_char(uint8 q)
+{
+ *(--m_pIn_buf_ofs) = q;
+ m_in_buf_left++;
+}
+
+// Retrieves one character from the input stream, but does not read past markers. Will continue to return 0xFF when a marker is encountered.
+inline uint8 jpeg_decoder::get_octet()
+{
+ bool padding_flag;
+ int c = get_char(&padding_flag);
+
+ if (c == 0xFF)
+ {
+ if (padding_flag)
+ return 0xFF;
+
+ c = get_char(&padding_flag);
+ if (padding_flag)
+ {
+ stuff_char(0xFF);
+ return 0xFF;
+ }
+
+ if (c == 0x00)
+ return 0xFF;
+ else
+ {
+ stuff_char(static_cast<uint8>(c));
+ stuff_char(0xFF);
+ return 0xFF;
+ }
+ }
+
+ return static_cast<uint8>(c);
+}
+
+// Retrieves a variable number of bits from the input stream. Does not recognize markers.
+inline uint jpeg_decoder::get_bits(int num_bits)
+{
+ if (!num_bits)
+ return 0;
+
+ uint i = m_bit_buf >> (32 - num_bits);
+
+ if ((m_bits_left -= num_bits) <= 0)
+ {
+ m_bit_buf <<= (num_bits += m_bits_left);
+
+ uint c1 = get_char();
+ uint c2 = get_char();
+ m_bit_buf = (m_bit_buf & 0xFFFF0000) | (c1 << 8) | c2;
+
+ m_bit_buf <<= -m_bits_left;
+
+ m_bits_left += 16;
+
+ JPGD_ASSERT(m_bits_left >= 0);
+ }
+ else
+ m_bit_buf <<= num_bits;
+
+ return i;
+}
+
+// Retrieves a variable number of bits from the input stream. Markers will not be read into the input bit buffer. Instead, an infinite number of all 1's will be returned when a marker is encountered.
+inline uint jpeg_decoder::get_bits_no_markers(int num_bits)
+{
+ if (!num_bits)
+ return 0;
+
+ uint i = m_bit_buf >> (32 - num_bits);
+
+ if ((m_bits_left -= num_bits) <= 0)
+ {
+ m_bit_buf <<= (num_bits += m_bits_left);
+
+ if ((m_in_buf_left < 2) || (m_pIn_buf_ofs[0] == 0xFF) || (m_pIn_buf_ofs[1] == 0xFF))
+ {
+ uint c1 = get_octet();
+ uint c2 = get_octet();
+ m_bit_buf |= (c1 << 8) | c2;
+ }
+ else
+ {
+ m_bit_buf |= ((uint)m_pIn_buf_ofs[0] << 8) | m_pIn_buf_ofs[1];
+ m_in_buf_left -= 2;
+ m_pIn_buf_ofs += 2;
+ }
+
+ m_bit_buf <<= -m_bits_left;
+
+ m_bits_left += 16;
+
+ JPGD_ASSERT(m_bits_left >= 0);
+ }
+ else
+ m_bit_buf <<= num_bits;
+
+ return i;
+}
+
+// Decodes a Huffman encoded symbol.
+inline int jpeg_decoder::huff_decode(huff_tables *pH)
+{
+ int symbol;
+
+ // Check first 8-bits: do we have a complete symbol?
+ if ((symbol = pH->look_up[m_bit_buf >> 24]) < 0)
+ {
+ // Decode more bits, use a tree traversal to find symbol.
+ int ofs = 23;
+ do
+ {
+ symbol = pH->tree[-(int)(symbol + ((m_bit_buf >> ofs) & 1))];
+ ofs--;
+ } while (symbol < 0);
+
+ get_bits_no_markers(8 + (23 - ofs));
+ }
+ else
+ get_bits_no_markers(pH->code_size[symbol]);
+
+ return symbol;
+}
+
+// Decodes a Huffman encoded symbol.
+inline int jpeg_decoder::huff_decode(huff_tables *pH, int& extra_bits)
+{
+ int symbol;
+
+ // Check first 8-bits: do we have a complete symbol?
+ if ((symbol = pH->look_up2[m_bit_buf >> 24]) < 0)
+ {
+ // Use a tree traversal to find symbol.
+ int ofs = 23;
+ do
+ {
+ symbol = pH->tree[-(int)(symbol + ((m_bit_buf >> ofs) & 1))];
+ ofs--;
+ } while (symbol < 0);
+
+ get_bits_no_markers(8 + (23 - ofs));
+
+ extra_bits = get_bits_no_markers(symbol & 0xF);
+ }
+ else
+ {
+ JPGD_ASSERT(((symbol >> 8) & 31) == pH->code_size[symbol & 255] + ((symbol & 0x8000) ? (symbol & 15) : 0));
+
+ if (symbol & 0x8000)
+ {
+ get_bits_no_markers((symbol >> 8) & 31);
+ extra_bits = symbol >> 16;
+ }
+ else
+ {
+ int code_size = (symbol >> 8) & 31;
+ int num_extra_bits = symbol & 0xF;
+ int bits = code_size + num_extra_bits;
+ if (bits <= (m_bits_left + 16))
+ extra_bits = get_bits_no_markers(bits) & ((1 << num_extra_bits) - 1);
+ else
+ {
+ get_bits_no_markers(code_size);
+ extra_bits = get_bits_no_markers(num_extra_bits);
+ }
+ }
+
+ symbol &= 0xFF;
+ }
+
+ return symbol;
+}
+
+// Tables and macro used to fully decode the DPCM differences.
+static const int s_extend_test[16] = { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
+static const int s_extend_offset[16] = { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+static const int s_extend_mask[] = { 0, (1<<0), (1<<1), (1<<2), (1<<3), (1<<4), (1<<5), (1<<6), (1<<7), (1<<8), (1<<9), (1<<10), (1<<11), (1<<12), (1<<13), (1<<14), (1<<15), (1<<16) };
+// The logical AND's in this macro are to shut up static code analysis (aren't really necessary - couldn't find another way to do this)
+#define JPGD_HUFF_EXTEND(x, s) (((x) < s_extend_test[s & 15]) ? ((x) + s_extend_offset[s & 15]) : (x))
+
+// Clamps a value between 0-255.
+inline uint8 jpeg_decoder::clamp(int i)
+{
+ if (static_cast<uint>(i) > 255)
+ i = (((~i) >> 31) & 0xFF);
+
+ return static_cast<uint8>(i);
+}
+
+namespace DCT_Upsample
+{
+ struct Matrix44
+ {
+ typedef int Element_Type;
+ enum { NUM_ROWS = 4, NUM_COLS = 4 };
+
+ Element_Type v[NUM_ROWS][NUM_COLS];
+
+ inline int rows() const { return NUM_ROWS; }
+ inline int cols() const { return NUM_COLS; }
+
+ inline const Element_Type & at(int r, int c) const { return v[r][c]; }
+ inline Element_Type & at(int r, int c) { return v[r][c]; }
+
+ inline Matrix44() { }
+
+ inline Matrix44& operator += (const Matrix44& a)
+ {
+ for (int r = 0; r < NUM_ROWS; r++)
+ {
+ at(r, 0) += a.at(r, 0);
+ at(r, 1) += a.at(r, 1);
+ at(r, 2) += a.at(r, 2);
+ at(r, 3) += a.at(r, 3);
+ }
+ return *this;
+ }
+
+ inline Matrix44& operator -= (const Matrix44& a)
+ {
+ for (int r = 0; r < NUM_ROWS; r++)
+ {
+ at(r, 0) -= a.at(r, 0);
+ at(r, 1) -= a.at(r, 1);
+ at(r, 2) -= a.at(r, 2);
+ at(r, 3) -= a.at(r, 3);
+ }
+ return *this;
+ }
+
+ friend inline Matrix44 operator + (const Matrix44& a, const Matrix44& b)
+ {
+ Matrix44 ret;
+ for (int r = 0; r < NUM_ROWS; r++)
+ {
+ ret.at(r, 0) = a.at(r, 0) + b.at(r, 0);
+ ret.at(r, 1) = a.at(r, 1) + b.at(r, 1);
+ ret.at(r, 2) = a.at(r, 2) + b.at(r, 2);
+ ret.at(r, 3) = a.at(r, 3) + b.at(r, 3);
+ }
+ return ret;
+ }
+
+ friend inline Matrix44 operator - (const Matrix44& a, const Matrix44& b)
+ {
+ Matrix44 ret;
+ for (int r = 0; r < NUM_ROWS; r++)
+ {
+ ret.at(r, 0) = a.at(r, 0) - b.at(r, 0);
+ ret.at(r, 1) = a.at(r, 1) - b.at(r, 1);
+ ret.at(r, 2) = a.at(r, 2) - b.at(r, 2);
+ ret.at(r, 3) = a.at(r, 3) - b.at(r, 3);
+ }
+ return ret;
+ }
+
+ static inline void add_and_store(jpgd_block_t* pDst, const Matrix44& a, const Matrix44& b)
+ {
+ for (int r = 0; r < 4; r++)
+ {
+ pDst[0*8 + r] = static_cast<jpgd_block_t>(a.at(r, 0) + b.at(r, 0));
+ pDst[1*8 + r] = static_cast<jpgd_block_t>(a.at(r, 1) + b.at(r, 1));
+ pDst[2*8 + r] = static_cast<jpgd_block_t>(a.at(r, 2) + b.at(r, 2));
+ pDst[3*8 + r] = static_cast<jpgd_block_t>(a.at(r, 3) + b.at(r, 3));
+ }
+ }
+
+ static inline void sub_and_store(jpgd_block_t* pDst, const Matrix44& a, const Matrix44& b)
+ {
+ for (int r = 0; r < 4; r++)
+ {
+ pDst[0*8 + r] = static_cast<jpgd_block_t>(a.at(r, 0) - b.at(r, 0));
+ pDst[1*8 + r] = static_cast<jpgd_block_t>(a.at(r, 1) - b.at(r, 1));
+ pDst[2*8 + r] = static_cast<jpgd_block_t>(a.at(r, 2) - b.at(r, 2));
+ pDst[3*8 + r] = static_cast<jpgd_block_t>(a.at(r, 3) - b.at(r, 3));
+ }
+ }
+ };
+
+ const int FRACT_BITS = 10;
+ const int SCALE = 1 << FRACT_BITS;
+
+ typedef int Temp_Type;
+ #define D(i) (((i) + (SCALE >> 1)) >> FRACT_BITS)
+ #define F(i) ((int)((i) * SCALE + .5f))
+
+ // Any decent C++ compiler will optimize this at compile time to a 0, or an array access.
+ #define AT(c, r) ((((c)>=NUM_COLS)||((r)>=NUM_ROWS)) ? 0 : pSrc[(c)+(r)*8])
+
+ // NUM_ROWS/NUM_COLS = # of non-zero rows/cols in input matrix
+ template<int NUM_ROWS, int NUM_COLS>
+ struct P_Q
+ {
+ static void calc(Matrix44& P, Matrix44& Q, const jpgd_block_t* pSrc)
+ {
+ // 4x8 = 4x8 times 8x8, matrix 0 is constant
+ const Temp_Type X000 = AT(0, 0);
+ const Temp_Type X001 = AT(0, 1);
+ const Temp_Type X002 = AT(0, 2);
+ const Temp_Type X003 = AT(0, 3);
+ const Temp_Type X004 = AT(0, 4);
+ const Temp_Type X005 = AT(0, 5);
+ const Temp_Type X006 = AT(0, 6);
+ const Temp_Type X007 = AT(0, 7);
+ const Temp_Type X010 = D(F(0.415735f) * AT(1, 0) + F(0.791065f) * AT(3, 0) + F(-0.352443f) * AT(5, 0) + F(0.277785f) * AT(7, 0));
+ const Temp_Type X011 = D(F(0.415735f) * AT(1, 1) + F(0.791065f) * AT(3, 1) + F(-0.352443f) * AT(5, 1) + F(0.277785f) * AT(7, 1));
+ const Temp_Type X012 = D(F(0.415735f) * AT(1, 2) + F(0.791065f) * AT(3, 2) + F(-0.352443f) * AT(5, 2) + F(0.277785f) * AT(7, 2));
+ const Temp_Type X013 = D(F(0.415735f) * AT(1, 3) + F(0.791065f) * AT(3, 3) + F(-0.352443f) * AT(5, 3) + F(0.277785f) * AT(7, 3));
+ const Temp_Type X014 = D(F(0.415735f) * AT(1, 4) + F(0.791065f) * AT(3, 4) + F(-0.352443f) * AT(5, 4) + F(0.277785f) * AT(7, 4));
+ const Temp_Type X015 = D(F(0.415735f) * AT(1, 5) + F(0.791065f) * AT(3, 5) + F(-0.352443f) * AT(5, 5) + F(0.277785f) * AT(7, 5));
+ const Temp_Type X016 = D(F(0.415735f) * AT(1, 6) + F(0.791065f) * AT(3, 6) + F(-0.352443f) * AT(5, 6) + F(0.277785f) * AT(7, 6));
+ const Temp_Type X017 = D(F(0.415735f) * AT(1, 7) + F(0.791065f) * AT(3, 7) + F(-0.352443f) * AT(5, 7) + F(0.277785f) * AT(7, 7));
+ const Temp_Type X020 = AT(4, 0);
+ const Temp_Type X021 = AT(4, 1);
+ const Temp_Type X022 = AT(4, 2);
+ const Temp_Type X023 = AT(4, 3);
+ const Temp_Type X024 = AT(4, 4);
+ const Temp_Type X025 = AT(4, 5);
+ const Temp_Type X026 = AT(4, 6);
+ const Temp_Type X027 = AT(4, 7);
+ const Temp_Type X030 = D(F(0.022887f) * AT(1, 0) + F(-0.097545f) * AT(3, 0) + F(0.490393f) * AT(5, 0) + F(0.865723f) * AT(7, 0));
+ const Temp_Type X031 = D(F(0.022887f) * AT(1, 1) + F(-0.097545f) * AT(3, 1) + F(0.490393f) * AT(5, 1) + F(0.865723f) * AT(7, 1));
+ const Temp_Type X032 = D(F(0.022887f) * AT(1, 2) + F(-0.097545f) * AT(3, 2) + F(0.490393f) * AT(5, 2) + F(0.865723f) * AT(7, 2));
+ const Temp_Type X033 = D(F(0.022887f) * AT(1, 3) + F(-0.097545f) * AT(3, 3) + F(0.490393f) * AT(5, 3) + F(0.865723f) * AT(7, 3));
+ const Temp_Type X034 = D(F(0.022887f) * AT(1, 4) + F(-0.097545f) * AT(3, 4) + F(0.490393f) * AT(5, 4) + F(0.865723f) * AT(7, 4));
+ const Temp_Type X035 = D(F(0.022887f) * AT(1, 5) + F(-0.097545f) * AT(3, 5) + F(0.490393f) * AT(5, 5) + F(0.865723f) * AT(7, 5));
+ const Temp_Type X036 = D(F(0.022887f) * AT(1, 6) + F(-0.097545f) * AT(3, 6) + F(0.490393f) * AT(5, 6) + F(0.865723f) * AT(7, 6));
+ const Temp_Type X037 = D(F(0.022887f) * AT(1, 7) + F(-0.097545f) * AT(3, 7) + F(0.490393f) * AT(5, 7) + F(0.865723f) * AT(7, 7));
+
+ // 4x4 = 4x8 times 8x4, matrix 1 is constant
+ P.at(0, 0) = X000;
+ P.at(0, 1) = D(X001 * F(0.415735f) + X003 * F(0.791065f) + X005 * F(-0.352443f) + X007 * F(0.277785f));
+ P.at(0, 2) = X004;
+ P.at(0, 3) = D(X001 * F(0.022887f) + X003 * F(-0.097545f) + X005 * F(0.490393f) + X007 * F(0.865723f));
+ P.at(1, 0) = X010;
+ P.at(1, 1) = D(X011 * F(0.415735f) + X013 * F(0.791065f) + X015 * F(-0.352443f) + X017 * F(0.277785f));
+ P.at(1, 2) = X014;
+ P.at(1, 3) = D(X011 * F(0.022887f) + X013 * F(-0.097545f) + X015 * F(0.490393f) + X017 * F(0.865723f));
+ P.at(2, 0) = X020;
+ P.at(2, 1) = D(X021 * F(0.415735f) + X023 * F(0.791065f) + X025 * F(-0.352443f) + X027 * F(0.277785f));
+ P.at(2, 2) = X024;
+ P.at(2, 3) = D(X021 * F(0.022887f) + X023 * F(-0.097545f) + X025 * F(0.490393f) + X027 * F(0.865723f));
+ P.at(3, 0) = X030;
+ P.at(3, 1) = D(X031 * F(0.415735f) + X033 * F(0.791065f) + X035 * F(-0.352443f) + X037 * F(0.277785f));
+ P.at(3, 2) = X034;
+ P.at(3, 3) = D(X031 * F(0.022887f) + X033 * F(-0.097545f) + X035 * F(0.490393f) + X037 * F(0.865723f));
+ // 40 muls 24 adds
+
+ // 4x4 = 4x8 times 8x4, matrix 1 is constant
+ Q.at(0, 0) = D(X001 * F(0.906127f) + X003 * F(-0.318190f) + X005 * F(0.212608f) + X007 * F(-0.180240f));
+ Q.at(0, 1) = X002;
+ Q.at(0, 2) = D(X001 * F(-0.074658f) + X003 * F(0.513280f) + X005 * F(0.768178f) + X007 * F(-0.375330f));
+ Q.at(0, 3) = X006;
+ Q.at(1, 0) = D(X011 * F(0.906127f) + X013 * F(-0.318190f) + X015 * F(0.212608f) + X017 * F(-0.180240f));
+ Q.at(1, 1) = X012;
+ Q.at(1, 2) = D(X011 * F(-0.074658f) + X013 * F(0.513280f) + X015 * F(0.768178f) + X017 * F(-0.375330f));
+ Q.at(1, 3) = X016;
+ Q.at(2, 0) = D(X021 * F(0.906127f) + X023 * F(-0.318190f) + X025 * F(0.212608f) + X027 * F(-0.180240f));
+ Q.at(2, 1) = X022;
+ Q.at(2, 2) = D(X021 * F(-0.074658f) + X023 * F(0.513280f) + X025 * F(0.768178f) + X027 * F(-0.375330f));
+ Q.at(2, 3) = X026;
+ Q.at(3, 0) = D(X031 * F(0.906127f) + X033 * F(-0.318190f) + X035 * F(0.212608f) + X037 * F(-0.180240f));
+ Q.at(3, 1) = X032;
+ Q.at(3, 2) = D(X031 * F(-0.074658f) + X033 * F(0.513280f) + X035 * F(0.768178f) + X037 * F(-0.375330f));
+ Q.at(3, 3) = X036;
+ // 40 muls 24 adds
+ }
+ };
+
+ template<int NUM_ROWS, int NUM_COLS>
+ struct R_S
+ {
+ static void calc(Matrix44& R, Matrix44& S, const jpgd_block_t* pSrc)
+ {
+ // 4x8 = 4x8 times 8x8, matrix 0 is constant
+ const Temp_Type X100 = D(F(0.906127f) * AT(1, 0) + F(-0.318190f) * AT(3, 0) + F(0.212608f) * AT(5, 0) + F(-0.180240f) * AT(7, 0));
+ const Temp_Type X101 = D(F(0.906127f) * AT(1, 1) + F(-0.318190f) * AT(3, 1) + F(0.212608f) * AT(5, 1) + F(-0.180240f) * AT(7, 1));
+ const Temp_Type X102 = D(F(0.906127f) * AT(1, 2) + F(-0.318190f) * AT(3, 2) + F(0.212608f) * AT(5, 2) + F(-0.180240f) * AT(7, 2));
+ const Temp_Type X103 = D(F(0.906127f) * AT(1, 3) + F(-0.318190f) * AT(3, 3) + F(0.212608f) * AT(5, 3) + F(-0.180240f) * AT(7, 3));
+ const Temp_Type X104 = D(F(0.906127f) * AT(1, 4) + F(-0.318190f) * AT(3, 4) + F(0.212608f) * AT(5, 4) + F(-0.180240f) * AT(7, 4));
+ const Temp_Type X105 = D(F(0.906127f) * AT(1, 5) + F(-0.318190f) * AT(3, 5) + F(0.212608f) * AT(5, 5) + F(-0.180240f) * AT(7, 5));
+ const Temp_Type X106 = D(F(0.906127f) * AT(1, 6) + F(-0.318190f) * AT(3, 6) + F(0.212608f) * AT(5, 6) + F(-0.180240f) * AT(7, 6));
+ const Temp_Type X107 = D(F(0.906127f) * AT(1, 7) + F(-0.318190f) * AT(3, 7) + F(0.212608f) * AT(5, 7) + F(-0.180240f) * AT(7, 7));
+ const Temp_Type X110 = AT(2, 0);
+ const Temp_Type X111 = AT(2, 1);
+ const Temp_Type X112 = AT(2, 2);
+ const Temp_Type X113 = AT(2, 3);
+ const Temp_Type X114 = AT(2, 4);
+ const Temp_Type X115 = AT(2, 5);
+ const Temp_Type X116 = AT(2, 6);
+ const Temp_Type X117 = AT(2, 7);
+ const Temp_Type X120 = D(F(-0.074658f) * AT(1, 0) + F(0.513280f) * AT(3, 0) + F(0.768178f) * AT(5, 0) + F(-0.375330f) * AT(7, 0));
+ const Temp_Type X121 = D(F(-0.074658f) * AT(1, 1) + F(0.513280f) * AT(3, 1) + F(0.768178f) * AT(5, 1) + F(-0.375330f) * AT(7, 1));
+ const Temp_Type X122 = D(F(-0.074658f) * AT(1, 2) + F(0.513280f) * AT(3, 2) + F(0.768178f) * AT(5, 2) + F(-0.375330f) * AT(7, 2));
+ const Temp_Type X123 = D(F(-0.074658f) * AT(1, 3) + F(0.513280f) * AT(3, 3) + F(0.768178f) * AT(5, 3) + F(-0.375330f) * AT(7, 3));
+ const Temp_Type X124 = D(F(-0.074658f) * AT(1, 4) + F(0.513280f) * AT(3, 4) + F(0.768178f) * AT(5, 4) + F(-0.375330f) * AT(7, 4));
+ const Temp_Type X125 = D(F(-0.074658f) * AT(1, 5) + F(0.513280f) * AT(3, 5) + F(0.768178f) * AT(5, 5) + F(-0.375330f) * AT(7, 5));
+ const Temp_Type X126 = D(F(-0.074658f) * AT(1, 6) + F(0.513280f) * AT(3, 6) + F(0.768178f) * AT(5, 6) + F(-0.375330f) * AT(7, 6));
+ const Temp_Type X127 = D(F(-0.074658f) * AT(1, 7) + F(0.513280f) * AT(3, 7) + F(0.768178f) * AT(5, 7) + F(-0.375330f) * AT(7, 7));
+ const Temp_Type X130 = AT(6, 0);
+ const Temp_Type X131 = AT(6, 1);
+ const Temp_Type X132 = AT(6, 2);
+ const Temp_Type X133 = AT(6, 3);
+ const Temp_Type X134 = AT(6, 4);
+ const Temp_Type X135 = AT(6, 5);
+ const Temp_Type X136 = AT(6, 6);
+ const Temp_Type X137 = AT(6, 7);
+ // 80 muls 48 adds
+
+ // 4x4 = 4x8 times 8x4, matrix 1 is constant
+ R.at(0, 0) = X100;
+ R.at(0, 1) = D(X101 * F(0.415735f) + X103 * F(0.791065f) + X105 * F(-0.352443f) + X107 * F(0.277785f));
+ R.at(0, 2) = X104;
+ R.at(0, 3) = D(X101 * F(0.022887f) + X103 * F(-0.097545f) + X105 * F(0.490393f) + X107 * F(0.865723f));
+ R.at(1, 0) = X110;
+ R.at(1, 1) = D(X111 * F(0.415735f) + X113 * F(0.791065f) + X115 * F(-0.352443f) + X117 * F(0.277785f));
+ R.at(1, 2) = X114;
+ R.at(1, 3) = D(X111 * F(0.022887f) + X113 * F(-0.097545f) + X115 * F(0.490393f) + X117 * F(0.865723f));
+ R.at(2, 0) = X120;
+ R.at(2, 1) = D(X121 * F(0.415735f) + X123 * F(0.791065f) + X125 * F(-0.352443f) + X127 * F(0.277785f));
+ R.at(2, 2) = X124;
+ R.at(2, 3) = D(X121 * F(0.022887f) + X123 * F(-0.097545f) + X125 * F(0.490393f) + X127 * F(0.865723f));
+ R.at(3, 0) = X130;
+ R.at(3, 1) = D(X131 * F(0.415735f) + X133 * F(0.791065f) + X135 * F(-0.352443f) + X137 * F(0.277785f));
+ R.at(3, 2) = X134;
+ R.at(3, 3) = D(X131 * F(0.022887f) + X133 * F(-0.097545f) + X135 * F(0.490393f) + X137 * F(0.865723f));
+ // 40 muls 24 adds
+ // 4x4 = 4x8 times 8x4, matrix 1 is constant
+ S.at(0, 0) = D(X101 * F(0.906127f) + X103 * F(-0.318190f) + X105 * F(0.212608f) + X107 * F(-0.180240f));
+ S.at(0, 1) = X102;
+ S.at(0, 2) = D(X101 * F(-0.074658f) + X103 * F(0.513280f) + X105 * F(0.768178f) + X107 * F(-0.375330f));
+ S.at(0, 3) = X106;
+ S.at(1, 0) = D(X111 * F(0.906127f) + X113 * F(-0.318190f) + X115 * F(0.212608f) + X117 * F(-0.180240f));
+ S.at(1, 1) = X112;
+ S.at(1, 2) = D(X111 * F(-0.074658f) + X113 * F(0.513280f) + X115 * F(0.768178f) + X117 * F(-0.375330f));
+ S.at(1, 3) = X116;
+ S.at(2, 0) = D(X121 * F(0.906127f) + X123 * F(-0.318190f) + X125 * F(0.212608f) + X127 * F(-0.180240f));
+ S.at(2, 1) = X122;
+ S.at(2, 2) = D(X121 * F(-0.074658f) + X123 * F(0.513280f) + X125 * F(0.768178f) + X127 * F(-0.375330f));
+ S.at(2, 3) = X126;
+ S.at(3, 0) = D(X131 * F(0.906127f) + X133 * F(-0.318190f) + X135 * F(0.212608f) + X137 * F(-0.180240f));
+ S.at(3, 1) = X132;
+ S.at(3, 2) = D(X131 * F(-0.074658f) + X133 * F(0.513280f) + X135 * F(0.768178f) + X137 * F(-0.375330f));
+ S.at(3, 3) = X136;
+ // 40 muls 24 adds
+ }
+ };
+} // end namespace DCT_Upsample
+
+// Unconditionally frees all allocated m_blocks.
+void jpeg_decoder::free_all_blocks()
+{
+ m_pStream = NULL;
+ for (mem_block *b = m_pMem_blocks; b; )
+ {
+ mem_block *n = b->m_pNext;
+ jpgd_free(b);
+ b = n;
+ }
+ m_pMem_blocks = NULL;
+}
+
+// This method handles all errors. It will never return.
+// It could easily be changed to use C++ exceptions.
+JPGD_NORETURN void jpeg_decoder::stop_decoding(jpgd_status status)
+{
+ m_error_code = status;
+ free_all_blocks();
+ longjmp(m_jmp_state, status);
+}
+
+void *jpeg_decoder::alloc(size_t nSize, bool zero)
+{
+ nSize = (JPGD_MAX(nSize, 1) + 3) & ~3;
+ char *rv = NULL;
+ for (mem_block *b = m_pMem_blocks; b; b = b->m_pNext)
+ {
+ if ((b->m_used_count + nSize) <= b->m_size)
+ {
+ rv = b->m_data + b->m_used_count;
+ b->m_used_count += nSize;
+ break;
+ }
+ }
+ if (!rv)
+ {
+ int capacity = JPGD_MAX(32768 - 256, (nSize + 2047) & ~2047);
+ mem_block *b = (mem_block*)jpgd_malloc(sizeof(mem_block) + capacity);
+ if (!b) { stop_decoding(JPGD_NOTENOUGHMEM); }
+ b->m_pNext = m_pMem_blocks; m_pMem_blocks = b;
+ b->m_used_count = nSize;
+ b->m_size = capacity;
+ rv = b->m_data;
+ }
+ if (zero) memset(rv, 0, nSize);
+ return rv;
+}
+
+void jpeg_decoder::word_clear(void *p, uint16 c, uint n)
+{
+ uint8 *pD = (uint8*)p;
+ const uint8 l = c & 0xFF, h = (c >> 8) & 0xFF;
+ while (n)
+ {
+ pD[0] = l; pD[1] = h; pD += 2;
+ n--;
+ }
+}
+
+// Refill the input buffer.
+// This method will sit in a loop until (A) the buffer is full or (B)
+// the stream's read() method reports and end of file condition.
+void jpeg_decoder::prep_in_buffer()
+{
+ m_in_buf_left = 0;
+ m_pIn_buf_ofs = m_in_buf;
+
+ if (m_eof_flag)
+ return;
+
+ do
+ {
+ int bytes_read = m_pStream->read(m_in_buf + m_in_buf_left, JPGD_IN_BUF_SIZE - m_in_buf_left, &m_eof_flag);
+ if (bytes_read == -1)
+ stop_decoding(JPGD_STREAM_READ);
+
+ m_in_buf_left += bytes_read;
+ } while ((m_in_buf_left < JPGD_IN_BUF_SIZE) && (!m_eof_flag));
+
+ m_total_bytes_read += m_in_buf_left;
+
+ // Pad the end of the block with M_EOI (prevents the decompressor from going off the rails if the stream is invalid).
+ // (This dates way back to when this decompressor was written in C/asm, and the all-asm Huffman decoder did some fancy things to increase perf.)
+ word_clear(m_pIn_buf_ofs + m_in_buf_left, 0xD9FF, 64);
+}
+
+// Read a Huffman code table.
+void jpeg_decoder::read_dht_marker()
+{
+ int i, index, count;
+ uint8 huff_num[17];
+ uint8 huff_val[256];
+
+ uint num_left = get_bits(16);
+
+ if (num_left < 2)
+ stop_decoding(JPGD_BAD_DHT_MARKER);
+
+ num_left -= 2;
+
+ while (num_left)
+ {
+ index = get_bits(8);
+
+ huff_num[0] = 0;
+
+ count = 0;
+
+ for (i = 1; i <= 16; i++)
+ {
+ huff_num[i] = static_cast<uint8>(get_bits(8));
+ count += huff_num[i];
+ }
+
+ if (count > 255)
+ stop_decoding(JPGD_BAD_DHT_COUNTS);
+
+ for (i = 0; i < count; i++)
+ huff_val[i] = static_cast<uint8>(get_bits(8));
+
+ i = 1 + 16 + count;
+
+ if (num_left < (uint)i)
+ stop_decoding(JPGD_BAD_DHT_MARKER);
+
+ num_left -= i;
+
+ if ((index & 0x10) > 0x10)
+ stop_decoding(JPGD_BAD_DHT_INDEX);
+
+ index = (index & 0x0F) + ((index & 0x10) >> 4) * (JPGD_MAX_HUFF_TABLES >> 1);
+
+ if (index >= JPGD_MAX_HUFF_TABLES)
+ stop_decoding(JPGD_BAD_DHT_INDEX);
+
+ if (!m_huff_num[index])
+ m_huff_num[index] = (uint8 *)alloc(17);
+
+ if (!m_huff_val[index])
+ m_huff_val[index] = (uint8 *)alloc(256);
+
+ m_huff_ac[index] = (index & 0x10) != 0;
+ memcpy(m_huff_num[index], huff_num, 17);
+ memcpy(m_huff_val[index], huff_val, 256);
+ }
+}
+
+// Read a quantization table.
+void jpeg_decoder::read_dqt_marker()
+{
+ int n, i, prec;
+ uint num_left;
+ uint temp;
+
+ num_left = get_bits(16);
+
+ if (num_left < 2)
+ stop_decoding(JPGD_BAD_DQT_MARKER);
+
+ num_left -= 2;
+
+ while (num_left)
+ {
+ n = get_bits(8);
+ prec = n >> 4;
+ n &= 0x0F;
+
+ if (n >= JPGD_MAX_QUANT_TABLES)
+ stop_decoding(JPGD_BAD_DQT_TABLE);
+
+ if (!m_quant[n])
+ m_quant[n] = (jpgd_quant_t *)alloc(64 * sizeof(jpgd_quant_t));
+
+ // read quantization entries, in zag order
+ for (i = 0; i < 64; i++)
+ {
+ temp = get_bits(8);
+
+ if (prec)
+ temp = (temp << 8) + get_bits(8);
+
+ m_quant[n][i] = static_cast<jpgd_quant_t>(temp);
+ }
+
+ i = 64 + 1;
+
+ if (prec)
+ i += 64;
+
+ if (num_left < (uint)i)
+ stop_decoding(JPGD_BAD_DQT_LENGTH);
+
+ num_left -= i;
+ }
+}
+
+// Read the start of frame (SOF) marker.
+void jpeg_decoder::read_sof_marker()
+{
+ int i;
+ uint num_left;
+
+ num_left = get_bits(16);
+
+ if (get_bits(8) != 8) /* precision: sorry, only 8-bit precision is supported right now */
+ stop_decoding(JPGD_BAD_PRECISION);
+
+ m_image_y_size = get_bits(16);
+
+ if ((m_image_y_size < 1) || (m_image_y_size > JPGD_MAX_HEIGHT))
+ stop_decoding(JPGD_BAD_HEIGHT);
+
+ m_image_x_size = get_bits(16);
+
+ if ((m_image_x_size < 1) || (m_image_x_size > JPGD_MAX_WIDTH))
+ stop_decoding(JPGD_BAD_WIDTH);
+
+ m_comps_in_frame = get_bits(8);
+
+ if (m_comps_in_frame > JPGD_MAX_COMPONENTS)
+ stop_decoding(JPGD_TOO_MANY_COMPONENTS);
+
+ if (num_left != (uint)(m_comps_in_frame * 3 + 8))
+ stop_decoding(JPGD_BAD_SOF_LENGTH);
+
+ for (i = 0; i < m_comps_in_frame; i++)
+ {
+ m_comp_ident[i] = get_bits(8);
+ m_comp_h_samp[i] = get_bits(4);
+ m_comp_v_samp[i] = get_bits(4);
+ m_comp_quant[i] = get_bits(8);
+ }
+}
+
+// Used to skip unrecognized markers.
+void jpeg_decoder::skip_variable_marker()
+{
+ uint num_left;
+
+ num_left = get_bits(16);
+
+ if (num_left < 2)
+ stop_decoding(JPGD_BAD_VARIABLE_MARKER);
+
+ num_left -= 2;
+
+ while (num_left)
+ {
+ get_bits(8);
+ num_left--;
+ }
+}
+
+// Read a define restart interval (DRI) marker.
+void jpeg_decoder::read_dri_marker()
+{
+ if (get_bits(16) != 4)
+ stop_decoding(JPGD_BAD_DRI_LENGTH);
+
+ m_restart_interval = get_bits(16);
+}
+
+// Read a start of scan (SOS) marker.
+void jpeg_decoder::read_sos_marker()
+{
+ uint num_left;
+ int i, ci, n, c, cc;
+
+ num_left = get_bits(16);
+
+ n = get_bits(8);
+
+ m_comps_in_scan = n;
+
+ num_left -= 3;
+
+ if ( (num_left != (uint)(n * 2 + 3)) || (n < 1) || (n > JPGD_MAX_COMPS_IN_SCAN) )
+ stop_decoding(JPGD_BAD_SOS_LENGTH);
+
+ for (i = 0; i < n; i++)
+ {
+ cc = get_bits(8);
+ c = get_bits(8);
+ num_left -= 2;
+
+ for (ci = 0; ci < m_comps_in_frame; ci++)
+ if (cc == m_comp_ident[ci])
+ break;
+
+ if (ci >= m_comps_in_frame)
+ stop_decoding(JPGD_BAD_SOS_COMP_ID);
+
+ m_comp_list[i] = ci;
+ m_comp_dc_tab[ci] = (c >> 4) & 15;
+ m_comp_ac_tab[ci] = (c & 15) + (JPGD_MAX_HUFF_TABLES >> 1);
+ }
+
+ m_spectral_start = get_bits(8);
+ m_spectral_end = get_bits(8);
+ m_successive_high = get_bits(4);
+ m_successive_low = get_bits(4);
+
+ if (!m_progressive_flag)
+ {
+ m_spectral_start = 0;
+ m_spectral_end = 63;
+ }
+
+ num_left -= 3;
+
+ while (num_left) /* read past whatever is num_left */
+ {
+ get_bits(8);
+ num_left--;
+ }
+}
+
+// Finds the next marker.
+int jpeg_decoder::next_marker()
+{
+ uint c, bytes;
+
+ bytes = 0;
+
+ do
+ {
+ do
+ {
+ bytes++;
+ c = get_bits(8);
+ } while (c != 0xFF);
+
+ do
+ {
+ c = get_bits(8);
+ } while (c == 0xFF);
+
+ } while (c == 0);
+
+ // If bytes > 0 here, there where extra bytes before the marker (not good).
+
+ return c;
+}
+
+// Process markers. Returns when an SOFx, SOI, EOI, or SOS marker is
+// encountered.
+int jpeg_decoder::process_markers()
+{
+ int c;
+
+ for ( ; ; )
+ {
+ c = next_marker();
+
+ switch (c)
+ {
+ case M_SOF0:
+ case M_SOF1:
+ case M_SOF2:
+ case M_SOF3:
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+// case M_JPG:
+ case M_SOF9:
+ case M_SOF10:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ case M_SOI:
+ case M_EOI:
+ case M_SOS:
+ {
+ return c;
+ }
+ case M_DHT:
+ {
+ read_dht_marker();
+ break;
+ }
+ // No arithmitic support - dumb patents!
+ case M_DAC:
+ {
+ stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT);
+ break;
+ }
+ case M_DQT:
+ {
+ read_dqt_marker();
+ break;
+ }
+ case M_DRI:
+ {
+ read_dri_marker();
+ break;
+ }
+ //case M_APP0: /* no need to read the JFIF marker */
+
+ case M_JPG:
+ case M_RST0: /* no parameters */
+ case M_RST1:
+ case M_RST2:
+ case M_RST3:
+ case M_RST4:
+ case M_RST5:
+ case M_RST6:
+ case M_RST7:
+ case M_TEM:
+ {
+ stop_decoding(JPGD_UNEXPECTED_MARKER);
+ break;
+ }
+ default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */
+ {
+ skip_variable_marker();
+ break;
+ }
+ }
+ }
+}
+
+// Finds the start of image (SOI) marker.
+// This code is rather defensive: it only checks the first 512 bytes to avoid
+// false positives.
+void jpeg_decoder::locate_soi_marker()
+{
+ uint lastchar, thischar;
+ uint bytesleft;
+
+ lastchar = get_bits(8);
+
+ thischar = get_bits(8);
+
+ /* ok if it's a normal JPEG file without a special header */
+
+ if ((lastchar == 0xFF) && (thischar == M_SOI))
+ return;
+
+ bytesleft = 4096; //512;
+
+ for ( ; ; )
+ {
+ if (--bytesleft == 0)
+ stop_decoding(JPGD_NOT_JPEG);
+
+ lastchar = thischar;
+
+ thischar = get_bits(8);
+
+ if (lastchar == 0xFF)
+ {
+ if (thischar == M_SOI)
+ break;
+ else if (thischar == M_EOI) // get_bits will keep returning M_EOI if we read past the end
+ stop_decoding(JPGD_NOT_JPEG);
+ }
+ }
+
+ // Check the next character after marker: if it's not 0xFF, it can't be the start of the next marker, so the file is bad.
+ thischar = (m_bit_buf >> 24) & 0xFF;
+
+ if (thischar != 0xFF)
+ stop_decoding(JPGD_NOT_JPEG);
+}
+
+// Find a start of frame (SOF) marker.
+void jpeg_decoder::locate_sof_marker()
+{
+ locate_soi_marker();
+
+ int c = process_markers();
+
+ switch (c)
+ {
+ case M_SOF2:
+ m_progressive_flag = JPGD_TRUE;
+ case M_SOF0: /* baseline DCT */
+ case M_SOF1: /* extended sequential DCT */
+ {
+ read_sof_marker();
+ break;
+ }
+ case M_SOF9: /* Arithmitic coding */
+ {
+ stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT);
+ break;
+ }
+ default:
+ {
+ stop_decoding(JPGD_UNSUPPORTED_MARKER);
+ break;
+ }
+ }
+}
+
+// Find a start of scan (SOS) marker.
+int jpeg_decoder::locate_sos_marker()
+{
+ int c;
+
+ c = process_markers();
+
+ if (c == M_EOI)
+ return JPGD_FALSE;
+ else if (c != M_SOS)
+ stop_decoding(JPGD_UNEXPECTED_MARKER);
+
+ read_sos_marker();
+
+ return JPGD_TRUE;
+}
+
+// Reset everything to default/uninitialized state.
+void jpeg_decoder::init(jpeg_decoder_stream *pStream)
+{
+ m_pMem_blocks = NULL;
+ m_error_code = JPGD_SUCCESS;
+ m_ready_flag = false;
+ m_image_x_size = m_image_y_size = 0;
+ m_pStream = pStream;
+ m_progressive_flag = JPGD_FALSE;
+
+ memset(m_huff_ac, 0, sizeof(m_huff_ac));
+ memset(m_huff_num, 0, sizeof(m_huff_num));
+ memset(m_huff_val, 0, sizeof(m_huff_val));
+ memset(m_quant, 0, sizeof(m_quant));
+
+ m_scan_type = 0;
+ m_comps_in_frame = 0;
+
+ memset(m_comp_h_samp, 0, sizeof(m_comp_h_samp));
+ memset(m_comp_v_samp, 0, sizeof(m_comp_v_samp));
+ memset(m_comp_quant, 0, sizeof(m_comp_quant));
+ memset(m_comp_ident, 0, sizeof(m_comp_ident));
+ memset(m_comp_h_blocks, 0, sizeof(m_comp_h_blocks));
+ memset(m_comp_v_blocks, 0, sizeof(m_comp_v_blocks));
+
+ m_comps_in_scan = 0;
+ memset(m_comp_list, 0, sizeof(m_comp_list));
+ memset(m_comp_dc_tab, 0, sizeof(m_comp_dc_tab));
+ memset(m_comp_ac_tab, 0, sizeof(m_comp_ac_tab));
+
+ m_spectral_start = 0;
+ m_spectral_end = 0;
+ m_successive_low = 0;
+ m_successive_high = 0;
+ m_max_mcu_x_size = 0;
+ m_max_mcu_y_size = 0;
+ m_blocks_per_mcu = 0;
+ m_max_blocks_per_row = 0;
+ m_mcus_per_row = 0;
+ m_mcus_per_col = 0;
+ m_expanded_blocks_per_component = 0;
+ m_expanded_blocks_per_mcu = 0;
+ m_expanded_blocks_per_row = 0;
+ m_freq_domain_chroma_upsample = false;
+
+ memset(m_mcu_org, 0, sizeof(m_mcu_org));
+
+ m_total_lines_left = 0;
+ m_mcu_lines_left = 0;
+ m_real_dest_bytes_per_scan_line = 0;
+ m_dest_bytes_per_scan_line = 0;
+ m_dest_bytes_per_pixel = 0;
+
+ memset(m_pHuff_tabs, 0, sizeof(m_pHuff_tabs));
+
+ memset(m_dc_coeffs, 0, sizeof(m_dc_coeffs));
+ memset(m_ac_coeffs, 0, sizeof(m_ac_coeffs));
+ memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu));
+
+ m_eob_run = 0;
+
+ memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu));
+
+ m_pIn_buf_ofs = m_in_buf;
+ m_in_buf_left = 0;
+ m_eof_flag = false;
+ m_tem_flag = 0;
+
+ memset(m_in_buf_pad_start, 0, sizeof(m_in_buf_pad_start));
+ memset(m_in_buf, 0, sizeof(m_in_buf));
+ memset(m_in_buf_pad_end, 0, sizeof(m_in_buf_pad_end));
+
+ m_restart_interval = 0;
+ m_restarts_left = 0;
+ m_next_restart_num = 0;
+
+ m_max_mcus_per_row = 0;
+ m_max_blocks_per_mcu = 0;
+ m_max_mcus_per_col = 0;
+
+ memset(m_last_dc_val, 0, sizeof(m_last_dc_val));
+ m_pMCU_coefficients = NULL;
+ m_pSample_buf = NULL;
+
+ m_total_bytes_read = 0;
+
+ m_pScan_line_0 = NULL;
+ m_pScan_line_1 = NULL;
+
+ // Ready the input buffer.
+ prep_in_buffer();
+
+ // Prime the bit buffer.
+ m_bits_left = 16;
+ m_bit_buf = 0;
+
+ get_bits(16);
+ get_bits(16);
+
+ for (int i = 0; i < JPGD_MAX_BLOCKS_PER_MCU; i++)
+ m_mcu_block_max_zag[i] = 64;
+}
+
+#define SCALEBITS 16
+#define ONE_HALF ((int) 1 << (SCALEBITS-1))
+#define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5f))
+
+// Create a few tables that allow us to quickly convert YCbCr to RGB.
+void jpeg_decoder::create_look_ups()
+{
+ for (int i = 0; i <= 255; i++)
+ {
+ int k = i - 128;
+ m_crr[i] = ( FIX(1.40200f) * k + ONE_HALF) >> SCALEBITS;
+ m_cbb[i] = ( FIX(1.77200f) * k + ONE_HALF) >> SCALEBITS;
+ m_crg[i] = (-FIX(0.71414f)) * k;
+ m_cbg[i] = (-FIX(0.34414f)) * k + ONE_HALF;
+ }
+}
+
+// This method throws back into the stream any bytes that where read
+// into the bit buffer during initial marker scanning.
+void jpeg_decoder::fix_in_buffer()
+{
+ // In case any 0xFF's where pulled into the buffer during marker scanning.
+ JPGD_ASSERT((m_bits_left & 7) == 0);
+
+ if (m_bits_left == 16)
+ stuff_char( (uint8)(m_bit_buf & 0xFF));
+
+ if (m_bits_left >= 8)
+ stuff_char( (uint8)((m_bit_buf >> 8) & 0xFF));
+
+ stuff_char((uint8)((m_bit_buf >> 16) & 0xFF));
+ stuff_char((uint8)((m_bit_buf >> 24) & 0xFF));
+
+ m_bits_left = 16;
+ get_bits_no_markers(16);
+ get_bits_no_markers(16);
+}
+
+void jpeg_decoder::transform_mcu(int mcu_row)
+{
+ jpgd_block_t* pSrc_ptr = m_pMCU_coefficients;
+ uint8* pDst_ptr = m_pSample_buf + mcu_row * m_blocks_per_mcu * 64;
+
+ for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
+ {
+ idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag[mcu_block]);
+ pSrc_ptr += 64;
+ pDst_ptr += 64;
+ }
+}
+
+static const uint8 s_max_rc[64] =
+{
+ 17, 18, 34, 50, 50, 51, 52, 52, 52, 68, 84, 84, 84, 84, 85, 86, 86, 86, 86, 86,
+ 102, 118, 118, 118, 118, 118, 118, 119, 120, 120, 120, 120, 120, 120, 120, 136,
+ 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
+ 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136
+};
+
+void jpeg_decoder::transform_mcu_expand(int mcu_row)
+{
+ jpgd_block_t* pSrc_ptr = m_pMCU_coefficients;
+ uint8* pDst_ptr = m_pSample_buf + mcu_row * m_expanded_blocks_per_mcu * 64;
+
+ // Y IDCT
+ int mcu_block;
+ for (mcu_block = 0; mcu_block < m_expanded_blocks_per_component; mcu_block++)
+ {
+ idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag[mcu_block]);
+ pSrc_ptr += 64;
+ pDst_ptr += 64;
+ }
+
+ // Chroma IDCT, with upsampling
+ jpgd_block_t temp_block[64];
+
+ for (int i = 0; i < 2; i++)
+ {
+ DCT_Upsample::Matrix44 P, Q, R, S;
+
+ JPGD_ASSERT(m_mcu_block_max_zag[mcu_block] >= 1);
+ JPGD_ASSERT(m_mcu_block_max_zag[mcu_block] <= 64);
+
+ int max_zag = m_mcu_block_max_zag[mcu_block++] - 1;
+ if (max_zag <= 0) max_zag = 0; // should never happen, only here to shut up static analysis
+ switch (s_max_rc[max_zag])
+ {
+ case 1*16+1:
+ DCT_Upsample::P_Q<1, 1>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<1, 1>::calc(R, S, pSrc_ptr);
+ break;
+ case 1*16+2:
+ DCT_Upsample::P_Q<1, 2>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<1, 2>::calc(R, S, pSrc_ptr);
+ break;
+ case 2*16+2:
+ DCT_Upsample::P_Q<2, 2>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<2, 2>::calc(R, S, pSrc_ptr);
+ break;
+ case 3*16+2:
+ DCT_Upsample::P_Q<3, 2>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<3, 2>::calc(R, S, pSrc_ptr);
+ break;
+ case 3*16+3:
+ DCT_Upsample::P_Q<3, 3>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<3, 3>::calc(R, S, pSrc_ptr);
+ break;
+ case 3*16+4:
+ DCT_Upsample::P_Q<3, 4>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<3, 4>::calc(R, S, pSrc_ptr);
+ break;
+ case 4*16+4:
+ DCT_Upsample::P_Q<4, 4>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<4, 4>::calc(R, S, pSrc_ptr);
+ break;
+ case 5*16+4:
+ DCT_Upsample::P_Q<5, 4>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<5, 4>::calc(R, S, pSrc_ptr);
+ break;
+ case 5*16+5:
+ DCT_Upsample::P_Q<5, 5>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<5, 5>::calc(R, S, pSrc_ptr);
+ break;
+ case 5*16+6:
+ DCT_Upsample::P_Q<5, 6>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<5, 6>::calc(R, S, pSrc_ptr);
+ break;
+ case 6*16+6:
+ DCT_Upsample::P_Q<6, 6>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<6, 6>::calc(R, S, pSrc_ptr);
+ break;
+ case 7*16+6:
+ DCT_Upsample::P_Q<7, 6>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<7, 6>::calc(R, S, pSrc_ptr);
+ break;
+ case 7*16+7:
+ DCT_Upsample::P_Q<7, 7>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<7, 7>::calc(R, S, pSrc_ptr);
+ break;
+ case 7*16+8:
+ DCT_Upsample::P_Q<7, 8>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<7, 8>::calc(R, S, pSrc_ptr);
+ break;
+ case 8*16+8:
+ DCT_Upsample::P_Q<8, 8>::calc(P, Q, pSrc_ptr);
+ DCT_Upsample::R_S<8, 8>::calc(R, S, pSrc_ptr);
+ break;
+ default:
+ JPGD_ASSERT(false);
+ }
+
+ DCT_Upsample::Matrix44 a(P + Q); P -= Q;
+ DCT_Upsample::Matrix44& b = P;
+ DCT_Upsample::Matrix44 c(R + S); R -= S;
+ DCT_Upsample::Matrix44& d = R;
+
+ DCT_Upsample::Matrix44::add_and_store(temp_block, a, c);
+ idct_4x4(temp_block, pDst_ptr);
+ pDst_ptr += 64;
+
+ DCT_Upsample::Matrix44::sub_and_store(temp_block, a, c);
+ idct_4x4(temp_block, pDst_ptr);
+ pDst_ptr += 64;
+
+ DCT_Upsample::Matrix44::add_and_store(temp_block, b, d);
+ idct_4x4(temp_block, pDst_ptr);
+ pDst_ptr += 64;
+
+ DCT_Upsample::Matrix44::sub_and_store(temp_block, b, d);
+ idct_4x4(temp_block, pDst_ptr);
+ pDst_ptr += 64;
+
+ pSrc_ptr += 64;
+ }
+}
+
+// Loads and dequantizes the next row of (already decoded) coefficients.
+// Progressive images only.
+void jpeg_decoder::load_next_row()
+{
+ int i;
+ jpgd_block_t *p;
+ jpgd_quant_t *q;
+ int mcu_row, mcu_block, row_block = 0;
+ int component_num, component_id;
+ int block_x_mcu[JPGD_MAX_COMPONENTS];
+
+ memset(block_x_mcu, 0, JPGD_MAX_COMPONENTS * sizeof(int));
+
+ for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
+ {
+ int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0;
+
+ for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
+ {
+ component_id = m_mcu_org[mcu_block];
+ q = m_quant[m_comp_quant[component_id]];
+
+ p = m_pMCU_coefficients + 64 * mcu_block;
+
+ jpgd_block_t* pAC = coeff_buf_getp(m_ac_coeffs[component_id], block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs);
+ jpgd_block_t* pDC = coeff_buf_getp(m_dc_coeffs[component_id], block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs);
+ p[0] = pDC[0];
+ memcpy(&p[1], &pAC[1], 63 * sizeof(jpgd_block_t));
+
+ for (i = 63; i > 0; i--)
+ if (p[g_ZAG[i]])
+ break;
+
+ m_mcu_block_max_zag[mcu_block] = i + 1;
+
+ for ( ; i >= 0; i--)
+ if (p[g_ZAG[i]])
+ p[g_ZAG[i]] = static_cast<jpgd_block_t>(p[g_ZAG[i]] * q[i]);
+
+ row_block++;
+
+ if (m_comps_in_scan == 1)
+ block_x_mcu[component_id]++;
+ else
+ {
+ if (++block_x_mcu_ofs == m_comp_h_samp[component_id])
+ {
+ block_x_mcu_ofs = 0;
+
+ if (++block_y_mcu_ofs == m_comp_v_samp[component_id])
+ {
+ block_y_mcu_ofs = 0;
+
+ block_x_mcu[component_id] += m_comp_h_samp[component_id];
+ }
+ }
+ }
+ }
+
+ if (m_freq_domain_chroma_upsample)
+ transform_mcu_expand(mcu_row);
+ else
+ transform_mcu(mcu_row);
+ }
+
+ if (m_comps_in_scan == 1)
+ m_block_y_mcu[m_comp_list[0]]++;
+ else
+ {
+ for (component_num = 0; component_num < m_comps_in_scan; component_num++)
+ {
+ component_id = m_comp_list[component_num];
+
+ m_block_y_mcu[component_id] += m_comp_v_samp[component_id];
+ }
+ }
+}
+
+// Restart interval processing.
+void jpeg_decoder::process_restart()
+{
+ int i;
+ int c = 0;
+
+ // Align to a byte boundry
+ // FIXME: Is this really necessary? get_bits_no_markers() never reads in markers!
+ //get_bits_no_markers(m_bits_left & 7);
+
+ // Let's scan a little bit to find the marker, but not _too_ far.
+ // 1536 is a "fudge factor" that determines how much to scan.
+ for (i = 1536; i > 0; i--)
+ if (get_char() == 0xFF)
+ break;
+
+ if (i == 0)
+ stop_decoding(JPGD_BAD_RESTART_MARKER);
+
+ for ( ; i > 0; i--)
+ if ((c = get_char()) != 0xFF)
+ break;
+
+ if (i == 0)
+ stop_decoding(JPGD_BAD_RESTART_MARKER);
+
+ // Is it the expected marker? If not, something bad happened.
+ if (c != (m_next_restart_num + M_RST0))
+ stop_decoding(JPGD_BAD_RESTART_MARKER);
+
+ // Reset each component's DC prediction values.
+ memset(&m_last_dc_val, 0, m_comps_in_frame * sizeof(uint));
+
+ m_eob_run = 0;
+
+ m_restarts_left = m_restart_interval;
+
+ m_next_restart_num = (m_next_restart_num + 1) & 7;
+
+ // Get the bit buffer going again...
+
+ m_bits_left = 16;
+ get_bits_no_markers(16);
+ get_bits_no_markers(16);
+}
+
+static inline int dequantize_ac(int c, int q) { c *= q; return c; }
+
+// Decodes and dequantizes the next row of coefficients.
+void jpeg_decoder::decode_next_row()
+{
+ int row_block = 0;
+
+ for (int mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
+ {
+ if ((m_restart_interval) && (m_restarts_left == 0))
+ process_restart();
+
+ jpgd_block_t* p = m_pMCU_coefficients;
+ for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++, p += 64)
+ {
+ int component_id = m_mcu_org[mcu_block];
+ jpgd_quant_t* q = m_quant[m_comp_quant[component_id]];
+
+ int r, s;
+ s = huff_decode(m_pHuff_tabs[m_comp_dc_tab[component_id]], r);
+ s = JPGD_HUFF_EXTEND(r, s);
+
+ m_last_dc_val[component_id] = (s += m_last_dc_val[component_id]);
+
+ p[0] = static_cast<jpgd_block_t>(s * q[0]);
+
+ int prev_num_set = m_mcu_block_max_zag[mcu_block];
+
+ huff_tables *pH = m_pHuff_tabs[m_comp_ac_tab[component_id]];
+
+ int k;
+ for (k = 1; k < 64; k++)
+ {
+ int extra_bits;
+ s = huff_decode(pH, extra_bits);
+
+ r = s >> 4;
+ s &= 15;
+
+ if (s)
+ {
+ if (r)
+ {
+ if ((k + r) > 63)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ if (k < prev_num_set)
+ {
+ int n = JPGD_MIN(r, prev_num_set - k);
+ int kt = k;
+ while (n--)
+ p[g_ZAG[kt++]] = 0;
+ }
+
+ k += r;
+ }
+
+ s = JPGD_HUFF_EXTEND(extra_bits, s);
+
+ JPGD_ASSERT(k < 64);
+
+ p[g_ZAG[k]] = static_cast<jpgd_block_t>(dequantize_ac(s, q[k])); //s * q[k];
+ }
+ else
+ {
+ if (r == 15)
+ {
+ if ((k + 16) > 64)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ if (k < prev_num_set)
+ {
+ int n = JPGD_MIN(16, prev_num_set - k);
+ int kt = k;
+ while (n--)
+ {
+ JPGD_ASSERT(kt <= 63);
+ p[g_ZAG[kt++]] = 0;
+ }
+ }
+
+ k += 16 - 1; // - 1 because the loop counter is k
+ JPGD_ASSERT(p[g_ZAG[k]] == 0);
+ }
+ else
+ break;
+ }
+ }
+
+ if (k < prev_num_set)
+ {
+ int kt = k;
+ while (kt < prev_num_set)
+ p[g_ZAG[kt++]] = 0;
+ }
+
+ m_mcu_block_max_zag[mcu_block] = k;
+
+ row_block++;
+ }
+
+ if (m_freq_domain_chroma_upsample)
+ transform_mcu_expand(mcu_row);
+ else
+ transform_mcu(mcu_row);
+
+ m_restarts_left--;
+ }
+}
+
+// YCbCr H1V1 (1x1:1:1, 3 m_blocks per MCU) to RGB
+void jpeg_decoder::H1V1Convert()
+{
+ int row = m_max_mcu_y_size - m_mcu_lines_left;
+ uint8 *d = m_pScan_line_0;
+ uint8 *s = m_pSample_buf + row * 8;
+
+ for (int i = m_max_mcus_per_row; i > 0; i--)
+ {
+ for (int j = 0; j < 8; j++)
+ {
+ int y = s[j];
+ int cb = s[64+j];
+ int cr = s[128+j];
+
+ d[0] = clamp(y + m_crr[cr]);
+ d[1] = clamp(y + ((m_crg[cr] + m_cbg[cb]) >> 16));
+ d[2] = clamp(y + m_cbb[cb]);
+ d[3] = 255;
+
+ d += 4;
+ }
+
+ s += 64*3;
+ }
+}
+
+// YCbCr H2V1 (2x1:1:1, 4 m_blocks per MCU) to RGB
+void jpeg_decoder::H2V1Convert()
+{
+ int row = m_max_mcu_y_size - m_mcu_lines_left;
+ uint8 *d0 = m_pScan_line_0;
+ uint8 *y = m_pSample_buf + row * 8;
+ uint8 *c = m_pSample_buf + 2*64 + row * 8;
+
+ for (int i = m_max_mcus_per_row; i > 0; i--)
+ {
+ for (int l = 0; l < 2; l++)
+ {
+ for (int j = 0; j < 4; j++)
+ {
+ int cb = c[0];
+ int cr = c[64];
+
+ int rc = m_crr[cr];
+ int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
+ int bc = m_cbb[cb];
+
+ int yy = y[j<<1];
+ d0[0] = clamp(yy+rc);
+ d0[1] = clamp(yy+gc);
+ d0[2] = clamp(yy+bc);
+ d0[3] = 255;
+
+ yy = y[(j<<1)+1];
+ d0[4] = clamp(yy+rc);
+ d0[5] = clamp(yy+gc);
+ d0[6] = clamp(yy+bc);
+ d0[7] = 255;
+
+ d0 += 8;
+
+ c++;
+ }
+ y += 64;
+ }
+
+ y += 64*4 - 64*2;
+ c += 64*4 - 8;
+ }
+}
+
+// YCbCr H2V1 (1x2:1:1, 4 m_blocks per MCU) to RGB
+void jpeg_decoder::H1V2Convert()
+{
+ int row = m_max_mcu_y_size - m_mcu_lines_left;
+ uint8 *d0 = m_pScan_line_0;
+ uint8 *d1 = m_pScan_line_1;
+ uint8 *y;
+ uint8 *c;
+
+ if (row < 8)
+ y = m_pSample_buf + row * 8;
+ else
+ y = m_pSample_buf + 64*1 + (row & 7) * 8;
+
+ c = m_pSample_buf + 64*2 + (row >> 1) * 8;
+
+ for (int i = m_max_mcus_per_row; i > 0; i--)
+ {
+ for (int j = 0; j < 8; j++)
+ {
+ int cb = c[0+j];
+ int cr = c[64+j];
+
+ int rc = m_crr[cr];
+ int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
+ int bc = m_cbb[cb];
+
+ int yy = y[j];
+ d0[0] = clamp(yy+rc);
+ d0[1] = clamp(yy+gc);
+ d0[2] = clamp(yy+bc);
+ d0[3] = 255;
+
+ yy = y[8+j];
+ d1[0] = clamp(yy+rc);
+ d1[1] = clamp(yy+gc);
+ d1[2] = clamp(yy+bc);
+ d1[3] = 255;
+
+ d0 += 4;
+ d1 += 4;
+ }
+
+ y += 64*4;
+ c += 64*4;
+ }
+}
+
+// YCbCr H2V2 (2x2:1:1, 6 m_blocks per MCU) to RGB
+void jpeg_decoder::H2V2Convert()
+{
+ int row = m_max_mcu_y_size - m_mcu_lines_left;
+ uint8 *d0 = m_pScan_line_0;
+ uint8 *d1 = m_pScan_line_1;
+ uint8 *y;
+ uint8 *c;
+
+ if (row < 8)
+ y = m_pSample_buf + row * 8;
+ else
+ y = m_pSample_buf + 64*2 + (row & 7) * 8;
+
+ c = m_pSample_buf + 64*4 + (row >> 1) * 8;
+
+ for (int i = m_max_mcus_per_row; i > 0; i--)
+ {
+ for (int l = 0; l < 2; l++)
+ {
+ for (int j = 0; j < 8; j += 2)
+ {
+ int cb = c[0];
+ int cr = c[64];
+
+ int rc = m_crr[cr];
+ int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
+ int bc = m_cbb[cb];
+
+ int yy = y[j];
+ d0[0] = clamp(yy+rc);
+ d0[1] = clamp(yy+gc);
+ d0[2] = clamp(yy+bc);
+ d0[3] = 255;
+
+ yy = y[j+1];
+ d0[4] = clamp(yy+rc);
+ d0[5] = clamp(yy+gc);
+ d0[6] = clamp(yy+bc);
+ d0[7] = 255;
+
+ yy = y[j+8];
+ d1[0] = clamp(yy+rc);
+ d1[1] = clamp(yy+gc);
+ d1[2] = clamp(yy+bc);
+ d1[3] = 255;
+
+ yy = y[j+8+1];
+ d1[4] = clamp(yy+rc);
+ d1[5] = clamp(yy+gc);
+ d1[6] = clamp(yy+bc);
+ d1[7] = 255;
+
+ d0 += 8;
+ d1 += 8;
+
+ c++;
+ }
+ y += 64;
+ }
+
+ y += 64*6 - 64*2;
+ c += 64*6 - 8;
+ }
+}
+
+// Y (1 block per MCU) to 8-bit grayscale
+void jpeg_decoder::gray_convert()
+{
+ int row = m_max_mcu_y_size - m_mcu_lines_left;
+ uint8 *d = m_pScan_line_0;
+ uint8 *s = m_pSample_buf + row * 8;
+
+ for (int i = m_max_mcus_per_row; i > 0; i--)
+ {
+ *(uint *)d = *(uint *)s;
+ *(uint *)(&d[4]) = *(uint *)(&s[4]);
+
+ s += 64;
+ d += 8;
+ }
+}
+
+void jpeg_decoder::expanded_convert()
+{
+ int row = m_max_mcu_y_size - m_mcu_lines_left;
+
+ uint8* Py = m_pSample_buf + (row / 8) * 64 * m_comp_h_samp[0] + (row & 7) * 8;
+
+ uint8* d = m_pScan_line_0;
+
+ for (int i = m_max_mcus_per_row; i > 0; i--)
+ {
+ for (int k = 0; k < m_max_mcu_x_size; k += 8)
+ {
+ const int Y_ofs = k * 8;
+ const int Cb_ofs = Y_ofs + 64 * m_expanded_blocks_per_component;
+ const int Cr_ofs = Y_ofs + 64 * m_expanded_blocks_per_component * 2;
+ for (int j = 0; j < 8; j++)
+ {
+ int y = Py[Y_ofs + j];
+ int cb = Py[Cb_ofs + j];
+ int cr = Py[Cr_ofs + j];
+
+ d[0] = clamp(y + m_crr[cr]);
+ d[1] = clamp(y + ((m_crg[cr] + m_cbg[cb]) >> 16));
+ d[2] = clamp(y + m_cbb[cb]);
+ d[3] = 255;
+
+ d += 4;
+ }
+ }
+
+ Py += 64 * m_expanded_blocks_per_mcu;
+ }
+}
+
+// Find end of image (EOI) marker, so we can return to the user the exact size of the input stream.
+void jpeg_decoder::find_eoi()
+{
+ if (!m_progressive_flag)
+ {
+ // Attempt to read the EOI marker.
+ //get_bits_no_markers(m_bits_left & 7);
+
+ // Prime the bit buffer
+ m_bits_left = 16;
+ get_bits(16);
+ get_bits(16);
+
+ // The next marker _should_ be EOI
+ process_markers();
+ }
+
+ m_total_bytes_read -= m_in_buf_left;
+}
+
+int jpeg_decoder::decode(const void** pScan_line, uint* pScan_line_len)
+{
+ if ((m_error_code) || (!m_ready_flag))
+ return JPGD_FAILED;
+
+ if (m_total_lines_left == 0)
+ return JPGD_DONE;
+
+ if (m_mcu_lines_left == 0)
+ {
+ if (setjmp(m_jmp_state))
+ return JPGD_FAILED;
+
+ if (m_progressive_flag)
+ load_next_row();
+ else
+ decode_next_row();
+
+ // Find the EOI marker if that was the last row.
+ if (m_total_lines_left <= m_max_mcu_y_size)
+ find_eoi();
+
+ m_mcu_lines_left = m_max_mcu_y_size;
+ }
+
+ if (m_freq_domain_chroma_upsample)
+ {
+ expanded_convert();
+ *pScan_line = m_pScan_line_0;
+ }
+ else
+ {
+ switch (m_scan_type)
+ {
+ case JPGD_YH2V2:
+ {
+ if ((m_mcu_lines_left & 1) == 0)
+ {
+ H2V2Convert();
+ *pScan_line = m_pScan_line_0;
+ }
+ else
+ *pScan_line = m_pScan_line_1;
+
+ break;
+ }
+ case JPGD_YH2V1:
+ {
+ H2V1Convert();
+ *pScan_line = m_pScan_line_0;
+ break;
+ }
+ case JPGD_YH1V2:
+ {
+ if ((m_mcu_lines_left & 1) == 0)
+ {
+ H1V2Convert();
+ *pScan_line = m_pScan_line_0;
+ }
+ else
+ *pScan_line = m_pScan_line_1;
+
+ break;
+ }
+ case JPGD_YH1V1:
+ {
+ H1V1Convert();
+ *pScan_line = m_pScan_line_0;
+ break;
+ }
+ case JPGD_GRAYSCALE:
+ {
+ gray_convert();
+ *pScan_line = m_pScan_line_0;
+
+ break;
+ }
+ }
+ }
+
+ *pScan_line_len = m_real_dest_bytes_per_scan_line;
+
+ m_mcu_lines_left--;
+ m_total_lines_left--;
+
+ return JPGD_SUCCESS;
+}
+
+// Creates the tables needed for efficient Huffman decoding.
+void jpeg_decoder::make_huff_table(int index, huff_tables *pH)
+{
+ int p, i, l, si;
+ uint8 huffsize[257];
+ uint huffcode[257];
+ uint code;
+ uint subtree;
+ int code_size;
+ int lastp;
+ int nextfreeentry;
+ int currententry;
+
+ pH->ac_table = m_huff_ac[index] != 0;
+
+ p = 0;
+
+ for (l = 1; l <= 16; l++)
+ {
+ for (i = 1; i <= m_huff_num[index][l]; i++)
+ huffsize[p++] = static_cast<uint8>(l);
+ }
+
+ huffsize[p] = 0;
+
+ lastp = p;
+
+ code = 0;
+ si = huffsize[0];
+ p = 0;
+
+ while (huffsize[p])
+ {
+ while (huffsize[p] == si)
+ {
+ huffcode[p++] = code;
+ code++;
+ }
+
+ code <<= 1;
+ si++;
+ }
+
+ memset(pH->look_up, 0, sizeof(pH->look_up));
+ memset(pH->look_up2, 0, sizeof(pH->look_up2));
+ memset(pH->tree, 0, sizeof(pH->tree));
+ memset(pH->code_size, 0, sizeof(pH->code_size));
+
+ nextfreeentry = -1;
+
+ p = 0;
+
+ while (p < lastp)
+ {
+ i = m_huff_val[index][p];
+ code = huffcode[p];
+ code_size = huffsize[p];
+
+ pH->code_size[i] = static_cast<uint8>(code_size);
+
+ if (code_size <= 8)
+ {
+ code <<= (8 - code_size);
+
+ for (l = 1 << (8 - code_size); l > 0; l--)
+ {
+ JPGD_ASSERT(i < 256);
+
+ pH->look_up[code] = i;
+
+ bool has_extrabits = false;
+ int extra_bits = 0;
+ int num_extra_bits = i & 15;
+
+ int bits_to_fetch = code_size;
+ if (num_extra_bits)
+ {
+ int total_codesize = code_size + num_extra_bits;
+ if (total_codesize <= 8)
+ {
+ has_extrabits = true;
+ extra_bits = ((1 << num_extra_bits) - 1) & (code >> (8 - total_codesize));
+ JPGD_ASSERT(extra_bits <= 0x7FFF);
+ bits_to_fetch += num_extra_bits;
+ }
+ }
+
+ if (!has_extrabits)
+ pH->look_up2[code] = i | (bits_to_fetch << 8);
+ else
+ pH->look_up2[code] = i | 0x8000 | (extra_bits << 16) | (bits_to_fetch << 8);
+
+ code++;
+ }
+ }
+ else
+ {
+ subtree = (code >> (code_size - 8)) & 0xFF;
+
+ currententry = pH->look_up[subtree];
+
+ if (currententry == 0)
+ {
+ pH->look_up[subtree] = currententry = nextfreeentry;
+ pH->look_up2[subtree] = currententry = nextfreeentry;
+
+ nextfreeentry -= 2;
+ }
+
+ code <<= (16 - (code_size - 8));
+
+ for (l = code_size; l > 9; l--)
+ {
+ if ((code & 0x8000) == 0)
+ currententry--;
+
+ if (pH->tree[-currententry - 1] == 0)
+ {
+ pH->tree[-currententry - 1] = nextfreeentry;
+
+ currententry = nextfreeentry;
+
+ nextfreeentry -= 2;
+ }
+ else
+ currententry = pH->tree[-currententry - 1];
+
+ code <<= 1;
+ }
+
+ if ((code & 0x8000) == 0)
+ currententry--;
+
+ pH->tree[-currententry - 1] = i;
+ }
+
+ p++;
+ }
+}
+
+// Verifies the quantization tables needed for this scan are available.
+void jpeg_decoder::check_quant_tables()
+{
+ for (int i = 0; i < m_comps_in_scan; i++)
+ if (m_quant[m_comp_quant[m_comp_list[i]]] == NULL)
+ stop_decoding(JPGD_UNDEFINED_QUANT_TABLE);
+}
+
+// Verifies that all the Huffman tables needed for this scan are available.
+void jpeg_decoder::check_huff_tables()
+{
+ for (int i = 0; i < m_comps_in_scan; i++)
+ {
+ if ((m_spectral_start == 0) && (m_huff_num[m_comp_dc_tab[m_comp_list[i]]] == NULL))
+ stop_decoding(JPGD_UNDEFINED_HUFF_TABLE);
+
+ if ((m_spectral_end > 0) && (m_huff_num[m_comp_ac_tab[m_comp_list[i]]] == NULL))
+ stop_decoding(JPGD_UNDEFINED_HUFF_TABLE);
+ }
+
+ for (int i = 0; i < JPGD_MAX_HUFF_TABLES; i++)
+ if (m_huff_num[i])
+ {
+ if (!m_pHuff_tabs[i])
+ m_pHuff_tabs[i] = (huff_tables *)alloc(sizeof(huff_tables));
+
+ make_huff_table(i, m_pHuff_tabs[i]);
+ }
+}
+
+// Determines the component order inside each MCU.
+// Also calcs how many MCU's are on each row, etc.
+void jpeg_decoder::calc_mcu_block_order()
+{
+ int component_num, component_id;
+ int max_h_samp = 0, max_v_samp = 0;
+
+ for (component_id = 0; component_id < m_comps_in_frame; component_id++)
+ {
+ if (m_comp_h_samp[component_id] > max_h_samp)
+ max_h_samp = m_comp_h_samp[component_id];
+
+ if (m_comp_v_samp[component_id] > max_v_samp)
+ max_v_samp = m_comp_v_samp[component_id];
+ }
+
+ for (component_id = 0; component_id < m_comps_in_frame; component_id++)
+ {
+ m_comp_h_blocks[component_id] = ((((m_image_x_size * m_comp_h_samp[component_id]) + (max_h_samp - 1)) / max_h_samp) + 7) / 8;
+ m_comp_v_blocks[component_id] = ((((m_image_y_size * m_comp_v_samp[component_id]) + (max_v_samp - 1)) / max_v_samp) + 7) / 8;
+ }
+
+ if (m_comps_in_scan == 1)
+ {
+ m_mcus_per_row = m_comp_h_blocks[m_comp_list[0]];
+ m_mcus_per_col = m_comp_v_blocks[m_comp_list[0]];
+ }
+ else
+ {
+ m_mcus_per_row = (((m_image_x_size + 7) / 8) + (max_h_samp - 1)) / max_h_samp;
+ m_mcus_per_col = (((m_image_y_size + 7) / 8) + (max_v_samp - 1)) / max_v_samp;
+ }
+
+ if (m_comps_in_scan == 1)
+ {
+ m_mcu_org[0] = m_comp_list[0];
+
+ m_blocks_per_mcu = 1;
+ }
+ else
+ {
+ m_blocks_per_mcu = 0;
+
+ for (component_num = 0; component_num < m_comps_in_scan; component_num++)
+ {
+ int num_blocks;
+
+ component_id = m_comp_list[component_num];
+
+ num_blocks = m_comp_h_samp[component_id] * m_comp_v_samp[component_id];
+
+ while (num_blocks--)
+ m_mcu_org[m_blocks_per_mcu++] = component_id;
+ }
+ }
+}
+
+// Starts a new scan.
+int jpeg_decoder::init_scan()
+{
+ if (!locate_sos_marker())
+ return JPGD_FALSE;
+
+ calc_mcu_block_order();
+
+ check_huff_tables();
+
+ check_quant_tables();
+
+ memset(m_last_dc_val, 0, m_comps_in_frame * sizeof(uint));
+
+ m_eob_run = 0;
+
+ if (m_restart_interval)
+ {
+ m_restarts_left = m_restart_interval;
+ m_next_restart_num = 0;
+ }
+
+ fix_in_buffer();
+
+ return JPGD_TRUE;
+}
+
+// Starts a frame. Determines if the number of components or sampling factors
+// are supported.
+void jpeg_decoder::init_frame()
+{
+ int i;
+
+ if (m_comps_in_frame == 1)
+ {
+ if ((m_comp_h_samp[0] != 1) || (m_comp_v_samp[0] != 1))
+ stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
+
+ m_scan_type = JPGD_GRAYSCALE;
+ m_max_blocks_per_mcu = 1;
+ m_max_mcu_x_size = 8;
+ m_max_mcu_y_size = 8;
+ }
+ else if (m_comps_in_frame == 3)
+ {
+ if ( ((m_comp_h_samp[1] != 1) || (m_comp_v_samp[1] != 1)) ||
+ ((m_comp_h_samp[2] != 1) || (m_comp_v_samp[2] != 1)) )
+ stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
+
+ if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 1))
+ {
+ m_scan_type = JPGD_YH1V1;
+
+ m_max_blocks_per_mcu = 3;
+ m_max_mcu_x_size = 8;
+ m_max_mcu_y_size = 8;
+ }
+ else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 1))
+ {
+ m_scan_type = JPGD_YH2V1;
+ m_max_blocks_per_mcu = 4;
+ m_max_mcu_x_size = 16;
+ m_max_mcu_y_size = 8;
+ }
+ else if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 2))
+ {
+ m_scan_type = JPGD_YH1V2;
+ m_max_blocks_per_mcu = 4;
+ m_max_mcu_x_size = 8;
+ m_max_mcu_y_size = 16;
+ }
+ else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 2))
+ {
+ m_scan_type = JPGD_YH2V2;
+ m_max_blocks_per_mcu = 6;
+ m_max_mcu_x_size = 16;
+ m_max_mcu_y_size = 16;
+ }
+ else
+ stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
+ }
+ else
+ stop_decoding(JPGD_UNSUPPORTED_COLORSPACE);
+
+ m_max_mcus_per_row = (m_image_x_size + (m_max_mcu_x_size - 1)) / m_max_mcu_x_size;
+ m_max_mcus_per_col = (m_image_y_size + (m_max_mcu_y_size - 1)) / m_max_mcu_y_size;
+
+ // These values are for the *destination* pixels: after conversion.
+ if (m_scan_type == JPGD_GRAYSCALE)
+ m_dest_bytes_per_pixel = 1;
+ else
+ m_dest_bytes_per_pixel = 4;
+
+ m_dest_bytes_per_scan_line = ((m_image_x_size + 15) & 0xFFF0) * m_dest_bytes_per_pixel;
+
+ m_real_dest_bytes_per_scan_line = (m_image_x_size * m_dest_bytes_per_pixel);
+
+ // Initialize two scan line buffers.
+ m_pScan_line_0 = (uint8 *)alloc(m_dest_bytes_per_scan_line, true);
+ if ((m_scan_type == JPGD_YH1V2) || (m_scan_type == JPGD_YH2V2))
+ m_pScan_line_1 = (uint8 *)alloc(m_dest_bytes_per_scan_line, true);
+
+ m_max_blocks_per_row = m_max_mcus_per_row * m_max_blocks_per_mcu;
+
+ // Should never happen
+ if (m_max_blocks_per_row > JPGD_MAX_BLOCKS_PER_ROW)
+ stop_decoding(JPGD_ASSERTION_ERROR);
+
+ // Allocate the coefficient buffer, enough for one MCU
+ m_pMCU_coefficients = (jpgd_block_t*)alloc(m_max_blocks_per_mcu * 64 * sizeof(jpgd_block_t));
+
+ for (i = 0; i < m_max_blocks_per_mcu; i++)
+ m_mcu_block_max_zag[i] = 64;
+
+ m_expanded_blocks_per_component = m_comp_h_samp[0] * m_comp_v_samp[0];
+ m_expanded_blocks_per_mcu = m_expanded_blocks_per_component * m_comps_in_frame;
+ m_expanded_blocks_per_row = m_max_mcus_per_row * m_expanded_blocks_per_mcu;
+ // Freq. domain chroma upsampling is only supported for H2V2 subsampling factor (the most common one I've seen).
+ m_freq_domain_chroma_upsample = false;
+#if JPGD_SUPPORT_FREQ_DOMAIN_UPSAMPLING
+ m_freq_domain_chroma_upsample = (m_expanded_blocks_per_mcu == 4*3);
+#endif
+
+ if (m_freq_domain_chroma_upsample)
+ m_pSample_buf = (uint8 *)alloc(m_expanded_blocks_per_row * 64);
+ else
+ m_pSample_buf = (uint8 *)alloc(m_max_blocks_per_row * 64);
+
+ m_total_lines_left = m_image_y_size;
+
+ m_mcu_lines_left = 0;
+
+ create_look_ups();
+}
+
+// The coeff_buf series of methods originally stored the coefficients
+// into a "virtual" file which was located in EMS, XMS, or a disk file. A cache
+// was used to make this process more efficient. Now, we can store the entire
+// thing in RAM.
+jpeg_decoder::coeff_buf* jpeg_decoder::coeff_buf_open(int block_num_x, int block_num_y, int block_len_x, int block_len_y)
+{
+ coeff_buf* cb = (coeff_buf*)alloc(sizeof(coeff_buf));
+
+ cb->block_num_x = block_num_x;
+ cb->block_num_y = block_num_y;
+ cb->block_len_x = block_len_x;
+ cb->block_len_y = block_len_y;
+ cb->block_size = (block_len_x * block_len_y) * sizeof(jpgd_block_t);
+ cb->pData = (uint8 *)alloc(cb->block_size * block_num_x * block_num_y, true);
+ return cb;
+}
+
+inline jpgd_block_t *jpeg_decoder::coeff_buf_getp(coeff_buf *cb, int block_x, int block_y)
+{
+ JPGD_ASSERT((block_x < cb->block_num_x) && (block_y < cb->block_num_y));
+ return (jpgd_block_t *)(cb->pData + block_x * cb->block_size + block_y * (cb->block_size * cb->block_num_x));
+}
+
+// The following methods decode the various types of m_blocks encountered
+// in progressively encoded images.
+void jpeg_decoder::decode_block_dc_first(jpeg_decoder *pD, int component_id, int block_x, int block_y)
+{
+ int s, r;
+ jpgd_block_t *p = pD->coeff_buf_getp(pD->m_dc_coeffs[component_id], block_x, block_y);
+
+ if ((s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_dc_tab[component_id]])) != 0)
+ {
+ r = pD->get_bits_no_markers(s);
+ s = JPGD_HUFF_EXTEND(r, s);
+ }
+
+ pD->m_last_dc_val[component_id] = (s += pD->m_last_dc_val[component_id]);
+
+ p[0] = static_cast<jpgd_block_t>(s << pD->m_successive_low);
+}
+
+void jpeg_decoder::decode_block_dc_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y)
+{
+ if (pD->get_bits_no_markers(1))
+ {
+ jpgd_block_t *p = pD->coeff_buf_getp(pD->m_dc_coeffs[component_id], block_x, block_y);
+
+ p[0] |= (1 << pD->m_successive_low);
+ }
+}
+
+void jpeg_decoder::decode_block_ac_first(jpeg_decoder *pD, int component_id, int block_x, int block_y)
+{
+ int k, s, r;
+
+ if (pD->m_eob_run)
+ {
+ pD->m_eob_run--;
+ return;
+ }
+
+ jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y);
+
+ for (k = pD->m_spectral_start; k <= pD->m_spectral_end; k++)
+ {
+ s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_ac_tab[component_id]]);
+
+ r = s >> 4;
+ s &= 15;
+
+ if (s)
+ {
+ if ((k += r) > 63)
+ pD->stop_decoding(JPGD_DECODE_ERROR);
+
+ r = pD->get_bits_no_markers(s);
+ s = JPGD_HUFF_EXTEND(r, s);
+
+ p[g_ZAG[k]] = static_cast<jpgd_block_t>(s << pD->m_successive_low);
+ }
+ else
+ {
+ if (r == 15)
+ {
+ if ((k += 15) > 63)
+ pD->stop_decoding(JPGD_DECODE_ERROR);
+ }
+ else
+ {
+ pD->m_eob_run = 1 << r;
+
+ if (r)
+ pD->m_eob_run += pD->get_bits_no_markers(r);
+
+ pD->m_eob_run--;
+
+ break;
+ }
+ }
+ }
+}
+
+void jpeg_decoder::decode_block_ac_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y)
+{
+ int s, k, r;
+ int p1 = 1 << pD->m_successive_low;
+ int m1 = (-1) << pD->m_successive_low;
+ jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y);
+
+ JPGD_ASSERT(pD->m_spectral_end <= 63);
+
+ k = pD->m_spectral_start;
+
+ if (pD->m_eob_run == 0)
+ {
+ for ( ; k <= pD->m_spectral_end; k++)
+ {
+ s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_ac_tab[component_id]]);
+
+ r = s >> 4;
+ s &= 15;
+
+ if (s)
+ {
+ if (s != 1)
+ pD->stop_decoding(JPGD_DECODE_ERROR);
+
+ if (pD->get_bits_no_markers(1))
+ s = p1;
+ else
+ s = m1;
+ }
+ else
+ {
+ if (r != 15)
+ {
+ pD->m_eob_run = 1 << r;
+
+ if (r)
+ pD->m_eob_run += pD->get_bits_no_markers(r);
+
+ break;
+ }
+ }
+
+ do
+ {
+ jpgd_block_t *this_coef = p + g_ZAG[k & 63];
+
+ if (*this_coef != 0)
+ {
+ if (pD->get_bits_no_markers(1))
+ {
+ if ((*this_coef & p1) == 0)
+ {
+ if (*this_coef >= 0)
+ *this_coef = static_cast<jpgd_block_t>(*this_coef + p1);
+ else
+ *this_coef = static_cast<jpgd_block_t>(*this_coef + m1);
+ }
+ }
+ }
+ else
+ {
+ if (--r < 0)
+ break;
+ }
+
+ k++;
+
+ } while (k <= pD->m_spectral_end);
+
+ if ((s) && (k < 64))
+ {
+ p[g_ZAG[k]] = static_cast<jpgd_block_t>(s);
+ }
+ }
+ }
+
+ if (pD->m_eob_run > 0)
+ {
+ for ( ; k <= pD->m_spectral_end; k++)
+ {
+ jpgd_block_t *this_coef = p + g_ZAG[k & 63]; // logical AND to shut up static code analysis
+
+ if (*this_coef != 0)
+ {
+ if (pD->get_bits_no_markers(1))
+ {
+ if ((*this_coef & p1) == 0)
+ {
+ if (*this_coef >= 0)
+ *this_coef = static_cast<jpgd_block_t>(*this_coef + p1);
+ else
+ *this_coef = static_cast<jpgd_block_t>(*this_coef + m1);
+ }
+ }
+ }
+ }
+
+ pD->m_eob_run--;
+ }
+}
+
+// Decode a scan in a progressively encoded image.
+void jpeg_decoder::decode_scan(pDecode_block_func decode_block_func)
+{
+ int mcu_row, mcu_col, mcu_block;
+ int block_x_mcu[JPGD_MAX_COMPONENTS], m_block_y_mcu[JPGD_MAX_COMPONENTS];
+
+ memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu));
+
+ for (mcu_col = 0; mcu_col < m_mcus_per_col; mcu_col++)
+ {
+ int component_num, component_id;
+
+ memset(block_x_mcu, 0, sizeof(block_x_mcu));
+
+ for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
+ {
+ int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0;
+
+ if ((m_restart_interval) && (m_restarts_left == 0))
+ process_restart();
+
+ for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
+ {
+ component_id = m_mcu_org[mcu_block];
+
+ decode_block_func(this, component_id, block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs);
+
+ if (m_comps_in_scan == 1)
+ block_x_mcu[component_id]++;
+ else
+ {
+ if (++block_x_mcu_ofs == m_comp_h_samp[component_id])
+ {
+ block_x_mcu_ofs = 0;
+
+ if (++block_y_mcu_ofs == m_comp_v_samp[component_id])
+ {
+ block_y_mcu_ofs = 0;
+ block_x_mcu[component_id] += m_comp_h_samp[component_id];
+ }
+ }
+ }
+ }
+
+ m_restarts_left--;
+ }
+
+ if (m_comps_in_scan == 1)
+ m_block_y_mcu[m_comp_list[0]]++;
+ else
+ {
+ for (component_num = 0; component_num < m_comps_in_scan; component_num++)
+ {
+ component_id = m_comp_list[component_num];
+ m_block_y_mcu[component_id] += m_comp_v_samp[component_id];
+ }
+ }
+ }
+}
+
+// Decode a progressively encoded image.
+void jpeg_decoder::init_progressive()
+{
+ int i;
+
+ if (m_comps_in_frame == 4)
+ stop_decoding(JPGD_UNSUPPORTED_COLORSPACE);
+
+ // Allocate the coefficient buffers.
+ for (i = 0; i < m_comps_in_frame; i++)
+ {
+ m_dc_coeffs[i] = coeff_buf_open(m_max_mcus_per_row * m_comp_h_samp[i], m_max_mcus_per_col * m_comp_v_samp[i], 1, 1);
+ m_ac_coeffs[i] = coeff_buf_open(m_max_mcus_per_row * m_comp_h_samp[i], m_max_mcus_per_col * m_comp_v_samp[i], 8, 8);
+ }
+
+ for ( ; ; )
+ {
+ int dc_only_scan, refinement_scan;
+ pDecode_block_func decode_block_func;
+
+ if (!init_scan())
+ break;
+
+ dc_only_scan = (m_spectral_start == 0);
+ refinement_scan = (m_successive_high != 0);
+
+ if ((m_spectral_start > m_spectral_end) || (m_spectral_end > 63))
+ stop_decoding(JPGD_BAD_SOS_SPECTRAL);
+
+ if (dc_only_scan)
+ {
+ if (m_spectral_end)
+ stop_decoding(JPGD_BAD_SOS_SPECTRAL);
+ }
+ else if (m_comps_in_scan != 1) /* AC scans can only contain one component */
+ stop_decoding(JPGD_BAD_SOS_SPECTRAL);
+
+ if ((refinement_scan) && (m_successive_low != m_successive_high - 1))
+ stop_decoding(JPGD_BAD_SOS_SUCCESSIVE);
+
+ if (dc_only_scan)
+ {
+ if (refinement_scan)
+ decode_block_func = decode_block_dc_refine;
+ else
+ decode_block_func = decode_block_dc_first;
+ }
+ else
+ {
+ if (refinement_scan)
+ decode_block_func = decode_block_ac_refine;
+ else
+ decode_block_func = decode_block_ac_first;
+ }
+
+ decode_scan(decode_block_func);
+
+ m_bits_left = 16;
+ get_bits(16);
+ get_bits(16);
+ }
+
+ m_comps_in_scan = m_comps_in_frame;
+
+ for (i = 0; i < m_comps_in_frame; i++)
+ m_comp_list[i] = i;
+
+ calc_mcu_block_order();
+}
+
+void jpeg_decoder::init_sequential()
+{
+ if (!init_scan())
+ stop_decoding(JPGD_UNEXPECTED_MARKER);
+}
+
+void jpeg_decoder::decode_start()
+{
+ init_frame();
+
+ if (m_progressive_flag)
+ init_progressive();
+ else
+ init_sequential();
+}
+
+void jpeg_decoder::decode_init(jpeg_decoder_stream *pStream)
+{
+ init(pStream);
+ locate_sof_marker();
+}
+
+jpeg_decoder::jpeg_decoder(jpeg_decoder_stream *pStream)
+{
+ if (setjmp(m_jmp_state))
+ return;
+ decode_init(pStream);
+}
+
+int jpeg_decoder::begin_decoding()
+{
+ if (m_ready_flag)
+ return JPGD_SUCCESS;
+
+ if (m_error_code)
+ return JPGD_FAILED;
+
+ if (setjmp(m_jmp_state))
+ return JPGD_FAILED;
+
+ decode_start();
+
+ m_ready_flag = true;
+
+ return JPGD_SUCCESS;
+}
+
+jpeg_decoder::~jpeg_decoder()
+{
+ free_all_blocks();
+}
+
+jpeg_decoder_file_stream::jpeg_decoder_file_stream()
+{
+ m_pFile = NULL;
+ m_eof_flag = false;
+ m_error_flag = false;
+}
+
+void jpeg_decoder_file_stream::close()
+{
+ if (m_pFile)
+ {
+ fclose(m_pFile);
+ m_pFile = NULL;
+ }
+
+ m_eof_flag = false;
+ m_error_flag = false;
+}
+
+jpeg_decoder_file_stream::~jpeg_decoder_file_stream()
+{
+ close();
+}
+
+bool jpeg_decoder_file_stream::open(const char *Pfilename)
+{
+ close();
+
+ m_eof_flag = false;
+ m_error_flag = false;
+
+#if defined(_MSC_VER)
+ m_pFile = NULL;
+ fopen_s(&m_pFile, Pfilename, "rb");
+#else
+ m_pFile = fopen(Pfilename, "rb");
+#endif
+ return m_pFile != NULL;
+}
+
+int jpeg_decoder_file_stream::read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag)
+{
+ if (!m_pFile)
+ return -1;
+
+ if (m_eof_flag)
+ {
+ *pEOF_flag = true;
+ return 0;
+ }
+
+ if (m_error_flag)
+ return -1;
+
+ int bytes_read = static_cast<int>(fread(pBuf, 1, max_bytes_to_read, m_pFile));
+ if (bytes_read < max_bytes_to_read)
+ {
+ if (ferror(m_pFile))
+ {
+ m_error_flag = true;
+ return -1;
+ }
+
+ m_eof_flag = true;
+ *pEOF_flag = true;
+ }
+
+ return bytes_read;
+}
+
+bool jpeg_decoder_mem_stream::open(const uint8 *pSrc_data, uint size)
+{
+ close();
+ m_pSrc_data = pSrc_data;
+ m_ofs = 0;
+ m_size = size;
+ return true;
+}
+
+int jpeg_decoder_mem_stream::read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag)
+{
+ *pEOF_flag = false;
+
+ if (!m_pSrc_data)
+ return -1;
+
+ uint bytes_remaining = m_size - m_ofs;
+ if ((uint)max_bytes_to_read > bytes_remaining)
+ {
+ max_bytes_to_read = bytes_remaining;
+ *pEOF_flag = true;
+ }
+
+ memcpy(pBuf, m_pSrc_data + m_ofs, max_bytes_to_read);
+ m_ofs += max_bytes_to_read;
+
+ return max_bytes_to_read;
+}
+
+unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, int *width, int *height, int *actual_comps, int req_comps)
+{
+ if (!actual_comps)
+ return NULL;
+ *actual_comps = 0;
+
+ if ((!pStream) || (!width) || (!height) || (!req_comps))
+ return NULL;
+
+ if ((req_comps != 1) && (req_comps != 3) && (req_comps != 4))
+ return NULL;
+
+ jpeg_decoder decoder(pStream);
+ if (decoder.get_error_code() != JPGD_SUCCESS)
+ return NULL;
+
+ const int image_width = decoder.get_width(), image_height = decoder.get_height();
+ *width = image_width;
+ *height = image_height;
+ *actual_comps = decoder.get_num_components();
+
+ if (decoder.begin_decoding() != JPGD_SUCCESS)
+ return NULL;
+
+ const int dst_bpl = image_width * req_comps;
+
+ uint8 *pImage_data = (uint8*)jpgd_malloc(dst_bpl * image_height);
+ if (!pImage_data)
+ return NULL;
+
+ for (int y = 0; y < image_height; y++)
+ {
+ const uint8* pScan_line;
+ uint scan_line_len;
+ if (decoder.decode((const void**)&pScan_line, &scan_line_len) != JPGD_SUCCESS)
+ {
+ jpgd_free(pImage_data);
+ return NULL;
+ }
+
+ uint8 *pDst = pImage_data + y * dst_bpl;
+
+ if (((req_comps == 1) && (decoder.get_num_components() == 1)) || ((req_comps == 4) && (decoder.get_num_components() == 3)))
+ memcpy(pDst, pScan_line, dst_bpl);
+ else if (decoder.get_num_components() == 1)
+ {
+ if (req_comps == 3)
+ {
+ for (int x = 0; x < image_width; x++)
+ {
+ uint8 luma = pScan_line[x];
+ pDst[0] = luma;
+ pDst[1] = luma;
+ pDst[2] = luma;
+ pDst += 3;
+ }
+ }
+ else
+ {
+ for (int x = 0; x < image_width; x++)
+ {
+ uint8 luma = pScan_line[x];
+ pDst[0] = luma;
+ pDst[1] = luma;
+ pDst[2] = luma;
+ pDst[3] = 255;
+ pDst += 4;
+ }
+ }
+ }
+ else if (decoder.get_num_components() == 3)
+ {
+ if (req_comps == 1)
+ {
+ const int YR = 19595, YG = 38470, YB = 7471;
+ for (int x = 0; x < image_width; x++)
+ {
+ int r = pScan_line[x*4+0];
+ int g = pScan_line[x*4+1];
+ int b = pScan_line[x*4+2];
+ *pDst++ = static_cast<uint8>((r * YR + g * YG + b * YB + 32768) >> 16);
+ }
+ }
+ else
+ {
+ for (int x = 0; x < image_width; x++)
+ {
+ pDst[0] = pScan_line[x*4+0];
+ pDst[1] = pScan_line[x*4+1];
+ pDst[2] = pScan_line[x*4+2];
+ pDst += 3;
+ }
+ }
+ }
+ }
+
+ return pImage_data;
+}
+
+unsigned char *decompress_jpeg_image_from_memory(const unsigned char *pSrc_data, int src_data_size, int *width, int *height, int *actual_comps, int req_comps)
+{
+ jpgd::jpeg_decoder_mem_stream mem_stream(pSrc_data, src_data_size);
+ return decompress_jpeg_image_from_stream(&mem_stream, width, height, actual_comps, req_comps);
+}
+
+unsigned char *decompress_jpeg_image_from_file(const char *pSrc_filename, int *width, int *height, int *actual_comps, int req_comps)
+{
+ jpgd::jpeg_decoder_file_stream file_stream;
+ if (!file_stream.open(pSrc_filename))
+ return NULL;
+ return decompress_jpeg_image_from_stream(&file_stream, width, height, actual_comps, req_comps);
+}
+
+} // namespace jpgd \ No newline at end of file
diff --git a/drivers/jpegd/jpgd.h b/drivers/jpegd/jpgd.h
new file mode 100644
index 0000000000..150b9a0b26
--- /dev/null
+++ b/drivers/jpegd/jpgd.h
@@ -0,0 +1,319 @@
+// jpgd.h - C++ class for JPEG decompression.
+// Public domain, Rich Geldreich <richgel99@gmail.com>
+#ifndef JPEG_DECODER_H
+#define JPEG_DECODER_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <setjmp.h>
+
+#ifdef _MSC_VER
+ #define JPGD_NORETURN __declspec(noreturn)
+#elif defined(__GNUC__)
+ #define JPGD_NORETURN __attribute__ ((noreturn))
+#else
+ #define JPGD_NORETURN
+#endif
+
+namespace jpgd
+{
+ typedef unsigned char uint8;
+ typedef signed short int16;
+ typedef unsigned short uint16;
+ typedef unsigned int uint;
+ typedef signed int int32;
+
+ // Loads a JPEG image from a memory buffer or a file.
+ // req_comps can be 1 (grayscale), 3 (RGB), or 4 (RGBA).
+ // On return, width/height will be set to the image's dimensions, and actual_comps will be set to the either 1 (grayscale) or 3 (RGB).
+ // Notes: For more control over where and how the source data is read, see the decompress_jpeg_image_from_stream() function below, or call the jpeg_decoder class directly.
+ // Requesting a 8 or 32bpp image is currently a little faster than 24bpp because the jpeg_decoder class itself currently always unpacks to either 8 or 32bpp.
+ unsigned char *decompress_jpeg_image_from_memory(const unsigned char *pSrc_data, int src_data_size, int *width, int *height, int *actual_comps, int req_comps);
+ unsigned char *decompress_jpeg_image_from_file(const char *pSrc_filename, int *width, int *height, int *actual_comps, int req_comps);
+
+ // Success/failure error codes.
+ enum jpgd_status
+ {
+ JPGD_SUCCESS = 0, JPGD_FAILED = -1, JPGD_DONE = 1,
+ JPGD_BAD_DHT_COUNTS = -256, JPGD_BAD_DHT_INDEX, JPGD_BAD_DHT_MARKER, JPGD_BAD_DQT_MARKER, JPGD_BAD_DQT_TABLE,
+ JPGD_BAD_PRECISION, JPGD_BAD_HEIGHT, JPGD_BAD_WIDTH, JPGD_TOO_MANY_COMPONENTS,
+ JPGD_BAD_SOF_LENGTH, JPGD_BAD_VARIABLE_MARKER, JPGD_BAD_DRI_LENGTH, JPGD_BAD_SOS_LENGTH,
+ JPGD_BAD_SOS_COMP_ID, JPGD_W_EXTRA_BYTES_BEFORE_MARKER, JPGD_NO_ARITHMITIC_SUPPORT, JPGD_UNEXPECTED_MARKER,
+ JPGD_NOT_JPEG, JPGD_UNSUPPORTED_MARKER, JPGD_BAD_DQT_LENGTH, JPGD_TOO_MANY_BLOCKS,
+ JPGD_UNDEFINED_QUANT_TABLE, JPGD_UNDEFINED_HUFF_TABLE, JPGD_NOT_SINGLE_SCAN, JPGD_UNSUPPORTED_COLORSPACE,
+ JPGD_UNSUPPORTED_SAMP_FACTORS, JPGD_DECODE_ERROR, JPGD_BAD_RESTART_MARKER, JPGD_ASSERTION_ERROR,
+ JPGD_BAD_SOS_SPECTRAL, JPGD_BAD_SOS_SUCCESSIVE, JPGD_STREAM_READ, JPGD_NOTENOUGHMEM
+ };
+
+ // Input stream interface.
+ // Derive from this class to read input data from sources other than files or memory. Set m_eof_flag to true when no more data is available.
+ // The decoder is rather greedy: it will keep on calling this method until its internal input buffer is full, or until the EOF flag is set.
+ // It the input stream contains data after the JPEG stream's EOI (end of image) marker it will probably be pulled into the internal buffer.
+ // Call the get_total_bytes_read() method to determine the actual size of the JPEG stream after successful decoding.
+ class jpeg_decoder_stream
+ {
+ public:
+ jpeg_decoder_stream() { }
+ virtual ~jpeg_decoder_stream() { }
+
+ // The read() method is called when the internal input buffer is empty.
+ // Parameters:
+ // pBuf - input buffer
+ // max_bytes_to_read - maximum bytes that can be written to pBuf
+ // pEOF_flag - set this to true if at end of stream (no more bytes remaining)
+ // Returns -1 on error, otherwise return the number of bytes actually written to the buffer (which may be 0).
+ // Notes: This method will be called in a loop until you set *pEOF_flag to true or the internal buffer is full.
+ virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag) = 0;
+ };
+
+ // stdio FILE stream class.
+ class jpeg_decoder_file_stream : public jpeg_decoder_stream
+ {
+ jpeg_decoder_file_stream(const jpeg_decoder_file_stream &);
+ jpeg_decoder_file_stream &operator =(const jpeg_decoder_file_stream &);
+
+ FILE *m_pFile;
+ bool m_eof_flag, m_error_flag;
+
+ public:
+ jpeg_decoder_file_stream();
+ virtual ~jpeg_decoder_file_stream();
+
+ bool open(const char *Pfilename);
+ void close();
+
+ virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag);
+ };
+
+ // Memory stream class.
+ class jpeg_decoder_mem_stream : public jpeg_decoder_stream
+ {
+ const uint8 *m_pSrc_data;
+ uint m_ofs, m_size;
+
+ public:
+ jpeg_decoder_mem_stream() : m_pSrc_data(NULL), m_ofs(0), m_size(0) { }
+ jpeg_decoder_mem_stream(const uint8 *pSrc_data, uint size) : m_pSrc_data(pSrc_data), m_ofs(0), m_size(size) { }
+
+ virtual ~jpeg_decoder_mem_stream() { }
+
+ bool open(const uint8 *pSrc_data, uint size);
+ void close() { m_pSrc_data = NULL; m_ofs = 0; m_size = 0; }
+
+ virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag);
+ };
+
+ // Loads JPEG file from a jpeg_decoder_stream.
+ unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, int *width, int *height, int *actual_comps, int req_comps);
+
+ enum
+ {
+ JPGD_IN_BUF_SIZE = 8192, JPGD_MAX_BLOCKS_PER_MCU = 10, JPGD_MAX_HUFF_TABLES = 8, JPGD_MAX_QUANT_TABLES = 4,
+ JPGD_MAX_COMPONENTS = 4, JPGD_MAX_COMPS_IN_SCAN = 4, JPGD_MAX_BLOCKS_PER_ROW = 8192, JPGD_MAX_HEIGHT = 16384, JPGD_MAX_WIDTH = 16384
+ };
+
+ typedef int16 jpgd_quant_t;
+ typedef int16 jpgd_block_t;
+
+ class jpeg_decoder
+ {
+ public:
+ // Call get_error_code() after constructing to determine if the stream is valid or not. You may call the get_width(), get_height(), etc.
+ // methods after the constructor is called. You may then either destruct the object, or begin decoding the image by calling begin_decoding(), then decode() on each scanline.
+ jpeg_decoder(jpeg_decoder_stream *pStream);
+
+ ~jpeg_decoder();
+
+ // Call this method after constructing the object to begin decompression.
+ // If JPGD_SUCCESS is returned you may then call decode() on each scanline.
+ int begin_decoding();
+
+ // Returns the next scan line.
+ // For grayscale images, pScan_line will point to a buffer containing 8-bit pixels (get_bytes_per_pixel() will return 1).
+ // Otherwise, it will always point to a buffer containing 32-bit RGBA pixels (A will always be 255, and get_bytes_per_pixel() will return 4).
+ // Returns JPGD_SUCCESS if a scan line has been returned.
+ // Returns JPGD_DONE if all scan lines have been returned.
+ // Returns JPGD_FAILED if an error occurred. Call get_error_code() for a more info.
+ int decode(const void** pScan_line, uint* pScan_line_len);
+
+ inline jpgd_status get_error_code() const { return m_error_code; }
+
+ inline int get_width() const { return m_image_x_size; }
+ inline int get_height() const { return m_image_y_size; }
+
+ inline int get_num_components() const { return m_comps_in_frame; }
+
+ inline int get_bytes_per_pixel() const { return m_dest_bytes_per_pixel; }
+ inline int get_bytes_per_scan_line() const { return m_image_x_size * get_bytes_per_pixel(); }
+
+ // Returns the total number of bytes actually consumed by the decoder (which should equal the actual size of the JPEG file).
+ inline int get_total_bytes_read() const { return m_total_bytes_read; }
+
+ private:
+ jpeg_decoder(const jpeg_decoder &);
+ jpeg_decoder &operator =(const jpeg_decoder &);
+
+ typedef void (*pDecode_block_func)(jpeg_decoder *, int, int, int);
+
+ struct huff_tables
+ {
+ bool ac_table;
+ uint look_up[256];
+ uint look_up2[256];
+ uint8 code_size[256];
+ uint tree[512];
+ };
+
+ struct coeff_buf
+ {
+ uint8 *pData;
+ int block_num_x, block_num_y;
+ int block_len_x, block_len_y;
+ int block_size;
+ };
+
+ struct mem_block
+ {
+ mem_block *m_pNext;
+ size_t m_used_count;
+ size_t m_size;
+ char m_data[1];
+ };
+
+ jmp_buf m_jmp_state;
+ mem_block *m_pMem_blocks;
+ int m_image_x_size;
+ int m_image_y_size;
+ jpeg_decoder_stream *m_pStream;
+ int m_progressive_flag;
+ uint8 m_huff_ac[JPGD_MAX_HUFF_TABLES];
+ uint8* m_huff_num[JPGD_MAX_HUFF_TABLES]; // pointer to number of Huffman codes per bit size
+ uint8* m_huff_val[JPGD_MAX_HUFF_TABLES]; // pointer to Huffman codes per bit size
+ jpgd_quant_t* m_quant[JPGD_MAX_QUANT_TABLES]; // pointer to quantization tables
+ int m_scan_type; // Gray, Yh1v1, Yh1v2, Yh2v1, Yh2v2 (CMYK111, CMYK4114 no longer supported)
+ int m_comps_in_frame; // # of components in frame
+ int m_comp_h_samp[JPGD_MAX_COMPONENTS]; // component's horizontal sampling factor
+ int m_comp_v_samp[JPGD_MAX_COMPONENTS]; // component's vertical sampling factor
+ int m_comp_quant[JPGD_MAX_COMPONENTS]; // component's quantization table selector
+ int m_comp_ident[JPGD_MAX_COMPONENTS]; // component's ID
+ int m_comp_h_blocks[JPGD_MAX_COMPONENTS];
+ int m_comp_v_blocks[JPGD_MAX_COMPONENTS];
+ int m_comps_in_scan; // # of components in scan
+ int m_comp_list[JPGD_MAX_COMPS_IN_SCAN]; // components in this scan
+ int m_comp_dc_tab[JPGD_MAX_COMPONENTS]; // component's DC Huffman coding table selector
+ int m_comp_ac_tab[JPGD_MAX_COMPONENTS]; // component's AC Huffman coding table selector
+ int m_spectral_start; // spectral selection start
+ int m_spectral_end; // spectral selection end
+ int m_successive_low; // successive approximation low
+ int m_successive_high; // successive approximation high
+ int m_max_mcu_x_size; // MCU's max. X size in pixels
+ int m_max_mcu_y_size; // MCU's max. Y size in pixels
+ int m_blocks_per_mcu;
+ int m_max_blocks_per_row;
+ int m_mcus_per_row, m_mcus_per_col;
+ int m_mcu_org[JPGD_MAX_BLOCKS_PER_MCU];
+ int m_total_lines_left; // total # lines left in image
+ int m_mcu_lines_left; // total # lines left in this MCU
+ int m_real_dest_bytes_per_scan_line;
+ int m_dest_bytes_per_scan_line; // rounded up
+ int m_dest_bytes_per_pixel; // 4 (RGB) or 1 (Y)
+ huff_tables* m_pHuff_tabs[JPGD_MAX_HUFF_TABLES];
+ coeff_buf* m_dc_coeffs[JPGD_MAX_COMPONENTS];
+ coeff_buf* m_ac_coeffs[JPGD_MAX_COMPONENTS];
+ int m_eob_run;
+ int m_block_y_mcu[JPGD_MAX_COMPONENTS];
+ uint8* m_pIn_buf_ofs;
+ int m_in_buf_left;
+ int m_tem_flag;
+ bool m_eof_flag;
+ uint8 m_in_buf_pad_start[128];
+ uint8 m_in_buf[JPGD_IN_BUF_SIZE + 128];
+ uint8 m_in_buf_pad_end[128];
+ int m_bits_left;
+ uint m_bit_buf;
+ int m_restart_interval;
+ int m_restarts_left;
+ int m_next_restart_num;
+ int m_max_mcus_per_row;
+ int m_max_blocks_per_mcu;
+ int m_expanded_blocks_per_mcu;
+ int m_expanded_blocks_per_row;
+ int m_expanded_blocks_per_component;
+ bool m_freq_domain_chroma_upsample;
+ int m_max_mcus_per_col;
+ uint m_last_dc_val[JPGD_MAX_COMPONENTS];
+ jpgd_block_t* m_pMCU_coefficients;
+ int m_mcu_block_max_zag[JPGD_MAX_BLOCKS_PER_MCU];
+ uint8* m_pSample_buf;
+ int m_crr[256];
+ int m_cbb[256];
+ int m_crg[256];
+ int m_cbg[256];
+ uint8* m_pScan_line_0;
+ uint8* m_pScan_line_1;
+ jpgd_status m_error_code;
+ bool m_ready_flag;
+ int m_total_bytes_read;
+
+ void free_all_blocks();
+ JPGD_NORETURN void stop_decoding(jpgd_status status);
+ void *alloc(size_t n, bool zero = false);
+ void word_clear(void *p, uint16 c, uint n);
+ void prep_in_buffer();
+ void read_dht_marker();
+ void read_dqt_marker();
+ void read_sof_marker();
+ void skip_variable_marker();
+ void read_dri_marker();
+ void read_sos_marker();
+ int next_marker();
+ int process_markers();
+ void locate_soi_marker();
+ void locate_sof_marker();
+ int locate_sos_marker();
+ void init(jpeg_decoder_stream * pStream);
+ void create_look_ups();
+ void fix_in_buffer();
+ void transform_mcu(int mcu_row);
+ void transform_mcu_expand(int mcu_row);
+ coeff_buf* coeff_buf_open(int block_num_x, int block_num_y, int block_len_x, int block_len_y);
+ inline jpgd_block_t *coeff_buf_getp(coeff_buf *cb, int block_x, int block_y);
+ void load_next_row();
+ void decode_next_row();
+ void make_huff_table(int index, huff_tables *pH);
+ void check_quant_tables();
+ void check_huff_tables();
+ void calc_mcu_block_order();
+ int init_scan();
+ void init_frame();
+ void process_restart();
+ void decode_scan(pDecode_block_func decode_block_func);
+ void init_progressive();
+ void init_sequential();
+ void decode_start();
+ void decode_init(jpeg_decoder_stream * pStream);
+ void H2V2Convert();
+ void H2V1Convert();
+ void H1V2Convert();
+ void H1V1Convert();
+ void gray_convert();
+ void expanded_convert();
+ void find_eoi();
+ inline uint get_char();
+ inline uint get_char(bool *pPadding_flag);
+ inline void stuff_char(uint8 q);
+ inline uint8 get_octet();
+ inline uint get_bits(int num_bits);
+ inline uint get_bits_no_markers(int numbits);
+ inline int huff_decode(huff_tables *pH);
+ inline int huff_decode(huff_tables *pH, int& extrabits);
+ static inline uint8 clamp(int i);
+ static void decode_block_dc_first(jpeg_decoder *pD, int component_id, int block_x, int block_y);
+ static void decode_block_dc_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y);
+ static void decode_block_ac_first(jpeg_decoder *pD, int component_id, int block_x, int block_y);
+ static void decode_block_ac_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y);
+ };
+
+} // namespace jpgd
+
+#endif // JPEG_DECODER_H
diff --git a/drivers/jpg/image_loader_jpg.cpp b/drivers/jpg/image_loader_jpg.cpp
deleted file mode 100644
index 76a8b25f62..0000000000
--- a/drivers/jpg/image_loader_jpg.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*************************************************/
-/* image_loader_jpg.cpp */
-/*************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/*************************************************/
-/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
-/* All Rights Reserved. */
-/*************************************************/
-
-#include "image_loader_jpg.h"
-
-#include "print_string.h"
-#include "os/os.h"
-#include "drivers/jpg/tinyjpeg.h"
-
-
-static void* _tinyjpg_alloc(unsigned int amount) {
-
- return memalloc(amount);
-}
-
-static void _tinyjpg_free(void *ptr) {
-
- memfree(ptr);
-}
-
-Error ImageLoaderJPG::load_image(Image *p_image,FileAccess *f) {
-
-
- DVector<uint8_t> src_image;
- int src_image_len = f->get_len();
- ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);
- src_image.resize(src_image_len);
-
- DVector<uint8_t>::Write w = src_image.write();
-
- f->get_buffer(&w[0],src_image_len);
-
- f->close();
-
- jdec_private* jdec=tinyjpeg_init(_tinyjpg_alloc,_tinyjpg_free);
- ERR_FAIL_COND_V(!jdec,ERR_UNAVAILABLE);
-
- int ret = tinyjpeg_parse_header(jdec,&w[0],src_image_len);
-
- if (ret!=0) {
- tinyjpeg_free(jdec);
- }
-
- ERR_FAIL_COND_V(ret!=0,ERR_FILE_CORRUPT);
-
- unsigned int width,height;
-
-
- tinyjpeg_get_size(jdec,&width,&height);
-
-
-
- DVector<uint8_t> imgdata;
- imgdata.resize(width*height*3);
- DVector<uint8_t>::Write imgdataw = imgdata.write();
-
-
- unsigned char *components[1]={&imgdataw[0]};
- tinyjpeg_set_components(jdec,components,1);
- tinyjpeg_decode(jdec,TINYJPEG_FMT_RGB24);
- imgdataw = DVector<uint8_t>::Write();
-
- Image dst_image(width,height,0,Image::FORMAT_RGB,imgdata);
-
- tinyjpeg_free(jdec);
-
- *p_image=dst_image;
-
- return OK;
-
-}
-
-void ImageLoaderJPG::get_recognized_extensions(List<String> *p_extensions) const {
-
- p_extensions->push_back("jpg");
- p_extensions->push_back("jpeg");
-}
-
-
-ImageLoaderJPG::ImageLoaderJPG() {
-
-
-}
-
-
diff --git a/drivers/jpg/jidctflt.c b/drivers/jpg/jidctflt.c
deleted file mode 100644
index 40a9eab83e..0000000000
--- a/drivers/jpg/jidctflt.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * jidctflt.c
- *
- * Copyright (C) 1994-1998, Thomas G. Lane.
- * This file is part of the Independent JPEG Group's software.
- *
- * The authors make NO WARRANTY or representation, either express or implied,
- * with respect to this software, its quality, accuracy, merchantability, or
- * fitness for a particular purpose. This software is provided "AS IS", and you,
- * its user, assume the entire risk as to its quality and accuracy.
- *
- * This software is copyright (C) 1991-1998, Thomas G. Lane.
- * All Rights Reserved except as specified below.
- *
- * Permission is hereby granted to use, copy, modify, and distribute this
- * software (or portions thereof) for any purpose, without fee, subject to these
- * conditions:
- * (1) If any part of the source code for this software is distributed, then this
- * README file must be included, with this copyright and no-warranty notice
- * unaltered; and any additions, deletions, or changes to the original files
- * must be clearly indicated in accompanying documentation.
- * (2) If only executable code is distributed, then the accompanying
- * documentation must state that "this software is based in part on the work of
- * the Independent JPEG Group".
- * (3) Permission for use of this software is granted only if the user accepts
- * full responsibility for any undesirable consequences; the authors accept
- * NO LIABILITY for damages of any kind.
- *
- * These conditions apply to any software derived from or based on the IJG code,
- * not just to the unmodified library. If you use our work, you ought to
- * acknowledge us.
- *
- * Permission is NOT granted for the use of any IJG author's name or company name
- * in advertising or publicity relating to this software or products derived from
- * it. This software may be referred to only as "the Independent JPEG Group's
- * software".
- *
- * We specifically permit and encourage the use of this software as the basis of
- * commercial products, provided that all warranty or liability claims are
- * assumed by the product vendor.
- *
- *
- * This file contains a floating-point implementation of the
- * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
- * must also perform dequantization of the input coefficients.
- *
- * This implementation should be more accurate than either of the integer
- * IDCT implementations. However, it may not give the same results on all
- * machines because of differences in roundoff behavior. Speed will depend
- * on the hardware's floating point capacity.
- *
- * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
- * on each row (or vice versa, but it's more convenient to emit a row at
- * a time). Direct algorithms are also available, but they are much more
- * complex and seem not to be any faster when reduced to code.
- *
- * This implementation is based on Arai, Agui, and Nakajima's algorithm for
- * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
- * Japanese, but the algorithm is described in the Pennebaker & Mitchell
- * JPEG textbook (see REFERENCES section in file README). The following code
- * is based directly on figure 4-8 in P&M.
- * While an 8-point DCT cannot be done in less than 11 multiplies, it is
- * possible to arrange the computation so that many of the multiplies are
- * simple scalings of the final outputs. These multiplies can then be
- * folded into the multiplications or divisions by the JPEG quantization
- * table entries. The AA&N method leaves only 5 multiplies and 29 adds
- * to be done in the DCT itself.
- * The primary disadvantage of this method is that with a fixed-point
- * implementation, accuracy is lost due to imprecise representation of the
- * scaled quantization values. However, that problem does not arise if
- * we use floating point arithmetic.
- */
-
-#include "tinyjpeg-internal.h"
-
-#define FAST_FLOAT float
-#define DCTSIZE 8
-#define DCTSIZE2 (DCTSIZE*DCTSIZE)
-
-#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval))
-
-#if 0 && defined(__GNUC__) && (defined(__i686__))
-// || defined(__x86_64__))
-
-static inline unsigned char descale_and_clamp(int x, int shift)
-{
- __asm__ (
- "add %3,%1\n"
- "\tsar %2,%1\n"
- "\tsub $-128,%1\n"
- "\tcmovl %5,%1\n" /* Use the sub to compare to 0 */
- "\tcmpl %4,%1\n"
- "\tcmovg %4,%1\n"
- : "=r"(x)
- : "0"(x), "Ir"(shift), "ir"(1UL<<(shift-1)), "r" (0xff), "r" (0)
- );
- return x;
-}
-
-#else
-static __inline unsigned char descale_and_clamp(int x, int shift)
-{
- x += (1UL<<(shift-1));
- if (x<0)
- x = (x >> shift) | ((~(0UL)) << (32-(shift)));
- else
- x >>= shift;
- x += 128;
- if (x>255)
- return 255;
- else if (x<0)
- return 0;
- else
- return x;
-}
-#endif
-
-/*
- * Perform dequantization and inverse DCT on one block of coefficients.
- */
-
-void
-tinyjpeg_idct_float (struct component *compptr, uint8_t *output_buf, int stride)
-{
- FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
- FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
- FAST_FLOAT z5, z10, z11, z12, z13;
- int16_t *inptr;
- FAST_FLOAT *quantptr;
- FAST_FLOAT *wsptr;
- uint8_t *outptr;
- int ctr;
- FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */
-
- /* Pass 1: process columns from input, store into work array. */
-
- inptr = compptr->DCT;
- quantptr = compptr->Q_table;
- wsptr = workspace;
- for (ctr = DCTSIZE; ctr > 0; ctr--) {
- /* Due to quantization, we will usually find that many of the input
- * coefficients are zero, especially the AC terms. We can exploit this
- * by short-circuiting the IDCT calculation for any column in which all
- * the AC terms are zero. In that case each output is equal to the
- * DC coefficient (with scale factor as needed).
- * With typical images and quantization tables, half or more of the
- * column DCT calculations can be simplified this way.
- */
-
- if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
- inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
- inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
- inptr[DCTSIZE*7] == 0) {
- /* AC terms all zero */
- FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
-
- wsptr[DCTSIZE*0] = dcval;
- wsptr[DCTSIZE*1] = dcval;
- wsptr[DCTSIZE*2] = dcval;
- wsptr[DCTSIZE*3] = dcval;
- wsptr[DCTSIZE*4] = dcval;
- wsptr[DCTSIZE*5] = dcval;
- wsptr[DCTSIZE*6] = dcval;
- wsptr[DCTSIZE*7] = dcval;
-
- inptr++; /* advance pointers to next column */
- quantptr++;
- wsptr++;
- continue;
- }
-
- /* Even part */
-
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
- tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
- tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
-
- tmp10 = tmp0 + tmp2; /* phase 3 */
- tmp11 = tmp0 - tmp2;
-
- tmp13 = tmp1 + tmp3; /* phases 5-3 */
- tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */
-
- tmp0 = tmp10 + tmp13; /* phase 2 */
- tmp3 = tmp10 - tmp13;
- tmp1 = tmp11 + tmp12;
- tmp2 = tmp11 - tmp12;
-
- /* Odd part */
-
- tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
-
- z13 = tmp6 + tmp5; /* phase 6 */
- z10 = tmp6 - tmp5;
- z11 = tmp4 + tmp7;
- z12 = tmp4 - tmp7;
-
- tmp7 = z11 + z13; /* phase 5 */
- tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */
-
- z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
- tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
- tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
-
- tmp6 = tmp12 - tmp7; /* phase 2 */
- tmp5 = tmp11 - tmp6;
- tmp4 = tmp10 + tmp5;
-
- wsptr[DCTSIZE*0] = tmp0 + tmp7;
- wsptr[DCTSIZE*7] = tmp0 - tmp7;
- wsptr[DCTSIZE*1] = tmp1 + tmp6;
- wsptr[DCTSIZE*6] = tmp1 - tmp6;
- wsptr[DCTSIZE*2] = tmp2 + tmp5;
- wsptr[DCTSIZE*5] = tmp2 - tmp5;
- wsptr[DCTSIZE*4] = tmp3 + tmp4;
- wsptr[DCTSIZE*3] = tmp3 - tmp4;
-
- inptr++; /* advance pointers to next column */
- quantptr++;
- wsptr++;
- }
-
- /* Pass 2: process rows from work array, store into output array. */
- /* Note that we must descale the results by a factor of 8 == 2**3. */
-
- wsptr = workspace;
- outptr = output_buf;
- for (ctr = 0; ctr < DCTSIZE; ctr++) {
- /* Rows of zeroes can be exploited in the same way as we did with columns.
- * However, the column calculation has created many nonzero AC terms, so
- * the simplification applies less often (typically 5% to 10% of the time).
- * And testing floats for zero is relatively expensive, so we don't bother.
- */
-
- /* Even part */
-
- tmp10 = wsptr[0] + wsptr[4];
- tmp11 = wsptr[0] - wsptr[4];
-
- tmp13 = wsptr[2] + wsptr[6];
- tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13;
-
- tmp0 = tmp10 + tmp13;
- tmp3 = tmp10 - tmp13;
- tmp1 = tmp11 + tmp12;
- tmp2 = tmp11 - tmp12;
-
- /* Odd part */
-
- z13 = wsptr[5] + wsptr[3];
- z10 = wsptr[5] - wsptr[3];
- z11 = wsptr[1] + wsptr[7];
- z12 = wsptr[1] - wsptr[7];
-
- tmp7 = z11 + z13;
- tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562);
-
- z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
- tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
- tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
-
- tmp6 = tmp12 - tmp7;
- tmp5 = tmp11 - tmp6;
- tmp4 = tmp10 + tmp5;
-
- /* Final output stage: scale down by a factor of 8 and range-limit */
-
- outptr[0] = descale_and_clamp((int)(tmp0 + tmp7), 3);
- outptr[7] = descale_and_clamp((int)(tmp0 - tmp7), 3);
- outptr[1] = descale_and_clamp((int)(tmp1 + tmp6), 3);
- outptr[6] = descale_and_clamp((int)(tmp1 - tmp6), 3);
- outptr[2] = descale_and_clamp((int)(tmp2 + tmp5), 3);
- outptr[5] = descale_and_clamp((int)(tmp2 - tmp5), 3);
- outptr[4] = descale_and_clamp((int)(tmp3 + tmp4), 3);
- outptr[3] = descale_and_clamp((int)(tmp3 - tmp4), 3);
-
-
- wsptr += DCTSIZE; /* advance pointer to next row */
- outptr += stride;
- }
-}
-
diff --git a/drivers/jpg/loadjpeg.c b/drivers/jpg/loadjpeg.c
deleted file mode 100644
index 82072d4272..0000000000
--- a/drivers/jpg/loadjpeg.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Small jpeg decoder library - testing application
- *
- * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the author nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "tinyjpeg.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#define snprintf(buf, size, fmt, ...) sprintf(buf, fmt, __VA_ARGS__)
-
-static void exitmessage(const char *message) __attribute__((noreturn));
-static void exitmessage(const char *message)
-{
- printf("%s\n", message);
- exit(0);
-}
-
-static int filesize(FILE *fp)
-{
- long pos;
- fseek(fp, 0, SEEK_END);
- pos = ftell(fp);
- fseek(fp, 0, SEEK_SET);
- return pos;
-}
-
-/**
- * Save a buffer in 24bits Targa format
- * (BGR byte order)
- */
-static void write_tga(const char *filename, int output_format, int width, int height, unsigned char **components)
-{
- unsigned char targaheader[18];
- FILE *F;
- char temp[1024];
- unsigned int bufferlen = width * height * 3;
- unsigned char *rgb_data = components[0];
-
- sprintf(temp, sizeof(temp), filename);
-
- memset(targaheader,0,sizeof(targaheader));
-
- targaheader[12] = (unsigned char) (width & 0xFF);
- targaheader[13] = (unsigned char) (width >> 8);
- targaheader[14] = (unsigned char) (height & 0xFF);
- targaheader[15] = (unsigned char) (height >> 8);
- targaheader[17] = 0x20; /* Top-down, non-interlaced */
- targaheader[2] = 2; /* image type = uncompressed RGB */
- targaheader[16] = 24;
-
- if (output_format == TINYJPEG_FMT_RGB24)
- {
- unsigned char *data = rgb_data + bufferlen - 3;
- do
- {
- unsigned char c = data[0];
- data[0] = data[2];
- data[2] = c;
- data-=3;
- }
- while (data > rgb_data);
- }
-
- F = fopen(temp, "wb");
- fwrite(targaheader, sizeof(targaheader), 1, F);
- fwrite(rgb_data, 1, bufferlen, F);
- fclose(F);
-}
-
-/**
- * Save a buffer in three files (.Y, .U, .V) useable by yuvsplittoppm
- */
-static void write_yuv(const char *filename, int width, int height, unsigned char **components)
-{
- FILE *F;
- char temp[1024];
-
- snprintf(temp, 1024, "%s.Y", filename);
- F = fopen(temp, "wb");
- fwrite(components[0], width, height, F);
- fclose(F);
- snprintf(temp, 1024, "%s.U", filename);
- F = fopen(temp, "wb");
- fwrite(components[1], width*height/4, 1, F);
- fclose(F);
- snprintf(temp, 1024, "%s.V", filename);
- F = fopen(temp, "wb");
- fwrite(components[2], width*height/4, 1, F);
- fclose(F);
-}
-
-/**
- * Save a buffer in grey image (pgm format)
- */
-static void write_pgm(const char *filename, int width, int height, unsigned char **components)
-{
- FILE *F;
- char temp[1024];
-
- snprintf(temp, 1024, "%s", filename);
- F = fopen(temp, "wb");
- fprintf(F, "P5\n%d %d\n255\n", width, height);
- fwrite(components[0], width, height, F);
- fclose(F);
-}
-
-/**
- * Load one jpeg image, and try to decompress 1000 times, and save the result.
- * This is mainly used for benchmarking the decoder, or to test if between each
- * called of the library the DCT is corrected reset (a bug was found).
- */
-int load_multiple_times(const char *filename, const char *outfilename, int output_format)
-{
- FILE *fp;
- int count, length_of_file;
- unsigned int width, height;
- unsigned char *buf;
- struct jdec_private *jdec;
- unsigned char *components[4];
-
- jdec = tinyjpeg_init();
- count = 0;
-
- /* Load the Jpeg into memory */
- fp = fopen(filename, "rb");
- if (fp == NULL)
- exitmessage("Cannot open filename\n");
- length_of_file = filesize(fp);
- buf = (unsigned char *)malloc(length_of_file + 4);
- fread(buf, length_of_file, 1, fp);
- fclose(fp);
-
- while (count<1000)
- {
- if (tinyjpeg_parse_header(jdec, buf, length_of_file)<0)
- exitmessage(tinyjpeg_get_errorstring(jdec));
-
- tinyjpeg_decode(jdec, output_format);
-
- count++;
- }
-
- /*
- * Get address for each plane (not only max 3 planes is supported), and
- * depending of the output mode, only some components will be filled
- * RGB: 1 plane, YUV420P: 3 planes, GREY: 1 plane
- */
- tinyjpeg_get_components(jdec, components);
- tinyjpeg_get_size(jdec, &width, &height);
-
- /* Save it */
- switch (output_format)
- {
- case TINYJPEG_FMT_RGB24:
- case TINYJPEG_FMT_BGR24:
- write_tga(outfilename, output_format, width, height, components);
- break;
- case TINYJPEG_FMT_YUV420P:
- write_yuv(outfilename, width, height, components);
- break;
- case TINYJPEG_FMT_GREY:
- write_pgm(outfilename, width, height, components);
- break;
- }
-
- free(buf);
- tinyjpeg_free(jdec);
- return 0;
-}
-
-/**
- * Load one jpeg image, and decompress it, and save the result.
- */
-int convert_one_image(const char *infilename, const char *outfilename, int output_format)
-{
- FILE *fp;
- unsigned int length_of_file;
- unsigned int width, height;
- unsigned char *buf;
- struct jdec_private *jdec;
- unsigned char *components[3];
-
- /* Load the Jpeg into memory */
- fp = fopen(infilename, "rb");
- if (fp == NULL)
- exitmessage("Cannot open filename\n");
- length_of_file = filesize(fp);
- buf = (unsigned char *)malloc(length_of_file + 4);
- if (buf == NULL)
- exitmessage("Not enough memory for loading file\n");
- fread(buf, length_of_file, 1, fp);
- fclose(fp);
-
- /* Decompress it */
- jdec = tinyjpeg_init();
- if (jdec == NULL)
- exitmessage("Not enough memory to alloc the structure need for decompressing\n");
-
- if (tinyjpeg_parse_header(jdec, buf, length_of_file)<0)
- exitmessage(tinyjpeg_get_errorstring(jdec));
-
- /* Get the size of the image */
- tinyjpeg_get_size(jdec, &width, &height);
-
- printf("Decoding JPEG image...\n");
- if (tinyjpeg_decode(jdec, output_format) < 0)
- exitmessage(tinyjpeg_get_errorstring(jdec));
-
- /*
- * Get address for each plane (not only max 3 planes is supported), and
- * depending of the output mode, only some components will be filled
- * RGB: 1 plane, YUV420P: 3 planes, GREY: 1 plane
- */
- tinyjpeg_get_components(jdec, components);
-
- /* Save it */
- switch (output_format)
- {
- case TINYJPEG_FMT_RGB24:
- case TINYJPEG_FMT_BGR24:
- write_tga(outfilename, output_format, width, height, components);
- break;
- case TINYJPEG_FMT_YUV420P:
- write_yuv(outfilename, width, height, components);
- break;
- case TINYJPEG_FMT_GREY:
- write_pgm(outfilename, width, height, components);
- break;
- }
-
- /* Only called this if the buffers were allocated by tinyjpeg_decode() */
- tinyjpeg_free(jdec);
- /* else called just free(jdec); */
-
- free(buf);
- return 0;
-}
-
-static void usage(void)
-{
- fprintf(stderr, "Usage: loadjpeg [options] <input_filename.jpeg> <format> <output_filename>\n");
- fprintf(stderr, "options:\n");
- fprintf(stderr, " --benchmark - Convert 1000 times the same image\n");
- fprintf(stderr, "format:\n");
- fprintf(stderr, " yuv420p - output 3 files .Y,.U,.V\n");
- fprintf(stderr, " rgb24 - output a .tga image\n");
- fprintf(stderr, " bgr24 - output a .tga image\n");
- fprintf(stderr, " gray - output a .pgm image\n");
- exit(1);
-}
-
-/**
- * main
- *
- */
-int main(int argc, char *argv[])
-{
- int output_format = TINYJPEG_FMT_YUV420P;
- char *output_filename, *input_filename;
- clock_t start_time, finish_time;
- unsigned int duration;
- int current_argument;
- int benchmark_mode = 0;
-
- if (argc < 3)
- usage();
-
- current_argument = 1;
- while (1)
- {
- if (strcmp(argv[current_argument], "--benchmark")==0)
- benchmark_mode = 1;
- else
- break;
- current_argument++;
- }
-
- if (argc < current_argument+2)
- usage();
-
- input_filename = argv[current_argument];
- if (strcmp(argv[current_argument+1],"yuv420p")==0)
- output_format = TINYJPEG_FMT_YUV420P;
- else if (strcmp(argv[current_argument+1],"rgb24")==0)
- output_format = TINYJPEG_FMT_RGB24;
- else if (strcmp(argv[current_argument+1],"bgr24")==0)
- output_format = TINYJPEG_FMT_BGR24;
- else if (strcmp(argv[current_argument+1],"grey")==0)
- output_format = TINYJPEG_FMT_GREY;
- else
- exitmessage("Bad format: need to be one of yuv420p, rgb24, bgr24, grey\n");
- output_filename = argv[current_argument+2];
-
- start_time = clock();
-
- if (benchmark_mode)
- load_multiple_times(input_filename, output_filename, output_format);
- else
- convert_one_image(input_filename, output_filename, output_format);
-
- finish_time = clock();
- duration = finish_time - start_time;
- printf("Decoding finished in %u ticks\n", duration);
-
- return 0;
-}
-
-
-
-
diff --git a/drivers/jpg/tinyjpeg-internal.h b/drivers/jpg/tinyjpeg-internal.h
deleted file mode 100644
index b2d5fe42aa..0000000000
--- a/drivers/jpg/tinyjpeg-internal.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Small jpeg decoder library (Internal header)
- *
- * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the author nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#ifndef __TINYJPEG_INTERNAL_H_
-#define __TINYJPEG_INTERNAL_H_
-
-#ifdef _MSC_VER
-
-typedef signed __int8 int8_t;
-typedef unsigned __int8 uint8_t;
-typedef signed __int16 int16_t;
-typedef unsigned __int16 uint16_t;
-typedef signed __int32 int32_t;
-typedef unsigned __int32 uint32_t;
-typedef signed __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-
-#else
-
-#ifdef NO_STDINT_H
-typedef unsigned char uint8_t;
-typedef signed char int8_t;
-typedef unsigned short uint16_t;
-typedef signed short int16_t;
-typedef unsigned int uint32_t;
-typedef signed int int32_t;
-typedef long long int64_t;
-typedef unsigned long long int64_t;
-#else
-#include <stdint.h>
-#endif
-#endif
-
-
-#include <setjmp.h>
-
-#define SANITY_CHECK 1
-
-struct jdec_private;
-
-#define HUFFMAN_BITS_SIZE 256
-#define HUFFMAN_HASH_NBITS 9
-#define HUFFMAN_HASH_SIZE (1UL<<HUFFMAN_HASH_NBITS)
-#define HUFFMAN_HASH_MASK (HUFFMAN_HASH_SIZE-1)
-
-#define HUFFMAN_TABLES 4
-#define COMPONENTS 3
-#define JPEG_MAX_WIDTH 4096
-#define JPEG_MAX_HEIGHT 4096
-
-struct huffman_table
-{
- /* Fast look up table, using HUFFMAN_HASH_NBITS bits we can have directly the symbol,
- * if the symbol is <0, then we need to look into the tree table */
- short int lookup[HUFFMAN_HASH_SIZE];
- /* code size: give the number of bits of a symbol is encoded */
- unsigned char code_size[HUFFMAN_HASH_SIZE];
- /* some place to store value that is not encoded in the lookup table
- * FIXME: Calculate if 256 value is enough to store all values
- */
- uint16_t slowtable[16-HUFFMAN_HASH_NBITS][256];
-};
-
-struct component
-{
- unsigned int Hfactor;
- unsigned int Vfactor;
- float *Q_table; /* Pointer to the quantisation table to use */
- struct huffman_table *AC_table;
- struct huffman_table *DC_table;
- short int previous_DC; /* Previous DC coefficient */
- short int DCT[64]; /* DCT coef */
-#if SANITY_CHECK
- unsigned int cid;
-#endif
-};
-
-
-typedef void (*decode_MCU_fct) (struct jdec_private *priv);
-typedef void (*convert_colorspace_fct) (struct jdec_private *priv);
-
-struct jdec_private
-{
- void *(*allocate_mem)(unsigned int amount);
- void (*free_mem)(void *mem);
-
- /* Public variables */
- uint8_t *components[COMPONENTS];
- unsigned int width, height; /* Size of the image */
- unsigned int flags;
-
- /* Private variables */
- const unsigned char *stream_begin, *stream_end;
- unsigned int stream_length;
-
- const unsigned char *stream; /* Pointer to the current stream */
- unsigned int reservoir, nbits_in_reservoir;
-
- struct component component_infos[COMPONENTS];
- float Q_tables[COMPONENTS][64]; /* quantization tables */
- struct huffman_table HTDC[HUFFMAN_TABLES]; /* DC huffman tables */
- struct huffman_table HTAC[HUFFMAN_TABLES]; /* AC huffman tables */
- int default_huffman_table_initialized;
- int restart_interval;
- int restarts_to_go; /* MCUs left in this restart interval */
- int last_rst_marker_seen; /* Rst marker is incremented each time */
-
- /* Temp space used after the IDCT to store each components */
- uint8_t Y[64*4], Cr[64], Cb[64];
-
- jmp_buf jump_state;
- /* Internal Pointer use for colorspace conversion, do not modify it !!! */
- uint8_t *plane[COMPONENTS];
-
- uint8_t decomp_block[16][16*3];
-
-};
-
-#if defined(__GNUC__) && (__GNUC__ > 3) && defined(__OPTIMIZE__)
-#define __likely(x) __builtin_expect(!!(x), 1)
-#define __unlikely(x) __builtin_expect(!!(x), 0)
-#else
-#define __likely(x) (x)
-#define __unlikely(x) (x)
-#endif
-
-#define IDCT tinyjpeg_idct_float
-void tinyjpeg_idct_float (struct component *compptr, uint8_t *output_buf, int stride);
-
-#endif
-
diff --git a/drivers/jpg/tinyjpeg.c b/drivers/jpg/tinyjpeg.c
deleted file mode 100644
index 8e3c934ce0..0000000000
--- a/drivers/jpg/tinyjpeg.c
+++ /dev/null
@@ -1,2202 +0,0 @@
-/*
- * Small jpeg decoder library
- *
- * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the author nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <errno.h>
-
-#include "tinyjpeg.h"
-#include "tinyjpeg-internal.h"
-
-enum std_markers {
- DQT = 0xDB, /* Define Quantization Table */
- SOF = 0xC0, /* Start of Frame (size information) */
- DHT = 0xC4, /* Huffman Table */
- SOI = 0xD8, /* Start of Image */
- SOS = 0xDA, /* Start of Scan */
- RST = 0xD0, /* Reset Marker d0 -> .. */
- RST7 = 0xD7, /* Reset Marker .. -> d7 */
- EOI = 0xD9, /* End of Image */
- DRI = 0xDD, /* Define Restart Interval */
- APP0 = 0xE0,
-};
-
-#define cY 0
-#define cCb 1
-#define cCr 2
-
-#define BLACK_Y 0
-#define BLACK_U 127
-#define BLACK_V 127
-
-#if DEBUG
-#define trace(fmt, args...) do { \
- fprintf(stderr, fmt, ## args); \
- fflush(stderr); \
-} while(0)
-#else
-#define trace(fmt, ...) do { } while (0)
-#endif
-
-#define error(fmt, ...) do { \
- sprintf(error_string, fmt, ## __VA_ARGS__); \
- return -1; \
-} while(0)
-
-
-#if 0
-static char *print_bits(unsigned int value, char *bitstr)
-{
- int i, j;
- i=31;
- while (i>0)
- {
- if (value & (1UL<<i))
- break;
- i--;
- }
- j=0;
- while (i>=0)
- {
- bitstr[j++] = (value & (1UL<<i))?'1':'0';
- i--;
- }
- bitstr[j] = 0;
- return bitstr;
-}
-
-static void print_next_16bytes(int offset, const unsigned char *stream)
-{
- trace("%4.4x: %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
- offset,
- stream[0], stream[1], stream[2], stream[3],
- stream[4], stream[5], stream[6], stream[7],
- stream[8], stream[9], stream[10], stream[11],
- stream[12], stream[13], stream[14], stream[15]);
-}
-
-#endif
-
-/* Global variable to return the last error found while deconding */
-static char error_string[256];
-
-static const unsigned char zigzag[64] =
-{
- 0, 1, 5, 6, 14, 15, 27, 28,
- 2, 4, 7, 13, 16, 26, 29, 42,
- 3, 8, 12, 17, 25, 30, 41, 43,
- 9, 11, 18, 24, 31, 40, 44, 53,
- 10, 19, 23, 32, 39, 45, 52, 54,
- 20, 22, 33, 38, 46, 51, 55, 60,
- 21, 34, 37, 47, 50, 56, 59, 61,
- 35, 36, 48, 49, 57, 58, 62, 63
-};
-
-/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
-/* IMPORTANT: these are only valid for 8-bit data precision! */
-static const unsigned char bits_dc_luminance[17] =
-{
- 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
-};
-static const unsigned char val_dc_luminance[] =
-{
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
-};
-
-static const unsigned char bits_dc_chrominance[17] =
-{
- 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
-};
-static const unsigned char val_dc_chrominance[] =
-{
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
-};
-
-static const unsigned char bits_ac_luminance[17] =
-{
- 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
-};
-static const unsigned char val_ac_luminance[] =
-{
- 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
- 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
- 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
- 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
- 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
- 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
- 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
- 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
- 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
- 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
- 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
- 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
- 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
- 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
- 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
- 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
- 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
- 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
- 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa
-};
-
-static const unsigned char bits_ac_chrominance[17] =
-{
- 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77
-};
-
-static const unsigned char val_ac_chrominance[] =
-{
- 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
- 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
- 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
- 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
- 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
- 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
- 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
- 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
- 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
- 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
- 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
- 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
- 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
- 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
- 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
- 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
- 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
- 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
- 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
- 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa
-};
-
-
-/*
- * 4 functions to manage the stream
- *
- * fill_nbits: put at least nbits in the reservoir of bits.
- * But convert any 0xff,0x00 into 0xff
- * get_nbits: read nbits from the stream, and put it in result,
- * bits is removed from the stream and the reservoir is filled
- * automaticaly. The result is signed according to the number of
- * bits.
- * look_nbits: read nbits from the stream without marking as read.
- * skip_nbits: read nbits from the stream but do not return the result.
- *
- * stream: current pointer in the jpeg data (read bytes per bytes)
- * nbits_in_reservoir: number of bits filled into the reservoir
- * reservoir: register that contains bits information. Only nbits_in_reservoir
- * is valid.
- * nbits_in_reservoir
- * <-- 17 bits -->
- * Ex: 0000 0000 1010 0000 1111 0000 <== reservoir
- * ^
- * bit 1
- * To get two bits from this example
- * result = (reservoir >> 15) & 3
- *
- */
-#define fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \
- while (nbits_in_reservoir<nbits_wanted) \
- { \
- unsigned char c; \
- if (stream >= priv->stream_end) \
- longjmp(priv->jump_state, -EIO); \
- c = *stream++; \
- reservoir <<= 8; \
- if (c == 0xff && *stream == 0x00) \
- stream++; \
- reservoir |= c; \
- nbits_in_reservoir+=8; \
- } \
-} while(0);
-
-/* Signed version !!!! */
-#define get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \
- fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \
- result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \
- nbits_in_reservoir -= (nbits_wanted); \
- reservoir &= ((1U<<nbits_in_reservoir)-1); \
- if ((unsigned int)result < (1UL<<((nbits_wanted)-1))) \
- result += (0xFFFFFFFFUL<<(nbits_wanted))+1; \
-} while(0);
-
-#define look_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \
- fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \
- result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \
-} while(0);
-
-/* To speed up the decoding, we assume that the reservoir have enough bit
- * slow version:
- * #define skip_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \
- * fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \
- * nbits_in_reservoir -= (nbits_wanted); \
- * reservoir &= ((1U<<nbits_in_reservoir)-1); \
- * } while(0);
- */
-#define skip_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \
- nbits_in_reservoir -= (nbits_wanted); \
- reservoir &= ((1U<<nbits_in_reservoir)-1); \
-} while(0);
-
-
-#define be16_to_cpu(x) (((x)[0]<<8)|(x)[1])
-
-static void resync(struct jdec_private *priv);
-
-/**
- * Get the next (valid) huffman code in the stream.
- *
- * To speedup the procedure, we look HUFFMAN_HASH_NBITS bits and the code is
- * lower than HUFFMAN_HASH_NBITS we have automaticaly the length of the code
- * and the value by using two lookup table.
- * Else if the value is not found, just search (linear) into an array for each
- * bits is the code is present.
- *
- * If the code is not present for any reason, -1 is return.
- */
-static int get_next_huffman_code(struct jdec_private *priv, struct huffman_table *huffman_table)
-{
- int value, hcode;
- unsigned int extra_nbits, nbits;
- uint16_t *slowtable;
-
- look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, HUFFMAN_HASH_NBITS, hcode);
- value = huffman_table->lookup[hcode];
- if (__likely(value >= 0))
- {
- unsigned int code_size = huffman_table->code_size[value];
- skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, code_size);
- return value;
- }
-
- /* Decode more bits each time ... */
- for (extra_nbits=0; extra_nbits<16-HUFFMAN_HASH_NBITS; extra_nbits++)
- {
- nbits = HUFFMAN_HASH_NBITS + 1 + extra_nbits;
-
- look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits, hcode);
- slowtable = huffman_table->slowtable[extra_nbits];
- /* Search if the code is in this array */
- while (slowtable[0]) {
- if (slowtable[0] == hcode) {
- skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits);
- return slowtable[1];
- }
- slowtable+=2;
- }
- }
- return 0;
-}
-
-
-
-
-/**
- *
- * Decode a single block that contains the DCT coefficients.
- * The table coefficients is already dezigzaged at the end of the operation.
- *
- */
-static void process_Huffman_data_unit(struct jdec_private *priv, int component)
-{
- unsigned char j;
- unsigned int huff_code;
- unsigned char size_val, count_0;
-
- struct component *c = &priv->component_infos[component];
- short int DCT[64];
-
-
- /* Initialize the DCT coef table */
- memset(DCT, 0, sizeof(DCT));
-
- /* DC coefficient decoding */
- huff_code = get_next_huffman_code(priv, c->DC_table);
- //trace("+ %x\n", huff_code);
- if (huff_code) {
- get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, huff_code, DCT[0]);
- DCT[0] += c->previous_DC;
- c->previous_DC = DCT[0];
- } else {
- DCT[0] = c->previous_DC;
- }
-
- /* AC coefficient decoding */
- j = 1;
- while (j<64)
- {
- huff_code = get_next_huffman_code(priv, c->AC_table);
- //trace("- %x\n", huff_code);
-
- size_val = huff_code & 0xF;
- count_0 = huff_code >> 4;
-
- if (size_val == 0)
- { /* RLE */
- if (count_0 == 0)
- break; /* EOB found, go out */
- else if (count_0 == 0xF)
- j += 16; /* skip 16 zeros */
- }
- else
- {
- j += count_0; /* skip count_0 zeroes */
- if (__unlikely(j >= 64))
- {
- sprintf(error_string, "Bad huffman data (buffer overflow)");
- break;
- }
- get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, size_val, DCT[j]);
- j++;
- }
- }
-
- for (j = 0; j < 64; j++)
- c->DCT[j] = DCT[zigzag[j]];
-}
-
-/*
- * Takes two array of bits, and build the huffman table for size, and code
- *
- * lookup will return the symbol if the code is less or equal than HUFFMAN_HASH_NBITS.
- * code_size will be used to known how many bits this symbol is encoded.
- * slowtable will be used when the first lookup didn't give the result.
- */
-static void build_huffman_table(const unsigned char *bits, const unsigned char *vals, struct huffman_table *table)
-{
- unsigned int i, j, code, code_size, val, nbits;
- unsigned char huffsize[HUFFMAN_BITS_SIZE+1], *hz;
- unsigned int huffcode[HUFFMAN_BITS_SIZE+1], *hc;
- int next_free_entry;
-
- /*
- * Build a temp array
- * huffsize[X] => numbers of bits to write vals[X]
- */
- hz = huffsize;
- for (i=1; i<=16; i++)
- {
- for (j=1; j<=bits[i]; j++)
- *hz++ = i;
- }
- *hz = 0;
-
- memset(table->lookup, 0xff, sizeof(table->lookup));
- for (i=0; i<(16-HUFFMAN_HASH_NBITS); i++)
- table->slowtable[i][0] = 0;
-
- /* Build a temp array
- * huffcode[X] => code used to write vals[X]
- */
- code = 0;
- hc = huffcode;
- hz = huffsize;
- nbits = *hz;
- while (*hz)
- {
- while (*hz == nbits)
- {
- *hc++ = code++;
- hz++;
- }
- code <<= 1;
- nbits++;
- }
-
- /*
- * Build the lookup table, and the slowtable if needed.
- */
- next_free_entry = -1;
- for (i=0; huffsize[i]; i++)
- {
- val = vals[i];
- code = huffcode[i];
- code_size = huffsize[i];
-
- trace("val=%2.2x code=%8.8x codesize=%2.2d\n", val, code, code_size);
-
- table->code_size[val] = code_size;
- if (code_size <= HUFFMAN_HASH_NBITS)
- {
- /*
- * Good: val can be put in the lookup table, so fill all value of this
- * column with value val
- */
- int repeat = 1UL<<(HUFFMAN_HASH_NBITS - code_size);
- code <<= HUFFMAN_HASH_NBITS - code_size;
- while ( repeat-- )
- table->lookup[code++] = val;
-
- }
- else
- {
- /* Perhaps sorting the array will be an optimization */
- uint16_t *slowtable = table->slowtable[code_size-HUFFMAN_HASH_NBITS-1];
- while(slowtable[0])
- slowtable+=2;
- slowtable[0] = code;
- slowtable[1] = val;
- slowtable[2] = 0;
- /* TODO: NEED TO CHECK FOR AN OVERFLOW OF THE TABLE */
- }
-
- }
-}
-
-static void build_default_huffman_tables(struct jdec_private *priv)
-{
- if ( (priv->flags & TINYJPEG_FLAGS_MJPEG_TABLE)
- && priv->default_huffman_table_initialized)
- return;
-
- build_huffman_table(bits_dc_luminance, val_dc_luminance, &priv->HTDC[0]);
- build_huffman_table(bits_ac_luminance, val_ac_luminance, &priv->HTAC[0]);
-
- build_huffman_table(bits_dc_chrominance, val_dc_chrominance, &priv->HTDC[1]);
- build_huffman_table(bits_ac_chrominance, val_ac_chrominance, &priv->HTAC[1]);
-
- priv->default_huffman_table_initialized = 1;
-}
-
-
-
-/*******************************************************************************
- *
- * Colorspace conversion routine
- *
- *
- * Note:
- * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
- * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
- * The conversion equations to be implemented are therefore
- * R = Y + 1.40200 * Cr
- * G = Y - 0.34414 * Cb - 0.71414 * Cr
- * B = Y + 1.77200 * Cb
- *
- ******************************************************************************/
-
-static unsigned char clamp(int i)
-{
- if (i<0)
- return 0;
- else if (i>255)
- return 255;
- else
- return i;
-}
-
-
-/**
- * YCrCb -> YUV420P (1x1)
- * .---.
- * | 1 |
- * `---'
- */
-static void YCrCB_to_YUV420P_1x1(struct jdec_private *priv)
-{
- const unsigned char *s, *y;
- unsigned char *p;
- int i,j;
-
- p = priv->plane[0];
- y = priv->Y;
- for (i=0; i<8; i++)
- {
- memcpy(p, y, 8);
- p+=priv->width;
- y+=8;
- }
-
- p = priv->plane[1];
- s = priv->Cb;
- for (i=0; i<8; i+=2)
- {
- for (j=0; j<8; j+=2, s+=2)
- *p++ = *s;
- s += 8; /* Skip one line */
- p += priv->width/2 - 4;
- }
-
- p = priv->plane[2];
- s = priv->Cr;
- for (i=0; i<8; i+=2)
- {
- for (j=0; j<8; j+=2, s+=2)
- *p++ = *s;
- s += 8; /* Skip one line */
- p += priv->width/2 - 4;
- }
-}
-
-/**
- * YCrCb -> YUV420P (2x1)
- * .-------.
- * | 1 | 2 |
- * `-------'
- */
-static void YCrCB_to_YUV420P_2x1(struct jdec_private *priv)
-{
- unsigned char *p;
- const unsigned char *s, *y1;
- unsigned int i;
-
- p = priv->plane[0];
- y1 = priv->Y;
- for (i=0; i<8; i++)
- {
- memcpy(p, y1, 16);
- p += priv->width;
- y1 += 16;
- }
-
- p = priv->plane[1];
- s = priv->Cb;
- for (i=0; i<8; i+=2)
- {
- memcpy(p, s, 8);
- s += 16; /* Skip one line */
- p += priv->width/2;
- }
-
- p = priv->plane[2];
- s = priv->Cr;
- for (i=0; i<8; i+=2)
- {
- memcpy(p, s, 8);
- s += 16; /* Skip one line */
- p += priv->width/2;
- }
-}
-
-
-/**
- * YCrCb -> YUV420P (1x2)
- * .---.
- * | 1 |
- * |---|
- * | 2 |
- * `---'
- */
-static void YCrCB_to_YUV420P_1x2(struct jdec_private *priv)
-{
- const unsigned char *s, *y;
- unsigned char *p;
- int i,j;
-
- p = priv->plane[0];
- y = priv->Y;
- for (i=0; i<16; i++)
- {
- memcpy(p, y, 8);
- p+=priv->width;
- y+=8;
- }
-
- p = priv->plane[1];
- s = priv->Cb;
- for (i=0; i<8; i++)
- {
- for (j=0; j<8; j+=2, s+=2)
- *p++ = *s;
- p += priv->width/2 - 4;
- }
-
- p = priv->plane[2];
- s = priv->Cr;
- for (i=0; i<8; i++)
- {
- for (j=0; j<8; j+=2, s+=2)
- *p++ = *s;
- p += priv->width/2 - 4;
- }
-}
-
-/**
- * YCrCb -> YUV420P (2x2)
- * .-------.
- * | 1 | 2 |
- * |---+---|
- * | 3 | 4 |
- * `-------'
- */
-static void YCrCB_to_YUV420P_2x2(struct jdec_private *priv)
-{
- unsigned char *p;
- const unsigned char *s, *y1;
- unsigned int i;
-
- p = priv->plane[0];
- y1 = priv->Y;
- for (i=0; i<16; i++)
- {
- memcpy(p, y1, 16);
- p += priv->width;
- y1 += 16;
- }
-
- p = priv->plane[1];
- s = priv->Cb;
- for (i=0; i<8; i++)
- {
- memcpy(p, s, 8);
- s += 8;
- p += priv->width/2;
- }
-
- p = priv->plane[2];
- s = priv->Cr;
- for (i=0; i<8; i++)
- {
- memcpy(p, s, 8);
- s += 8;
- p += priv->width/2;
- }
-}
-
-/**
- * YCrCb -> RGB24 (1x1)
- * .---.
- * | 1 |
- * `---'
- */
-static void YCrCB_to_RGB24_1x1(struct jdec_private *priv)
-{
- const unsigned char *Y, *Cb, *Cr;
- unsigned char *p;
- int i,j;
- int offset_to_next_row;
-
-#define SCALEBITS 10
-#define ONE_HALF (1UL << (SCALEBITS-1))
-#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
- p = priv->plane[0];
- Y = priv->Y;
- Cb = priv->Cb;
- Cr = priv->Cr;
- offset_to_next_row = priv->width*3 - 8*3;
- for (i=0; i<8; i++) {
-
- for (j=0; j<8; j++) {
-
- int y, cb, cr;
- int add_r, add_g, add_b;
- int r, g , b;
-
- y = (*Y++) << SCALEBITS;
- cb = *Cb++ - 128;
- cr = *Cr++ - 128;
- add_r = FIX(1.40200) * cr + ONE_HALF;
- add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
- add_b = FIX(1.77200) * cb + ONE_HALF;
-
-
- r = (y + add_r) >> SCALEBITS;
- g = (y + add_g) >> SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
- priv->decomp_block[i][j*3+0]=clamp(r);
- priv->decomp_block[i][j*3+1]=clamp(g);
- priv->decomp_block[i][j*3+2]=clamp(b);
-
- }
-
-// p += offset_to_next_row;
- }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-/**
- * YCrCb -> BGR24 (1x1)
- * .---.
- * | 1 |
- * `---'
- */
-static void YCrCB_to_BGR24_1x1(struct jdec_private *priv)
-{
- const unsigned char *Y, *Cb, *Cr;
- unsigned char *p;
- int i,j;
- int offset_to_next_row;
-
-#define SCALEBITS 10
-#define ONE_HALF (1UL << (SCALEBITS-1))
-#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
- p = priv->plane[0];
- Y = priv->Y;
- Cb = priv->Cb;
- Cr = priv->Cr;
- offset_to_next_row = priv->width*3 - 8*3;
- for (i=0; i<8; i++) {
-
- for (j=0; j<8; j++) {
-
- int y, cb, cr;
- int add_r, add_g, add_b;
- int r, g , b;
-
- y = (*Y++) << SCALEBITS;
- cb = *Cb++ - 128;
- cr = *Cr++ - 128;
- add_r = FIX(1.40200) * cr + ONE_HALF;
- add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
- add_b = FIX(1.77200) * cb + ONE_HALF;
-
- b = (y + add_b) >> SCALEBITS;
- *p++ = clamp(b);
- g = (y + add_g) >> SCALEBITS;
- *p++ = clamp(g);
- r = (y + add_r) >> SCALEBITS;
- *p++ = clamp(r);
-
- }
-
- p += offset_to_next_row;
- }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-
-/**
- * YCrCb -> RGB24 (2x1)
- * .-------.
- * | 1 | 2 |
- * `-------'
- */
-static void YCrCB_to_RGB24_2x1(struct jdec_private *priv)
-{
- const unsigned char *Y, *Cb, *Cr;
- unsigned char *p;
- int i,j;
- int offset_to_next_row;
-
-#define SCALEBITS 10
-#define ONE_HALF (1UL << (SCALEBITS-1))
-#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
- p = priv->plane[0];
- Y = priv->Y;
- Cb = priv->Cb;
- Cr = priv->Cr;
- offset_to_next_row = priv->width*3 - 16*3;
- for (i=0; i<8; i++) {
-
- for (j=0; j<8; j++) {
-
- int y, cb, cr;
- int add_r, add_g, add_b;
- int r, g , b;
-
- y = (*Y++) << SCALEBITS;
- cb = *Cb++ - 128;
- cr = *Cr++ - 128;
- add_r = FIX(1.40200) * cr + ONE_HALF;
- add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
- add_b = FIX(1.77200) * cb + ONE_HALF;
-
- r = (y + add_r) >> SCALEBITS;
- g = (y + add_g) >> SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
-
- priv->decomp_block[i][j*6+0]=clamp(r);
- priv->decomp_block[i][j*6+1]=clamp(g);
- priv->decomp_block[i][j*6+2]=clamp(b);
-
- y = (*Y++) << SCALEBITS;
-
- r = (y + add_r) >> SCALEBITS;
- g = (y + add_g) >> SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
-
- priv->decomp_block[i][j*6+3]=clamp(r);
- priv->decomp_block[i][j*6+4]=clamp(g);
- priv->decomp_block[i][j*6+5]=clamp(b);
-
- }
-
- p += offset_to_next_row;
- }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-/*
- * YCrCb -> BGR24 (2x1)
- * .-------.
- * | 1 | 2 |
- * `-------'
- */
-static void YCrCB_to_BGR24_2x1(struct jdec_private *priv)
-{
- const unsigned char *Y, *Cb, *Cr;
- unsigned char *p;
- int i,j;
- int offset_to_next_row;
-
-#define SCALEBITS 10
-#define ONE_HALF (1UL << (SCALEBITS-1))
-#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
- p = priv->plane[0];
- Y = priv->Y;
- Cb = priv->Cb;
- Cr = priv->Cr;
- offset_to_next_row = priv->width*3 - 16*3;
- for (i=0; i<8; i++) {
-
- for (j=0; j<8; j++) {
-
- int y, cb, cr;
- int add_r, add_g, add_b;
- int r, g , b;
-
- cb = *Cb++ - 128;
- cr = *Cr++ - 128;
- add_r = FIX(1.40200) * cr + ONE_HALF;
- add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
- add_b = FIX(1.77200) * cb + ONE_HALF;
-
- y = (*Y++) << SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
- *p++ = clamp(b);
- g = (y + add_g) >> SCALEBITS;
- *p++ = clamp(g);
- r = (y + add_r) >> SCALEBITS;
- *p++ = clamp(r);
-
- y = (*Y++) << SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
- *p++ = clamp(b);
- g = (y + add_g) >> SCALEBITS;
- *p++ = clamp(g);
- r = (y + add_r) >> SCALEBITS;
- *p++ = clamp(r);
-
- }
-
- p += offset_to_next_row;
- }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-/**
- * YCrCb -> RGB24 (1x2)
- * .---.
- * | 1 |
- * |---|
- * | 2 |
- * `---'
- */
-static void YCrCB_to_RGB24_1x2(struct jdec_private *priv)
-{
- const unsigned char *Y, *Cb, *Cr;
- unsigned char *p, *p2;
- int i,j;
- int offset_to_next_row;
-
-#define SCALEBITS 10
-#define ONE_HALF (1UL << (SCALEBITS-1))
-#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
- p = priv->plane[0];
- p2 = priv->plane[0] + priv->width*3;
- Y = priv->Y;
- Cb = priv->Cb;
- Cr = priv->Cr;
- offset_to_next_row = 2*priv->width*3 - 8*3;
- for (i=0; i<8; i++) {
-
- for (j=0; j<8; j++) {
-
- int y, cb, cr;
- int add_r, add_g, add_b;
- int r, g , b;
-
- cb = *Cb++ - 128;
- cr = *Cr++ - 128;
- add_r = FIX(1.40200) * cr + ONE_HALF;
- add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
- add_b = FIX(1.77200) * cb + ONE_HALF;
-
- y = (*Y++) << SCALEBITS;
- r = (y + add_r) >> SCALEBITS;
- g = (y + add_g) >> SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
-
- priv->decomp_block[i*2][j*3+0]=clamp(r);
- priv->decomp_block[i*2][j*3+1]=clamp(g);
- priv->decomp_block[i*2][j*3+2]=clamp(b);
-
- y = (Y[8-1]) << SCALEBITS;
- r = (y + add_r) >> SCALEBITS;
- g = (y + add_g) >> SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
-
- priv->decomp_block[i*2+1][j*3+0]=clamp(r);
- priv->decomp_block[i*2+1][j*3+1]=clamp(g);
- priv->decomp_block[i*2+1][j*3+2]=clamp(b);
-
- }
- Y += 8;
- p += offset_to_next_row;
- p2 += offset_to_next_row;
- }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-/*
- * YCrCb -> BGR24 (1x2)
- * .---.
- * | 1 |
- * |---|
- * | 2 |
- * `---'
- */
-static void YCrCB_to_BGR24_1x2(struct jdec_private *priv)
-{
- const unsigned char *Y, *Cb, *Cr;
- unsigned char *p, *p2;
- int i,j;
- int offset_to_next_row;
-
-#define SCALEBITS 10
-#define ONE_HALF (1UL << (SCALEBITS-1))
-#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
- p = priv->plane[0];
- p2 = priv->plane[0] + priv->width*3;
- Y = priv->Y;
- Cb = priv->Cb;
- Cr = priv->Cr;
- offset_to_next_row = 2*priv->width*3 - 8*3;
- for (i=0; i<8; i++) {
-
- for (j=0; j<8; j++) {
-
- int y, cb, cr;
- int add_r, add_g, add_b;
- int r, g , b;
-
- cb = *Cb++ - 128;
- cr = *Cr++ - 128;
- add_r = FIX(1.40200) * cr + ONE_HALF;
- add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
- add_b = FIX(1.77200) * cb + ONE_HALF;
-
- y = (*Y++) << SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
- *p++ = clamp(b);
- g = (y + add_g) >> SCALEBITS;
- *p++ = clamp(g);
- r = (y + add_r) >> SCALEBITS;
- *p++ = clamp(r);
-
- y = (Y[8-1]) << SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
- *p2++ = clamp(b);
- g = (y + add_g) >> SCALEBITS;
- *p2++ = clamp(g);
- r = (y + add_r) >> SCALEBITS;
- *p2++ = clamp(r);
-
- }
- Y += 8;
- p += offset_to_next_row;
- p2 += offset_to_next_row;
- }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-
-/**
- * YCrCb -> RGB24 (2x2)
- * .-------.
- * | 1 | 2 |
- * |---+---|
- * | 3 | 4 |
- * `-------'
- */
-static void YCrCB_to_RGB24_2x2(struct jdec_private *priv)
-{
- const unsigned char *Y, *Cb, *Cr;
- unsigned char *p, *p2;
- int i,j;
- int offset_to_next_row;
-
-#define SCALEBITS 10
-#define ONE_HALF (1UL << (SCALEBITS-1))
-#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
- p = priv->plane[0];
- p2 = priv->plane[0] + priv->width*3;
- Y = priv->Y;
- Cb = priv->Cb;
- Cr = priv->Cr;
- offset_to_next_row = (priv->width*3*2) - 16*3;
- for (i=0; i<8; i++) {
-
- for (j=0; j<8; j++) {
-
- int y, cb, cr;
- int add_r, add_g, add_b;
- int r, g , b;
-
- cb = *Cb++ - 128;
- cr = *Cr++ - 128;
- add_r = FIX(1.40200) * cr + ONE_HALF;
- add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
- add_b = FIX(1.77200) * cb + ONE_HALF;
-
- y = (*Y++) << SCALEBITS;
- r = (y + add_r) >> SCALEBITS;
- g = (y + add_g) >> SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
-
- priv->decomp_block[i*2][j*6+0]=clamp(r);
- priv->decomp_block[i*2][j*6+1]=clamp(g);
- priv->decomp_block[i*2][j*6+2]=clamp(b);
-
- y = (*Y++) << SCALEBITS;
- r = (y + add_r) >> SCALEBITS;
- g = (y + add_g) >> SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
-
- priv->decomp_block[i*2][j*6+3]=clamp(r);
- priv->decomp_block[i*2][j*6+4]=clamp(g);
- priv->decomp_block[i*2][j*6+5]=clamp(b);
-
- y = (Y[16-2]) << SCALEBITS;
- r = (y + add_r) >> SCALEBITS;
- g = (y + add_g) >> SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
-
- priv->decomp_block[i*2+1][j*6+0]=clamp(r);
- priv->decomp_block[i*2+1][j*6+1]=clamp(g);
- priv->decomp_block[i*2+1][j*6+2]=clamp(b);
-
- y = (Y[16-1]) << SCALEBITS;
- r = (y + add_r) >> SCALEBITS;
- g = (y + add_g) >> SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
-
- priv->decomp_block[i*2+1][j*6+3]=clamp(r);
- priv->decomp_block[i*2+1][j*6+4]=clamp(g);
- priv->decomp_block[i*2+1][j*6+5]=clamp(b);
-
- }
- Y += 16;
- p += offset_to_next_row;
- p2 += offset_to_next_row;
- }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-
-/*
- * YCrCb -> BGR24 (2x2)
- * .-------.
- * | 1 | 2 |
- * |---+---|
- * | 3 | 4 |
- * `-------'
- */
-static void YCrCB_to_BGR24_2x2(struct jdec_private *priv)
-{
- const unsigned char *Y, *Cb, *Cr;
- unsigned char *p, *p2;
- int i,j;
- int offset_to_next_row;
-
-#define SCALEBITS 10
-#define ONE_HALF (1UL << (SCALEBITS-1))
-#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
- p = priv->plane[0];
- p2 = priv->plane[0] + priv->width*3;
- Y = priv->Y;
- Cb = priv->Cb;
- Cr = priv->Cr;
- offset_to_next_row = (priv->width*3*2) - 16*3;
- for (i=0; i<8; i++) {
-
- for (j=0; j<8; j++) {
-
- int y, cb, cr;
- int add_r, add_g, add_b;
- int r, g , b;
-
- cb = *Cb++ - 128;
- cr = *Cr++ - 128;
- add_r = FIX(1.40200) * cr + ONE_HALF;
- add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
- add_b = FIX(1.77200) * cb + ONE_HALF;
-
- y = (*Y++) << SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
- *p++ = clamp(b);
- g = (y + add_g) >> SCALEBITS;
- *p++ = clamp(g);
- r = (y + add_r) >> SCALEBITS;
- *p++ = clamp(r);
-
- y = (*Y++) << SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
- *p++ = clamp(b);
- g = (y + add_g) >> SCALEBITS;
- *p++ = clamp(g);
- r = (y + add_r) >> SCALEBITS;
- *p++ = clamp(r);
-
- y = (Y[16-2]) << SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
- *p2++ = clamp(b);
- g = (y + add_g) >> SCALEBITS;
- *p2++ = clamp(g);
- r = (y + add_r) >> SCALEBITS;
- *p2++ = clamp(r);
-
- y = (Y[16-1]) << SCALEBITS;
- b = (y + add_b) >> SCALEBITS;
- *p2++ = clamp(b);
- g = (y + add_g) >> SCALEBITS;
- *p2++ = clamp(g);
- r = (y + add_r) >> SCALEBITS;
- *p2++ = clamp(r);
- }
- Y += 16;
- p += offset_to_next_row;
- p2 += offset_to_next_row;
- }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-
-
-/**
- * YCrCb -> Grey (1x1)
- * .---.
- * | 1 |
- * `---'
- */
-static void YCrCB_to_Grey_1x1(struct jdec_private *priv)
-{
- const unsigned char *y;
- unsigned char *p;
- unsigned int i;
- int offset_to_next_row;
-
- p = priv->plane[0];
- y = priv->Y;
- offset_to_next_row = priv->width;
-
- for (i=0; i<8; i++) {
- memcpy(p, y, 8);
- y+=8;
- p += offset_to_next_row;
- }
-}
-
-/**
- * YCrCb -> Grey (2x1)
- * .-------.
- * | 1 | 2 |
- * `-------'
- */
-static void YCrCB_to_Grey_2x1(struct jdec_private *priv)
-{
- const unsigned char *y;
- unsigned char *p;
- unsigned int i;
-
- p = priv->plane[0];
- y = priv->Y;
-
- for (i=0; i<8; i++) {
- memcpy(p, y, 16);
- y += 16;
- p += priv->width;
- }
-}
-
-
-/**
- * YCrCb -> Grey (1x2)
- * .---.
- * | 1 |
- * |---|
- * | 2 |
- * `---'
- */
-static void YCrCB_to_Grey_1x2(struct jdec_private *priv)
-{
- const unsigned char *y;
- unsigned char *p;
- unsigned int i;
-
- p = priv->plane[0];
- y = priv->Y;
-
- for (i=0; i<16; i++) {
- memcpy(p, y, 8);
- y += 8;
- p += priv->width;
- }
-}
-
-/**
- * YCrCb -> Grey (2x2)
- * .-------.
- * | 1 | 2 |
- * |---+---|
- * | 3 | 4 |
- * `-------'
- */
-static void YCrCB_to_Grey_2x2(struct jdec_private *priv)
-{
- const unsigned char *y;
- unsigned char *p;
- unsigned int i;
-
- p = priv->plane[0];
- y = priv->Y;
-
- for (i=0; i<16; i++) {
- memcpy(p, y, 16);
- y += 16;
- p += priv->width;
- }
-}
-
-
-/*
- * Decode all the 3 components for 1x1
- */
-static void decode_MCU_1x1_3planes(struct jdec_private *priv)
-{
- // Y
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y, 8);
-
- // Cb
- process_Huffman_data_unit(priv, cCb);
- IDCT(&priv->component_infos[cCb], priv->Cb, 8);
-
- // Cr
- process_Huffman_data_unit(priv, cCr);
- IDCT(&priv->component_infos[cCr], priv->Cr, 8);
-}
-
-/*
- * Decode a 1x1 directly in 1 color
- */
-static void decode_MCU_1x1_1plane(struct jdec_private *priv)
-{
- // Y
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y, 8);
-
- // Cb
- process_Huffman_data_unit(priv, cCb);
- IDCT(&priv->component_infos[cCb], priv->Cb, 8);
-
- // Cr
- process_Huffman_data_unit(priv, cCr);
- IDCT(&priv->component_infos[cCr], priv->Cr, 8);
-}
-
-
-/*
- * Decode a 2x1
- * .-------.
- * | 1 | 2 |
- * `-------'
- */
-static void decode_MCU_2x1_3planes(struct jdec_private *priv)
-{
- // Y
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y, 16);
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y+8, 16);
-
- // Cb
- process_Huffman_data_unit(priv, cCb);
- IDCT(&priv->component_infos[cCb], priv->Cb, 8);
-
- // Cr
- process_Huffman_data_unit(priv, cCr);
- IDCT(&priv->component_infos[cCr], priv->Cr, 8);
-}
-
-/*
- * Decode a 2x1
- * .-------.
- * | 1 | 2 |
- * `-------'
- */
-static void decode_MCU_2x1_1plane(struct jdec_private *priv)
-{
- // Y
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y, 16);
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y+8, 16);
-
- // Cb
- process_Huffman_data_unit(priv, cCb);
-
- // Cr
- process_Huffman_data_unit(priv, cCr);
-}
-
-
-/*
- * Decode a 2x2
- * .-------.
- * | 1 | 2 |
- * |---+---|
- * | 3 | 4 |
- * `-------'
- */
-static void decode_MCU_2x2_3planes(struct jdec_private *priv)
-{
- // Y
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y, 16);
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y+8, 16);
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y+64*2, 16);
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16);
-
- // Cb
- process_Huffman_data_unit(priv, cCb);
- IDCT(&priv->component_infos[cCb], priv->Cb, 8);
-
- // Cr
- process_Huffman_data_unit(priv, cCr);
- IDCT(&priv->component_infos[cCr], priv->Cr, 8);
-}
-
-/*
- * Decode a 2x2 directly in GREY format (8bits)
- * .-------.
- * | 1 | 2 |
- * |---+---|
- * | 3 | 4 |
- * `-------'
- */
-static void decode_MCU_2x2_1plane(struct jdec_private *priv)
-{
- // Y
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y, 16);
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y+8, 16);
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y+64*2, 16);
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16);
-
- // Cb
- process_Huffman_data_unit(priv, cCb);
-
- // Cr
- process_Huffman_data_unit(priv, cCr);
-}
-
-/*
- * Decode a 1x2 mcu
- * .---.
- * | 1 |
- * |---|
- * | 2 |
- * `---'
- */
-static void decode_MCU_1x2_3planes(struct jdec_private *priv)
-{
- // Y
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y, 8);
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y+64, 8);
-
- // Cb
- process_Huffman_data_unit(priv, cCb);
- IDCT(&priv->component_infos[cCb], priv->Cb, 8);
-
- // Cr
- process_Huffman_data_unit(priv, cCr);
- IDCT(&priv->component_infos[cCr], priv->Cr, 8);
-}
-
-/*
- * Decode a 1x2 mcu
- * .---.
- * | 1 |
- * |---|
- * | 2 |
- * `---'
- */
-static void decode_MCU_1x2_1plane(struct jdec_private *priv)
-{
- // Y
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y, 8);
- process_Huffman_data_unit(priv, cY);
- IDCT(&priv->component_infos[cY], priv->Y+64, 8);
-
- // Cb
- process_Huffman_data_unit(priv, cCb);
-
- // Cr
- process_Huffman_data_unit(priv, cCr);
-}
-
-static void print_SOF(const unsigned char *stream)
-{
- int width, height, nr_components, precision;
-#if DEBUG
- const char *nr_components_to_string[] = {
- "????",
- "Grayscale",
- "????",
- "YCbCr",
- "CYMK"
- };
-#endif
-
- precision = stream[2];
- height = be16_to_cpu(stream+3);
- width = be16_to_cpu(stream+5);
- nr_components = stream[7];
-
- trace("> SOF marker\n");
- trace("Size:%dx%d nr_components:%d (%s) precision:%d\n",
- width, height,
- nr_components, nr_components_to_string[nr_components],
- precision);
-}
-
-/*******************************************************************************
- *
- * JPEG/JFIF Parsing functions
- *
- * Note: only a small subset of the jpeg file format is supported. No markers,
- * nor progressive stream is supported.
- *
- ******************************************************************************/
-
-static void build_quantization_table(float *qtable, const unsigned char *ref_table)
-{
- /* Taken from libjpeg. Copyright Independent JPEG Group's LLM idct.
- * For float AA&N IDCT method, divisors are equal to quantization
- * coefficients scaled by scalefactor[row]*scalefactor[col], where
- * scalefactor[0] = 1
- * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
- * We apply a further scale factor of 8.
- * What's actually stored is 1/divisor so that the inner loop can
- * use a multiplication rather than a division.
- */
- int i, j;
- static const double aanscalefactor[8] = {
- 1.0, 1.387039845, 1.306562965, 1.175875602,
- 1.0, 0.785694958, 0.541196100, 0.275899379
- };
- const unsigned char *zz = zigzag;
-
- for (i=0; i<8; i++) {
- for (j=0; j<8; j++) {
- *qtable++ = ref_table[*zz++] * aanscalefactor[i] * aanscalefactor[j];
- }
- }
-
-}
-
-static int parse_DQT(struct jdec_private *priv, const unsigned char *stream)
-{
- int qi;
- float *table;
- const unsigned char *dqt_block_end;
-
- trace("> DQT marker\n");
- dqt_block_end = stream + be16_to_cpu(stream);
- stream += 2; /* Skip length */
-
- while (stream < dqt_block_end)
- {
- qi = *stream++;
-#if SANITY_CHECK
- if (qi>>4)
- error("16 bits quantization table is not supported\n");
- if (qi>4)
- error("No more 4 quantization table is supported (got %d)\n", qi);
-#endif
- table = priv->Q_tables[qi];
- build_quantization_table(table, stream);
- stream += 64;
- }
- trace("< DQT marker\n");
- return 0;
-}
-
-static int parse_SOF(struct jdec_private *priv, const unsigned char *stream)
-{
- int i, width, height, nr_components, cid, sampling_factor;
- int Q_table;
- struct component *c;
-
- trace("> SOF marker\n");
- print_SOF(stream);
-
- height = be16_to_cpu(stream+3);
- width = be16_to_cpu(stream+5);
- nr_components = stream[7];
-#if SANITY_CHECK
- if (stream[2] != 8)
- error("Precision other than 8 is not supported\n");
- if (width>JPEG_MAX_WIDTH || height>JPEG_MAX_HEIGHT)
- error("Width and Height (%dx%d) seems suspicious\n", width, height);
- if (nr_components != 3)
- error("We only support YUV images\n");
- //if (height%16)
-// error("Height need to be a multiple of 16 (current height is %d)\n", height);
-// if (width%16)
- // error("Width need to be a multiple of 16 (current Width is %d)\n", width);
-#endif
- stream += 8;
- for (i=0; i<nr_components; i++) {
- cid = *stream++;
- sampling_factor = *stream++;
- Q_table = *stream++;
- c = &priv->component_infos[i];
-#if SANITY_CHECK
- c->cid = cid;
- if (Q_table >= COMPONENTS)
- error("Bad Quantization table index (got %d, max allowed %d)\n", Q_table, COMPONENTS-1);
-#endif
- c->Vfactor = sampling_factor&0xf;
- c->Hfactor = sampling_factor>>4;
- c->Q_table = priv->Q_tables[Q_table];
- trace("Component:%d factor:%dx%d Quantization table:%d\n",
- cid, c->Hfactor, c->Hfactor, Q_table );
-
- }
- priv->width = width;
- priv->height = height;
-
- trace("< SOF marker\n");
-
- return 0;
-}
-
-static int parse_SOS(struct jdec_private *priv, const unsigned char *stream)
-{
- unsigned int i, cid, table;
- unsigned int nr_components = stream[2];
-
- trace("> SOS marker\n");
-
-#if SANITY_CHECK
- if (nr_components != 3)
- error("We only support YCbCr image\n");
-#endif
-
- stream += 3;
- for (i=0;i<nr_components;i++) {
- cid = *stream++;
- table = *stream++;
-#if SANITY_CHECK
- if ((table&0xf)>=4)
- error("We do not support more than 2 AC Huffman table\n");
- if ((table>>4)>=4)
- error("We do not support more than 2 DC Huffman table\n");
- if (cid != priv->component_infos[i].cid)
- error("SOS cid order (%d:%d) isn't compatible with the SOF marker (%d:%d)\n",
- i, cid, i, priv->component_infos[i].cid);
- trace("ComponentId:%d tableAC:%d tableDC:%d\n", cid, table&0xf, table>>4);
-#endif
- priv->component_infos[i].AC_table = &priv->HTAC[table&0xf];
- priv->component_infos[i].DC_table = &priv->HTDC[table>>4];
- }
- priv->stream = stream+3;
- trace("< SOS marker\n");
- return 0;
-}
-
-static int parse_DHT(struct jdec_private *priv, const unsigned char *stream)
-{
- unsigned int count, i;
- unsigned char huff_bits[17];
- int length, index;
-
- length = be16_to_cpu(stream) - 2;
- stream += 2; /* Skip length */
-
- trace("> DHT marker (length=%d)\n", length);
-
- while (length>0) {
- index = *stream++;
-
- /* We need to calculate the number of bytes 'vals' will takes */
- huff_bits[0] = 0;
- count = 0;
- for (i=1; i<17; i++) {
- huff_bits[i] = *stream++;
- count += huff_bits[i];
- }
-#if SANITY_CHECK
- if (count >= HUFFMAN_BITS_SIZE)
- error("No more than %d bytes is allowed to describe a huffman table", HUFFMAN_BITS_SIZE);
- if ( (index &0xf) >= HUFFMAN_TABLES)
- error("No more than %d Huffman tables is supported (got %d)\n", HUFFMAN_TABLES, index&0xf);
- trace("Huffman table %s[%d] length=%d\n", (index&0xf0)?"AC":"DC", index&0xf, count);
-#endif
-
- if (index & 0xf0 )
- build_huffman_table(huff_bits, stream, &priv->HTAC[index&0xf]);
- else
- build_huffman_table(huff_bits, stream, &priv->HTDC[index&0xf]);
-
- length -= 1;
- length -= 16;
- length -= count;
- stream += count;
- }
- trace("< DHT marker\n");
- return 0;
-}
-
-static int parse_DRI(struct jdec_private *priv, const unsigned char *stream)
-{
- unsigned int length;
-
- trace("> DRI marker\n");
-
- length = be16_to_cpu(stream);
-
-#if SANITY_CHECK
- if (length != 4)
- error("Length of DRI marker need to be 4\n");
-#endif
-
- priv->restart_interval = be16_to_cpu(stream+2);
-
-#if DEBUG
- trace("Restart interval = %d\n", priv->restart_interval);
-#endif
-
- trace("< DRI marker\n");
-
- return 0;
-}
-
-
-
-static void resync(struct jdec_private *priv)
-{
- int i;
-
- /* Init DC coefficients */
- for (i=0; i<COMPONENTS; i++)
- priv->component_infos[i].previous_DC = 0;
-
- priv->reservoir = 0;
- priv->nbits_in_reservoir = 0;
- if (priv->restart_interval > 0)
- priv->restarts_to_go = priv->restart_interval;
- else
- priv->restarts_to_go = -1;
-}
-
-static int find_next_rst_marker(struct jdec_private *priv)
-{
- int rst_marker_found = 0;
- int marker;
- const unsigned char *stream = priv->stream;
-
- /* Parse marker */
- while (!rst_marker_found)
- {
- while (*stream++ != 0xff)
- {
- if (stream >= priv->stream_end)
- error("EOF while search for a RST marker.");
- }
- /* Skip any padding ff byte (this is normal) */
- while (*stream == 0xff)
- stream++;
-
- marker = *stream++;
- if ((RST+priv->last_rst_marker_seen) == marker)
- rst_marker_found = 1;
- else if (marker >= RST && marker <= RST7)
- error("Wrong Reset marker found, abording");
- else if (marker == EOI)
- return 0;
- }
- trace("RST Marker %d found at offset %d\n", priv->last_rst_marker_seen, stream - priv->stream_begin);
-
- priv->stream = stream;
- priv->last_rst_marker_seen++;
- priv->last_rst_marker_seen &= 7;
-
- return 0;
-}
-
-static int parse_JFIF(struct jdec_private *priv, const unsigned char *stream)
-{
- int chuck_len;
- int marker;
- int sos_marker_found = 0;
- int dht_marker_found = 0;
- const unsigned char *next_chunck;
-
- /* Parse marker */
- while (!sos_marker_found)
- {
- if (*stream++ != 0xff)
- goto bogus_jpeg_format;
- /* Skip any padding ff byte (this is normal) */
- while (*stream == 0xff)
- stream++;
-
- marker = *stream++;
- chuck_len = be16_to_cpu(stream);
- next_chunck = stream + chuck_len;
- switch (marker)
- {
- case SOF:
- if (parse_SOF(priv, stream) < 0)
- return -1;
- break;
- case DQT:
- if (parse_DQT(priv, stream) < 0)
- return -1;
- break;
- case SOS:
- if (parse_SOS(priv, stream) < 0)
- return -1;
- sos_marker_found = 1;
- break;
- case DHT:
- if (parse_DHT(priv, stream) < 0)
- return -1;
- dht_marker_found = 1;
- break;
- case DRI:
- if (parse_DRI(priv, stream) < 0)
- return -1;
- break;
- default:
- trace("> Unknown marker %2.2x\n", marker);
- break;
- }
-
- stream = next_chunck;
- }
-
- if (!dht_marker_found) {
- trace("No Huffman table loaded, using the default one\n");
- build_default_huffman_tables(priv);
- }
-
-#ifdef SANITY_CHECK
- if ( (priv->component_infos[cY].Hfactor < priv->component_infos[cCb].Hfactor)
- || (priv->component_infos[cY].Hfactor < priv->component_infos[cCr].Hfactor))
- error("Horizontal sampling factor for Y should be greater than horitontal sampling factor for Cb or Cr\n");
- if ( (priv->component_infos[cY].Vfactor < priv->component_infos[cCb].Vfactor)
- || (priv->component_infos[cY].Vfactor < priv->component_infos[cCr].Vfactor))
- error("Vertical sampling factor for Y should be greater than vertical sampling factor for Cb or Cr\n");
- if ( (priv->component_infos[cCb].Hfactor!=1)
- || (priv->component_infos[cCr].Hfactor!=1)
- || (priv->component_infos[cCb].Vfactor!=1)
- || (priv->component_infos[cCr].Vfactor!=1))
- error("Sampling other than 1x1 for Cr and Cb is not supported");
-#endif
-
- return 0;
-bogus_jpeg_format:
- trace("Bogus jpeg format\n");
- return -1;
-}
-
-/*******************************************************************************
- *
- * Functions exported of the library.
- *
- * Note: Some applications can access directly to internal pointer of the
- * structure. It's is not recommended, but if you have many images to
- * uncompress with the same parameters, some functions can be called to speedup
- * the decoding.
- *
- ******************************************************************************/
-
-/**
- * Allocate a new tinyjpeg decoder object.
- *
- * Before calling any other functions, an object need to be called.
- */
-struct jdec_private *tinyjpeg_init(void *(*allocate_mem)(unsigned int),void (*free_mem)(void *))
-{
- struct jdec_private *priv;
- unsigned int i;
-
- priv = (struct jdec_private *)allocate_mem(sizeof(struct jdec_private));
- for(i=0;i<sizeof(struct jdec_private);i++) {
- char *pzero = (char*)priv;
- pzero[i]=0;
- }
- priv->allocate_mem=allocate_mem;
- priv->free_mem=free_mem;
- if (priv == NULL)
- return NULL;
- return priv;
-}
-
-/**
- * Free a tinyjpeg object.
- *
- * No others function can be called after this one.
- */
-void tinyjpeg_free(struct jdec_private *priv)
-{
- int i;
- for (i=0; i<COMPONENTS; i++) {
- if (priv->components[i]) {
- // priv->free_mem(priv->components[i]);
- priv->components[i] = NULL;
- }
- }
- priv->free_mem(priv);
-}
-
-/**
- * Initialize the tinyjpeg object and prepare the decoding of the stream.
- *
- * Check if the jpeg can be decoded with this jpeg decoder.
- * Fill some table used for preprocessing.
- */
-int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size)
-{
- int ret;
-
- /* Identify the file */
- if ((buf[0] != 0xFF) || (buf[1] != SOI))
- error("Not a JPG file ?\n");
-
- priv->stream_begin = buf+2;
- priv->stream_length = size-2;
- priv->stream_end = priv->stream_begin + priv->stream_length;
-
- ret = parse_JFIF(priv, priv->stream_begin);
-
- return ret;
-}
-
-static const decode_MCU_fct decode_mcu_3comp_table[4] = {
- decode_MCU_1x1_3planes,
- decode_MCU_1x2_3planes,
- decode_MCU_2x1_3planes,
- decode_MCU_2x2_3planes,
-};
-
-static const decode_MCU_fct decode_mcu_1comp_table[4] = {
- decode_MCU_1x1_1plane,
- decode_MCU_1x2_1plane,
- decode_MCU_2x1_1plane,
- decode_MCU_2x2_1plane,
-};
-
-static const convert_colorspace_fct convert_colorspace_yuv420p[4] = {
- YCrCB_to_YUV420P_1x1,
- YCrCB_to_YUV420P_1x2,
- YCrCB_to_YUV420P_2x1,
- YCrCB_to_YUV420P_2x2,
-};
-
-static const convert_colorspace_fct convert_colorspace_rgb24[4] = {
- YCrCB_to_RGB24_1x1,
- YCrCB_to_RGB24_1x2,
- YCrCB_to_RGB24_2x1,
- YCrCB_to_RGB24_2x2,
-};
-
-static const convert_colorspace_fct convert_colorspace_bgr24[4] = {
- YCrCB_to_BGR24_1x1,
- YCrCB_to_BGR24_1x2,
- YCrCB_to_BGR24_2x1,
- YCrCB_to_BGR24_2x2,
-};
-
-static const convert_colorspace_fct convert_colorspace_grey[4] = {
- YCrCB_to_Grey_1x1,
- YCrCB_to_Grey_1x2,
- YCrCB_to_Grey_2x1,
- YCrCB_to_Grey_2x2,
-};
-
-/**
- * Decode and convert the jpeg image into @pixfmt@ image
- *
- * Note: components will be automaticaly allocated if no memory is attached.
- */
-int tinyjpeg_decode(struct jdec_private *priv, int pixfmt)
-{
- unsigned int x, y, xstride_by_mcu, ystride_by_mcu;
- unsigned int bytes_per_blocklines[3], bytes_per_mcu[3];
- decode_MCU_fct decode_MCU;
- const decode_MCU_fct *decode_mcu_table;
- const convert_colorspace_fct *colorspace_array_conv;
- convert_colorspace_fct convert_to_pixfmt;
-
- if (pixfmt!=TINYJPEG_FMT_RGB24)
- error("Only TINYJPEG_FMT_RGB24 is supported in this version");
-
- if (setjmp(priv->jump_state))
- return -1;
-
- /* To keep gcc happy initialize some array */
- bytes_per_mcu[1] = 0;
- bytes_per_mcu[2] = 0;
- bytes_per_blocklines[1] = 0;
- bytes_per_blocklines[2] = 0;
-
- decode_mcu_table = decode_mcu_3comp_table;
- switch (pixfmt) {
- case TINYJPEG_FMT_YUV420P:
- colorspace_array_conv = convert_colorspace_yuv420p;
- if (priv->components[0] == NULL)
- priv->components[0] = (uint8_t *)priv->allocate_mem(priv->width * priv->height);
- if (priv->components[1] == NULL)
- priv->components[1] = (uint8_t *)priv->allocate_mem(priv->width * priv->height/4);
- if (priv->components[2] == NULL)
- priv->components[2] = (uint8_t *)priv->allocate_mem(priv->width * priv->height/4);
- bytes_per_blocklines[0] = priv->width;
- bytes_per_blocklines[1] = priv->width/4;
- bytes_per_blocklines[2] = priv->width/4;
- bytes_per_mcu[0] = 8;
- bytes_per_mcu[1] = 4;
- bytes_per_mcu[2] = 4;
- break;
-
- case TINYJPEG_FMT_RGB24:
- colorspace_array_conv = convert_colorspace_rgb24;
- if (priv->components[0] == NULL)
- priv->components[0] = (uint8_t *)priv->allocate_mem(priv->width * priv->height * 3);
- bytes_per_blocklines[0] = priv->width * 3;
- bytes_per_mcu[0] = 3*8;
- break;
-
- case TINYJPEG_FMT_BGR24:
- colorspace_array_conv = convert_colorspace_bgr24;
- if (priv->components[0] == NULL)
- priv->components[0] = (uint8_t *)priv->allocate_mem(priv->width * priv->height * 3);
- bytes_per_blocklines[0] = priv->width * 3;
- bytes_per_mcu[0] = 3*8;
- break;
-
- case TINYJPEG_FMT_GREY:
- decode_mcu_table = decode_mcu_1comp_table;
- colorspace_array_conv = convert_colorspace_grey;
- if (priv->components[0] == NULL)
- priv->components[0] = (uint8_t *)priv->allocate_mem(priv->width * priv->height);
- bytes_per_blocklines[0] = priv->width;
- bytes_per_mcu[0] = 8;
- break;
-
- default:
- trace("Bad pixel format\n");
- return -1;
- }
-
- xstride_by_mcu = ystride_by_mcu = 8;
- if ((priv->component_infos[cY].Hfactor | priv->component_infos[cY].Vfactor) == 1) {
- decode_MCU = decode_mcu_table[0];
- convert_to_pixfmt = colorspace_array_conv[0];
- trace("Use decode 1x1 sampling\n");
- } else if (priv->component_infos[cY].Hfactor == 1) {
- decode_MCU = decode_mcu_table[1];
- convert_to_pixfmt = colorspace_array_conv[1];
- ystride_by_mcu = 16;
- trace("Use decode 1x2 sampling (not supported)\n");
- } else if (priv->component_infos[cY].Vfactor == 2) {
- decode_MCU = decode_mcu_table[3];
- convert_to_pixfmt = colorspace_array_conv[3];
- xstride_by_mcu = 16;
- ystride_by_mcu = 16;
- trace("Use decode 2x2 sampling\n");
- } else {
- decode_MCU = decode_mcu_table[2];
- convert_to_pixfmt = colorspace_array_conv[2];
- xstride_by_mcu = 16;
- trace("Use decode 2x1 sampling\n");
- }
-
- resync(priv);
-
- /* Don't forget to that block can be either 8 or 16 lines */
- bytes_per_blocklines[0] *= ystride_by_mcu;
- bytes_per_blocklines[1] *= ystride_by_mcu;
- bytes_per_blocklines[2] *= ystride_by_mcu;
-
- bytes_per_mcu[0] *= xstride_by_mcu/8;
- bytes_per_mcu[1] *= xstride_by_mcu/8;
- bytes_per_mcu[2] *= xstride_by_mcu/8;
-
- /* Just the decode the image by macroblock (size is 8x8, 8x16, or 16x16) */
-
-
-
- for (y=0; y < priv->height; y+=ystride_by_mcu)
- {
- //trace("Decoding row %d\n", y);
- /// priv->plane[0] = priv->components[0] + (y/ystride_by_mcu * bytes_per_blocklines[0]);
- /// priv->plane[1] = priv->components[1] + (y/ystride_by_mcu * bytes_per_blocklines[1]);
- /// priv->plane[2] = priv->components[2] + (y/ystride_by_mcu * bytes_per_blocklines[2]);
- for (x=0; x < priv->width; x+=xstride_by_mcu)
- {
- int i,copy_x,copy_y;
- decode_MCU(priv);
- convert_to_pixfmt(priv);
- //priv->plane[0] += bytes_per_mcu[0];
- //priv->plane[1] += bytes_per_mcu[1];
- //priv->plane[2] += bytes_per_mcu[2];
-
- copy_x=priv->width-x;
- if (copy_x>xstride_by_mcu)
- copy_x=xstride_by_mcu;
-
- copy_y=priv->height-y;
- if (copy_y>ystride_by_mcu)
- copy_y=ystride_by_mcu;
-
- for(i=0;i<copy_y;i++) {
- unsigned char *dst = &priv->components[0][((y+i)*priv->width+x)*3];
- memcpy(dst,&priv->decomp_block[i][0],copy_x*3);
- }
-
- if (priv->restarts_to_go>0)
- {
- priv->restarts_to_go--;
- if (priv->restarts_to_go == 0)
- {
- priv->stream -= (priv->nbits_in_reservoir/8);
- resync(priv);
- if (find_next_rst_marker(priv) < 0)
- return -1;
- }
- }
- }
- }
-
- trace("Input file size: %d\n", priv->stream_length+2);
- trace("Input bytes actually read: %d\n", priv->stream - priv->stream_begin + 2);
-
- return 0;
-}
-
-const char *tinyjpeg_get_errorstring(struct jdec_private *priv)
-{
- /* FIXME: the error string must be store in the context */
- priv = priv;
- return error_string;
-}
-
-void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int *height)
-{
- *width = priv->width;
- *height = priv->height;
-}
-
-int tinyjpeg_get_components(struct jdec_private *priv, unsigned char **components)
-{
- int i;
- for (i=0; priv->components[i] && i<COMPONENTS; i++)
- components[i] = priv->components[i];
- return 0;
-}
-
-int tinyjpeg_set_components(struct jdec_private *priv, unsigned char **components, unsigned int ncomponents)
-{
- unsigned int i;
- if (ncomponents > COMPONENTS)
- ncomponents = COMPONENTS;
- for (i=0; i<ncomponents; i++)
- priv->components[i] = components[i];
- return 0;
-}
-
-int tinyjpeg_set_flags(struct jdec_private *priv, int flags)
-{
- int oldflags = priv->flags;
- priv->flags = flags;
- return oldflags;
-}
-
diff --git a/drivers/jpg/tinyjpeg.h b/drivers/jpg/tinyjpeg.h
deleted file mode 100644
index fe4652360b..0000000000
--- a/drivers/jpg/tinyjpeg.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Small jpeg decoder library (header file)
- *
- * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the author nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#ifndef __JPEGDEC_H__
-#define __JPEGDEC_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct jdec_private;
-
-/* Flags that can be set by any applications */
-#define TINYJPEG_FLAGS_MJPEG_TABLE (1<<1)
-
-/* Format accepted in outout */
-enum tinyjpeg_fmt {
- TINYJPEG_FMT_GREY = 1,
- TINYJPEG_FMT_BGR24,
- TINYJPEG_FMT_RGB24,
- TINYJPEG_FMT_YUV420P,
-};
-
-struct jdec_private *tinyjpeg_init(void *(*allocate_mem)(unsigned int),void (*free_mem)(void *));
-
-void tinyjpeg_free(struct jdec_private *priv);
-
-int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size);
-int tinyjpeg_decode(struct jdec_private *priv, int pixel_format);
-const char *tinyjpeg_get_errorstring(struct jdec_private *priv);
-void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int *height);
-int tinyjpeg_get_components(struct jdec_private *priv, unsigned char **components);
-int tinyjpeg_set_components(struct jdec_private *priv, unsigned char **components, unsigned int ncomponents);
-int tinyjpeg_set_flags(struct jdec_private *priv, int flags);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
-
diff --git a/drivers/nedmalloc/memory_pool_static_nedmalloc.cpp b/drivers/nedmalloc/memory_pool_static_nedmalloc.cpp
index 76090844fe..301e94bb7b 100644
--- a/drivers/nedmalloc/memory_pool_static_nedmalloc.cpp
+++ b/drivers/nedmalloc/memory_pool_static_nedmalloc.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/drivers/nedmalloc/memory_pool_static_nedmalloc.h b/drivers/nedmalloc/memory_pool_static_nedmalloc.h
index 49f648a37b..20b060537c 100644
--- a/drivers/nedmalloc/memory_pool_static_nedmalloc.h
+++ b/drivers/nedmalloc/memory_pool_static_nedmalloc.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/drivers/nrex/README.md b/drivers/nrex/README.md
index 951b301c1e..9ff67992dc 100644
--- a/drivers/nrex/README.md
+++ b/drivers/nrex/README.md
@@ -1,5 +1,7 @@
# NREX: Node RegEx
+Version 0.1
+
Small node-based regular expression library. It only does text pattern
matchhing, not replacement. To use add the files `nrex.hpp`, `nrex.cpp`
and `nrex_config.h` to your project and follow the example:
@@ -32,7 +34,7 @@ Currently supported features:
* Unicode `\uFFFF` code points
* Positive `(?=)` and negative `(?!)` lookahead
* Positive `(?<=)` and negative `(?<!)` lookbehind (fixed length and no alternations)
- * Backreferences `\1` to `\9` (with option to expand to `\99`)
+ * Backreferences `\1` and `\g{1}` (limited by default to 9 - can be unlimited)
## License
diff --git a/drivers/nrex/nrex.cpp b/drivers/nrex/nrex.cpp
index 104e07f887..1eb9ec38c8 100644
--- a/drivers/nrex/nrex.cpp
+++ b/drivers/nrex/nrex.cpp
@@ -1,4 +1,5 @@
// NREX: Node RegEx
+// Version 0.1
//
// Copyright (c) 2015, Zher Huei Lee
// All rights reserved.
@@ -299,6 +300,10 @@ struct nrex_node_group : public nrex_node
{
length = 1;
}
+ if (mode == LookAhead || mode == LookBehind)
+ {
+ quantifiable = false;
+ }
}
virtual ~nrex_node_group()
@@ -322,6 +327,10 @@ struct nrex_node_group : public nrex_node
int offset = 0;
if (mode == LookBehind)
{
+ if (pos < length)
+ {
+ return -1;
+ }
offset = length;
}
int res = childset[i]->test(s, pos - offset);
@@ -450,7 +459,7 @@ struct nrex_node_char : public nrex_node
int test(nrex_search* s, int pos) const
{
- if (s->end == pos || s->at(pos) != ch)
+ if (s->end <= pos || 0 > pos || s->at(pos) != ch)
{
return -1;
}
@@ -473,7 +482,7 @@ struct nrex_node_range : public nrex_node
int test(nrex_search* s, int pos) const
{
- if (s->end == pos)
+ if (s->end <= pos || 0 > pos)
{
return -1;
}
@@ -555,7 +564,7 @@ struct nrex_node_class : public nrex_node
int test(nrex_search* s, int pos) const
{
- if (s->end == pos)
+ if (s->end <= pos || 0 > pos)
{
return -1;
}
@@ -727,7 +736,7 @@ struct nrex_node_shorthand : public nrex_node
int test(nrex_search* s, int pos) const
{
- if (s->end == pos)
+ if (s->end <= pos || 0 > pos)
{
return -1;
}
@@ -811,16 +820,12 @@ struct nrex_node_quantifier : public nrex_node
int test(nrex_search* s, int pos) const
{
- return test_step(s, pos, 1);
+ return test_step(s, pos, 0, pos);
}
- int test_step(nrex_search* s, int pos, int level) const
+ int test_step(nrex_search* s, int pos, int level, int start) const
{
- if (max == 0)
- {
- return pos;
- }
- if ((max >= 1 && level > max) || pos > s->end)
+ if (pos > s->end)
{
return -1;
}
@@ -840,14 +845,26 @@ struct nrex_node_quantifier : public nrex_node
return res;
}
}
- int res = child->test(s, pos);
- if (s->complete)
+ if (max >= 0 && level > max)
{
- return res;
+ return -1;
+ }
+ if (level > 1 && level > min + 1 && pos == start)
+ {
+ return -1;
+ }
+ int res = pos;
+ if (level >= 1)
+ {
+ res = child->test(s, pos);
+ if (s->complete)
+ {
+ return res;
+ }
}
if (res >= 0)
{
- int res_step = test_step(s, res, level + 1);
+ int res_step = test_step(s, res, level + 1, start);
if (res_step >= 0)
{
return res_step;
@@ -983,6 +1000,13 @@ nrex::nrex()
{
}
+nrex::nrex(const nrex_char* pattern, int captures)
+ : _capturing(0)
+ , _root(NULL)
+{
+ compile(pattern, captures);
+}
+
nrex::~nrex()
{
if (_root)
@@ -1008,10 +1032,14 @@ void nrex::reset()
int nrex::capture_size() const
{
- return _capturing + 1;
+ if (_root)
+ {
+ return _capturing + 1;
+ }
+ return 0;
}
-bool nrex::compile(const nrex_char* pattern, bool extended)
+bool nrex::compile(const nrex_char* pattern, int captures)
{
reset();
nrex_node_group* root = NREX_NEW(nrex_node_group(_capturing));
@@ -1053,7 +1081,7 @@ bool nrex::compile(const nrex_char* pattern, bool extended)
NREX_COMPILE_ERROR("unrecognised qualifier for group");
}
}
- else if ((!extended && _capturing < 9) || (extended && _capturing < 99))
+ else if (captures >= 0 && _capturing < captures)
{
nrex_node_group* group = NREX_NEW(nrex_node_group(++_capturing));
stack.top()->add_child(group);
@@ -1190,15 +1218,6 @@ bool nrex::compile(const nrex_char* pattern, bool extended)
}
else if (nrex_is_quantifier(c[0]))
{
- if (stack.top()->back == NULL || !stack.top()->back->quantifiable)
- {
- if (c[0] == '{')
- {
- stack.top()->add_child(NREX_NEW(nrex_node_char('{')));
- continue;
- }
- NREX_COMPILE_ERROR("element not quantifiable");
- }
int min = 0;
int max = -1;
bool valid_quantifier = true;
@@ -1270,6 +1289,10 @@ bool nrex::compile(const nrex_char* pattern, bool extended)
}
if (valid_quantifier)
{
+ if (stack.top()->back == NULL || !stack.top()->back->quantifiable)
+ {
+ NREX_COMPILE_ERROR("element not quantifiable");
+ }
nrex_node_quantifier* quant = NREX_NEW(nrex_node_quantifier(min, max));
if (min == max)
{
@@ -1323,20 +1346,26 @@ bool nrex::compile(const nrex_char* pattern, bool extended)
stack.top()->add_child(NREX_NEW(nrex_node_shorthand(c[1])));
++c;
}
- else if ('1' <= c[1] && c[1] <= '9')
+ else if (('1' <= c[1] && c[1] <= '9') || (c[1] == 'g' && c[2] == '{'))
{
int ref = 0;
- if (extended && '0' <= c[2] && c[2] <= '9')
+ bool unclosed = false;
+ if (c[1] == 'g')
{
- ref = int(c[1] - '0') * 10 + int(c[2] - '0');
+ unclosed = true;
c = &c[2];
}
- else
+ while ('0' <= c[1] && c[1] <= '9')
{
- ref = int(c[1] - '0');
+ ref = ref * 10 + int(c[1] - '0');
++c;
}
- if (ref > _capturing)
+ if (c[1] == '}')
+ {
+ unclosed = false;
+ ++c;
+ }
+ if (ref > _capturing || ref <= 0 || unclosed)
{
NREX_COMPILE_ERROR("backreference to non-existent capture");
}
@@ -1377,6 +1406,10 @@ bool nrex::compile(const nrex_char* pattern, bool extended)
bool nrex::match(const nrex_char* str, nrex_result* captures, int offset, int end) const
{
+ if (!_root)
+ {
+ return false;
+ }
nrex_search s(str, captures);
if (end >= offset)
{
@@ -1386,7 +1419,7 @@ bool nrex::match(const nrex_char* str, nrex_result* captures, int offset, int en
{
s.end = NREX_STRLEN(str);
}
- for (int i = offset; i < s.end; ++i)
+ for (int i = offset; i <= s.end; ++i)
{
for (int c = 0; c <= _capturing; ++c)
{
diff --git a/drivers/nrex/nrex.hpp b/drivers/nrex/nrex.hpp
index e26a61c39a..44e950c517 100644
--- a/drivers/nrex/nrex.hpp
+++ b/drivers/nrex/nrex.hpp
@@ -1,4 +1,5 @@
// NREX: Node RegEx
+// Version 0.1
//
// Copyright (c) 2015, Zher Huei Lee
// All rights reserved.
@@ -59,7 +60,32 @@ class nrex
int _capturing;
nrex_node* _root;
public:
+
+ /*!
+ * \brief Initialises an empty regex container
+ */
nrex();
+
+ /*!
+ * \brief Initialises and compiles the regex pattern
+ *
+ * This calls nrex::compile() with the same arguments. To check whether
+ * the compilation was successfull, use nrex::valid().
+ *
+ * If the NREX_THROW_ERROR was defined it would automatically throw a
+ * runtime error nrex_compile_error if it encounters a problem when
+ * parsing the pattern.
+ *
+ * \param pattern The regex pattern
+ * \param captures The maximum number of capture groups to allow. Any
+ * extra would be converted to non-capturing groups.
+ * If negative, no limit would be imposed. Defaults
+ * to 9.
+ *
+ * \see nrex::compile()
+ */
+ nrex(const nrex_char* pattern, int captures = 9);
+
~nrex();
/*!
@@ -78,9 +104,9 @@ class nrex
*
* This is used to provide the array size of the captures needed for
* nrex::match() to work. The size is actually the number of capture
- * groups + one for the matching of the entire pattern. The result is
- * always capped at 10 or 100, depending on the extend option given in
- * nrex::compile() (default 10).
+ * groups + one for the matching of the entire pattern. This can be
+ * capped using the extra argument given in nrex::compile()
+ * (default 10).
*
* \return The number of captures
*/
@@ -97,12 +123,13 @@ class nrex
* parsing the pattern.
*
* \param pattern The regex pattern
- * \param extended If true, raises the limit on number of capture
- * groups and back-references to 99. Otherwise limited
- * to 9. Defaults to false.
+ * \param captures The maximum number of capture groups to allow. Any
+ * extra would be converted to non-capturing groups.
+ * If negative, no limit would be imposed. Defaults
+ * to 9.
* \return True if the pattern was succesfully compiled
*/
- bool compile(const nrex_char* pattern, bool extended = false);
+ bool compile(const nrex_char* pattern, int captures = 9);
/*!
* \brief Uses the pattern to search through the provided string
diff --git a/drivers/nrex/regex.cpp b/drivers/nrex/regex.cpp
index 246384b10a..459cf28e1e 100644
--- a/drivers/nrex/regex.cpp
+++ b/drivers/nrex/regex.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
@@ -15,7 +15,7 @@
void RegEx::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("compile","pattern", "expanded"),&RegEx::compile, DEFVAL(true));
+ ObjectTypeDB::bind_method(_MD("compile","pattern", "capture"),&RegEx::compile, DEFVAL(9));
ObjectTypeDB::bind_method(_MD("find","text","start","end"),&RegEx::find, DEFVAL(0), DEFVAL(-1));
ObjectTypeDB::bind_method(_MD("clear"),&RegEx::clear);
ObjectTypeDB::bind_method(_MD("is_valid"),&RegEx::is_valid);
@@ -68,11 +68,11 @@ String RegEx::get_capture(int capture) const {
}
-Error RegEx::compile(const String& p_pattern, bool expanded) {
+Error RegEx::compile(const String& p_pattern, int capture) {
clear();
- exp.compile(p_pattern.c_str(), expanded);
+ exp.compile(p_pattern.c_str(), capture);
ERR_FAIL_COND_V( !exp.valid(), FAILED );
diff --git a/drivers/nrex/regex.h b/drivers/nrex/regex.h
index be52da8149..ae8d40ceab 100644
--- a/drivers/nrex/regex.h
+++ b/drivers/nrex/regex.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
@@ -36,7 +36,7 @@ public:
bool is_valid() const;
int get_capture_count() const;
String get_capture(int capture) const;
- Error compile(const String& p_pattern, bool expanded = false);
+ Error compile(const String& p_pattern, int capture = 9);
int find(const String& p_text, int p_start = 0, int p_end = -1) const;
RegEx();
diff --git a/drivers/openssl/stream_peer_openssl.cpp b/drivers/openssl/stream_peer_openssl.cpp
index ef07f11334..81795fdc60 100644
--- a/drivers/openssl/stream_peer_openssl.cpp
+++ b/drivers/openssl/stream_peer_openssl.cpp
@@ -479,6 +479,13 @@ Error StreamPeerOpenSSL::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_
return OK;
}
+int StreamPeerOpenSSL::get_available_bytes() const {
+
+ ERR_FAIL_COND_V(!connected,0);
+
+ return SSL_pending(ssl);
+
+}
StreamPeerOpenSSL::StreamPeerOpenSSL() {
ctx=NULL;
diff --git a/drivers/openssl/stream_peer_openssl.h b/drivers/openssl/stream_peer_openssl.h
index a66b641dd4..64f5a1d7ac 100644
--- a/drivers/openssl/stream_peer_openssl.h
+++ b/drivers/openssl/stream_peer_openssl.h
@@ -71,6 +71,8 @@ public:
virtual Error get_data(uint8_t* p_buffer, int p_bytes);
virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received);
+ virtual int get_available_bytes() const;
+
static void initialize_ssl();
static void finalize_ssl();
diff --git a/drivers/opus/audio_stream_opus.cpp b/drivers/opus/audio_stream_opus.cpp
index eb9c81e152..ab53fee0c9 100644
--- a/drivers/opus/audio_stream_opus.cpp
+++ b/drivers/opus/audio_stream_opus.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Author: George Marques <george@gmarqu.es> */
/* */
diff --git a/drivers/opus/audio_stream_opus.h b/drivers/opus/audio_stream_opus.h
index 2f173cc270..fc5531470d 100644
--- a/drivers/opus/audio_stream_opus.h
+++ b/drivers/opus/audio_stream_opus.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Author: George Marques <george@gmarqu.es> */
/* */
diff --git a/drivers/png/SCsub b/drivers/png/SCsub
index 9ee066cbb2..5532e28ade 100644
--- a/drivers/png/SCsub
+++ b/drivers/png/SCsub
@@ -23,15 +23,18 @@ png_sources = [
]
if ("neon_enabled" in env and env["neon_enabled"]):
+ env.Append(CPPFLAGS=["-DPNG_ARM_NEON_OPT=2"])
env_neon = env.Clone();
if "S_compiler" in env:
env_neon['CC'] = env['S_compiler']
- env_neon.Append(CPPFLAGS=["-DPNG_ARM_NEON"])
+ #env_neon.Append(CPPFLAGS=["-DPNG_ARM_NEON"])
import os
# Currently .ASM filter_neon.S does not compile on NT.
if (os.name!="nt"):
- png_sources.append(env_neon.Object("#drivers/png/filter_neon.S"))
-
+ png_sources.append(env_neon.Object("#drivers/png/arm/arm_init.c"))
+ png_sources.append(env_neon.Object("#drivers/png/arm/filter_neon.S"))
+else:
+ env.Append(CPPFLAGS=["-DPNG_ARM_NEON_OPT=0"])
env.drivers_sources+=png_sources
diff --git a/drivers/png/arm/arm_init.c b/drivers/png/arm/arm_init.c
new file mode 100644
index 0000000000..6a6a019acb
--- /dev/null
+++ b/drivers/png/arm/arm_init.c
@@ -0,0 +1,232 @@
+
+/* arm_init.c - NEON optimised filter functions
+ *
+ * Copyright (c) 2013 Glenn Randers-Pehrson
+ * Written by Mans Rullgard, 2011.
+ * Last changed in libpng 1.6.8 [December 19, 2013]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
+ * called.
+ */
+#define _POSIX_SOURCE 1
+
+#include "../pngpriv.h"
+
+#ifdef PNG_READ_SUPPORTED
+#if PNG_ARM_NEON_OPT > 0
+#ifdef PNG_ARM_NEON_CHECK_SUPPORTED /* Do run-time checks */
+#include <signal.h> /* for sig_atomic_t */
+
+#ifdef __ANDROID__
+/* Linux provides access to information about CPU capabilites via
+ * /proc/self/auxv, however Android blocks this while still claiming to be
+ * Linux. The Andoid NDK, however, provides appropriate support.
+ *
+ * Documentation: http://www.kandroid.org/ndk/docs/CPU-ARM-NEON.html
+ */
+#include <cpu-features.h>
+
+static int
+png_have_neon(png_structp png_ptr)
+{
+ /* This is a whole lot easier than the mess below, however it is probably
+ * implemented as below, therefore it is better to cache the result (these
+ * function calls may be slow!)
+ */
+ PNG_UNUSED(png_ptr)
+ return android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM &&
+ (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
+}
+#elif defined(__linux__)
+/* The generic __linux__ implementation requires reading /proc/self/auxv and
+ * looking at each element for one that records NEON capabilities.
+ */
+#include <unistd.h> /* for POSIX 1003.1 */
+#include <errno.h> /* for EINTR */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <elf.h>
+#include <asm/hwcap.h>
+
+/* A read call may be interrupted, in which case it returns -1 and sets errno to
+ * EINTR if nothing was done, otherwise (if something was done) a partial read
+ * may result.
+ */
+static size_t
+safe_read(png_structp png_ptr, int fd, void *buffer_in, size_t nbytes)
+{
+ size_t ntotal = 0;
+ char *buffer = png_voidcast(char*, buffer_in);
+
+ while (nbytes > 0)
+ {
+ unsigned int nread;
+ int iread;
+
+ /* Passing nread > INT_MAX to read is implementation defined in POSIX
+ * 1003.1, therefore despite the unsigned argument portable code must
+ * limit the value to INT_MAX!
+ */
+ if (nbytes > INT_MAX)
+ nread = INT_MAX;
+
+ else
+ nread = (unsigned int)/*SAFE*/nbytes;
+
+ iread = read(fd, buffer, nread);
+
+ if (iread == -1)
+ {
+ /* This is the devil in the details, a read can terminate early with 0
+ * bytes read because of EINTR, yet it still returns -1 otherwise end
+ * of file cannot be distinguished.
+ */
+ if (errno != EINTR)
+ {
+ png_warning(png_ptr, "/proc read failed");
+ return 0; /* I.e., a permanent failure */
+ }
+ }
+
+ else if (iread < 0)
+ {
+ /* Not a valid 'read' result: */
+ png_warning(png_ptr, "OS /proc read bug");
+ return 0;
+ }
+
+ else if (iread > 0)
+ {
+ /* Continue reading until a permanent failure, or EOF */
+ buffer += iread;
+ nbytes -= (unsigned int)/*SAFE*/iread;
+ ntotal += (unsigned int)/*SAFE*/iread;
+ }
+
+ else
+ return ntotal;
+ }
+
+ return ntotal; /* nbytes == 0 */
+}
+
+static int
+png_have_neon(png_structp png_ptr)
+{
+ int fd = open("/proc/self/auxv", O_RDONLY);
+ Elf32_auxv_t aux;
+
+ /* Failsafe: failure to open means no NEON */
+ if (fd == -1)
+ {
+ png_warning(png_ptr, "/proc/self/auxv open failed");
+ return 0;
+ }
+
+ while (safe_read(png_ptr, fd, &aux, sizeof aux) == sizeof aux)
+ {
+ if (aux.a_type == AT_HWCAP && (aux.a_un.a_val & HWCAP_NEON) != 0)
+ {
+ close(fd);
+ return 1;
+ }
+ }
+
+ close(fd);
+ return 0;
+}
+#else
+ /* We don't know how to do a run-time check on this system */
+# error "no support for run-time ARM NEON checks"
+#endif /* OS checks */
+#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
+
+#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
+# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
+#endif
+
+void
+png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
+{
+ /* The switch statement is compiled in for ARM_NEON_API, the call to
+ * png_have_neon is compiled in for ARM_NEON_CHECK. If both are defined
+ * the check is only performed if the API has not set the NEON option on
+ * or off explicitly. In this case the check controls what happens.
+ *
+ * If the CHECK is not compiled in and the option is UNSET the behavior prior
+ * to 1.6.7 was to use the NEON code - this was a bug caused by having the
+ * wrong order of the 'ON' and 'default' cases. UNSET now defaults to OFF,
+ * as documented in png.h
+ */
+#ifdef PNG_ARM_NEON_API_SUPPORTED
+ switch ((pp->options >> PNG_ARM_NEON) & 3)
+ {
+ case PNG_OPTION_UNSET:
+ /* Allow the run-time check to execute if it has been enabled -
+ * thus both API and CHECK can be turned on. If it isn't supported
+ * this case will fall through to the 'default' below, which just
+ * returns.
+ */
+#endif /* PNG_ARM_NEON_API_SUPPORTED */
+#ifdef PNG_ARM_NEON_CHECK_SUPPORTED
+ {
+ static volatile sig_atomic_t no_neon = -1; /* not checked */
+
+ if (no_neon < 0)
+ no_neon = !png_have_neon(pp);
+
+ if (no_neon)
+ return;
+ }
+#ifdef PNG_ARM_NEON_API_SUPPORTED
+ break;
+#endif
+#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
+
+#ifdef PNG_ARM_NEON_API_SUPPORTED
+ default: /* OFF or INVALID */
+ return;
+
+ case PNG_OPTION_ON:
+ /* Option turned on */
+ break;
+ }
+#endif
+
+ /* IMPORTANT: any new external functions used here must be declared using
+ * PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the
+ * 'prefix' option to configure works:
+ *
+ * ./configure --with-libpng-prefix=foobar_
+ *
+ * Verify you have got this right by running the above command, doing a build
+ * and examining pngprefix.h; it must contain a #define for every external
+ * function you add. (Notice that this happens automatically for the
+ * initialization function.)
+ */
+ pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon;
+
+ if (bpp == 3)
+ {
+ pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon;
+ pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon;
+ pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
+ png_read_filter_row_paeth3_neon;
+ }
+
+ else if (bpp == 4)
+ {
+ pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon;
+ pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon;
+ pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
+ png_read_filter_row_paeth4_neon;
+ }
+}
+#endif /* PNG_ARM_NEON_OPT > 0 */
+#endif /* PNG_READ_SUPPORTED */
diff --git a/drivers/png/filter_neon.S b/drivers/png/arm/filter_neon.S
index 63a5d8c17f..477df7c99b 100644
--- a/drivers/png/filter_neon.S
+++ b/drivers/png/arm/filter_neon.S
@@ -1,18 +1,27 @@
/* filter_neon.S - NEON optimised filter functions
*
- * Copyright (c) 2011 Glenn Randers-Pehrson
+ * Copyright (c) 2013 Glenn Randers-Pehrson
* Written by Mans Rullgard, 2011.
+ * Last changed in libpng 1.5.17 [June 27, 2013]
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
+/* This is required to get the symbol renames, which are #defines, and also
+ * includes the definition (or not) of PNG_ARM_NEON_OPT.
+ */
+#define PNG_VERSION_INFO_ONLY
+#include "../pngpriv.h"
+
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
#endif
+#if PNG_ARM_NEON_OPT > 0
+
#ifdef __ELF__
# define ELF
#else
@@ -223,3 +232,4 @@ func png_read_filter_row_paeth3_neon, export=1
pop {r4,pc}
endfunc
+#endif /* PNG_ARM_NEON_OPT > 0 */
diff --git a/drivers/png/example.c b/drivers/png/example.c
index ec53a8cdee..7171d9847e 100644
--- a/drivers/png/example.c
+++ b/drivers/png/example.c
@@ -2,8 +2,8 @@
#if 0 /* in case someone actually tries to compile this */
/* example.c - an example of using libpng
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Maintained 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.19 [August 21, 2014]
+ * Maintained 1998-2014 Glenn Randers-Pehrson
* Maintained 1996, 1997 Andreas Dilger
* Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
*/
@@ -89,7 +89,7 @@ void read_png(char *file_name) /* We need to open the file */
{
png_structp png_ptr;
png_infop info_ptr;
- unsigned int sig_read = 0;
+ int sig_read = 0;
png_uint_32 width, height;
int bit_depth, color_type, interlace_type;
FILE *fp;
@@ -98,7 +98,7 @@ void read_png(char *file_name) /* We need to open the file */
return (ERROR);
#else no_open_file /* prototype 2 */
-void read_png(FILE *fp, unsigned int sig_read) /* File is already open */
+void read_png(FILE *fp, int sig_read) /* File is already open */
{
png_structp png_ptr;
png_infop info_ptr;
@@ -188,7 +188,7 @@ void read_png(FILE *fp, unsigned int sig_read) /* File is already open */
* are mutually exclusive.
*/
- /* Tell libpng to strip 16 bit/color files down to 8 bits/color.
+ /* Tell libpng to strip 16 bits/color files down to 8 bits/color.
* Use accurate scaling if it's available, otherwise just chop off the
* low byte.
*/
@@ -259,9 +259,9 @@ void read_png(FILE *fp, unsigned int sig_read) /* File is already open */
/* If we don't have another value */
else
{
- screen_gamma = 2.2; /* A good guess for a PC monitor in a dimly
- lit room */
- screen_gamma = 1.7 or 1.0; /* A good guess for Mac systems */
+ screen_gamma = PNG_DEFAULT_sRGB; /* A good guess for a PC monitor
+ in a dimly lit room */
+ screen_gamma = PNG_GAMMA_MAC_18 or 1.0; /* Good guesses for Mac systems */
}
/* Tell libpng to handle the gamma conversion for you. The final call
@@ -273,7 +273,7 @@ void read_png(FILE *fp, unsigned int sig_read) /* File is already open */
int intent;
if (png_get_sRGB(png_ptr, info_ptr, &intent))
- png_set_gamma(png_ptr, screen_gamma, 0.45455);
+ png_set_gamma(png_ptr, screen_gamma, PNG_DEFAULT_sRGB);
else
{
double image_gamma;
@@ -284,7 +284,7 @@ void read_png(FILE *fp, unsigned int sig_read) /* File is already open */
}
#ifdef PNG_READ_QUANTIZE_SUPPORTED
- /* Quantize RGB files down to 8 bit palette or reduce palettes
+ /* Quantize RGB files down to 8-bit palette or reduce palettes
* to the number of colors available on your screen.
*/
if (color_type & PNG_COLOR_MASK_COLOR)
@@ -336,7 +336,7 @@ void read_png(FILE *fp, unsigned int sig_read) /* File is already open */
/* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
png_set_swap_alpha(png_ptr);
- /* Swap bytes of 16 bit files to least significant byte first */
+ /* Swap bytes of 16-bit files to least significant byte first */
png_set_swap(png_ptr);
/* Add filler (or alpha) byte (before/after each RGB triplet) */
@@ -695,25 +695,38 @@ void write_png(char *file_name /* , ... other image information ... */)
png_set_gAMA(png_ptr, info_ptr, gamma);
/* Optionally write comments into the image */
- text_ptr[0].key = "Title";
- text_ptr[0].text = "Mona Lisa";
- text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
- text_ptr[0].itxt_length = 0;
- text_ptr[0].lang = NULL;
- text_ptr[0].lang_key = NULL;
- text_ptr[1].key = "Author";
- text_ptr[1].text = "Leonardo DaVinci";
- text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
- text_ptr[1].itxt_length = 0;
- text_ptr[1].lang = NULL;
- text_ptr[1].lang_key = NULL;
- text_ptr[2].key = "Description";
- text_ptr[2].text = "<long text>";
- text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
- text_ptr[2].itxt_length = 0;
- text_ptr[2].lang = NULL;
- text_ptr[2].lang_key = NULL;
- png_set_text(png_ptr, info_ptr, text_ptr, 3);
+ {
+ png_text text_ptr[3];
+
+ char key0[]="Title";
+ char text0[]="Mona Lisa";
+ text_ptr[0].key = key0;
+ text_ptr[0].text = text0;
+ text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
+ text_ptr[0].itxt_length = 0;
+ text_ptr[0].lang = NULL;
+ text_ptr[0].lang_key = NULL;
+
+ char key1[]="Author";
+ char text1[]="Leonardo DaVinci";
+ text_ptr[1].key = key1;
+ text_ptr[1].text = text1;
+ text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
+ text_ptr[1].itxt_length = 0;
+ text_ptr[1].lang = NULL;
+ text_ptr[1].lang_key = NULL;
+
+ char key2[]="Description";
+ char text2[]="<long text>";
+ text_ptr[2].key = key2;
+ text_ptr[2].text = text2;
+ text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
+ text_ptr[2].itxt_length = 0;
+ text_ptr[2].lang = NULL;
+ text_ptr[2].lang_key = NULL;
+
+ png_set_text(write_ptr, write_info_ptr, text_ptr, 3);
+ }
/* Other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs */
@@ -737,7 +750,7 @@ void write_png(char *file_name /* , ... other image information ... */)
*/
/* Once we write out the header, the compression type on the text
- * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
+ * chunk gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
* PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
* at the end.
*/
@@ -771,11 +784,11 @@ void write_png(char *file_name /* , ... other image information ... */)
/* Swap bytes of 16-bit files to most significant byte first */
png_set_swap(png_ptr);
- /* Swap bits of 1, 2, 4 bit packed pixel formats */
+ /* Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats */
png_set_packswap(png_ptr);
/* Turn on interlace handling if you are not using png_write_image() */
- if (interlacing)
+ if (interlacing != 0)
number_passes = png_set_interlace_handling(png_ptr);
else
@@ -786,12 +799,16 @@ void write_png(char *file_name /* , ... other image information ... */)
* use the first method if you aren't handling interlacing yourself.
*/
png_uint_32 k, height, width;
- png_byte image[height][width*bytes_per_pixel];
+
+ /* In this example, "image" is a one-dimensional array of bytes */
+ png_byte image[height*width*bytes_per_pixel];
+
png_bytep row_pointers[height];
if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
png_error (png_ptr, "Image is too tall to process in memory");
+ /* Set up pointers into your "image" byte array */
for (k = 0; k < height; k++)
row_pointers[k] = image + k*width*bytes_per_pixel;
diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp
index 2a4720b07b..50b26d601a 100644
--- a/drivers/png/image_loader_png.cpp
+++ b/drivers/png/image_loader_png.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -124,6 +124,13 @@ Error ImageLoaderPNG::_load_image(void *rf_up,png_rw_ptr p_func,Image *p_image)
png_read_update_info(png, info);
}
+ if (png_get_valid(png,info,PNG_INFO_tRNS)) {
+// png_set_expand_gray_1_2_4_to_8(png);
+ png_set_tRNS_to_alpha(png);
+ png_read_update_info(png, info);
+ png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);
+ }
+
int palette_colors = 0;
int palette_components = 0;
int components = 0;
diff --git a/drivers/png/image_loader_png.h b/drivers/png/image_loader_png.h
index 8413a7eae1..d87d67d898 100644
--- a/drivers/png/image_loader_png.h
+++ b/drivers/png/image_loader_png.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/png/png.c b/drivers/png/png.c
index 08074485b8..cd7da59222 100644
--- a/drivers/png/png.c
+++ b/drivers/png/png.c
@@ -1,8 +1,8 @@
/* png.c - location for general purpose libpng functions
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.23 [July 23, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -14,7 +14,7 @@
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_5_7 Your_png_h_is_not_version_1_5_7;
+typedef png_libpng_version_1_5_26 Your_png_h_is_not_version_1_5_26;
/* Tells libpng that we have already handled the first "num_bytes" bytes
* of the PNG file signature. If the PNG data is embedded into another
@@ -26,15 +26,20 @@ typedef png_libpng_version_1_5_7 Your_png_h_is_not_version_1_5_7;
void PNGAPI
png_set_sig_bytes(png_structp png_ptr, int num_bytes)
{
+ unsigned int nb = (unsigned int)num_bytes;
+
png_debug(1, "in png_set_sig_bytes");
if (png_ptr == NULL)
return;
- if (num_bytes > 8)
+ if (num_bytes < 0)
+ nb = 0;
+
+ if (nb > 8)
png_error(png_ptr, "Too many bytes for PNG signature");
- png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes);
+ png_ptr->sig_bytes = (png_byte)nb;
}
/* Checks whether the supplied bytes match the PNG signature. We allow
@@ -73,13 +78,16 @@ PNG_FUNCTION(voidpf /* PRIVATE */,
png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED)
{
png_voidp ptr;
- png_structp p=(png_structp)png_ptr;
- png_uint_32 save_flags=p->flags;
+ png_structp p;
+ png_uint_32 save_flags;
png_alloc_size_t num_bytes;
if (png_ptr == NULL)
return (NULL);
+ p=(png_structp)png_ptr;
+ save_flags=p->flags;
+
if (items > PNG_UINT_32_MAX/size)
{
png_warning (p, "Potential overflow in png_zalloc()");
@@ -146,9 +154,10 @@ png_calculate_crc(png_structp png_ptr, png_const_bytep ptr, png_size_t length)
do
{
uInt safeLength = (uInt)length;
+#ifndef __COVERITY__
if (safeLength == 0)
safeLength = (uInt)-1; /* evil, but safe */
-
+#endif
crc = crc32(crc, ptr, safeLength);
/* The following should never issue compiler warnings, if they do the
@@ -171,49 +180,51 @@ png_calculate_crc(png_structp png_ptr, png_const_bytep ptr, png_size_t length)
int
png_user_version_check(png_structp png_ptr, png_const_charp user_png_ver)
{
- if (user_png_ver)
+ /* Libpng versions 1.0.0 and later are binary compatible if the version
+ * string matches through the second '.'; we must recompile any
+ * applications that use any older library version.
+ */
+
+ if (user_png_ver != NULL)
{
- int i = 0;
+ int i = -1;
+ int found_dots = 0;
do
{
- if (user_png_ver[i] != png_libpng_ver[i])
+ i++;
+ if (user_png_ver[i] != PNG_LIBPNG_VER_STRING[i])
png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
- } while (png_libpng_ver[i++]);
+ if (user_png_ver[i] == '.')
+ found_dots++;
+ } while (found_dots < 2 && user_png_ver[i] != 0 &&
+ PNG_LIBPNG_VER_STRING[i] != 0);
}
else
png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
- if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
+ if ((png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) != 0)
{
- /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
- * we must recompile any applications that use any older library version.
- * For versions after libpng 1.0, we will be compatible, so we need
- * only check the first digit.
- */
- if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
- (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
- (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
- {
#ifdef PNG_WARNINGS_SUPPORTED
- size_t pos = 0;
- char m[128];
+ size_t pos = 0;
+ char m[128];
- pos = png_safecat(m, sizeof m, pos, "Application built with libpng-");
- pos = png_safecat(m, sizeof m, pos, user_png_ver);
- pos = png_safecat(m, sizeof m, pos, " but running with ");
- pos = png_safecat(m, sizeof m, pos, png_libpng_ver);
+ pos = png_safecat(m, (sizeof m), pos,
+ "Application built with libpng-");
+ pos = png_safecat(m, (sizeof m), pos, user_png_ver);
+ pos = png_safecat(m, (sizeof m), pos, " but running with ");
+ pos = png_safecat(m, (sizeof m), pos, PNG_LIBPNG_VER_STRING);
+ PNG_UNUSED(pos)
- png_warning(png_ptr, m);
+ png_warning(png_ptr, m);
#endif
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
- png_ptr->flags = 0;
+ png_ptr->flags = 0;
#endif
- return 0;
- }
+ return 0;
}
/* Success return. */
@@ -300,6 +311,8 @@ png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size)
png_destroy_struct(info_ptr);
info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
*ptr_ptr = info_ptr;
+ if (info_ptr == NULL)
+ return;
}
/* Set everything to 0 */
@@ -337,42 +350,43 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#ifdef PNG_TEXT_SUPPORTED
/* Free text item num or (if num == -1) all text items */
- if ((mask & PNG_FREE_TEXT) & info_ptr->free_me)
+ if (info_ptr->text != 0 &&
+ ((mask & PNG_FREE_TEXT) & info_ptr->free_me) != 0)
{
if (num != -1)
{
- if (info_ptr->text && info_ptr->text[num].key)
- {
- png_free(png_ptr, info_ptr->text[num].key);
- info_ptr->text[num].key = NULL;
- }
+ png_free(png_ptr, info_ptr->text[num].key);
+ info_ptr->text[num].key = NULL;
}
else
{
int i;
+
for (i = 0; i < info_ptr->num_text; i++)
- png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i);
+ png_free(png_ptr, info_ptr->text[i].key);
+
png_free(png_ptr, info_ptr->text);
info_ptr->text = NULL;
- info_ptr->num_text=0;
+ info_ptr->num_text = 0;
}
}
#endif
#ifdef PNG_tRNS_SUPPORTED
/* Free any tRNS entry */
- if ((mask & PNG_FREE_TRNS) & info_ptr->free_me)
+ if (((mask & PNG_FREE_TRNS) & info_ptr->free_me) != 0)
{
+ info_ptr->valid &= ~PNG_INFO_tRNS;
png_free(png_ptr, info_ptr->trans_alpha);
info_ptr->trans_alpha = NULL;
- info_ptr->valid &= ~PNG_INFO_tRNS;
+ info_ptr->num_trans = 0;
}
#endif
#ifdef PNG_sCAL_SUPPORTED
/* Free any sCAL entry */
- if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)
+ if (((mask & PNG_FREE_SCAL) & info_ptr->free_me) != 0)
{
png_free(png_ptr, info_ptr->scal_s_width);
png_free(png_ptr, info_ptr->scal_s_height);
@@ -384,20 +398,20 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#ifdef PNG_pCAL_SUPPORTED
/* Free any pCAL entry */
- if ((mask & PNG_FREE_PCAL) & info_ptr->free_me)
+ if (((mask & PNG_FREE_PCAL) & info_ptr->free_me) != 0)
{
png_free(png_ptr, info_ptr->pcal_purpose);
png_free(png_ptr, info_ptr->pcal_units);
info_ptr->pcal_purpose = NULL;
info_ptr->pcal_units = NULL;
+
if (info_ptr->pcal_params != NULL)
{
int i;
- for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
- {
+
+ for (i = 0; i < info_ptr->pcal_nparams; i++)
png_free(png_ptr, info_ptr->pcal_params[i]);
- info_ptr->pcal_params[i] = NULL;
- }
+
png_free(png_ptr, info_ptr->pcal_params);
info_ptr->pcal_params = NULL;
}
@@ -406,8 +420,8 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#endif
#ifdef PNG_iCCP_SUPPORTED
- /* Free any iCCP entry */
- if ((mask & PNG_FREE_ICCP) & info_ptr->free_me)
+ /* Free any profile entry */
+ if (((mask & PNG_FREE_ICCP) & info_ptr->free_me) != 0)
{
png_free(png_ptr, info_ptr->iccp_name);
png_free(png_ptr, info_ptr->iccp_profile);
@@ -419,74 +433,62 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#ifdef PNG_sPLT_SUPPORTED
/* Free a given sPLT entry, or (if num == -1) all sPLT entries */
- if ((mask & PNG_FREE_SPLT) & info_ptr->free_me)
+ if (info_ptr->splt_palettes != 0 &&
+ ((mask & PNG_FREE_SPLT) & info_ptr->free_me) != 0)
{
if (num != -1)
{
- if (info_ptr->splt_palettes)
- {
- png_free(png_ptr, info_ptr->splt_palettes[num].name);
- png_free(png_ptr, info_ptr->splt_palettes[num].entries);
- info_ptr->splt_palettes[num].name = NULL;
- info_ptr->splt_palettes[num].entries = NULL;
- }
+ png_free(png_ptr, info_ptr->splt_palettes[num].name);
+ png_free(png_ptr, info_ptr->splt_palettes[num].entries);
+ info_ptr->splt_palettes[num].name = NULL;
+ info_ptr->splt_palettes[num].entries = NULL;
}
else
{
- if (info_ptr->splt_palettes_num)
- {
- int i;
- for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
- png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i);
+ int i;
- png_free(png_ptr, info_ptr->splt_palettes);
- info_ptr->splt_palettes = NULL;
- info_ptr->splt_palettes_num = 0;
+ for (i = 0; i < info_ptr->splt_palettes_num; i++)
+ {
+ png_free(png_ptr, info_ptr->splt_palettes[i].name);
+ png_free(png_ptr, info_ptr->splt_palettes[i].entries);
}
+
+ png_free(png_ptr, info_ptr->splt_palettes);
+ info_ptr->splt_palettes = NULL;
+ info_ptr->splt_palettes_num = 0;
info_ptr->valid &= ~PNG_INFO_sPLT;
}
}
#endif
#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
- if (png_ptr->unknown_chunk.data)
- {
- png_free(png_ptr, png_ptr->unknown_chunk.data);
- png_ptr->unknown_chunk.data = NULL;
- }
-
- if ((mask & PNG_FREE_UNKN) & info_ptr->free_me)
+ if (info_ptr->unknown_chunks != 0 &&
+ ((mask & PNG_FREE_UNKN) & info_ptr->free_me) != 0)
{
if (num != -1)
{
- if (info_ptr->unknown_chunks)
- {
- png_free(png_ptr, info_ptr->unknown_chunks[num].data);
- info_ptr->unknown_chunks[num].data = NULL;
- }
+ png_free(png_ptr, info_ptr->unknown_chunks[num].data);
+ info_ptr->unknown_chunks[num].data = NULL;
}
else
{
int i;
- if (info_ptr->unknown_chunks_num)
- {
- for (i = 0; i < info_ptr->unknown_chunks_num; i++)
- png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i);
+ for (i = 0; i < info_ptr->unknown_chunks_num; i++)
+ png_free(png_ptr, info_ptr->unknown_chunks[i].data);
- png_free(png_ptr, info_ptr->unknown_chunks);
- info_ptr->unknown_chunks = NULL;
- info_ptr->unknown_chunks_num = 0;
- }
+ png_free(png_ptr, info_ptr->unknown_chunks);
+ info_ptr->unknown_chunks = NULL;
+ info_ptr->unknown_chunks_num = 0;
}
}
#endif
#ifdef PNG_hIST_SUPPORTED
/* Free any hIST entry */
- if ((mask & PNG_FREE_HIST) & info_ptr->free_me)
+ if (((mask & PNG_FREE_HIST) & info_ptr->free_me) != 0)
{
png_free(png_ptr, info_ptr->hist);
info_ptr->hist = NULL;
@@ -495,9 +497,9 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#endif
/* Free any PLTE entry that was internally allocated */
- if ((mask & PNG_FREE_PLTE) & info_ptr->free_me)
+ if (((mask & PNG_FREE_PLTE) & info_ptr->free_me) != 0)
{
- png_zfree(png_ptr, info_ptr->palette);
+ png_free(png_ptr, info_ptr->palette);
info_ptr->palette = NULL;
info_ptr->valid &= ~PNG_INFO_PLTE;
info_ptr->num_palette = 0;
@@ -505,16 +507,14 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#ifdef PNG_INFO_IMAGE_SUPPORTED
/* Free any image bits attached to the info structure */
- if ((mask & PNG_FREE_ROWS) & info_ptr->free_me)
+ if (((mask & PNG_FREE_ROWS) & info_ptr->free_me) != 0)
{
- if (info_ptr->row_pointers)
+ if (info_ptr->row_pointers != 0)
{
- int row;
- for (row = 0; row < (int)info_ptr->height; row++)
- {
+ png_uint_32 row;
+ for (row = 0; row < info_ptr->height; row++)
png_free(png_ptr, info_ptr->row_pointers[row]);
- info_ptr->row_pointers[row] = NULL;
- }
+
png_free(png_ptr, info_ptr->row_pointers);
info_ptr->row_pointers = NULL;
}
@@ -655,14 +655,15 @@ png_get_copyright(png_const_structp png_ptr)
#else
# ifdef __STDC__
return PNG_STRING_NEWLINE \
- "libpng version 1.5.7 - December 15, 2011" PNG_STRING_NEWLINE \
- "Copyright (c) 1998-2011 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
+ "libpng version 1.5.26 - December 17, 2015" PNG_STRING_NEWLINE \
+ "Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson" \
+ PNG_STRING_NEWLINE \
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
"Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
PNG_STRING_NEWLINE;
# else
- return "libpng version 1.5.7 - December 15, 2011\
- Copyright (c) 1998-2011 Glenn Randers-Pehrson\
+ return "libpng version 1.5.26 - December 17, 2015\
+ Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson\
Copyright (c) 1996-1997 Andreas Dilger\
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
# endif
@@ -892,7 +893,8 @@ int png_XYZ_from_xy(png_XYZ *XYZ, png_xy xy)
/* Check xy and, implicitly, z. Note that wide gamut color spaces typically
* have end points with 0 tristimulus values (these are impossible end
- * points, but they are used to cover the possible colors.)
+ * points, but they are used to cover the possible colors). We check
+ * xy.whitey against 5, not 0, to avoid a possible integer overflow.
*/
if (xy.redx < 0 || xy.redx > PNG_FP_1) return 1;
if (xy.redy < 0 || xy.redy > PNG_FP_1-xy.redx) return 1;
@@ -901,7 +903,7 @@ int png_XYZ_from_xy(png_XYZ *XYZ, png_xy xy)
if (xy.bluex < 0 || xy.bluex > PNG_FP_1) return 1;
if (xy.bluey < 0 || xy.bluey > PNG_FP_1-xy.bluex) return 1;
if (xy.whitex < 0 || xy.whitex > PNG_FP_1) return 1;
- if (xy.whitey < 0 || xy.whitey > PNG_FP_1-xy.whitex) return 1;
+ if (xy.whitey < 5 || xy.whitey > PNG_FP_1-xy.whitex) return 1;
/* The reverse calculation is more difficult because the original tristimulus
* value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
@@ -969,8 +971,8 @@ int png_XYZ_from_xy(png_XYZ *XYZ, png_xy xy)
* and it is certain that it becomes unstable where the end points are close
* together.
*
- * So this code uses the perhaps slighly less optimal but more understandable
- * and totally obvious approach of calculating color-scale.
+ * So this code uses the perhaps slightly less optimal but more
+ * understandable and totally obvious approach of calculating color-scale.
*
* This algorithm depends on the precision in white-scale and that is
* (1/white-y), so we can immediately see that as white-y approaches 0 the
@@ -1165,6 +1167,17 @@ int png_XYZ_from_xy_checked(png_structp png_ptr, png_XYZ *XYZ, png_xy xy)
}
#endif
+#ifdef __GNUC__
+/* This exists solely to work round a warning from GNU C. */
+static int /* PRIVATE */
+png_gt(size_t a, size_t b)
+{
+ return a > b;
+}
+#else
+# define png_gt(a,b) ((a) > (b))
+#endif
+
void /* PRIVATE */
png_check_IHDR(png_structp png_ptr,
png_uint_32 width, png_uint_32 height, int bit_depth,
@@ -1179,53 +1192,68 @@ png_check_IHDR(png_structp png_ptr,
png_warning(png_ptr, "Image width is zero in IHDR");
error = 1;
}
-
- if (height == 0)
+ else if (width > PNG_UINT_31_MAX)
{
- png_warning(png_ptr, "Image height is zero in IHDR");
+ png_warning(png_ptr, "Invalid image width in IHDR");
error = 1;
}
-# ifdef PNG_SET_USER_LIMITS_SUPPORTED
- if (width > png_ptr->user_width_max)
-
-# else
- if (width > PNG_USER_WIDTH_MAX)
-# endif
+ else if (png_gt(width,
+ (PNG_SIZE_MAX >> 3) /* 8-byte RGBA pixels */
+ - 48 /* big_row_buf hack */
+ - 1 /* filter byte */
+ - 7*8 /* rounding width to multiple of 8 pix */
+ - 8)) /* extra max_pixel_depth pad */
{
- png_warning(png_ptr, "Image width exceeds user limit in IHDR");
+ /* The size of the row must be within the limits of this architecture.
+ * Because the read code can perform arbitrary transformations the
+ * maximum size is checked here. Because the code in png_read_start_row
+ * adds extra space "for safety's sake" in several places a conservative
+ * limit is used here.
+ *
+ * NOTE: it would be far better to check the size that is actually used,
+ * but the effect in the real world is minor and the changes are more
+ * extensive, therefore much more dangerous and much more difficult to
+ * write in a way that avoids compiler warnings.
+ */
+ png_warning(png_ptr, "Image width is too large for this architecture");
error = 1;
}
-
-# ifdef PNG_SET_USER_LIMITS_SUPPORTED
- if (height > png_ptr->user_height_max)
-# else
- if (height > PNG_USER_HEIGHT_MAX)
-# endif
+ else
{
- png_warning(png_ptr, "Image height exceeds user limit in IHDR");
- error = 1;
+# ifdef PNG_SET_USER_LIMITS_SUPPORTED
+ if (width > png_ptr->user_width_max)
+# else
+ if (width > PNG_USER_WIDTH_MAX)
+# endif
+ {
+ png_warning(png_ptr, "Image width exceeds user limit in IHDR");
+ error = 1;
+ }
}
- if (width > PNG_UINT_31_MAX)
+ if (height == 0)
{
- png_warning(png_ptr, "Invalid image width in IHDR");
+ png_warning(png_ptr, "Image height is zero in IHDR");
error = 1;
}
-
- if (height > PNG_UINT_31_MAX)
+ else if (height > PNG_UINT_31_MAX)
{
png_warning(png_ptr, "Invalid image height in IHDR");
error = 1;
}
-
- if (width > (PNG_UINT_32_MAX
- >> 3) /* 8-byte RGBA pixels */
- - 48 /* bigrowbuf hack */
- - 1 /* filter byte */
- - 7*8 /* rounding of width to multiple of 8 pixels */
- - 8) /* extra max_pixel_depth pad */
- png_warning(png_ptr, "Width is too large for libpng to process pixels");
+ else
+ {
+# ifdef PNG_SET_USER_LIMITS_SUPPORTED
+ if (height > png_ptr->user_height_max)
+# else
+ if (height > PNG_USER_HEIGHT_MAX)
+# endif
+ {
+ png_warning(png_ptr, "Image height exceeds user limit in IHDR");
+ error = 1;
+ }
+ }
/* Check other values */
if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
@@ -1458,7 +1486,7 @@ png_check_fp_string(png_const_charp string, png_size_t size)
}
#endif /* pCAL or sCAL */
-#ifdef PNG_READ_sCAL_SUPPORTED
+#ifdef PNG_sCAL_SUPPORTED
# ifdef PNG_FLOATING_POINT_SUPPORTED
/* Utility used below - a simple accurate power of ten from an integral
* exponent.
@@ -1467,7 +1495,7 @@ static double
png_pow10(int power)
{
int recip = 0;
- double d = 1;
+ double d = 1.0;
/* Handle negative exponent with a reciprocal at the end because
* 10 is exact whereas .1 is inexact in base 2
@@ -1481,7 +1509,7 @@ png_pow10(int power)
if (power > 0)
{
/* Decompose power bitwise. */
- double mult = 10;
+ double mult = 10.0;
do
{
if (power & 1) d *= mult;
@@ -1490,7 +1518,7 @@ png_pow10(int power)
}
while (power > 0);
- if (recip) d = 1/d;
+ if (recip != 0) d = 1/d;
}
/* else power is 0 and d is 1 */
@@ -1600,7 +1628,8 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
{
double d;
- fp *= 10;
+ fp *= 10.0;
+
/* Use modf here, not floor and subtract, so that
* the separation is done in one step. At the end
* of the loop don't break the number into parts so
@@ -1613,7 +1642,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
{
d = floor(fp + .5);
- if (d > 9)
+ if (d > 9.0)
{
/* Rounding up to 10, handle that here. */
if (czero > 0)
@@ -1621,9 +1650,10 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
--czero, d = 1;
if (cdigits == 0) --clead;
}
+
else
{
- while (cdigits > 0 && d > 9)
+ while (cdigits > 0 && d > 9.0)
{
int ch = *--ascii;
@@ -1648,7 +1678,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
* exponent but take into account the leading
* decimal point.
*/
- if (d > 9) /* cdigits == 0 */
+ if (d > 9.0) /* cdigits == 0 */
{
if (exp_b10 == (-1))
{
@@ -1669,18 +1699,19 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
++exp_b10;
/* In all cases we output a '1' */
- d = 1;
+ d = 1.0;
}
}
}
fp = 0; /* Guarantees termination below. */
}
- if (d == 0)
+ if (d == 0.0)
{
++czero;
if (cdigits == 0) ++clead;
}
+
else
{
/* Included embedded zeros in the digit count. */
@@ -1708,6 +1739,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
above */
--exp_b10;
}
+
*ascii++ = (char)(48 + (int)d), ++cdigits;
}
}
@@ -1718,7 +1750,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
/* Check for an exponent, if we don't need one we are
* done and just need to terminate the string. At
* this point exp_b10==(-1) is effectively if flag - it got
- * to '-1' because of the decrement after outputing
+ * to '-1' because of the decrement after outputting
* the decimal point above (the exponent required is
* *not* -1!)
*/
@@ -1726,7 +1758,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
{
/* The following only happens if we didn't output the
* leading zeros above for negative exponent, so this
- * doest add to the digit requirement. Note that the
+ * doesn't add to the digit requirement. Note that the
* two zeros here can only be output if the two leading
* zeros were *not* output, so this doesn't increase
* the output count.
@@ -1900,7 +1932,7 @@ png_fixed(png_structp png_ptr, double fp, png_const_charp text)
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED) || \
- defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG__READ_pHYs_SUPPORTED)
+ defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
/* muldiv functions */
/* This API takes signed arguments and rounds the result to the nearest
* integer (or, for a fixed point number - the standard argument - to
@@ -2004,7 +2036,7 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
if (s00 >= (D >> 1))
++result;
- if (negative)
+ if (negative != 0)
result = -result;
/* Check for overflow. */
@@ -2040,26 +2072,31 @@ png_muldiv_warn(png_structp png_ptr, png_fixed_point a, png_int_32 times,
}
#endif
-#ifdef PNG_READ_GAMMA_SUPPORTED /* more fixed point functions for gammma */
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED)
+/* more fixed point functions for gamma and cHRM (xy/XYZ) suport. */
/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
png_fixed_point
png_reciprocal(png_fixed_point a)
{
+ if (a != 0)
+ {
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
- double r = floor(1E10/a+.5);
+ double r = floor(1E10/a+.5);
- if (r <= 2147483647. && r >= -2147483648.)
- return (png_fixed_point)r;
+ if (r <= 2147483647. && r >= -2147483648.)
+ return (png_fixed_point)r;
#else
- png_fixed_point res;
+ png_fixed_point res;
- if (png_muldiv(&res, 100000, 100000, a))
- return res;
+ if (png_muldiv(&res, 100000, 100000, a))
+ return res;
#endif
+ }
return 0; /* error/overflow */
}
+#ifdef PNG_READ_GAMMA_SUPPORTED
/* A local convenience routine. */
static png_fixed_point
png_product2(png_fixed_point a, png_fixed_point b)
@@ -2081,6 +2118,7 @@ png_product2(png_fixed_point a, png_fixed_point b)
return 0; /* overflow */
}
+#endif /* READ_GAMMA */
/* The inverse of the above. */
png_fixed_point
@@ -2088,17 +2126,20 @@ png_reciprocal2(png_fixed_point a, png_fixed_point b)
{
/* The required result is 1/a * 1/b; the following preserves accuracy. */
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
- double r = 1E15/a;
- r /= b;
- r = floor(r+.5);
+ if (a != 0 && b != 0)
+ {
+ double r = 1E15/a;
+ r /= b;
+ r = floor(r+.5);
- if (r <= 2147483647. && r >= -2147483648.)
- return (png_fixed_point)r;
+ if (r <= 2147483647. && r >= -2147483648.)
+ return (png_fixed_point)r;
+ }
#else
- /* This may overflow because the range of png_fixed_point isn't symmetric,
- * but this API is only used for the product of file and screen gamma so it
- * doesn't matter that the smallest number it can produce is 1/21474, not
- * 1/100000
+ /* This may overflow because the range of png_fixed_point isn't
+ * symmetric, but this API is only used for the product of file and
+ * screen gamma so it doesn't matter that the smallest number it can
+ * produce is 1/21474, not 1/100000
*/
png_fixed_point res = png_product2(a, b);
@@ -2108,7 +2149,7 @@ png_reciprocal2(png_fixed_point a, png_fixed_point b)
return 0; /* overflow */
}
-#endif /* READ_GAMMA */
+#endif /* READ_GAMMA || cHRM */
#ifdef PNG_CHECK_cHRM_SUPPORTED
/* Added at libpng version 1.2.34 (Dec 8, 2008) and 1.4.0 (Jan 2,
@@ -2519,6 +2560,7 @@ png_gamma_significant(png_fixed_point gamma_val)
gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
}
+#ifdef PNG_16BIT_SUPPORTED
/* Internal function to build a single 16-bit table - the table consists of
* 'num' 256-entry subtables, where 'num' is determined by 'shift' - the amount
* to shift the input values right (or 16-number_of_signifiant_bits).
@@ -2567,7 +2609,7 @@ png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable,
double d = floor(65535*pow(ig/(double)max, gamma_val*.00001)+.5);
sub_table[j] = (png_uint_16)d;
# else
- if (shift)
+ if (shift != 0)
ig = (ig * 65535U + max_by_2)/max;
sub_table[j] = png_gamma_16bit_correct(ig, gamma_val);
@@ -2583,7 +2625,7 @@ png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable,
{
png_uint_32 ig = (j << (8-shift)) + i;
- if (shift)
+ if (shift != 0)
ig = (ig * 65535U + max_by_2)/max;
sub_table[j] = (png_uint_16)ig;
@@ -2591,6 +2633,7 @@ png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable,
}
}
}
+#endif
/* NOTE: this function expects the *inverse* of the overall gamma transformation
* required.
@@ -2868,3 +2911,24 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
}
#endif /* READ_GAMMA */
#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
+
+/* HARDWARE OPTION SUPPORT */
+#ifdef PNG_SET_OPTION_SUPPORTED
+int PNGAPI
+png_set_option(png_structp png_ptr, int option, int onoff)
+{
+ if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT &&
+ (option & 1) == 0)
+ {
+ int mask = 3 << option;
+ int setting = (2 + (onoff != 0)) << option;
+ int current = png_ptr->options;
+
+ png_ptr->options = (png_byte)((current & ~mask) | setting);
+
+ return (current & mask) >> option;
+ }
+
+ return PNG_OPTION_INVALID;
+}
+#endif
diff --git a/drivers/png/png.h b/drivers/png/png.h
index e22ec5c5df..c4f2bab15e 100644
--- a/drivers/png/png.h
+++ b/drivers/png/png.h
@@ -1,8 +1,9 @@
/* png.h - header file for PNG reference library
*
- * libpng version 1.5.7 - December 15, 2011
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * libpng version 1.5.26, December 17, 2015
+ *
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -11,182 +12,9 @@
* Authors and maintainers:
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
* libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
- * libpng versions 0.97, January 1998, through 1.5.7 - December 15, 2011: Glenn
+ * libpng versions 0.97, January 1998, through 1.5.26, December 17, 2015:
+ * Glenn Randers-Pehrson.
* See also "Contributing Authors", below.
- *
- * Note about libpng version numbers:
- *
- * Due to various miscommunications, unforeseen code incompatibilities
- * and occasional factors outside the authors' control, version numbering
- * on the library has not always been consistent and straightforward.
- * The following table summarizes matters since version 0.89c, which was
- * the first widely used release:
- *
- * source png.h png.h shared-lib
- * version string int version
- * ------- ------ ----- ----------
- * 0.89c "1.0 beta 3" 0.89 89 1.0.89
- * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90]
- * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95]
- * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96]
- * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97]
- * 0.97c 0.97 97 2.0.97
- * 0.98 0.98 98 2.0.98
- * 0.99 0.99 98 2.0.99
- * 0.99a-m 0.99 99 2.0.99
- * 1.00 1.00 100 2.1.0 [100 should be 10000]
- * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000]
- * 1.0.1 png.h string is 10001 2.1.0
- * 1.0.1a-e identical to the 10002 from here on, the shared library
- * 1.0.2 source version) 10002 is 2.V where V is the source code
- * 1.0.2a-b 10003 version, except as noted.
- * 1.0.3 10003
- * 1.0.3a-d 10004
- * 1.0.4 10004
- * 1.0.4a-f 10005
- * 1.0.5 (+ 2 patches) 10005
- * 1.0.5a-d 10006
- * 1.0.5e-r 10100 (not source compatible)
- * 1.0.5s-v 10006 (not binary compatible)
- * 1.0.6 (+ 3 patches) 10006 (still binary incompatible)
- * 1.0.6d-f 10007 (still binary incompatible)
- * 1.0.6g 10007
- * 1.0.6h 10007 10.6h (testing xy.z so-numbering)
- * 1.0.6i 10007 10.6i
- * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0)
- * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible)
- * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible)
- * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible)
- * 1.0.7 1 10007 (still compatible)
- * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4
- * 1.0.8rc1 1 10008 2.1.0.8rc1
- * 1.0.8 1 10008 2.1.0.8
- * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6
- * 1.0.9rc1 1 10009 2.1.0.9rc1
- * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10
- * 1.0.9rc2 1 10009 2.1.0.9rc2
- * 1.0.9 1 10009 2.1.0.9
- * 1.0.10beta1 1 10010 2.1.0.10beta1
- * 1.0.10rc1 1 10010 2.1.0.10rc1
- * 1.0.10 1 10010 2.1.0.10
- * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3
- * 1.0.11rc1 1 10011 2.1.0.11rc1
- * 1.0.11 1 10011 2.1.0.11
- * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2
- * 1.0.12rc1 2 10012 2.1.0.12rc1
- * 1.0.12 2 10012 2.1.0.12
- * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned)
- * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2
- * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5
- * 1.2.0rc1 3 10200 3.1.2.0rc1
- * 1.2.0 3 10200 3.1.2.0
- * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4
- * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2
- * 1.2.1 3 10201 3.1.2.1
- * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6
- * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1
- * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1
- * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1
- * 1.0.13 10 10013 10.so.0.1.0.13
- * 1.2.2 12 10202 12.so.0.1.2.2
- * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6
- * 1.2.3 12 10203 12.so.0.1.2.3
- * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3
- * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1
- * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1
- * 1.0.14 10 10014 10.so.0.1.0.14
- * 1.2.4 13 10204 12.so.0.1.2.4
- * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2
- * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3
- * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3
- * 1.0.15 10 10015 10.so.0.1.0.15
- * 1.2.5 13 10205 12.so.0.1.2.5
- * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4
- * 1.0.16 10 10016 10.so.0.1.0.16
- * 1.2.6 13 10206 12.so.0.1.2.6
- * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2
- * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1
- * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1
- * 1.0.17 10 10017 12.so.0.1.0.17
- * 1.2.7 13 10207 12.so.0.1.2.7
- * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5
- * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5
- * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5
- * 1.0.18 10 10018 12.so.0.1.0.18
- * 1.2.8 13 10208 12.so.0.1.2.8
- * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3
- * 1.2.9beta4-11 13 10209 12.so.0.9[.0]
- * 1.2.9rc1 13 10209 12.so.0.9[.0]
- * 1.2.9 13 10209 12.so.0.9[.0]
- * 1.2.10beta1-7 13 10210 12.so.0.10[.0]
- * 1.2.10rc1-2 13 10210 12.so.0.10[.0]
- * 1.2.10 13 10210 12.so.0.10[.0]
- * 1.4.0beta1-5 14 10400 14.so.0.0[.0]
- * 1.2.11beta1-4 13 10211 12.so.0.11[.0]
- * 1.4.0beta7-8 14 10400 14.so.0.0[.0]
- * 1.2.11 13 10211 12.so.0.11[.0]
- * 1.2.12 13 10212 12.so.0.12[.0]
- * 1.4.0beta9-14 14 10400 14.so.0.0[.0]
- * 1.2.13 13 10213 12.so.0.13[.0]
- * 1.4.0beta15-36 14 10400 14.so.0.0[.0]
- * 1.4.0beta37-87 14 10400 14.so.14.0[.0]
- * 1.4.0rc01 14 10400 14.so.14.0[.0]
- * 1.4.0beta88-109 14 10400 14.so.14.0[.0]
- * 1.4.0rc02-08 14 10400 14.so.14.0[.0]
- * 1.4.0 14 10400 14.so.14.0[.0]
- * 1.4.1beta01-03 14 10401 14.so.14.1[.0]
- * 1.4.1rc01 14 10401 14.so.14.1[.0]
- * 1.4.1beta04-12 14 10401 14.so.14.1[.0]
- * 1.4.1 14 10401 14.so.14.1[.0]
- * 1.4.2 14 10402 14.so.14.2[.0]
- * 1.4.3 14 10403 14.so.14.3[.0]
- * 1.4.4 14 10404 14.so.14.4[.0]
- * 1.5.0beta01-58 15 10500 15.so.15.0[.0]
- * 1.5.0rc01-07 15 10500 15.so.15.0[.0]
- * 1.5.0 15 10500 15.so.15.0[.0]
- * 1.5.1beta01-11 15 10501 15.so.15.1[.0]
- * 1.5.1rc01-02 15 10501 15.so.15.1[.0]
- * 1.5.1 15 10501 15.so.15.1[.0]
- * 1.5.2beta01-03 15 10502 15.so.15.2[.0]
- * 1.5.2rc01-03 15 10502 15.so.15.2[.0]
- * 1.5.2 15 10502 15.so.15.2[.0]
- * 1.5.3beta01-10 15 10503 15.so.15.3[.0]
- * 1.5.3rc01-02 15 10503 15.so.15.3[.0]
- * 1.5.3beta11 15 10503 15.so.15.3[.0]
- * 1.5.3 [omitted]
- * 1.5.4beta01-08 15 10504 15.so.15.4[.0]
- * 1.5.4rc01 15 10504 15.so.15.4[.0]
- * 1.5.4 15 10504 15.so.15.4[.0]
- * 1.5.5beta01-08 15 10505 15.so.15.5[.0]
- * 1.5.5rc01 15 10505 15.so.15.5[.0]
- * 1.5.5 15 10505 15.so.15.5[.0]
- * 1.5.6beta01-07 15 10506 15.so.15.6[.0]
- * 1.5.6rc01-03 15 10506 15.so.15.6[.0]
- * 1.5.6 15 10506 15.so.15.6[.0]
- * 1.5.7beta01-05 15 10507 15.so.15.7[.0]
- * 1.5.7rc01-03 15 10507 15.so.15.7[.0]
- * 1.5.7 15 10507 15.so.15.7[.0]
- *
- * Henceforth the source version will match the shared-library major
- * and minor numbers; the shared-library major version number will be
- * used for changes in backward compatibility, as it is intended. The
- * PNG_LIBPNG_VER macro, which is not used within libpng but is available
- * for applications, is an unsigned integer of the form xyyzz corresponding
- * to the source version x.y.z (leading zeros in y and z). Beta versions
- * were given the previous public release number plus a letter, until
- * version 1.0.6j; from then on they were given the upcoming public
- * release number plus "betaNN" or "rcN".
- *
- * Binary incompatibility exists only when applications make direct access
- * to the info_ptr or png_ptr members through png.h, and the compiled
- * application is loaded with a different version of the library.
- *
- * DLLNUM will change each time there are forward or backward changes
- * in binary compatibility (e.g., when a new feature is added).
- *
- * See libpng-manual.txt or libpng.3 for more information. The PNG
- * specification is available as a W3C Recommendation and as an ISO
- * Specification, <http://www.w3.org/TR/2003/REC-PNG-20031110/
*/
/*
@@ -197,20 +25,16 @@
*
* This code is released under the libpng license.
*
- * libpng versions 1.2.6, August 15, 2004, through 1.5.7, December 15, 2011, are
- * Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are
- * distributed according to the same disclaimer and license as libpng-1.2.5
- * with the following individual added to the list of Contributing Authors:
- *
- * Cosmin Truta
- *
- * libpng versions 1.0.7, July 1, 2000, through 1.2.5, October 3, 2002, are
- * Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are
- * distributed according to the same disclaimer and license as libpng-1.0.6
- * with the following individuals added to the list of Contributing Authors:
+ * libpng versions 1.0.7, July 1, 2000, through 1.5.26, December 17, 2015, are
+ * Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are
+ * derived from libpng-1.0.6, and are distributed according to the same
+ * disclaimer and license as libpng-1.0.6 with the following individuals
+ * added to the list of Contributing Authors:
*
* Simon-Pierre Cadieux
* Eric S. Raymond
+ * Mans Rullgard
+ * Cosmin Truta
* Gilles Vollant
*
* and with the following additions to the disclaimer:
@@ -223,18 +47,20 @@
* the user.
*
* libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
- * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson, and are
- * distributed according to the same disclaimer and license as libpng-0.96,
- * with the following individuals added to the list of Contributing Authors:
+ * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
+ * libpng-0.96, and are distributed according to the same disclaimer and
+ * license as libpng-0.96, with the following individuals added to the list
+ * of Contributing Authors:
*
* Tom Lane
* Glenn Randers-Pehrson
* Willem van Schaik
*
* libpng versions 0.89, June 1996, through 0.96, May 1997, are
- * Copyright (c) 1996, 1997 Andreas Dilger
- * Distributed according to the same disclaimer and license as libpng-0.88,
- * with the following individuals added to the list of Contributing Authors:
+ * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
+ * and are distributed according to the same disclaimer and license as
+ * libpng-0.88, with the following individuals added to the list of
+ * Contributing Authors:
*
* John Bowler
* Kevin Bracey
@@ -244,7 +70,7 @@
* Tom Tanner
*
* libpng versions 0.5, May 1995, through 0.88, January 1996, are
- * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* For the purposes of this copyright and license, "Contributing Authors"
* is defined as the following set of individuals:
@@ -272,29 +98,32 @@
* 2. Altered versions must be plainly marked as such and must not
* be misrepresented as being the original source.
*
- * 3. This Copyright notice may not be removed or altered from
- * any source or altered source distribution.
+ * 3. This Copyright notice may not be removed or altered from any
+ * source or altered source distribution.
*
* The Contributing Authors and Group 42, Inc. specifically permit, without
* fee, and encourage the use of this source code as a component to
* supporting the PNG file format in commercial products. If you use this
* source code in a product, acknowledgment is not required but would be
* appreciated.
+ *
+ * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
*/
/*
* A "png_get_copyright" function is available, for convenient use in "about"
* boxes and the like:
*
- * printf("%s", png_get_copyright(NULL));
+ * printf("%s", png_get_copyright(NULL));
*
* Also, the PNG logo (in PNG format, of course) is supplied in the
* files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
*/
/*
- * Libpng is OSI Certified Open Source Software. OSI Certified is a
- * certification mark of the Open Source Initiative.
+ * Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
+ * a certification mark of the Open Source Initiative. OSI has not addressed
+ * the additional disclaimers inserted at version 1.0.7.
*/
/*
@@ -305,17 +134,90 @@
* Thanks to Frank J. T. Wojcik for helping with the documentation.
*/
+/* Note about libpng version numbers:
+ *
+ * Due to various miscommunications, unforeseen code incompatibilities
+ * and occasional factors outside the authors' control, version numbering
+ * on the library has not always been consistent and straightforward.
+ * The following table summarizes matters since version 0.89c, which was
+ * the first widely used release:
+ *
+ * source png.h png.h shared-lib
+ * version string int version
+ * ------- ------ ----- ----------
+ * 0.89c "1.0 beta 3" 0.89 89 1.0.89
+ * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90]
+ * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95]
+ * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96]
+ * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97]
+ * 0.97c 0.97 97 2.0.97
+ * 0.98 0.98 98 2.0.98
+ * 0.99 0.99 98 2.0.99
+ * 0.99a-m 0.99 99 2.0.99
+ * 1.00 1.00 100 2.1.0 [100 should be 10000]
+ * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000]
+ * 1.0.1 png.h string is 10001 2.1.0
+ * 1.0.1a-e identical to the 10002 from here on, the shared library
+ * 1.0.2 source version) 10002 is 2.V where V is the source code
+ * 1.0.2a-b 10003 version, except as noted.
+ * 1.0.3 10003
+ * 1.0.3a-d 10004
+ * 1.0.4 10004
+ * 1.0.4a-f 10005
+ * 1.0.5 (+ 2 patches) 10005
+ * 1.0.5a-d 10006
+ * 1.0.5e-r 10100 (not source compatible)
+ * 1.0.5s-v 10006 (not binary compatible)
+ * 1.0.6 (+ 3 patches) 10006 (still binary incompatible)
+ * 1.0.6d-f 10007 (still binary incompatible)
+ * 1.0.6g 10007
+ * 1.0.6h 10007 10.6h (testing xy.z so-numbering)
+ * 1.0.6i 10007 10.6i
+ * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0)
+ * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible)
+ * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible)
+ * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible)
+ * 1.0.7 1 10007 (still compatible)
+ * ...
+ * 1.0.19 10 10019 10.so.0.19[.0]
+ * ...
+ * 1.2.53 13 10253 12.so.0.53[.0]
+ * ...
+ * 1.5.25 15 10525 15.so.15.25[.0]
+ *
+ * Henceforth the source version will match the shared-library major
+ * and minor numbers; the shared-library major version number will be
+ * used for changes in backward compatibility, as it is intended. The
+ * PNG_LIBPNG_VER macro, which is not used within libpng but is available
+ * for applications, is an unsigned integer of the form xyyzz corresponding
+ * to the source version x.y.z (leading zeros in y and z). Beta versions
+ * were given the previous public release number plus a letter, until
+ * version 1.0.6j; from then on they were given the upcoming public
+ * release number plus "betaNN" or "rcNN".
+ *
+ * Binary incompatibility exists only when applications make direct access
+ * to the info_ptr or png_ptr members through png.h, and the compiled
+ * application is loaded with a different version of the library.
+ *
+ * DLLNUM will change each time there are forward or backward changes
+ * in binary compatibility (e.g., when a new feature is added).
+ *
+ * See libpng.txt or libpng.3 for more information. The PNG specification
+ * is available as a W3C Recommendation and as an ISO Specification,
+ * <http://www.w3.org/TR/2003/REC-PNG-20031110/
+ */
+
/*
* Y2K compliance in libpng:
* =========================
*
- * December 15, 2011
+ * December 17, 2015
*
* Since the PNG Development group is an ad-hoc body, we can't make
* an official declaration.
*
* This is your unofficial assurance that libpng from version 0.71 and
- * upward through 1.5.7 are Y2K compliant. It is my belief that
+ * upward through 1.5.26 are Y2K compliant. It is my belief that
* earlier versions were also Y2K compliant.
*
* Libpng only has two year fields. One is a 2-byte unsigned integer
@@ -326,7 +228,8 @@
* "png_uint_16 year" in png_time_struct.
*
* The string is
- * "png_char time_buffer" in png_struct
+ * "char time_buffer[29]" in png_struct. This will be no
+ * longer used in libpng-1.6.0 and will be removed from libpng-1.7.0.
*
* There are seven time-related functions:
* png.c: png_convert_to_rfc_1123() in png.c
@@ -366,16 +269,18 @@
/* This is not the place to learn how to use libpng. The file libpng-manual.txt
* describes how to use libpng, and the file example.c summarizes it
* with some code on which to build. This file is useful for looking
- * at the actual function definitions and structure components.
+ * at the actual function definitions and structure components. If that
+ * file has been stripped from your copy of libpng, you can find it at
+ * <http://www.libpng.org/pub/png/libpng-manual.txt>
*
* If you just need to read a PNG file and don't want to read the documentation
* skip to the end of this file and read the section entitled 'simplified API'.
*/
/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.5.7"
+#define PNG_LIBPNG_VER_STRING "1.5.26"
#define PNG_HEADER_VERSION_STRING \
- " libpng version 1.5.7 - December 15, 2011\n"
+ " libpng version 1.5.26 - December 17, 2015\n"
#define PNG_LIBPNG_VER_SONUM 15
#define PNG_LIBPNG_VER_DLLNUM 15
@@ -383,7 +288,7 @@
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
#define PNG_LIBPNG_VER_MINOR 5
-#define PNG_LIBPNG_VER_RELEASE 7
+#define PNG_LIBPNG_VER_RELEASE 26
/* This should match the numeric part of the final component of
* PNG_LIBPNG_VER_STRING, omitting any leading zero:
@@ -406,7 +311,7 @@
#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with
PNG_LIBPNG_BUILD_PRIVATE */
-#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_BETA
+#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE
/* Careful here. At one time, Guy wanted to use 082, but that would be octal.
* We must not include leading zeros.
@@ -414,7 +319,7 @@
* version 1.0.0 was mis-numbered 100 instead of 10000). From
* version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release
*/
-#define PNG_LIBPNG_VER 10507 /* 1.5.7 */
+#define PNG_LIBPNG_VER 10526 /* 1.5.26 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -447,7 +352,7 @@
/* Machine specific configuration. */
# include "pngconf.h"
-#endif
+#endif /* PNG_VERSION_INFO_ONLY */
/*
* Added at libpng-1.2.8
@@ -536,7 +441,7 @@ extern "C" {
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
-typedef char* png_libpng_version_1_5_7;
+typedef char* png_libpng_version_1_5_26;
/* Three color definitions. The order of the red, green, and blue, (and the
* exact size) is not important, although the size of the fields need to
@@ -1007,11 +912,13 @@ PNG_EXPORTA(5, png_structp, png_create_write_struct,
png_error_ptr warn_fn),
PNG_ALLOCATED);
+#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size,
(png_const_structp png_ptr));
PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr,
png_size_t size));
+#endif /* WRITE_CUSTOMIZE_COMPRESSION */
/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp
* match up.
@@ -1145,9 +1052,9 @@ PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr));
#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/
PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr,
- int error_action, double red, double green));
+ int error_action, double red, double green))
PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr,
- int error_action, png_fixed_point red, png_fixed_point green));
+ int error_action, png_fixed_point red, png_fixed_point green))
PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structp
png_ptr));
@@ -1215,9 +1122,9 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth,
#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */
PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structp png_ptr, int mode,
- double output_gamma));
+ double output_gamma))
PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr,
- int mode, png_fixed_point output_gamma));
+ int mode, png_fixed_point output_gamma))
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED)
@@ -1440,10 +1347,10 @@ PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr));
*/
PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr,
png_const_color_16p background_color, int background_gamma_code,
- int need_expand, double background_gamma));
+ int need_expand, double background_gamma))
PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr,
png_const_color_16p background_color, int background_gamma_code,
- int need_expand, png_fixed_point background_gamma));
+ int need_expand, png_fixed_point background_gamma))
#endif
#ifdef PNG_READ_BACKGROUND_SUPPORTED
# define PNG_BACKGROUND_GAMMA_UNKNOWN 0
@@ -1492,9 +1399,9 @@ PNG_EXPORT(49, void, png_set_quantize,
*/
PNG_FP_EXPORT(50, void, png_set_gamma,
(png_structp png_ptr, double screen_gamma,
- double override_file_gamma));
+ double override_file_gamma))
PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structp png_ptr,
- png_fixed_point screen_gamma, png_fixed_point override_file_gamma));
+ png_fixed_point screen_gamma, png_fixed_point override_file_gamma))
#endif
#ifdef PNG_WRITE_FLUSH_SUPPORTED
@@ -1623,47 +1530,17 @@ PNG_EXPORT(67, void, png_set_filter,
#define PNG_FILTER_VALUE_PAETH 4
#define PNG_FILTER_VALUE_LAST 5
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */
-/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_
- * defines, either the default (minimum-sum-of-absolute-differences), or
- * the experimental method (weighted-minimum-sum-of-absolute-differences).
- *
- * Weights are factors >= 1.0, indicating how important it is to keep the
- * filter type consistent between rows. Larger numbers mean the current
- * filter is that many times as likely to be the same as the "num_weights"
- * previous filters. This is cumulative for each previous row with a weight.
- * There needs to be "num_weights" values in "filter_weights", or it can be
- * NULL if the weights aren't being specified. Weights have no influence on
- * the selection of the first row filter. Well chosen weights can (in theory)
- * improve the compression for a given image.
- *
- * Costs are factors >= 1.0 indicating the relative decoding costs of a
- * filter type. Higher costs indicate more decoding expense, and are
- * therefore less likely to be selected over a filter with lower computational
- * costs. There needs to be a value in "filter_costs" for each valid filter
- * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't
- * setting the costs. Costs try to improve the speed of decompression without
- * unduly increasing the compressed image size.
- *
- * A negative weight or cost indicates the default value is to be used, and
- * values in the range [0.0, 1.0) indicate the value is to remain unchanged.
- * The default values for both weights and costs are currently 1.0, but may
- * change if good general weighting/cost heuristics can be found. If both
- * the weights and costs are set to 1.0, this degenerates the WEIGHTED method
- * to the UNWEIGHTED method, but with added encoding time/computation.
- */
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */
PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structp png_ptr,
int heuristic_method, int num_weights, png_const_doublep filter_weights,
- png_const_doublep filter_costs));
+ png_const_doublep filter_costs))
PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed,
(png_structp png_ptr,
int heuristic_method, int num_weights, png_const_fixed_point_p
- filter_weights, png_const_fixed_point_p filter_costs));
+ filter_weights, png_const_fixed_point_p filter_costs))
#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
-/* Heuristic used for row filter selection. These defines should NOT be
- * changed.
- */
+/* The following are no longer used and will be removed from libpng-1.7: */
#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */
#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */
#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */
@@ -1677,6 +1554,7 @@ PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed,
* for PNG images, and do considerably fewer caclulations. In the future,
* these values may not correspond directly to the zlib compression levels.
*/
+#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
PNG_EXPORT(69, void, png_set_compression_level,
(png_structp png_ptr, int level));
@@ -1694,7 +1572,7 @@ PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr,
PNG_EXPORT(73, void, png_set_compression_method, (png_structp png_ptr,
int method));
-#endif
+#endif /* WRITE_CUSTOMIZE_COMPRESSION */
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
/* Also set zlib parameters for compressing non-IDAT chunks */
@@ -1716,6 +1594,7 @@ PNG_EXPORT(225, void, png_set_text_compression_window_bits, (png_structp
PNG_EXPORT(226, void, png_set_text_compression_method, (png_structp png_ptr,
int method));
#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */
+#endif /* WRITE */
/* These next functions are called for input/output, memory, and error
* handling. They are in the file pngrio.c, pngwio.c, and pngerror.c,
@@ -1927,6 +1806,8 @@ PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr,
#else
/* Fatal error in PNG image of libpng - can't continue */
PNG_EXPORTA(104, void, png_err, (png_structp png_ptr), PNG_NORETURN);
+# define png_error(s1,s2) png_err(s1)
+# define png_chunk_error(s1,s2) png_err(s1)
#endif
#ifdef PNG_WARNINGS_SUPPORTED
@@ -1937,6 +1818,9 @@ PNG_EXPORT(105, void, png_warning, (png_structp png_ptr,
/* Non-fatal error in libpng, chunk name is prepended to message. */
PNG_EXPORT(106, void, png_chunk_warning, (png_structp png_ptr,
png_const_charp warning_message));
+#else
+# define png_warning(s1,s2) ((void)(s1))
+# define png_chunk_warning(s1,s2) ((void)(s1))
#endif
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
@@ -2040,9 +1924,9 @@ PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter,
/* Returns pixel aspect ratio, computed from pHYs chunk data. */
PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structp png_ptr, png_const_infop info_ptr))
PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structp png_ptr, png_const_infop info_ptr))
/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */
PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels,
@@ -2075,11 +1959,11 @@ PNG_EXPORT(132, void, png_set_bKGD, (png_structp png_ptr, png_infop info_ptr,
PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structp png_ptr,
png_const_infop info_ptr, double *white_x, double *white_y, double *red_x,
double *red_y, double *green_x, double *green_y, double *blue_x,
- double *blue_y));
+ double *blue_y))
PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_structp png_ptr,
png_const_infop info_ptr, double *red_X, double *red_Y, double *red_Z,
double *green_X, double *green_Y, double *green_Z, double *blue_X,
- double *blue_Y, double *blue_Z));
+ double *blue_Y, double *blue_Z))
#ifdef PNG_FIXED_POINT_SUPPORTED /* Otherwise not implemented */
PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed,
(png_const_structp png_ptr,
@@ -2087,7 +1971,7 @@ PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed,
png_fixed_point *int_white_y, png_fixed_point *int_red_x,
png_fixed_point *int_red_y, png_fixed_point *int_green_x,
png_fixed_point *int_green_y, png_fixed_point *int_blue_x,
- png_fixed_point *int_blue_y));
+ png_fixed_point *int_blue_y))
#endif
PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed,
(png_structp png_ptr, png_const_infop info_ptr,
@@ -2095,46 +1979,46 @@ PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed,
png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
- png_fixed_point *int_blue_Z));
+ png_fixed_point *int_blue_Z))
#endif
#ifdef PNG_cHRM_SUPPORTED
PNG_FP_EXPORT(135, void, png_set_cHRM,
(png_structp png_ptr, png_infop info_ptr,
double white_x, double white_y, double red_x, double red_y, double green_x,
- double green_y, double blue_x, double blue_y));
+ double green_y, double blue_x, double blue_y))
PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_structp png_ptr,
png_infop info_ptr, double red_X, double red_Y, double red_Z,
double green_X, double green_Y, double green_Z, double blue_X,
- double blue_Y, double blue_Z));
+ double blue_Y, double blue_Z))
PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_structp png_ptr,
png_infop info_ptr, png_fixed_point int_white_x,
png_fixed_point int_white_y, png_fixed_point int_red_x,
png_fixed_point int_red_y, png_fixed_point int_green_x,
png_fixed_point int_green_y, png_fixed_point int_blue_x,
- png_fixed_point int_blue_y));
+ png_fixed_point int_blue_y))
PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_structp png_ptr,
png_infop info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y,
png_fixed_point int_red_Z, png_fixed_point int_green_X,
png_fixed_point int_green_Y, png_fixed_point int_green_Z,
png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
- png_fixed_point int_blue_Z));
+ png_fixed_point int_blue_Z))
#endif
#ifdef PNG_gAMA_SUPPORTED
PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA,
(png_const_structp png_ptr, png_const_infop info_ptr,
- double *file_gamma));
+ double *file_gamma))
PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed,
(png_const_structp png_ptr, png_const_infop info_ptr,
- png_fixed_point *int_file_gamma));
+ png_fixed_point *int_file_gamma))
#endif
#ifdef PNG_gAMA_SUPPORTED
PNG_FP_EXPORT(139, void, png_set_gAMA, (png_structp png_ptr,
- png_infop info_ptr, double file_gamma));
+ png_infop info_ptr, double file_gamma))
PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_structp png_ptr,
- png_infop info_ptr, png_fixed_point int_file_gamma));
+ png_infop info_ptr, png_fixed_point int_file_gamma))
#endif
#ifdef PNG_hIST_SUPPORTED
@@ -2300,7 +2184,7 @@ PNG_EXPORT(167, void, png_set_tRNS,
#ifdef PNG_sCAL_SUPPORTED
PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL,
(png_const_structp png_ptr, png_const_infop info_ptr,
- int *unit, double *width, double *height));
+ int *unit, double *width, double *height))
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
/* NOTE: this API is currently implemented using floating point arithmetic,
* consequently it can only be used on systems with floating point support.
@@ -2310,7 +2194,7 @@ PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL,
PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed,
(png_structp png_ptr, png_const_infop info_ptr, int *unit,
png_fixed_point *width,
- png_fixed_point *height));
+ png_fixed_point *height))
#endif
PNG_EXPORT(169, png_uint_32, png_get_sCAL_s,
(png_const_structp png_ptr, png_const_infop info_ptr,
@@ -2318,10 +2202,10 @@ PNG_EXPORT(169, png_uint_32, png_get_sCAL_s,
PNG_FP_EXPORT(170, void, png_set_sCAL,
(png_structp png_ptr, png_infop info_ptr,
- int unit, double width, double height));
+ int unit, double width, double height))
PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_structp png_ptr,
png_infop info_ptr, int unit, png_fixed_point width,
- png_fixed_point height));
+ png_fixed_point height))
PNG_EXPORT(171, void, png_set_sCAL_s,
(png_structp png_ptr, png_infop info_ptr,
int unit, png_const_charp swidth, png_const_charp sheight));
@@ -2434,17 +2318,17 @@ PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch,
(png_const_structp png_ptr, png_const_infop info_ptr));
PNG_FP_EXPORT(196, float, png_get_x_offset_inches,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structp png_ptr, png_const_infop info_ptr))
#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */
PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed,
- (png_structp png_ptr, png_const_infop info_ptr));
+ (png_structp png_ptr, png_const_infop info_ptr))
#endif
PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+ png_const_infop info_ptr))
#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */
PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed,
- (png_structp png_ptr, png_const_infop info_ptr));
+ (png_structp png_ptr, png_const_infop info_ptr))
#endif
# ifdef PNG_pHYs_SUPPORTED
@@ -2627,10 +2511,60 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
# define png_get_int_32(buf) \
((png_int_32)((*(buf) & 0x80) \
- ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \
+ ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \
: (png_int_32)png_get_uint_32(buf)))
#endif
+#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+PNG_EXPORT(234, void, png_set_check_for_invalid_index, (png_structp png_ptr,
+ int allowed));
+# ifdef PNG_GET_PALETTE_MAX_SUPPORTED
+PNG_EXPORT(235, int, png_get_palette_max, (png_const_structp png_ptr,
+ png_const_infop info_ptr));
+# endif
+#endif /* CHECK_FOR_INVALID_INDEX */
+
+/*******************************************************************************
+ * IMPLEMENTATION OPTIONS
+ *******************************************************************************
+ *
+ * Support for arbitrary implementation-specific optimizations. The API allows
+ * particular options to be turned on or off. 'Option' is the number of the
+ * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given
+ * by the PNG_OPTION_ defines below.
+ *
+ * HARDWARE: normally hardware capabilites, such as the Intel SSE instructions,
+ * are detected at run time, however sometimes it may be impossible
+ * to do this in user mode, in which case it is necessary to discover
+ * the capabilities in an OS specific way. Such capabilities are
+ * listed here when libpng has support for them and must be turned
+ * ON by the application if present.
+ *
+ * SOFTWARE: sometimes software optimizations actually result in performance
+ * decrease on some architectures or systems, or with some sets of
+ * PNG images. 'Software' options allow such optimizations to be
+ * selected at run time.
+ */
+#ifdef PNG_SET_OPTION_SUPPORTED
+#ifdef PNG_ARM_NEON_API_SUPPORTED
+# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */
+#endif
+#define PNG_OPTION_NEXT 2 /* Next option - numbers must be even */
+
+/* Return values: NOTE: there are four values and 'off' is *not* zero */
+#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */
+#define PNG_OPTION_INVALID 1 /* Option number out of range */
+#define PNG_OPTION_OFF 2
+#define PNG_OPTION_ON 3
+
+PNG_EXPORT(236, int, png_set_option, (png_structp png_ptr, int option,
+ int onoff));
+#endif
+
+/*******************************************************************************
+ * END OF HARDWARE OPTIONS
+ ******************************************************************************/
+
/* Maintainer: Put new public prototypes here ^, in libpng.3, and project
* defs
*/
@@ -2640,7 +2574,7 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
* scripts/symbols.def as well.
*/
#ifdef PNG_EXPORT_LAST_ORDINAL
- PNG_EXPORT_LAST_ORDINAL(233);
+ PNG_EXPORT_LAST_ORDINAL(236);
#endif
#ifdef __cplusplus
diff --git a/drivers/png/pngconf.h b/drivers/png/pngconf.h
index d07054de28..62588337d0 100644
--- a/drivers/png/pngconf.h
+++ b/drivers/png/pngconf.h
@@ -1,9 +1,9 @@
/* pngconf.h - machine configurable file for libpng
*
- * libpng version 1.5.7 - December 15, 2011
+ * libpng version 1.5.26, December 17, 2015
*
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -11,9 +11,7 @@
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*
- */
-
-/* Any machine specific code is near the front of this file, so if you
+ * Any machine specific code is near the front of this file, so if you
* are configuring libpng for a machine, you may want to read the section
* starting here down to where it starts to typedef png_color, png_text,
* and png_info.
@@ -25,7 +23,7 @@
#ifndef PNG_BUILDING_SYMBOL_TABLE
/* PNG_NO_LIMITS_H may be used to turn off the use of the standard C
* definition file for machine specific limits, this may impact the
- * correctness of the definitons below (see uses of INT_MAX).
+ * correctness of the definitions below (see uses of INT_MAX).
*/
# ifndef PNG_NO_LIMITS_H
# include <limits.h>
@@ -51,8 +49,8 @@
/* This controls optimization of the reading of 16 and 32 bit values
* from PNG files. It can be set on a per-app-file basis - it
- * just changes whether a macro is used to the function is called.
- * The library builder sets the default, if read functions are not
+ * just changes whether a macro is used when the function is called.
+ * The library builder sets the default; if read functions are not
* built into the library the macro implementation is forced on.
*/
#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED
@@ -177,18 +175,16 @@
* ==========================
* This code is used at build time to find PNG_IMPEXP, the API settings
* and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL
- * import processing is possible. On Windows/x86 systems it also sets
+ * import processing is possible. On Windows systems it also sets
* compiler-specific macros to the values required to change the calling
* conventions of the various functions.
*/
-#if ( defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\
- defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) ) &&\
- ( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\
- defined(_M_X64) || defined(_M_IA64) )
- /* Windows system (DOS doesn't support DLLs) running on x86/x64. Includes
- * builds under Cygwin or MinGW. Also includes Watcom builds but these need
- * special treatment because they are not compatible with GCC or Visual C
- * because of different calling conventions.
+#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\
+ defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+ /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or
+ * MinGW on any architecture currently supported by Windows. Also includes
+ * Watcom builds but these need special treatment because they are not
+ * compatible with GCC or Visual C because of different calling conventions.
*/
# if PNG_API_RULE == 2
/* If this line results in an error, either because __watcall is not
@@ -199,9 +195,12 @@
# define PNGCAPI __watcall
# endif
-# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800))
+# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800))
# define PNGCAPI __cdecl
# if PNG_API_RULE == 1
+ /* If this line results in an error __stdcall is not understood and
+ * PNG_API_RULE should not have been set to '1'.
+ */
# define PNGAPI __stdcall
# endif
# else
@@ -239,7 +238,7 @@
# endif
# endif /* compiler */
-#else /* !Windows/x86 */
+#else /* !Windows */
# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__)
# define PNGAPI _System
# else /* !Windows/x86 && !OS/2 */
@@ -337,6 +336,7 @@
* functions in png.h will generate compiler warnings. Added at libpng
* version 1.2.41.
*/
+
# if defined(__GNUC__)
# ifndef PNG_USE_RESULT
# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
@@ -344,21 +344,23 @@
# ifndef PNG_NORETURN
# define PNG_NORETURN __attribute__((__noreturn__))
# endif
-# ifndef PNG_ALLOCATED
-# define PNG_ALLOCATED __attribute__((__malloc__))
-# endif
-# ifndef PNG_DEPRECATED
-# define PNG_DEPRECATED __attribute__((__deprecated__))
-# endif
-# ifndef PNG_PRIVATE
-# if 0 /* Doesn't work so we use deprecated instead*/
-# define PNG_PRIVATE \
- __attribute__((warning("This function is not exported by libpng.")))
-# else
-# define PNG_PRIVATE \
- __attribute__((__deprecated__))
+# if __GNUC__ >= 3
+# ifndef PNG_ALLOCATED
+# define PNG_ALLOCATED __attribute__((__malloc__))
# endif
-# endif
+# ifndef PNG_DEPRECATED
+# define PNG_DEPRECATED __attribute__((__deprecated__))
+# endif
+# ifndef PNG_PRIVATE
+# if 0 /* Doesn't work so we use deprecated instead*/
+# define PNG_PRIVATE \
+ __attribute__((warning("This function is not exported by libpng.")))
+# else
+# define PNG_PRIVATE \
+ __attribute__((__deprecated__))
+# endif
+# endif
+# endif /* __GNUC__ >= 3 */
# endif /* __GNUC__ */
# if defined(_MSC_VER) && (_MSC_VER >= 1300)
@@ -400,7 +402,7 @@
#ifndef PNG_FP_EXPORT /* A floating point API. */
# ifdef PNG_FLOATING_POINT_SUPPORTED
# define PNG_FP_EXPORT(ordinal, type, name, args)\
- PNG_EXPORT(ordinal, type, name, args)
+ PNG_EXPORT(ordinal, type, name, args);
# else /* No floating point APIs */
# define PNG_FP_EXPORT(ordinal, type, name, args)
# endif
@@ -408,7 +410,7 @@
#ifndef PNG_FIXED_EXPORT /* A fixed point API. */
# ifdef PNG_FIXED_POINT_SUPPORTED
# define PNG_FIXED_EXPORT(ordinal, type, name, args)\
- PNG_EXPORT(ordinal, type, name, args)
+ PNG_EXPORT(ordinal, type, name, args);
# else /* No fixed point APIs */
# define PNG_FIXED_EXPORT(ordinal, type, name, args)
# endif
diff --git a/drivers/png/pngdebug.h b/drivers/png/pngdebug.h
index 16f81fdd14..020369f061 100644
--- a/drivers/png/pngdebug.h
+++ b/drivers/png/pngdebug.h
@@ -1,12 +1,11 @@
/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
*
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.18 [February 6, 2014]
+ * Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
- * Last changed in libpng 1.5.0 [January 6, 2011]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
@@ -25,7 +24,7 @@
* (actually ((void)0)).
*
* level: level of detail of message, starting at 0. A level 'n'
- * message is preceded by 'n' tab characters (not implemented
+ * message is preceded by 'n' 3-space indentations (not implemented
* on Microsoft compilers unless PNG_DEBUG_FILE is also
* defined, to allow debug DLL compilation with no standard IO).
* message: a printf(3) style text string. A trailing '\n' is added
@@ -77,32 +76,29 @@
# endif /* PNG_DEBUG_FILE */
# if (PNG_DEBUG > 1)
-/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on
- * non-ISO compilers
- */
# ifdef __STDC__
# ifndef png_debug
# define png_debug(l,m) \
do { \
int num_tabs=l; \
- fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
- (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \
+ fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
+ (num_tabs==2 ? " " : (num_tabs>2 ? " " : "")))); \
} while (0)
# endif
# ifndef png_debug1
# define png_debug1(l,m,p1) \
do { \
int num_tabs=l; \
- fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
- (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \
+ fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
+ (num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1); \
} while (0)
# endif
# ifndef png_debug2
# define png_debug2(l,m,p1,p2) \
do { \
int num_tabs=l; \
- fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
- (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \
+ fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
+ (num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1,p2);\
} while (0)
# endif
# else /* __STDC __ */
diff --git a/drivers/png/pngerror.c b/drivers/png/pngerror.c
index 7604bddf18..372d1b6fbd 100644
--- a/drivers/png/pngerror.c
+++ b/drivers/png/pngerror.c
@@ -1,8 +1,8 @@
/* pngerror.c - stub functions for i/o and memory allocation
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.19 [August 21, 2014]
+ * Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -161,7 +161,7 @@ png_format_number(png_const_charp start, png_charp end, int format,
case PNG_NUMBER_FORMAT_02u:
/* Expects at least 2 digits. */
mincount = 2;
- /* fall through */
+ /* FALL THROUGH */
case PNG_NUMBER_FORMAT_u:
*--end = digits[number % 10];
@@ -171,7 +171,7 @@ png_format_number(png_const_charp start, png_charp end, int format,
case PNG_NUMBER_FORMAT_02x:
/* This format expects at least two digits */
mincount = 2;
- /* fall through */
+ /* FALL THROUGH */
case PNG_NUMBER_FORMAT_x:
*--end = digits[number & 0xf];
@@ -193,7 +193,7 @@ png_format_number(png_const_charp start, png_charp end, int format,
* drop the decimal point. If the number is a true zero handle that
* here.
*/
- if (output)
+ if (output != 0)
*--end = '.';
else if (number == 0) /* and !output */
*--end = '0';
@@ -281,35 +281,40 @@ void
png_formatted_warning(png_structp png_ptr, png_warning_parameters p,
png_const_charp message)
{
- /* The internal buffer is just 128 bytes - enough for all our messages,
- * overflow doesn't happen because this code checks!
+ /* The internal buffer is just 192 bytes - enough for all our messages,
+ * overflow doesn't happen because this code checks! If someone figures
+ * out how to send us a message longer than 192 bytes, all that will
+ * happen is that the message will be truncated appropriately.
*/
- size_t i;
- char msg[128];
-
- for (i=0; i<(sizeof msg)-1 && *message != '\0'; ++i)
+ size_t i = 0; /* Index in the msg[] buffer: */
+ char msg[192];
+
+ /* Each iteration through the following loop writes at most one character
+ * to msg[i++] then returns here to validate that there is still space for
+ * the trailing '\0'. It may (in the case of a parameter) read more than
+ * one character from message[]; it must check for '\0' and continue to the
+ * test if it finds the end of string.
+ */
+ while (i<(sizeof msg)-1 && *message != '\0')
{
- if (*message == '@')
+ /* '@' at end of string is now just printed (previously it was skipped);
+ * it is an error in the calling code to terminate the string with @.
+ */
+ if (p != NULL && *message == '@' && message[1] != '\0')
{
- int parameter = -1;
- switch (*++message)
- {
- case '1':
- parameter = 0;
- break;
-
- case '2':
- parameter = 1;
- break;
+ int parameter_char = *++message; /* Consume the '@' */
+ static const char valid_parameters[] = "123456789";
+ int parameter = 0;
- case '\0':
- continue; /* To break out of the for loop above. */
-
- default:
- break;
- }
+ /* Search for the parameter digit, the index in the string is the
+ * parameter to use.
+ */
+ while (valid_parameters[parameter] != parameter_char &&
+ valid_parameters[parameter] != '\0')
+ ++parameter;
- if (parameter >= 0 && parameter < PNG_WARNING_PARAMETER_COUNT)
+ /* If the parameter digit is out of range it will just get printed. */
+ if (parameter < PNG_WARNING_PARAMETER_COUNT)
{
/* Append this parameter */
png_const_charp parm = p[parameter];
@@ -319,28 +324,32 @@ png_formatted_warning(png_structp png_ptr, png_warning_parameters p,
* that parm[] has been initialized, so there is no guarantee of a
* trailing '\0':
*/
- for (; i<(sizeof msg)-1 && parm != '\0' && parm < pend; ++i)
- msg[i] = *parm++;
+ while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend)
+ msg[i++] = *parm++;
+ /* Consume the parameter digit too: */
++message;
continue;
}
/* else not a parameter and there is a character after the @ sign; just
- * copy that.
+ * copy that. This is known not to be '\0' because of the test above.
*/
}
/* At this point *message can't be '\0', even in the bad parameter case
* above where there is a lone '@' at the end of the message string.
*/
- msg[i] = *message++;
+ msg[i++] = *message++;
}
/* i is always less than (sizeof msg), so: */
msg[i] = '\0';
- /* And this is the formatted message: */
+ /* And this is the formatted message, it may be larger than
+ * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these are
+ * not (currently) formatted.
+ */
png_warning(png_ptr, msg);
}
#endif /* PNG_WARNINGS_SUPPORTED */
@@ -569,6 +578,9 @@ png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN)
png_ptr->longjmp_fn(png_ptr->longjmp_buffer, val);
# endif
}
+#else
+ PNG_UNUSED(png_ptr);
+ PNG_UNUSED(val);
#endif
/* Here if not setjmp support or if png_ptr is null. */
PNG_ABORT();
diff --git a/drivers/png/pngget.c b/drivers/png/pngget.c
index 43400cda7e..5b1d757c66 100644
--- a/drivers/png/pngget.c
+++ b/drivers/png/pngget.c
@@ -1,8 +1,8 @@
/* pngget.c - retrieval of values from info struct
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.19 [August 21, 2014]
+ * Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -123,6 +123,9 @@ png_get_x_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
return (info_ptr->x_pixels_per_unit);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
@@ -140,6 +143,9 @@ png_get_y_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
return (info_ptr->y_pixels_per_unit);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
@@ -157,6 +163,9 @@ png_get_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit)
return (info_ptr->x_pixels_per_unit);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
@@ -175,6 +184,9 @@ png_get_pixel_aspect_ratio(png_const_structp png_ptr, png_const_infop info_ptr)
return ((float)((float)info_ptr->y_pixels_per_unit
/(float)info_ptr->x_pixels_per_unit));
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return ((float)0.0);
@@ -203,6 +215,9 @@ png_get_pixel_aspect_ratio_fixed(png_const_structp png_ptr,
(png_int_32)info_ptr->x_pixels_per_unit))
return res;
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return 0;
@@ -220,6 +235,9 @@ png_get_x_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr)
if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
return (info_ptr->x_offset);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
@@ -236,6 +254,9 @@ png_get_y_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr)
if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
return (info_ptr->y_offset);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
@@ -252,6 +273,9 @@ png_get_x_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr)
if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
return (info_ptr->x_offset);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
@@ -268,6 +292,9 @@ png_get_y_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr)
if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
return (info_ptr->y_offset);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
@@ -646,7 +673,7 @@ png_get_gAMA(png_const_structp png_ptr, png_const_infop info_ptr,
png_fixed_point igamma;
png_uint_32 ok = png_get_gAMA_fixed(png_ptr, info_ptr, &igamma);
- if (ok)
+ if (ok != 0)
*file_gamma = png_float(png_ptr, igamma, "png_get_gAMA");
return ok;
@@ -741,14 +768,20 @@ png_get_IHDR(png_structp png_ptr, png_infop info_ptr,
{
png_debug1(1, "in %s retrieval function", "IHDR");
- if (png_ptr == NULL || info_ptr == NULL || width == NULL ||
- height == NULL || bit_depth == NULL || color_type == NULL)
+ if (png_ptr == NULL || info_ptr == NULL)
return (0);
- *width = info_ptr->width;
- *height = info_ptr->height;
- *bit_depth = info_ptr->bit_depth;
- *color_type = info_ptr->color_type;
+ if (width != NULL)
+ *width = info_ptr->width;
+
+ if (height != NULL)
+ *height = info_ptr->height;
+
+ if (bit_depth != NULL)
+ *bit_depth = info_ptr->bit_depth;
+
+ if (color_type != NULL)
+ *color_type = info_ptr->color_type;
if (compression_type != NULL)
*compression_type = info_ptr->compression_type;
@@ -1121,4 +1154,17 @@ png_get_io_chunk_name (png_structp png_ptr)
}
#endif /* ?PNG_IO_STATE_SUPPORTED */
+#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+# ifdef PNG_GET_PALETTE_MAX_SUPPORTED
+int PNGAPI
+png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+ return png_ptr->num_palette_max;
+
+ return (-1);
+}
+# endif
+#endif
+
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
diff --git a/drivers/png/pnginfo.h b/drivers/png/pnginfo.h
index a33bfab06d..c5b68c1e84 100644
--- a/drivers/png/pnginfo.h
+++ b/drivers/png/pnginfo.h
@@ -1,12 +1,11 @@
/* pnginfo.h - header file for PNG reference library
*
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.0 [January 6, 2011]
+ * Copyright (c) 1998-2002,2004,2006-2011 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
- * Last changed in libpng 1.5.0 [January 6, 2011]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
@@ -242,7 +241,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
#ifdef PNG_sPLT_SUPPORTED
/* Data on sPLT chunks (there may be more than one). */
png_sPLT_tp splt_palettes;
- png_uint_32 splt_palettes_num;
+ int splt_palettes_num;
#endif
#ifdef PNG_sCAL_SUPPORTED
diff --git a/drivers/png/pnglibconf.h b/drivers/png/pnglibconf.h
index 0a799915f8..37f63f2721 100644
--- a/drivers/png/pnglibconf.h
+++ b/drivers/png/pnglibconf.h
@@ -1,51 +1,28 @@
-
-/* libpng STANDARD API DEFINITION */
-
+/* 1.5.26 STANDARD API DEFINITION */
/* pnglibconf.h - library build configuration */
-/* Libpng 1.5.7 - December 15, 2011 */
+/* libpng version 1.5.26 - December 17, 2015 */
-/* Copyright (c) 1998-2011 Glenn Randers-Pehrson */
+/* Copyright (c) 1998-2015 Glenn Randers-Pehrson */
/* This code is released under the libpng license. */
/* For conditions of distribution and use, see the disclaimer */
/* and license in png.h */
/* pnglibconf.h */
+/* Machine generated file: DO NOT EDIT */
/* Derived from: scripts/pnglibconf.dfa */
-/* If you edit this file by hand you must obey the rules expressed in */
-/* pnglibconf.dfa with respect to the dependencies between the following */
-/* symbols. It is much better to generate a new file using */
-/* scripts/libpngconf.mak */
-
#ifndef PNGLCONF_H
#define PNGLCONF_H
-/* settings */
-#define PNG_API_RULE 0
-#define PNG_CALLOC_SUPPORTED
-#define PNG_COST_SHIFT 3
-#define PNG_DEFAULT_READ_MACROS 1
-#define PNG_GAMMA_THRESHOLD_FIXED 5000
-#define PNG_MAX_GAMMA_8 11
-#define PNG_QUANTIZE_BLUE_BITS 5
-#define PNG_QUANTIZE_GREEN_BITS 5
-#define PNG_QUANTIZE_RED_BITS 5
-#define PNG_sCAL_PRECISION 5
-#define PNG_USER_CHUNK_CACHE_MAX 0
-#define PNG_USER_CHUNK_MALLOC_MAX 0
-#define PNG_USER_HEIGHT_MAX 1000000
-#define PNG_USER_WIDTH_MAX 1000000
-#define PNG_WEIGHT_SHIFT 8
-#define PNG_ZBUF_SIZE 8192
-/* end of settings */
/* options */
#define PNG_16BIT_SUPPORTED
-#define PNG_ALIGN_MEMORY_SUPPORTED
+#define PNG_ALIGNED_MEMORY_SUPPORTED
+/*#undef PNG_ARM_NEON_API_SUPPORTED*/
+/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
#define PNG_BENIGN_ERRORS_SUPPORTED
-#define PNG_bKGD_SUPPORTED
#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
+#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
#define PNG_CHECK_cHRM_SUPPORTED
-#define PNG_cHRM_SUPPORTED
#define PNG_CONSOLE_IO_SUPPORTED
#define PNG_CONVERT_tIME_SUPPORTED
#define PNG_EASY_ACCESS_SUPPORTED
@@ -54,20 +31,12 @@
#define PNG_FIXED_POINT_SUPPORTED
#define PNG_FLOATING_ARITHMETIC_SUPPORTED
#define PNG_FLOATING_POINT_SUPPORTED
-#define PNG_FORMAT_AFIRST_SUPPORTED
-#define PNG_FORMAT_BGR_SUPPORTED
-#define PNG_gAMA_SUPPORTED
+#define PNG_GET_PALETTE_MAX_SUPPORTED
#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-#define PNG_hIST_SUPPORTED
-#define PNG_iCCP_SUPPORTED
#define PNG_INCH_CONVERSIONS_SUPPORTED
#define PNG_INFO_IMAGE_SUPPORTED
#define PNG_IO_STATE_SUPPORTED
-#define PNG_iTXt_SUPPORTED
#define PNG_MNG_FEATURES_SUPPORTED
-#define PNG_oFFs_SUPPORTED
-#define PNG_pCAL_SUPPORTED
-#define PNG_pHYs_SUPPORTED
#define PNG_POINTER_INDEXING_SUPPORTED
#define PNG_PROGRESSIVE_READ_SUPPORTED
#define PNG_READ_16BIT_SUPPORTED
@@ -75,67 +44,62 @@
#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
#define PNG_READ_BACKGROUND_SUPPORTED
#define PNG_READ_BGR_SUPPORTED
-#define PNG_READ_bKGD_SUPPORTED
-#define PNG_READ_cHRM_SUPPORTED
+#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
#define PNG_READ_COMPOSITE_NODIV_SUPPORTED
#define PNG_READ_COMPRESSED_TEXT_SUPPORTED
#define PNG_READ_EXPAND_16_SUPPORTED
#define PNG_READ_EXPAND_SUPPORTED
#define PNG_READ_FILLER_SUPPORTED
-#define PNG_READ_gAMA_SUPPORTED
#define PNG_READ_GAMMA_SUPPORTED
+#define PNG_READ_GET_PALETTE_MAX_SUPPORTED
#define PNG_READ_GRAY_TO_RGB_SUPPORTED
-#define PNG_READ_hIST_SUPPORTED
-#define PNG_READ_iCCP_SUPPORTED
#define PNG_READ_INTERLACING_SUPPORTED
#define PNG_READ_INT_FUNCTIONS_SUPPORTED
#define PNG_READ_INVERT_ALPHA_SUPPORTED
#define PNG_READ_INVERT_SUPPORTED
-#define PNG_READ_iTXt_SUPPORTED
-#define PNG_READ_oFFs_SUPPORTED
#define PNG_READ_OPT_PLTE_SUPPORTED
-#define PNG_READ_PACK_SUPPORTED
#define PNG_READ_PACKSWAP_SUPPORTED
-#define PNG_READ_pCAL_SUPPORTED
-#define PNG_READ_pHYs_SUPPORTED
+#define PNG_READ_PACK_SUPPORTED
#define PNG_READ_QUANTIZE_SUPPORTED
#define PNG_READ_RGB_TO_GRAY_SUPPORTED
-#define PNG_READ_sBIT_SUPPORTED
#define PNG_READ_SCALE_16_TO_8_SUPPORTED
-#define PNG_READ_sCAL_SUPPORTED
#define PNG_READ_SHIFT_SUPPORTED
-#define PNG_READ_sPLT_SUPPORTED
-#define PNG_READ_sRGB_SUPPORTED
#define PNG_READ_STRIP_16_TO_8_SUPPORTED
#define PNG_READ_STRIP_ALPHA_SUPPORTED
#define PNG_READ_SUPPORTED
#define PNG_READ_SWAP_ALPHA_SUPPORTED
#define PNG_READ_SWAP_SUPPORTED
-#define PNG_READ_tEXt_SUPPORTED
#define PNG_READ_TEXT_SUPPORTED
-#define PNG_READ_tIME_SUPPORTED
#define PNG_READ_TRANSFORMS_SUPPORTED
-#define PNG_READ_tRNS_SUPPORTED
#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_READ_USER_CHUNKS_SUPPORTED
#define PNG_READ_USER_TRANSFORM_SUPPORTED
+#define PNG_READ_bKGD_SUPPORTED
+#define PNG_READ_cHRM_SUPPORTED
+#define PNG_READ_gAMA_SUPPORTED
+#define PNG_READ_hIST_SUPPORTED
+#define PNG_READ_iCCP_SUPPORTED
+#define PNG_READ_iTXt_SUPPORTED
+#define PNG_READ_oFFs_SUPPORTED
+#define PNG_READ_pCAL_SUPPORTED
+#define PNG_READ_pHYs_SUPPORTED
+#define PNG_READ_sBIT_SUPPORTED
+#define PNG_READ_sCAL_SUPPORTED
+#define PNG_READ_sPLT_SUPPORTED
+#define PNG_READ_sRGB_SUPPORTED
+#define PNG_READ_tEXt_SUPPORTED
+#define PNG_READ_tIME_SUPPORTED
+#define PNG_READ_tRNS_SUPPORTED
#define PNG_READ_zTXt_SUPPORTED
+/*#undef PNG_SAFE_LIMITS_SUPPORTED*/
#define PNG_SAVE_INT_32_SUPPORTED
-#define PNG_sBIT_SUPPORTED
-#define PNG_sCAL_SUPPORTED
#define PNG_SEQUENTIAL_READ_SUPPORTED
-#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED
-#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
#define PNG_SETJMP_SUPPORTED
+/*#undef PNG_SET_OPTION_SUPPORTED*/
#define PNG_SET_USER_LIMITS_SUPPORTED
-#define PNG_sPLT_SUPPORTED
-#define PNG_sRGB_SUPPORTED
#define PNG_STDIO_SUPPORTED
-#define PNG_tEXt_SUPPORTED
#define PNG_TEXT_SUPPORTED
#define PNG_TIME_RFC1123_SUPPORTED
-#define PNG_tIME_SUPPORTED
-#define PNG_tRNS_SUPPORTED
#define PNG_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_USER_CHUNKS_SUPPORTED
#define PNG_USER_LIMITS_SUPPORTED
@@ -146,44 +110,78 @@
#define PNG_WRITE_16BIT_SUPPORTED
#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
#define PNG_WRITE_BGR_SUPPORTED
-#define PNG_WRITE_bKGD_SUPPORTED
-#define PNG_WRITE_cHRM_SUPPORTED
+#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
+#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
#define PNG_WRITE_FILLER_SUPPORTED
#define PNG_WRITE_FILTER_SUPPORTED
#define PNG_WRITE_FLUSH_SUPPORTED
-#define PNG_WRITE_gAMA_SUPPORTED
-#define PNG_WRITE_hIST_SUPPORTED
-#define PNG_WRITE_iCCP_SUPPORTED
+#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED
#define PNG_WRITE_INTERLACING_SUPPORTED
#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED
#define PNG_WRITE_INVERT_ALPHA_SUPPORTED
#define PNG_WRITE_INVERT_SUPPORTED
-#define PNG_WRITE_iTXt_SUPPORTED
-#define PNG_WRITE_oFFs_SUPPORTED
#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
-#define PNG_WRITE_PACK_SUPPORTED
#define PNG_WRITE_PACKSWAP_SUPPORTED
-#define PNG_WRITE_pCAL_SUPPORTED
-#define PNG_WRITE_pHYs_SUPPORTED
-#define PNG_WRITE_sBIT_SUPPORTED
-#define PNG_WRITE_sCAL_SUPPORTED
+#define PNG_WRITE_PACK_SUPPORTED
#define PNG_WRITE_SHIFT_SUPPORTED
-#define PNG_WRITE_sPLT_SUPPORTED
-#define PNG_WRITE_sRGB_SUPPORTED
#define PNG_WRITE_SUPPORTED
#define PNG_WRITE_SWAP_ALPHA_SUPPORTED
#define PNG_WRITE_SWAP_SUPPORTED
-#define PNG_WRITE_tEXt_SUPPORTED
#define PNG_WRITE_TEXT_SUPPORTED
-#define PNG_WRITE_tIME_SUPPORTED
#define PNG_WRITE_TRANSFORMS_SUPPORTED
-#define PNG_WRITE_tRNS_SUPPORTED
#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_WRITE_USER_TRANSFORM_SUPPORTED
#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+#define PNG_WRITE_bKGD_SUPPORTED
+#define PNG_WRITE_cHRM_SUPPORTED
+#define PNG_WRITE_gAMA_SUPPORTED
+#define PNG_WRITE_hIST_SUPPORTED
+#define PNG_WRITE_iCCP_SUPPORTED
+#define PNG_WRITE_iTXt_SUPPORTED
+#define PNG_WRITE_oFFs_SUPPORTED
+#define PNG_WRITE_pCAL_SUPPORTED
+#define PNG_WRITE_pHYs_SUPPORTED
+#define PNG_WRITE_sBIT_SUPPORTED
+#define PNG_WRITE_sCAL_SUPPORTED
+#define PNG_WRITE_sPLT_SUPPORTED
+#define PNG_WRITE_sRGB_SUPPORTED
+#define PNG_WRITE_tEXt_SUPPORTED
+#define PNG_WRITE_tIME_SUPPORTED
+#define PNG_WRITE_tRNS_SUPPORTED
#define PNG_WRITE_zTXt_SUPPORTED
+#define PNG_bKGD_SUPPORTED
+#define PNG_cHRM_SUPPORTED
+#define PNG_gAMA_SUPPORTED
+#define PNG_hIST_SUPPORTED
+#define PNG_iCCP_SUPPORTED
+#define PNG_iTXt_SUPPORTED
+#define PNG_oFFs_SUPPORTED
+#define PNG_pCAL_SUPPORTED
+#define PNG_pHYs_SUPPORTED
+#define PNG_sBIT_SUPPORTED
+#define PNG_sCAL_SUPPORTED
+#define PNG_sPLT_SUPPORTED
+#define PNG_sRGB_SUPPORTED
+#define PNG_tEXt_SUPPORTED
+#define PNG_tIME_SUPPORTED
+#define PNG_tRNS_SUPPORTED
#define PNG_zTXt_SUPPORTED
/* end of options */
+/* settings */
+#define PNG_API_RULE 0
+#define PNG_DEFAULT_READ_MACROS 1
+#define PNG_GAMMA_THRESHOLD_FIXED 5000
+#define PNG_MAX_GAMMA_8 11
+#define PNG_QUANTIZE_BLUE_BITS 5
+#define PNG_QUANTIZE_GREEN_BITS 5
+#define PNG_QUANTIZE_RED_BITS 5
+#define PNG_USER_CHUNK_CACHE_MAX 1000
+#define PNG_USER_CHUNK_MALLOC_MAX 8000000
+#define PNG_USER_HEIGHT_MAX 1000000
+#define PNG_USER_WIDTH_MAX 1000000
+#define PNG_ZBUF_SIZE 8192
+#define PNG_sCAL_PRECISION 5
+/* end of settings */
#endif /* PNGLCONF_H */
diff --git a/drivers/png/pngmem.c b/drivers/png/pngmem.c
index bf5ff037da..ae74dcace0 100644
--- a/drivers/png/pngmem.c
+++ b/drivers/png/pngmem.c
@@ -1,8 +1,8 @@
/* pngmem.c - stub functions for memory allocation
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.13 [September 27, 2012]
+ * Copyright (c) 1998-2002,2004,2006-2012 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -56,7 +56,7 @@ png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr),
if (malloc_fn != NULL)
{
png_struct dummy_struct;
- memset(&dummy_struct, 0, sizeof dummy_struct);
+ png_memset(&dummy_struct, 0, sizeof dummy_struct);
dummy_struct.mem_ptr=mem_ptr;
struct_ptr = (*(malloc_fn))(&dummy_struct, (png_alloc_size_t)size);
}
@@ -90,7 +90,7 @@ png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
if (free_fn != NULL)
{
png_struct dummy_struct;
- memset(&dummy_struct, 0, sizeof dummy_struct);
+ png_memset(&dummy_struct, 0, sizeof dummy_struct);
dummy_struct.mem_ptr=mem_ptr;
(*(free_fn))(&dummy_struct, struct_ptr);
return;
@@ -102,7 +102,7 @@ png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
}
/* Allocate memory. For reasonable files, size should never exceed
- * 64K. However, zlib may allocate more then 64K if you don't tell
+ * 64K. However, zlib may allocate more than 64K if you don't tell
* it not to. See zconf.h and png.h for more information. zlib does
* need to allocate exactly 64K, so whatever you call here must
* have the ability to do that.
@@ -475,7 +475,7 @@ png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
}
/* Allocate memory. For reasonable files, size should never exceed
- * 64K. However, zlib may allocate more then 64K if you don't tell
+ * 64K. However, zlib may allocate more than 64K if you don't tell
* it not to. See zconf.h and png.h for more information. zlib does
* need to allocate exactly 64K, so whatever you call here must
* have the ability to do that.
diff --git a/drivers/png/pngpread.c b/drivers/png/pngpread.c
index 20d3f236e1..9cf987d7e3 100644
--- a/drivers/png/pngpread.c
+++ b/drivers/png/pngpread.c
@@ -1,8 +1,8 @@
/* pngpread.c - read a png file in push mode
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.23 [July 23, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -19,7 +19,6 @@
#define PNG_READ_SIG_MODE 0
#define PNG_READ_CHUNK_MODE 1
#define PNG_READ_IDAT_MODE 2
-#define PNG_SKIP_MODE 3
#define PNG_READ_tEXt_MODE 4
#define PNG_READ_zTXt_MODE 5
#define PNG_READ_DONE_MODE 6
@@ -49,7 +48,7 @@ png_process_data_pause(png_structp png_ptr, int save)
/* It's easiest for the caller if we do the save, then the caller doesn't
* have to supply the same data again:
*/
- if (save)
+ if (save != 0)
png_push_save_buffer(png_ptr);
else
{
@@ -71,32 +70,15 @@ png_process_data_pause(png_structp png_ptr, int save)
png_uint_32 PNGAPI
png_process_data_skip(png_structp png_ptr)
{
- png_uint_32 remaining = 0;
-
- if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE &&
- png_ptr->skip_length > 0)
- {
- /* At the end of png_process_data the buffer size must be 0 (see the loop
- * above) so we can detect a broken call here:
- */
- if (png_ptr->buffer_size != 0)
- png_error(png_ptr,
- "png_process_data_skip called inside png_process_data");
-
- /* If is impossible for there to be a saved buffer at this point -
- * otherwise we could not be in SKIP mode. This will also happen if
- * png_process_skip is called inside png_process_data (but only very
- * rarely.)
- */
- if (png_ptr->save_buffer_size != 0)
- png_error(png_ptr, "png_process_data_skip called with saved data");
-
- remaining = png_ptr->skip_length;
- png_ptr->skip_length = 0;
- png_ptr->process_mode = PNG_READ_CHUNK_MODE;
- }
-
- return remaining;
+ /* TODO: Deprecate and remove this API.
+ * Somewhere the implementation of this seems to have been lost,
+ * or abandoned. It was only to support some internal back-door access
+ * to png_struct) in libpng-1.4.x.
+ */
+ png_warning(png_ptr,
+ "png_process_data_skip is not implemented in any current version"
+ " of libpng");
+ return 0;
}
/* What we do with the incoming data depends on what we were previously
@@ -128,36 +110,6 @@ png_process_some_data(png_structp png_ptr, png_infop info_ptr)
break;
}
-#ifdef PNG_READ_tEXt_SUPPORTED
- case PNG_READ_tEXt_MODE:
- {
- png_push_read_tEXt(png_ptr, info_ptr);
- break;
- }
-
-#endif
-#ifdef PNG_READ_zTXt_SUPPORTED
- case PNG_READ_zTXt_MODE:
- {
- png_push_read_zTXt(png_ptr, info_ptr);
- break;
- }
-
-#endif
-#ifdef PNG_READ_iTXt_SUPPORTED
- case PNG_READ_iTXt_MODE:
- {
- png_push_read_iTXt(png_ptr, info_ptr);
- break;
- }
-
-#endif
- case PNG_SKIP_MODE:
- {
- png_push_crc_finish(png_ptr);
- break;
- }
-
default:
{
png_ptr->buffer_size = 0;
@@ -175,8 +127,8 @@ png_process_some_data(png_structp png_ptr, png_infop info_ptr)
void /* PRIVATE */
png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
{
- png_size_t num_checked = png_ptr->sig_bytes,
- num_to_check = 8 - num_checked;
+ png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */
+ num_to_check = 8 - num_checked;
if (png_ptr->buffer_size < num_to_check)
{
@@ -196,6 +148,7 @@ png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
else
png_error(png_ptr, "PNG file corrupted by ASCII conversion");
}
+
else
{
if (png_ptr->sig_bytes >= 8)
@@ -305,8 +258,8 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
png_error(png_ptr, "Missing PLTE before IDAT");
}
}
-
#endif
+
else if (chunk_name == png_PLTE)
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -543,7 +496,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
return;
}
- png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
+ png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
@@ -556,7 +509,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
return;
}
- png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
+ png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
@@ -569,10 +522,11 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
return;
}
- png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
+ png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
+
else
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -580,80 +534,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
png_push_save_buffer(png_ptr);
return;
}
- png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
+ png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
}
png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
}
-void /* PRIVATE */
-png_push_crc_skip(png_structp png_ptr, png_uint_32 skip)
-{
- png_ptr->process_mode = PNG_SKIP_MODE;
- png_ptr->skip_length = skip;
-}
-
-void /* PRIVATE */
-png_push_crc_finish(png_structp png_ptr)
-{
- if (png_ptr->skip_length && png_ptr->save_buffer_size)
- {
- png_size_t save_size = png_ptr->save_buffer_size;
- png_uint_32 skip_length = png_ptr->skip_length;
-
- /* We want the smaller of 'skip_length' and 'save_buffer_size', but
- * they are of different types and we don't know which variable has the
- * fewest bits. Carefully select the smaller and cast it to the type of
- * the larger - this cannot overflow. Do not cast in the following test
- * - it will break on either 16 or 64 bit platforms.
- */
- if (skip_length < save_size)
- save_size = (png_size_t)skip_length;
-
- else
- skip_length = (png_uint_32)save_size;
-
- png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
-
- png_ptr->skip_length -= skip_length;
- png_ptr->buffer_size -= save_size;
- png_ptr->save_buffer_size -= save_size;
- png_ptr->save_buffer_ptr += save_size;
- }
- if (png_ptr->skip_length && png_ptr->current_buffer_size)
- {
- png_size_t save_size = png_ptr->current_buffer_size;
- png_uint_32 skip_length = png_ptr->skip_length;
-
- /* We want the smaller of 'skip_length' and 'current_buffer_size', here,
- * the same problem exists as above and the same solution.
- */
- if (skip_length < save_size)
- save_size = (png_size_t)skip_length;
-
- else
- skip_length = (png_uint_32)save_size;
-
- png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
-
- png_ptr->skip_length -= skip_length;
- png_ptr->buffer_size -= save_size;
- png_ptr->current_buffer_size -= save_size;
- png_ptr->current_buffer_ptr += save_size;
- }
- if (!png_ptr->skip_length)
- {
- if (png_ptr->buffer_size < 4)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_crc_finish(png_ptr, 0);
- png_ptr->process_mode = PNG_READ_CHUNK_MODE;
- }
-}
-
void PNGCBAPI
png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
{
@@ -663,6 +549,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
return;
ptr = buffer;
+
if (png_ptr->save_buffer_size)
{
png_size_t save_size;
@@ -680,6 +567,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
png_ptr->save_buffer_size -= save_size;
png_ptr->save_buffer_ptr += save_size;
}
+
if (length && png_ptr->current_buffer_size)
{
png_size_t save_size;
@@ -709,6 +597,7 @@ png_push_save_buffer(png_structp png_ptr)
png_bytep dp;
istop = png_ptr->save_buffer_size;
+
for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
i < istop; i++, sp++, dp++)
{
@@ -716,6 +605,7 @@ png_push_save_buffer(png_structp png_ptr)
}
}
}
+
if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
png_ptr->save_buffer_max)
{
@@ -730,8 +620,7 @@ png_push_save_buffer(png_structp png_ptr)
new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
old_buffer = png_ptr->save_buffer;
- png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
- (png_size_t)new_max);
+ png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, new_max);
if (png_ptr->save_buffer == NULL)
{
@@ -743,6 +632,7 @@ png_push_save_buffer(png_structp png_ptr)
png_free(png_ptr, old_buffer);
png_ptr->save_buffer_max = new_max;
}
+
if (png_ptr->current_buffer_size)
{
png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
@@ -750,6 +640,7 @@ png_push_save_buffer(png_structp png_ptr)
png_ptr->save_buffer_size += png_ptr->current_buffer_size;
png_ptr->current_buffer_size = 0;
}
+
png_ptr->save_buffer_ptr = png_ptr->save_buffer;
png_ptr->buffer_size = 0;
}
@@ -851,6 +742,7 @@ png_push_read_IDAT(png_structp png_ptr)
png_ptr->current_buffer_size -= save_size;
png_ptr->current_buffer_ptr += save_size;
}
+
if (!png_ptr->idat_size)
{
if (png_ptr->buffer_size < 4)
@@ -911,6 +803,12 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
*/
ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH);
+ /* Hack, added in 1.5.18: the progressive reader does not reset
+ * png_ptr->zstream, so any attempt to use it after the last IDAT fails
+ * (silently). This allows the read code to do the reset when required.
+ */
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_PROGRESSIVE;
+
/* Check for any failure before proceeding. */
if (ret != Z_OK && ret != Z_STREAM_END)
{
@@ -1201,6 +1099,7 @@ png_push_process_row(png_structp png_ptr)
void /* PRIVATE */
png_read_push_finish_row(png_structp png_ptr)
{
+#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
@@ -1219,6 +1118,7 @@ png_read_push_finish_row(png_structp png_ptr)
* it, uncomment it here and in png.h
static PNG_CONST png_byte FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
*/
+#endif
png_ptr->row_number++;
if (png_ptr->row_number < png_ptr->num_rows)
@@ -1262,525 +1162,6 @@ png_read_push_finish_row(png_structp png_ptr)
#endif /* PNG_READ_INTERLACING_SUPPORTED */
}
-#ifdef PNG_READ_tEXt_SUPPORTED
-void /* PRIVATE */
-png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
- length)
-{
- if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
- {
- PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */
- png_error(png_ptr, "Out of place tEXt");
- /* NOT REACHED */
- }
-
-#ifdef PNG_MAX_MALLOC_64K
- png_ptr->skip_length = 0; /* This may not be necessary */
-
- if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
- {
- png_warning(png_ptr, "tEXt chunk too large to fit in memory");
- png_ptr->skip_length = length - (png_uint_32)65535L;
- length = (png_uint_32)65535L;
- }
-#endif
-
- png_ptr->current_text = (png_charp)png_malloc(png_ptr,
- (png_size_t)(length + 1));
- png_ptr->current_text[length] = '\0';
- png_ptr->current_text_ptr = png_ptr->current_text;
- png_ptr->current_text_size = (png_size_t)length;
- png_ptr->current_text_left = (png_size_t)length;
- png_ptr->process_mode = PNG_READ_tEXt_MODE;
-}
-
-void /* PRIVATE */
-png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
-{
- if (png_ptr->buffer_size && png_ptr->current_text_left)
- {
- png_size_t text_size;
-
- if (png_ptr->buffer_size < png_ptr->current_text_left)
- text_size = png_ptr->buffer_size;
-
- else
- text_size = png_ptr->current_text_left;
-
- png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
- png_ptr->current_text_left -= text_size;
- png_ptr->current_text_ptr += text_size;
- }
- if (!(png_ptr->current_text_left))
- {
- png_textp text_ptr;
- png_charp text;
- png_charp key;
- int ret;
-
- if (png_ptr->buffer_size < 4)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_push_crc_finish(png_ptr);
-
-#ifdef PNG_MAX_MALLOC_64K
- if (png_ptr->skip_length)
- return;
-#endif
-
- key = png_ptr->current_text;
-
- for (text = key; *text; text++)
- /* Empty loop */ ;
-
- if (text < key + png_ptr->current_text_size)
- text++;
-
- text_ptr = (png_textp)png_malloc(png_ptr, png_sizeof(png_text));
- text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
- text_ptr->key = key;
- text_ptr->itxt_length = 0;
- text_ptr->lang = NULL;
- text_ptr->lang_key = NULL;
- text_ptr->text = text;
-
- ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
- png_free(png_ptr, key);
- png_free(png_ptr, text_ptr);
- png_ptr->current_text = NULL;
-
- if (ret)
- png_warning(png_ptr, "Insufficient memory to store text chunk");
- }
-}
-#endif
-
-#ifdef PNG_READ_zTXt_SUPPORTED
-void /* PRIVATE */
-png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
- length)
-{
- if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
- {
- PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */
- png_error(png_ptr, "Out of place zTXt");
- /* NOT REACHED */
- }
-
-#ifdef PNG_MAX_MALLOC_64K
- /* We can't handle zTXt chunks > 64K, since we don't have enough space
- * to be able to store the uncompressed data. Actually, the threshold
- * is probably around 32K, but it isn't as definite as 64K is.
- */
- if (length > (png_uint_32)65535L)
- {
- png_warning(png_ptr, "zTXt chunk too large to fit in memory");
- png_push_crc_skip(png_ptr, length);
- return;
- }
-#endif
-
- png_ptr->current_text = (png_charp)png_malloc(png_ptr,
- (png_size_t)(length + 1));
- png_ptr->current_text[length] = '\0';
- png_ptr->current_text_ptr = png_ptr->current_text;
- png_ptr->current_text_size = (png_size_t)length;
- png_ptr->current_text_left = (png_size_t)length;
- png_ptr->process_mode = PNG_READ_zTXt_MODE;
-}
-
-void /* PRIVATE */
-png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
-{
- if (png_ptr->buffer_size && png_ptr->current_text_left)
- {
- png_size_t text_size;
-
- if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left)
- text_size = png_ptr->buffer_size;
-
- else
- text_size = png_ptr->current_text_left;
-
- png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
- png_ptr->current_text_left -= text_size;
- png_ptr->current_text_ptr += text_size;
- }
- if (!(png_ptr->current_text_left))
- {
- png_textp text_ptr;
- png_charp text;
- png_charp key;
- int ret;
- png_size_t text_size, key_size;
-
- if (png_ptr->buffer_size < 4)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_push_crc_finish(png_ptr);
-
- key = png_ptr->current_text;
-
- for (text = key; *text; text++)
- /* Empty loop */ ;
-
- /* zTXt can't have zero text */
- if (text >= key + png_ptr->current_text_size)
- {
- png_ptr->current_text = NULL;
- png_free(png_ptr, key);
- return;
- }
-
- text++;
-
- if (*text != PNG_TEXT_COMPRESSION_zTXt) /* Check compression byte */
- {
- png_ptr->current_text = NULL;
- png_free(png_ptr, key);
- return;
- }
-
- text++;
-
- png_ptr->zstream.next_in = (png_bytep)text;
- png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -
- (text - key));
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
-
- key_size = text - key;
- text_size = 0;
- text = NULL;
- ret = Z_STREAM_END;
-
- while (png_ptr->zstream.avail_in)
- {
- ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
- if (ret != Z_OK && ret != Z_STREAM_END)
- {
- inflateReset(&png_ptr->zstream);
- png_ptr->zstream.avail_in = 0;
- png_ptr->current_text = NULL;
- png_free(png_ptr, key);
- png_free(png_ptr, text);
- return;
- }
-
- if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END)
- {
- if (text == NULL)
- {
- text = (png_charp)png_malloc(png_ptr,
- (png_ptr->zbuf_size
- - png_ptr->zstream.avail_out + key_size + 1));
-
- png_memcpy(text + key_size, png_ptr->zbuf,
- png_ptr->zbuf_size - png_ptr->zstream.avail_out);
-
- png_memcpy(text, key, key_size);
-
- text_size = key_size + png_ptr->zbuf_size -
- png_ptr->zstream.avail_out;
-
- *(text + text_size) = '\0';
- }
-
- else
- {
- png_charp tmp;
-
- tmp = text;
- text = (png_charp)png_malloc(png_ptr, text_size +
- (png_ptr->zbuf_size
- - png_ptr->zstream.avail_out + 1));
-
- png_memcpy(text, tmp, text_size);
- png_free(png_ptr, tmp);
-
- png_memcpy(text + text_size, png_ptr->zbuf,
- png_ptr->zbuf_size - png_ptr->zstream.avail_out);
-
- text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
- *(text + text_size) = '\0';
- }
-
- if (ret != Z_STREAM_END)
- {
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
- }
- }
- else
- {
- break;
- }
-
- if (ret == Z_STREAM_END)
- break;
- }
-
- inflateReset(&png_ptr->zstream);
- png_ptr->zstream.avail_in = 0;
-
- if (ret != Z_STREAM_END)
- {
- png_ptr->current_text = NULL;
- png_free(png_ptr, key);
- png_free(png_ptr, text);
- return;
- }
-
- png_ptr->current_text = NULL;
- png_free(png_ptr, key);
- key = text;
- text += key_size;
-
- text_ptr = (png_textp)png_malloc(png_ptr,
- png_sizeof(png_text));
- text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;
- text_ptr->key = key;
- text_ptr->itxt_length = 0;
- text_ptr->lang = NULL;
- text_ptr->lang_key = NULL;
- text_ptr->text = text;
-
- ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
- png_free(png_ptr, key);
- png_free(png_ptr, text_ptr);
-
- if (ret)
- png_warning(png_ptr, "Insufficient memory to store text chunk");
- }
-}
-#endif
-
-#ifdef PNG_READ_iTXt_SUPPORTED
-void /* PRIVATE */
-png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
- length)
-{
- if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
- {
- PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */
- png_error(png_ptr, "Out of place iTXt");
- /* NOT REACHED */
- }
-
-#ifdef PNG_MAX_MALLOC_64K
- png_ptr->skip_length = 0; /* This may not be necessary */
-
- if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
- {
- png_warning(png_ptr, "iTXt chunk too large to fit in memory");
- png_ptr->skip_length = length - (png_uint_32)65535L;
- length = (png_uint_32)65535L;
- }
-#endif
-
- png_ptr->current_text = (png_charp)png_malloc(png_ptr,
- (png_size_t)(length + 1));
- png_ptr->current_text[length] = '\0';
- png_ptr->current_text_ptr = png_ptr->current_text;
- png_ptr->current_text_size = (png_size_t)length;
- png_ptr->current_text_left = (png_size_t)length;
- png_ptr->process_mode = PNG_READ_iTXt_MODE;
-}
-
-void /* PRIVATE */
-png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr)
-{
-
- if (png_ptr->buffer_size && png_ptr->current_text_left)
- {
- png_size_t text_size;
-
- if (png_ptr->buffer_size < png_ptr->current_text_left)
- text_size = png_ptr->buffer_size;
-
- else
- text_size = png_ptr->current_text_left;
-
- png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
- png_ptr->current_text_left -= text_size;
- png_ptr->current_text_ptr += text_size;
- }
-
- if (!(png_ptr->current_text_left))
- {
- png_textp text_ptr;
- png_charp key;
- int comp_flag;
- png_charp lang;
- png_charp lang_key;
- png_charp text;
- int ret;
-
- if (png_ptr->buffer_size < 4)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_push_crc_finish(png_ptr);
-
-#ifdef PNG_MAX_MALLOC_64K
- if (png_ptr->skip_length)
- return;
-#endif
-
- key = png_ptr->current_text;
-
- for (lang = key; *lang; lang++)
- /* Empty loop */ ;
-
- if (lang < key + png_ptr->current_text_size - 3)
- lang++;
-
- comp_flag = *lang++;
- lang++; /* Skip comp_type, always zero */
-
- for (lang_key = lang; *lang_key; lang_key++)
- /* Empty loop */ ;
-
- lang_key++; /* Skip NUL separator */
-
- text=lang_key;
-
- if (lang_key < key + png_ptr->current_text_size - 1)
- {
- for (; *text; text++)
- /* Empty loop */ ;
- }
-
- if (text < key + png_ptr->current_text_size)
- text++;
-
- text_ptr = (png_textp)png_malloc(png_ptr,
- png_sizeof(png_text));
-
- text_ptr->compression = comp_flag + 2;
- text_ptr->key = key;
- text_ptr->lang = lang;
- text_ptr->lang_key = lang_key;
- text_ptr->text = text;
- text_ptr->text_length = 0;
- text_ptr->itxt_length = png_strlen(text);
-
- ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
- png_ptr->current_text = NULL;
-
- png_free(png_ptr, text_ptr);
- if (ret)
- png_warning(png_ptr, "Insufficient memory to store iTXt chunk");
- }
-}
-#endif
-
-/* This function is called when we haven't found a handler for this
- * chunk. If there isn't a problem with the chunk itself (ie a bad chunk
- * name or a critical chunk), the chunk is (currently) silently ignored.
- */
-void /* PRIVATE */
-png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32
- length)
-{
- png_uint_32 skip = 0;
- png_uint_32 chunk_name = png_ptr->chunk_name;
-
- if (PNG_CHUNK_CRITICAL(chunk_name))
- {
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
- if (png_chunk_unknown_handling(png_ptr, chunk_name) !=
- PNG_HANDLE_CHUNK_ALWAYS
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
- && png_ptr->read_user_chunk_fn == NULL
-#endif
- )
-#endif
- png_chunk_error(png_ptr, "unknown critical chunk");
-
- PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */
- }
-
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
- /* TODO: the code below is apparently just using the
- * png_struct::unknown_chunk member as a temporarily variable, it should be
- * possible to eliminate both it and the temporary buffer.
- */
- if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
- {
-#ifdef PNG_MAX_MALLOC_64K
- if (length > 65535)
- {
- png_warning(png_ptr, "unknown chunk too large to fit in memory");
- skip = length - 65535;
- length = 65535;
- }
-#endif
- /* This is just a record for the user; libpng doesn't use the character
- * form of the name.
- */
- PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name);
-
- /* The following cast should be safe because of the check above. */
- png_ptr->unknown_chunk.size = (png_size_t)length;
-
- if (length == 0)
- png_ptr->unknown_chunk.data = NULL;
-
- else
- {
- png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr,
- png_ptr->unknown_chunk.size);
- png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data,
- png_ptr->unknown_chunk.size);
- }
-
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
- if (png_ptr->read_user_chunk_fn != NULL)
- {
- /* Callback to user unknown chunk handler */
- int ret;
- ret = (*(png_ptr->read_user_chunk_fn))
- (png_ptr, &png_ptr->unknown_chunk);
-
- if (ret < 0)
- png_chunk_error(png_ptr, "error in user chunk");
-
- if (ret == 0)
- {
- if (PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
- if (png_chunk_unknown_handling(png_ptr, chunk_name) !=
- PNG_HANDLE_CHUNK_ALWAYS)
- png_chunk_error(png_ptr, "unknown critical chunk");
- png_set_unknown_chunks(png_ptr, info_ptr,
- &png_ptr->unknown_chunk, 1);
- }
- }
-
- else
-#endif
- png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
- png_free(png_ptr, png_ptr->unknown_chunk.data);
- png_ptr->unknown_chunk.data = NULL;
- }
-
- else
-#endif
- skip=length;
- png_push_crc_skip(png_ptr, skip);
-}
-
void /* PRIVATE */
png_push_have_info(png_structp png_ptr, png_infop info_ptr)
{
@@ -1816,7 +1197,7 @@ png_progressive_combine_row (png_structp png_ptr, png_bytep old_row,
* it must be png_ptr->row_buf+1
*/
if (new_row != NULL)
- png_combine_row(png_ptr, old_row, 1/*display*/);
+ png_combine_row(png_ptr, old_row, 1/*blocky display*/);
}
#endif /* PNG_READ_INTERLACING_SUPPORTED */
diff --git a/drivers/png/pngpriv.h b/drivers/png/pngpriv.h
index 56532f4eeb..8bdccccafb 100644
--- a/drivers/png/pngpriv.h
+++ b/drivers/png/pngpriv.h
@@ -1,13 +1,11 @@
/* pngpriv.h - private declarations for use inside libpng
*
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.26 [December 17, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
@@ -39,6 +37,7 @@
*/
#define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */
+#ifndef PNG_VERSION_INFO_ONLY
/* This is required for the definition of abort(), used as a last ditch
* error handler when all else fails.
*/
@@ -46,6 +45,7 @@
/* This is used to find 'offsetof', used below for alignment tests. */
#include <stddef.h>
+#endif /* !PNG_VERSION_INFO_ONLY */
#define PNGLIB_BUILD /*libpng is being built, not used*/
@@ -125,21 +125,68 @@
#endif
#include "png.h"
-#include "pnginfo.h"
-#include "pngstruct.h"
/* pngconf.h does not set PNG_DLL_EXPORT unless it is required, so: */
#ifndef PNG_DLL_EXPORT
# define PNG_DLL_EXPORT
#endif
-/* This is used for 16 bit gamma tables - only the top level pointers are const,
- * this could be changed:
+/* Compile time options.
+ * =====================
+ * In a multi-arch build the compiler may compile the code several times for the
+ * same object module, producing different binaries for different architectures.
+ * When this happens configure-time setting of the target host options cannot be
+ * done and this interferes with the handling of the ARM NEON optimizations, and
+ * possibly other similar optimizations. Put additional tests here; in general
+ * this is needed when the same option can be changed at both compile time and
+ * run time depending on the target OS (i.e. iOS vs Android.)
+ *
+ * NOTE: symbol prefixing does not pass $(CFLAGS) to the preprocessor, because
+ * this is not possible with certain compilers (Oracle SUN OS CC), as a result
+ * it is necessary to ensure that all extern functions that *might* be used
+ * regardless of $(CFLAGS) get declared in this file. The test on __ARM_NEON__
+ * below is one example of this behavior because it is controlled by the
+ * presence or not of -mfpu=neon on the GCC command line, it is possible to do
+ * this in $(CC), e.g. "CC=gcc -mfpu=neon", but people who build libpng rarely
+ * do this.
*/
-typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
+#ifndef PNG_ARM_NEON_OPT
+ /* ARM NEON optimizations are being controlled by the compiler settings,
+ * typically the target FPU. If the FPU has been set to NEON (-mfpu=neon
+ * with GCC) then the compiler will define __ARM_NEON__ and we can rely
+ * unconditionally on NEON instructions not crashing, otherwise we must
+ * disable use of NEON instructions.
+ *
+ * NOTE: at present these optimizations depend on 'ALIGNED_MEMORY', so they
+ * can only be turned on automatically if that is supported too. If
+ * PNG_ARM_NEON_OPT is set in CPPFLAGS (to >0) then arm/arm_init.c will fail
+ * to compile with an appropriate #error if ALIGNED_MEMORY has been turned
+ * off.
+ */
+# if defined(__ARM_NEON__) && defined(PNG_ALIGNED_MEMORY_SUPPORTED)
+# define PNG_ARM_NEON_OPT 2
+# else
+# define PNG_ARM_NEON_OPT 0
+# endif
+#endif
-/* Added at libpng-1.2.9 */
-/* Moved to pngpriv.h at libpng-1.5.0 */
+
+#if PNG_ARM_NEON_OPT > 0
+ /* NEON optimizations are to be at least considered by libpng, so enable the
+ * callbacks to do this.
+ */
+# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon
+#endif
+
+/* SECURITY and SAFETY:
+ *
+ * By default libpng is built without any internal limits on image size,
+ * individual heap (png_malloc) allocations or the total amount of memory used.
+ * If PNG_SAFE_LIMITS_SUPPORTED is defined, however, the limits below are used
+ * (unless individually overridden). These limits are believed to be fairly
+ * safe, but builders of secure systems should verify the values against the
+ * real system capabilities.
+ */
/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure"
* script. We may need it here to get the correct configuration on things
@@ -151,9 +198,11 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
# endif
#endif
-/* Moved to pngpriv.h at libpng-1.5.0 */
-/* NOTE: some of these may have been used in external applications as
- * these definitions were exposed in pngconf.h prior to 1.5.
+/* SECURITY and SAFETY:
+ *
+ * libpng is built with support for internal limits on image dimensions and
+ * memory usage. These are documented in scripts/pnglibconf.dfa of the
+ * source and recorded in the machine generated header file pnglibconf.h.
*/
/* If you are running on a machine where you cannot allocate more
@@ -171,6 +220,11 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
# define PNG_MAX_MALLOC_64K
#endif
+/* Moved to pngpriv.h at libpng-1.5.0 */
+/* NOTE: some of these may have been used in external applications as
+ * these definitions were exposed in pngconf.h prior to 1.5.
+ */
+
#ifndef PNG_UNUSED
/* Unused formal parameter warnings are silenced using the following macro
* which is expected to have no bad effects on performance (optimizing
@@ -206,7 +260,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
/* Modern compilers support restrict, but assume not for anything not
* recognized here:
*/
-# if defined __GNUC__ || defined _MSC_VER || defined __WATCOMC__
+# if defined(__GNUC__) || defined(_MSC_VER) || defined(__WATCOMC__)
# define PNG_RESTRICT restrict
# else
# define PNG_RESTRICT
@@ -220,8 +274,6 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#ifdef PNG_WARNINGS_SUPPORTED
# define PNG_WARNING_PARAMETERS(p) png_warning_parameters p;
#else
-# define png_warning(s1,s2) ((void)(s1))
-# define png_chunk_warning(s1,s2) ((void)(s1))
# define png_warning_parameter(p,number,string) ((void)0)
# define png_warning_parameter_unsigned(p,number,format,value) ((void)0)
# define png_warning_parameter_signed(p,number,format,value) ((void)0)
@@ -229,8 +281,6 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
# define PNG_WARNING_PARAMETERS(p)
#endif
#ifndef PNG_ERROR_TEXT_SUPPORTED
-# define png_error(s1,s2) png_err(s1)
-# define png_chunk_error(s1,s2) png_err(s1)
# define png_fixed_error(s1,s2) png_err(s1)
#endif
@@ -268,6 +318,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
# define PNGFAPI /* PRIVATE */
#endif
+#ifndef PNG_VERSION_INFO_ONLY
/* Other defines specific to compilers can go here. Try to keep
* them inside an appropriate ifdef/endif pair for portability.
*/
@@ -312,6 +363,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
defined(_WIN32) || defined(__WIN32__)
# include <windows.h> /* defines _WINDOWS_ macro */
#endif
+#endif /* !PNG_VERSION_INFO_ONLY */
/* Moved here around 1.5.0beta36 from pngconf.h */
/* Users may want to use these so they are not private. Any library
@@ -341,13 +393,9 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
# ifdef _WINDOWS_ /* Favor Windows over C runtime fns */
# define CVT_PTR(ptr) (ptr)
# define CVT_PTR_NOCHECK(ptr) (ptr)
-# ifdef WINRT_ENABLED
-# define png_strlen strlen
-# else
-# define png_strlen lstrlenA
-# endif
+# define png_strlen lstrlenA
# define png_memcmp memcmp
-# define png_memcpy CopyMemory
+# define png_memcpy memcpy
# define png_memset memset
# else
# define CVT_PTR(ptr) (ptr)
@@ -380,7 +428,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#if PNG_ALIGN_TYPE == PNG_ALIGN_SIZE
/* This is used because in some compiler implementations non-aligned
* structure members are supported, so the offsetof approach below fails.
- * Set PNG_ALIGN_TO_SIZE=0 for compiler combinations where unaligned access
+ * Set PNG_ALIGN_SIZE=0 for compiler combinations where unaligned access
* is good for performance. Do not do this unless you have tested the result
* and understand it.
*/
@@ -430,6 +478,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#define PNG_BACKGROUND_IS_GRAY 0x800
#define PNG_HAVE_PNG_SIGNATURE 0x1000
#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */
+#define PNG_HAVE_iCCP 0x4000
/* Flags for the transformations the PNG library does on the image data */
#define PNG_BGR 0x0001
@@ -468,10 +517,6 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#define PNG_STRUCT_PNG 0x0001
#define PNG_STRUCT_INFO 0x0002
-/* Scaling factor for filter heuristic weighting calculations */
-#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT))
-#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT))
-
/* Flags for the png_ptr->flags rather than declaring a byte for each one */
#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001
#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002
@@ -494,7 +539,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000
#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000
#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000
- /* 0x200000 unused */
+#define PNG_FLAG_ZSTREAM_PROGRESSIVE 0x200000
/* 0x400000 unused */
#define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000 /* Added to libpng-1.4.0 */
#define PNG_FLAG_ZTXT_CUSTOM_STRATEGY 0x1000000 /* 5 lines added */
@@ -580,8 +625,10 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\
((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0))
#else
+#ifndef PNG_VERSION_INFO_ONLY
PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp,
png_const_charp text));
+#endif /* !PNG_VERSION_INFO_ONLY */
#endif
#endif
@@ -655,6 +702,18 @@ PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp,
#define PNG_GAMMA_MAC_INVERSE 65909
#define PNG_GAMMA_sRGB_INVERSE 45455
+/* Almost everything below is C specific; the #defines above can be used in
+ * non-C code (so long as it is C-preprocessed) the rest of this stuff cannot.
+ */
+#ifndef PNG_VERSION_INFO_ONLY
+
+#include "pngstruct.h"
+#include "pnginfo.h"
+
+/* This is used for 16 bit gamma tables -- only the top level pointers are
+ * const; this could be changed:
+ */
+typedef const png_uint_16p * png_const_uint_16pp;
/* Inhibit C++ name-mangling for libpng functions but not for system calls. */
#ifdef __cplusplus
@@ -786,10 +845,8 @@ PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr));
# ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma));
# endif
-# ifdef PNG_FIXED_POINT_SUPPORTED
PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr,
png_fixed_point file_gamma));
-# endif
#endif
#ifdef PNG_WRITE_sBIT_SUPPORTED
@@ -844,13 +901,6 @@ PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr,
png_const_uint_16p hist, int num_hist));
#endif
-/* Chunks that have keywords */
-#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
- defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
-PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr,
- png_const_charp key, png_charpp new_key));
-#endif
-
#ifdef PNG_WRITE_tEXt_SUPPORTED
PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_const_charp key,
png_const_charp text, png_size_t text_len));
@@ -956,8 +1006,8 @@ PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info,
/* Unfilter a row: check the filter value before calling this, there is no point
* calling it for PNG_FILTER_VALUE_NONE.
*/
-PNG_EXTERN void png_read_filter_row PNGARG((png_structp pp, png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row, int filter));
+PNG_EXTERN void png_read_filter_row PNGARG((png_structp pp, png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row, int filter));
PNG_EXTERN void png_read_filter_row_up_neon PNGARG((png_row_infop row_info,
png_bytep row, png_const_bytep prev_row));
@@ -1222,10 +1272,8 @@ PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr,
png_infop info_ptr, png_uint_32 length));
-#endif
PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr,
png_uint_32 chunk_name));
@@ -1258,9 +1306,6 @@ PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr,
PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr,
png_infop info_ptr));
PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr));
-PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr,
- png_uint_32 length));
-PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr));
PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr));
PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr,
png_bytep buffer, png_size_t buffer_length));
@@ -1359,6 +1404,13 @@ PNG_EXTERN void png_check_IHDR PNGARG((png_structp png_ptr,
int color_type, int interlace_type, int compression_type,
int filter_type));
+/* Added at libpng version 1.5.10 */
+#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
+ defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
+PNG_EXTERN void png_do_check_palette_indexes PNGARG((png_structp png_ptr,
+ png_row_infop row_info));
+#endif
+
/* Free all memory used by the read (old method - NOT DLL EXPORTED) */
PNG_EXTERN void png_read_destroy PNGARG((png_structp png_ptr,
png_infop info_ptr, png_infop end_info_ptr));
@@ -1449,14 +1501,16 @@ PNG_EXTERN void png_formatted_warning(png_structp png_ptr,
/* ASCII to FP interfaces, currently only implemented if sCAL
* support is required.
*/
-#if defined(PNG_READ_sCAL_SUPPORTED)
+#ifdef PNG_sCAL_SUPPORTED
/* MAX_DIGITS is actually the maximum number of characters in an sCAL
* width or height, derived from the precision (number of significant
* digits - a build time settable option) and assumpitions about the
* maximum ridiculous exponent.
*/
#define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/)
+#endif
+#ifdef PNG_sCAL_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXTERN void png_ascii_from_fp PNGARG((png_structp png_ptr, png_charp ascii,
png_size_t size, double fp, unsigned int precision));
@@ -1540,15 +1594,15 @@ PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr,
#define PNG_FP_IS_ZERO(state) (((state) & PNG_FP_Z_MASK) == PNG_FP_SAW_DIGIT)
#define PNG_FP_IS_POSITIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_Z_MASK)
#define PNG_FP_IS_NEGATIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_NZ_MASK)
-
-/* The actual parser. This can be called repeatedly, it updates
+
+/* The actual parser. This can be called repeatedly. It updates
* the index into the string and the state variable (which must
- * be initialzed to 0). It returns a result code, as above. There
+ * be initialized to 0). It returns a result code, as above. There
* is no point calling the parser any more if it fails to advance to
* the end of the string - it is stuck on an invalid character (or
* terminated by '\0').
*
- * Note that the pointer will consume an E or even an E+ then leave
+ * Note that the pointer will consume an E or even an E+ and then leave
* a 'maybe' state even though a preceding integer.fraction is valid.
* The PNG_FP_WAS_VALID flag indicates that a preceding substring was
* a valid number. It's possible to recover from this by calling
@@ -1587,7 +1641,7 @@ PNG_EXTERN png_fixed_point png_muldiv_warn PNGARG((png_structp png_ptr,
png_fixed_point a, png_int_32 multiplied_by, png_int_32 divided_by));
#endif
-#ifdef PNG_READ_GAMMA_SUPPORTED
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED)
/* Calculate a reciprocal - used for gamma values. This returns
* 0 if the argument is 0 in order to maintain an undefined value,
* there are no warnings.
@@ -1622,7 +1676,80 @@ PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr,
int bit_depth));
#endif
-/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
+/* Missing declarations if FIXED_POINT is *not* supported - fixed properly
+ * in libpng 1.6
+ */
+#ifndef PNG_FIXED_POINT_SUPPORTED
+#ifdef PNG_cHRM_SUPPORTED
+PNG_EXTERN png_uint_32 png_get_cHRM_XYZ_fixed PNGARG(
+ (png_structp png_ptr, png_const_infop info_ptr,
+ png_fixed_point *int_red_X, png_fixed_point *int_red_Y,
+ png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
+ png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
+ png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
+ png_fixed_point *int_blue_Z));
+PNG_EXTERN void png_set_cHRM_XYZ_fixed PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y,
+ png_fixed_point int_red_Z, png_fixed_point int_green_X,
+ png_fixed_point int_green_Y, png_fixed_point int_green_Z,
+ png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
+ png_fixed_point int_blue_Z));
+PNG_EXTERN void png_set_cHRM_fixed PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_fixed_point int_white_x,
+ png_fixed_point int_white_y, png_fixed_point int_red_x,
+ png_fixed_point int_red_y, png_fixed_point int_green_x,
+ png_fixed_point int_green_y, png_fixed_point int_blue_x,
+ png_fixed_point int_blue_y));
+#endif
+
+#ifdef PNG_gAMA_SUPPORTED
+PNG_EXTERN png_uint_32 png_get_gAMA_fixed PNGARG(
+ (png_const_structp png_ptr, png_const_infop info_ptr,
+ png_fixed_point *int_file_gamma));
+PNG_EXTERN void png_set_gAMA_fixed PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_fixed_point int_file_gamma));
+#endif
+
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+PNG_EXTERN void png_set_background_fixed PNGARG((png_structp png_ptr,
+ png_const_color_16p background_color, int background_gamma_code,
+ int need_expand, png_fixed_point background_gamma));
+#endif
+
+#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
+PNG_EXTERN void png_set_alpha_mode_fixed PNGARG((png_structp png_ptr,
+ int mode, png_fixed_point output_gamma));
+#endif
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+PNG_EXTERN void png_set_gamma_fixed PNGARG((png_structp png_ptr,
+ png_fixed_point screen_gamma, png_fixed_point override_file_gamma));
+#endif
+
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+PNG_EXTERN void png_set_rgb_to_gray_fixed PNGARG((png_structp png_ptr,
+ int error_action, png_fixed_point red, png_fixed_point green));
+#endif
+#endif /* FIX MISSING !FIXED_POINT DECLARATIONS */
+
+/* These are initialization functions for hardware specific PNG filter
+ * optimizations; list these here then select the appropriate one at compile
+ * time using the macro PNG_FILTER_OPTIMIZATIONS. If the macro is not defined
+ * the generic code is used.
+ */
+#ifdef PNG_FILTER_OPTIMIZATIONS
+PNG_EXTERN void PNG_FILTER_OPTIMIZATIONS(png_structp png_ptr, unsigned int bpp);
+ /* Just declare the optimization that will be used */
+#else
+ /* List *all* the possible optimizations here - this branch is required if
+ * the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in
+ * CFLAGS in place of CPPFLAGS *and* uses symbol prefixing.
+ */
+PNG_EXTERN void png_init_filter_functions_neon(png_structp png_ptr,
+ unsigned int bpp);
+#endif
+
+/* Maintainer: Put new private prototypes here ^ */
#include "pngdebug.h"
@@ -1630,4 +1757,5 @@ PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr,
}
#endif
+#endif /* PNG_VERSION_INFO_ONLY */
#endif /* PNGPRIV_H */
diff --git a/drivers/png/pngread.c b/drivers/png/pngread.c
index 0643754dad..b90e017e62 100644
--- a/drivers/png/pngread.c
+++ b/drivers/png/pngread.c
@@ -1,8 +1,8 @@
/* pngread.c - read a PNG file
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.23 [July 23, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -67,15 +67,11 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
-# ifdef PNG_USER_CHUNK_CACHE_MAX
/* Added at libpng-1.2.43 and 1.4.0 */
png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
-# endif
-# ifdef PNG_SET_USER_CHUNK_MALLOC_MAX
/* Added at libpng-1.2.43 and 1.4.1 */
png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
-# endif
#endif
#ifdef PNG_SETJMP_SUPPORTED
@@ -104,7 +100,7 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
if (!png_user_version_check(png_ptr, user_png_ver))
png_cleanup_needed = 1;
- if (!png_cleanup_needed)
+ if (png_cleanup_needed == 0)
{
/* Initialize zbuf - compression buffer */
png_ptr->zbuf_size = PNG_ZBUF_SIZE;
@@ -118,7 +114,7 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
png_ptr->zstream.zfree = png_zfree;
png_ptr->zstream.opaque = (voidpf)png_ptr;
- if (!png_cleanup_needed)
+ if (png_cleanup_needed == 0)
{
switch (inflateInit(&png_ptr->zstream))
{
@@ -145,7 +141,7 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
}
}
- if (png_cleanup_needed)
+ if (png_cleanup_needed != 0)
{
/* Clean up PNG structure and deallocate any memory. */
png_free(png_ptr, png_ptr->zbuf);
@@ -563,7 +559,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
if (ret == Z_STREAM_END)
{
if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||
- png_ptr->idat_size)
+ png_ptr->idat_size)
png_benign_error(png_ptr, "Extra compressed data");
png_ptr->mode |= PNG_AFTER_IDAT;
png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
@@ -621,7 +617,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Blow up interlaced rows to full size */
if (png_ptr->interlaced &&
- (png_ptr->transformations & PNG_INTERLACE))
+ (png_ptr->transformations & PNG_INTERLACE))
{
if (png_ptr->pass < 6)
png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
@@ -805,6 +801,13 @@ png_read_end(png_structp png_ptr, png_infop info_ptr)
png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
+#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Report invalid palette index; added at libng-1.5.10 */
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+ png_ptr->num_palette_max > png_ptr->num_palette)
+ png_benign_error(png_ptr, "Read palette index exceeding num_palette");
+#endif
+
do
{
png_uint_32 length = png_read_chunk_header(png_ptr);
@@ -1070,12 +1073,6 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr,
png_free(png_ptr, png_ptr->save_buffer);
#endif
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-#ifdef PNG_TEXT_SUPPORTED
- png_free(png_ptr, png_ptr->current_text);
-#endif /* PNG_TEXT_SUPPORTED */
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
-
/* Save the important info out of the png_struct, in case it is
* being used again.
*/
@@ -1122,9 +1119,8 @@ png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
#ifdef PNG_INFO_IMAGE_SUPPORTED
void PNGAPI
-png_read_png(png_structp png_ptr, png_infop info_ptr,
- int transforms,
- voidp params)
+png_read_png(png_structp png_ptr, png_infop info_ptr, int transforms,
+ voidp params)
{
int row;
@@ -1194,7 +1190,7 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
if (transforms & PNG_TRANSFORM_EXPAND)
if ((png_ptr->bit_depth < 8) ||
(png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
- (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
+ (info_ptr->valid & PNG_INFO_tRNS))
png_set_expand(png_ptr);
#endif
@@ -1213,14 +1209,8 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
* [0,65535] to the original [0,7] or [0,31], or whatever range the
* colors were originally in:
*/
- if ((transforms & PNG_TRANSFORM_SHIFT)
- && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
- {
- png_color_8p sig_bit;
-
- png_get_sBIT(png_ptr, info_ptr, &sig_bit);
- png_set_shift(png_ptr, sig_bit);
- }
+ if ((transforms & PNG_TRANSFORM_SHIFT) && (info_ptr->valid & PNG_INFO_sBIT))
+ png_set_shift(png_ptr, &info_ptr->sig_bit);
#endif
#ifdef PNG_READ_BGR_SUPPORTED
@@ -1290,7 +1280,7 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
for (row = 0; row < (int)info_ptr->height; row++)
info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr,
- png_get_rowbytes(png_ptr, info_ptr));
+ png_get_rowbytes(png_ptr, info_ptr));
}
png_read_image(png_ptr, info_ptr->row_pointers);
diff --git a/drivers/png/pngrio.c b/drivers/png/pngrio.c
index e9c381c5ba..b4042e9ed3 100644
--- a/drivers/png/pngrio.c
+++ b/drivers/png/pngrio.c
@@ -2,7 +2,7 @@
/* pngrio.c - functions for data input
*
* Last changed in libpng 1.5.0 [January 6, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2011 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -26,7 +26,7 @@
* reads from a file pointer. Note that this routine sometimes gets called
* with very small lengths, so you should implement some kind of simple
* buffering if you are using unbuffered reads. This should never be asked
- * to read more then 64K on a 16 bit machine.
+ * to read more than 64K on a 16 bit machine.
*/
void /* PRIVATE */
png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
diff --git a/drivers/png/pngrtran.c b/drivers/png/pngrtran.c
index 1079595f0a..f273362616 100644
--- a/drivers/png/pngrtran.c
+++ b/drivers/png/pngrtran.c
@@ -1,8 +1,8 @@
/* pngrtran.c - transforms the data in a row for PNG readers
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.24 [November 12, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -114,7 +114,7 @@ png_set_background_fixed(png_structp png_ptr,
png_sizeof(png_color_16));
png_ptr->background_gamma = background_gamma;
png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
- if (need_expand)
+ if (need_expand != 0)
png_ptr->transformations |= PNG_BACKGROUND_EXPAND;
else
png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
@@ -194,8 +194,10 @@ translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
*/
# ifdef PNG_READ_sRGB_SUPPORTED
png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
+# else
+ PNG_UNUSED(png_ptr)
# endif
- if (is_screen)
+ if (is_screen != 0)
output_gamma = PNG_GAMMA_sRGB;
else
output_gamma = PNG_GAMMA_sRGB_INVERSE;
@@ -204,7 +206,7 @@ translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
else if (output_gamma == PNG_GAMMA_MAC_18 ||
output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)
{
- if (is_screen)
+ if (is_screen != 0)
output_gamma = PNG_GAMMA_MAC_OLD;
else
output_gamma = PNG_GAMMA_MAC_INVERSE;
@@ -329,7 +331,7 @@ png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
/* Finally, if pre-multiplying, set the background fields to achieve the
* desired result.
*/
- if (compose)
+ if (compose != 0)
{
/* And obtain alpha pre-multiplication by composing on black: */
png_memset(&png_ptr->background, 0, sizeof png_ptr->background);
@@ -389,7 +391,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
png_ptr->transformations |= PNG_QUANTIZE;
- if (!full_quantize)
+ if (full_quantize == 0)
{
int i;
@@ -444,12 +446,12 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
}
}
- if (done)
+ if (done != 0)
break;
}
/* Swap the palette around, and set up a table, if necessary */
- if (full_quantize)
+ if (full_quantize != 0)
{
int j = num_palette;
@@ -632,7 +634,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
num_new_palette--;
palette[png_ptr->index_to_palette[j]]
= palette[num_new_palette];
- if (!full_quantize)
+ if (full_quantize == 0)
{
int k;
@@ -700,7 +702,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
}
png_ptr->num_palette = (png_uint_16)num_palette;
- if (full_quantize)
+ if (full_quantize != 0)
{
int i;
png_bytep distance;
@@ -969,7 +971,7 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
png_uint_16 red_int, green_int;
/* NOTE: this calculation does not round, but this behavior is retained
- * for consistency, the inaccuracy is very small. The code here always
+ * for consistency; the inaccuracy is very small. The code here always
* overwrites the coefficients, regardless of whether they have been
* defaulted or set already.
*/
@@ -1068,7 +1070,7 @@ png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)
* the palette.
*/
-/*For the moment 'png_init_palette_transformations' and
+/* For the moment 'png_init_palette_transformations' and
* 'png_init_rgb_transformations' only do some flag canceling optimizations.
* The intent is that these two routines should have palette or rgb operations
* extracted from 'png_init_read_transformations'.
@@ -1093,25 +1095,31 @@ png_init_palette_transformations(png_structp png_ptr)
/* Ignore if all the entries are opaque (unlikely!) */
for (i=0; i<png_ptr->num_trans; ++i)
+ {
if (png_ptr->trans_alpha[i] == 255)
continue;
else if (png_ptr->trans_alpha[i] == 0)
input_has_transparency = 1;
else
+ {
+ input_has_transparency = 1;
input_has_alpha = 1;
+ break;
+ }
+ }
}
/* If no alpha we can optimize. */
- if (!input_has_alpha)
+ if (input_has_alpha == 0)
{
/* Any alpha means background and associative alpha processing is
- * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA
+ * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
* and ENCODE_ALPHA are irrelevant.
*/
png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
- if (!input_has_transparency)
+ if (input_has_transparency == 0)
png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
}
@@ -1167,10 +1175,10 @@ png_init_rgb_transformations(png_structp png_ptr)
int input_has_transparency = png_ptr->num_trans > 0;
/* If no alpha we can optimize. */
- if (!input_has_alpha)
+ if (input_has_alpha == 0)
{
/* Any alpha means background and associative alpha processing is
- * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA
+ * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
* and ENCODE_ALPHA are irrelevant.
*/
# ifdef PNG_READ_ALPHA_MODE_SUPPORTED
@@ -1178,7 +1186,7 @@ png_init_rgb_transformations(png_structp png_ptr)
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
# endif
- if (!input_has_transparency)
+ if (input_has_transparency == 0)
png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
}
@@ -1221,7 +1229,7 @@ png_init_rgb_transformations(png_structp png_ptr)
default:
case 8:
- /* Already 8 bits, fall through */
+ /* FALL THROUGH (already 8 bits) */
case 16:
/* Already a full 16 bits */
@@ -1304,7 +1312,7 @@ png_init_read_transformations(png_structp png_ptr)
* the code immediately below if the transform can be handled outside the
* row loop.
*/
- if (gamma_correction)
+ if (gamma_correction != 0)
png_ptr->transformations |= PNG_GAMMA;
else
@@ -1313,7 +1321,7 @@ png_init_read_transformations(png_structp png_ptr)
#endif
/* Certain transformations have the effect of preventing other
- * transformations that happen afterward in png_do_read_transformations,
+ * transformations that happen afterward in png_do_read_transformations;
* resolve the interdependencies here. From the code of
* png_do_read_transformations the order is:
*
@@ -1702,11 +1710,11 @@ png_init_read_transformations(png_structp png_ptr)
g_sig = png_gamma_significant(g);
gs_sig = png_gamma_significant(gs);
- if (g_sig)
+ if (g_sig != 0)
png_ptr->background_1.gray = png_gamma_correct(png_ptr,
png_ptr->background.gray, g);
- if (gs_sig)
+ if (gs_sig != 0)
png_ptr->background.gray = png_gamma_correct(png_ptr,
png_ptr->background.gray, gs);
@@ -1715,7 +1723,7 @@ png_init_read_transformations(png_structp png_ptr)
(png_ptr->background.red != png_ptr->background.gray))
{
/* RGB or RGBA with color background */
- if (g_sig)
+ if (g_sig != 0)
{
png_ptr->background_1.red = png_gamma_correct(png_ptr,
png_ptr->background.red, g);
@@ -1727,7 +1735,7 @@ png_init_read_transformations(png_structp png_ptr)
png_ptr->background.blue, g);
}
- if (gs_sig)
+ if (gs_sig != 0)
{
png_ptr->background.red = png_gamma_correct(png_ptr,
png_ptr->background.red, gs);
@@ -1770,8 +1778,8 @@ png_init_read_transformations(png_structp png_ptr)
int num_palette = png_ptr->num_palette;
int i;
- /*NOTE: there are other transformations that should probably be in here
- * too.
+ /* NOTE: there are other transformations that should probably be in
+ * here too.
*/
for (i = 0; i < num_palette; i++)
{
@@ -1830,12 +1838,15 @@ png_init_read_transformations(png_structp png_ptr)
#ifdef PNG_READ_SHIFT_SUPPORTED
if ((png_ptr->transformations & PNG_SHIFT) &&
+ !(png_ptr->transformations & PNG_EXPAND) &&
(png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
{
int i;
int istop = png_ptr->num_palette;
int shift = 8 - png_ptr->sig_bit.red;
+ png_ptr->transformations &= ~PNG_SHIFT;
+
/* significant bits can be in the range 1 to 7 for a meaninful result, if
* the number of significant bits is 0 then no shift is done (this is an
* error condition which is silently ignored.)
@@ -1895,6 +1906,9 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
info_ptr->bit_depth = 8;
info_ptr->num_trans = 0;
+
+ if (png_ptr->palette == NULL)
+ png_error (png_ptr, "Palette is NULL in indexed image");
}
else
{
@@ -2042,10 +2056,10 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
if (png_ptr->transformations & PNG_USER_TRANSFORM)
{
- if (info_ptr->bit_depth < png_ptr->user_transform_depth)
+ if (png_ptr->user_transform_depth)
info_ptr->bit_depth = png_ptr->user_transform_depth;
- if (info_ptr->channels < png_ptr->user_transform_channels)
+ if (png_ptr->user_transform_channels)
info_ptr->channels = png_ptr->user_transform_channels;
}
#endif
@@ -2064,7 +2078,7 @@ defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
png_ptr->info_rowbytes = info_ptr->rowbytes;
#ifndef PNG_READ_EXPAND_SUPPORTED
- if (png_ptr)
+ if (png_ptr != NULL)
return;
#endif
}
@@ -2141,7 +2155,7 @@ png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
png_do_rgb_to_gray(png_ptr, row_info,
png_ptr->row_buf + 1);
- if (rgb_error)
+ if (rgb_error != 0)
{
png_ptr->rgb_to_gray_status=1;
if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
@@ -2195,8 +2209,8 @@ png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
#endif
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
- (defined PNG_READ_ALPHA_MODE_SUPPORTED)
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+ defined(PNG_READ_ALPHA_MODE_SUPPORTED)
if (png_ptr->transformations & PNG_COMPOSE)
png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
@@ -2207,8 +2221,8 @@ png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
/* Because RGB_TO_GRAY does the gamma transform. */
!(png_ptr->transformations & PNG_RGB_TO_GRAY) &&
#endif
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
- (defined PNG_READ_ALPHA_MODE_SUPPORTED)
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+ defined(PNG_READ_ALPHA_MODE_SUPPORTED)
/* Because PNG_COMPOSE does the gamma transform if there is something to
* do (if there is an alpha channel or transparency.)
*/
@@ -2274,7 +2288,7 @@ png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
#endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
- /*NOTE: moved here in 1.5.4 (from much later in this list.) */
+ /* NOTE: moved here in 1.5.4 (from much later in this list.) */
if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
@@ -2296,6 +2310,13 @@ png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
png_do_unpack(row_info, png_ptr->row_buf + 1);
#endif
+#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Added at libpng-1.5.10 */
+ if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
+ png_ptr->num_palette_max >= 0)
+ png_do_check_palette_indexes(png_ptr, row_info);
+#endif
+
#ifdef PNG_READ_BGR_SUPPORTED
if (png_ptr->transformations & PNG_BGR)
png_do_bgr(row_info, png_ptr->row_buf + 1);
@@ -2512,7 +2533,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row,
have_shift = 1;
}
- if (!have_shift)
+ if (have_shift == 0)
return;
}
@@ -2948,13 +2969,13 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
png_bytep dp = sp + (png_size_t)row_width * 2;
for (i = 1; i < row_width; i++)
{
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
*(--dp) = *(--sp);
*(--dp) = *(--sp);
}
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
row_info->channels = 2;
row_info->pixel_depth = 32;
row_info->rowbytes = row_width * 4;
@@ -2969,8 +2990,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
{
*(--dp) = *(--sp);
*(--dp) = *(--sp);
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
}
row_info->channels = 2;
row_info->pixel_depth = 32;
@@ -3029,8 +3050,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
png_bytep dp = sp + (png_size_t)row_width * 2;
for (i = 1; i < row_width; i++)
{
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
*(--dp) = *(--sp);
*(--dp) = *(--sp);
*(--dp) = *(--sp);
@@ -3038,8 +3059,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
*(--dp) = *(--sp);
*(--dp) = *(--sp);
}
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
row_info->channels = 4;
row_info->pixel_depth = 64;
row_info->rowbytes = row_width * 8;
@@ -3058,8 +3079,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
*(--dp) = *(--sp);
*(--dp) = *(--sp);
*(--dp) = *(--sp);
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
}
row_info->channels = 4;
@@ -3273,7 +3294,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
*(dp++) = red;
}
- if (have_alpha)
+ if (have_alpha != 0)
*(dp++) = *(sp++);
}
}
@@ -3293,7 +3314,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
if (red != green || red != blue)
{
rgb_error |= 1;
- /*NOTE: this is the historical approach which simply
+ /* NOTE: this is the historical approach which simply
* truncates the results.
*/
*(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
@@ -3302,7 +3323,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
else
*(dp++) = red;
- if (have_alpha)
+ if (have_alpha != 0)
*(dp++) = *(sp++);
}
}
@@ -3320,11 +3341,17 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
for (i = 0; i < row_width; i++)
{
png_uint_16 red, green, blue, w;
-
+#if 0 /* Coverity doesn't like this */
red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
+#else
+ png_byte hi,lo;
+ hi=*(sp)++; lo=*(sp)++; red = (png_uint_16)((hi << 8) | (lo));
+ hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
+ hi=*(sp)++; lo=*(sp)++; blue = (png_uint_16)((hi << 8) | (lo));
+#endif
if (red == green && red == blue)
{
if (png_ptr->gamma_16_table != NULL)
@@ -3354,7 +3381,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
*(dp++) = (png_byte)((w>>8) & 0xff);
*(dp++) = (png_byte)(w & 0xff);
- if (have_alpha)
+ if (have_alpha != 0)
{
*(dp++) = *(sp++);
*(dp++) = *(sp++);
@@ -3388,7 +3415,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
*(dp++) = (png_byte)((gray16>>8) & 0xff);
*(dp++) = (png_byte)(gray16 & 0xff);
- if (have_alpha)
+ if (have_alpha != 0)
{
*(dp++) = *(sp++);
*(dp++) = *(sp++);
@@ -3467,8 +3494,8 @@ png_build_grayscale_palette(int bit_depth, png_colorp palette)
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
- (defined PNG_READ_ALPHA_MODE_SUPPORTED)
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+ defined(PNG_READ_ALPHA_MODE_SUPPORTED)
/* Replace any alpha or transparency with the supplied background color.
* "background" is already in the screen gamma, while "background_1" is
* at a gamma of 1.0. Paletted files have already been taken care of.
@@ -3514,7 +3541,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
*sp |= (png_byte)(png_ptr->background.gray << shift);
}
- if (!shift)
+ if (shift == 0)
{
shift = 7;
sp++;
@@ -3551,7 +3578,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
*sp |= (png_byte)(g << shift);
}
- if (!shift)
+ if (shift == 0)
{
shift = 6;
sp++;
@@ -3576,7 +3603,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
*sp |= (png_byte)(png_ptr->background.gray << shift);
}
- if (!shift)
+ if (shift == 0)
{
shift = 6;
sp++;
@@ -3614,7 +3641,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
*sp |= (png_byte)(g << shift);
}
- if (!shift)
+ if (shift == 0)
{
shift = 4;
sp++;
@@ -3639,7 +3666,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
*sp |= (png_byte)(png_ptr->background.gray << shift);
}
- if (!shift)
+ if (shift == 0)
{
shift = 4;
sp++;
@@ -3695,8 +3722,10 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if (v == png_ptr->trans_color.gray)
{
/* Background is already in screen gamma */
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
- *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
+ *(sp + 1) = (png_byte)(png_ptr->background.gray
+ & 0xff);
}
else
@@ -3719,8 +3748,10 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if (v == png_ptr->trans_color.gray)
{
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
- *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
+ *(sp + 1) = (png_byte)(png_ptr->background.gray
+ & 0xff);
}
}
}
@@ -3800,9 +3831,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
/* Background is already in screen gamma */
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
@@ -3843,9 +3877,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
{
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
}
@@ -3882,7 +3919,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
v = gamma_to_1[*sp];
png_composite(w, v, a, png_ptr->background_1.gray);
- if (!optimize)
+ if (optimize == 0)
w = gamma_from_1[w];
*sp = w;
}
@@ -3900,7 +3937,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
*sp = (png_byte)png_ptr->background.gray;
else if (a < 0xff)
- png_composite(*sp, *sp, a, png_ptr->background_1.gray);
+ png_composite(*sp, *sp, a, png_ptr->background.gray);
}
}
}
@@ -3928,7 +3965,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
else if (a == 0)
{
/* Background is already in screen gamma */
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
}
@@ -3938,7 +3976,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
png_composite_16(v, g, a, png_ptr->background_1.gray);
- if (optimize)
+ if (optimize != 0)
w = v;
else
w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
@@ -3958,7 +3996,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if (a == 0)
{
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
}
@@ -3967,7 +4006,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
png_uint_16 g, v;
g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
- png_composite_16(v, g, a, png_ptr->background_1.gray);
+ png_composite_16(v, g, a, png_ptr->background.gray);
*sp = (png_byte)((v >> 8) & 0xff);
*(sp + 1) = (png_byte)(v & 0xff);
}
@@ -4011,17 +4050,17 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
v = gamma_to_1[*sp];
png_composite(w, v, a, png_ptr->background_1.red);
- if (!optimize) w = gamma_from_1[w];
+ if (optimize == 0) w = gamma_from_1[w];
*sp = w;
v = gamma_to_1[*(sp + 1)];
png_composite(w, v, a, png_ptr->background_1.green);
- if (!optimize) w = gamma_from_1[w];
+ if (optimize == 0) w = gamma_from_1[w];
*(sp + 1) = w;
v = gamma_to_1[*(sp + 2)];
png_composite(w, v, a, png_ptr->background_1.blue);
- if (!optimize) w = gamma_from_1[w];
+ if (optimize == 0) w = gamma_from_1[w];
*(sp + 2) = w;
}
}
@@ -4088,9 +4127,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
/* Background is already in screen gamma */
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
@@ -4100,23 +4142,26 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
png_composite_16(w, v, a, png_ptr->background_1.red);
- if (!optimize)
- w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+ if (optimize == 0)
+ w = gamma_16_from_1[((w&0xff) >> gamma_shift)]
+ [w >> 8];
*sp = (png_byte)((w >> 8) & 0xff);
*(sp + 1) = (png_byte)(w & 0xff);
v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
png_composite_16(w, v, a, png_ptr->background_1.green);
- if (!optimize)
- w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+ if (optimize == 0)
+ w = gamma_16_from_1[((w&0xff) >> gamma_shift)]
+ [w >> 8];
*(sp + 2) = (png_byte)((w >> 8) & 0xff);
*(sp + 3) = (png_byte)(w & 0xff);
v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
png_composite_16(w, v, a, png_ptr->background_1.blue);
- if (!optimize)
- w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+ if (optimize == 0)
+ w = gamma_16_from_1[((w&0xff) >> gamma_shift)]
+ [w >> 8];
*(sp + 4) = (png_byte)((w >> 8) & 0xff);
*(sp + 5) = (png_byte)(w & 0xff);
@@ -4137,9 +4182,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
{
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
@@ -4715,7 +4763,9 @@ png_do_expand(png_row_infop row_info, png_bytep row,
{
if (row_info->bit_depth == 8)
{
- gray = gray & 0xff;
+ /* NOTE: prior to libpng 1.5.14 this cleared out the top bits of
+ * 'gray', however if those are set it is an error.
+ */
sp = row + (png_size_t)row_width - 1;
dp = row + (png_size_t)(row_width << 1) - 1;
diff --git a/drivers/png/pngrutil.c b/drivers/png/pngrutil.c
index c53117ab29..632c5c8e02 100644
--- a/drivers/png/pngrutil.c
+++ b/drivers/png/pngrutil.c
@@ -1,8 +1,8 @@
/* pngrutil.c - utilities to read a PNG file
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.25 [December 17, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -18,8 +18,6 @@
#ifdef PNG_READ_SUPPORTED
-#define png_strtod(p,a,b) strtod(a,b)
-
png_uint_32 PNGAPI
png_get_uint_31(png_structp png_ptr, png_const_bytep buf)
{
@@ -91,7 +89,13 @@ png_get_int_32)(png_const_bytep buf)
return uval;
uval = (uval ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */
- return -(png_int_32)uval;
+ if ((uval & 0x80000000) == 0) /* no overflow */
+ return -(png_int_32)uval;
+ /* The following has to be safe; this function only gets called on PNG data
+ * and if we get here that data is invalid. 0 is the most safe value and
+ * if not then an attacker would surely just generate a PNG with 0 instead.
+ */
+ return 0;
}
/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
@@ -211,7 +215,7 @@ png_crc_finish(png_structp png_ptr, png_uint_32 skip)
png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
}
- if (i)
+ if (i != 0)
{
png_crc_read(png_ptr, png_ptr->zbuf, i);
}
@@ -267,7 +271,7 @@ png_crc_error(png_structp png_ptr)
/* The chunk CRC must be serialized in a single I/O call. */
png_read_data(png_ptr, crc_bytes, 4);
- if (need_crc)
+ if (need_crc != 0)
{
crc = png_get_uint_32(crc_bytes);
return ((int)(crc != png_ptr->crc));
@@ -284,6 +288,17 @@ png_inflate(png_structp png_ptr, png_bytep data, png_size_t size,
{
png_size_t count = 0;
+ /* HACK: added in libpng 1.5.18: the progressive reader always leaves
+ * png_ptr->zstream in a non-reset state. This causes a reset if it needs to
+ * be used again. This only copes with that one specific error; see libpng
+ * 1.6 for a better solution.
+ */
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_PROGRESSIVE) != 0)
+ {
+ (void)inflateReset(&png_ptr->zstream);
+ png_ptr->flags &= ~PNG_FLAG_ZSTREAM_PROGRESSIVE;
+ }
+
/* zlib can't necessarily handle more than 65535 bytes at once (i.e. it can't
* even necessarily handle 65536 bytes) because the type uInt is "16 bits or
* more". Consequently it is necessary to chunk the input to zlib. This
@@ -432,15 +447,16 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
/* Now check the limits on this chunk - if the limit fails the
* compressed data will be removed, the prefix will remain.
*/
-#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
- if (png_ptr->user_chunk_malloc_max &&
+ if (prefix_size >= (~(png_size_t)0) - 1 ||
+ expanded_size >= (~(png_size_t)0) - 1 - prefix_size
+#ifdef PNG_USER_LIMITS_SUPPORTED
+ || (png_ptr->user_chunk_malloc_max &&
(prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1))
#else
-# ifdef PNG_USER_CHUNK_MALLOC_MAX
- if ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
+ || ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
-# endif
#endif
+ )
png_warning(png_ptr, "Exceeded size limit while expanding chunk");
/* If the size is zero either there was an error and a message
@@ -448,12 +464,7 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
* and we have nothing to do - the code will exit through the
* error case below.
*/
-#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \
- defined(PNG_USER_CHUNK_MALLOC_MAX)
else if (expanded_size > 0)
-#else
- if (expanded_size > 0)
-#endif
{
/* Success (maybe) - really uncompress the chunk. */
png_size_t new_size = 0;
@@ -600,7 +611,7 @@ void /* PRIVATE */
png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
png_color palette[PNG_MAX_PALETTE_LENGTH];
- int num, i;
+ int max_palette_length, num, i;
#ifdef PNG_POINTER_INDEXING_SUPPORTED
png_colorp pal_ptr;
#endif
@@ -653,8 +664,22 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
}
+ /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */
num = (int)length / 3;
+ /* If the palette has 256 or fewer entries but is too large for the bit
+ * depth, we don't issue an error, to preserve the behavior of previous
+ * libpng versions. We silently truncate the unused extra palette entries
+ * here.
+ */
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ max_palette_length = (1 << png_ptr->bit_depth);
+ else
+ max_palette_length = PNG_MAX_PALETTE_LENGTH;
+
+ if (num > max_palette_length)
+ num = max_palette_length;
+
#ifdef PNG_POINTER_INDEXING_SUPPORTED
for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
{
@@ -687,7 +712,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
#endif
{
- png_crc_finish(png_ptr, 0);
+ png_crc_finish(png_ptr, (int) length - num * 3);
}
#ifndef PNG_READ_OPT_PLTE_SUPPORTED
@@ -1261,13 +1286,16 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* Should be an error, but we can cope with it */
png_warning(png_ptr, "Out of place iCCP chunk");
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
+ if ((png_ptr->mode & PNG_HAVE_iCCP) || (info_ptr != NULL &&
+ (info_ptr->valid & (PNG_INFO_iCCP|PNG_INFO_sRGB))))
{
png_warning(png_ptr, "Duplicate iCCP chunk");
png_crc_finish(png_ptr, length);
return;
}
+ png_ptr->mode |= PNG_HAVE_iCCP;
+
#ifdef PNG_MAX_MALLOC_64K
if (length > (png_uint_32)65535L)
{
@@ -1279,7 +1307,7 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
- slength = (png_size_t)length;
+ slength = length;
png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
if (png_crc_finish(png_ptr, skip))
@@ -1299,7 +1327,7 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* There should be at least one zero (the compression type byte)
* following the separator, and we should be on it
*/
- if (profile >= png_ptr->chunkdata + slength - 1)
+ if (slength < 1U || profile >= png_ptr->chunkdata + slength - 1U)
{
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = NULL;
@@ -1310,7 +1338,7 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* Compression_type should always be zero */
compression_type = *profile++;
- if (compression_type)
+ if (compression_type != 0)
{
png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
@@ -1429,7 +1457,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
* that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a
* potential breakage point if the types in pngconf.h aren't exactly right.
*/
- slength = (png_size_t)length;
+ slength = length;
png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
if (png_crc_finish(png_ptr, skip))
@@ -1448,7 +1476,8 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
++entry_start;
/* A sample depth should follow the separator, and we should be on it */
- if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
+ if (slength < 2U ||
+ entry_start > (png_bytep)png_ptr->chunkdata + slength - 2U)
{
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = NULL;
@@ -1797,16 +1826,16 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
return;
}
- num = length / 2 ;
-
- if (num != (unsigned int)png_ptr->num_palette || num >
- (unsigned int)PNG_MAX_PALETTE_LENGTH)
+ if (length > 2*PNG_MAX_PALETTE_LENGTH ||
+ length != (unsigned int) (2*png_ptr->num_palette))
{
png_warning(png_ptr, "Incorrect hIST chunk length");
png_crc_finish(png_ptr, length);
return;
}
+ num = length / 2 ;
+
for (i = 0; i < num; i++)
{
png_byte buf[2];
@@ -1956,7 +1985,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
return;
}
- slength = (png_size_t)length;
+ slength = length;
png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
if (png_crc_finish(png_ptr, 0))
@@ -1977,7 +2006,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* We need to have at least 12 bytes after the purpose string
* in order to get the parameter information.
*/
- if (endptr <= buf + 12)
+ if (endptr - buf <= 12)
{
png_warning(png_ptr, "Invalid pCAL data");
png_free(png_ptr, png_ptr->chunkdata);
@@ -2105,7 +2134,7 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
return;
}
- slength = (png_size_t)length;
+ slength = length;
png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
@@ -2265,7 +2294,7 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
return;
}
- slength = (png_size_t)length;
+ slength = length;
png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
if (png_crc_finish(png_ptr, skip))
@@ -2310,7 +2339,7 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_ptr->chunkdata = NULL;
png_free(png_ptr, text_ptr);
- if (ret)
+ if (ret != 0)
png_warning(png_ptr, "Insufficient memory to process text chunk");
}
#endif
@@ -2373,7 +2402,7 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
return;
}
- slength = (png_size_t)length;
+ slength = length;
png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
if (png_crc_finish(png_ptr, 0))
@@ -2389,7 +2418,7 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* Empty loop */ ;
/* zTXt must have some text after the chunkdataword */
- if (text >= png_ptr->chunkdata + slength - 2)
+ if (slength < 2U || text >= png_ptr->chunkdata + slength - 2U)
{
png_warning(png_ptr, "Truncated zTXt chunk");
png_free(png_ptr, png_ptr->chunkdata);
@@ -2440,7 +2469,7 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = NULL;
- if (ret)
+ if (ret != 0)
png_error(png_ptr, "Insufficient memory to store zTXt chunk");
}
#endif
@@ -2453,7 +2482,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_textp text_ptr;
png_charp key, lang, text, lang_key;
int comp_flag;
- int comp_type = 0;
+ int comp_type;
int ret;
png_size_t slength, prefix_len, data_len;
@@ -2504,7 +2533,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
return;
}
- slength = (png_size_t)length;
+ slength = length;
png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
if (png_crc_finish(png_ptr, 0))
@@ -2526,7 +2555,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
* keyword
*/
- if (lang >= png_ptr->chunkdata + slength - 3)
+ if (slength < 3U || lang >= png_ptr->chunkdata + slength - 3U)
{
png_warning(png_ptr, "Truncated iTXt chunk");
png_free(png_ptr, png_ptr->chunkdata);
@@ -2534,18 +2563,30 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
return;
}
- else
- {
- comp_flag = *lang++;
- comp_type = *lang++;
- }
+ comp_flag = *lang++;
+ comp_type = *lang++;
- if (comp_type || (comp_flag && comp_flag != PNG_TEXT_COMPRESSION_zTXt))
+ /* 1.5.14: The spec says "for uncompressed text decoders shall ignore [the
+ * compression type]". The compression flag shall be 0 (no compression) or
+ * 1 (compressed with method 0 - deflate.)
+ */
+ if (comp_flag/*compressed*/ != 0)
{
- png_warning(png_ptr, "Unknown iTXt compression type or method");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
+ if (comp_flag != 1)
+ {
+ png_warning(png_ptr, "invalid iTXt compression flag");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+
+ if (comp_type != 0)
+ {
+ png_warning(png_ptr, "unknown iTXt compression type");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
}
for (lang_key = lang; *lang_key; lang_key++)
@@ -2578,7 +2619,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
key=png_ptr->chunkdata;
- if (comp_flag)
+ if (comp_flag/*compressed*/)
png_decompress_chunk(png_ptr, comp_type,
(size_t)length, prefix_len, &data_len);
@@ -2596,7 +2637,8 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
return;
}
- text_ptr->compression = (int)comp_flag + 1;
+ text_ptr->compression =
+ (comp_flag ? PNG_ITXT_COMPRESSION_zTXt : PNG_ITXT_COMPRESSION_NONE);
text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
text_ptr->lang = png_ptr->chunkdata + (lang - key);
text_ptr->itxt_length = data_len;
@@ -2610,7 +2652,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = NULL;
- if (ret)
+ if (ret != 0)
png_error(png_ptr, "Insufficient memory to store iTXt chunk");
}
#endif
@@ -2787,7 +2829,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
{
unsigned int pixel_depth = png_ptr->transformed_pixel_depth;
png_const_bytep sp = png_ptr->row_buf + 1;
- png_uint_32 row_width = png_ptr->width;
+ png_alloc_size_t row_width = png_ptr->width;
unsigned int pass = png_ptr->pass;
png_bytep end_ptr = 0;
png_byte end_byte = 0;
@@ -2939,7 +2981,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
# define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\
S_MASK(3,d,s), S_MASK(4,d,s), S_MASK(5,d,s) }
-# define B_MASKS(d,s) { B_MASK(1,d,s), S_MASK(3,d,s), S_MASK(5,d,s) }
+# define B_MASKS(d,s) { B_MASK(1,d,s), B_MASK(3,d,s), B_MASK(5,d,s) }
# define DEPTH_INDEX(d) ((d)==1?0:((d)==2?1:2))
@@ -3050,7 +3092,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
}
/* Work out the bytes to copy. */
- if (display)
+ if (display != 0)
{
/* When doing the 'block' algorithm the pixel in the pass gets
* replicated to adjacent pixels. This is why the even (0,2,4,6)
@@ -3060,7 +3102,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
/* But don't allow this number to exceed the actual row width. */
if (bytes_to_copy > row_width)
- bytes_to_copy = row_width;
+ bytes_to_copy = (unsigned int)/*SAFE*/row_width;
}
else /* normal row; Adam7 only ever gives us one pixel to copy. */
@@ -3152,7 +3194,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
{
png_uint_32p dp32 = (png_uint_32p)dp;
png_const_uint_32p sp32 = (png_const_uint_32p)sp;
- unsigned int skip = (bytes_to_jump-bytes_to_copy) /
+ size_t skip = (bytes_to_jump-bytes_to_copy) /
sizeof (png_uint_32);
do
@@ -3193,7 +3235,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
{
png_uint_16p dp16 = (png_uint_16p)dp;
png_const_uint_16p sp16 = (png_const_uint_16p)sp;
- unsigned int skip = (bytes_to_jump-bytes_to_copy) /
+ size_t skip = (bytes_to_jump-bytes_to_copy) /
sizeof (png_uint_16);
do
@@ -3238,7 +3280,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
dp += bytes_to_jump;
row_width -= bytes_to_jump;
if (bytes_to_copy > row_width)
- bytes_to_copy = row_width;
+ bytes_to_copy = (unsigned int)/*SAFE*/row_width;
}
}
@@ -3477,7 +3519,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
for (i = 0; i < row_info->width; i++)
{
- png_byte v[8];
+ png_byte v[8]; /* SAFE; pixel_depth does not exceed 64 */
int j;
png_memcpy(v, sp, pixel_bytes);
@@ -3661,68 +3703,6 @@ png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row,
}
}
-#ifdef PNG_ARM_NEON
-
-#if 0
-#ifdef __linux__
-#include <stdio.h>
-#include <elf.h>
-#include <asm/hwcap.h>
-
-static int png_have_hwcap(unsigned cap)
-{
- FILE *f = fopen("/proc/self/auxv", "r");
- Elf32_auxv_t aux;
- int have_cap = 0;
-
- if (!f)
- return 0;
-
- while (fread(&aux, sizeof(aux), 1, f) > 0)
- {
- if (aux.a_type == AT_HWCAP &&
- aux.a_un.a_val & cap)
- {
- have_cap = 1;
- break;
- }
- }
-
- fclose(f);
-
- return have_cap;
-}
-#endif /* __linux__ */
-#endif
-static void
-png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
-{
-#if 0
-#ifdef __linux__
- if (!png_have_hwcap(HWCAP_NEON))
- return;
-#endif
-#endif
- pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon;
-
- if (bpp == 3)
- {
- pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon;
- pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon;
- pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
- png_read_filter_row_paeth3_neon;
- }
-
- else if (bpp == 4)
- {
- pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon;
- pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon;
- pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
- png_read_filter_row_paeth4_neon;
- }
-}
-#endif /* PNG_ARM_NEON */
-
static void
png_init_filter_functions(png_structp pp)
{
@@ -3738,8 +3718,16 @@ png_init_filter_functions(png_structp pp)
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
png_read_filter_row_paeth_multibyte_pixel;
-#ifdef PNG_ARM_NEON
- png_init_filter_functions_neon(pp, bpp);
+#ifdef PNG_FILTER_OPTIMIZATIONS
+ /* To use this define PNG_FILTER_OPTIMIZATIONS as the name of a function to
+ * call to install hardware optimizations for the above functions; simply
+ * replace whatever elements of the pp->read_filter[] array with a hardware
+ * specific (or, for that matter, generic) optimization.
+ *
+ * To see an example of this examine what configure.ac does when
+ * --enable-arm-neon is specified on the command line.
+ */
+ PNG_FILTER_OPTIMIZATIONS(pp, bpp);
#endif
}
@@ -3747,10 +3735,13 @@ void /* PRIVATE */
png_read_filter_row(png_structp pp, png_row_infop row_info, png_bytep row,
png_const_bytep prev_row, int filter)
{
- if (pp->read_filter[0] == NULL)
- png_init_filter_functions(pp);
if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST)
+ {
+ if (pp->read_filter[0] == NULL)
+ png_init_filter_functions(pp);
+
pp->read_filter[filter-1](row_info, row, prev_row);
+ }
}
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
diff --git a/drivers/png/pngset.c b/drivers/png/pngset.c
index 92db3890a8..61be6bc62e 100644
--- a/drivers/png/pngset.c
+++ b/drivers/png/pngset.c
@@ -1,8 +1,8 @@
/* pngset.c - storage of image information into info struct
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.26 [December 17, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -20,6 +20,60 @@
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) ||\
+ defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
+/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
+ * and if invalid, correct the keyword rather than discarding the entire
+ * chunk. The PNG 1.0 specification requires keywords 1-79 characters in
+ * length, forbids leading or trailing whitespace, multiple internal spaces,
+ * and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
+ *
+ * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
+ * trailing '\0'). If this routine returns 0 then there was no keyword, or a
+ * valid one could not be generated, and the caller must handle the error by not
+ * setting the keyword.
+ */
+static png_uint_32
+png_check_keyword(png_const_charp key, png_bytep new_key)
+{
+ png_uint_32 key_len = 0;
+ int space = 1;
+
+ if (key == NULL)
+ {
+ *new_key = 0;
+ return 0;
+ }
+
+ while (*key && key_len < 79)
+ {
+ png_byte ch = (png_byte)*key++;
+
+ if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
+ *new_key++ = ch, ++key_len, space = 0;
+
+ else if (space == 0)
+ {
+ /* A space or an invalid character when one wasn't seen immediately
+ * before; output just a space.
+ */
+ *new_key++ = 32, ++key_len, space = 1;
+ }
+ }
+
+ if (key_len > 0 && space != 0) /* trailing space */
+ --key_len, --new_key;
+
+ /* Terminate the keyword */
+ *new_key = 0;
+
+ if (key_len == 0)
+ return 0;
+
+ return key_len;
+}
+#endif /* TEXT || pCAL || iCCP || sPLT */
+
#ifdef PNG_bKGD_SUPPORTED
void PNGAPI
png_set_bKGD(png_structp png_ptr, png_infop info_ptr,
@@ -123,12 +177,12 @@ png_set_cHRM_XYZ(png_structp png_ptr, png_infop info_ptr, double red_X,
png_fixed(png_ptr, red_X, "cHRM Red X"),
png_fixed(png_ptr, red_Y, "cHRM Red Y"),
png_fixed(png_ptr, red_Z, "cHRM Red Z"),
- png_fixed(png_ptr, green_X, "cHRM Red X"),
- png_fixed(png_ptr, green_Y, "cHRM Red Y"),
- png_fixed(png_ptr, green_Z, "cHRM Red Z"),
- png_fixed(png_ptr, blue_X, "cHRM Red X"),
- png_fixed(png_ptr, blue_Y, "cHRM Red Y"),
- png_fixed(png_ptr, blue_Z, "cHRM Red Z"));
+ png_fixed(png_ptr, green_X, "cHRM Green X"),
+ png_fixed(png_ptr, green_Y, "cHRM Green Y"),
+ png_fixed(png_ptr, green_Z, "cHRM Green Z"),
+ png_fixed(png_ptr, blue_X, "cHRM Blue X"),
+ png_fixed(png_ptr, blue_Y, "cHRM Blue Y"),
+ png_fixed(png_ptr, blue_Z, "cHRM Blue Z"));
}
# endif /* PNG_FLOATING_POINT_SUPPORTED */
@@ -149,7 +203,7 @@ png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
* possible for 1/gamma to overflow the limit of 21474 and this means the
* gamma value must be at least 5/100000 and hence at most 20000.0. For
* safety the limits here are a little narrower. The values are 0.00016 to
- * 6250.0, which are truly ridiculous gammma values (and will produce
+ * 6250.0, which are truly ridiculous gamma values (and will produce
* displays that are all black or all white.)
*/
if (file_gamma < 16 || file_gamma > 625000000)
@@ -252,16 +306,7 @@ png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
- /* Check for potential overflow */
- if (width >
- (PNG_UINT_32_MAX >> 3) /* 8-byte RRGGBBAA pixels */
- - 48 /* bigrowbuf hack */
- - 1 /* filter byte */
- - 7*8 /* rounding of width to multiple of 8 pixels */
- - 8) /* extra max_pixel_depth pad */
- info_ptr->rowbytes = 0;
- else
- info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
+ info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
}
#ifdef PNG_oFFs_SUPPORTED
@@ -287,6 +332,7 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type,
int nparams, png_const_charp units, png_charpp params)
{
+ png_byte new_purpose[80];
png_size_t length;
int i;
@@ -295,7 +341,15 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
if (png_ptr == NULL || info_ptr == NULL)
return;
- length = png_strlen(purpose) + 1;
+ length = png_check_keyword(purpose, new_purpose);
+
+ if (length == 0)
+ {
+ png_warning(png_ptr, "pCAL: invalid purpose keyword");
+ return;
+ }
+
+ ++length;
png_debug1(3, "allocating purpose for info (%lu bytes)",
(unsigned long)length);
@@ -318,7 +372,7 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
return;
}
- png_memcpy(info_ptr->pcal_purpose, purpose, length);
+ png_memcpy(info_ptr->pcal_purpose, new_purpose, length);
png_debug(3, "storing X0, X1, type, and nparams in info");
info_ptr->pcal_X0 = X0;
@@ -517,12 +571,17 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
png_const_colorp palette, int num_palette)
{
+ png_uint_32 max_palette_length;
+
png_debug1(1, "in %s storage function", "PLTE");
if (png_ptr == NULL || info_ptr == NULL)
return;
- if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)
+ max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
+ (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
+
+ if (num_palette < 0 || num_palette > (int) max_palette_length)
{
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
png_error(png_ptr, "Invalid palette length");
@@ -541,8 +600,8 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
/* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
- * of num_palette entries, in case of an invalid PNG file that has
- * too-large sample values.
+ * of num_palette entries, in case of an invalid PNG file or incorrect
+ * call to png_set_PLTE() with too-large sample values.
*/
png_ptr->palette = (png_colorp)png_calloc(png_ptr,
PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color));
@@ -618,6 +677,7 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
png_const_charp name, int compression_type,
png_const_bytep profile, png_uint_32 proflen)
{
+ png_byte new_name[80];
png_charp new_iccp_name;
png_bytep new_iccp_profile;
png_size_t length;
@@ -627,7 +687,15 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
return;
- length = png_strlen(name)+1;
+ length = png_check_keyword(name, new_name);
+
+ if (length == 0)
+ {
+ png_warning(png_ptr, "iCCP: invalid keyword");
+ return;
+ }
+
+ ++length;
new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length);
if (new_iccp_name == NULL)
@@ -636,7 +704,7 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
return;
}
- png_memcpy(new_iccp_name, name, length);
+ png_memcpy(new_iccp_name, new_name, length);
new_iccp_profile = (png_bytep)png_malloc_warn(png_ptr, proflen);
if (new_iccp_profile == NULL)
@@ -671,7 +739,7 @@ png_set_text(png_structp png_ptr, png_infop info_ptr, png_const_textp text_ptr,
int ret;
ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
- if (ret)
+ if (ret != 0)
png_error(png_ptr, "Insufficient memory to store text");
}
@@ -680,8 +748,9 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
png_const_textp text_ptr, int num_text)
{
int i;
+ size_t element_size;
- png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" :
+ png_debug1(1, "in %lx storage function", png_ptr == NULL ? 0xabadca11 :
(unsigned long)png_ptr->chunk_name);
if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
@@ -690,26 +759,42 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
/* Make sure we have enough space in the "text" array in info_struct
* to hold all of the incoming text_ptr objects.
*/
+
+ element_size=png_sizeof(png_text);
+ if (num_text < 0 ||
+ num_text > INT_MAX - info_ptr->num_text - 8 ||
+ (unsigned int)/*SAFE*/(num_text +/*SAFE*/
+ info_ptr->num_text + 8) >=
+ PNG_SIZE_MAX/element_size)
+ {
+ png_warning(png_ptr, "too many text chunks");
+ return(0);
+ }
+
if (info_ptr->num_text + num_text > info_ptr->max_text)
{
+ int old_max_text = info_ptr->max_text;
+ int old_num_text = info_ptr->num_text;
+
if (info_ptr->text != NULL)
{
png_textp old_text;
- int old_max;
- old_max = info_ptr->max_text;
info_ptr->max_text = info_ptr->num_text + num_text + 8;
old_text = info_ptr->text;
+
info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
(png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
if (info_ptr->text == NULL)
{
- png_free(png_ptr, old_text);
+ /* Restore to previous condition */
+ info_ptr->max_text = old_max_text;
+ info_ptr->text = old_text;
return(1);
}
- png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *
+ png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max_text *
png_sizeof(png_text)));
png_free(png_ptr, old_text);
}
@@ -721,7 +806,12 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
(png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
if (info_ptr->text == NULL)
+ {
+ /* Restore to previous condition */
+ info_ptr->num_text = old_num_text;
+ info_ptr->max_text = old_max_text;
return(1);
+ }
info_ptr->free_me |= PNG_FREE_TEXT;
}
@@ -730,6 +820,7 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
}
for (i = 0; i < num_text; i++)
{
+ png_byte new_key[80], new_lang[80];
png_size_t text_length, key_len;
png_size_t lang_len, lang_key_len;
png_textp textp = &(info_ptr->text[info_ptr->num_text]);
@@ -744,7 +835,13 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
continue;
}
- key_len = png_strlen(text_ptr[i].key);
+ key_len = png_check_keyword(text_ptr[i].key, new_key);
+
+ if (key_len == 0)
+ {
+ png_warning(png_ptr, "invalid text keyword");
+ continue;
+ }
if (text_ptr[i].compression <= 0)
{
@@ -757,8 +854,9 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
{
/* Set iTXt data */
+ /* Zero length language is OK */
if (text_ptr[i].lang != NULL)
- lang_len = png_strlen(text_ptr[i].lang);
+ lang_len = png_check_keyword(text_ptr[i].lang, new_lang);
else
lang_len = 0;
@@ -806,7 +904,7 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
(key_len + lang_len + lang_key_len + text_length + 4),
textp->key);
- png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len));
+ png_memcpy(textp->key, new_key, (png_size_t)(key_len));
*(textp->key + key_len) = '\0';
if (text_ptr[i].compression > 0)
@@ -827,7 +925,7 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
textp->text = textp->key + key_len + 1;
}
- if (text_length)
+ if (text_length != 0)
png_memcpy(textp->text, text_ptr[i].text,
(png_size_t)(text_length));
@@ -888,6 +986,12 @@ png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
if (png_ptr == NULL || info_ptr == NULL)
return;
+ if (num_trans < 0 || num_trans > PNG_MAX_PALETTE_LENGTH)
+ {
+ png_warning(png_ptr, "Ignoring invalid num_trans value");
+ return;
+ }
+
if (trans_alpha != NULL)
{
/* It may not actually be necessary to set png_ptr->trans_alpha here;
@@ -907,16 +1011,19 @@ png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
if (trans_color != NULL)
{
- int sample_max = (1 << info_ptr->bit_depth);
-
- if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
- (int)trans_color->gray > sample_max) ||
- (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
- ((int)trans_color->red > sample_max ||
- (int)trans_color->green > sample_max ||
- (int)trans_color->blue > sample_max)))
- png_warning(png_ptr,
- "tRNS chunk has out-of-range samples for bit_depth");
+ if (info_ptr->bit_depth < 16)
+ {
+ unsigned int sample_max = (1U << info_ptr->bit_depth) - 1U;
+
+ if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
+ trans_color->gray > sample_max) ||
+ (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
+ (trans_color->red > sample_max ||
+ trans_color->green > sample_max ||
+ trans_color->blue > sample_max)))
+ png_warning(png_ptr,
+ "tRNS chunk has out-of-range samples for bit_depth");
+ }
png_memcpy(&(info_ptr->trans_color), trans_color,
png_sizeof(png_color_16));
@@ -949,14 +1056,25 @@ png_set_sPLT(png_structp png_ptr,
*/
{
png_sPLT_tp np;
- int i;
+ int i, j;
+ size_t element_size;
if (png_ptr == NULL || info_ptr == NULL)
return;
- np = (png_sPLT_tp)png_malloc_warn(png_ptr,
- (info_ptr->splt_palettes_num + nentries) *
- (png_size_t)png_sizeof(png_sPLT_t));
+ element_size = png_sizeof(png_sPLT_t);
+ if (nentries < 0 ||
+ nentries > INT_MAX-info_ptr->splt_palettes_num ||
+ (unsigned int)/*SAFE*/(nentries +/*SAFE*/
+ info_ptr->splt_palettes_num) >=
+ PNG_SIZE_MAX/element_size)
+ np=NULL;
+
+ else
+
+ np = (png_sPLT_tp)png_malloc_warn(png_ptr,
+ (info_ptr->splt_palettes_num + nentries) *
+ (png_size_t)png_sizeof(png_sPLT_t));
if (np == NULL)
{
@@ -970,13 +1088,22 @@ png_set_sPLT(png_structp png_ptr,
png_free(png_ptr, info_ptr->splt_palettes);
info_ptr->splt_palettes=NULL;
- for (i = 0; i < nentries; i++)
+ for (i = j = 0; i < nentries; i++)
{
- png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
+ png_sPLT_tp to = np + info_ptr->splt_palettes_num + j;
png_const_sPLT_tp from = entries + i;
+ png_byte new_name[80];
png_size_t length;
- length = png_strlen(from->name) + 1;
+ length = png_check_keyword(from->name, new_name);
+
+ if (length == 0)
+ {
+ png_warning(png_ptr, "sPLT: invalid keyword");
+ continue;
+ }
+
+ ++length; /* for trailing '\0' */
to->name = (png_charp)png_malloc_warn(png_ptr, length);
if (to->name == NULL)
@@ -986,7 +1113,7 @@ png_set_sPLT(png_structp png_ptr,
continue;
}
- png_memcpy(to->name, from->name, length);
+ png_memcpy(to->name, new_name, length);
to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr,
from->nentries * png_sizeof(png_sPLT_entry));
@@ -1004,10 +1131,11 @@ png_set_sPLT(png_structp png_ptr,
to->nentries = from->nentries;
to->depth = from->depth;
+ ++j;
}
info_ptr->splt_palettes = np;
- info_ptr->splt_palettes_num += nentries;
+ info_ptr->splt_palettes_num = j;
info_ptr->valid |= PNG_INFO_sPLT;
info_ptr->free_me |= PNG_FREE_SPLT;
}
@@ -1020,13 +1148,23 @@ png_set_unknown_chunks(png_structp png_ptr,
{
png_unknown_chunkp np;
int i;
+ size_t element_size;
if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
return;
- np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
- (png_size_t)(info_ptr->unknown_chunks_num + num_unknowns) *
- png_sizeof(png_unknown_chunk));
+ element_size = png_sizeof(png_unknown_chunk);
+ if (num_unknowns < 0 ||
+ num_unknowns > INT_MAX-info_ptr->unknown_chunks_num ||
+ (unsigned int)/*SAFE*/(num_unknowns +/*SAFE*/
+ info_ptr->unknown_chunks_num) >=
+ PNG_SIZE_MAX/element_size)
+ np=NULL;
+
+ else
+ np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
+ (png_size_t)(info_ptr->unknown_chunks_num + num_unknowns) *
+ png_sizeof(png_unknown_chunk));
if (np == NULL)
{
@@ -1189,11 +1327,12 @@ png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
info_ptr->row_pointers = row_pointers;
- if (row_pointers)
+ if (row_pointers != NULL)
info_ptr->valid |= PNG_INFO_IDAT;
}
#endif
+#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
void PNGAPI
png_set_compression_buffer_size(png_structp png_ptr, png_size_t size)
{
@@ -1221,6 +1360,7 @@ png_set_compression_buffer_size(png_structp png_ptr, png_size_t size)
png_ptr->zstream.avail_out = 0;
png_ptr->zstream.avail_in = 0;
}
+#endif /* WRITE_CUSTOMIZE_COMPRESSION */
void PNGAPI
png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask)
@@ -1239,7 +1379,7 @@ png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max,
{
/* Images with dimensions larger than these limits will be
* rejected by png_set_IHDR(). To accept any PNG datastream
- * regardless of dimensions, set both limits to 0x7ffffffL.
+ * regardless of dimensions, set both limits to 0x7fffffffL.
*/
if (png_ptr == NULL)
return;
@@ -1253,7 +1393,7 @@ void PNGAPI
png_set_chunk_cache_max (png_structp png_ptr,
png_uint_32 user_chunk_cache_max)
{
- if (png_ptr)
+ if (png_ptr != NULL)
png_ptr->user_chunk_cache_max = user_chunk_cache_max;
}
@@ -1262,7 +1402,7 @@ void PNGAPI
png_set_chunk_malloc_max (png_structp png_ptr,
png_alloc_size_t user_chunk_malloc_max)
{
- if (png_ptr)
+ if (png_ptr != NULL)
png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
}
#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
@@ -1274,11 +1414,28 @@ png_set_benign_errors(png_structp png_ptr, int allowed)
{
png_debug(1, "in png_set_benign_errors");
- if (allowed)
+ if (allowed != 0)
png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
else
png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN;
}
#endif /* PNG_BENIGN_ERRORS_SUPPORTED */
+
+#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+/* Whether to report invalid palette index; added at libng-1.5.10
+ * allowed - one of 0: disable; 1: enable
+ */
+void PNGAPI
+png_set_check_for_invalid_index(png_structp png_ptr, int allowed)
+{
+ png_debug(1, "in png_set_check_for_invalid_index");
+
+ if (allowed != 0)
+ png_ptr->num_palette_max = 0;
+
+ else
+ png_ptr->num_palette_max = -1;
+}
+#endif
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
diff --git a/drivers/png/pngstruct.h b/drivers/png/pngstruct.h
index 07f3a04255..52eef80e69 100644
--- a/drivers/png/pngstruct.h
+++ b/drivers/png/pngstruct.h
@@ -1,12 +1,11 @@
/* pngstruct.h - header file for PNG reference library
*
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.23 [July 23, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
- * Last changed in libpng 1.5.5 [September 22, 2011]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
@@ -121,6 +120,12 @@ struct png_struct_def
png_uint_32 crc; /* current chunk CRC value */
png_colorp palette; /* palette from the input file */
png_uint_16 num_palette; /* number of color entries in palette */
+
+/* Added at libpng-1.5.10 */
+#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ int num_palette_max; /* maximum palette index found in IDAT */
+#endif
+
png_uint_16 num_trans; /* number of transparency values */
png_byte compression; /* file compression type (always 0) */
png_byte filter; /* file filter type (always 0) */
@@ -211,13 +216,6 @@ struct png_struct_def
int process_mode; /* what push library is currently doing */
int cur_palette; /* current push library palette index */
-# ifdef PNG_TEXT_SUPPORTED
- png_size_t current_text_size; /* current size of text input data */
- png_size_t current_text_left; /* how much text left to read in input */
- png_charp current_text; /* current text chunk buffer */
- png_charp current_text_ptr; /* current location in current_text */
-# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */
-
#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
@@ -238,17 +236,8 @@ struct png_struct_def
png_uint_16p hist; /* histogram */
#endif
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- png_byte heuristic_method; /* heuristic for row filter selection */
- png_byte num_prev_filters; /* number of weights for previous rows */
- png_bytep prev_filters; /* filter type(s) of previous row(s) */
- png_uint_16p filter_weights; /* weight(s) for previous line(s) */
- png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */
- png_uint_16p filter_costs; /* relative filter calculation cost */
- png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */
-#endif
-
#ifdef PNG_TIME_RFC1123_SUPPORTED
+ /* This is going to be unused in libpng16 and removed from libpng17 */
char time_buffer[29]; /* String to hold RFC 1123 time text */
#endif
@@ -283,9 +272,7 @@ struct png_struct_def
#endif
/* New member added in libpng-1.0.4 (renamed in 1.0.9) */
-#if defined(PNG_MNG_FEATURES_SUPPORTED) || \
- defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
- defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
/* Changed from png_byte to png_uint_32 at version 1.2.0 */
png_uint_32 mng_features_permitted;
#endif
@@ -354,7 +341,13 @@ struct png_struct_def
/* New member added in libpng-1.5.6 */
png_bytep big_prev_row;
+/* New member added in libpng-1.5.7 */
void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info,
png_bytep row, png_const_bytep prev_row);
+
+ /* Options */
+#ifdef PNG_SET_OPTION_SUPPORTED
+ png_byte options; /* On/off state (up to 4 options) */
+#endif
};
#endif /* PNGSTRUCT_H */
diff --git a/drivers/png/pngtrans.c b/drivers/png/pngtrans.c
index 6a6908dcd2..a5df5afe00 100644
--- a/drivers/png/pngtrans.c
+++ b/drivers/png/pngtrans.c
@@ -1,8 +1,8 @@
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
*
- * Last changed in libpng 1.5.4 [July 7, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.19 [August 21, 2014]
+ * Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -452,7 +452,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
{
if (row_info->bit_depth == 8)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
++sp;
else /* Skip initial channel and, for sp, the filler */
sp += 2, ++dp;
@@ -466,7 +466,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
else if (row_info->bit_depth == 16)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
sp += 2;
else /* Skip initial channel and, for sp, the filler */
sp += 4, dp += 2;
@@ -492,7 +492,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
{
if (row_info->bit_depth == 8)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
++sp;
else /* Skip initial channels and, for sp, the filler */
sp += 4, dp += 3;
@@ -506,7 +506,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
else if (row_info->bit_depth == 16)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
sp += 2;
else /* Skip initial channels and, for sp, the filler */
sp += 8, dp += 6;
@@ -619,6 +619,109 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
}
#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
+#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
+ defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
+/* Added at libpng-1.5.10 */
+void /* PRIVATE */
+png_do_check_palette_indexes(png_structp png_ptr, png_row_infop row_info)
+{
+ if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
+ png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
+ {
+ /* Calculations moved outside switch in an attempt to stop different
+ * compiler warnings. 'padding' is in *bits* within the last byte, it is
+ * an 'int' because pixel_depth becomes an 'int' in the expression below,
+ * and this calculation is used because it avoids warnings that other
+ * forms produced on either GCC or MSVC.
+ */
+ int padding = (-row_info->pixel_depth * row_info->width) & 7;
+ png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
+
+ switch (row_info->bit_depth)
+ {
+ case 1:
+ {
+ /* in this case, all bytes must be 0 so we don't need
+ * to unpack the pixels except for the rightmost one.
+ */
+ for (; rp > png_ptr->row_buf; rp--)
+ {
+ if (*rp >> padding != 0)
+ png_ptr->num_palette_max = 1;
+ padding = 0;
+ }
+
+ break;
+ }
+
+ case 2:
+ {
+ for (; rp > png_ptr->row_buf; rp--)
+ {
+ int i = ((*rp >> padding) & 0x03);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ i = (((*rp >> padding) >> 2) & 0x03);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ i = (((*rp >> padding) >> 4) & 0x03);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ i = (((*rp >> padding) >> 6) & 0x03);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ padding = 0;
+ }
+
+ break;
+ }
+
+ case 4:
+ {
+ for (; rp > png_ptr->row_buf; rp--)
+ {
+ int i = ((*rp >> padding) & 0x0f);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ i = (((*rp >> padding) >> 4) & 0x0f);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ padding = 0;
+ }
+
+ break;
+ }
+
+ case 8:
+ {
+ for (; rp > png_ptr->row_buf; rp--)
+ {
+ if (*rp > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = (int) *rp;
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+}
+#endif /* PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED */
+
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
diff --git a/drivers/png/pngwio.c b/drivers/png/pngwio.c
index 95ffb3429f..cc55521452 100644
--- a/drivers/png/pngwio.c
+++ b/drivers/png/pngwio.c
@@ -1,8 +1,8 @@
/* pngwio.c - functions for data output
*
- * Last changed in libpng 1.5.0 [January 6, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.18 [February 6, 2014]
+ * Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -207,6 +207,8 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
# else
png_ptr->output_flush_fn = output_flush_fn;
# endif
+#else
+ PNG_UNUSED(output_flush_fn)
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
/* It is an error to read while writing a png file */
diff --git a/drivers/png/pngwrite.c b/drivers/png/pngwrite.c
index 6d3fd4c386..776c23603a 100644
--- a/drivers/png/pngwrite.c
+++ b/drivers/png/pngwrite.c
@@ -1,8 +1,8 @@
/* pngwrite.c - general routines to write a PNG file
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.23 [July 23, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -34,85 +34,87 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
{
- /* Write PNG signature */
- png_write_sig(png_ptr);
+ /* Write PNG signature */
+ png_write_sig(png_ptr);
#ifdef PNG_MNG_FEATURES_SUPPORTED
- if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \
- (png_ptr->mng_features_permitted))
- {
- png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
- png_ptr->mng_features_permitted = 0;
- }
+ if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \
+ (png_ptr->mng_features_permitted))
+ {
+ png_warning(png_ptr,
+ "MNG features are not allowed in a PNG datastream");
+ png_ptr->mng_features_permitted = 0;
+ }
#endif
- /* Write IHDR information. */
- png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
- info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
- info_ptr->filter_type,
+ /* Write IHDR information. */
+ png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
+ info_ptr->bit_depth, info_ptr->color_type,
+ info_ptr->compression_type, info_ptr->filter_type,
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
- info_ptr->interlace_type);
+ info_ptr->interlace_type
#else
- 0);
+ 0
#endif
- /* The rest of these check to see if the valid field has the appropriate
- * flag set, and if it does, writes the chunk.
- */
+ );
+ /* The rest of these check to see if the valid field has the appropriate
+ * flag set, and if it does, writes the chunk.
+ */
#ifdef PNG_WRITE_gAMA_SUPPORTED
- if (info_ptr->valid & PNG_INFO_gAMA)
- png_write_gAMA_fixed(png_ptr, info_ptr->gamma);
+ if (info_ptr->valid & PNG_INFO_gAMA)
+ png_write_gAMA_fixed(png_ptr, info_ptr->gamma);
#endif
#ifdef PNG_WRITE_sRGB_SUPPORTED
- if (info_ptr->valid & PNG_INFO_sRGB)
- png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
+ if (info_ptr->valid & PNG_INFO_sRGB)
+ png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
#endif
#ifdef PNG_WRITE_iCCP_SUPPORTED
- if (info_ptr->valid & PNG_INFO_iCCP)
- png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
- (png_charp)info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
+ if (info_ptr->valid & PNG_INFO_iCCP)
+ png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
+ (png_charp)info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
#endif
#ifdef PNG_WRITE_sBIT_SUPPORTED
- if (info_ptr->valid & PNG_INFO_sBIT)
- png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
+ if (info_ptr->valid & PNG_INFO_sBIT)
+ png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
#endif
#ifdef PNG_WRITE_cHRM_SUPPORTED
- if (info_ptr->valid & PNG_INFO_cHRM)
- png_write_cHRM_fixed(png_ptr,
- info_ptr->x_white, info_ptr->y_white,
- info_ptr->x_red, info_ptr->y_red,
- info_ptr->x_green, info_ptr->y_green,
- info_ptr->x_blue, info_ptr->y_blue);
+ if (info_ptr->valid & PNG_INFO_cHRM)
+ png_write_cHRM_fixed(png_ptr,
+ info_ptr->x_white, info_ptr->y_white,
+ info_ptr->x_red, info_ptr->y_red,
+ info_ptr->x_green, info_ptr->y_green,
+ info_ptr->x_blue, info_ptr->y_blue);
#endif
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
- if (info_ptr->unknown_chunks_num)
- {
- png_unknown_chunk *up;
-
- png_debug(5, "writing extra chunks");
-
- for (up = info_ptr->unknown_chunks;
- up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
- up++)
+ if (info_ptr->unknown_chunks_num)
{
- int keep = png_handle_as_unknown(png_ptr, up->name);
+ png_unknown_chunk *up;
- if (keep != PNG_HANDLE_CHUNK_NEVER &&
- up->location &&
- !(up->location & PNG_HAVE_PLTE) &&
- !(up->location & PNG_HAVE_IDAT) &&
- !(up->location & PNG_AFTER_IDAT) &&
- ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
- (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
+ png_debug(5, "writing extra chunks");
+
+ for (up = info_ptr->unknown_chunks;
+ up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+ up++)
{
- if (up->size == 0)
- png_warning(png_ptr, "Writing zero-length unknown chunk");
+ int keep = png_handle_as_unknown(png_ptr, up->name);
+
+ if (keep != PNG_HANDLE_CHUNK_NEVER &&
+ up->location &&
+ !(up->location & PNG_HAVE_PLTE) &&
+ !(up->location & PNG_HAVE_IDAT) &&
+ !(up->location & PNG_AFTER_IDAT) &&
+ ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
+ {
+ if (up->size == 0)
+ png_warning(png_ptr, "Writing zero-length unknown chunk");
- png_write_chunk(png_ptr, up->name, up->data, up->size);
+ png_write_chunk(png_ptr, up->name, up->data, up->size);
+ }
}
}
- }
#endif
png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
}
@@ -223,11 +225,14 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
info_ptr->text[i].lang,
info_ptr->text[i].lang_key,
info_ptr->text[i].text);
+ /* Mark this chunk as written */
+ if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+ else
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#else
- png_warning(png_ptr, "Unable to write international text");
+ png_warning(png_ptr, "Unable to write international text");
#endif
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
}
/* If we want a compressed text chunk */
@@ -238,11 +243,11 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
png_write_zTXt(png_ptr, info_ptr->text[i].key,
info_ptr->text[i].text, 0,
info_ptr->text[i].compression);
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#else
png_warning(png_ptr, "Unable to write compressed text");
#endif
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
}
else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
@@ -305,6 +310,11 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
if (!(png_ptr->mode & PNG_HAVE_IDAT))
png_error(png_ptr, "No IDATs written into file");
+#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ if (png_ptr->num_palette_max > png_ptr->num_palette)
+ png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
+#endif
+
/* See if user wants us to write information chunks */
if (info_ptr != NULL)
{
@@ -335,11 +345,11 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
info_ptr->text[i].lang,
info_ptr->text[i].lang_key,
info_ptr->text[i].text);
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
#else
png_warning(png_ptr, "Unable to write international text");
#endif
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
}
else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
@@ -349,11 +359,11 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
png_write_zTXt(png_ptr, info_ptr->text[i].key,
info_ptr->text[i].text, 0,
info_ptr->text[i].compression);
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#else
png_warning(png_ptr, "Unable to write compressed text");
#endif
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
}
else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
@@ -362,12 +372,11 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
/* Write uncompressed chunk */
png_write_tEXt(png_ptr, info_ptr->text[i].key,
info_ptr->text[i].text, 0);
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
#else
png_warning(png_ptr, "Unable to write uncompressed text");
#endif
-
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
}
}
#endif
@@ -415,7 +424,6 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
}
#ifdef PNG_CONVERT_tIME_SUPPORTED
-/* "tm" structure is not supported on WindowsCE */
void PNGAPI
png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm FAR * ttime)
{
@@ -451,9 +459,6 @@ png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
warn_fn, NULL, NULL, NULL));
}
-/* Alternate initialize png_ptr structure, and allocate any memory needed */
-static void png_reset_filter_heuristics(png_structp png_ptr); /* forward decl */
-
PNG_FUNCTION(png_structp,PNGAPI
png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
@@ -495,14 +500,13 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
*/
#ifdef USE_FAR_KEYWORD
if (setjmp(tmp_jmpbuf))
+ png_memcpy(png_jmpbuf(png_ptr), tmp_jmpbuf, png_sizeof(jmp_buf));
+ PNG_ABORT();
#else
if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */
-#endif
-#ifdef USE_FAR_KEYWORD
- png_memcpy(png_jmpbuf(png_ptr), tmp_jmpbuf, png_sizeof(jmp_buf));
-#endif
PNG_ABORT();
#endif
+#endif
#ifdef PNG_USER_MEM_SUPPORTED
png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
@@ -515,7 +519,7 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
/* Initialize zbuf - compression buffer */
png_ptr->zbuf_size = PNG_ZBUF_SIZE;
- if (!png_cleanup_needed)
+ if (png_cleanup_needed == 0)
{
png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr,
png_ptr->zbuf_size);
@@ -523,7 +527,7 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
png_cleanup_needed = 1;
}
- if (png_cleanup_needed)
+ if (png_cleanup_needed != 0)
{
/* Clean up PNG structure and deallocate any memory. */
png_free(png_ptr, png_ptr->zbuf);
@@ -539,10 +543,6 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
png_set_write_fn(png_ptr, NULL, NULL, NULL);
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- png_reset_filter_heuristics(png_ptr);
-#endif
-
return (png_ptr);
}
@@ -759,7 +759,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
{
png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass);
/* This should always get caught above, but still ... */
- if (!(row_info.width))
+ if (row_info.width == 0)
{
png_write_finish_row(png_ptr);
return;
@@ -798,6 +798,14 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
}
#endif
+/* Added at libpng-1.5.10 */
+#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Check for out-of-range palette index */
+ if (row_info.color_type == PNG_COLOR_TYPE_PALETTE &&
+ png_ptr->num_palette_max >= 0)
+ png_do_check_palette_indexes(png_ptr, &row_info);
+#endif
+
/* Find a filter if necessary, filter the row and write it out. */
png_write_find_filter(png_ptr, &row_info);
@@ -851,7 +859,7 @@ png_write_flush(png_structp png_ptr)
png_error(png_ptr, "zlib error");
}
- if (!(png_ptr->zstream.avail_out))
+ if ((png_ptr->zstream.avail_out) == 0)
{
/* Write the IDAT and reset the zlib output buffer */
png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
@@ -969,13 +977,6 @@ png_write_destroy(png_structp png_ptr)
png_free(png_ptr, png_ptr->paeth_row);
#endif
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- /* Use this to save a little code space, it doesn't free the filter_costs */
- png_reset_filter_heuristics(png_ptr);
- png_free(png_ptr, png_ptr->filter_costs);
- png_free(png_ptr, png_ptr->inv_filter_costs);
-#endif
-
#ifdef PNG_SETJMP_SUPPORTED
/* Reset structure */
png_memcpy(tmp_jmp, png_ptr->longjmp_buffer, png_sizeof(jmp_buf));
@@ -1029,6 +1030,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
case 5:
case 6:
case 7: png_warning(png_ptr, "Unknown row filter for method 0");
+ /* FALL THROUGH */
#endif /* PNG_WRITE_FILTER_SUPPORTED */
case PNG_FILTER_VALUE_NONE:
png_ptr->do_filter = PNG_FILTER_NONE; break;
@@ -1065,6 +1067,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
*/
if (png_ptr->row_buf != NULL)
{
+ png_ptr->do_filter = PNG_FILTER_NONE;
#ifdef PNG_WRITE_FILTER_SUPPORTED
if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL)
{
@@ -1125,8 +1128,8 @@ png_set_filter(png_structp png_ptr, int method, int filters)
}
if (png_ptr->do_filter == PNG_NO_FILTERS)
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
png_ptr->do_filter = PNG_FILTER_NONE;
+#endif /* PNG_WRITE_FILTER_SUPPORTED */
}
}
else
@@ -1140,122 +1143,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
* filtered data going to zlib more consistent, hopefully resulting in
* better compression.
*/
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */
-/* Convenience reset API. */
-static void
-png_reset_filter_heuristics(png_structp png_ptr)
-{
- /* Clear out any old values in the 'weights' - this must be done because if
- * the app calls set_filter_heuristics multiple times with different
- * 'num_weights' values we would otherwise potentially have wrong sized
- * arrays.
- */
- png_ptr->num_prev_filters = 0;
- png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED;
- if (png_ptr->prev_filters != NULL)
- {
- png_bytep old = png_ptr->prev_filters;
- png_ptr->prev_filters = NULL;
- png_free(png_ptr, old);
- }
- if (png_ptr->filter_weights != NULL)
- {
- png_uint_16p old = png_ptr->filter_weights;
- png_ptr->filter_weights = NULL;
- png_free(png_ptr, old);
- }
-
- if (png_ptr->inv_filter_weights != NULL)
- {
- png_uint_16p old = png_ptr->inv_filter_weights;
- png_ptr->inv_filter_weights = NULL;
- png_free(png_ptr, old);
- }
-
- /* Leave the filter_costs - this array is fixed size. */
-}
-
-static int
-png_init_filter_heuristics(png_structp png_ptr, int heuristic_method,
- int num_weights)
-{
- if (png_ptr == NULL)
- return 0;
-
- /* Clear out the arrays */
- png_reset_filter_heuristics(png_ptr);
-
- /* Check arguments; the 'reset' function makes the correct settings for the
- * unweighted case, but we must handle the weight case by initializing the
- * arrays for the caller.
- */
- if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int i;
-
- if (num_weights > 0)
- {
- png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_byte) * num_weights));
-
- /* To make sure that the weighting starts out fairly */
- for (i = 0; i < num_weights; i++)
- {
- png_ptr->prev_filters[i] = 255;
- }
-
- png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
-
- png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
-
- for (i = 0; i < num_weights; i++)
- {
- png_ptr->inv_filter_weights[i] =
- png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
- }
-
- /* Safe to set this now */
- png_ptr->num_prev_filters = (png_byte)num_weights;
- }
-
- /* If, in the future, there are other filter methods, this would
- * need to be based on png_ptr->filter.
- */
- if (png_ptr->filter_costs == NULL)
- {
- png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
-
- png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
- }
-
- for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
- {
- png_ptr->inv_filter_costs[i] =
- png_ptr->filter_costs[i] = PNG_COST_FACTOR;
- }
-
- /* All the arrays are inited, safe to set this: */
- png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_WEIGHTED;
-
- /* Return the 'ok' code. */
- return 1;
- }
- else if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT ||
- heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED)
- {
- return 1;
- }
- else
- {
- png_warning(png_ptr, "Unknown filter heuristic method");
- return 0;
- }
-}
-
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */
/* Provide floating and fixed point APIs */
#ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
@@ -1263,52 +1151,11 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
int num_weights, png_const_doublep filter_weights,
png_const_doublep filter_costs)
{
- png_debug(1, "in png_set_filter_heuristics");
-
- /* The internal API allocates all the arrays and ensures that the elements of
- * those arrays are set to the default value.
- */
- if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights))
- return;
-
- /* If using the weighted method copy in the weights. */
- if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int i;
- for (i = 0; i < num_weights; i++)
- {
- if (filter_weights[i] <= 0.0)
- {
- png_ptr->inv_filter_weights[i] =
- png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
- }
-
- else
- {
- png_ptr->inv_filter_weights[i] =
- (png_uint_16)(PNG_WEIGHT_FACTOR*filter_weights[i]+.5);
-
- png_ptr->filter_weights[i] =
- (png_uint_16)(PNG_WEIGHT_FACTOR/filter_weights[i]+.5);
- }
- }
-
- /* Here is where we set the relative costs of the different filters. We
- * should take the desired compression level into account when setting
- * the costs, so that Paeth, for instance, has a high relative cost at low
- * compression levels, while it has a lower relative cost at higher
- * compression settings. The filter types are in order of increasing
- * relative cost, so it would be possible to do this with an algorithm.
- */
- for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) if (filter_costs[i] >= 1.0)
- {
- png_ptr->inv_filter_costs[i] =
- (png_uint_16)(PNG_COST_FACTOR / filter_costs[i] + .5);
-
- png_ptr->filter_costs[i] =
- (png_uint_16)(PNG_COST_FACTOR * filter_costs[i] + .5);
- }
- }
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(heuristic_method)
+ PNG_UNUSED(num_weights)
+ PNG_UNUSED(filter_weights)
+ PNG_UNUSED(filter_costs)
}
#endif /* FLOATING_POINT */
@@ -1318,67 +1165,16 @@ png_set_filter_heuristics_fixed(png_structp png_ptr, int heuristic_method,
int num_weights, png_const_fixed_point_p filter_weights,
png_const_fixed_point_p filter_costs)
{
- png_debug(1, "in png_set_filter_heuristics_fixed");
-
- /* The internal API allocates all the arrays and ensures that the elements of
- * those arrays are set to the default value.
- */
- if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights))
- return;
-
- /* If using the weighted method copy in the weights. */
- if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int i;
- for (i = 0; i < num_weights; i++)
- {
- if (filter_weights[i] <= 0)
- {
- png_ptr->inv_filter_weights[i] =
- png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
- }
-
- else
- {
- png_ptr->inv_filter_weights[i] = (png_uint_16)
- ((PNG_WEIGHT_FACTOR*filter_weights[i]+PNG_FP_HALF)/PNG_FP_1);
-
- png_ptr->filter_weights[i] = (png_uint_16)((PNG_WEIGHT_FACTOR*
- PNG_FP_1+(filter_weights[i]/2))/filter_weights[i]);
- }
- }
-
- /* Here is where we set the relative costs of the different filters. We
- * should take the desired compression level into account when setting
- * the costs, so that Paeth, for instance, has a high relative cost at low
- * compression levels, while it has a lower relative cost at higher
- * compression settings. The filter types are in order of increasing
- * relative cost, so it would be possible to do this with an algorithm.
- */
- for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
- if (filter_costs[i] >= PNG_FP_1)
- {
- png_uint_32 tmp;
-
- /* Use a 32 bit unsigned temporary here because otherwise the
- * intermediate value will be a 32 bit *signed* integer (ANSI rules)
- * and this will get the wrong answer on division.
- */
- tmp = PNG_COST_FACTOR*PNG_FP_1 + (filter_costs[i]/2);
- tmp /= filter_costs[i];
-
- png_ptr->inv_filter_costs[i] = (png_uint_16)tmp;
-
- tmp = PNG_COST_FACTOR * filter_costs[i] + PNG_FP_HALF;
- tmp /= PNG_FP_1;
-
- png_ptr->filter_costs[i] = (png_uint_16)tmp;
- }
- }
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(heuristic_method)
+ PNG_UNUSED(num_weights)
+ PNG_UNUSED(filter_weights)
+ PNG_UNUSED(filter_costs)
}
#endif /* FIXED_POINT */
-#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
+#endif /* WRITE_WEIGHTED_FILTER */
+#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
void PNGAPI
png_set_compression_level(png_structp png_ptr, int level)
{
@@ -1457,6 +1253,7 @@ png_set_compression_method(png_structp png_ptr, int method)
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
png_ptr->zlib_method = method;
}
+#endif /* WRITE_CUSTOMIZE_COMPRESSION */
/* The following were added to libpng-1.5.4 */
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
@@ -1514,10 +1311,10 @@ png_set_text_compression_window_bits(png_structp png_ptr, int window_bits)
#ifndef WBITS_8_OK
/* Avoid libpng bug with 256-byte windows */
if (window_bits == 8)
- {
- png_warning(png_ptr, "Text compression window is being reset to 512");
- window_bits = 9;
- }
+ {
+ png_warning(png_ptr, "Text compression window is being reset to 512");
+ window_bits = 9;
+ }
#endif
png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS;
diff --git a/drivers/png/pngwtran.c b/drivers/png/pngwtran.c
index 96608efcb4..24c436ffe4 100644
--- a/drivers/png/pngwtran.c
+++ b/drivers/png/pngwtran.c
@@ -1,8 +1,8 @@
/* pngwtran.c - transforms the data in a row for PNG writers
*
- * Last changed in libpng 1.5.6 [November 3, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2012 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -45,8 +45,20 @@ png_do_write_transformations(png_structp png_ptr, png_row_infop row_info)
#ifdef PNG_WRITE_FILLER_SUPPORTED
if (png_ptr->transformations & PNG_FILLER)
- png_do_strip_channel(row_info, png_ptr->row_buf + 1,
- !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
+ {
+ if (png_ptr->color_type & (PNG_COLOR_MASK_ALPHA|PNG_COLOR_MASK_PALETTE))
+ {
+ /* GA, RGBA or palette; in any of these cases libpng will not do the
+ * the correct thing (whatever that might be).
+ */
+ png_warning(png_ptr, "incorrect png_set_filler call ignored");
+ png_ptr->transformations &= ~PNG_FILLER;
+ }
+
+ else
+ png_do_strip_channel(row_info, png_ptr->row_buf + 1,
+ !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
+ }
#endif
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
diff --git a/drivers/png/pngwutil.c b/drivers/png/pngwutil.c
index da18e9502e..d5f097fb97 100644
--- a/drivers/png/pngwutil.c
+++ b/drivers/png/pngwutil.c
@@ -1,8 +1,8 @@
/* pngwutil.c - utilities to write a PNG file
*
- * Last changed in libpng 1.5.6 [November 3, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.26 [December 17, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -30,19 +30,20 @@ png_save_uint_32(png_bytep buf, png_uint_32 i)
}
#ifdef PNG_SAVE_INT_32_SUPPORTED
-/* The png_save_int_32 function assumes integers are stored in two's
- * complement format. If this isn't the case, then this routine needs to
- * be modified to write data in two's complement format. Note that,
- * the following works correctly even if png_int_32 has more than 32 bits
- * (compare the more complex code required on read for sign extention.)
+/* PNG signed integers are saved in 32-bit 2's complement format. ANSI C-90
+ * defines a cast of a signed integer to an unsigned integer either to preserve
+ * the value, if it is positive, or to calculate:
+ *
+ * (UNSIGNED_MAX+1) + integer
+ *
+ * Where UNSIGNED_MAX is the appropriate maximum unsigned value, so when the
+ * negative integral value is added the result will be an unsigned value
+ * correspnding to the 2's complement representation.
*/
void PNGAPI
png_save_int_32(png_bytep buf, png_int_32 i)
{
- buf[0] = (png_byte)((i >> 24) & 0xff);
- buf[1] = (png_byte)((i >> 16) & 0xff);
- buf[2] = (png_byte)((i >> 8) & 0xff);
- buf[3] = (png_byte)(i & 0xff);
+ png_save_uint_32(buf, i);
}
#endif
@@ -315,6 +316,7 @@ png_zlib_release(png_structp png_ptr)
if (ret != Z_OK)
{
+#ifdef PNG_WARNINGS_SUPPORTED
png_const_charp err;
PNG_WARNING_PARAMETERS(p)
@@ -349,6 +351,7 @@ png_zlib_release(png_structp png_ptr)
png_formatted_warning(png_ptr, p,
"zlib failed to reset compressor: @1(@2): @3");
+#endif
}
}
@@ -460,24 +463,21 @@ png_text_compress(png_structp png_ptr,
old_ptr = comp->output_ptr;
comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
- (png_alloc_size_t)
- (comp->max_output_ptr * png_sizeof(png_charpp)));
+ (comp->max_output_ptr * png_sizeof(png_bytep)));
png_memcpy(comp->output_ptr, old_ptr, old_max
- * png_sizeof(png_charp));
+ * png_sizeof(png_bytep));
png_free(png_ptr, old_ptr);
}
else
comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
- (png_alloc_size_t)
- (comp->max_output_ptr * png_sizeof(png_charp)));
+ (comp->max_output_ptr * png_sizeof(png_bytep)));
}
/* Save the data */
comp->output_ptr[comp->num_output_ptr] =
- (png_bytep)png_malloc(png_ptr,
- (png_alloc_size_t)png_ptr->zbuf_size);
+ (png_bytep)png_malloc(png_ptr, png_ptr->zbuf_size);
png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
png_ptr->zbuf_size);
@@ -569,14 +569,15 @@ png_text_compress(png_structp png_ptr,
/* Ship the compressed text out via chunk writes */
static void /* PRIVATE */
-png_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
+png_write_compressed_data_out(png_structp png_ptr, compression_state *comp,
+ png_size_t data_len)
{
int i;
/* Handle the no-compression case */
if (comp->input)
{
- png_write_chunk_data(png_ptr, comp->input, comp->input_len);
+ png_write_chunk_data(png_ptr, comp->input, data_len);
return;
}
@@ -585,7 +586,7 @@ png_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
/* The zbuf_size test is because the code below doesn't work if zbuf_size is
* '1'; simply skip it to avoid memory overwrite.
*/
- if (comp->input_len >= 2 && comp->input_len < 16384 && png_ptr->zbuf_size > 1)
+ if (data_len >= 2 && comp->input_len < 16384 && png_ptr->zbuf_size > 1)
{
unsigned int z_cmf; /* zlib compression method and flags */
@@ -825,7 +826,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
png_ptr->zstream.zfree = png_zfree;
png_ptr->zstream.opaque = (voidpf)png_ptr;
- if (!(png_ptr->do_filter))
+ if ((png_ptr->do_filter) == PNG_NO_FILTERS)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
png_ptr->bit_depth < 8)
@@ -895,17 +896,20 @@ void /* PRIVATE */
png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
png_uint_32 num_pal)
{
- png_uint_32 i;
+ png_uint_32 max_palette_length, i;
png_const_colorp pal_ptr;
png_byte buf[3];
png_debug(1, "in png_write_PLTE");
+ max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
+ (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
+
if ((
#ifdef PNG_MNG_FEATURES_SUPPORTED
!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
#endif
- num_pal == 0) || num_pal > 256)
+ num_pal == 0) || num_pal > max_palette_length)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
@@ -1095,7 +1099,6 @@ png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type,
png_const_charp profile, int profile_len)
{
png_size_t name_len;
- png_charp new_name;
compression_state comp;
int embedded_profile_len = 0;
@@ -1107,8 +1110,7 @@ png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type,
comp.input = NULL;
comp.input_len = 0;
- if ((name_len = png_check_keyword(png_ptr, name, &new_name)) == 0)
- return;
+ name_len = png_strlen(name);
if (compression_type != PNG_COMPRESSION_TYPE_BASE)
png_warning(png_ptr, "Unknown compression type in iCCP chunk");
@@ -1127,8 +1129,6 @@ png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type,
{
png_warning(png_ptr,
"Embedded profile length in iCCP chunk is negative");
-
- png_free(png_ptr, new_name);
return;
}
@@ -1136,8 +1136,6 @@ png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type,
{
png_warning(png_ptr,
"Embedded profile length too large in iCCP chunk");
-
- png_free(png_ptr, new_name);
return;
}
@@ -1149,7 +1147,7 @@ png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type,
profile_len = embedded_profile_len;
}
- if (profile_len)
+ if (profile_len != 0)
profile_len = png_text_compress(png_ptr, profile,
(png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp);
@@ -1157,19 +1155,21 @@ png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type,
png_write_chunk_header(png_ptr, png_iCCP,
(png_uint_32)(name_len + profile_len + 2));
- new_name[name_len + 1] = 0x00;
+ png_write_chunk_data(png_ptr, (png_bytep)name, name_len);
- png_write_chunk_data(png_ptr, (png_bytep)new_name,
- (png_size_t)(name_len + 2));
+ {
+ png_byte buffer[2];
+ buffer[0] = 0; /* terminate name */
+ buffer[1] = 0xFFU & compression_type;
+ png_write_chunk_data(png_ptr, buffer, 2);
+ }
- if (profile_len)
+ if (profile_len != 0)
{
- comp.input_len = profile_len;
- png_write_compressed_data_out(png_ptr, &comp);
+ png_write_compressed_data_out(png_ptr, &comp, profile_len);
}
png_write_chunk_end(png_ptr);
- png_free(png_ptr, new_name);
}
#endif
@@ -1179,7 +1179,6 @@ void /* PRIVATE */
png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
{
png_size_t name_len;
- png_charp new_name;
png_byte entrybuf[10];
png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
png_size_t palette_size = entry_size * spalette->nentries;
@@ -1190,14 +1189,13 @@ png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
png_debug(1, "in png_write_sPLT");
- if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0)
- return;
+ name_len = png_strlen(spalette->name);
/* Make sure we include the NULL after the name */
png_write_chunk_header(png_ptr, png_sPLT,
(png_uint_32)(name_len + 2 + palette_size));
- png_write_chunk_data(png_ptr, (png_bytep)new_name,
+ png_write_chunk_data(png_ptr, (png_bytep)spalette->name,
(png_size_t)(name_len + 1));
png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1);
@@ -1253,7 +1251,6 @@ png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
#endif
png_write_chunk_end(png_ptr);
- png_free(png_ptr, new_name);
}
#endif
@@ -1370,7 +1367,8 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
}
/* Write the chunk out as it is */
- png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, (png_size_t)num_trans);
+ png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha,
+ (png_size_t)num_trans);
}
else if (color_type == PNG_COLOR_TYPE_GRAY)
@@ -1508,138 +1506,6 @@ png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist)
}
#endif
-#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
- defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
-/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
- * and if invalid, correct the keyword rather than discarding the entire
- * chunk. The PNG 1.0 specification requires keywords 1-79 characters in
- * length, forbids leading or trailing whitespace, multiple internal spaces,
- * and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
- *
- * The new_key is allocated to hold the corrected keyword and must be freed
- * by the calling routine. This avoids problems with trying to write to
- * static keywords without having to have duplicate copies of the strings.
- */
-png_size_t /* PRIVATE */
-png_check_keyword(png_structp png_ptr, png_const_charp key, png_charpp new_key)
-{
- png_size_t key_len;
- png_const_charp ikp;
- png_charp kp, dp;
- int kflag;
- int kwarn=0;
-
- png_debug(1, "in png_check_keyword");
-
- *new_key = NULL;
-
- if (key == NULL || (key_len = png_strlen(key)) == 0)
- {
- png_warning(png_ptr, "zero length keyword");
- return ((png_size_t)0);
- }
-
- png_debug1(2, "Keyword to be checked is '%s'", key);
-
- *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
-
- if (*new_key == NULL)
- {
- png_warning(png_ptr, "Out of memory while procesing keyword");
- return ((png_size_t)0);
- }
-
- /* Replace non-printing characters with a blank and print a warning */
- for (ikp = key, dp = *new_key; *ikp != '\0'; ikp++, dp++)
- {
- if ((png_byte)*ikp < 0x20 ||
- ((png_byte)*ikp > 0x7E && (png_byte)*ikp < 0xA1))
- {
- PNG_WARNING_PARAMETERS(p)
-
- png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_02x,
- (png_byte)*ikp);
- png_formatted_warning(png_ptr, p, "invalid keyword character 0x@1");
- *dp = ' ';
- }
-
- else
- {
- *dp = *ikp;
- }
- }
- *dp = '\0';
-
- /* Remove any trailing white space. */
- kp = *new_key + key_len - 1;
- if (*kp == ' ')
- {
- png_warning(png_ptr, "trailing spaces removed from keyword");
-
- while (*kp == ' ')
- {
- *(kp--) = '\0';
- key_len--;
- }
- }
-
- /* Remove any leading white space. */
- kp = *new_key;
- if (*kp == ' ')
- {
- png_warning(png_ptr, "leading spaces removed from keyword");
-
- while (*kp == ' ')
- {
- kp++;
- key_len--;
- }
- }
-
- png_debug1(2, "Checking for multiple internal spaces in '%s'", kp);
-
- /* Remove multiple internal spaces. */
- for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
- {
- if (*kp == ' ' && kflag == 0)
- {
- *(dp++) = *kp;
- kflag = 1;
- }
-
- else if (*kp == ' ')
- {
- key_len--;
- kwarn = 1;
- }
-
- else
- {
- *(dp++) = *kp;
- kflag = 0;
- }
- }
- *dp = '\0';
- if (kwarn)
- png_warning(png_ptr, "extra interior spaces removed from keyword");
-
- if (key_len == 0)
- {
- png_free(png_ptr, *new_key);
- png_warning(png_ptr, "Zero length keyword");
- }
-
- if (key_len > 79)
- {
- png_warning(png_ptr, "keyword length must be 1 - 79 characters");
- (*new_key)[79] = '\0';
- key_len = 79;
- }
-
- return (key_len);
-}
-#endif
-
#ifdef PNG_WRITE_tEXt_SUPPORTED
/* Write a tEXt chunk */
void /* PRIVATE */
@@ -1647,12 +1513,10 @@ png_write_tEXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
png_size_t text_len)
{
png_size_t key_len;
- png_charp new_key;
png_debug(1, "in png_write_tEXt");
- if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
- return;
+ key_len = strlen(key);
if (text == NULL || *text == '\0')
text_len = 0;
@@ -1669,15 +1533,14 @@ png_write_tEXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
* any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
* The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
*/
- png_write_chunk_data(png_ptr, (png_bytep)new_key,
+ png_write_chunk_data(png_ptr, (png_bytep)key,
(png_size_t)(key_len + 1));
- if (text_len)
+ if (text_len != 0)
png_write_chunk_data(png_ptr, (png_const_bytep)text,
(png_size_t)text_len);
png_write_chunk_end(png_ptr);
- png_free(png_ptr, new_key);
}
#endif
@@ -1689,7 +1552,6 @@ png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
{
png_size_t key_len;
png_byte buf;
- png_charp new_key;
compression_state comp;
png_debug(1, "in png_write_zTXt");
@@ -1700,16 +1562,11 @@ png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
comp.input = NULL;
comp.input_len = 0;
- if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
- {
- png_free(png_ptr, new_key);
- return;
- }
+ key_len = strlen(key);
if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
{
- png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
- png_free(png_ptr, new_key);
+ png_write_tEXt(png_ptr, key, text, (png_size_t)0);
return;
}
@@ -1724,19 +1581,16 @@ png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
(png_uint_32)(key_len+text_len + 2));
/* Write key */
- png_write_chunk_data(png_ptr, (png_bytep)new_key,
+ png_write_chunk_data(png_ptr, (png_bytep)key,
(png_size_t)(key_len + 1));
- png_free(png_ptr, new_key);
-
buf = (png_byte)compression;
/* Write compression */
png_write_chunk_data(png_ptr, &buf, (png_size_t)1);
/* Write the compressed data */
- comp.input_len = text_len;
- png_write_compressed_data_out(png_ptr, &comp);
+ png_write_compressed_data_out(png_ptr, &comp, text_len);
/* Close the chunk */
png_write_chunk_end(png_ptr);
@@ -1750,8 +1604,6 @@ png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key,
png_const_charp lang, png_const_charp lang_key, png_const_charp text)
{
png_size_t lang_len, key_len, lang_key_len, text_len;
- png_charp new_lang;
- png_charp new_key = NULL;
png_byte cbuf[2];
compression_state comp;
@@ -1762,15 +1614,13 @@ png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key,
comp.output_ptr = NULL;
comp.input = NULL;
- if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
- return;
+ key_len = png_strlen(key);
- if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang)) == 0)
- {
- png_warning(png_ptr, "Empty language field in iTXt chunk");
- new_lang = NULL;
+ if (lang == NULL)
lang_len = 0;
- }
+
+ else
+ lang_len = png_strlen(lang);
if (lang_key == NULL)
lang_key_len = 0;
@@ -1805,7 +1655,7 @@ png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key,
* any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
* The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
*/
- png_write_chunk_data(png_ptr, (png_bytep)new_key, (png_size_t)(key_len + 1));
+ png_write_chunk_data(png_ptr, (png_bytep)key, (png_size_t)(key_len + 1));
/* Set the compression flag */
if (compression == PNG_ITXT_COMPRESSION_NONE ||
@@ -1821,18 +1671,15 @@ png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key,
png_write_chunk_data(png_ptr, cbuf, (png_size_t)2);
cbuf[0] = 0;
- png_write_chunk_data(png_ptr, (new_lang ? (png_const_bytep)new_lang : cbuf),
+ png_write_chunk_data(png_ptr, (lang ? (png_const_bytep)lang : cbuf),
(png_size_t)(lang_len + 1));
png_write_chunk_data(png_ptr, (lang_key ? (png_const_bytep)lang_key : cbuf),
(png_size_t)(lang_key_len + 1));
- png_write_compressed_data_out(png_ptr, &comp);
+ png_write_compressed_data_out(png_ptr, &comp, text_len);
png_write_chunk_end(png_ptr);
-
- png_free(png_ptr, new_key);
- png_free(png_ptr, new_lang);
}
#endif
@@ -1866,7 +1713,6 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
png_size_t purpose_len, units_len, total_len;
png_size_tp params_len;
png_byte buf[10];
- png_charp new_purpose;
int i;
png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
@@ -1874,7 +1720,7 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
if (type >= PNG_EQUATION_LAST)
png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
- purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
+ purpose_len = strlen(purpose) + 1;
png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
png_debug1(3, "pCAL units length = %d", (int)units_len);
@@ -1896,7 +1742,7 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
png_debug1(3, "pCAL total length = %d", (int)total_len);
png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len);
- png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose, purpose_len);
+ png_write_chunk_data(png_ptr, (png_const_bytep)purpose, purpose_len);
png_save_int_32(buf, X0);
png_save_int_32(buf + 4, X1);
buf[8] = (png_byte)type;
@@ -1904,8 +1750,6 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
png_write_chunk_data(png_ptr, buf, (png_size_t)10);
png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len);
- png_free(png_ptr, new_purpose);
-
for (i = 0; i < nparams; i++)
{
png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]);
@@ -2430,20 +2274,9 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
png_uint_32 mins, bpp;
png_byte filter_to_do = png_ptr->do_filter;
png_size_t row_bytes = row_info->rowbytes;
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- int num_p_filters = png_ptr->num_prev_filters;
-#endif
png_debug(1, "in png_write_find_filter");
-#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
- {
- /* These will never be selected so we need not test them. */
- filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
- }
-#endif
-
/* Find out how many bytes offset each pixel is */
bpp = (row_info->pixel_depth + 7) >> 3;
@@ -2495,44 +2328,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
sum += (v < 128) ? v : 256 - v;
}
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- png_uint_32 sumhi, sumlo;
- int j;
- sumlo = sum & PNG_LOMASK;
- sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
-
- /* Reduce the sum if we match any of the previous rows */
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
- {
- sumlo = (sumlo * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- /* Factor in the cost of this filter (this is here for completeness,
- * but it makes no sense to have a "cost" for the NONE filter, as
- * it has the minimum possible computational cost - none).
- */
- sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
- PNG_COST_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
- PNG_COST_SHIFT;
-
- if (sumhi > PNG_HIMASK)
- sum = PNG_MAXSUM;
-
- else
- sum = (sumhi << PNG_HISHIFT) + sumlo;
- }
-#endif
mins = sum;
}
@@ -2565,44 +2360,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
png_size_t i;
int v;
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- /* We temporarily increase the "minimum sum" by the factor we
- * would reduce the sum of this filter, so that we can do the
- * early exit comparison without scaling the sum each time.
- */
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 lmhi, lmlo;
- lmlo = lmins & PNG_LOMASK;
- lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
- {
- lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
- PNG_COST_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
- PNG_COST_SHIFT;
-
- if (lmhi > PNG_HIMASK)
- lmins = PNG_MAXSUM;
-
- else
- lmins = (lmhi << PNG_HISHIFT) + lmlo;
- }
-#endif
-
for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
i++, rp++, dp++)
{
@@ -2622,40 +2379,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
break;
}
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 sumhi, sumlo;
- sumlo = sum & PNG_LOMASK;
- sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
- {
- sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
- PNG_COST_SHIFT;
-
- sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
- PNG_COST_SHIFT;
-
- if (sumhi > PNG_HIMASK)
- sum = PNG_MAXSUM;
-
- else
- sum = (sumhi << PNG_HISHIFT) + sumlo;
- }
-#endif
-
if (sum < mins)
{
mins = sum;
@@ -2686,41 +2409,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
png_size_t i;
int v;
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 lmhi, lmlo;
- lmlo = lmins & PNG_LOMASK;
- lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
- {
- lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
- PNG_COST_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
- PNG_COST_SHIFT;
-
- if (lmhi > PNG_HIMASK)
- lmins = PNG_MAXSUM;
-
- else
- lmins = (lmhi << PNG_HISHIFT) + lmlo;
- }
-#endif
-
for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
pp = prev_row + 1; i < row_bytes; i++)
{
@@ -2732,40 +2420,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
break;
}
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 sumhi, sumlo;
- sumlo = sum & PNG_LOMASK;
- sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
- {
- sumlo = (sumlo * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
- PNG_COST_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
- PNG_COST_SHIFT;
-
- if (sumhi > PNG_HIMASK)
- sum = PNG_MAXSUM;
-
- else
- sum = (sumhi << PNG_HISHIFT) + sumlo;
- }
-#endif
-
if (sum < mins)
{
mins = sum;
@@ -2800,40 +2454,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
png_size_t i;
int v;
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 lmhi, lmlo;
- lmlo = lmins & PNG_LOMASK;
- lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
- {
- lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
- PNG_COST_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
- PNG_COST_SHIFT;
-
- if (lmhi > PNG_HIMASK)
- lmins = PNG_MAXSUM;
-
- else
- lmins = (lmhi << PNG_HISHIFT) + lmlo;
- }
-#endif
-
for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
pp = prev_row + 1; i < bpp; i++)
{
@@ -2853,40 +2473,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
break;
}
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 sumhi, sumlo;
- sumlo = sum & PNG_LOMASK;
- sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
- {
- sumlo = (sumlo * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
- PNG_COST_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
- PNG_COST_SHIFT;
-
- if (sumhi > PNG_HIMASK)
- sum = PNG_MAXSUM;
-
- else
- sum = (sumhi << PNG_HISHIFT) + sumlo;
- }
-#endif
-
if (sum < mins)
{
mins = sum;
@@ -2941,40 +2527,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
png_size_t i;
int v;
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 lmhi, lmlo;
- lmlo = lmins & PNG_LOMASK;
- lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
- {
- lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
- PNG_COST_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
- PNG_COST_SHIFT;
-
- if (lmhi > PNG_HIMASK)
- lmins = PNG_MAXSUM;
-
- else
- lmins = (lmhi << PNG_HISHIFT) + lmlo;
- }
-#endif
-
for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
pp = prev_row + 1; i < bpp; i++)
{
@@ -3028,40 +2580,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
break;
}
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 sumhi, sumlo;
- sumlo = sum & PNG_LOMASK;
- sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
- {
- sumlo = (sumlo * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
- PNG_COST_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
- PNG_COST_SHIFT;
-
- if (sumhi > PNG_HIMASK)
- sum = PNG_MAXSUM;
-
- else
- sum = (sumhi << PNG_HISHIFT) + sumlo;
- }
-#endif
-
if (sum < mins)
{
best_row = png_ptr->paeth_row;
@@ -3071,26 +2589,8 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
/* Do the actual writing of the filtered row data from the chosen filter. */
png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1);
-
-#ifdef PNG_WRITE_FILTER_SUPPORTED
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- /* Save the type of filter we picked this time for future calculations */
- if (png_ptr->num_prev_filters > 0)
- {
- int j;
-
- for (j = 1; j < num_p_filters; j++)
- {
- png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
- }
-
- png_ptr->prev_filters[j] = best_row[0];
- }
-#endif
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
}
-
/* Do the actual writing of a previously filtered row. */
static void
png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp
index 581efb5adc..b91329c8da 100644
--- a/drivers/png/resource_saver_png.cpp
+++ b/drivers/png/resource_saver_png.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/pnm/SCsub b/drivers/pnm/SCsub
new file mode 100644
index 0000000000..28b35773a4
--- /dev/null
+++ b/drivers/pnm/SCsub
@@ -0,0 +1,10 @@
+Import('env')
+
+
+pnm_sources = [
+ "pnm/bitmap_loader_pnm.cpp"
+ ]
+
+env.drivers_sources+=pnm_sources
+
+#env.add_source_files(env.drivers_sources, pnm_sources)
diff --git a/drivers/pnm/bitmap_loader_pnm.cpp b/drivers/pnm/bitmap_loader_pnm.cpp
new file mode 100644
index 0000000000..c9298be26a
--- /dev/null
+++ b/drivers/pnm/bitmap_loader_pnm.cpp
@@ -0,0 +1,235 @@
+/*************************************************/
+/* image_loader_jpg.cpp */
+/*************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/*************************************************/
+/* Source code within this file is: */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
+/* All Rights Reserved. */
+/*************************************************/
+
+#include "bitmap_loader_pnm.h"
+#include "os/file_access.h"
+#include "scene/resources/bit_mask.h"
+
+
+static bool _get_token(FileAccessRef& f,uint8_t &saved,DVector<uint8_t>& r_token,bool p_binary=false,bool p_single_chunk=false) {
+
+
+ int token_max = r_token.size();
+ DVector<uint8_t>::Write w;
+ if (token_max)
+ w=r_token.write();
+ int ofs=0;
+ bool lf=false;
+
+
+ while(true) {
+
+ uint8_t b;
+ if (saved) {
+ b=saved;
+ saved=0;
+ } else {
+ b = f->get_8();
+ }
+ if (f->eof_reached()) {
+ if (ofs) {
+ w=DVector<uint8_t>::Write();
+ r_token.resize(ofs);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ if (!ofs && !p_binary && b=='#') {
+ //skip comment
+ while(b!='\n') {
+ if (f->eof_reached()) {
+ return false;
+ }
+
+ b = f->get_8();
+ }
+
+ lf=true;
+
+ } else if (b<=32 && !(p_binary && (ofs || lf))) {
+
+ if (b=='\n') {
+ lf=true;
+ }
+
+
+ if (ofs && !p_single_chunk) {
+ w=DVector<uint8_t>::Write();
+ r_token.resize(ofs);
+ saved=b;
+
+ return true;
+ }
+ } else {
+
+ bool resized=false;
+ while (ofs>=token_max) {
+ if (token_max)
+ token_max<<=1;
+ else
+ token_max=1;
+ resized=true;
+ }
+ if (resized) {
+ w=DVector<uint8_t>::Write();
+ r_token.resize(token_max);
+ w=r_token.write();
+ }
+ w[ofs++]=b;
+ }
+ }
+
+ return false;
+}
+
+static int _get_number_from_token(DVector<uint8_t>& r_token) {
+
+ int len = r_token.size();
+ DVector<uint8_t>::Read r = r_token.read();
+ return String::to_int((const char*)r.ptr(),len);
+
+}
+
+
+RES ResourceFormatPBM::load(const String &p_path,const String& p_original_path,Error *r_error) {
+
+#define _RETURN(m_err)\
+{\
+ if (r_error)\
+ *r_error=m_err;\
+ ERR_FAIL_V(RES());\
+}
+
+
+ FileAccessRef f=FileAccess::open(p_path,FileAccess::READ);
+ uint8_t saved=0;
+ if (!f)
+ _RETURN(ERR_CANT_OPEN);
+
+ DVector<uint8_t> token;
+
+ if (!_get_token(f,saved,token)) {
+ _RETURN(ERR_PARSE_ERROR);
+ }
+
+ if (token.size()!=2) {
+ _RETURN(ERR_FILE_CORRUPT);
+ }
+ if (token[0]!='P') {
+ _RETURN(ERR_FILE_CORRUPT);
+ }
+ if (token[1]!='1' && token[1]!='4') {
+ _RETURN(ERR_FILE_CORRUPT);
+ }
+
+ bool bits = token[1]=='4';
+
+ if (!_get_token(f,saved,token)) {
+ _RETURN(ERR_PARSE_ERROR);
+ }
+
+ int width = _get_number_from_token(token);
+ if (width<=0) {
+ _RETURN(ERR_FILE_CORRUPT);
+ }
+
+
+ if (!_get_token(f,saved,token)) {
+ _RETURN(ERR_PARSE_ERROR);
+ }
+
+ int height = _get_number_from_token(token);
+ if (height<=0) {
+ _RETURN(ERR_FILE_CORRUPT);
+ }
+
+
+ Ref<BitMap> bm;
+ bm.instance();
+ bm->create(Size2i(width,height));
+
+ if (!bits) {
+
+ int required_bytes = width*height;
+ if (!_get_token(f,saved,token,false,true)) {
+ _RETURN(ERR_PARSE_ERROR);
+ }
+
+ if (token.size()<required_bytes) {
+ _RETURN(ERR_FILE_CORRUPT);
+ }
+
+ DVector<uint8_t>::Read r=token.read();
+
+ for(int i=0;i<height;i++) {
+ for(int j=0;j<width;j++) {
+
+
+ char num = r[i*width+j];
+ bm->set_bit(Point2i(j,i),num=='0');
+ }
+
+ }
+
+
+
+ } else {
+ //a single, entire token of bits!
+ if (!_get_token(f,saved,token,true)) {
+ _RETURN(ERR_PARSE_ERROR);
+ }
+ int required_bytes = Math::ceil((width*height)/8.0);
+ if (token.size()<required_bytes) {
+ _RETURN(ERR_FILE_CORRUPT);
+ }
+
+ DVector<uint8_t>::Read r=token.read();
+ int bitwidth = width;
+ if (bitwidth % 8)
+ bitwidth+=8-(bitwidth%8);
+
+ for(int i=0;i<height;i++) {
+ for(int j=0;j<width;j++) {
+
+ int ofs = bitwidth*i+j;
+
+ uint8_t byte = r[ofs/8];
+ bool bit = (byte>>(7-(ofs%8)))&1;
+
+ bm->set_bit(Point2i(j,i),!bit);
+
+ }
+
+ }
+
+ }
+
+ return bm;
+
+
+}
+
+void ResourceFormatPBM::get_recognized_extensions(List<String> *p_extensions) const {
+ p_extensions->push_back("pbm");
+}
+bool ResourceFormatPBM::handles_type(const String& p_type) const {
+ return p_type=="BitMap";
+}
+String ResourceFormatPBM::get_resource_type(const String &p_path) const {
+
+ if (p_path.extension().to_lower()=="pbm")
+ return "BitMap";
+ return "";
+}
+
+
diff --git a/drivers/pnm/bitmap_loader_pnm.h b/drivers/pnm/bitmap_loader_pnm.h
new file mode 100644
index 0000000000..6e6c8a59c8
--- /dev/null
+++ b/drivers/pnm/bitmap_loader_pnm.h
@@ -0,0 +1,33 @@
+/*************************************************/
+/* image_loader_jpg.h */
+/*************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/*************************************************/
+/* Source code within this file is: */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
+/* All Rights Reserved. */
+/*************************************************/
+
+#ifndef BITMAP_LOADER_PNM_H
+#define BITMAP_LOADER_PNM_H
+
+#include "io/resource_loader.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class ResourceFormatPBM : public ResourceFormatLoader {
+
+
+public:
+
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String& p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+};
+
+
+
+#endif
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index 4cda141f92..813a95816b 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h
index e7c8bcce36..8a2fbfd38b 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.h
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/register_driver_types.cpp b/drivers/register_driver_types.cpp
index 11c4e7dd29..e7bbf28f01 100644
--- a/drivers/register_driver_types.cpp
+++ b/drivers/register_driver_types.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
@@ -14,11 +14,12 @@
#include "png/image_loader_png.h"
#include "webp/image_loader_webp.h"
#include "png/resource_saver_png.h"
-#include "jpg/image_loader_jpg.h"
+#include "jpegd/image_loader_jpegd.h"
#include "dds/texture_loader_dds.h"
#include "pvr/texture_loader_pvr.h"
#include "etc1/image_etc.h"
#include "chibi/event_stream_chibi.h"
+#include "pnm/bitmap_loader_pnm.h"
#ifdef TOOLS_ENABLED
@@ -112,6 +113,9 @@ static ResourceFormatLoaderAudioStreamMPC * mpc_stream_loader=NULL;
#include "openssl/register_openssl.h"
#endif
+
+static ResourceFormatPBM * pbm_loader=NULL;
+
void register_core_driver_types() {
#ifdef PNG_ENABLED
@@ -138,6 +142,9 @@ void register_core_driver_types() {
ImageLoader::add_image_format_loader( image_loader_jpg );
#endif
+ pbm_loader = memnew( ResourceFormatPBM );
+ ResourceLoader::add_resource_format_loader(pbm_loader);
+
ObjectTypeDB::register_type<RegEx>();
}
@@ -162,6 +169,7 @@ void unregister_core_driver_types() {
memdelete( image_loader_jpg );
#endif
+ memdelete( pbm_loader );
}
diff --git a/drivers/register_driver_types.h b/drivers/register_driver_types.h
index 9ae4b0be08..8a13ad4471 100644
--- a/drivers/register_driver_types.h
+++ b/drivers/register_driver_types.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/drivers/rtaudio/RtAudio.cpp b/drivers/rtaudio/RtAudio.cpp
index 72ca836907..86981e56d2 100644
--- a/drivers/rtaudio/RtAudio.cpp
+++ b/drivers/rtaudio/RtAudio.cpp
@@ -139,8 +139,7 @@ void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis ) throw()
void RtAudio :: openRtApi( RtAudio::Api api )
{
- if ( rtapi_ )
- delete rtapi_;
+ delete rtapi_;
rtapi_ = 0;
#if defined(__UNIX_JACK__)
@@ -216,8 +215,7 @@ RtAudio :: RtAudio( RtAudio::Api api )
RtAudio :: ~RtAudio() throw()
{
- if ( rtapi_ )
- delete rtapi_;
+ delete rtapi_;
}
void RtAudio :: openStream( RtAudio::StreamParameters *outputParameters,
diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp
index 7bee495869..335f4b632f 100644
--- a/drivers/rtaudio/audio_driver_rtaudio.cpp
+++ b/drivers/rtaudio/audio_driver_rtaudio.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/drivers/rtaudio/audio_driver_rtaudio.h b/drivers/rtaudio/audio_driver_rtaudio.h
index a16470d701..115953ce1f 100644
--- a/drivers/rtaudio/audio_driver_rtaudio.h
+++ b/drivers/rtaudio/audio_driver_rtaudio.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/drivers/theora/video_stream_theora.cpp b/drivers/theora/video_stream_theora.cpp
index f301bd7515..1d2e6b9dda 100644
--- a/drivers/theora/video_stream_theora.cpp
+++ b/drivers/theora/video_stream_theora.cpp
@@ -7,16 +7,47 @@
int VideoStreamPlaybackTheora:: buffer_data() {
- char *buffer=ogg_sync_buffer(&oy,4096);
- int bytes=file->get_buffer((uint8_t*)buffer, 4096);
- ogg_sync_wrote(&oy,bytes);
- return(bytes);
+ char *buffer=ogg_sync_buffer(&oy,4096);
+
+#ifdef THEORA_USE_THREAD_STREAMING
+
+ int read;
+
+ do {
+ thread_sem->post();
+ read = MIN(ring_buffer.data_left(),4096);
+ if (read) {
+ ring_buffer.read((uint8_t*)buffer,read);
+ ogg_sync_wrote(&oy,read);
+ } else {
+ OS::get_singleton()->delay_usec(100);
+ }
+
+ } while(read==0);
+
+ return read;
+
+#else
+
+ int bytes=file->get_buffer((uint8_t*)buffer, 4096);
+ ogg_sync_wrote(&oy,bytes);
+ return(bytes);
+
+#endif
}
int VideoStreamPlaybackTheora::queue_page(ogg_page *page){
- if(theora_p)ogg_stream_pagein(&to,page);
- if(vorbis_p)ogg_stream_pagein(&vo,page);
+ if(theora_p) {
+ ogg_stream_pagein(&to,page);
+ if (to.e_o_s)
+ theora_eos=true;
+ }
+ if(vorbis_p) {
+ ogg_stream_pagein(&vo,page);
+ if (vo.e_o_s)
+ vorbis_eos=true;
+ }
return 0;
}
@@ -200,6 +231,14 @@ void VideoStreamPlaybackTheora::clear() {
}
ogg_sync_clear(&oy);
+#ifdef THEORA_USE_THREAD_STREAMING
+ thread_exit=true;
+ thread_sem->post(); //just in case
+ Thread::wait_to_finish(thread);
+ memdelete(thread);
+ thread=NULL;
+ ring_buffer.clear();
+#endif
//file_name = "";
theora_p = 0;
@@ -207,6 +246,8 @@ void VideoStreamPlaybackTheora::clear() {
videobuf_ready = 0;
frames_pending = 0;
videobuf_time = 0;
+ theora_eos=false;
+ vorbis_eos=false;
if (file) {
memdelete(file);
@@ -217,6 +258,7 @@ void VideoStreamPlaybackTheora::clear() {
void VideoStreamPlaybackTheora::set_file(const String& p_file) {
+ ERR_FAIL_COND(playing);
ogg_packet op;
th_setup_info *ts = NULL;
@@ -227,7 +269,17 @@ void VideoStreamPlaybackTheora::set_file(const String& p_file) {
file = FileAccess::open(p_file, FileAccess::READ);
ERR_FAIL_COND(!file);
+#ifdef THEORA_USE_THREAD_STREAMING
+ thread_exit=false;
+ thread_eof=false;
+ //pre-fill buffer
+ int to_read = ring_buffer.space_left();
+ int read = file->get_buffer(read_buffer.ptr(),to_read);
+ ring_buffer.write(read_buffer.ptr(),read);
+ thread=Thread::create(_streaming_thread,this);
+
+#endif
ogg_sync_init(&oy);
@@ -239,6 +291,9 @@ void VideoStreamPlaybackTheora::set_file(const String& p_file) {
th_comment_init(&tc);
th_info_init(&ti);
+ theora_eos=false;
+ vorbis_eos=false;
+
/* Ogg file open; parse the headers */
/* Only interested in Vorbis/Theora streams */
int stateflag = 0;
@@ -369,6 +424,7 @@ void VideoStreamPlaybackTheora::set_file(const String& p_file) {
th_decode_ctl(td,TH_DECCTL_GET_PPLEVEL_MAX,&pp_level_max,
sizeof(pp_level_max));
pp_level=pp_level_max;
+ pp_level=0;
th_decode_ctl(td,TH_DECCTL_SET_PPLEVEL,&pp_level,sizeof(pp_level));
pp_inc=0;
@@ -415,6 +471,8 @@ void VideoStreamPlaybackTheora::set_file(const String& p_file) {
buffering=true;
time=0;
audio_frames_wrote=0;
+
+
};
float VideoStreamPlaybackTheora::get_time() const {
@@ -431,31 +489,42 @@ Ref<Texture> VideoStreamPlaybackTheora::get_texture() {
void VideoStreamPlaybackTheora::update(float p_delta) {
- if (!playing) {
+ if (!playing || paused) {
//printf("not playing\n");
return;
};
+
+
+#ifdef THEORA_USE_THREAD_STREAMING
+ thread_sem->post();
+#endif
+
//double ctime =AudioServer::get_singleton()->get_mix_time();
//print_line("play "+rtos(p_delta));
time+=p_delta;
if (videobuf_time>get_time()) {
-
return; //no new frames need to be produced
}
bool frame_done=false;
bool audio_done=false;
- while (!frame_done || !audio_done) {
+ bool theora_done=false;
+
+ while (!frame_done || (!audio_done && !vorbis_eos)) {
//a frame needs to be produced
ogg_packet op;
bool audio_pending = false;
+ bool no_vorbis=false;
+ bool no_theora=false;
+
+
while (vorbis_p) {
int ret;
float **pcm;
@@ -527,6 +596,7 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
}
} else { /* we need more data; break out to suck in another page */
//printf("need moar data\n");
+ no_vorbis=true;
break;
};
}
@@ -573,21 +643,28 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
if(videobuf_time>=get_time()) {
frame_done=true;
- print_line("frame!");
} else{
/*If we are too slow, reduce the pp level.*/
pp_inc=pp_level>0?-1:0;
- print_line("skip!");
}
+ } else {
+
}
} else {
- print_line("no packet..");
+ no_theora=true;
break;
}
}
- if (file && /*!videobuf_ready && */ file->eof_reached()) {
+
+ //print_line("no theora: "+itos(no_theora)+" theora eos: "+itos(theora_eos)+" frame done "+itos(frame_done));
+
+#ifdef THEORA_USE_THREAD_STREAMING
+ if (file && thread_eof && no_theora && theora_eos && ring_buffer.data_left()==0) {
+#else
+ if (file && /*!videobuf_ready && */ no_theora && theora_eos) {
+#endif
printf("video done, stopping\n");
stop();
return;
@@ -633,6 +710,7 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
else if(tdiff<ti.fps_denominator*0.05/ti.fps_numerator){
pp_inc=pp_level>0?-1:0;
}
+
}
video_write();
@@ -644,15 +722,21 @@ void VideoStreamPlaybackTheora::play() {
if (!playing)
time=0;
+ else {
+ stop();
+ }
+
playing = true;
delay_compensation=Globals::get_singleton()->get("audio/video_delay_compensation_ms");
delay_compensation/=1000.0;
+
};
void VideoStreamPlaybackTheora::stop() {
if (playing) {
+
clear();
set_file(file_name); //reset
}
@@ -667,12 +751,13 @@ bool VideoStreamPlaybackTheora::is_playing() const {
void VideoStreamPlaybackTheora::set_paused(bool p_paused) {
- playing = !p_paused;
+ paused=p_paused;
+ //pau = !p_paused;
};
bool VideoStreamPlaybackTheora::is_paused(bool p_paused) const {
- return playing;
+ return paused;
};
void VideoStreamPlaybackTheora::set_loop(bool p_enable) {
@@ -730,7 +815,33 @@ int VideoStreamPlaybackTheora::get_mix_rate() const{
return vi.rate;
}
+#ifdef THEORA_USE_THREAD_STREAMING
+
+
+void VideoStreamPlaybackTheora::_streaming_thread(void *ud) {
+
+ VideoStreamPlaybackTheora *vs=(VideoStreamPlaybackTheora*)ud;
+
+ while(!vs->thread_exit) {
+
+ //just fill back the buffer
+ if (!vs->thread_eof) {
+
+ int to_read = vs->ring_buffer.space_left();
+ if (to_read) {
+ int read = vs->file->get_buffer(vs->read_buffer.ptr(),to_read);
+ vs->ring_buffer.write(vs->read_buffer.ptr(),read);
+ vs->thread_eof=vs->file->eof_reached();
+ }
+
+
+ }
+ vs->thread_sem->wait();
+ }
+}
+
+#endif
VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() {
@@ -741,6 +852,7 @@ VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() {
playing = false;
frames_pending = 0;
videobuf_time = 0;
+ paused=false;
buffering=false;
texture = Ref<ImageTexture>( memnew(ImageTexture ));
@@ -749,14 +861,31 @@ VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() {
audio_track=0;
delay_compensation=0;
audio_frames_wrote=0;
+
+#ifdef THEORA_USE_THREAD_STREAMING
+ int rb_power = nearest_shift(RB_SIZE_KB*1024);
+ ring_buffer.resize(rb_power);
+ read_buffer.resize(RB_SIZE_KB*1024);
+ thread_sem=Semaphore::create();
+ thread=NULL;
+ thread_exit=false;
+ thread_eof=false;
+
+#endif
};
VideoStreamPlaybackTheora::~VideoStreamPlaybackTheora() {
+#ifdef THEORA_USE_THREAD_STREAMING
+
+ memdelete(thread_sem);
+#endif
clear();
if (file)
memdelete(file);
+
+
};
diff --git a/drivers/theora/video_stream_theora.h b/drivers/theora/video_stream_theora.h
index 5540f050f9..f07acb2935 100644
--- a/drivers/theora/video_stream_theora.h
+++ b/drivers/theora/video_stream_theora.h
@@ -6,9 +6,13 @@
#include "theora/theoradec.h"
#include "vorbis/codec.h"
#include "os/file_access.h"
-
+#include "ring_buffer.h"
#include "io/resource_loader.h"
#include "scene/resources/video_stream.h"
+#include "os/thread.h"
+#include "os/semaphore.h"
+
+//#define THEORA_USE_THREAD_STREAMING
class VideoStreamPlaybackTheora : public VideoStreamPlayback {
@@ -32,6 +36,8 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback {
void video_write(void);
float get_time() const;
+ bool theora_eos;
+ bool vorbis_eos;
ogg_sync_state oy;
ogg_page og;
@@ -65,8 +71,27 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback {
AudioMixCallback mix_callback;
void* mix_udata;
+ bool paused;
+
+#ifdef THEORA_USE_THREAD_STREAMING
+
+ enum {
+ RB_SIZE_KB=1024
+ };
+
+ RingBuffer<uint8_t> ring_buffer;
+ Vector<uint8_t> read_buffer;
+ bool thread_eof;
+ Semaphore *thread_sem;
+ Thread *thread;
+ volatile bool thread_exit;
+
+ static void _streaming_thread(void *ud);
+
+#endif
+
- int audio_track;
+ int audio_track;
protected:
@@ -116,20 +141,20 @@ class VideoStreamTheora : public VideoStream {
OBJ_TYPE(VideoStreamTheora,VideoStream);
String file;
- int audio_track;
+ int audio_track;
public:
Ref<VideoStreamPlayback> instance_playback() {
Ref<VideoStreamPlaybackTheora> pb = memnew( VideoStreamPlaybackTheora );
- pb->set_audio_track(audio_track);
+ pb->set_audio_track(audio_track);
pb->set_file(file);
return pb;
}
void set_file(const String& p_file) { file=p_file; }
- void set_audio_track(int p_track) { audio_track=p_track; }
+ void set_audio_track(int p_track) { audio_track=p_track; }
VideoStreamTheora() { audio_track=0; }
diff --git a/drivers/unix/SCsub b/drivers/unix/SCsub
index 9fbb467baa..3d46a85cdf 100644
--- a/drivers/unix/SCsub
+++ b/drivers/unix/SCsub
@@ -1,5 +1,15 @@
Import('env')
+g_set_p='#ifdef UNIX_ENABLED\n'
+g_set_p+='#include "os_unix.h"\n'
+g_set_p+='String OS_Unix::get_global_settings_path() const {\n'
+g_set_p+='\treturn "' + env["unix_global_settings_path"]+'";\n'
+g_set_p+='}\n'
+g_set_p+='#endif'
+f = open("os_unix_global_settings_path.cpp","wb")
+f.write(g_set_p)
+f.close()
+
env.add_source_files(env.drivers_sources,"*.cpp")
Export('env')
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index 0c0867e030..23a63be339 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
index 3091e01511..9cba1ed3e0 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 8e70ecc932..9f24633bd4 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -75,6 +75,8 @@ Error FileAccessUnix::_open(const String& p_path, int p_mode_flags) {
mode_string="wb";
else if (p_mode_flags==READ_WRITE)
mode_string="rb+";
+ else if (p_mode_flags==WRITE_READ)
+ mode_string="wb+";
else
return ERR_INVALID_PARAMETER;
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
index 6c41a51ec5..d6a172bf47 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
index 989aba52bb..535a425302 100644
--- a/drivers/unix/ip_unix.cpp
+++ b/drivers/unix/ip_unix.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h
index 5798ac8137..c0034c9a3a 100644
--- a/drivers/unix/ip_unix.h
+++ b/drivers/unix/ip_unix.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/unix/memory_pool_static_malloc.cpp b/drivers/unix/memory_pool_static_malloc.cpp
index e0bab27a63..1a79272dc1 100644
--- a/drivers/unix/memory_pool_static_malloc.cpp
+++ b/drivers/unix/memory_pool_static_malloc.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/unix/memory_pool_static_malloc.h b/drivers/unix/memory_pool_static_malloc.h
index a96259556d..78ad82ee22 100644
--- a/drivers/unix/memory_pool_static_malloc.h
+++ b/drivers/unix/memory_pool_static_malloc.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/unix/mutex_posix.cpp b/drivers/unix/mutex_posix.cpp
index 73563ea538..fb4fa4a891 100644
--- a/drivers/unix/mutex_posix.cpp
+++ b/drivers/unix/mutex_posix.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/unix/mutex_posix.h b/drivers/unix/mutex_posix.h
index 9b50d7963e..a1993be221 100644
--- a/drivers/unix/mutex_posix.h
+++ b/drivers/unix/mutex_posix.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index fd8c26f6d9..a004a116e0 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -78,11 +78,11 @@ void OS_Unix::print_error(const char* p_function,const char* p_file,int p_line,c
break;
case ERR_WARNING:
print("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n",p_function,err_details);
- print("\E[0;33m At: %s:%i.\E[0m\n",p_file,p_line);
+ print("\E[0;33m At: %s:%i.\E[0m\n",p_file,p_line);
break;
case ERR_SCRIPT:
print("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n",p_function,err_details);
- print("\E[0;35m At: %s:%i.\E[0m\n",p_file,p_line);
+ print("\E[0;35m At: %s:%i.\E[0m\n",p_file,p_line);
break;
}
}
@@ -149,8 +149,7 @@ void OS_Unix::finalize_core() {
if (mempool_dynamic)
memdelete( mempool_dynamic );
- if (mempool_static)
- delete mempool_static;
+ delete mempool_static;
}
@@ -233,13 +232,12 @@ uint64_t OS_Unix::get_unix_time() const {
return time(NULL);
};
-uint64_t OS_Unix::get_system_time_msec() const {
+uint64_t OS_Unix::get_system_time_secs() const {
struct timeval tv_now;
gettimeofday(&tv_now, NULL);
//localtime(&tv_now.tv_usec);
//localtime((const long *)&tv_now.tv_usec);
- uint64_t msec = uint64_t(tv_now.tv_sec)*1000+tv_now.tv_usec/1000;
- return msec;
+ return uint64_t(tv_now.tv_sec);
}
@@ -477,6 +475,14 @@ String OS_Unix::get_data_dir() const {
}
+String OS_Unix::get_installed_templates_path() const {
+ String p=get_global_settings_path();
+ if (p!="")
+ return p+"/templates/";
+ else
+ return "";
+}
+
String OS_Unix::get_executable_path() const {
#ifdef __linux__
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
index 2ee6102164..a889bba0ff 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -64,6 +64,8 @@ protected:
String stdin_buf;
+ String get_global_settings_path() const;
+
public:
@@ -93,7 +95,7 @@ public:
virtual TimeZoneInfo get_time_zone_info() const;
virtual uint64_t get_unix_time() const;
- virtual uint64_t get_system_time_msec() const;
+ virtual uint64_t get_system_time_secs() const;
virtual void delay_usec(uint32_t p_usec) const;
virtual uint64_t get_ticks_usec() const;
@@ -111,6 +113,7 @@ public:
virtual void debug_break();
+ virtual String get_installed_templates_path() const;
virtual String get_executable_path() const;
virtual String get_data_dir() const;
diff --git a/drivers/unix/semaphore_posix.cpp b/drivers/unix/semaphore_posix.cpp
index fba4cd3641..3ae94ae5d9 100644
--- a/drivers/unix/semaphore_posix.cpp
+++ b/drivers/unix/semaphore_posix.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,7 +42,7 @@ Error SemaphorePosix::wait() {
errno=0;
continue;
} else {
-perror("sem waiting");
+ perror("sem waiting");
return ERR_BUSY;
}
}
diff --git a/drivers/unix/semaphore_posix.h b/drivers/unix/semaphore_posix.h
index 6f938455b3..0a3cf36749 100644
--- a/drivers/unix/semaphore_posix.h
+++ b/drivers/unix/semaphore_posix.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp
index 5aa3915893..45a4b934c1 100644
--- a/drivers/unix/stream_peer_tcp_posix.cpp
+++ b/drivers/unix/stream_peer_tcp_posix.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -38,6 +38,7 @@
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
+#include <sys/ioctl.h>
#ifndef NO_FCNTL
#ifdef __HAIKU__
#include <fcntl.h>
@@ -367,6 +368,14 @@ Error StreamPeerTCPPosix::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r
return read(p_buffer, p_bytes, r_received, false);
};
+int StreamPeerTCPPosix::get_available_bytes() const {
+
+ unsigned long len;
+ int ret = ioctl(sockfd,FIONREAD,&len);
+ ERR_FAIL_COND_V(ret==-1,0)
+ return len;
+
+}
IP_Address StreamPeerTCPPosix::get_connected_host() const {
return peer_host;
diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h
index 9b1716ac42..a379efe3ca 100644
--- a/drivers/unix/stream_peer_tcp_posix.h
+++ b/drivers/unix/stream_peer_tcp_posix.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -67,6 +67,8 @@ public:
virtual Error get_data(uint8_t* p_buffer, int p_bytes);
virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received);
+ virtual int get_available_bytes() const;
+
void set_socket(int p_sockfd, IP_Address p_host, int p_port);
virtual IP_Address get_connected_host() const;
diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp
index aaca0fe0d8..98451957fd 100644
--- a/drivers/unix/tcp_server_posix.cpp
+++ b/drivers/unix/tcp_server_posix.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h
index 17a9fd1d98..570bcaab12 100644
--- a/drivers/unix/tcp_server_posix.h
+++ b/drivers/unix/tcp_server_posix.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp
index 03963a9756..bd33c81298 100644
--- a/drivers/unix/thread_posix.cpp
+++ b/drivers/unix/thread_posix.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,6 +30,10 @@
#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
+#ifdef PTHREAD_BSD_SET_NAME
+#include <pthread_np.h>
+#endif
+
#include "os/memory.h"
Thread::ID ThreadPosix::get_ID() const {
@@ -45,8 +49,8 @@ Thread* ThreadPosix::create_thread_posix() {
void *ThreadPosix::thread_callback(void *userdata) {
ThreadPosix *t=reinterpret_cast<ThreadPosix*>(userdata);
- t->callback(t->user);
t->id=(ID)pthread_self();
+ t->callback(t->user);
return NULL;
}
@@ -77,6 +81,42 @@ void ThreadPosix::wait_to_finish_func_posix(Thread* p_thread) {
tp->pthread=0;
}
+Error ThreadPosix::set_name(const String& p_name) {
+
+ ERR_FAIL_COND_V(pthread == 0, ERR_UNCONFIGURED);
+
+ #ifdef PTHREAD_NO_RENAME
+ return ERR_UNAVAILABLE;
+
+ #else
+
+ #ifdef PTHREAD_RENAME_SELF
+
+ // check if thread is the same as caller
+ int caller = Thread::get_caller_ID();
+ int self = get_ID();
+ if (caller != self) {
+ ERR_EXPLAIN("On this platform, thread can only be renamed with calls from the threads to be renamed.");
+ ERR_FAIL_V(ERR_UNAVAILABLE);
+ return ERR_UNAVAILABLE;
+ };
+ int err = pthread_setname_np(p_name.utf8().get_data());
+
+ #else
+
+ #ifdef PTHREAD_BSD_SET_NAME
+ pthread_set_name_np(pthread, p_name.utf8().get_data());
+ int err = 0; // Open/FreeBSD ignore errors in this function
+ #else
+ int err = pthread_setname_np(pthread, p_name.utf8().get_data());
+ #endif // PTHREAD_BSD_SET_NAME
+
+ #endif // PTHREAD_RENAME_SELF
+
+ return err == 0 ? OK : ERR_INVALID_PARAMETER;
+
+ #endif // PTHREAD_NO_RENAME
+};
void ThreadPosix::make_default() {
diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h
index 4f76f3d7b3..179d56d5bd 100644
--- a/drivers/unix/thread_posix.h
+++ b/drivers/unix/thread_posix.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -61,6 +61,7 @@ public:
virtual ID get_ID() const;
+ Error set_name(const String& p_name);
static void make_default();
diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.cpp b/drivers/vorbis/audio_stream_ogg_vorbis.cpp
index 9a60098526..4ce7940a01 100644
--- a/drivers/vorbis/audio_stream_ogg_vorbis.cpp
+++ b/drivers/vorbis/audio_stream_ogg_vorbis.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.h b/drivers/vorbis/audio_stream_ogg_vorbis.h
index 5dbada962a..bb4d521c1e 100644
--- a/drivers/vorbis/audio_stream_ogg_vorbis.h
+++ b/drivers/vorbis/audio_stream_ogg_vorbis.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/webp/SCsub b/drivers/webp/SCsub
index 5596edbe09..f65bd13dba 100644
--- a/drivers/webp/SCsub
+++ b/drivers/webp/SCsub
@@ -1,63 +1,115 @@
Import('env')
-
webp_sources = [
- "webp/mux/muxedit.c",
- "webp/mux/muxread.c",
- "webp/mux/muxinternal.c",
- "webp/mux/demux.c",
- "webp/enc/tree.c",
- "webp/enc/analysis.c",
- "webp/enc/backward_references.c",
- "webp/enc/alpha.c",
- "webp/enc/picture.c",
- "webp/enc/frame.c",
- "webp/enc/webpenc.c",
- "webp/enc/cost.c",
- "webp/enc/filter.c",
- "webp/enc/vp8l.c",
- "webp/enc/quant.c",
- "webp/enc/histogram.c",
- "webp/enc/syntax.c",
- "webp/enc/config.c",
- "webp/enc/layer.c",
- "webp/enc/iterator.c",
- "webp/dsp/dec_sse2.c",
- "webp/dsp/upsampling_sse2.c",
- "webp/dsp/dec_neon.c",
- "webp/dsp/enc.c",
- "webp/dsp/enc_sse2.c",
- "webp/dsp/upsampling.c",
- "webp/dsp/lossless.c",
- "webp/dsp/cpu.c",
- "webp/dsp/dec.c",
- "webp/dsp/yuv.c",
- "webp/utils/bit_reader.c",
- "webp/utils/filters.c",
- "webp/utils/bit_writer.c",
- "webp/utils/thread.c",
- "webp/utils/quant_levels.c",
- "webp/utils/color_cache.c",
- "webp/utils/rescaler.c",
- "webp/utils/utils.c",
- "webp/utils/huffman.c",
- "webp/utils/huffman_encode.c",
- "webp/dec/tree.c",
- "webp/dec/alpha.c",
- "webp/dec/frame.c",
- "webp/dec/vp8l.c",
- "webp/dec/vp8.c",
- "webp/dec/quant.c",
- "webp/dec/webp.c",
- "webp/dec/buffer.c",
- "webp/dec/io.c",
- "webp/dec/layer.c",
- "webp/dec/idec.c",
- "webp/image_loader_webp.cpp"
+"webp/enc/webpenc.c",\
+"webp/enc/near_lossless.c",\
+"webp/enc/frame.c",\
+"webp/enc/alpha.c",\
+"webp/enc/picture_csp.c",\
+"webp/enc/vp8l.c",\
+"webp/enc/picture_psnr.c",\
+"webp/enc/delta_palettization.c",\
+"webp/enc/syntax.c",\
+"webp/enc/backward_references.c",\
+"webp/enc/token.c",\
+"webp/enc/analysis.c",\
+"webp/enc/iterator.c",\
+"webp/enc/picture_tools.c",\
+"webp/enc/picture_rescale.c",\
+"webp/enc/config.c",\
+"webp/enc/tree.c",\
+"webp/enc/cost.c",\
+"webp/enc/picture.c",\
+"webp/enc/quant.c",\
+"webp/enc/filter.c",\
+"webp/enc/histogram.c",\
+"webp/image_loader_webp.cpp",\
+"webp/utils/rescaler.c",\
+"webp/utils/filters.c",\
+"webp/utils/quant_levels_dec.c",\
+"webp/utils/huffman.c",\
+"webp/utils/thread.c",\
+"webp/utils/quant_levels.c",\
+"webp/utils/bit_writer.c",\
+"webp/utils/bit_reader.c",\
+"webp/utils/random.c",\
+"webp/utils/utils.c",\
+"webp/utils/huffman_encode.c",\
+"webp/utils/color_cache.c",\
+"webp/mux/muxinternal.c",\
+"webp/mux/muxread.c",\
+"webp/mux/anim_encode.c",\
+"webp/mux/muxedit.c",\
+"webp/dec/webp.c",\
+"webp/dec/frame.c",\
+"webp/dec/alpha.c",\
+"webp/dec/vp8l.c",\
+"webp/dec/io.c",\
+"webp/dec/vp8.c",\
+"webp/dec/idec.c",\
+"webp/dec/tree.c",\
+"webp/dec/buffer.c",\
+"webp/dec/quant.c",\
+"webp/demux/demux.c",\
+"webp/demux/anim_decode.c",\
+"webp/dsp/yuv.c",\
+"webp/dsp/filters_sse2.c",\
+"webp/dsp/dec_sse41.c",\
+"webp/dsp/rescaler.c",\
+"webp/dsp/lossless_sse2.c",\
+"webp/dsp/alpha_processing_sse41.c",\
+"webp/dsp/alpha_processing_sse2.c",\
+"webp/dsp/filters.c",\
+"webp/dsp/upsampling_mips_dsp_r2.c",\
+"webp/dsp/dec_neon.c",\
+"webp/dsp/enc_neon.c",\
+"webp/dsp/lossless_enc_mips32.c",\
+"webp/dsp/lossless_enc_sse2.c",\
+"webp/dsp/upsampling.c",\
+"webp/dsp/lossless_enc_neon.c",\
+"webp/dsp/alpha_processing.c",\
+"webp/dsp/cost_sse2.c",\
+"webp/dsp/dec_mips32.c",\
+"webp/dsp/enc_avx2.c",\
+"webp/dsp/rescaler_mips32.c",\
+"webp/dsp/enc.c",\
+"webp/dsp/lossless_enc_sse41.c",\
+"webp/dsp/cost_mips32.c",\
+"webp/dsp/lossless_mips_dsp_r2.c",\
+"webp/dsp/filters_mips_dsp_r2.c",\
+"webp/dsp/upsampling_neon.c",\
+"webp/dsp/alpha_processing_mips_dsp_r2.c",\
+"webp/dsp/enc_mips_dsp_r2.c",\
+"webp/dsp/lossless.c",\
+"webp/dsp/yuv_mips_dsp_r2.c",\
+"webp/dsp/cost_mips_dsp_r2.c",\
+"webp/dsp/argb.c",\
+"webp/dsp/dec_sse2.c",\
+"webp/dsp/rescaler_sse2.c",\
+"webp/dsp/enc_sse41.c",\
+"webp/dsp/argb_mips_dsp_r2.c",\
+"webp/dsp/lossless_enc_mips_dsp_r2.c",\
+"webp/dsp/dec_clip_tables.c",\
+"webp/dsp/yuv_mips32.c",\
+"webp/dsp/cpu.c",\
+"webp/dsp/dec.c",\
+"webp/dsp/argb_sse2.c",\
+"webp/dsp/lossless_neon.c",\
+"webp/dsp/lossless_enc.c",\
+"webp/dsp/enc_mips32.c",\
+"webp/dsp/cost.c",\
+"webp/dsp/rescaler_mips_dsp_r2.c",\
+"webp/dsp/dec_mips_dsp_r2.c",\
+"webp/dsp/rescaler_neon.c",\
+"webp/dsp/yuv_sse2.c",\
+"webp/dsp/enc_sse2.c",\
+"webp/dsp/upsampling_sse2.c"
]
env.drivers_sources+=webp_sources
#env.add_source_files(env.drivers_sources, webp_sources)
+
Export('env')
+
diff --git a/drivers/webp/config.h b/drivers/webp/config.h
new file mode 100644
index 0000000000..d85e5d1da6
--- /dev/null
+++ b/drivers/webp/config.h
@@ -0,0 +1,145 @@
+/* src/webp/config.h. Generated from config.h.in by configure. */
+/* src/webp/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define if building universal (internal helper macro) */
+/* #undef AC_APPLE_UNIVERSAL_BUILD */
+
+/* Set to 1 if __builtin_bswap16 is available */
+#define HAVE_BUILTIN_BSWAP16 1
+
+/* Set to 1 if __builtin_bswap32 is available */
+#define HAVE_BUILTIN_BSWAP32 1
+
+/* Set to 1 if __builtin_bswap64 is available */
+#define HAVE_BUILTIN_BSWAP64 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <GLUT/glut.h> header file. */
+/* #undef HAVE_GLUT_GLUT_H */
+
+/* Define to 1 if you have the <GL/glut.h> header file. */
+#define HAVE_GL_GLUT_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <OpenGL/glut.h> header file. */
+/* #undef HAVE_OPENGL_GLUT_H */
+
+/* Have PTHREAD_PRIO_INHERIT. */
+#define HAVE_PTHREAD_PRIO_INHERIT 1
+
+/* Define to 1 if you have the <shlwapi.h> header file. */
+/* #undef HAVE_SHLWAPI_H */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <wincodec.h> header file. */
+/* #undef HAVE_WINCODEC_H */
+
+/* Define to 1 if you have the <windows.h> header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Name of package */
+#define PACKAGE "libwebp"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "http://code.google.com/p/webp/issues"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "libwebp"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "libwebp 0.4.4"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "libwebp"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL "http://developers.google.com/speed/webp"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.4.4"
+
+/* Define to necessary symbol if this constant uses a non-standard name on
+ your system. */
+/* #undef PTHREAD_CREATE_JOINABLE */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "0.4.4"
+
+/* Enable experimental code */
+/* #undef WEBP_EXPERIMENTAL_FEATURES */
+
+/* Define to 1 to force aligned memory operations */
+/* #undef WEBP_FORCE_ALIGNED */
+
+/* Set to 1 if AVX2 is supported */
+#define WEBP_HAVE_AVX2 1
+
+/* Set to 1 if GIF library is installed */
+/* #undef WEBP_HAVE_GIF */
+
+/* Set to 1 if OpenGL is supported */
+#define WEBP_HAVE_GL 1
+
+/* Set to 1 if JPEG library is installed */
+/* #undef WEBP_HAVE_JPEG */
+
+/* Set to 1 if PNG library is installed */
+#define WEBP_HAVE_PNG 1
+
+/* Set to 1 if SSE2 is supported */
+#define WEBP_HAVE_SSE2 1
+
+/* Set to 1 if SSE4.1 is supported */
+#define WEBP_HAVE_SSE41 1
+
+/* Set to 1 if TIFF library is installed */
+/* #undef WEBP_HAVE_TIFF */
+
+/* Undefine this to disable thread support. */
+#define WEBP_USE_THREAD 1
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+/* # undef WORDS_BIGENDIAN */
+# endif
+#endif
diff --git a/drivers/webp/dec/alpha.c b/drivers/webp/dec/alpha.c
index d1095fa555..1d029b0e6a 100644
--- a/drivers/webp/dec/alpha.c
+++ b/drivers/webp/dec/alpha.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Alpha-plane decompression.
@@ -10,131 +12,156 @@
// Author: Skal (pascal.massimino@gmail.com)
#include <stdlib.h>
+#include "./alphai.h"
#include "./vp8i.h"
#include "./vp8li.h"
-#include "../utils/filters.h"
-#include "../utils/quant_levels.h"
-#include "../format_constants.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-// TODO(skal): move to dsp/ ?
-static void CopyPlane(const uint8_t* src, int src_stride,
- uint8_t* dst, int dst_stride, int width, int height) {
- while (height-- > 0) {
- memcpy(dst, src, width);
- src += src_stride;
- dst += dst_stride;
+#include "../dsp/dsp.h"
+#include "../utils/quant_levels_dec.h"
+#include "../utils/utils.h"
+#include "webp/format_constants.h"
+
+//------------------------------------------------------------------------------
+// ALPHDecoder object.
+
+ALPHDecoder* ALPHNew(void) {
+ ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
+ return dec;
+}
+
+void ALPHDelete(ALPHDecoder* const dec) {
+ if (dec != NULL) {
+ VP8LDelete(dec->vp8l_dec_);
+ dec->vp8l_dec_ = NULL;
+ WebPSafeFree(dec);
}
}
//------------------------------------------------------------------------------
-// Decodes the compressed data 'data' of size 'data_size' into the 'output'.
-// The 'output' buffer should be pre-allocated and must be of the same
-// dimension 'height'x'stride', as that of the image.
-//
-// Returns 1 on successfully decoding the compressed alpha and
-// 0 if either:
-// error in bit-stream header (invalid compression mode or filter), or
-// error returned by appropriate compression method.
-
-static int DecodeAlpha(const uint8_t* data, size_t data_size,
- int width, int height, int stride, uint8_t* output) {
- uint8_t* decoded_data = NULL;
- const size_t decoded_size = height * width;
- uint8_t* unfiltered_data = NULL;
- WEBP_FILTER_TYPE filter;
- int pre_processing;
- int rsrv;
+// Decoding.
+
+// Initialize alpha decoding by parsing the alpha header and decoding the image
+// header for alpha data stored using lossless compression.
+// Returns false in case of error in alpha header (data too short, invalid
+// compression method or filter, error in lossless header data etc).
+static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
+ size_t data_size, int width, int height, uint8_t* output) {
int ok = 0;
- int method;
+ const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN;
+ const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN;
+ int rsrv;
- assert(width > 0 && height > 0 && stride >= width);
+ assert(width > 0 && height > 0);
assert(data != NULL && output != NULL);
+ dec->width_ = width;
+ dec->height_ = height;
+
if (data_size <= ALPHA_HEADER_LEN) {
return 0;
}
- method = (data[0] >> 0) & 0x03;
- filter = (data[0] >> 2) & 0x03;
- pre_processing = (data[0] >> 4) & 0x03;
+ dec->method_ = (data[0] >> 0) & 0x03;
+ dec->filter_ = (data[0] >> 2) & 0x03;
+ dec->pre_processing_ = (data[0] >> 4) & 0x03;
rsrv = (data[0] >> 6) & 0x03;
- if (method < ALPHA_NO_COMPRESSION ||
- method > ALPHA_LOSSLESS_COMPRESSION ||
- filter >= WEBP_FILTER_LAST ||
- pre_processing > ALPHA_PREPROCESSED_LEVELS ||
+ if (dec->method_ < ALPHA_NO_COMPRESSION ||
+ dec->method_ > ALPHA_LOSSLESS_COMPRESSION ||
+ dec->filter_ >= WEBP_FILTER_LAST ||
+ dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS ||
rsrv != 0) {
return 0;
}
- if (method == ALPHA_NO_COMPRESSION) {
- ok = (data_size >= decoded_size);
- decoded_data = (uint8_t*)data + ALPHA_HEADER_LEN;
+ if (dec->method_ == ALPHA_NO_COMPRESSION) {
+ const size_t alpha_decoded_size = dec->width_ * dec->height_;
+ ok = (alpha_data_size >= alpha_decoded_size);
} else {
- decoded_data = (uint8_t*)malloc(decoded_size);
- if (decoded_data == NULL) return 0;
- ok = VP8LDecodeAlphaImageStream(width, height,
- data + ALPHA_HEADER_LEN,
- data_size - ALPHA_HEADER_LEN,
- decoded_data);
+ assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION);
+ ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size, output);
}
+ VP8FiltersInit();
+ return ok;
+}
- if (ok) {
- WebPFilterFunc unfilter_func = WebPUnfilters[filter];
- if (unfilter_func != NULL) {
- unfiltered_data = (uint8_t*)malloc(decoded_size);
- if (unfiltered_data == NULL) {
- ok = 0;
- goto Error;
- }
- // TODO(vikas): Implement on-the-fly decoding & filter mechanism to decode
- // and apply filter per image-row.
- unfilter_func(decoded_data, width, height, 1, width, unfiltered_data);
- // Construct raw_data (height x stride) from alpha data (height x width).
- CopyPlane(unfiltered_data, width, output, stride, width, height);
- free(unfiltered_data);
- } else {
- // Construct raw_data (height x stride) from alpha data (height x width).
- CopyPlane(decoded_data, width, output, stride, width, height);
- }
- if (pre_processing == ALPHA_PREPROCESSED_LEVELS) {
- ok = DequantizeLevels(decoded_data, width, height);
+// Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha
+// starting from row number 'row'. It assumes that rows up to (row - 1) have
+// already been decoded.
+// Returns false in case of bitstream error.
+static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
+ ALPHDecoder* const alph_dec = dec->alph_dec_;
+ const int width = alph_dec->width_;
+ const int height = alph_dec->height_;
+ WebPUnfilterFunc unfilter_func = WebPUnfilters[alph_dec->filter_];
+ uint8_t* const output = dec->alpha_plane_;
+ if (alph_dec->method_ == ALPHA_NO_COMPRESSION) {
+ const size_t offset = row * width;
+ const size_t num_pixels = num_rows * width;
+ assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN + offset + num_pixels);
+ memcpy(dec->alpha_plane_ + offset,
+ dec->alpha_data_ + ALPHA_HEADER_LEN + offset, num_pixels);
+ } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION
+ assert(alph_dec->vp8l_dec_ != NULL);
+ if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) {
+ return 0;
}
}
- Error:
- if (method != ALPHA_NO_COMPRESSION) {
- free(decoded_data);
+ if (unfilter_func != NULL) {
+ unfilter_func(width, height, width, row, num_rows, output);
}
- return ok;
+
+ if (row + num_rows == dec->pic_hdr_.height_) {
+ dec->is_alpha_decoded_ = 1;
+ }
+ return 1;
}
//------------------------------------------------------------------------------
+// Main entry point.
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
int row, int num_rows) {
- const int stride = dec->pic_hdr_.width_;
+ const int width = dec->pic_hdr_.width_;
+ const int height = dec->pic_hdr_.height_;
- if (row < 0 || num_rows < 0 || row + num_rows > dec->pic_hdr_.height_) {
+ if (row < 0 || num_rows <= 0 || row + num_rows > height) {
return NULL; // sanity check.
}
if (row == 0) {
- // Decode everything during the first call.
- if (!DecodeAlpha(dec->alpha_data_, (size_t)dec->alpha_data_size_,
- dec->pic_hdr_.width_, dec->pic_hdr_.height_, stride,
- dec->alpha_plane_)) {
- return NULL; // Error.
+ // Initialize decoding.
+ assert(dec->alpha_plane_ != NULL);
+ dec->alph_dec_ = ALPHNew();
+ if (dec->alph_dec_ == NULL) return NULL;
+ if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_,
+ width, height, dec->alpha_plane_)) {
+ ALPHDelete(dec->alph_dec_);
+ dec->alph_dec_ = NULL;
+ return NULL;
+ }
+ // if we allowed use of alpha dithering, check whether it's needed at all
+ if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) {
+ dec->alpha_dithering_ = 0; // disable dithering
+ } else {
+ num_rows = height; // decode everything in one pass
}
}
+ if (!dec->is_alpha_decoded_) {
+ int ok = 0;
+ assert(dec->alph_dec_ != NULL);
+ ok = ALPHDecode(dec, row, num_rows);
+ if (ok && dec->alpha_dithering_ > 0) {
+ ok = WebPDequantizeLevels(dec->alpha_plane_, width, height,
+ dec->alpha_dithering_);
+ }
+ if (!ok || dec->is_alpha_decoded_) {
+ ALPHDelete(dec->alph_dec_);
+ dec->alph_dec_ = NULL;
+ }
+ if (!ok) return NULL; // Error.
+ }
+
// Return a pointer to the current decoded row.
- return dec->alpha_plane_ + row * stride;
+ return dec->alpha_plane_ + row * width;
}
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/dec/alphai.h b/drivers/webp/dec/alphai.h
new file mode 100644
index 0000000000..5fa230ca82
--- /dev/null
+++ b/drivers/webp/dec/alphai.h
@@ -0,0 +1,55 @@
+// Copyright 2013 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Alpha decoder: internal header.
+//
+// Author: Urvang (urvang@google.com)
+
+#ifndef WEBP_DEC_ALPHAI_H_
+#define WEBP_DEC_ALPHAI_H_
+
+#include "./webpi.h"
+#include "../utils/filters.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct VP8LDecoder; // Defined in dec/vp8li.h.
+
+typedef struct ALPHDecoder ALPHDecoder;
+struct ALPHDecoder {
+ int width_;
+ int height_;
+ int method_;
+ WEBP_FILTER_TYPE filter_;
+ int pre_processing_;
+ struct VP8LDecoder* vp8l_dec_;
+ VP8Io io_;
+ int use_8b_decode; // Although alpha channel requires only 1 byte per
+ // pixel, sometimes VP8LDecoder may need to allocate
+ // 4 bytes per pixel internally during decode.
+};
+
+//------------------------------------------------------------------------------
+// internal functions. Not public.
+
+// Allocates a new alpha decoder instance.
+ALPHDecoder* ALPHNew(void);
+
+// Clears and deallocates an alpha decoder instance.
+void ALPHDelete(ALPHDecoder* const dec);
+
+//------------------------------------------------------------------------------
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_DEC_ALPHAI_H_ */
diff --git a/drivers/webp/dec/buffer.c b/drivers/webp/dec/buffer.c
index c159f6f248..9ed2b3fe1a 100644
--- a/drivers/webp/dec/buffer.c
+++ b/drivers/webp/dec/buffer.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Everything about WebPDecBuffer
@@ -15,10 +17,6 @@
#include "./webpi.h"
#include "../utils/utils.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
//------------------------------------------------------------------------------
// WebPDecBuffer
@@ -35,6 +33,11 @@ static int IsValidColorspace(int webp_csp_mode) {
return (webp_csp_mode >= MODE_RGB && webp_csp_mode < MODE_LAST);
}
+// strictly speaking, the very last (or first, if flipped) row
+// doesn't require padding.
+#define MIN_BUFFER_SIZE(WIDTH, HEIGHT, STRIDE) \
+ (uint64_t)(STRIDE) * ((HEIGHT) - 1) + (WIDTH)
+
static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
int ok = 1;
const WEBP_CSP_MODE mode = buffer->colorspace;
@@ -44,33 +47,41 @@ static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
ok = 0;
} else if (!WebPIsRGBMode(mode)) { // YUV checks
const WebPYUVABuffer* const buf = &buffer->u.YUVA;
- const uint64_t y_size = (uint64_t)buf->y_stride * height;
- const uint64_t u_size = (uint64_t)buf->u_stride * ((height + 1) / 2);
- const uint64_t v_size = (uint64_t)buf->v_stride * ((height + 1) / 2);
- const uint64_t a_size = (uint64_t)buf->a_stride * height;
+ const int uv_width = (width + 1) / 2;
+ const int uv_height = (height + 1) / 2;
+ const int y_stride = abs(buf->y_stride);
+ const int u_stride = abs(buf->u_stride);
+ const int v_stride = abs(buf->v_stride);
+ const int a_stride = abs(buf->a_stride);
+ const uint64_t y_size = MIN_BUFFER_SIZE(width, height, y_stride);
+ const uint64_t u_size = MIN_BUFFER_SIZE(uv_width, uv_height, u_stride);
+ const uint64_t v_size = MIN_BUFFER_SIZE(uv_width, uv_height, v_stride);
+ const uint64_t a_size = MIN_BUFFER_SIZE(width, height, a_stride);
ok &= (y_size <= buf->y_size);
ok &= (u_size <= buf->u_size);
ok &= (v_size <= buf->v_size);
- ok &= (buf->y_stride >= width);
- ok &= (buf->u_stride >= (width + 1) / 2);
- ok &= (buf->v_stride >= (width + 1) / 2);
+ ok &= (y_stride >= width);
+ ok &= (u_stride >= uv_width);
+ ok &= (v_stride >= uv_width);
ok &= (buf->y != NULL);
ok &= (buf->u != NULL);
ok &= (buf->v != NULL);
if (mode == MODE_YUVA) {
- ok &= (buf->a_stride >= width);
+ ok &= (a_stride >= width);
ok &= (a_size <= buf->a_size);
ok &= (buf->a != NULL);
}
} else { // RGB checks
const WebPRGBABuffer* const buf = &buffer->u.RGBA;
- const uint64_t size = (uint64_t)buf->stride * height;
+ const int stride = abs(buf->stride);
+ const uint64_t size = MIN_BUFFER_SIZE(width, height, stride);
ok &= (size <= buf->size);
- ok &= (buf->stride >= width * kModeBpp[mode]);
+ ok &= (stride >= width * kModeBpp[mode]);
ok &= (buf->rgba != NULL);
}
return ok ? VP8_STATUS_OK : VP8_STATUS_INVALID_PARAM;
}
+#undef MIN_BUFFER_SIZE
static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) {
const int w = buffer->width;
@@ -133,9 +144,35 @@ static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) {
return CheckDecBuffer(buffer);
}
+VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer) {
+ if (buffer == NULL) {
+ return VP8_STATUS_INVALID_PARAM;
+ }
+ if (WebPIsRGBMode(buffer->colorspace)) {
+ WebPRGBABuffer* const buf = &buffer->u.RGBA;
+ buf->rgba += (buffer->height - 1) * buf->stride;
+ buf->stride = -buf->stride;
+ } else {
+ WebPYUVABuffer* const buf = &buffer->u.YUVA;
+ const int H = buffer->height;
+ buf->y += (H - 1) * buf->y_stride;
+ buf->y_stride = -buf->y_stride;
+ buf->u += ((H - 1) >> 1) * buf->u_stride;
+ buf->u_stride = -buf->u_stride;
+ buf->v += ((H - 1) >> 1) * buf->v_stride;
+ buf->v_stride = -buf->v_stride;
+ if (buf->a != NULL) {
+ buf->a += (H - 1) * buf->a_stride;
+ buf->a_stride = -buf->a_stride;
+ }
+ }
+ return VP8_STATUS_OK;
+}
+
VP8StatusCode WebPAllocateDecBuffer(int w, int h,
const WebPDecoderOptions* const options,
WebPDecBuffer* const out) {
+ VP8StatusCode status;
if (out == NULL || w <= 0 || h <= 0) {
return VP8_STATUS_INVALID_PARAM;
}
@@ -152,18 +189,28 @@ VP8StatusCode WebPAllocateDecBuffer(int w, int h,
h = ch;
}
if (options->use_scaling) {
- if (options->scaled_width <= 0 || options->scaled_height <= 0) {
+ int scaled_width = options->scaled_width;
+ int scaled_height = options->scaled_height;
+ if (!WebPRescalerGetScaledDimensions(
+ w, h, &scaled_width, &scaled_height)) {
return VP8_STATUS_INVALID_PARAM;
}
- w = options->scaled_width;
- h = options->scaled_height;
+ w = scaled_width;
+ h = scaled_height;
}
}
out->width = w;
out->height = h;
- // Then, allocate buffer for real
- return AllocateBuffer(out);
+ // Then, allocate buffer for real.
+ status = AllocateBuffer(out);
+ if (status != VP8_STATUS_OK) return status;
+
+ // Use the stride trick if vertical flip is needed.
+ if (options != NULL && options->flip) {
+ status = WebPFlipBuffer(out);
+ }
+ return status;
}
//------------------------------------------------------------------------------
@@ -180,8 +227,9 @@ int WebPInitDecBufferInternal(WebPDecBuffer* buffer, int version) {
void WebPFreeDecBuffer(WebPDecBuffer* buffer) {
if (buffer != NULL) {
- if (!buffer->is_external_memory)
- free(buffer->private_memory);
+ if (!buffer->is_external_memory) {
+ WebPSafeFree(buffer->private_memory);
+ }
buffer->private_memory = NULL;
}
}
@@ -210,6 +258,3 @@ void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst) {
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/dec/common.h b/drivers/webp/dec/common.h
new file mode 100644
index 0000000000..6961e22470
--- /dev/null
+++ b/drivers/webp/dec/common.h
@@ -0,0 +1,54 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Definitions and macros common to encoding and decoding
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_DEC_COMMON_H_
+#define WEBP_DEC_COMMON_H_
+
+// intra prediction modes
+enum { B_DC_PRED = 0, // 4x4 modes
+ B_TM_PRED = 1,
+ B_VE_PRED = 2,
+ B_HE_PRED = 3,
+ B_RD_PRED = 4,
+ B_VR_PRED = 5,
+ B_LD_PRED = 6,
+ B_VL_PRED = 7,
+ B_HD_PRED = 8,
+ B_HU_PRED = 9,
+ NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10
+
+ // Luma16 or UV modes
+ DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED,
+ H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED,
+ B_PRED = NUM_BMODES, // refined I4x4 mode
+ NUM_PRED_MODES = 4,
+
+ // special modes
+ B_DC_PRED_NOTOP = 4,
+ B_DC_PRED_NOLEFT = 5,
+ B_DC_PRED_NOTOPLEFT = 6,
+ NUM_B_DC_MODES = 7 };
+
+enum { MB_FEATURE_TREE_PROBS = 3,
+ NUM_MB_SEGMENTS = 4,
+ NUM_REF_LF_DELTAS = 4,
+ NUM_MODE_LF_DELTAS = 4, // I4x4, ZERO, *, SPLIT
+ MAX_NUM_PARTITIONS = 8,
+ // Probabilities
+ NUM_TYPES = 4, // 0: i16-AC, 1: i16-DC, 2:chroma-AC, 3:i4-AC
+ NUM_BANDS = 8,
+ NUM_CTX = 3,
+ NUM_PROBAS = 11
+ };
+
+#endif // WEBP_DEC_COMMON_H_
diff --git a/drivers/webp/dec/decode_vp8.h b/drivers/webp/dec/decode_vp8.h
index c26a9fc891..2bf1bdbbf5 100644
--- a/drivers/webp/dec/decode_vp8.h
+++ b/drivers/webp/dec/decode_vp8.h
@@ -1,8 +1,10 @@
// Copyright 2010 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Low-level API for VP8 decoder
@@ -12,9 +14,9 @@
#ifndef WEBP_WEBP_DECODE_VP8_H_
#define WEBP_WEBP_DECODE_VP8_H_
-#include "../decode.h"
+#include "webp/decode.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
@@ -130,7 +132,8 @@ static WEBP_INLINE int VP8InitIo(VP8Io* const io) {
return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION);
}
-// Start decoding a new picture. Returns true if ok.
+// Decode the VP8 frame header. Returns true if ok.
+// Note: 'io->data' must be pointing to the start of the VP8 frame header.
int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io);
// Decode a picture. Will call VP8GetHeaders() if it wasn't done already.
@@ -175,7 +178,7 @@ WEBP_EXTERN(int) VP8LGetInfo(
const uint8_t* data, size_t data_size, // data available so far
int* const width, int* const height, int* const has_alpha);
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/dec/frame.c b/drivers/webp/dec/frame.c
index 9c91a48e17..b882133eab 100644
--- a/drivers/webp/dec/frame.c
+++ b/drivers/webp/dec/frame.c
@@ -1,8 +1,10 @@
// Copyright 2010 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Frame-reconstruction function. Memory allocation.
@@ -13,11 +15,180 @@
#include "./vp8i.h"
#include "../utils/utils.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+//------------------------------------------------------------------------------
+// Main reconstruction function.
+
+static const int kScan[16] = {
+ 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS,
+ 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS,
+ 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS,
+ 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS
+};
+
+static int CheckMode(int mb_x, int mb_y, int mode) {
+ if (mode == B_DC_PRED) {
+ if (mb_x == 0) {
+ return (mb_y == 0) ? B_DC_PRED_NOTOPLEFT : B_DC_PRED_NOLEFT;
+ } else {
+ return (mb_y == 0) ? B_DC_PRED_NOTOP : B_DC_PRED;
+ }
+ }
+ return mode;
+}
-#define ALIGN_MASK (32 - 1)
+static void Copy32b(uint8_t* const dst, const uint8_t* const src) {
+ memcpy(dst, src, 4);
+}
+
+static WEBP_INLINE void DoTransform(uint32_t bits, const int16_t* const src,
+ uint8_t* const dst) {
+ switch (bits >> 30) {
+ case 3:
+ VP8Transform(src, dst, 0);
+ break;
+ case 2:
+ VP8TransformAC3(src, dst);
+ break;
+ case 1:
+ VP8TransformDC(src, dst);
+ break;
+ default:
+ break;
+ }
+}
+
+static void DoUVTransform(uint32_t bits, const int16_t* const src,
+ uint8_t* const dst) {
+ if (bits & 0xff) { // any non-zero coeff at all?
+ if (bits & 0xaa) { // any non-zero AC coefficient?
+ VP8TransformUV(src, dst); // note we don't use the AC3 variant for U/V
+ } else {
+ VP8TransformDCUV(src, dst);
+ }
+ }
+}
+
+static void ReconstructRow(const VP8Decoder* const dec,
+ const VP8ThreadContext* ctx) {
+ int j;
+ int mb_x;
+ const int mb_y = ctx->mb_y_;
+ const int cache_id = ctx->id_;
+ uint8_t* const y_dst = dec->yuv_b_ + Y_OFF;
+ uint8_t* const u_dst = dec->yuv_b_ + U_OFF;
+ uint8_t* const v_dst = dec->yuv_b_ + V_OFF;
+
+ // Initialize left-most block.
+ for (j = 0; j < 16; ++j) {
+ y_dst[j * BPS - 1] = 129;
+ }
+ for (j = 0; j < 8; ++j) {
+ u_dst[j * BPS - 1] = 129;
+ v_dst[j * BPS - 1] = 129;
+ }
+
+ // Init top-left sample on left column too.
+ if (mb_y > 0) {
+ y_dst[-1 - BPS] = u_dst[-1 - BPS] = v_dst[-1 - BPS] = 129;
+ } else {
+ // we only need to do this init once at block (0,0).
+ // Afterward, it remains valid for the whole topmost row.
+ memset(y_dst - BPS - 1, 127, 16 + 4 + 1);
+ memset(u_dst - BPS - 1, 127, 8 + 1);
+ memset(v_dst - BPS - 1, 127, 8 + 1);
+ }
+
+ // Reconstruct one row.
+ for (mb_x = 0; mb_x < dec->mb_w_; ++mb_x) {
+ const VP8MBData* const block = ctx->mb_data_ + mb_x;
+
+ // Rotate in the left samples from previously decoded block. We move four
+ // pixels at a time for alignment reason, and because of in-loop filter.
+ if (mb_x > 0) {
+ for (j = -1; j < 16; ++j) {
+ Copy32b(&y_dst[j * BPS - 4], &y_dst[j * BPS + 12]);
+ }
+ for (j = -1; j < 8; ++j) {
+ Copy32b(&u_dst[j * BPS - 4], &u_dst[j * BPS + 4]);
+ Copy32b(&v_dst[j * BPS - 4], &v_dst[j * BPS + 4]);
+ }
+ }
+ {
+ // bring top samples into the cache
+ VP8TopSamples* const top_yuv = dec->yuv_t_ + mb_x;
+ const int16_t* const coeffs = block->coeffs_;
+ uint32_t bits = block->non_zero_y_;
+ int n;
+
+ if (mb_y > 0) {
+ memcpy(y_dst - BPS, top_yuv[0].y, 16);
+ memcpy(u_dst - BPS, top_yuv[0].u, 8);
+ memcpy(v_dst - BPS, top_yuv[0].v, 8);
+ }
+
+ // predict and add residuals
+ if (block->is_i4x4_) { // 4x4
+ uint32_t* const top_right = (uint32_t*)(y_dst - BPS + 16);
+
+ if (mb_y > 0) {
+ if (mb_x >= dec->mb_w_ - 1) { // on rightmost border
+ memset(top_right, top_yuv[0].y[15], sizeof(*top_right));
+ } else {
+ memcpy(top_right, top_yuv[1].y, sizeof(*top_right));
+ }
+ }
+ // replicate the top-right pixels below
+ top_right[BPS] = top_right[2 * BPS] = top_right[3 * BPS] = top_right[0];
+
+ // predict and add residuals for all 4x4 blocks in turn.
+ for (n = 0; n < 16; ++n, bits <<= 2) {
+ uint8_t* const dst = y_dst + kScan[n];
+ VP8PredLuma4[block->imodes_[n]](dst);
+ DoTransform(bits, coeffs + n * 16, dst);
+ }
+ } else { // 16x16
+ const int pred_func = CheckMode(mb_x, mb_y, block->imodes_[0]);
+ VP8PredLuma16[pred_func](y_dst);
+ if (bits != 0) {
+ for (n = 0; n < 16; ++n, bits <<= 2) {
+ DoTransform(bits, coeffs + n * 16, y_dst + kScan[n]);
+ }
+ }
+ }
+ {
+ // Chroma
+ const uint32_t bits_uv = block->non_zero_uv_;
+ const int pred_func = CheckMode(mb_x, mb_y, block->uvmode_);
+ VP8PredChroma8[pred_func](u_dst);
+ VP8PredChroma8[pred_func](v_dst);
+ DoUVTransform(bits_uv >> 0, coeffs + 16 * 16, u_dst);
+ DoUVTransform(bits_uv >> 8, coeffs + 20 * 16, v_dst);
+ }
+
+ // stash away top samples for next block
+ if (mb_y < dec->mb_h_ - 1) {
+ memcpy(top_yuv[0].y, y_dst + 15 * BPS, 16);
+ memcpy(top_yuv[0].u, u_dst + 7 * BPS, 8);
+ memcpy(top_yuv[0].v, v_dst + 7 * BPS, 8);
+ }
+ }
+ // Transfer reconstructed samples from yuv_b_ cache to final destination.
+ {
+ const int y_offset = cache_id * 16 * dec->cache_y_stride_;
+ const int uv_offset = cache_id * 8 * dec->cache_uv_stride_;
+ uint8_t* const y_out = dec->cache_y_ + mb_x * 16 + y_offset;
+ uint8_t* const u_out = dec->cache_u_ + mb_x * 8 + uv_offset;
+ uint8_t* const v_out = dec->cache_v_ + mb_x * 8 + uv_offset;
+ for (j = 0; j < 16; ++j) {
+ memcpy(y_out + j * dec->cache_y_stride_, y_dst + j * BPS, 16);
+ }
+ for (j = 0; j < 8; ++j) {
+ memcpy(u_out + j * dec->cache_uv_stride_, u_dst + j * BPS, 8);
+ memcpy(v_out + j * dec->cache_uv_stride_, v_dst + j * BPS, 8);
+ }
+ }
+ }
+}
//------------------------------------------------------------------------------
// Filtering
@@ -29,25 +200,18 @@ extern "C" {
// U/V, so it's 8 samples total (because of the 2x upsampling).
static const uint8_t kFilterExtraRows[3] = { 0, 2, 8 };
-static WEBP_INLINE int hev_thresh_from_level(int level, int keyframe) {
- if (keyframe) {
- return (level >= 40) ? 2 : (level >= 15) ? 1 : 0;
- } else {
- return (level >= 40) ? 3 : (level >= 20) ? 2 : (level >= 15) ? 1 : 0;
- }
-}
-
static void DoFilter(const VP8Decoder* const dec, int mb_x, int mb_y) {
const VP8ThreadContext* const ctx = &dec->thread_ctx_;
+ const int cache_id = ctx->id_;
const int y_bps = dec->cache_y_stride_;
- VP8FInfo* const f_info = ctx->f_info_ + mb_x;
- uint8_t* const y_dst = dec->cache_y_ + ctx->id_ * 16 * y_bps + mb_x * 16;
- const int level = f_info->f_level_;
+ const VP8FInfo* const f_info = ctx->f_info_ + mb_x;
+ uint8_t* const y_dst = dec->cache_y_ + cache_id * 16 * y_bps + mb_x * 16;
const int ilevel = f_info->f_ilevel_;
- const int limit = 2 * level + ilevel;
- if (level == 0) {
+ const int limit = f_info->f_limit_;
+ if (limit == 0) {
return;
}
+ assert(limit >= 3);
if (dec->filter_type_ == 1) { // simple
if (mb_x > 0) {
VP8SimpleHFilter16(y_dst, y_bps, limit + 4);
@@ -63,10 +227,9 @@ static void DoFilter(const VP8Decoder* const dec, int mb_x, int mb_y) {
}
} else { // complex
const int uv_bps = dec->cache_uv_stride_;
- uint8_t* const u_dst = dec->cache_u_ + ctx->id_ * 8 * uv_bps + mb_x * 8;
- uint8_t* const v_dst = dec->cache_v_ + ctx->id_ * 8 * uv_bps + mb_x * 8;
- const int hev_thresh =
- hev_thresh_from_level(level, dec->frm_hdr_.key_frame_);
+ uint8_t* const u_dst = dec->cache_u_ + cache_id * 8 * uv_bps + mb_x * 8;
+ uint8_t* const v_dst = dec->cache_v_ + cache_id * 8 * uv_bps + mb_x * 8;
+ const int hev_thresh = f_info->hev_thresh_;
if (mb_x > 0) {
VP8HFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh);
VP8HFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh);
@@ -97,53 +260,138 @@ static void FilterRow(const VP8Decoder* const dec) {
}
//------------------------------------------------------------------------------
+// Precompute the filtering strength for each segment and each i4x4/i16x16 mode.
-void VP8StoreBlock(VP8Decoder* const dec) {
+static void PrecomputeFilterStrengths(VP8Decoder* const dec) {
if (dec->filter_type_ > 0) {
- VP8FInfo* const info = dec->f_info_ + dec->mb_x_;
- const int skip = dec->mb_info_[dec->mb_x_].skip_;
- int level = dec->filter_levels_[dec->segment_];
- if (dec->filter_hdr_.use_lf_delta_) {
- // TODO(skal): only CURRENT is handled for now.
- level += dec->filter_hdr_.ref_lf_delta_[0];
- if (dec->is_i4x4_) {
- level += dec->filter_hdr_.mode_lf_delta_[0];
+ int s;
+ const VP8FilterHeader* const hdr = &dec->filter_hdr_;
+ for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
+ int i4x4;
+ // First, compute the initial level
+ int base_level;
+ if (dec->segment_hdr_.use_segment_) {
+ base_level = dec->segment_hdr_.filter_strength_[s];
+ if (!dec->segment_hdr_.absolute_delta_) {
+ base_level += hdr->level_;
+ }
+ } else {
+ base_level = hdr->level_;
+ }
+ for (i4x4 = 0; i4x4 <= 1; ++i4x4) {
+ VP8FInfo* const info = &dec->fstrengths_[s][i4x4];
+ int level = base_level;
+ if (hdr->use_lf_delta_) {
+ level += hdr->ref_lf_delta_[0];
+ if (i4x4) {
+ level += hdr->mode_lf_delta_[0];
+ }
+ }
+ level = (level < 0) ? 0 : (level > 63) ? 63 : level;
+ if (level > 0) {
+ int ilevel = level;
+ if (hdr->sharpness_ > 0) {
+ if (hdr->sharpness_ > 4) {
+ ilevel >>= 2;
+ } else {
+ ilevel >>= 1;
+ }
+ if (ilevel > 9 - hdr->sharpness_) {
+ ilevel = 9 - hdr->sharpness_;
+ }
+ }
+ if (ilevel < 1) ilevel = 1;
+ info->f_ilevel_ = ilevel;
+ info->f_limit_ = 2 * level + ilevel;
+ info->hev_thresh_ = (level >= 40) ? 2 : (level >= 15) ? 1 : 0;
+ } else {
+ info->f_limit_ = 0; // no filtering
+ }
+ info->f_inner_ = i4x4;
}
}
- level = (level < 0) ? 0 : (level > 63) ? 63 : level;
- info->f_level_ = level;
+ }
+}
- if (dec->filter_hdr_.sharpness_ > 0) {
- if (dec->filter_hdr_.sharpness_ > 4) {
- level >>= 2;
- } else {
- level >>= 1;
+//------------------------------------------------------------------------------
+// Dithering
+
+#define DITHER_AMP_TAB_SIZE 12
+static const int kQuantToDitherAmp[DITHER_AMP_TAB_SIZE] = {
+ // roughly, it's dqm->uv_mat_[1]
+ 8, 7, 6, 4, 4, 2, 2, 2, 1, 1, 1, 1
+};
+
+void VP8InitDithering(const WebPDecoderOptions* const options,
+ VP8Decoder* const dec) {
+ assert(dec != NULL);
+ if (options != NULL) {
+ const int d = options->dithering_strength;
+ const int max_amp = (1 << VP8_RANDOM_DITHER_FIX) - 1;
+ const int f = (d < 0) ? 0 : (d > 100) ? max_amp : (d * max_amp / 100);
+ if (f > 0) {
+ int s;
+ int all_amp = 0;
+ for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
+ VP8QuantMatrix* const dqm = &dec->dqm_[s];
+ if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) {
+ // TODO(skal): should we specially dither more for uv_quant_ < 0?
+ const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_;
+ dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3;
+ }
+ all_amp |= dqm->dither_;
}
- if (level > 9 - dec->filter_hdr_.sharpness_) {
- level = 9 - dec->filter_hdr_.sharpness_;
+ if (all_amp != 0) {
+ VP8InitRandom(&dec->dithering_rg_, 1.0f);
+ dec->dither_ = 1;
}
}
+ // potentially allow alpha dithering
+ dec->alpha_dithering_ = options->alpha_dithering_strength;
+ if (dec->alpha_dithering_ > 100) {
+ dec->alpha_dithering_ = 100;
+ } else if (dec->alpha_dithering_ < 0) {
+ dec->alpha_dithering_ = 0;
+ }
+ }
+}
- info->f_ilevel_ = (level < 1) ? 1 : level;
- info->f_inner_ = (!skip || dec->is_i4x4_);
+// minimal amp that will provide a non-zero dithering effect
+#define MIN_DITHER_AMP 4
+#define DITHER_DESCALE 4
+#define DITHER_DESCALE_ROUNDER (1 << (DITHER_DESCALE - 1))
+#define DITHER_AMP_BITS 8
+#define DITHER_AMP_CENTER (1 << DITHER_AMP_BITS)
+
+static void Dither8x8(VP8Random* const rg, uint8_t* dst, int bps, int amp) {
+ int i, j;
+ for (j = 0; j < 8; ++j) {
+ for (i = 0; i < 8; ++i) {
+ // TODO: could be made faster with SSE2
+ const int bits =
+ VP8RandomBits2(rg, DITHER_AMP_BITS + 1, amp) - DITHER_AMP_CENTER;
+ // Convert to range: [-2,2] for dither=50, [-4,4] for dither=100
+ const int delta = (bits + DITHER_DESCALE_ROUNDER) >> DITHER_DESCALE;
+ const int v = (int)dst[i] + delta;
+ dst[i] = (v < 0) ? 0 : (v > 255) ? 255u : (uint8_t)v;
+ }
+ dst += bps;
}
- {
- // Transfer samples to row cache
- int y;
- const int y_offset = dec->cache_id_ * 16 * dec->cache_y_stride_;
- const int uv_offset = dec->cache_id_ * 8 * dec->cache_uv_stride_;
- uint8_t* const ydst = dec->cache_y_ + dec->mb_x_ * 16 + y_offset;
- uint8_t* const udst = dec->cache_u_ + dec->mb_x_ * 8 + uv_offset;
- uint8_t* const vdst = dec->cache_v_ + dec->mb_x_ * 8 + uv_offset;
- for (y = 0; y < 16; ++y) {
- memcpy(ydst + y * dec->cache_y_stride_,
- dec->yuv_b_ + Y_OFF + y * BPS, 16);
- }
- for (y = 0; y < 8; ++y) {
- memcpy(udst + y * dec->cache_uv_stride_,
- dec->yuv_b_ + U_OFF + y * BPS, 8);
- memcpy(vdst + y * dec->cache_uv_stride_,
- dec->yuv_b_ + V_OFF + y * BPS, 8);
+}
+
+static void DitherRow(VP8Decoder* const dec) {
+ int mb_x;
+ assert(dec->dither_);
+ for (mb_x = dec->tl_mb_x_; mb_x < dec->br_mb_x_; ++mb_x) {
+ const VP8ThreadContext* const ctx = &dec->thread_ctx_;
+ const VP8MBData* const data = ctx->mb_data_ + mb_x;
+ const int cache_id = ctx->id_;
+ const int uv_bps = dec->cache_uv_stride_;
+ if (data->dither_ >= MIN_DITHER_AMP) {
+ uint8_t* const u_dst = dec->cache_u_ + cache_id * 8 * uv_bps + mb_x * 8;
+ uint8_t* const v_dst = dec->cache_v_ + cache_id * 8 * uv_bps + mb_x * 8;
+ Dither8x8(&dec->dithering_rg_, u_dst, uv_bps, data->dither_);
+ Dither8x8(&dec->dithering_rg_, v_dst, uv_bps, data->dither_);
}
}
}
@@ -165,25 +413,35 @@ void VP8StoreBlock(VP8Decoder* const dec) {
static int FinishRow(VP8Decoder* const dec, VP8Io* const io) {
int ok = 1;
const VP8ThreadContext* const ctx = &dec->thread_ctx_;
+ const int cache_id = ctx->id_;
const int extra_y_rows = kFilterExtraRows[dec->filter_type_];
const int ysize = extra_y_rows * dec->cache_y_stride_;
const int uvsize = (extra_y_rows / 2) * dec->cache_uv_stride_;
- const int y_offset = ctx->id_ * 16 * dec->cache_y_stride_;
- const int uv_offset = ctx->id_ * 8 * dec->cache_uv_stride_;
+ const int y_offset = cache_id * 16 * dec->cache_y_stride_;
+ const int uv_offset = cache_id * 8 * dec->cache_uv_stride_;
uint8_t* const ydst = dec->cache_y_ - ysize + y_offset;
uint8_t* const udst = dec->cache_u_ - uvsize + uv_offset;
uint8_t* const vdst = dec->cache_v_ - uvsize + uv_offset;
- const int first_row = (ctx->mb_y_ == 0);
- const int last_row = (ctx->mb_y_ >= dec->br_mb_y_ - 1);
- int y_start = MACROBLOCK_VPOS(ctx->mb_y_);
- int y_end = MACROBLOCK_VPOS(ctx->mb_y_ + 1);
+ const int mb_y = ctx->mb_y_;
+ const int is_first_row = (mb_y == 0);
+ const int is_last_row = (mb_y >= dec->br_mb_y_ - 1);
+
+ if (dec->mt_method_ == 2) {
+ ReconstructRow(dec, ctx);
+ }
if (ctx->filter_row_) {
FilterRow(dec);
}
- if (io->put) {
- if (!first_row) {
+ if (dec->dither_) {
+ DitherRow(dec);
+ }
+
+ if (io->put != NULL) {
+ int y_start = MACROBLOCK_VPOS(mb_y);
+ int y_end = MACROBLOCK_VPOS(mb_y + 1);
+ if (!is_first_row) {
y_start -= extra_y_rows;
io->y = ydst;
io->u = udst;
@@ -194,7 +452,7 @@ static int FinishRow(VP8Decoder* const dec, VP8Io* const io) {
io->v = dec->cache_v_ + uv_offset;
}
- if (!last_row) {
+ if (!is_last_row) {
y_end -= extra_y_rows;
}
if (y_end > io->crop_bottom) {
@@ -202,11 +460,8 @@ static int FinishRow(VP8Decoder* const dec, VP8Io* const io) {
}
io->a = NULL;
if (dec->alpha_data_ != NULL && y_start < y_end) {
- // TODO(skal): several things to correct here:
- // * testing presence of alpha with dec->alpha_data_ is not a good idea
- // * we're actually decompressing the full plane only once. It should be
- // more obvious from signature.
- // * we could free alpha_data_ right after this call, but we don't own.
+ // TODO(skal): testing presence of alpha with dec->alpha_data_ is not a
+ // good idea.
io->a = VP8DecompressAlphaRows(dec, y_start, y_end - y_start);
if (io->a == NULL) {
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
@@ -238,8 +493,8 @@ static int FinishRow(VP8Decoder* const dec, VP8Io* const io) {
}
}
// rotate top samples if needed
- if (ctx->id_ + 1 == dec->num_caches_) {
- if (!last_row) {
+ if (cache_id + 1 == dec->num_caches_) {
+ if (!is_last_row) {
memcpy(dec->cache_y_ - ysize, ydst + 16 * dec->cache_y_stride_, ysize);
memcpy(dec->cache_u_ - uvsize, udst + 8 * dec->cache_uv_stride_, uvsize);
memcpy(dec->cache_v_ - uvsize, vdst + 8 * dec->cache_uv_stride_, uvsize);
@@ -256,27 +511,40 @@ static int FinishRow(VP8Decoder* const dec, VP8Io* const io) {
int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io) {
int ok = 1;
VP8ThreadContext* const ctx = &dec->thread_ctx_;
- if (!dec->use_threads_) {
+ const int filter_row =
+ (dec->filter_type_ > 0) &&
+ (dec->mb_y_ >= dec->tl_mb_y_) && (dec->mb_y_ <= dec->br_mb_y_);
+ if (dec->mt_method_ == 0) {
// ctx->id_ and ctx->f_info_ are already set
ctx->mb_y_ = dec->mb_y_;
- ctx->filter_row_ = dec->filter_row_;
+ ctx->filter_row_ = filter_row;
+ ReconstructRow(dec, ctx);
ok = FinishRow(dec, io);
} else {
WebPWorker* const worker = &dec->worker_;
// Finish previous job *before* updating context
- ok &= WebPWorkerSync(worker);
+ ok &= WebPGetWorkerInterface()->Sync(worker);
assert(worker->status_ == OK);
if (ok) { // spawn a new deblocking/output job
ctx->io_ = *io;
ctx->id_ = dec->cache_id_;
ctx->mb_y_ = dec->mb_y_;
- ctx->filter_row_ = dec->filter_row_;
- if (ctx->filter_row_) { // just swap filter info
+ ctx->filter_row_ = filter_row;
+ if (dec->mt_method_ == 2) { // swap macroblock data
+ VP8MBData* const tmp = ctx->mb_data_;
+ ctx->mb_data_ = dec->mb_data_;
+ dec->mb_data_ = tmp;
+ } else {
+ // perform reconstruction directly in main thread
+ ReconstructRow(dec, ctx);
+ }
+ if (filter_row) { // swap filter info
VP8FInfo* const tmp = ctx->f_info_;
ctx->f_info_ = dec->f_info_;
dec->f_info_ = tmp;
}
- WebPWorkerLaunch(worker);
+ // (reconstruct)+filter in parallel
+ WebPGetWorkerInterface()->Launch(worker);
if (++dec->cache_id_ == dec->num_caches_) {
dec->cache_id_ = 0;
}
@@ -290,8 +558,8 @@ int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io) {
VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) {
// Call setup() first. This may trigger additional decoding features on 'io'.
- // Note: Afterward, we must call teardown() not matter what.
- if (io->setup && !io->setup(io)) {
+ // Note: Afterward, we must call teardown() no matter what.
+ if (io->setup != NULL && !io->setup(io)) {
VP8SetError(dec, VP8_STATUS_USER_ABORT, "Frame setup failed");
return dec->status_;
}
@@ -304,7 +572,7 @@ VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) {
// Define the area where we can skip in-loop filtering, in case of cropping.
//
- // 'Simple' filter reads two luma samples outside of the macroblock and
+ // 'Simple' filter reads two luma samples outside of the macroblock
// and filters one. It doesn't filter the chroma samples. Hence, we can
// avoid doing the in-loop filtering before crop_top/crop_left position.
// For the 'Complex' filter, 3 samples are read and up to 3 are filtered.
@@ -339,16 +607,17 @@ VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) {
dec->br_mb_y_ = dec->mb_h_;
}
}
+ PrecomputeFilterStrengths(dec);
return VP8_STATUS_OK;
}
int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io) {
int ok = 1;
- if (dec->use_threads_) {
- ok = WebPWorkerSync(&dec->worker_);
+ if (dec->mt_method_ > 0) {
+ ok = WebPGetWorkerInterface()->Sync(&dec->worker_);
}
- if (io->teardown) {
+ if (io->teardown != NULL) {
io->teardown(io);
}
return ok;
@@ -384,9 +653,9 @@ int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io) {
// Initialize multi/single-thread worker
static int InitThreadContext(VP8Decoder* const dec) {
dec->cache_id_ = 0;
- if (dec->use_threads_) {
+ if (dec->mt_method_ > 0) {
WebPWorker* const worker = &dec->worker_;
- if (!WebPWorkerReset(worker)) {
+ if (!WebPGetWorkerInterface()->Reset(worker)) {
return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY,
"thread initialization failed.");
}
@@ -401,6 +670,28 @@ static int InitThreadContext(VP8Decoder* const dec) {
return 1;
}
+int VP8GetThreadMethod(const WebPDecoderOptions* const options,
+ const WebPHeaderStructure* const headers,
+ int width, int height) {
+ if (options == NULL || options->use_threads == 0) {
+ return 0;
+ }
+ (void)headers;
+ (void)width;
+ (void)height;
+ assert(headers == NULL || !headers->is_lossless);
+#if defined(WEBP_USE_THREAD)
+ if (width < MIN_WIDTH_FOR_THREADS) return 0;
+ // TODO(skal): tune the heuristic further
+#if 0
+ if (height < 2 * width) return 2;
+#endif
+ return 2;
+#else // !WEBP_USE_THREAD
+ return 0;
+#endif
+}
+
#undef MT_CACHE_LINES
#undef ST_CACHE_LINES
@@ -412,14 +703,15 @@ static int AllocateMemory(VP8Decoder* const dec) {
const int mb_w = dec->mb_w_;
// Note: we use 'size_t' when there's no overflow risk, uint64_t otherwise.
const size_t intra_pred_mode_size = 4 * mb_w * sizeof(uint8_t);
- const size_t top_size = (16 + 8 + 8) * mb_w;
+ const size_t top_size = sizeof(VP8TopSamples) * mb_w;
const size_t mb_info_size = (mb_w + 1) * sizeof(VP8MB);
const size_t f_info_size =
(dec->filter_type_ > 0) ?
- mb_w * (dec->use_threads_ ? 2 : 1) * sizeof(VP8FInfo)
+ mb_w * (dec->mt_method_ > 0 ? 2 : 1) * sizeof(VP8FInfo)
: 0;
const size_t yuv_size = YUV_SIZE * sizeof(*dec->yuv_b_);
- const size_t coeffs_size = 384 * sizeof(*dec->coeffs_);
+ const size_t mb_data_size =
+ (dec->mt_method_ == 2 ? 2 : 1) * mb_w * sizeof(*dec->mb_data_);
const size_t cache_height = (16 * num_caches
+ kFilterExtraRows[dec->filter_type_]) * 3 / 2;
const size_t cache_size = top_size * cache_height;
@@ -428,13 +720,13 @@ static int AllocateMemory(VP8Decoder* const dec) {
(uint64_t)dec->pic_hdr_.width_ * dec->pic_hdr_.height_ : 0ULL;
const uint64_t needed = (uint64_t)intra_pred_mode_size
+ top_size + mb_info_size + f_info_size
- + yuv_size + coeffs_size
- + cache_size + alpha_size + ALIGN_MASK;
+ + yuv_size + mb_data_size
+ + cache_size + alpha_size + WEBP_ALIGN_CST;
uint8_t* mem;
if (needed != (size_t)needed) return 0; // check for overflow
if (needed > dec->mem_size_) {
- free(dec->mem_);
+ WebPSafeFree(dec->mem_);
dec->mem_size_ = 0;
dec->mem_ = WebPSafeMalloc(needed, sizeof(uint8_t));
if (dec->mem_ == NULL) {
@@ -449,12 +741,8 @@ static int AllocateMemory(VP8Decoder* const dec) {
dec->intra_t_ = (uint8_t*)mem;
mem += intra_pred_mode_size;
- dec->y_t_ = (uint8_t*)mem;
- mem += 16 * mb_w;
- dec->u_t_ = (uint8_t*)mem;
- mem += 8 * mb_w;
- dec->v_t_ = (uint8_t*)mem;
- mem += 8 * mb_w;
+ dec->yuv_t_ = (VP8TopSamples*)mem;
+ mem += top_size;
dec->mb_info_ = ((VP8MB*)mem) + 1;
mem += mb_info_size;
@@ -463,20 +751,24 @@ static int AllocateMemory(VP8Decoder* const dec) {
mem += f_info_size;
dec->thread_ctx_.id_ = 0;
dec->thread_ctx_.f_info_ = dec->f_info_;
- if (dec->use_threads_) {
+ if (dec->mt_method_ > 0) {
// secondary cache line. The deblocking process need to make use of the
// filtering strength from previous macroblock row, while the new ones
// are being decoded in parallel. We'll just swap the pointers.
dec->thread_ctx_.f_info_ += mb_w;
}
- mem = (uint8_t*)((uintptr_t)(mem + ALIGN_MASK) & ~ALIGN_MASK);
- assert((yuv_size & ALIGN_MASK) == 0);
+ mem = (uint8_t*)WEBP_ALIGN(mem);
+ assert((yuv_size & WEBP_ALIGN_CST) == 0);
dec->yuv_b_ = (uint8_t*)mem;
mem += yuv_size;
- dec->coeffs_ = (int16_t*)mem;
- mem += coeffs_size;
+ dec->mb_data_ = (VP8MBData*)mem;
+ dec->thread_ctx_.mb_data_ = (VP8MBData*)mem;
+ if (dec->mt_method_ == 2) {
+ dec->thread_ctx_.mb_data_ += mb_w;
+ }
+ mem += mb_data_size;
dec->cache_y_stride_ = 16 * mb_w;
dec->cache_uv_stride_ = 8 * mb_w;
@@ -496,9 +788,11 @@ static int AllocateMemory(VP8Decoder* const dec) {
// alpha plane
dec->alpha_plane_ = alpha_size ? (uint8_t*)mem : NULL;
mem += alpha_size;
+ assert(mem <= (uint8_t*)dec->mem_ + dec->mem_size_);
- // note: left-info is initialized once for all.
+ // note: left/top-info is initialized once for all.
memset(dec->mb_info_ - 1, 0, mb_info_size);
+ VP8InitScanline(dec); // initialize left too.
// initialize top
memset(dec->intra_t_, B_DC_PRED, intra_pred_mode_size);
@@ -517,7 +811,7 @@ static void InitIo(VP8Decoder* const dec, VP8Io* io) {
io->a = NULL;
}
-int VP8InitFrame(VP8Decoder* const dec, VP8Io* io) {
+int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io) {
if (!InitThreadContext(dec)) return 0; // call first. Sets dec->num_caches_.
if (!AllocateMemory(dec)) return 0;
InitIo(dec, io);
@@ -526,154 +820,3 @@ int VP8InitFrame(VP8Decoder* const dec, VP8Io* io) {
}
//------------------------------------------------------------------------------
-// Main reconstruction function.
-
-static const int kScan[16] = {
- 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS,
- 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS,
- 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS,
- 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS
-};
-
-static WEBP_INLINE int CheckMode(VP8Decoder* const dec, int mode) {
- if (mode == B_DC_PRED) {
- if (dec->mb_x_ == 0) {
- return (dec->mb_y_ == 0) ? B_DC_PRED_NOTOPLEFT : B_DC_PRED_NOLEFT;
- } else {
- return (dec->mb_y_ == 0) ? B_DC_PRED_NOTOP : B_DC_PRED;
- }
- }
- return mode;
-}
-
-static WEBP_INLINE void Copy32b(uint8_t* dst, uint8_t* src) {
- *(uint32_t*)dst = *(uint32_t*)src;
-}
-
-void VP8ReconstructBlock(VP8Decoder* const dec) {
- uint8_t* const y_dst = dec->yuv_b_ + Y_OFF;
- uint8_t* const u_dst = dec->yuv_b_ + U_OFF;
- uint8_t* const v_dst = dec->yuv_b_ + V_OFF;
-
- // Rotate in the left samples from previously decoded block. We move four
- // pixels at a time for alignment reason, and because of in-loop filter.
- if (dec->mb_x_ > 0) {
- int j;
- for (j = -1; j < 16; ++j) {
- Copy32b(&y_dst[j * BPS - 4], &y_dst[j * BPS + 12]);
- }
- for (j = -1; j < 8; ++j) {
- Copy32b(&u_dst[j * BPS - 4], &u_dst[j * BPS + 4]);
- Copy32b(&v_dst[j * BPS - 4], &v_dst[j * BPS + 4]);
- }
- } else {
- int j;
- for (j = 0; j < 16; ++j) {
- y_dst[j * BPS - 1] = 129;
- }
- for (j = 0; j < 8; ++j) {
- u_dst[j * BPS - 1] = 129;
- v_dst[j * BPS - 1] = 129;
- }
- // Init top-left sample on left column too
- if (dec->mb_y_ > 0) {
- y_dst[-1 - BPS] = u_dst[-1 - BPS] = v_dst[-1 - BPS] = 129;
- }
- }
- {
- // bring top samples into the cache
- uint8_t* const top_y = dec->y_t_ + dec->mb_x_ * 16;
- uint8_t* const top_u = dec->u_t_ + dec->mb_x_ * 8;
- uint8_t* const top_v = dec->v_t_ + dec->mb_x_ * 8;
- const int16_t* coeffs = dec->coeffs_;
- int n;
-
- if (dec->mb_y_ > 0) {
- memcpy(y_dst - BPS, top_y, 16);
- memcpy(u_dst - BPS, top_u, 8);
- memcpy(v_dst - BPS, top_v, 8);
- } else if (dec->mb_x_ == 0) {
- // we only need to do this init once at block (0,0).
- // Afterward, it remains valid for the whole topmost row.
- memset(y_dst - BPS - 1, 127, 16 + 4 + 1);
- memset(u_dst - BPS - 1, 127, 8 + 1);
- memset(v_dst - BPS - 1, 127, 8 + 1);
- }
-
- // predict and add residuals
-
- if (dec->is_i4x4_) { // 4x4
- uint32_t* const top_right = (uint32_t*)(y_dst - BPS + 16);
-
- if (dec->mb_y_ > 0) {
- if (dec->mb_x_ >= dec->mb_w_ - 1) { // on rightmost border
- top_right[0] = top_y[15] * 0x01010101u;
- } else {
- memcpy(top_right, top_y + 16, sizeof(*top_right));
- }
- }
- // replicate the top-right pixels below
- top_right[BPS] = top_right[2 * BPS] = top_right[3 * BPS] = top_right[0];
-
- // predict and add residues for all 4x4 blocks in turn.
- for (n = 0; n < 16; n++) {
- uint8_t* const dst = y_dst + kScan[n];
- VP8PredLuma4[dec->imodes_[n]](dst);
- if (dec->non_zero_ac_ & (1 << n)) {
- VP8Transform(coeffs + n * 16, dst, 0);
- } else if (dec->non_zero_ & (1 << n)) { // only DC is present
- VP8TransformDC(coeffs + n * 16, dst);
- }
- }
- } else { // 16x16
- const int pred_func = CheckMode(dec, dec->imodes_[0]);
- VP8PredLuma16[pred_func](y_dst);
- if (dec->non_zero_) {
- for (n = 0; n < 16; n++) {
- uint8_t* const dst = y_dst + kScan[n];
- if (dec->non_zero_ac_ & (1 << n)) {
- VP8Transform(coeffs + n * 16, dst, 0);
- } else if (dec->non_zero_ & (1 << n)) { // only DC is present
- VP8TransformDC(coeffs + n * 16, dst);
- }
- }
- }
- }
- {
- // Chroma
- const int pred_func = CheckMode(dec, dec->uvmode_);
- VP8PredChroma8[pred_func](u_dst);
- VP8PredChroma8[pred_func](v_dst);
-
- if (dec->non_zero_ & 0x0f0000) { // chroma-U
- const int16_t* const u_coeffs = dec->coeffs_ + 16 * 16;
- if (dec->non_zero_ac_ & 0x0f0000) {
- VP8TransformUV(u_coeffs, u_dst);
- } else {
- VP8TransformDCUV(u_coeffs, u_dst);
- }
- }
- if (dec->non_zero_ & 0xf00000) { // chroma-V
- const int16_t* const v_coeffs = dec->coeffs_ + 20 * 16;
- if (dec->non_zero_ac_ & 0xf00000) {
- VP8TransformUV(v_coeffs, v_dst);
- } else {
- VP8TransformDCUV(v_coeffs, v_dst);
- }
- }
-
- // stash away top samples for next block
- if (dec->mb_y_ < dec->mb_h_ - 1) {
- memcpy(top_y, y_dst + 15 * BPS, 16);
- memcpy(top_u, u_dst + 7 * BPS, 8);
- memcpy(top_v, v_dst + 7 * BPS, 8);
- }
- }
- }
-}
-
-//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/dec/idec.c b/drivers/webp/dec/idec.c
index 7df790ced8..abafb9f3d1 100644
--- a/drivers/webp/dec/idec.c
+++ b/drivers/webp/dec/idec.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Incremental decoding
@@ -13,14 +15,11 @@
#include <string.h>
#include <stdlib.h>
+#include "./alphai.h"
#include "./webpi.h"
#include "./vp8i.h"
#include "../utils/utils.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
// In append mode, buffer allocations increase as multiples of this value.
// Needs to be a power of 2.
#define CHUNK_SIZE 4096
@@ -29,11 +28,13 @@ extern "C" {
//------------------------------------------------------------------------------
// Data structures for memory and states
-// Decoding states. State normally flows like HEADER->PARTS0->DATA->DONE.
+// Decoding states. State normally flows as:
+// WEBP_HEADER->VP8_HEADER->VP8_PARTS0->VP8_DATA->DONE for a lossy image, and
+// WEBP_HEADER->VP8L_HEADER->VP8L_DATA->DONE for a lossless image.
// If there is any error the decoder goes into state ERROR.
typedef enum {
- STATE_PRE_VP8, // All data before that of the first VP8 chunk.
- STATE_VP8_FRAME_HEADER, // For VP8 Frame header (within VP8 chunk).
+ STATE_WEBP_HEADER, // All the data before that of the VP8/VP8L chunk.
+ STATE_VP8_HEADER, // The VP8 Frame header (within the VP8 chunk).
STATE_VP8_PARTS0,
STATE_VP8_DATA,
STATE_VP8L_HEADER,
@@ -71,32 +72,41 @@ struct WebPIDecoder {
MemBuffer mem_; // input memory buffer.
WebPDecBuffer output_; // output buffer (when no external one is supplied)
size_t chunk_size_; // Compressed VP8/VP8L size extracted from Header.
+
+ int last_mb_y_; // last row reached for intra-mode decoding
};
// MB context to restore in case VP8DecodeMB() fails
typedef struct {
VP8MB left_;
VP8MB info_;
- uint8_t intra_t_[4];
- uint8_t intra_l_[4];
- VP8BitReader br_;
VP8BitReader token_br_;
} MBContext;
//------------------------------------------------------------------------------
// MemBuffer: incoming data handling
-static void RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) {
- if (br->buf_ != NULL) {
- br->buf_ += offset;
- br->buf_end_ += offset;
- }
-}
-
static WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) {
return (mem->end_ - mem->start_);
}
+// Check if we need to preserve the compressed alpha data, as it may not have
+// been decoded yet.
+static int NeedCompressedAlpha(const WebPIDecoder* const idec) {
+ if (idec->state_ == STATE_WEBP_HEADER) {
+ // We haven't parsed the headers yet, so we don't know whether the image is
+ // lossy or lossless. This also means that we haven't parsed the ALPH chunk.
+ return 0;
+ }
+ if (idec->is_lossless_) {
+ return 0; // ALPH chunk is not present for lossless images.
+ } else {
+ const VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
+ assert(dec != NULL); // Must be true as idec->state_ != STATE_WEBP_HEADER.
+ return (dec->alpha_data_ != NULL) && !dec->is_alpha_decoded_;
+ }
+}
+
static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) {
MemBuffer* const mem = &idec->mem_;
const uint8_t* const new_base = mem->buf_ + mem->start_;
@@ -112,16 +122,36 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) {
if (offset != 0) {
int p;
for (p = 0; p <= last_part; ++p) {
- RemapBitReader(dec->parts_ + p, offset);
+ VP8RemapBitReader(dec->parts_ + p, offset);
}
// Remap partition #0 data pointer to new offset, but only in MAP
// mode (in APPEND mode, partition #0 is copied into a fixed memory).
if (mem->mode_ == MEM_MODE_MAP) {
- RemapBitReader(&dec->br_, offset);
+ VP8RemapBitReader(&dec->br_, offset);
+ }
+ }
+ {
+ const uint8_t* const last_start = dec->parts_[last_part].buf_;
+ assert(last_part >= 0);
+ VP8BitReaderSetBuffer(&dec->parts_[last_part], last_start,
+ mem->buf_ + mem->end_ - last_start);
+ }
+ if (NeedCompressedAlpha(idec)) {
+ ALPHDecoder* const alph_dec = dec->alph_dec_;
+ dec->alpha_data_ += offset;
+ if (alph_dec != NULL) {
+ if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) {
+ VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_;
+ assert(alph_vp8l_dec != NULL);
+ assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN);
+ VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_,
+ dec->alpha_data_ + ALPHA_HEADER_LEN,
+ dec->alpha_data_size_ - ALPHA_HEADER_LEN);
+ } else { // alph_dec->method_ == ALPHA_NO_COMPRESSION
+ // Nothing special to do in this case.
+ }
}
}
- assert(last_part >= 0);
- dec->parts_[last_part].buf_end_ = mem->buf_ + mem->end_;
} else { // Resize lossless bitreader
VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_;
VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem));
@@ -133,8 +163,12 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) {
// size if required and also updates VP8BitReader's if new memory is allocated.
static int AppendToMemBuffer(WebPIDecoder* const idec,
const uint8_t* const data, size_t data_size) {
+ VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
MemBuffer* const mem = &idec->mem_;
- const uint8_t* const old_base = mem->buf_ + mem->start_;
+ const int need_compressed_alpha = NeedCompressedAlpha(idec);
+ const uint8_t* const old_start = mem->buf_ + mem->start_;
+ const uint8_t* const old_base =
+ need_compressed_alpha ? dec->alpha_data_ : old_start;
assert(mem->mode_ == MEM_MODE_APPEND);
if (data_size > MAX_CHUNK_PAYLOAD) {
// security safeguard: trying to allocate more than what the format
@@ -143,17 +177,18 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
}
if (mem->end_ + data_size > mem->buf_size_) { // Need some free memory
- const size_t current_size = MemDataSize(mem);
+ const size_t new_mem_start = old_start - old_base;
+ const size_t current_size = MemDataSize(mem) + new_mem_start;
const uint64_t new_size = (uint64_t)current_size + data_size;
const uint64_t extra_size = (new_size + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1);
uint8_t* const new_buf =
(uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf));
if (new_buf == NULL) return 0;
memcpy(new_buf, old_base, current_size);
- free(mem->buf_);
+ WebPSafeFree(mem->buf_);
mem->buf_ = new_buf;
mem->buf_size_ = (size_t)extra_size;
- mem->start_ = 0;
+ mem->start_ = new_mem_start;
mem->end_ = current_size;
}
@@ -161,14 +196,15 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
mem->end_ += data_size;
assert(mem->end_ <= mem->buf_size_);
- DoRemap(idec, mem->buf_ + mem->start_ - old_base);
+ DoRemap(idec, mem->buf_ + mem->start_ - old_start);
return 1;
}
static int RemapMemBuffer(WebPIDecoder* const idec,
const uint8_t* const data, size_t data_size) {
MemBuffer* const mem = &idec->mem_;
- const uint8_t* const old_base = mem->buf_ + mem->start_;
+ const uint8_t* const old_buf = mem->buf_;
+ const uint8_t* const old_start = old_buf + mem->start_;
assert(mem->mode_ == MEM_MODE_MAP);
if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer!
@@ -176,7 +212,7 @@ static int RemapMemBuffer(WebPIDecoder* const idec,
mem->buf_ = (uint8_t*)data;
mem->end_ = mem->buf_size_ = data_size;
- DoRemap(idec, mem->buf_ + mem->start_ - old_base);
+ DoRemap(idec, mem->buf_ + mem->start_ - old_start);
return 1;
}
@@ -191,8 +227,8 @@ static void InitMemBuffer(MemBuffer* const mem) {
static void ClearMemBuffer(MemBuffer* const mem) {
assert(mem);
if (mem->mode_ == MEM_MODE_APPEND) {
- free(mem->buf_);
- free((void*)mem->part0_buf_);
+ WebPSafeFree(mem->buf_);
+ WebPSafeFree((void*)mem->part0_buf_);
}
}
@@ -206,35 +242,34 @@ static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) {
return 1;
}
+// To be called last.
+static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) {
+ const WebPDecoderOptions* const options = idec->params_.options;
+ WebPDecBuffer* const output = idec->params_.output;
+
+ idec->state_ = STATE_DONE;
+ if (options != NULL && options->flip) {
+ return WebPFlipBuffer(output);
+ } else {
+ return VP8_STATUS_OK;
+ }
+}
+
//------------------------------------------------------------------------------
// Macroblock-decoding contexts
static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br,
MBContext* const context) {
- const VP8BitReader* const br = &dec->br_;
- const VP8MB* const left = dec->mb_info_ - 1;
- const VP8MB* const info = dec->mb_info_ + dec->mb_x_;
-
- context->left_ = *left;
- context->info_ = *info;
- context->br_ = *br;
+ context->left_ = dec->mb_info_[-1];
+ context->info_ = dec->mb_info_[dec->mb_x_];
context->token_br_ = *token_br;
- memcpy(context->intra_t_, dec->intra_t_ + 4 * dec->mb_x_, 4);
- memcpy(context->intra_l_, dec->intra_l_, 4);
}
static void RestoreContext(const MBContext* context, VP8Decoder* const dec,
VP8BitReader* const token_br) {
- VP8BitReader* const br = &dec->br_;
- VP8MB* const left = dec->mb_info_ - 1;
- VP8MB* const info = dec->mb_info_ + dec->mb_x_;
-
- *left = context->left_;
- *info = context->info_;
- *br = context->br_;
+ dec->mb_info_[-1] = context->left_;
+ dec->mb_info_[dec->mb_x_] = context->info_;
*token_br = context->token_br_;
- memcpy(dec->intra_t_ + 4 * dec->mb_x_, context->intra_t_, 4);
- memcpy(dec->intra_l_, context->intra_l_, 4);
}
//------------------------------------------------------------------------------
@@ -242,7 +277,7 @@ static void RestoreContext(const MBContext* context, VP8Decoder* const dec,
static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) {
if (idec->state_ == STATE_VP8_DATA) {
VP8Io* const io = &idec->io_;
- if (io->teardown) {
+ if (io->teardown != NULL) {
io->teardown(io);
}
}
@@ -270,6 +305,7 @@ static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) {
headers.data = data;
headers.data_size = curr_size;
+ headers.have_all_data = 0;
status = WebPParseHeaders(&headers);
if (status == VP8_STATUS_NOT_ENOUGH_DATA) {
return VP8_STATUS_SUSPENDED; // We haven't found a VP8 chunk yet.
@@ -285,15 +321,9 @@ static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) {
return VP8_STATUS_OUT_OF_MEMORY;
}
idec->dec_ = dec;
-#ifdef WEBP_USE_THREAD
- dec->use_threads_ = (idec->params_.options != NULL) &&
- (idec->params_.options->use_threads > 0);
-#else
- dec->use_threads_ = 0;
-#endif
dec->alpha_data_ = headers.alpha_data;
dec->alpha_data_size_ = headers.alpha_data_size;
- ChangeState(idec, STATE_VP8_FRAME_HEADER, headers.offset);
+ ChangeState(idec, STATE_VP8_HEADER, headers.offset);
} else {
VP8LDecoder* const dec = VP8LNew();
if (dec == NULL) {
@@ -308,13 +338,14 @@ static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) {
static VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) {
const uint8_t* data = idec->mem_.buf_ + idec->mem_.start_;
const size_t curr_size = MemDataSize(&idec->mem_);
+ int width, height;
uint32_t bits;
if (curr_size < VP8_FRAME_HEADER_SIZE) {
// Not enough data bytes to extract VP8 Frame Header.
return VP8_STATUS_SUSPENDED;
}
- if (!VP8GetInfo(data, curr_size, idec->chunk_size_, NULL, NULL)) {
+ if (!VP8GetInfo(data, curr_size, idec->chunk_size_, &width, &height)) {
return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
}
@@ -328,30 +359,32 @@ static VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) {
}
// Partition #0
-static int CopyParts0Data(WebPIDecoder* const idec) {
+static VP8StatusCode CopyParts0Data(WebPIDecoder* const idec) {
VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
VP8BitReader* const br = &dec->br_;
- const size_t psize = br->buf_end_ - br->buf_;
+ const size_t part_size = br->buf_end_ - br->buf_;
MemBuffer* const mem = &idec->mem_;
assert(!idec->is_lossless_);
assert(mem->part0_buf_ == NULL);
- assert(psize > 0);
- assert(psize <= mem->part0_size_); // Format limit: no need for runtime check
+ // the following is a format limitation, no need for runtime check:
+ assert(part_size <= mem->part0_size_);
+ if (part_size == 0) { // can't have zero-size partition #0
+ return VP8_STATUS_BITSTREAM_ERROR;
+ }
if (mem->mode_ == MEM_MODE_APPEND) {
// We copy and grab ownership of the partition #0 data.
- uint8_t* const part0_buf = (uint8_t*)malloc(psize);
+ uint8_t* const part0_buf = (uint8_t*)WebPSafeMalloc(1ULL, part_size);
if (part0_buf == NULL) {
- return 0;
+ return VP8_STATUS_OUT_OF_MEMORY;
}
- memcpy(part0_buf, br->buf_, psize);
+ memcpy(part0_buf, br->buf_, part_size);
mem->part0_buf_ = part0_buf;
- br->buf_ = part0_buf;
- br->buf_end_ = part0_buf + psize;
+ VP8BitReaderSetBuffer(br, part0_buf, part_size);
} else {
// Else: just keep pointers to the partition #0's data in dec_->br_.
}
- mem->start_ += psize;
- return 1;
+ mem->start_ += part_size;
+ return VP8_STATUS_OK;
}
static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) {
@@ -381,9 +414,14 @@ static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) {
if (dec->status_ != VP8_STATUS_OK) {
return IDecError(idec, dec->status_);
}
+ // This change must be done before calling VP8InitFrame()
+ dec->mt_method_ = VP8GetThreadMethod(params->options, NULL,
+ io->width, io->height);
+ VP8InitDithering(params->options, dec);
- if (!CopyParts0Data(idec)) {
- return IDecError(idec, VP8_STATUS_OUT_OF_MEMORY);
+ dec->status_ = CopyParts0Data(idec);
+ if (dec->status_ != VP8_STATUS_OK) {
+ return IDecError(idec, dec->status_);
}
// Finish setting up the decoding parameters. Will call io->setup().
@@ -407,50 +445,52 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
VP8Io* const io = &idec->io_;
assert(dec->ready_);
-
for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) {
- VP8BitReader* token_br = &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)];
- if (dec->mb_x_ == 0) {
- VP8InitScanline(dec);
+ if (idec->last_mb_y_ != dec->mb_y_) {
+ if (!VP8ParseIntraModeRow(&dec->br_, dec)) {
+ // note: normally, error shouldn't occur since we already have the whole
+ // partition0 available here in DecodeRemaining(). Reaching EOF while
+ // reading intra modes really means a BITSTREAM_ERROR.
+ return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
+ }
+ idec->last_mb_y_ = dec->mb_y_;
}
- for (; dec->mb_x_ < dec->mb_w_; dec->mb_x_++) {
+ for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) {
+ VP8BitReader* const token_br =
+ &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)];
MBContext context;
SaveContext(dec, token_br, &context);
-
if (!VP8DecodeMB(dec, token_br)) {
- RestoreContext(&context, dec, token_br);
// We shouldn't fail when MAX_MB data was available
if (dec->num_parts_ == 1 && MemDataSize(&idec->mem_) > MAX_MB_SIZE) {
return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
}
+ RestoreContext(&context, dec, token_br);
return VP8_STATUS_SUSPENDED;
}
- VP8ReconstructBlock(dec);
- // Store data and save block's filtering params
- VP8StoreBlock(dec);
-
// Release buffer only if there is only one partition
if (dec->num_parts_ == 1) {
idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_;
assert(idec->mem_.start_ <= idec->mem_.end_);
}
}
+ VP8InitScanline(dec); // Prepare for next scanline
+
+ // Reconstruct, filter and emit the row.
if (!VP8ProcessRow(dec, io)) {
return IDecError(idec, VP8_STATUS_USER_ABORT);
}
- dec->mb_x_ = 0;
}
// Synchronize the thread and check for errors.
if (!VP8ExitCritical(dec, io)) {
return IDecError(idec, VP8_STATUS_USER_ABORT);
}
dec->ready_ = 0;
- idec->state_ = STATE_DONE;
-
- return VP8_STATUS_OK;
+ return FinishDecoding(idec);
}
-static int ErrorStatusLossless(WebPIDecoder* const idec, VP8StatusCode status) {
+static VP8StatusCode ErrorStatusLossless(WebPIDecoder* const idec,
+ VP8StatusCode status) {
if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) {
return VP8_STATUS_SUSPENDED;
}
@@ -467,9 +507,15 @@ static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) {
// Wait until there's enough data for decoding header.
if (curr_size < (idec->chunk_size_ >> 3)) {
- return VP8_STATUS_SUSPENDED;
+ dec->status_ = VP8_STATUS_SUSPENDED;
+ return ErrorStatusLossless(idec, dec->status_);
}
+
if (!VP8LDecodeHeader(dec, io)) {
+ if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR &&
+ curr_size < idec->chunk_size_) {
+ dec->status_ = VP8_STATUS_SUSPENDED;
+ }
return ErrorStatusLossless(idec, dec->status_);
}
// Allocate/verify output buffer now.
@@ -488,33 +534,29 @@ static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) {
const size_t curr_size = MemDataSize(&idec->mem_);
assert(idec->is_lossless_);
- // At present Lossless decoder can't decode image incrementally. So wait till
- // all the image data is aggregated before image can be decoded.
- if (curr_size < idec->chunk_size_) {
- return VP8_STATUS_SUSPENDED;
- }
+ // Switch to incremental decoding if we don't have all the bytes available.
+ dec->incremental_ = (curr_size < idec->chunk_size_);
if (!VP8LDecodeImage(dec)) {
return ErrorStatusLossless(idec, dec->status_);
}
-
- idec->state_ = STATE_DONE;
-
- return VP8_STATUS_OK;
+ assert(dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED);
+ return (dec->status_ == VP8_STATUS_SUSPENDED) ? dec->status_
+ : FinishDecoding(idec);
}
// Main decoding loop
static VP8StatusCode IDecode(WebPIDecoder* idec) {
VP8StatusCode status = VP8_STATUS_SUSPENDED;
- if (idec->state_ == STATE_PRE_VP8) {
+ if (idec->state_ == STATE_WEBP_HEADER) {
status = DecodeWebPHeaders(idec);
} else {
if (idec->dec_ == NULL) {
return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder.
}
}
- if (idec->state_ == STATE_VP8_FRAME_HEADER) {
+ if (idec->state_ == STATE_VP8_HEADER) {
status = DecodeVP8FrameHeader(idec);
}
if (idec->state_ == STATE_VP8_PARTS0) {
@@ -536,20 +578,23 @@ static VP8StatusCode IDecode(WebPIDecoder* idec) {
// Public functions
WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) {
- WebPIDecoder* idec = (WebPIDecoder*)calloc(1, sizeof(*idec));
+ WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec));
if (idec == NULL) {
return NULL;
}
- idec->state_ = STATE_PRE_VP8;
+ idec->state_ = STATE_WEBP_HEADER;
idec->chunk_size_ = 0;
+ idec->last_mb_y_ = -1;
+
InitMemBuffer(&idec->mem_);
WebPInitDecBuffer(&idec->output_);
VP8InitIo(&idec->io_);
WebPResetDecParams(&idec->params_);
- idec->params_.output = output_buffer ? output_buffer : &idec->output_;
+ idec->params_.output = (output_buffer != NULL) ? output_buffer
+ : &idec->output_;
WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions.
return idec;
@@ -581,14 +626,18 @@ void WebPIDelete(WebPIDecoder* idec) {
if (idec == NULL) return;
if (idec->dec_ != NULL) {
if (!idec->is_lossless_) {
- VP8Delete(idec->dec_);
+ if (idec->state_ == STATE_VP8_DATA) {
+ // Synchronize the thread, clean-up and check for errors.
+ VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_);
+ }
+ VP8Delete((VP8Decoder*)idec->dec_);
} else {
- VP8LDelete(idec->dec_);
+ VP8LDelete((VP8LDecoder*)idec->dec_);
}
}
ClearMemBuffer(&idec->mem_);
WebPFreeDecBuffer(&idec->output_);
- free(idec);
+ WebPSafeFree(idec);
}
//------------------------------------------------------------------------------
@@ -596,12 +645,22 @@ void WebPIDelete(WebPIDecoder* idec) {
WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer,
size_t output_buffer_size, int output_stride) {
+ const int is_external_memory = (output_buffer != NULL);
WebPIDecoder* idec;
+
if (mode >= MODE_YUV) return NULL;
+ if (!is_external_memory) { // Overwrite parameters to sane values.
+ output_buffer_size = 0;
+ output_stride = 0;
+ } else { // A buffer was passed. Validate the other params.
+ if (output_stride == 0 || output_buffer_size == 0) {
+ return NULL; // invalid parameter.
+ }
+ }
idec = WebPINewDecoder(NULL);
if (idec == NULL) return NULL;
idec->output_.colorspace = mode;
- idec->output_.is_external_memory = 1;
+ idec->output_.is_external_memory = is_external_memory;
idec->output_.u.RGBA.rgba = output_buffer;
idec->output_.u.RGBA.stride = output_stride;
idec->output_.u.RGBA.size = output_buffer_size;
@@ -612,10 +671,30 @@ WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride,
uint8_t* u, size_t u_size, int u_stride,
uint8_t* v, size_t v_size, int v_stride,
uint8_t* a, size_t a_size, int a_stride) {
- WebPIDecoder* const idec = WebPINewDecoder(NULL);
+ const int is_external_memory = (luma != NULL);
+ WebPIDecoder* idec;
+ WEBP_CSP_MODE colorspace;
+
+ if (!is_external_memory) { // Overwrite parameters to sane values.
+ luma_size = u_size = v_size = a_size = 0;
+ luma_stride = u_stride = v_stride = a_stride = 0;
+ u = v = a = NULL;
+ colorspace = MODE_YUVA;
+ } else { // A luma buffer was passed. Validate the other parameters.
+ if (u == NULL || v == NULL) return NULL;
+ if (luma_size == 0 || u_size == 0 || v_size == 0) return NULL;
+ if (luma_stride == 0 || u_stride == 0 || v_stride == 0) return NULL;
+ if (a != NULL) {
+ if (a_size == 0 || a_stride == 0) return NULL;
+ }
+ colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA;
+ }
+
+ idec = WebPINewDecoder(NULL);
if (idec == NULL) return NULL;
- idec->output_.colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA;
- idec->output_.is_external_memory = 1;
+
+ idec->output_.colorspace = colorspace;
+ idec->output_.is_external_memory = is_external_memory;
idec->output_.u.YUVA.y = luma;
idec->output_.u.YUVA.y_stride = luma_stride;
idec->output_.u.YUVA.y_size = luma_size;
@@ -768,7 +847,7 @@ int WebPISetIOHooks(WebPIDecoder* const idec,
VP8IoSetupHook setup,
VP8IoTeardownHook teardown,
void* user_data) {
- if (idec == NULL || idec->state_ > STATE_PRE_VP8) {
+ if (idec == NULL || idec->state_ > STATE_WEBP_HEADER) {
return 0;
}
@@ -779,7 +858,3 @@ int WebPISetIOHooks(WebPIDecoder* const idec,
return 1;
}
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/dec/io.c b/drivers/webp/dec/io.c
index 594804c2e6..13e469ab73 100644
--- a/drivers/webp/dec/io.c
+++ b/drivers/webp/dec/io.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// functions for sample output.
@@ -15,10 +17,7 @@
#include "./webpi.h"
#include "../dsp/dsp.h"
#include "../dsp/yuv.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+#include "../utils/utils.h"
//------------------------------------------------------------------------------
// Main YUV<->RGB conversion functions
@@ -46,57 +45,17 @@ static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) {
// Point-sampling U/V sampler.
static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) {
- WebPDecBuffer* output = p->output;
- const WebPRGBABuffer* const buf = &output->u.RGBA;
- uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
- const uint8_t* y_src = io->y;
- const uint8_t* u_src = io->u;
- const uint8_t* v_src = io->v;
- const WebPSampleLinePairFunc sample = WebPSamplers[output->colorspace];
- const int mb_w = io->mb_w;
- const int last = io->mb_h - 1;
- int j;
- for (j = 0; j < last; j += 2) {
- sample(y_src, y_src + io->y_stride, u_src, v_src,
- dst, dst + buf->stride, mb_w);
- y_src += 2 * io->y_stride;
- u_src += io->uv_stride;
- v_src += io->uv_stride;
- dst += 2 * buf->stride;
- }
- if (j == last) { // Just do the last line twice
- sample(y_src, y_src, u_src, v_src, dst, dst, mb_w);
- }
+ WebPDecBuffer* const output = p->output;
+ WebPRGBABuffer* const buf = &output->u.RGBA;
+ uint8_t* const dst = buf->rgba + io->mb_y * buf->stride;
+ WebPSamplerProcessPlane(io->y, io->y_stride,
+ io->u, io->v, io->uv_stride,
+ dst, buf->stride, io->mb_w, io->mb_h,
+ WebPSamplers[output->colorspace]);
return io->mb_h;
}
//------------------------------------------------------------------------------
-// YUV444 -> RGB conversion
-
-#if 0 // TODO(skal): this is for future rescaling.
-static int EmitRGB(const VP8Io* const io, WebPDecParams* const p) {
- WebPDecBuffer* output = p->output;
- const WebPRGBABuffer* const buf = &output->u.RGBA;
- uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
- const uint8_t* y_src = io->y;
- const uint8_t* u_src = io->u;
- const uint8_t* v_src = io->v;
- const WebPYUV444Converter convert = WebPYUV444Converters[output->colorspace];
- const int mb_w = io->mb_w;
- const int last = io->mb_h;
- int j;
- for (j = 0; j < last; ++j) {
- convert(y_src, u_src, v_src, dst, mb_w);
- y_src += io->y_stride;
- u_src += io->uv_stride;
- v_src += io->uv_stride;
- dst += buf->stride;
- }
- return io->mb_h;
-}
-#endif
-
-//------------------------------------------------------------------------------
// Fancy upsampling
#ifdef FANCY_UPSAMPLING
@@ -117,7 +76,7 @@ static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
if (y == 0) {
// First line is special cased. We mirror the u/v samples at boundary.
- upsample(NULL, cur_y, cur_u, cur_v, cur_u, cur_v, NULL, dst, mb_w);
+ upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, mb_w);
} else {
// We can finish the left-over line from previous call.
upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v,
@@ -160,14 +119,16 @@ static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
//------------------------------------------------------------------------------
-static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p) {
+static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p,
+ int expected_num_lines_out) {
const uint8_t* alpha = io->a;
const WebPYUVABuffer* const buf = &p->output->u.YUVA;
const int mb_w = io->mb_w;
const int mb_h = io->mb_h;
uint8_t* dst = buf->a + io->mb_y * buf->a_stride;
int j;
-
+ (void)expected_num_lines_out;
+ assert(expected_num_lines_out == mb_h);
if (alpha != NULL) {
for (j = 0; j < mb_h; ++j) {
memcpy(dst, alpha, mb_w * sizeof(*dst));
@@ -210,7 +171,8 @@ static int GetAlphaSourceRow(const VP8Io* const io,
return start_y;
}
-static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
+static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p,
+ int expected_num_lines_out) {
const uint8_t* alpha = io->a;
if (alpha != NULL) {
const int mb_w = io->mb_w;
@@ -221,21 +183,13 @@ static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
int num_rows;
const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
- uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
- uint32_t alpha_mask = 0xff;
- int i, j;
-
- for (j = 0; j < num_rows; ++j) {
- for (i = 0; i < mb_w; ++i) {
- const uint32_t alpha_value = alpha[i];
- dst[4 * i] = alpha_value;
- alpha_mask &= alpha_value;
- }
- alpha += io->width;
- dst += buf->stride;
- }
- // alpha_mask is < 0xff if there's non-trivial alpha to premultiply with.
- if (alpha_mask != 0xff && WebPIsPremultipliedMode(colorspace)) {
+ uint8_t* const dst = base_rgba + (alpha_first ? 0 : 3);
+ const int has_alpha = WebPDispatchAlpha(alpha, io->width, mb_w,
+ num_rows, dst, buf->stride);
+ (void)expected_num_lines_out;
+ assert(expected_num_lines_out == num_rows);
+ // has_alpha is true if there's non-trivial alpha to premultiply with.
+ if (has_alpha && WebPIsPremultipliedMode(colorspace)) {
WebPApplyAlphaMultiply(base_rgba, alpha_first,
mb_w, num_rows, buf->stride);
}
@@ -243,7 +197,8 @@ static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
return 0;
}
-static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p) {
+static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p,
+ int expected_num_lines_out) {
const uint8_t* alpha = io->a;
if (alpha != NULL) {
const int mb_w = io->mb_w;
@@ -252,10 +207,13 @@ static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p) {
int num_rows;
const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
+#ifdef WEBP_SWAP_16BIT_CSP
+ uint8_t* alpha_dst = base_rgba;
+#else
uint8_t* alpha_dst = base_rgba + 1;
+#endif
uint32_t alpha_mask = 0x0f;
int i, j;
-
for (j = 0; j < num_rows; ++j) {
for (i = 0; i < mb_w; ++i) {
// Fill in the alpha value (converted to 4 bits).
@@ -266,6 +224,8 @@ static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p) {
alpha += io->width;
alpha_dst += buf->stride;
}
+ (void)expected_num_lines_out;
+ assert(expected_num_lines_out == num_rows);
if (alpha_mask != 0x0f && WebPIsPremultipliedMode(colorspace)) {
WebPApplyAlphaMultiply4444(base_rgba, mb_w, num_rows, buf->stride);
}
@@ -291,15 +251,35 @@ static int Rescale(const uint8_t* src, int src_stride,
static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
const int mb_h = io->mb_h;
const int uv_mb_h = (mb_h + 1) >> 1;
- const int num_lines_out = Rescale(io->y, io->y_stride, mb_h, &p->scaler_y);
+ WebPRescaler* const scaler = &p->scaler_y;
+ int num_lines_out = 0;
+ if (WebPIsAlphaMode(p->output->colorspace) && io->a != NULL) {
+ // Before rescaling, we premultiply the luma directly into the io->y
+ // internal buffer. This is OK since these samples are not used for
+ // intra-prediction (the top samples are saved in cache_y_/u_/v_).
+ // But we need to cast the const away, though.
+ WebPMultRows((uint8_t*)io->y, io->y_stride,
+ io->a, io->width, io->mb_w, mb_h, 0);
+ }
+ num_lines_out = Rescale(io->y, io->y_stride, mb_h, scaler);
Rescale(io->u, io->uv_stride, uv_mb_h, &p->scaler_u);
Rescale(io->v, io->uv_stride, uv_mb_h, &p->scaler_v);
return num_lines_out;
}
-static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p) {
+static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p,
+ int expected_num_lines_out) {
if (io->a != NULL) {
- Rescale(io->a, io->width, io->mb_h, &p->scaler_a);
+ const WebPYUVABuffer* const buf = &p->output->u.YUVA;
+ uint8_t* dst_y = buf->y + p->last_y * buf->y_stride;
+ const uint8_t* src_a = buf->a + p->last_y * buf->a_stride;
+ const int num_lines_out = Rescale(io->a, io->width, io->mb_h, &p->scaler_a);
+ (void)expected_num_lines_out;
+ assert(expected_num_lines_out == num_lines_out);
+ if (num_lines_out > 0) { // unmultiply the Y
+ WebPMultRows(dst_y, buf->y_stride, src_a, buf->a_stride,
+ p->scaler_a.dst_width, num_lines_out, 1);
+ }
}
return 0;
}
@@ -316,39 +296,34 @@ static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
const size_t work_size = 2 * out_width; // scratch memory for luma rescaler
const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones
size_t tmp_size;
- int32_t* work;
+ rescaler_t* work;
- tmp_size = work_size + 2 * uv_work_size;
+ tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work);
if (has_alpha) {
- tmp_size += work_size;
+ tmp_size += work_size * sizeof(*work);
}
- p->memory = calloc(1, tmp_size * sizeof(*work));
+ p->memory = WebPSafeMalloc(1ULL, tmp_size);
if (p->memory == NULL) {
return 0; // memory error
}
- work = (int32_t*)p->memory;
+ work = (rescaler_t*)p->memory;
WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h,
buf->y, out_width, out_height, buf->y_stride, 1,
- io->mb_w, out_width, io->mb_h, out_height,
work);
WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
buf->u, uv_out_width, uv_out_height, buf->u_stride, 1,
- uv_in_width, uv_out_width,
- uv_in_height, uv_out_height,
work + work_size);
WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height,
buf->v, uv_out_width, uv_out_height, buf->v_stride, 1,
- uv_in_width, uv_out_width,
- uv_in_height, uv_out_height,
work + work_size + uv_work_size);
p->emit = EmitRescaledYUV;
if (has_alpha) {
WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h,
buf->a, out_width, out_height, buf->a_stride, 1,
- io->mb_w, out_width, io->mb_h, out_height,
work + work_size + 2 * uv_work_size);
p->emit_alpha = EmitRescaledAlphaYUV;
+ WebPInitAlphaProcessing();
}
return 1;
}
@@ -360,13 +335,13 @@ static int ExportRGB(WebPDecParams* const p, int y_pos) {
const WebPYUV444Converter convert =
WebPYUV444Converters[p->output->colorspace];
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- uint8_t* dst = buf->rgba + (p->last_y + y_pos) * buf->stride;
+ uint8_t* dst = buf->rgba + y_pos * buf->stride;
int num_lines_out = 0;
// For RGB rescaling, because of the YUV420, current scan position
// U/V can be +1/-1 line from the Y one. Hence the double test.
while (WebPRescalerHasPendingOutput(&p->scaler_y) &&
WebPRescalerHasPendingOutput(&p->scaler_u)) {
- assert(p->last_y + y_pos + num_lines_out < p->output->height);
+ assert(y_pos + num_lines_out < p->output->height);
assert(p->scaler_u.y_accum == p->scaler_v.y_accum);
WebPRescalerExportRow(&p->scaler_y);
WebPRescalerExportRow(&p->scaler_u);
@@ -388,65 +363,69 @@ static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
const int y_lines_in =
WebPRescalerImport(&p->scaler_y, mb_h - j,
io->y + j * io->y_stride, io->y_stride);
- const int u_lines_in =
- WebPRescalerImport(&p->scaler_u, uv_mb_h - uv_j,
- io->u + uv_j * io->uv_stride, io->uv_stride);
- const int v_lines_in =
- WebPRescalerImport(&p->scaler_v, uv_mb_h - uv_j,
- io->v + uv_j * io->uv_stride, io->uv_stride);
- (void)v_lines_in; // remove a gcc warning
- assert(u_lines_in == v_lines_in);
j += y_lines_in;
- uv_j += u_lines_in;
- num_lines_out += ExportRGB(p, num_lines_out);
+ if (WebPRescaleNeededLines(&p->scaler_u, uv_mb_h - uv_j)) {
+ const int u_lines_in =
+ WebPRescalerImport(&p->scaler_u, uv_mb_h - uv_j,
+ io->u + uv_j * io->uv_stride, io->uv_stride);
+ const int v_lines_in =
+ WebPRescalerImport(&p->scaler_v, uv_mb_h - uv_j,
+ io->v + uv_j * io->uv_stride, io->uv_stride);
+ (void)v_lines_in; // remove a gcc warning
+ assert(u_lines_in == v_lines_in);
+ uv_j += u_lines_in;
+ }
+ num_lines_out += ExportRGB(p, p->last_y + num_lines_out);
}
return num_lines_out;
}
-static int ExportAlpha(WebPDecParams* const p, int y_pos) {
+static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) {
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride;
+ uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride;
const WEBP_CSP_MODE colorspace = p->output->colorspace;
const int alpha_first =
(colorspace == MODE_ARGB || colorspace == MODE_Argb);
uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
int num_lines_out = 0;
const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
- uint32_t alpha_mask = 0xff;
+ uint32_t non_opaque = 0;
const int width = p->scaler_a.dst_width;
- while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
- int i;
- assert(p->last_y + y_pos + num_lines_out < p->output->height);
+ while (WebPRescalerHasPendingOutput(&p->scaler_a) &&
+ num_lines_out < max_lines_out) {
+ assert(y_pos + num_lines_out < p->output->height);
WebPRescalerExportRow(&p->scaler_a);
- for (i = 0; i < width; ++i) {
- const uint32_t alpha_value = p->scaler_a.dst[i];
- dst[4 * i] = alpha_value;
- alpha_mask &= alpha_value;
- }
+ non_opaque |= WebPDispatchAlpha(p->scaler_a.dst, 0, width, 1, dst, 0);
dst += buf->stride;
++num_lines_out;
}
- if (is_premult_alpha && alpha_mask != 0xff) {
+ if (is_premult_alpha && non_opaque) {
WebPApplyAlphaMultiply(base_rgba, alpha_first,
width, num_lines_out, buf->stride);
}
return num_lines_out;
}
-static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos) {
+static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos,
+ int max_lines_out) {
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride;
+ uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride;
+#ifdef WEBP_SWAP_16BIT_CSP
+ uint8_t* alpha_dst = base_rgba;
+#else
uint8_t* alpha_dst = base_rgba + 1;
+#endif
int num_lines_out = 0;
const WEBP_CSP_MODE colorspace = p->output->colorspace;
const int width = p->scaler_a.dst_width;
const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
uint32_t alpha_mask = 0x0f;
- while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
+ while (WebPRescalerHasPendingOutput(&p->scaler_a) &&
+ num_lines_out < max_lines_out) {
int i;
- assert(p->last_y + y_pos + num_lines_out < p->output->height);
+ assert(y_pos + num_lines_out < p->output->height);
WebPRescalerExportRow(&p->scaler_a);
for (i = 0; i < width; ++i) {
// Fill in the alpha value (converted to 4 bits).
@@ -463,15 +442,17 @@ static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos) {
return num_lines_out;
}
-static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
+static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p,
+ int expected_num_out_lines) {
if (io->a != NULL) {
WebPRescaler* const scaler = &p->scaler_a;
- int j = 0;
- int pos = 0;
- while (j < io->mb_h) {
- j += WebPRescalerImport(scaler, io->mb_h - j,
- io->a + j * io->width, io->width);
- pos += p->emit_alpha_row(p, pos);
+ int lines_left = expected_num_out_lines;
+ const int y_end = p->last_y + lines_left;
+ while (lines_left > 0) {
+ const int row_offset = scaler->src_y - io->mb_y;
+ WebPRescalerImport(scaler, io->mb_h + io->mb_y - scaler->src_y,
+ io->a + row_offset * io->width, io->width);
+ lines_left -= p->emit_alpha_row(p, y_end - lines_left, lines_left);
}
}
return 0;
@@ -484,9 +465,9 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
const int uv_in_width = (io->mb_w + 1) >> 1;
const int uv_in_height = (io->mb_h + 1) >> 1;
const size_t work_size = 2 * out_width; // scratch memory for one rescaler
- int32_t* work; // rescalers work area
+ rescaler_t* work; // rescalers work area
uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion
- size_t tmp_size1, tmp_size2;
+ size_t tmp_size1, tmp_size2, total_size;
tmp_size1 = 3 * work_size;
tmp_size2 = 3 * out_width;
@@ -494,30 +475,28 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
tmp_size1 += work_size;
tmp_size2 += out_width;
}
- p->memory = calloc(1, tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp));
+ total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp);
+ p->memory = WebPSafeMalloc(1ULL, total_size);
if (p->memory == NULL) {
return 0; // memory error
}
- work = (int32_t*)p->memory;
+ work = (rescaler_t*)p->memory;
tmp = (uint8_t*)(work + tmp_size1);
WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h,
tmp + 0 * out_width, out_width, out_height, 0, 1,
- io->mb_w, out_width, io->mb_h, out_height,
work + 0 * work_size);
WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
tmp + 1 * out_width, out_width, out_height, 0, 1,
- io->mb_w, 2 * out_width, io->mb_h, 2 * out_height,
work + 1 * work_size);
WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height,
tmp + 2 * out_width, out_width, out_height, 0, 1,
- io->mb_w, 2 * out_width, io->mb_h, 2 * out_height,
work + 2 * work_size);
p->emit = EmitRescaledRGB;
+ WebPInitYUV444Converters();
if (has_alpha) {
WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h,
tmp + 3 * out_width, out_width, out_height, 0, 1,
- io->mb_w, out_width, io->mb_h, out_height,
work + 3 * work_size);
p->emit_alpha = EmitRescaledAlphaRGB;
if (p->output->colorspace == MODE_RGBA_4444 ||
@@ -526,6 +505,7 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
} else {
p->emit_alpha_row = ExportAlpha;
}
+ WebPInitAlphaProcessing();
}
return 1;
}
@@ -546,7 +526,9 @@ static int CustomSetup(VP8Io* io) {
if (!WebPIoInitFromOptions(p->options, io, is_alpha ? MODE_YUV : MODE_YUVA)) {
return 0;
}
-
+ if (is_alpha && WebPIsPremultipliedMode(colorspace)) {
+ WebPInitUpsamplers();
+ }
if (io->use_scaling) {
const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p);
if (!ok) {
@@ -554,11 +536,12 @@ static int CustomSetup(VP8Io* io) {
}
} else {
if (is_rgb) {
+ WebPInitSamplers();
p->emit = EmitSampledRGB; // default
-#ifdef FANCY_UPSAMPLING
if (io->fancy_upsampling) {
+#ifdef FANCY_UPSAMPLING
const int uv_width = (io->mb_w + 1) >> 1;
- p->memory = malloc(io->mb_w + 2 * uv_width);
+ p->memory = WebPSafeMalloc(1ULL, (size_t)(io->mb_w + 2 * uv_width));
if (p->memory == NULL) {
return 0; // memory error.
}
@@ -567,18 +550,20 @@ static int CustomSetup(VP8Io* io) {
p->tmp_v = p->tmp_u + uv_width;
p->emit = EmitFancyRGB;
WebPInitUpsamplers();
- }
#endif
+ }
} else {
p->emit = EmitYUV;
}
if (is_alpha) { // need transparency output
- if (WebPIsPremultipliedMode(colorspace)) WebPInitPremultiply();
p->emit_alpha =
(colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444) ?
EmitAlphaRGBA4444
: is_rgb ? EmitAlphaRGB
: EmitAlphaYUV;
+ if (is_rgb) {
+ WebPInitAlphaProcessing();
+ }
}
}
@@ -601,8 +586,8 @@ static int CustomPut(const VP8Io* io) {
return 0;
}
num_lines_out = p->emit(io, p);
- if (p->emit_alpha) {
- p->emit_alpha(io, p);
+ if (p->emit_alpha != NULL) {
+ p->emit_alpha(io, p, num_lines_out);
}
p->last_y += num_lines_out;
return 1;
@@ -612,7 +597,7 @@ static int CustomPut(const VP8Io* io) {
static void CustomTeardown(const VP8Io* io) {
WebPDecParams* const p = (WebPDecParams*)io->opaque;
- free(p->memory);
+ WebPSafeFree(p->memory);
p->memory = NULL;
}
@@ -627,7 +612,3 @@ void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) {
}
//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/dec/quant.c b/drivers/webp/dec/quant.c
index d54097af0d..5b648f942c 100644
--- a/drivers/webp/dec/quant.c
+++ b/drivers/webp/dec/quant.c
@@ -1,8 +1,10 @@
// Copyright 2010 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Quantizer initialization
@@ -11,10 +13,6 @@
#include "./vp8i.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
static WEBP_INLINE int clip(int v, int M) {
return v < 0 ? 0 : v > M ? M : v;
}
@@ -102,12 +100,11 @@ void VP8ParseQuant(VP8Decoder* const dec) {
m->uv_mat_[0] = kDcTable[clip(q + dquv_dc, 117)];
m->uv_mat_[1] = kAcTable[clip(q + dquv_ac, 127)];
+
+ m->uv_quant_ = q + dquv_ac; // for dithering strength evaluation
}
}
}
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/dec/tree.c b/drivers/webp/dec/tree.c
index 82484e4c55..c2007ea733 100644
--- a/drivers/webp/dec/tree.c
+++ b/drivers/webp/dec/tree.c
@@ -1,22 +1,21 @@
// Copyright 2010 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Coding trees and probas
//
// Author: Skal (pascal.massimino@gmail.com)
-#include "vp8i.h"
+#include "./vp8i.h"
+#include "../utils/bit_reader_inl.h"
#define USE_GENERIC_TREE
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
#ifdef USE_GENERIC_TREE
static const int8_t kYModesIntra4[18] = {
-B_DC_PRED, 1,
@@ -31,61 +30,12 @@ static const int8_t kYModesIntra4[18] = {
};
#endif
-#ifndef ONLY_KEYFRAME_CODE
-
-// inter prediction modes
-enum {
- LEFT4 = 0, ABOVE4 = 1, ZERO4 = 2, NEW4 = 3,
- NEARESTMV, NEARMV, ZEROMV, NEWMV, SPLITMV };
-
-static const int8_t kYModesInter[8] = {
- -DC_PRED, 1,
- 2, 3,
- -V_PRED, -H_PRED,
- -TM_PRED, -B_PRED
-};
-
-static const int8_t kMBSplit[6] = {
- -3, 1,
- -2, 2,
- -0, -1
-};
-
-static const int8_t kMVRef[8] = {
- -ZEROMV, 1,
- -NEARESTMV, 2,
- -NEARMV, 3,
- -NEWMV, -SPLITMV
-};
-
-static const int8_t kMVRef4[6] = {
- -LEFT4, 1,
- -ABOVE4, 2,
- -ZERO4, -NEW4
-};
-#endif
-
//------------------------------------------------------------------------------
// Default probabilities
-// Inter
-#ifndef ONLY_KEYFRAME_CODE
-static const uint8_t kYModeProbaInter0[4] = { 112, 86, 140, 37 };
-static const uint8_t kUVModeProbaInter0[3] = { 162, 101, 204 };
-static const uint8_t kMVProba0[2][NUM_MV_PROBAS] = {
- { 162, 128, 225, 146, 172, 147, 214, 39,
- 156, 128, 129, 132, 75, 145, 178, 206,
- 239, 254, 254 },
- { 164, 128, 204, 170, 119, 235, 140, 230,
- 228, 128, 130, 130, 74, 148, 180, 203,
- 236, 254, 254 }
-};
-#endif
-
// Paragraph 13.5
static const uint8_t
CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
- // genereated using vp8_default_coef_probs() in entropy.c:129
{ { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
{ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
{ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
@@ -326,28 +276,38 @@ static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = {
void VP8ResetProba(VP8Proba* const proba) {
memset(proba->segments_, 255u, sizeof(proba->segments_));
- memcpy(proba->coeffs_, CoeffsProba0, sizeof(CoeffsProba0));
-#ifndef ONLY_KEYFRAME_CODE
- memcpy(proba->mv_, kMVProba0, sizeof(kMVProba0));
- memcpy(proba->ymode_, kYModeProbaInter0, sizeof(kYModeProbaInter0));
- memcpy(proba->uvmode_, kUVModeProbaInter0, sizeof(kUVModeProbaInter0));
-#endif
+ // proba->bands_[][] is initialized later
}
-void VP8ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec) {
- uint8_t* const top = dec->intra_t_ + 4 * dec->mb_x_;
+static void ParseIntraMode(VP8BitReader* const br,
+ VP8Decoder* const dec, int mb_x) {
+ uint8_t* const top = dec->intra_t_ + 4 * mb_x;
uint8_t* const left = dec->intra_l_;
- // Hardcoded 16x16 intra-mode decision tree.
- dec->is_i4x4_ = !VP8GetBit(br, 145); // decide for B_PRED first
- if (!dec->is_i4x4_) {
+ VP8MBData* const block = dec->mb_data_ + mb_x;
+
+ // Note: we don't save segment map (yet), as we don't expect
+ // to decode more than 1 keyframe.
+ if (dec->segment_hdr_.update_map_) {
+ // Hardcoded tree parsing
+ block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0])
+ ? VP8GetBit(br, dec->proba_.segments_[1])
+ : 2 + VP8GetBit(br, dec->proba_.segments_[2]);
+ } else {
+ block->segment_ = 0; // default for intra
+ }
+ if (dec->use_skip_proba_) block->skip_ = VP8GetBit(br, dec->skip_p_);
+
+ block->is_i4x4_ = !VP8GetBit(br, 145); // decide for B_PRED first
+ if (!block->is_i4x4_) {
+ // Hardcoded 16x16 intra-mode decision tree.
const int ymode =
VP8GetBit(br, 156) ? (VP8GetBit(br, 128) ? TM_PRED : H_PRED)
: (VP8GetBit(br, 163) ? V_PRED : DC_PRED);
- dec->imodes_[0] = ymode;
- memset(top, ymode, 4 * sizeof(top[0]));
- memset(left, ymode, 4 * sizeof(left[0]));
+ block->imodes_[0] = ymode;
+ memset(top, ymode, 4 * sizeof(*top));
+ memset(left, ymode, 4 * sizeof(*left));
} else {
- uint8_t* modes = dec->imodes_;
+ uint8_t* modes = block->imodes_;
int y;
for (y = 0; y < 4; ++y) {
int ymode = left[y];
@@ -356,10 +316,10 @@ void VP8ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec) {
const uint8_t* const prob = kBModesProba[top[x]][ymode];
#ifdef USE_GENERIC_TREE
// Generic tree-parsing
- int i = 0;
- do {
+ int i = kYModesIntra4[VP8GetBit(br, prob[0])];
+ while (i > 0) {
i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])];
- } while (i > 0);
+ }
ymode = -i;
#else
// Hardcoded tree parsing
@@ -374,15 +334,24 @@ void VP8ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec) {
(!VP8GetBit(br, prob[8]) ? B_HD_PRED : B_HU_PRED)));
#endif // USE_GENERIC_TREE
top[x] = ymode;
- *modes++ = ymode;
}
+ memcpy(modes, top, 4 * sizeof(*top));
+ modes += 4;
left[y] = ymode;
}
}
// Hardcoded UVMode decision tree
- dec->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED
- : !VP8GetBit(br, 114) ? V_PRED
- : VP8GetBit(br, 183) ? TM_PRED : H_PRED;
+ block->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED
+ : !VP8GetBit(br, 114) ? V_PRED
+ : VP8GetBit(br, 183) ? TM_PRED : H_PRED;
+}
+
+int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) {
+ int mb_x;
+ for (mb_x = 0; mb_x < dec->mb_w_; ++mb_x) {
+ ParseIntraMode(br, dec, mb_x);
+ }
+ return !dec->br_.eof_;
}
//------------------------------------------------------------------------------
@@ -524,18 +493,13 @@ static const uint8_t
}
};
-#ifndef ONLY_KEYFRAME_CODE
-static const uint8_t MVUpdateProba[2][NUM_MV_PROBAS] = {
- { 237, 246, 253, 253, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 250, 250,
- 252, 254, 254 },
- { 231, 243, 245, 253, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 251, 251,
- 254, 254, 254 }
+// Paragraph 9.9
+
+static const int kBands[16 + 1] = {
+ 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
+ 0 // extra entry as sentinel
};
-#endif
-// Paragraph 9.9
void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
VP8Proba* const proba = &dec->proba_;
int t, b, c, p;
@@ -543,47 +507,19 @@ void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
for (b = 0; b < NUM_BANDS; ++b) {
for (c = 0; c < NUM_CTX; ++c) {
for (p = 0; p < NUM_PROBAS; ++p) {
- if (VP8GetBit(br, CoeffsUpdateProba[t][b][c][p])) {
- proba->coeffs_[t][b][c][p] = VP8GetValue(br, 8);
- }
+ const int v = VP8GetBit(br, CoeffsUpdateProba[t][b][c][p]) ?
+ VP8GetValue(br, 8) : CoeffsProba0[t][b][c][p];
+ proba->bands_[t][b].probas_[c][p] = v;
}
}
}
+ for (b = 0; b < 16 + 1; ++b) {
+ proba->bands_ptr_[t][b] = &proba->bands_[t][kBands[b]];
+ }
}
dec->use_skip_proba_ = VP8Get(br);
if (dec->use_skip_proba_) {
dec->skip_p_ = VP8GetValue(br, 8);
}
-#ifndef ONLY_KEYFRAME_CODE
- if (!dec->frm_hdr_.key_frame_) {
- int i;
- dec->intra_p_ = VP8GetValue(br, 8);
- dec->last_p_ = VP8GetValue(br, 8);
- dec->golden_p_ = VP8GetValue(br, 8);
- if (VP8Get(br)) { // update y-mode
- for (i = 0; i < 4; ++i) {
- proba->ymode_[i] = VP8GetValue(br, 8);
- }
- }
- if (VP8Get(br)) { // update uv-mode
- for (i = 0; i < 3; ++i) {
- proba->uvmode_[i] = VP8GetValue(br, 8);
- }
- }
- // update MV
- for (i = 0; i < 2; ++i) {
- int k;
- for (k = 0; k < NUM_MV_PROBAS; ++k) {
- if (VP8GetBit(br, MVUpdateProba[i][k])) {
- const int v = VP8GetValue(br, 7);
- proba->mv_[i][k] = v ? v << 1 : 1;
- }
- }
- }
- }
-#endif
}
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/dec/vp8.c b/drivers/webp/dec/vp8.c
index b0ccfa2a06..d89eb1c59e 100644
--- a/drivers/webp/dec/vp8.c
+++ b/drivers/webp/dec/vp8.c
@@ -1,8 +1,10 @@
// Copyright 2010 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// main entry for the decoder
@@ -11,14 +13,12 @@
#include <stdlib.h>
+#include "./alphai.h"
#include "./vp8i.h"
#include "./vp8li.h"
#include "./webpi.h"
-#include "../utils/bit_reader.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+#include "../utils/bit_reader_inl.h"
+#include "../utils/utils.h"
//------------------------------------------------------------------------------
@@ -45,10 +45,10 @@ int VP8InitIoInternal(VP8Io* const io, int version) {
}
VP8Decoder* VP8New(void) {
- VP8Decoder* const dec = (VP8Decoder*)calloc(1, sizeof(*dec));
+ VP8Decoder* const dec = (VP8Decoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
if (dec != NULL) {
SetOk(dec);
- WebPWorkerInit(&dec->worker_);
+ WebPGetWorkerInterface()->Init(&dec->worker_);
dec->ready_ = 0;
dec->num_parts_ = 1;
}
@@ -69,16 +69,13 @@ const char* VP8StatusMessage(VP8Decoder* const dec) {
void VP8Delete(VP8Decoder* const dec) {
if (dec != NULL) {
VP8Clear(dec);
- free(dec);
+ WebPSafeFree(dec);
}
}
int VP8SetError(VP8Decoder* const dec,
VP8StatusCode error, const char* const msg) {
- // TODO This check would be unnecessary if alpha decompression was separated
- // from VP8ProcessRow/FinishRow. This avoids setting 'dec->status_' to
- // something other than VP8_STATUS_BITSTREAM_ERROR on alpha decompression
- // failure.
+ // The oldest error reported takes precedence over the new one.
if (dec->status_ == VP8_STATUS_OK) {
dec->status_ = error;
dec->error_msg_ = msg;
@@ -121,6 +118,9 @@ int VP8GetInfo(const uint8_t* data, size_t data_size, size_t chunk_size,
if (((bits >> 5)) >= chunk_size) { // partition_length
return 0; // inconsistent size information.
}
+ if (w == 0 || h == 0) {
+ return 0; // We don't support both width and height to be zero.
+ }
if (width) {
*width = w;
@@ -190,25 +190,27 @@ static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
const uint8_t* sz = buf;
const uint8_t* buf_end = buf + size;
const uint8_t* part_start;
- int last_part;
- int p;
+ size_t size_left = size;
+ size_t last_part;
+ size_t p;
dec->num_parts_ = 1 << VP8GetValue(br, 2);
last_part = dec->num_parts_ - 1;
- part_start = buf + last_part * 3;
- if (buf_end < part_start) {
+ if (size < 3 * last_part) {
// we can't even read the sizes with sz[]! That's a failure.
return VP8_STATUS_NOT_ENOUGH_DATA;
}
+ part_start = buf + last_part * 3;
+ size_left -= last_part * 3;
for (p = 0; p < last_part; ++p) {
- const uint32_t psize = sz[0] | (sz[1] << 8) | (sz[2] << 16);
- const uint8_t* part_end = part_start + psize;
- if (part_end > buf_end) part_end = buf_end;
- VP8InitBitReader(dec->parts_ + p, part_start, part_end);
- part_start = part_end;
+ size_t psize = sz[0] | (sz[1] << 8) | (sz[2] << 16);
+ if (psize > size_left) psize = size_left;
+ VP8InitBitReader(dec->parts_ + p, part_start, psize);
+ part_start += psize;
+ size_left -= psize;
sz += 3;
}
- VP8InitBitReader(dec->parts_ + last_part, part_start, buf_end);
+ VP8InitBitReader(dec->parts_ + last_part, part_start, size_left);
return (part_start < buf_end) ? VP8_STATUS_OK :
VP8_STATUS_SUSPENDED; // Init is ok, but there's not enough data
}
@@ -236,20 +238,6 @@ static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) {
}
}
dec->filter_type_ = (hdr->level_ == 0) ? 0 : hdr->simple_ ? 1 : 2;
- if (dec->filter_type_ > 0) { // precompute filter levels per segment
- if (dec->segment_hdr_.use_segment_) {
- int s;
- for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- int strength = dec->segment_hdr_.filter_strength_[s];
- if (!dec->segment_hdr_.absolute_delta_) {
- strength += hdr->level_;
- }
- dec->filter_levels_[s] = strength;
- }
- } else {
- dec->filter_levels_[0] = hdr->level_;
- }
- }
return !br->eof_;
}
@@ -261,7 +249,6 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
VP8PictureHeader* pic_hdr;
VP8BitReader* br;
VP8StatusCode status;
- WebPHeaderStructure headers;
if (dec == NULL) {
return 0;
@@ -271,33 +258,8 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
return VP8SetError(dec, VP8_STATUS_INVALID_PARAM,
"null VP8Io passed to VP8GetHeaders()");
}
-
- // Process Pre-VP8 chunks.
- headers.data = io->data;
- headers.data_size = io->data_size;
- status = WebPParseHeaders(&headers);
- if (status != VP8_STATUS_OK) {
- return VP8SetError(dec, status, "Incorrect/incomplete header.");
- }
- if (headers.is_lossless) {
- return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
- "Unexpected lossless format encountered.");
- }
-
- if (dec->alpha_data_ == NULL) {
- assert(dec->alpha_data_size_ == 0);
- // We have NOT set alpha data yet. Set it now.
- // (This is to ensure that dec->alpha_data_ is NOT reset to NULL if
- // WebPParseHeaders() is called more than once, as in incremental decoding
- // case.)
- dec->alpha_data_ = headers.alpha_data;
- dec->alpha_data_size_ = headers.alpha_data_size;
- }
-
- // Process the VP8 frame header.
- buf = headers.data + headers.offset;
- buf_size = headers.data_size - headers.offset;
- assert(headers.data_size >= headers.offset); // WebPParseHeaders' guarantee
+ buf = io->data;
+ buf_size = io->data_size;
if (buf_size < 4) {
return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
"Truncated header.");
@@ -355,7 +317,6 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
VP8ResetProba(&dec->proba_);
ResetSegmentHeader(&dec->segment_hdr_);
- dec->segment_ = 0; // default for intra
}
// Check if we have all the partition #0 available, and initialize dec->br_
@@ -366,7 +327,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
}
br = &dec->br_;
- VP8InitBitReader(br, buf, buf + frm_hdr->partition_length_);
+ VP8InitBitReader(br, buf, frm_hdr->partition_length_);
buf += frm_hdr->partition_length_;
buf_size -= frm_hdr->partition_length_;
@@ -393,63 +354,14 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
// Frame buffer marking
if (!frm_hdr->key_frame_) {
- // Paragraph 9.7
-#ifndef ONLY_KEYFRAME_CODE
- dec->buffer_flags_ = VP8Get(br) << 0; // update golden
- dec->buffer_flags_ |= VP8Get(br) << 1; // update alt ref
- if (!(dec->buffer_flags_ & 1)) {
- dec->buffer_flags_ |= VP8GetValue(br, 2) << 2;
- }
- if (!(dec->buffer_flags_ & 2)) {
- dec->buffer_flags_ |= VP8GetValue(br, 2) << 4;
- }
- dec->buffer_flags_ |= VP8Get(br) << 6; // sign bias golden
- dec->buffer_flags_ |= VP8Get(br) << 7; // sign bias alt ref
-#else
return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE,
"Not a key frame.");
-#endif
- } else {
- dec->buffer_flags_ = 0x003 | 0x100;
}
- // Paragraph 9.8
-#ifndef ONLY_KEYFRAME_CODE
- dec->update_proba_ = VP8Get(br);
- if (!dec->update_proba_) { // save for later restore
- dec->proba_saved_ = dec->proba_;
- }
- dec->buffer_flags_ &= 1 << 8;
- dec->buffer_flags_ |=
- (frm_hdr->key_frame_ || VP8Get(br)) << 8; // refresh last frame
-#else
- VP8Get(br); // just ignore the value of update_proba_
-#endif
+ VP8Get(br); // ignore the value of update_proba_
VP8ParseProba(br, dec);
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- // Extensions
- if (dec->pic_hdr_.colorspace_) {
- const size_t kTrailerSize = 8;
- const uint8_t kTrailerMarker = 0x01;
- const uint8_t* ext_buf = buf - kTrailerSize;
- size_t size;
-
- if (frm_hdr->partition_length_ < kTrailerSize ||
- ext_buf[kTrailerSize - 1] != kTrailerMarker) {
- return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
- "RIFF: Inconsistent extra information.");
- }
-
- // Layer
- size = (ext_buf[0] << 0) | (ext_buf[1] << 8) | (ext_buf[2] << 16);
- dec->layer_data_size_ = size;
- dec->layer_data_ = NULL; // will be set later
- dec->layer_colorspace_ = ext_buf[3];
- }
-#endif
-
// sanitized state
dec->ready_ = 1;
return 1;
@@ -458,11 +370,6 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
//------------------------------------------------------------------------------
// Residual decoding (Paragraph 13.2 / 13.3)
-static const uint8_t kBands[16 + 1] = {
- 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
- 0 // extra entry as sentinel
-};
-
static const uint8_t kCat3[] = { 173, 148, 140, 0 };
static const uint8_t kCat4[] = { 176, 155, 140, 135, 0 };
static const uint8_t kCat5[] = { 180, 157, 141, 134, 130, 0 };
@@ -473,253 +380,226 @@ static const uint8_t kZigzag[16] = {
0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
};
-typedef const uint8_t (*ProbaArray)[NUM_CTX][NUM_PROBAS]; // for const-casting
+// See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2
+static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) {
+ int v;
+ if (!VP8GetBit(br, p[3])) {
+ if (!VP8GetBit(br, p[4])) {
+ v = 2;
+ } else {
+ v = 3 + VP8GetBit(br, p[5]);
+ }
+ } else {
+ if (!VP8GetBit(br, p[6])) {
+ if (!VP8GetBit(br, p[7])) {
+ v = 5 + VP8GetBit(br, 159);
+ } else {
+ v = 7 + 2 * VP8GetBit(br, 165);
+ v += VP8GetBit(br, 145);
+ }
+ } else {
+ const uint8_t* tab;
+ const int bit1 = VP8GetBit(br, p[8]);
+ const int bit0 = VP8GetBit(br, p[9 + bit1]);
+ const int cat = 2 * bit1 + bit0;
+ v = 0;
+ for (tab = kCat3456[cat]; *tab; ++tab) {
+ v += v + VP8GetBit(br, *tab);
+ }
+ v += 3 + (8 << cat);
+ }
+ }
+ return v;
+}
// Returns the position of the last non-zero coeff plus one
-// (and 0 if there's no coeff at all)
-static int GetCoeffs(VP8BitReader* const br, ProbaArray prob,
+static int GetCoeffs(VP8BitReader* const br, const VP8BandProbas* const prob[],
int ctx, const quant_t dq, int n, int16_t* out) {
- // n is either 0 or 1 here. kBands[n] is not necessary for extracting '*p'.
- const uint8_t* p = prob[n][ctx];
- if (!VP8GetBit(br, p[0])) { // first EOB is more a 'CBP' bit.
- return 0;
- }
- while (1) {
- ++n;
- if (!VP8GetBit(br, p[1])) {
- p = prob[kBands[n]][0];
- } else { // non zero coeff
- int v, j;
+ const uint8_t* p = prob[n]->probas_[ctx];
+ for (; n < 16; ++n) {
+ if (!VP8GetBit(br, p[0])) {
+ return n; // previous coeff was last non-zero coeff
+ }
+ while (!VP8GetBit(br, p[1])) { // sequence of zero coeffs
+ p = prob[++n]->probas_[0];
+ if (n == 16) return 16;
+ }
+ { // non zero coeff
+ const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0];
+ int v;
if (!VP8GetBit(br, p[2])) {
- p = prob[kBands[n]][1];
v = 1;
+ p = p_ctx[1];
} else {
- if (!VP8GetBit(br, p[3])) {
- if (!VP8GetBit(br, p[4])) {
- v = 2;
- } else {
- v = 3 + VP8GetBit(br, p[5]);
- }
- } else {
- if (!VP8GetBit(br, p[6])) {
- if (!VP8GetBit(br, p[7])) {
- v = 5 + VP8GetBit(br, 159);
- } else {
- v = 7 + 2 * VP8GetBit(br, 165);
- v += VP8GetBit(br, 145);
- }
- } else {
- const uint8_t* tab;
- const int bit1 = VP8GetBit(br, p[8]);
- const int bit0 = VP8GetBit(br, p[9 + bit1]);
- const int cat = 2 * bit1 + bit0;
- v = 0;
- for (tab = kCat3456[cat]; *tab; ++tab) {
- v += v + VP8GetBit(br, *tab);
- }
- v += 3 + (8 << cat);
- }
- }
- p = prob[kBands[n]][2];
+ v = GetLargeValue(br, p);
+ p = p_ctx[2];
}
- j = kZigzag[n - 1];
- out[j] = VP8GetSigned(br, v) * dq[j > 0];
- if (n == 16 || !VP8GetBit(br, p[0])) { // EOB
- return n;
- }
- }
- if (n == 16) {
- return 16;
+ out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0];
}
}
+ return 16;
}
-// Alias-safe way of converting 4bytes to 32bits.
-typedef union {
- uint8_t i8[4];
- uint32_t i32;
-} PackedNz;
-
-// Table to unpack four bits into four bytes
-static const PackedNz kUnpackTab[16] = {
- {{0, 0, 0, 0}}, {{1, 0, 0, 0}}, {{0, 1, 0, 0}}, {{1, 1, 0, 0}},
- {{0, 0, 1, 0}}, {{1, 0, 1, 0}}, {{0, 1, 1, 0}}, {{1, 1, 1, 0}},
- {{0, 0, 0, 1}}, {{1, 0, 0, 1}}, {{0, 1, 0, 1}}, {{1, 1, 0, 1}},
- {{0, 0, 1, 1}}, {{1, 0, 1, 1}}, {{0, 1, 1, 1}}, {{1, 1, 1, 1}} };
-
-// Macro to pack four LSB of four bytes into four bits.
-#if defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || \
- defined(__BIG_ENDIAN__)
-#define PACK_CST 0x08040201U
-#else
-#define PACK_CST 0x01020408U
-#endif
-#define PACK(X, S) ((((X).i32 * PACK_CST) & 0xff000000) >> (S))
-
-static void ParseResiduals(VP8Decoder* const dec,
- VP8MB* const mb, VP8BitReader* const token_br) {
- int out_t_nz, out_l_nz, first;
- ProbaArray ac_prob;
- const VP8QuantMatrix* q = &dec->dqm_[dec->segment_];
- int16_t* dst = dec->coeffs_;
+static WEBP_INLINE uint32_t NzCodeBits(uint32_t nz_coeffs, int nz, int dc_nz) {
+ nz_coeffs <<= 2;
+ nz_coeffs |= (nz > 3) ? 3 : (nz > 1) ? 2 : dc_nz;
+ return nz_coeffs;
+}
+
+static int ParseResiduals(VP8Decoder* const dec,
+ VP8MB* const mb, VP8BitReader* const token_br) {
+ const VP8BandProbas* (* const bands)[16 + 1] = dec->proba_.bands_ptr_;
+ const VP8BandProbas* const * ac_proba;
+ VP8MBData* const block = dec->mb_data_ + dec->mb_x_;
+ const VP8QuantMatrix* const q = &dec->dqm_[block->segment_];
+ int16_t* dst = block->coeffs_;
VP8MB* const left_mb = dec->mb_info_ - 1;
- PackedNz nz_ac, nz_dc;
- PackedNz tnz, lnz;
- uint32_t non_zero_ac = 0;
- uint32_t non_zero_dc = 0;
+ uint8_t tnz, lnz;
+ uint32_t non_zero_y = 0;
+ uint32_t non_zero_uv = 0;
int x, y, ch;
+ uint32_t out_t_nz, out_l_nz;
+ int first;
- nz_dc.i32 = nz_ac.i32 = 0;
memset(dst, 0, 384 * sizeof(*dst));
- if (!dec->is_i4x4_) { // parse DC
+ if (!block->is_i4x4_) { // parse DC
int16_t dc[16] = { 0 };
- const int ctx = mb->dc_nz_ + left_mb->dc_nz_;
- mb->dc_nz_ = left_mb->dc_nz_ =
- (GetCoeffs(token_br, (ProbaArray)dec->proba_.coeffs_[1],
- ctx, q->y2_mat_, 0, dc) > 0);
+ const int ctx = mb->nz_dc_ + left_mb->nz_dc_;
+ const int nz = GetCoeffs(token_br, bands[1], ctx, q->y2_mat_, 0, dc);
+ mb->nz_dc_ = left_mb->nz_dc_ = (nz > 0);
+ if (nz > 1) { // more than just the DC -> perform the full transform
+ VP8TransformWHT(dc, dst);
+ } else { // only DC is non-zero -> inlined simplified transform
+ int i;
+ const int dc0 = (dc[0] + 3) >> 3;
+ for (i = 0; i < 16 * 16; i += 16) dst[i] = dc0;
+ }
first = 1;
- ac_prob = (ProbaArray)dec->proba_.coeffs_[0];
- VP8TransformWHT(dc, dst);
+ ac_proba = bands[0];
} else {
first = 0;
- ac_prob = (ProbaArray)dec->proba_.coeffs_[3];
+ ac_proba = bands[3];
}
- tnz = kUnpackTab[mb->nz_ & 0xf];
- lnz = kUnpackTab[left_mb->nz_ & 0xf];
+ tnz = mb->nz_ & 0x0f;
+ lnz = left_mb->nz_ & 0x0f;
for (y = 0; y < 4; ++y) {
- int l = lnz.i8[y];
+ int l = lnz & 1;
+ uint32_t nz_coeffs = 0;
for (x = 0; x < 4; ++x) {
- const int ctx = l + tnz.i8[x];
- const int nz = GetCoeffs(token_br, ac_prob, ctx,
- q->y1_mat_, first, dst);
- tnz.i8[x] = l = (nz > 0);
- nz_dc.i8[x] = (dst[0] != 0);
- nz_ac.i8[x] = (nz > 1);
+ const int ctx = l + (tnz & 1);
+ const int nz = GetCoeffs(token_br, ac_proba, ctx, q->y1_mat_, first, dst);
+ l = (nz > first);
+ tnz = (tnz >> 1) | (l << 7);
+ nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0);
dst += 16;
}
- lnz.i8[y] = l;
- non_zero_dc |= PACK(nz_dc, 24 - y * 4);
- non_zero_ac |= PACK(nz_ac, 24 - y * 4);
+ tnz >>= 4;
+ lnz = (lnz >> 1) | (l << 7);
+ non_zero_y = (non_zero_y << 8) | nz_coeffs;
}
- out_t_nz = PACK(tnz, 24);
- out_l_nz = PACK(lnz, 24);
+ out_t_nz = tnz;
+ out_l_nz = lnz >> 4;
- tnz = kUnpackTab[mb->nz_ >> 4];
- lnz = kUnpackTab[left_mb->nz_ >> 4];
for (ch = 0; ch < 4; ch += 2) {
+ uint32_t nz_coeffs = 0;
+ tnz = mb->nz_ >> (4 + ch);
+ lnz = left_mb->nz_ >> (4 + ch);
for (y = 0; y < 2; ++y) {
- int l = lnz.i8[ch + y];
+ int l = lnz & 1;
for (x = 0; x < 2; ++x) {
- const int ctx = l + tnz.i8[ch + x];
- const int nz =
- GetCoeffs(token_br, (ProbaArray)dec->proba_.coeffs_[2],
- ctx, q->uv_mat_, 0, dst);
- tnz.i8[ch + x] = l = (nz > 0);
- nz_dc.i8[y * 2 + x] = (dst[0] != 0);
- nz_ac.i8[y * 2 + x] = (nz > 1);
+ const int ctx = l + (tnz & 1);
+ const int nz = GetCoeffs(token_br, bands[2], ctx, q->uv_mat_, 0, dst);
+ l = (nz > 0);
+ tnz = (tnz >> 1) | (l << 3);
+ nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0);
dst += 16;
}
- lnz.i8[ch + y] = l;
+ tnz >>= 2;
+ lnz = (lnz >> 1) | (l << 5);
}
- non_zero_dc |= PACK(nz_dc, 8 - ch * 2);
- non_zero_ac |= PACK(nz_ac, 8 - ch * 2);
+ // Note: we don't really need the per-4x4 details for U/V blocks.
+ non_zero_uv |= nz_coeffs << (4 * ch);
+ out_t_nz |= (tnz << 4) << ch;
+ out_l_nz |= (lnz & 0xf0) << ch;
}
- out_t_nz |= PACK(tnz, 20);
- out_l_nz |= PACK(lnz, 20);
mb->nz_ = out_t_nz;
left_mb->nz_ = out_l_nz;
- dec->non_zero_ac_ = non_zero_ac;
- dec->non_zero_ = non_zero_ac | non_zero_dc;
- mb->skip_ = !dec->non_zero_;
+ block->non_zero_y_ = non_zero_y;
+ block->non_zero_uv_ = non_zero_uv;
+
+ // We look at the mode-code of each block and check if some blocks have less
+ // than three non-zero coeffs (code < 2). This is to avoid dithering flat and
+ // empty blocks.
+ block->dither_ = (non_zero_uv & 0xaaaa) ? 0 : q->dither_;
+
+ return !(non_zero_y | non_zero_uv); // will be used for further optimization
}
-#undef PACK
//------------------------------------------------------------------------------
// Main loop
int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) {
- VP8BitReader* const br = &dec->br_;
VP8MB* const left = dec->mb_info_ - 1;
- VP8MB* const info = dec->mb_info_ + dec->mb_x_;
-
- // Note: we don't save segment map (yet), as we don't expect
- // to decode more than 1 keyframe.
- if (dec->segment_hdr_.update_map_) {
- // Hardcoded tree parsing
- dec->segment_ = !VP8GetBit(br, dec->proba_.segments_[0]) ?
- VP8GetBit(br, dec->proba_.segments_[1]) :
- 2 + VP8GetBit(br, dec->proba_.segments_[2]);
- }
- info->skip_ = dec->use_skip_proba_ ? VP8GetBit(br, dec->skip_p_) : 0;
+ VP8MB* const mb = dec->mb_info_ + dec->mb_x_;
+ VP8MBData* const block = dec->mb_data_ + dec->mb_x_;
+ int skip = dec->use_skip_proba_ ? block->skip_ : 0;
- VP8ParseIntraMode(br, dec);
- if (br->eof_) {
- return 0;
- }
-
- if (!info->skip_) {
- ParseResiduals(dec, info, token_br);
+ if (!skip) {
+ skip = ParseResiduals(dec, mb, token_br);
} else {
- left->nz_ = info->nz_ = 0;
- if (!dec->is_i4x4_) {
- left->dc_nz_ = info->dc_nz_ = 0;
+ left->nz_ = mb->nz_ = 0;
+ if (!block->is_i4x4_) {
+ left->nz_dc_ = mb->nz_dc_ = 0;
}
- dec->non_zero_ = 0;
- dec->non_zero_ac_ = 0;
+ block->non_zero_y_ = 0;
+ block->non_zero_uv_ = 0;
+ block->dither_ = 0;
+ }
+
+ if (dec->filter_type_ > 0) { // store filter info
+ VP8FInfo* const finfo = dec->f_info_ + dec->mb_x_;
+ *finfo = dec->fstrengths_[block->segment_][block->is_i4x4_];
+ finfo->f_inner_ |= !skip;
}
- return (!token_br->eof_);
+ return !token_br->eof_;
}
void VP8InitScanline(VP8Decoder* const dec) {
VP8MB* const left = dec->mb_info_ - 1;
left->nz_ = 0;
- left->dc_nz_ = 0;
+ left->nz_dc_ = 0;
memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_));
- dec->filter_row_ =
- (dec->filter_type_ > 0) &&
- (dec->mb_y_ >= dec->tl_mb_y_) && (dec->mb_y_ <= dec->br_mb_y_);
+ dec->mb_x_ = 0;
}
static int ParseFrame(VP8Decoder* const dec, VP8Io* io) {
for (dec->mb_y_ = 0; dec->mb_y_ < dec->br_mb_y_; ++dec->mb_y_) {
+ // Parse bitstream for this row.
VP8BitReader* const token_br =
&dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)];
- VP8InitScanline(dec);
- for (dec->mb_x_ = 0; dec->mb_x_ < dec->mb_w_; dec->mb_x_++) {
+ if (!VP8ParseIntraModeRow(&dec->br_, dec)) {
+ return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
+ "Premature end-of-partition0 encountered.");
+ }
+ for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) {
if (!VP8DecodeMB(dec, token_br)) {
return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
"Premature end-of-file encountered.");
}
- VP8ReconstructBlock(dec);
-
- // Store data and save block's filtering params
- VP8StoreBlock(dec);
}
+ VP8InitScanline(dec); // Prepare for next scanline
+
+ // Reconstruct, filter and emit the row.
if (!VP8ProcessRow(dec, io)) {
return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted.");
}
}
- if (dec->use_threads_ && !WebPWorkerSync(&dec->worker_)) {
- return 0;
- }
-
- // Finish
-#ifndef ONLY_KEYFRAME_CODE
- if (!dec->update_proba_) {
- dec->proba_ = dec->proba_saved_;
+ if (dec->mt_method_ > 0) {
+ if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) return 0;
}
-#endif
-
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- if (dec->layer_data_size_ > 0) {
- if (!VP8DecodeLayer(dec)) {
- return 0;
- }
- }
-#endif
return 1;
}
@@ -768,12 +648,10 @@ void VP8Clear(VP8Decoder* const dec) {
if (dec == NULL) {
return;
}
- if (dec->use_threads_) {
- WebPWorkerEnd(&dec->worker_);
- }
- if (dec->mem_) {
- free(dec->mem_);
- }
+ WebPGetWorkerInterface()->End(&dec->worker_);
+ ALPHDelete(dec->alph_dec_);
+ dec->alph_dec_ = NULL;
+ WebPSafeFree(dec->mem_);
dec->mem_ = NULL;
dec->mem_size_ = 0;
memset(&dec->br_, 0, sizeof(dec->br_));
@@ -782,6 +660,3 @@ void VP8Clear(VP8Decoder* const dec) {
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/dec/vp8i.h b/drivers/webp/dec/vp8i.h
index 4382edfd8e..b5f2b23009 100644
--- a/drivers/webp/dec/vp8i.h
+++ b/drivers/webp/dec/vp8i.h
@@ -1,8 +1,10 @@
// Copyright 2010 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// VP8 decoder: internal header.
@@ -13,12 +15,14 @@
#define WEBP_DEC_VP8I_H_
#include <string.h> // for memcpy()
+#include "./common.h"
#include "./vp8li.h"
#include "../utils/bit_reader.h"
+#include "../utils/random.h"
#include "../utils/thread.h"
#include "../dsp/dsp.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
@@ -27,48 +31,10 @@ extern "C" {
// version numbers
#define DEC_MAJ_VERSION 0
-#define DEC_MIN_VERSION 2
-#define DEC_REV_VERSION 0
-
-#define ONLY_KEYFRAME_CODE // to remove any code related to P-Frames
-
-// intra prediction modes
-enum { B_DC_PRED = 0, // 4x4 modes
- B_TM_PRED,
- B_VE_PRED,
- B_HE_PRED,
- B_RD_PRED,
- B_VR_PRED,
- B_LD_PRED,
- B_VL_PRED,
- B_HD_PRED,
- B_HU_PRED,
- NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10
-
- // Luma16 or UV modes
- DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED,
- H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED,
- B_PRED = NUM_BMODES, // refined I4x4 mode
-
- // special modes
- B_DC_PRED_NOTOP = 4,
- B_DC_PRED_NOLEFT = 5,
- B_DC_PRED_NOTOPLEFT = 6,
- NUM_B_DC_MODES = 7 };
-
-enum { MB_FEATURE_TREE_PROBS = 3,
- NUM_MB_SEGMENTS = 4,
- NUM_REF_LF_DELTAS = 4,
- NUM_MODE_LF_DELTAS = 4, // I4x4, ZERO, *, SPLIT
- MAX_NUM_PARTITIONS = 8,
- // Probabilities
- NUM_TYPES = 4,
- NUM_BANDS = 8,
- NUM_CTX = 3,
- NUM_PROBAS = 11,
- NUM_MV_PROBAS = 19 };
-
-// YUV-cache parameters.
+#define DEC_MIN_VERSION 4
+#define DEC_REV_VERSION 4
+
+// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
// Constraints are: We need to store one 16x16 block of luma samples (y),
// and two 8x8 chroma blocks (u/v). These are better be 16-bytes aligned,
// in order to be SIMD-friendly. We also need to store the top, left and
@@ -90,14 +56,15 @@ enum { MB_FEATURE_TREE_PROBS = 3,
// 'y' = y-samples 'u' = u-samples 'v' = u-samples
// '|' = left sample, '-' = top sample, '+' = top-left sample
// 't' = extra top-right sample for 4x4 modes
-// With this layout, BPS (=Bytes Per Scan-line) is one cacheline size.
-#define BPS 32 // this is the common stride used by yuv[]
#define YUV_SIZE (BPS * 17 + BPS * 9)
#define Y_SIZE (BPS * 17)
#define Y_OFF (BPS * 1 + 8)
#define U_OFF (Y_OFF + BPS * 16 + BPS)
#define V_OFF (U_OFF + 16)
+// minimal width under which lossy multi-threading is always disabled
+#define MIN_WIDTH_FOR_THREADS 512
+
//------------------------------------------------------------------------------
// Headers
@@ -126,15 +93,19 @@ typedef struct {
int8_t filter_strength_[NUM_MB_SEGMENTS]; // filter strength for segments
} VP8SegmentHeader;
+// probas associated to one of the contexts
+typedef uint8_t VP8ProbaArray[NUM_PROBAS];
+
+typedef struct { // all the probas associated to one band
+ VP8ProbaArray probas_[NUM_CTX];
+} VP8BandProbas;
+
// Struct collecting all frame-persistent probabilities.
typedef struct {
uint8_t segments_[MB_FEATURE_TREE_PROBS];
// Type: 0:Intra16-AC 1:Intra16-DC 2:Chroma 3:Intra4
- uint8_t coeffs_[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS];
-#ifndef ONLY_KEYFRAME_CODE
- uint8_t ymode_[4], uvmode_[3];
- uint8_t mv_[2][NUM_MV_PROBAS];
-#endif
+ VP8BandProbas bands_[NUM_TYPES][NUM_BANDS];
+ const VP8BandProbas* bands_ptr_[NUM_TYPES][16 + 1];
} VP8Proba;
// Filter parameters
@@ -151,32 +122,61 @@ typedef struct {
// Informations about the macroblocks.
typedef struct { // filter specs
- unsigned int f_level_:6; // filter strength: 0..63
- unsigned int f_ilevel_:6; // inner limit: 1..63
- unsigned int f_inner_:1; // do inner filtering?
+ uint8_t f_limit_; // filter limit in [3..189], or 0 if no filtering
+ uint8_t f_ilevel_; // inner limit in [1..63]
+ uint8_t f_inner_; // do inner filtering?
+ uint8_t hev_thresh_; // high edge variance threshold in [0..2]
} VP8FInfo;
-typedef struct { // used for syntax-parsing
- unsigned int nz_; // non-zero AC/DC coeffs
- unsigned int dc_nz_:1; // non-zero DC coeffs
- unsigned int skip_:1; // block type
+typedef struct { // Top/Left Contexts used for syntax-parsing
+ uint8_t nz_; // non-zero AC/DC coeffs (4bit for luma + 4bit for chroma)
+ uint8_t nz_dc_; // non-zero DC coeff (1bit)
} VP8MB;
// Dequantization matrices
typedef int quant_t[2]; // [DC / AC]. Can be 'uint16_t[2]' too (~slower).
typedef struct {
quant_t y1_mat_, y2_mat_, uv_mat_;
+
+ int uv_quant_; // U/V quantizer value
+ int dither_; // dithering amplitude (0 = off, max=255)
} VP8QuantMatrix;
+// Data needed to reconstruct a macroblock
+typedef struct {
+ int16_t coeffs_[384]; // 384 coeffs = (16+4+4) * 4*4
+ uint8_t is_i4x4_; // true if intra4x4
+ uint8_t imodes_[16]; // one 16x16 mode (#0) or sixteen 4x4 modes
+ uint8_t uvmode_; // chroma prediction mode
+ // bit-wise info about the content of each sub-4x4 blocks (in decoding order).
+ // Each of the 4x4 blocks for y/u/v is associated with a 2b code according to:
+ // code=0 -> no coefficient
+ // code=1 -> only DC
+ // code=2 -> first three coefficients are non-zero
+ // code=3 -> more than three coefficients are non-zero
+ // This allows to call specialized transform functions.
+ uint32_t non_zero_y_;
+ uint32_t non_zero_uv_;
+ uint8_t dither_; // local dithering strength (deduced from non_zero_*)
+ uint8_t skip_;
+ uint8_t segment_;
+} VP8MBData;
+
// Persistent information needed by the parallel processing
typedef struct {
- int id_; // cache row to process (in [0..2])
- int mb_y_; // macroblock position of the row
- int filter_row_; // true if row-filtering is needed
- VP8FInfo* f_info_; // filter strengths
- VP8Io io_; // copy of the VP8Io to pass to put()
+ int id_; // cache row to process (in [0..2])
+ int mb_y_; // macroblock position of the row
+ int filter_row_; // true if row-filtering is needed
+ VP8FInfo* f_info_; // filter strengths (swapped with dec->f_info_)
+ VP8MBData* mb_data_; // reconstruction data (swapped with dec->mb_data_)
+ VP8Io io_; // copy of the VP8Io to pass to put()
} VP8ThreadContext;
+// Saved top samples, per macroblock. Fits into a cache-line.
+typedef struct {
+ uint8_t y[16], u[8], v[8];
+} VP8TopSamples;
+
//------------------------------------------------------------------------------
// VP8Decoder: the main opaque structure handed over to user
@@ -196,7 +196,8 @@ struct VP8Decoder {
// Worker
WebPWorker worker_;
- int use_threads_; // use multi-thread
+ int mt_method_; // multi-thread method: 0=off, 1=[parse+recon][filter]
+ // 2=[parse][recon+filter]
int cache_id_; // current cache row
int num_caches_; // number of cached rows of 16 pixels (1, 2 or 3)
VP8ThreadContext thread_ctx_; // Thread context
@@ -213,12 +214,9 @@ struct VP8Decoder {
// per-partition boolean decoders.
VP8BitReader parts_[MAX_NUM_PARTITIONS];
- // buffer refresh flags
- // bit 0: refresh Gold, bit 1: refresh Alt
- // bit 2-3: copy to Gold, bit 4-5: copy to Alt
- // bit 6: Gold sign bias, bit 7: Alt sign bias
- // bit 8: refresh last frame
- uint32_t buffer_flags_;
+ // Dithering strength, deduced from decoding options
+ int dither_; // whether to use dithering or not
+ VP8Random dithering_rg_; // random generator for dithering
// dequantization (one set of DC/AC dequant factor per segment)
VP8QuantMatrix dqm_[NUM_MB_SEGMENTS];
@@ -227,24 +225,18 @@ struct VP8Decoder {
VP8Proba proba_;
int use_skip_proba_;
uint8_t skip_p_;
-#ifndef ONLY_KEYFRAME_CODE
- uint8_t intra_p_, last_p_, golden_p_;
- VP8Proba proba_saved_;
- int update_proba_;
-#endif
// Boundary data cache and persistent buffers.
- uint8_t* intra_t_; // top intra modes values: 4 * mb_w_
- uint8_t intra_l_[4]; // left intra modes values
- uint8_t* y_t_; // top luma samples: 16 * mb_w_
- uint8_t* u_t_, *v_t_; // top u/v samples: 8 * mb_w_ each
+ uint8_t* intra_t_; // top intra modes values: 4 * mb_w_
+ uint8_t intra_l_[4]; // left intra modes values
- VP8MB* mb_info_; // contextual macroblock info (mb_w_ + 1)
- VP8FInfo* f_info_; // filter strength info
- uint8_t* yuv_b_; // main block for Y/U/V (size = YUV_SIZE)
- int16_t* coeffs_; // 384 coeffs = (16+8+8) * 4*4
+ VP8TopSamples* yuv_t_; // top y/u/v samples
- uint8_t* cache_y_; // macroblock row for storing unfiltered samples
+ VP8MB* mb_info_; // contextual macroblock info (mb_w_ + 1)
+ VP8FInfo* f_info_; // filter strength info
+ uint8_t* yuv_b_; // main block for Y/U/V (size = YUV_SIZE)
+
+ uint8_t* cache_y_; // macroblock row for storing unfiltered samples
uint8_t* cache_u_;
uint8_t* cache_v_;
int cache_y_stride_;
@@ -256,31 +248,19 @@ struct VP8Decoder {
// Per macroblock non-persistent infos.
int mb_x_, mb_y_; // current position, in macroblock units
- uint8_t is_i4x4_; // true if intra4x4
- uint8_t imodes_[16]; // one 16x16 mode (#0) or sixteen 4x4 modes
- uint8_t uvmode_; // chroma prediction mode
- uint8_t segment_; // block's segment
-
- // bit-wise info about the content of each sub-4x4 blocks: there are 16 bits
- // for luma (bits #0->#15), then 4 bits for chroma-u (#16->#19) and 4 bits for
- // chroma-v (#20->#23), each corresponding to one 4x4 block in decoding order.
- // If the bit is set, the 4x4 block contains some non-zero coefficients.
- uint32_t non_zero_;
- uint32_t non_zero_ac_;
+ VP8MBData* mb_data_; // parsed reconstruction data
// Filtering side-info
- int filter_type_; // 0=off, 1=simple, 2=complex
- int filter_row_; // per-row flag
- uint8_t filter_levels_[NUM_MB_SEGMENTS]; // precalculated per-segment
+ int filter_type_; // 0=off, 1=simple, 2=complex
+ VP8FInfo fstrengths_[NUM_MB_SEGMENTS][2]; // precalculated per-segment/type
- // extensions
- const uint8_t* alpha_data_; // compressed alpha data (if present)
+ // Alpha
+ struct ALPHDecoder* alph_dec_; // alpha-plane decoder object
+ const uint8_t* alpha_data_; // compressed alpha data (if present)
size_t alpha_data_size_;
- uint8_t* alpha_plane_; // output. Persistent, contains the whole data.
-
- int layer_colorspace_;
- const uint8_t* layer_data_; // compressed layer data (if present)
- size_t layer_data_size_;
+ int is_alpha_decoded_; // true if alpha_data_ is decoded in alpha_plane_
+ uint8_t* alpha_plane_; // output. Persistent, contains the whole data.
+ int alpha_dithering_; // derived from decoding options (0=off, 100=full).
};
//------------------------------------------------------------------------------
@@ -293,15 +273,14 @@ int VP8SetError(VP8Decoder* const dec,
// in tree.c
void VP8ResetProba(VP8Proba* const proba);
void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec);
-void VP8ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec);
+// parses one row of intra mode data in partition 0, returns !eof
+int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec);
// in quant.c
void VP8ParseQuant(VP8Decoder* const dec);
// in frame.c
-int VP8InitFrame(VP8Decoder* const dec, VP8Io* io);
-// Predict a block and add residual
-void VP8ReconstructBlock(VP8Decoder* const dec);
+int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io);
// Call io->setup() and finish setting up scan parameters.
// After this call returns, one must always call VP8ExitCritical() with the
// same parameters. Both functions should be used in pair. Returns VP8_STATUS_OK
@@ -310,10 +289,16 @@ VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io);
// Must always be called in pair with VP8EnterCritical().
// Returns false in case of error.
int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io);
-// Process the last decoded row (filtering + output)
+// Return the multi-threading method to use (0=off), depending
+// on options and bitstream size. Only for lossy decoding.
+int VP8GetThreadMethod(const WebPDecoderOptions* const options,
+ const WebPHeaderStructure* const headers,
+ int width, int height);
+// Initialize dithering post-process if needed.
+void VP8InitDithering(const WebPDecoderOptions* const options,
+ VP8Decoder* const dec);
+// Process the last decoded row (filtering + output).
int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io);
-// Store a block, along with filtering params
-void VP8StoreBlock(VP8Decoder* const dec);
// To be called at the start of a new scanline, to initialize predictors.
void VP8InitScanline(VP8Decoder* const dec);
// Decode one macroblock. Returns false if there is not enough data.
@@ -323,12 +308,9 @@ int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br);
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
int row, int num_rows);
-// in layer.c
-int VP8DecodeLayer(VP8Decoder* const dec);
-
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/dec/vp8l.c b/drivers/webp/dec/vp8l.c
index 897e4395c7..19665a007d 100644
--- a/drivers/webp/dec/vp8l.c
+++ b/drivers/webp/dec/vp8l.c
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// main entry for the decoder
@@ -10,18 +12,17 @@
// Authors: Vikas Arora (vikaas.arora@gmail.com)
// Jyrki Alakuijala (jyrki@google.com)
-#include <stdio.h>
#include <stdlib.h>
+
+#include "./alphai.h"
#include "./vp8li.h"
+#include "../dsp/dsp.h"
#include "../dsp/lossless.h"
#include "../dsp/yuv.h"
+#include "../utils/endian_inl.h"
#include "../utils/huffman.h"
#include "../utils/utils.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
#define NUM_ARGB_CACHE_ROWS 16
static const int kCodeLengthLiterals = 16;
@@ -50,6 +51,9 @@ static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = {
NUM_DISTANCE_CODES
};
+static const uint8_t kLiteralMap[HUFFMAN_CODES_PER_META_CODE] = {
+ 0, 1, 1, 1, 0
+};
#define NUM_CODE_LENGTH_CODES 19
static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = {
@@ -57,19 +61,43 @@ static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = {
};
#define CODE_TO_PLANE_CODES 120
-static const uint8_t code_to_plane_lut[CODE_TO_PLANE_CODES] = {
- 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
- 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
- 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
- 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
- 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
- 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
- 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
- 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
- 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
- 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
- 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
- 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70
+static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {
+ 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
+ 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
+ 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
+ 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
+ 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
+ 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
+ 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
+ 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
+ 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
+ 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
+ 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
+ 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70
+};
+
+// Memory needed for lookup tables of one Huffman tree group. Red, blue, alpha
+// and distance alphabets are constant (256 for red, blue and alpha, 40 for
+// distance) and lookup table sizes for them in worst case are 630 and 410
+// respectively. Size of green alphabet depends on color cache size and is equal
+// to 256 (green component values) + 24 (length prefix values)
+// + color_cache_size (between 0 and 2048).
+// All values computed for 8-bit first level lookup with Mark Adler's tool:
+// http://www.hdfgroup.org/ftp/lib-external/zlib/zlib-1.2.5/examples/enough.c
+#define FIXED_TABLE_SIZE (630 * 3 + 410)
+static const int kTableSize[12] = {
+ FIXED_TABLE_SIZE + 654,
+ FIXED_TABLE_SIZE + 656,
+ FIXED_TABLE_SIZE + 658,
+ FIXED_TABLE_SIZE + 662,
+ FIXED_TABLE_SIZE + 670,
+ FIXED_TABLE_SIZE + 686,
+ FIXED_TABLE_SIZE + 718,
+ FIXED_TABLE_SIZE + 782,
+ FIXED_TABLE_SIZE + 912,
+ FIXED_TABLE_SIZE + 1168,
+ FIXED_TABLE_SIZE + 1680,
+ FIXED_TABLE_SIZE + 2704
};
static int DecodeImageStream(int xsize, int ysize,
@@ -80,27 +108,28 @@ static int DecodeImageStream(int xsize, int ysize,
//------------------------------------------------------------------------------
int VP8LCheckSignature(const uint8_t* const data, size_t size) {
- return (size >= 1) && (data[0] == VP8L_MAGIC_BYTE);
+ return (size >= VP8L_FRAME_HEADER_SIZE &&
+ data[0] == VP8L_MAGIC_BYTE &&
+ (data[4] >> 5) == 0); // version
}
static int ReadImageInfo(VP8LBitReader* const br,
int* const width, int* const height,
int* const has_alpha) {
- const uint8_t signature = VP8LReadBits(br, 8);
- if (!VP8LCheckSignature(&signature, 1)) {
- return 0;
- }
+ if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0;
*width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
*height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
*has_alpha = VP8LReadBits(br, 1);
- VP8LReadBits(br, VP8L_VERSION_BITS); // Read/ignore the version number.
- return 1;
+ if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0;
+ return !br->eos_;
}
int VP8LGetInfo(const uint8_t* data, size_t data_size,
int* const width, int* const height, int* const has_alpha) {
if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) {
return 0; // not enough data
+ } else if (!VP8LCheckSignature(data, data_size)) {
+ return 0; // bad signature
} else {
int w, h, a;
VP8LBitReader br;
@@ -138,39 +167,80 @@ static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {
if (plane_code > CODE_TO_PLANE_CODES) {
return plane_code - CODE_TO_PLANE_CODES;
} else {
- const int dist_code = code_to_plane_lut[plane_code - 1];
+ const int dist_code = kCodeToPlane[plane_code - 1];
const int yoffset = dist_code >> 4;
const int xoffset = 8 - (dist_code & 0xf);
const int dist = yoffset * xsize + xoffset;
- return (dist >= 1) ? dist : 1;
+ return (dist >= 1) ? dist : 1; // dist<1 can happen if xsize is very small
}
}
//------------------------------------------------------------------------------
// Decodes the next Huffman code from bit-stream.
// FillBitWindow(br) needs to be called at minimum every second call
-// to ReadSymbolUnsafe.
-static int ReadSymbolUnsafe(const HuffmanTree* tree, VP8LBitReader* const br) {
- const HuffmanTreeNode* node = tree->root_;
- assert(node != NULL);
- while (!HuffmanTreeNodeIsLeaf(node)) {
- node = HuffmanTreeNextNode(node, VP8LReadOneBitUnsafe(br));
- }
- return node->symbol_;
+// to ReadSymbol, in order to pre-fetch enough bits.
+static WEBP_INLINE int ReadSymbol(const HuffmanCode* table,
+ VP8LBitReader* const br) {
+ int nbits;
+ uint32_t val = VP8LPrefetchBits(br);
+ table += val & HUFFMAN_TABLE_MASK;
+ nbits = table->bits - HUFFMAN_TABLE_BITS;
+ if (nbits > 0) {
+ VP8LSetBitPos(br, br->bit_pos_ + HUFFMAN_TABLE_BITS);
+ val = VP8LPrefetchBits(br);
+ table += table->value;
+ table += val & ((1 << nbits) - 1);
+ }
+ VP8LSetBitPos(br, br->bit_pos_ + table->bits);
+ return table->value;
}
-static WEBP_INLINE int ReadSymbol(const HuffmanTree* tree,
- VP8LBitReader* const br) {
- const int read_safe = (br->pos_ + 8 > br->len_);
- if (!read_safe) {
- return ReadSymbolUnsafe(tree, br);
+// Reads packed symbol depending on GREEN channel
+#define BITS_SPECIAL_MARKER 0x100 // something large enough (and a bit-mask)
+#define PACKED_NON_LITERAL_CODE 0 // must be < NUM_LITERAL_CODES
+static WEBP_INLINE int ReadPackedSymbols(const HTreeGroup* group,
+ VP8LBitReader* const br,
+ uint32_t* const dst) {
+ const uint32_t val = VP8LPrefetchBits(br) & (HUFFMAN_PACKED_TABLE_SIZE - 1);
+ const HuffmanCode32 code = group->packed_table[val];
+ assert(group->use_packed_table);
+ if (code.bits < BITS_SPECIAL_MARKER) {
+ VP8LSetBitPos(br, br->bit_pos_ + code.bits);
+ *dst = code.value;
+ return PACKED_NON_LITERAL_CODE;
} else {
- const HuffmanTreeNode* node = tree->root_;
- assert(node != NULL);
- while (!HuffmanTreeNodeIsLeaf(node)) {
- node = HuffmanTreeNextNode(node, VP8LReadOneBit(br));
+ VP8LSetBitPos(br, br->bit_pos_ + code.bits - BITS_SPECIAL_MARKER);
+ assert(code.value >= NUM_LITERAL_CODES);
+ return code.value;
+ }
+}
+
+static int AccumulateHCode(HuffmanCode hcode, int shift,
+ HuffmanCode32* const huff) {
+ huff->bits += hcode.bits;
+ huff->value |= (uint32_t)hcode.value << shift;
+ assert(huff->bits <= HUFFMAN_TABLE_BITS);
+ return hcode.bits;
+}
+
+static void BuildPackedTable(HTreeGroup* const htree_group) {
+ uint32_t code;
+ for (code = 0; code < HUFFMAN_PACKED_TABLE_SIZE; ++code) {
+ uint32_t bits = code;
+ HuffmanCode32* const huff = &htree_group->packed_table[bits];
+ HuffmanCode hcode = htree_group->htrees[GREEN][bits];
+ if (hcode.value >= NUM_LITERAL_CODES) {
+ huff->bits = hcode.bits + BITS_SPECIAL_MARKER;
+ huff->value = hcode.value;
+ } else {
+ huff->bits = 0;
+ huff->value = 0;
+ bits >>= AccumulateHCode(hcode, 8, huff);
+ bits >>= AccumulateHCode(htree_group->htrees[RED][bits], 16, huff);
+ bits >>= AccumulateHCode(htree_group->htrees[BLUE][bits], 0, huff);
+ bits >>= AccumulateHCode(htree_group->htrees[ALPHA][bits], 24, huff);
+ (void)bits;
}
- return node->symbol_;
}
}
@@ -182,19 +252,18 @@ static int ReadHuffmanCodeLengths(
int symbol;
int max_symbol;
int prev_code_len = DEFAULT_CODE_LENGTH;
- HuffmanTree tree;
+ HuffmanCode table[1 << LENGTHS_TABLE_BITS];
- if (!HuffmanTreeBuildImplicit(&tree, code_length_code_lengths,
- NUM_CODE_LENGTH_CODES)) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- return 0;
+ if (!VP8LBuildHuffmanTable(table, LENGTHS_TABLE_BITS,
+ code_length_code_lengths,
+ NUM_CODE_LENGTH_CODES)) {
+ goto End;
}
if (VP8LReadBits(br, 1)) { // use length
const int length_nbits = 2 + 2 * VP8LReadBits(br, 3);
max_symbol = 2 + VP8LReadBits(br, length_nbits);
if (max_symbol > num_symbols) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
goto End;
}
} else {
@@ -203,10 +272,13 @@ static int ReadHuffmanCodeLengths(
symbol = 0;
while (symbol < num_symbols) {
+ const HuffmanCode* p;
int code_len;
if (max_symbol-- == 0) break;
VP8LFillBitWindow(br);
- code_len = ReadSymbol(&tree, br);
+ p = &table[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
+ VP8LSetBitPos(br, br->bit_pos_ + p->bits);
+ code_len = p->value;
if (code_len < kCodeLengthLiterals) {
code_lengths[symbol++] = code_len;
if (code_len != 0) prev_code_len = code_len;
@@ -217,7 +289,6 @@ static int ReadHuffmanCodeLengths(
const int repeat_offset = kCodeLengthRepeatOffsets[slot];
int repeat = VP8LReadBits(br, extra_bits) + repeat_offset;
if (symbol + repeat > num_symbols) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
goto End;
} else {
const int length = use_prev ? prev_code_len : 0;
@@ -228,36 +299,34 @@ static int ReadHuffmanCodeLengths(
ok = 1;
End:
- HuffmanTreeRelease(&tree);
+ if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
return ok;
}
+// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
+// tree.
static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
- HuffmanTree* const tree) {
+ int* const code_lengths, HuffmanCode* const table) {
int ok = 0;
+ int size = 0;
VP8LBitReader* const br = &dec->br_;
const int simple_code = VP8LReadBits(br, 1);
+ memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths));
+
if (simple_code) { // Read symbols, codes & code lengths directly.
- int symbols[2];
- int codes[2];
- int code_lengths[2];
const int num_symbols = VP8LReadBits(br, 1) + 1;
const int first_symbol_len_code = VP8LReadBits(br, 1);
// The first code is either 1 bit or 8 bit code.
- symbols[0] = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);
- codes[0] = 0;
- code_lengths[0] = num_symbols - 1;
+ int symbol = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);
+ code_lengths[symbol] = 1;
// The second code (if present), is always 8 bit long.
if (num_symbols == 2) {
- symbols[1] = VP8LReadBits(br, 8);
- codes[1] = 1;
- code_lengths[1] = num_symbols - 1;
+ symbol = VP8LReadBits(br, 8);
+ code_lengths[symbol] = 1;
}
- ok = HuffmanTreeBuildExplicit(tree, code_lengths, codes, symbols,
- alphabet_size, num_symbols);
+ ok = 1;
} else { // Decode Huffman-coded code lengths.
- int* code_lengths = NULL;
int i;
int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
const int num_codes = VP8LReadBits(br, 4) + 4;
@@ -266,42 +335,23 @@ static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
return 0;
}
- code_lengths =
- (int*)WebPSafeCalloc((uint64_t)alphabet_size, sizeof(*code_lengths));
- if (code_lengths == NULL) {
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- return 0;
- }
-
for (i = 0; i < num_codes; ++i) {
code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3);
}
ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size,
code_lengths);
- if (ok) {
- ok = HuffmanTreeBuildImplicit(tree, code_lengths, alphabet_size);
- }
- free(code_lengths);
}
- ok = ok && !br->error_;
- if (!ok) {
+
+ ok = ok && !br->eos_;
+ if (ok) {
+ size = VP8LBuildHuffmanTable(table, HUFFMAN_TABLE_BITS,
+ code_lengths, alphabet_size);
+ }
+ if (!ok || size == 0) {
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
return 0;
}
- return 1;
-}
-
-static void DeleteHtreeGroups(HTreeGroup* htree_groups, int num_htree_groups) {
- if (htree_groups != NULL) {
- int i, j;
- for (i = 0; i < num_htree_groups; ++i) {
- HuffmanTree* const htrees = htree_groups[i].htrees_;
- for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
- HuffmanTreeRelease(&htrees[j]);
- }
- }
- free(htree_groups);
- }
+ return size;
}
static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
@@ -311,7 +361,12 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
VP8LMetadata* const hdr = &dec->hdr_;
uint32_t* huffman_image = NULL;
HTreeGroup* htree_groups = NULL;
+ HuffmanCode* huffman_tables = NULL;
+ HuffmanCode* next = NULL;
int num_htree_groups = 1;
+ int max_alphabet_size = 0;
+ int* code_lengths = NULL;
+ const int table_size = kTableSize[color_cache_bits];
if (allow_recursion && VP8LReadBits(br, 1)) {
// use meta Huffman codes.
@@ -321,51 +376,108 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
const int huffman_pixs = huffman_xsize * huffman_ysize;
if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,
&huffman_image)) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
goto Error;
}
hdr->huffman_subsample_bits_ = huffman_precision;
for (i = 0; i < huffman_pixs; ++i) {
// The huffman data is stored in red and green bytes.
- const int index = (huffman_image[i] >> 8) & 0xffff;
- huffman_image[i] = index;
- if (index >= num_htree_groups) {
- num_htree_groups = index + 1;
+ const int group = (huffman_image[i] >> 8) & 0xffff;
+ huffman_image[i] = group;
+ if (group >= num_htree_groups) {
+ num_htree_groups = group + 1;
}
}
}
- if (br->error_) goto Error;
+ if (br->eos_) goto Error;
+
+ // Find maximum alphabet size for the htree group.
+ for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
+ int alphabet_size = kAlphabetSize[j];
+ if (j == 0 && color_cache_bits > 0) {
+ alphabet_size += 1 << color_cache_bits;
+ }
+ if (max_alphabet_size < alphabet_size) {
+ max_alphabet_size = alphabet_size;
+ }
+ }
+
+ huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size,
+ sizeof(*huffman_tables));
+ htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
+ code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
+ sizeof(*code_lengths));
- assert(num_htree_groups <= 0x10000);
- htree_groups =
- (HTreeGroup*)WebPSafeCalloc((uint64_t)num_htree_groups,
- sizeof(*htree_groups));
- if (htree_groups == NULL) {
+ if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
goto Error;
}
+ next = huffman_tables;
for (i = 0; i < num_htree_groups; ++i) {
- HuffmanTree* const htrees = htree_groups[i].htrees_;
+ HTreeGroup* const htree_group = &htree_groups[i];
+ HuffmanCode** const htrees = htree_group->htrees;
+ int size;
+ int total_size = 0;
+ int is_trivial_literal = 1;
+ int max_bits = 0;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
+ htrees[j] = next;
if (j == 0 && color_cache_bits > 0) {
alphabet_size += 1 << color_cache_bits;
}
- if (!ReadHuffmanCode(alphabet_size, dec, htrees + j)) goto Error;
+ size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next);
+ if (is_trivial_literal && kLiteralMap[j] == 1) {
+ is_trivial_literal = (next->bits == 0);
+ }
+ total_size += next->bits;
+ next += size;
+ if (size == 0) {
+ goto Error;
+ }
+ if (j <= ALPHA) {
+ int local_max_bits = code_lengths[0];
+ int k;
+ for (k = 1; k < alphabet_size; ++k) {
+ if (code_lengths[k] > local_max_bits) {
+ local_max_bits = code_lengths[k];
+ }
+ }
+ max_bits += local_max_bits;
+ }
}
+ htree_group->is_trivial_literal = is_trivial_literal;
+ htree_group->is_trivial_code = 0;
+ if (is_trivial_literal) {
+ const int red = htrees[RED][0].value;
+ const int blue = htrees[BLUE][0].value;
+ const int alpha = htrees[ALPHA][0].value;
+ htree_group->literal_arb =
+ ((uint32_t)alpha << 24) | (red << 16) | blue;
+ if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
+ htree_group->is_trivial_code = 1;
+ htree_group->literal_arb |= htrees[GREEN][0].value << 8;
+ }
+ }
+ htree_group->use_packed_table = !htree_group->is_trivial_code &&
+ (max_bits < HUFFMAN_PACKED_BITS);
+ if (htree_group->use_packed_table) BuildPackedTable(htree_group);
}
+ WebPSafeFree(code_lengths);
// All OK. Finalize pointers and return.
hdr->huffman_image_ = huffman_image;
hdr->num_htree_groups_ = num_htree_groups;
hdr->htree_groups_ = htree_groups;
+ hdr->huffman_tables_ = huffman_tables;
return 1;
Error:
- free(huffman_image);
- DeleteHtreeGroups(htree_groups, num_htree_groups);
+ WebPSafeFree(code_lengths);
+ WebPSafeFree(huffman_image);
+ WebPSafeFree(huffman_tables);
+ VP8LHtreeGroupsFree(htree_groups);
return 0;
}
@@ -379,13 +491,13 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
const int in_height = io->mb_h;
const int out_height = io->scaled_height;
const uint64_t work_size = 2 * num_channels * (uint64_t)out_width;
- int32_t* work; // Rescaler work area.
- const uint64_t scaled_data_size = num_channels * (uint64_t)out_width;
+ rescaler_t* work; // Rescaler work area.
+ const uint64_t scaled_data_size = (uint64_t)out_width;
uint32_t* scaled_data; // Temporary storage for scaled BGRA data.
const uint64_t memory_size = sizeof(*dec->rescaler) +
work_size * sizeof(*work) +
scaled_data_size * sizeof(*scaled_data);
- uint8_t* memory = (uint8_t*)WebPSafeCalloc(memory_size, sizeof(*memory));
+ uint8_t* memory = (uint8_t*)WebPSafeMalloc(memory_size, sizeof(*memory));
if (memory == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
return 0;
@@ -395,13 +507,12 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
dec->rescaler = (WebPRescaler*)memory;
memory += sizeof(*dec->rescaler);
- work = (int32_t*)memory;
+ work = (rescaler_t*)memory;
memory += work_size * sizeof(*work);
scaled_data = (uint32_t*)memory;
WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data,
- out_width, out_height, 0, num_channels,
- in_width, out_width, in_height, out_height, work);
+ out_width, out_height, 0, num_channels, work);
return 1;
}
@@ -411,12 +522,13 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
// We have special "export" function since we need to convert from BGRA
static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,
int rgba_stride, uint8_t* const rgba) {
- const uint32_t* const src = (const uint32_t*)rescaler->dst;
+ uint32_t* const src = (uint32_t*)rescaler->dst;
const int dst_width = rescaler->dst_width;
int num_lines_out = 0;
while (WebPRescalerHasPendingOutput(rescaler)) {
uint8_t* const dst = rgba + num_lines_out * rgba_stride;
WebPRescalerExportRow(rescaler);
+ WebPMultARGBRow(src, dst_width, 1);
VP8LConvertFromBGRA(src, dst_width, colorspace, dst);
++num_lines_out;
}
@@ -424,18 +536,22 @@ static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,
}
// Emit scaled rows.
-static int EmitRescaledRows(const VP8LDecoder* const dec,
- const uint32_t* const data, int in_stride, int mb_h,
- uint8_t* const out, int out_stride) {
+static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,
+ uint8_t* in, int in_stride, int mb_h,
+ uint8_t* const out, int out_stride) {
const WEBP_CSP_MODE colorspace = dec->output_->colorspace;
- const uint8_t* const in = (const uint8_t*)data;
int num_lines_in = 0;
int num_lines_out = 0;
while (num_lines_in < mb_h) {
- const uint8_t* const row_in = in + num_lines_in * in_stride;
+ uint8_t* const row_in = in + num_lines_in * in_stride;
uint8_t* const row_out = out + num_lines_out * out_stride;
- num_lines_in += WebPRescalerImport(dec->rescaler, mb_h - num_lines_in,
- row_in, in_stride);
+ const int lines_left = mb_h - num_lines_in;
+ const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
+ assert(needed_lines > 0 && needed_lines <= lines_left);
+ WebPMultARGBRows(row_in, in_stride,
+ dec->rescaler->src_width, needed_lines, 0);
+ WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride);
+ num_lines_in += needed_lines;
num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out);
}
return num_lines_out;
@@ -443,11 +559,10 @@ static int EmitRescaledRows(const VP8LDecoder* const dec,
// Emit rows without any scaling.
static int EmitRows(WEBP_CSP_MODE colorspace,
- const uint32_t* const data, int in_stride,
+ const uint8_t* row_in, int in_stride,
int mb_w, int mb_h,
uint8_t* const out, int out_stride) {
int lines = mb_h;
- const uint8_t* row_in = (const uint8_t*)data;
uint8_t* row_out = out;
while (lines-- > 0) {
VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out);
@@ -463,72 +578,37 @@ static int EmitRows(WEBP_CSP_MODE colorspace,
static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,
const WebPDecBuffer* const output) {
const WebPYUVABuffer* const buf = &output->u.YUVA;
+
// first, the luma plane
- {
- int i;
- uint8_t* const y = buf->y + y_pos * buf->y_stride;
- for (i = 0; i < width; ++i) {
- const uint32_t p = src[i];
- y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff);
- }
- }
+ WebPConvertARGBToY(src, buf->y + y_pos * buf->y_stride, width);
// then U/V planes
{
uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride;
uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride;
- const int uv_width = width >> 1;
- int i;
- for (i = 0; i < uv_width; ++i) {
- const uint32_t v0 = src[2 * i + 0];
- const uint32_t v1 = src[2 * i + 1];
- // VP8RGBToU/V expects four accumulated pixels. Hence we need to
- // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less.
- const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe);
- const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe);
- const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe);
- if (!(y_pos & 1)) { // even lines: store values
- u[i] = VP8RGBToU(r, g, b);
- v[i] = VP8RGBToV(r, g, b);
- } else { // odd lines: average with previous values
- const int tmp_u = VP8RGBToU(r, g, b);
- const int tmp_v = VP8RGBToV(r, g, b);
- // Approximated average-of-four. But it's an acceptable diff.
- u[i] = (u[i] + tmp_u + 1) >> 1;
- v[i] = (v[i] + tmp_v + 1) >> 1;
- }
- }
- if (width & 1) { // last pixel
- const uint32_t v0 = src[2 * i + 0];
- const int r = (v0 >> 14) & 0x3fc;
- const int g = (v0 >> 6) & 0x3fc;
- const int b = (v0 << 2) & 0x3fc;
- if (!(y_pos & 1)) { // even lines
- u[i] = VP8RGBToU(r, g, b);
- v[i] = VP8RGBToV(r, g, b);
- } else { // odd lines (note: we could just skip this)
- const int tmp_u = VP8RGBToU(r, g, b);
- const int tmp_v = VP8RGBToV(r, g, b);
- u[i] = (u[i] + tmp_u + 1) >> 1;
- v[i] = (v[i] + tmp_v + 1) >> 1;
- }
- }
+ // even lines: store values
+ // odd lines: average with previous values
+ WebPConvertARGBToUV(src, u, v, width, !(y_pos & 1));
}
// Lastly, store alpha if needed.
if (buf->a != NULL) {
- int i;
uint8_t* const a = buf->a + y_pos * buf->a_stride;
- for (i = 0; i < width; ++i) a[i] = (src[i] >> 24);
+#if defined(WORDS_BIGENDIAN)
+ WebPExtractAlpha((uint8_t*)src + 0, 0, width, 1, a, 0);
+#else
+ WebPExtractAlpha((uint8_t*)src + 3, 0, width, 1, a, 0);
+#endif
}
}
static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {
WebPRescaler* const rescaler = dec->rescaler;
- const uint32_t* const src = (const uint32_t*)rescaler->dst;
+ uint32_t* const src = (uint32_t*)rescaler->dst;
const int dst_width = rescaler->dst_width;
int num_lines_out = 0;
while (WebPRescalerHasPendingOutput(rescaler)) {
WebPRescalerExportRow(rescaler);
+ WebPMultARGBRow(src, dst_width, 1);
ConvertToYUVA(src, dst_width, y_pos, dec->output_);
++y_pos;
++num_lines_out;
@@ -537,28 +617,28 @@ static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {
}
static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
- const uint32_t* const data,
- int in_stride, int mb_h) {
- const uint8_t* const in = (const uint8_t*)data;
+ uint8_t* in, int in_stride, int mb_h) {
int num_lines_in = 0;
int y_pos = dec->last_out_row_;
while (num_lines_in < mb_h) {
- const uint8_t* const row_in = in + num_lines_in * in_stride;
- num_lines_in += WebPRescalerImport(dec->rescaler, mb_h - num_lines_in,
- row_in, in_stride);
+ const int lines_left = mb_h - num_lines_in;
+ const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
+ WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0);
+ WebPRescalerImport(dec->rescaler, lines_left, in, in_stride);
+ num_lines_in += needed_lines;
+ in += needed_lines * in_stride;
y_pos += ExportYUVA(dec, y_pos);
}
return y_pos;
}
static int EmitRowsYUVA(const VP8LDecoder* const dec,
- const uint32_t* const data, int in_stride,
+ const uint8_t* in, int in_stride,
int mb_w, int num_rows) {
int y_pos = dec->last_out_row_;
- const uint8_t* row_in = (const uint8_t*)data;
while (num_rows-- > 0) {
- ConvertToYUVA((const uint32_t*)row_in, mb_w, y_pos, dec->output_);
- row_in += in_stride;
+ ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_);
+ in += in_stride;
++y_pos;
}
return y_pos;
@@ -569,11 +649,11 @@ static int EmitRowsYUVA(const VP8LDecoder* const dec,
// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and
// crop options. Also updates the input data pointer, so that it points to the
-// start of the cropped window.
-// Note that 'pixel_stride' is in units of 'uint32_t' (and not 'bytes).
+// start of the cropped window. Note that pixels are in ARGB format even if
+// 'in_data' is uint8_t*.
// Returns true if the crop window is not empty.
static int SetCropWindow(VP8Io* const io, int y_start, int y_end,
- const uint32_t** const in_data, int pixel_stride) {
+ uint8_t** const in_data, int pixel_stride) {
assert(y_start < y_end);
assert(io->crop_left < io->crop_right);
if (y_end > io->crop_bottom) {
@@ -582,11 +662,11 @@ static int SetCropWindow(VP8Io* const io, int y_start, int y_end,
if (y_start < io->crop_top) {
const int delta = io->crop_top - y_start;
y_start = io->crop_top;
- *in_data += pixel_stride * delta;
+ *in_data += delta * pixel_stride;
}
if (y_start >= y_end) return 0; // Crop window is empty.
- *in_data += io->crop_left;
+ *in_data += io->crop_left * sizeof(uint32_t);
io->mb_y = y_start - io->crop_top;
io->mb_w = io->crop_right - io->crop_left;
@@ -634,10 +714,24 @@ static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,
}
}
+// Special method for paletted alpha data.
+static void ApplyInverseTransformsAlpha(VP8LDecoder* const dec, int num_rows,
+ const uint8_t* const rows) {
+ const int start_row = dec->last_row_;
+ const int end_row = start_row + num_rows;
+ const uint8_t* rows_in = rows;
+ uint8_t* rows_out = (uint8_t*)dec->io_->opaque + dec->io_->width * start_row;
+ VP8LTransform* const transform = &dec->transforms_[0];
+ assert(dec->next_transform_ == 1);
+ assert(transform->type_ == COLOR_INDEXING_TRANSFORM);
+ VP8LColorIndexInverseTransformAlpha(transform, start_row, end_row, rows_in,
+ rows_out);
+}
+
// Processes (transforms, scales & color-converts) the rows decoded after the
// last call.
static void ProcessRows(VP8LDecoder* const dec, int row) {
- const uint32_t* const rows = dec->argb_ + dec->width_ * dec->last_row_;
+ const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_;
const int num_rows = row - dec->last_row_;
if (num_rows <= 0) return; // Nothing to be done.
@@ -646,18 +740,18 @@ static void ProcessRows(VP8LDecoder* const dec, int row) {
// Emit output.
{
VP8Io* const io = dec->io_;
- const uint32_t* rows_data = dec->argb_cache_;
- if (!SetCropWindow(io, dec->last_row_, row, &rows_data, io->width)) {
+ uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
+ const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA
+ if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
// Nothing to output (this time).
} else {
const WebPDecBuffer* const output = dec->output_;
- const int in_stride = io->width * sizeof(*rows_data);
- if (output->colorspace < MODE_YUV) { // convert to RGBA
+ if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA
const WebPRGBABuffer* const buf = &output->u.RGBA;
uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride;
const int num_rows_out = io->use_scaling ?
- EmitRescaledRows(dec, rows_data, in_stride, io->mb_h,
- rgba, buf->stride) :
+ EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h,
+ rgba, buf->stride) :
EmitRows(output->colorspace, rows_data, in_stride,
io->mb_w, io->mb_h, rgba, buf->stride);
// Update 'last_out_row_'.
@@ -676,50 +770,317 @@ static void ProcessRows(VP8LDecoder* const dec, int row) {
assert(dec->last_row_ <= dec->height_);
}
-static int DecodeImageData(VP8LDecoder* const dec,
- uint32_t* const data, int width, int height,
- ProcessRowsFunc process_func) {
+// Row-processing for the special case when alpha data contains only one
+// transform (color indexing), and trivial non-green literals.
+static int Is8bOptimizable(const VP8LMetadata* const hdr) {
+ int i;
+ if (hdr->color_cache_size_ > 0) return 0;
+ // When the Huffman tree contains only one symbol, we can skip the
+ // call to ReadSymbol() for red/blue/alpha channels.
+ for (i = 0; i < hdr->num_htree_groups_; ++i) {
+ HuffmanCode** const htrees = hdr->htree_groups_[i].htrees;
+ if (htrees[RED][0].bits > 0) return 0;
+ if (htrees[BLUE][0].bits > 0) return 0;
+ if (htrees[ALPHA][0].bits > 0) return 0;
+ }
+ return 1;
+}
+
+static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) {
+ const int num_rows = row - dec->last_row_;
+ const uint8_t* const in =
+ (uint8_t*)dec->pixels_ + dec->width_ * dec->last_row_;
+ if (num_rows > 0) {
+ ApplyInverseTransformsAlpha(dec, num_rows, in);
+ }
+ dec->last_row_ = dec->last_out_row_ = row;
+}
+
+//------------------------------------------------------------------------------
+// Helper functions for fast pattern copy (8b and 32b)
+
+// cyclic rotation of pattern word
+static WEBP_INLINE uint32_t Rotate8b(uint32_t V) {
+#if defined(WORDS_BIGENDIAN)
+ return ((V & 0xff000000u) >> 24) | (V << 8);
+#else
+ return ((V & 0xffu) << 24) | (V >> 8);
+#endif
+}
+
+// copy 1, 2 or 4-bytes pattern
+static WEBP_INLINE void CopySmallPattern8b(const uint8_t* src, uint8_t* dst,
+ int length, uint32_t pattern) {
+ int i;
+ // align 'dst' to 4-bytes boundary. Adjust the pattern along the way.
+ while ((uintptr_t)dst & 3) {
+ *dst++ = *src++;
+ pattern = Rotate8b(pattern);
+ --length;
+ }
+ // Copy the pattern 4 bytes at a time.
+ for (i = 0; i < (length >> 2); ++i) {
+ ((uint32_t*)dst)[i] = pattern;
+ }
+ // Finish with left-overs. 'pattern' is still correctly positioned,
+ // so no Rotate8b() call is needed.
+ for (i <<= 2; i < length; ++i) {
+ dst[i] = src[i];
+ }
+}
+
+static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
+ const uint8_t* src = dst - dist;
+ if (length >= 8) {
+ uint32_t pattern = 0;
+ switch (dist) {
+ case 1:
+ pattern = src[0];
+#if defined(__arm__) || defined(_M_ARM) // arm doesn't like multiply that much
+ pattern |= pattern << 8;
+ pattern |= pattern << 16;
+#elif defined(WEBP_USE_MIPS_DSP_R2)
+ __asm__ volatile ("replv.qb %0, %0" : "+r"(pattern));
+#else
+ pattern = 0x01010101u * pattern;
+#endif
+ break;
+ case 2:
+ memcpy(&pattern, src, sizeof(uint16_t));
+#if defined(__arm__) || defined(_M_ARM)
+ pattern |= pattern << 16;
+#elif defined(WEBP_USE_MIPS_DSP_R2)
+ __asm__ volatile ("replv.ph %0, %0" : "+r"(pattern));
+#else
+ pattern = 0x00010001u * pattern;
+#endif
+ break;
+ case 4:
+ memcpy(&pattern, src, sizeof(uint32_t));
+ break;
+ default:
+ goto Copy;
+ break;
+ }
+ CopySmallPattern8b(src, dst, length, pattern);
+ return;
+ }
+ Copy:
+ if (dist >= length) { // no overlap -> use memcpy()
+ memcpy(dst, src, length * sizeof(*dst));
+ } else {
+ int i;
+ for (i = 0; i < length; ++i) dst[i] = src[i];
+ }
+}
+
+// copy pattern of 1 or 2 uint32_t's
+static WEBP_INLINE void CopySmallPattern32b(const uint32_t* src,
+ uint32_t* dst,
+ int length, uint64_t pattern) {
+ int i;
+ if ((uintptr_t)dst & 4) { // Align 'dst' to 8-bytes boundary.
+ *dst++ = *src++;
+ pattern = (pattern >> 32) | (pattern << 32);
+ --length;
+ }
+ assert(0 == ((uintptr_t)dst & 7));
+ for (i = 0; i < (length >> 1); ++i) {
+ ((uint64_t*)dst)[i] = pattern; // Copy the pattern 8 bytes at a time.
+ }
+ if (length & 1) { // Finish with left-over.
+ dst[i << 1] = src[i << 1];
+ }
+}
+
+static WEBP_INLINE void CopyBlock32b(uint32_t* const dst,
+ int dist, int length) {
+ const uint32_t* const src = dst - dist;
+ if (dist <= 2 && length >= 4 && ((uintptr_t)dst & 3) == 0) {
+ uint64_t pattern;
+ if (dist == 1) {
+ pattern = (uint64_t)src[0];
+ pattern |= pattern << 32;
+ } else {
+ memcpy(&pattern, src, sizeof(pattern));
+ }
+ CopySmallPattern32b(src, dst, length, pattern);
+ } else if (dist >= length) { // no overlap
+ memcpy(dst, src, length * sizeof(*dst));
+ } else {
+ int i;
+ for (i = 0; i < length; ++i) dst[i] = src[i];
+ }
+}
+
+//------------------------------------------------------------------------------
+
+static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
+ int width, int height, int last_row) {
int ok = 1;
- int col = 0, row = 0;
+ int row = dec->last_pixel_ / width;
+ int col = dec->last_pixel_ % width;
VP8LBitReader* const br = &dec->br_;
VP8LMetadata* const hdr = &dec->hdr_;
- HTreeGroup* htree_group = hdr->htree_groups_;
- uint32_t* src = data;
- uint32_t* last_cached = data;
- uint32_t* const src_end = data + width * height;
+ const HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row);
+ int pos = dec->last_pixel_; // current position
+ const int end = width * height; // End of data
+ const int last = width * last_row; // Last pixel to decode
const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
- const int color_cache_limit = len_code_limit + hdr->color_cache_size_;
- VP8LColorCache* const color_cache =
- (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL;
const int mask = hdr->huffman_mask_;
-
assert(htree_group != NULL);
+ assert(pos < end);
+ assert(last_row <= height);
+ assert(Is8bOptimizable(hdr));
- while (!br->eos_ && src < src_end) {
+ while (!br->eos_ && pos < last) {
int code;
- // Only update when changing tile. Note we could use the following test:
- // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed
- // but that's actually slower and requires storing the previous col/row
+ // Only update when changing tile.
if ((col & mask) == 0) {
htree_group = GetHtreeGroupForPos(hdr, col, row);
}
VP8LFillBitWindow(br);
- code = ReadSymbol(&htree_group->htrees_[GREEN], br);
- if (code < NUM_LITERAL_CODES) { // Literal.
- int red, green, blue, alpha;
- red = ReadSymbol(&htree_group->htrees_[RED], br);
- green = code;
+ code = ReadSymbol(htree_group->htrees[GREEN], br);
+ if (code < NUM_LITERAL_CODES) { // Literal
+ data[pos] = code;
+ ++pos;
+ ++col;
+ if (col >= width) {
+ col = 0;
+ ++row;
+ if (row % NUM_ARGB_CACHE_ROWS == 0) {
+ ExtractPalettedAlphaRows(dec, row);
+ }
+ }
+ } else if (code < len_code_limit) { // Backward reference
+ int dist_code, dist;
+ const int length_sym = code - NUM_LITERAL_CODES;
+ const int length = GetCopyLength(length_sym, br);
+ const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br);
VP8LFillBitWindow(br);
- blue = ReadSymbol(&htree_group->htrees_[BLUE], br);
- alpha = ReadSymbol(&htree_group->htrees_[ALPHA], br);
- *src = (alpha << 24) + (red << 16) + (green << 8) + blue;
- AdvanceByOne:
+ dist_code = GetCopyDistance(dist_symbol, br);
+ dist = PlaneCodeToDistance(width, dist_code);
+ if (pos >= dist && end - pos >= length) {
+ CopyBlock8b(data + pos, dist, length);
+ } else {
+ ok = 0;
+ goto End;
+ }
+ pos += length;
+ col += length;
+ while (col >= width) {
+ col -= width;
+ ++row;
+ if (row % NUM_ARGB_CACHE_ROWS == 0) {
+ ExtractPalettedAlphaRows(dec, row);
+ }
+ }
+ if (pos < last && (col & mask)) {
+ htree_group = GetHtreeGroupForPos(hdr, col, row);
+ }
+ } else { // Not reached
+ ok = 0;
+ goto End;
+ }
+ assert(br->eos_ == VP8LIsEndOfStream(br));
+ }
+ // Process the remaining rows corresponding to last row-block.
+ ExtractPalettedAlphaRows(dec, row);
+
+ End:
+ if (!ok || (br->eos_ && pos < end)) {
+ ok = 0;
+ dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED
+ : VP8_STATUS_BITSTREAM_ERROR;
+ } else {
+ dec->last_pixel_ = pos;
+ }
+ return ok;
+}
+
+static void SaveState(VP8LDecoder* const dec, int last_pixel) {
+ assert(dec->incremental_);
+ dec->saved_br_ = dec->br_;
+ dec->saved_last_pixel_ = last_pixel;
+ if (dec->hdr_.color_cache_size_ > 0) {
+ VP8LColorCacheCopy(&dec->hdr_.color_cache_, &dec->hdr_.saved_color_cache_);
+ }
+}
+
+static void RestoreState(VP8LDecoder* const dec) {
+ assert(dec->br_.eos_);
+ dec->status_ = VP8_STATUS_SUSPENDED;
+ dec->br_ = dec->saved_br_;
+ dec->last_pixel_ = dec->saved_last_pixel_;
+ if (dec->hdr_.color_cache_size_ > 0) {
+ VP8LColorCacheCopy(&dec->hdr_.saved_color_cache_, &dec->hdr_.color_cache_);
+ }
+}
+
+#define SYNC_EVERY_N_ROWS 8 // minimum number of rows between check-points
+static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
+ int width, int height, int last_row,
+ ProcessRowsFunc process_func) {
+ int row = dec->last_pixel_ / width;
+ int col = dec->last_pixel_ % width;
+ VP8LBitReader* const br = &dec->br_;
+ VP8LMetadata* const hdr = &dec->hdr_;
+ HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row);
+ uint32_t* src = data + dec->last_pixel_;
+ uint32_t* last_cached = src;
+ uint32_t* const src_end = data + width * height; // End of data
+ uint32_t* const src_last = data + width * last_row; // Last pixel to decode
+ const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
+ const int color_cache_limit = len_code_limit + hdr->color_cache_size_;
+ int next_sync_row = dec->incremental_ ? row : 1 << 24;
+ VP8LColorCache* const color_cache =
+ (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL;
+ const int mask = hdr->huffman_mask_;
+ assert(htree_group != NULL);
+ assert(src < src_end);
+ assert(src_last <= src_end);
+
+ while (src < src_last) {
+ int code;
+ if (row >= next_sync_row) {
+ SaveState(dec, (int)(src - data));
+ next_sync_row = row + SYNC_EVERY_N_ROWS;
+ }
+ // Only update when changing tile. Note we could use this test:
+ // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed
+ // but that's actually slower and needs storing the previous col/row.
+ if ((col & mask) == 0) htree_group = GetHtreeGroupForPos(hdr, col, row);
+ if (htree_group->is_trivial_code) {
+ *src = htree_group->literal_arb;
+ goto AdvanceByOne;
+ }
+ VP8LFillBitWindow(br);
+ if (htree_group->use_packed_table) {
+ code = ReadPackedSymbols(htree_group, br, src);
+ if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne;
+ } else {
+ code = ReadSymbol(htree_group->htrees[GREEN], br);
+ }
+ if (br->eos_) break; // early out
+ if (code < NUM_LITERAL_CODES) { // Literal
+ if (htree_group->is_trivial_literal) {
+ *src = htree_group->literal_arb | (code << 8);
+ } else {
+ int red, blue, alpha;
+ red = ReadSymbol(htree_group->htrees[RED], br);
+ VP8LFillBitWindow(br);
+ blue = ReadSymbol(htree_group->htrees[BLUE], br);
+ alpha = ReadSymbol(htree_group->htrees[ALPHA], br);
+ if (br->eos_) break;
+ *src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue;
+ }
+ AdvanceByOne:
++src;
++col;
if (col >= width) {
col = 0;
++row;
- if ((process_func != NULL) && (row % NUM_ARGB_CACHE_ROWS == 0)) {
+ if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) {
process_func(dec, row);
}
if (color_cache != NULL) {
@@ -728,40 +1089,39 @@ static int DecodeImageData(VP8LDecoder* const dec,
}
}
}
- } else if (code < len_code_limit) { // Backward reference
+ } else if (code < len_code_limit) { // Backward reference
int dist_code, dist;
const int length_sym = code - NUM_LITERAL_CODES;
const int length = GetCopyLength(length_sym, br);
- const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br);
+ const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br);
VP8LFillBitWindow(br);
dist_code = GetCopyDistance(dist_symbol, br);
dist = PlaneCodeToDistance(width, dist_code);
- if (src - data < dist || src_end - src < length) {
- ok = 0;
- goto End;
- }
- {
- int i;
- for (i = 0; i < length; ++i) src[i] = src[i - dist];
- src += length;
+ if (br->eos_) break;
+ if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {
+ goto Error;
+ } else {
+ CopyBlock32b(src, dist, length);
}
+ src += length;
col += length;
while (col >= width) {
col -= width;
++row;
- if ((process_func != NULL) && (row % NUM_ARGB_CACHE_ROWS == 0)) {
+ if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) {
process_func(dec, row);
}
}
- if (src < src_end) {
- htree_group = GetHtreeGroupForPos(hdr, col, row);
- if (color_cache != NULL) {
- while (last_cached < src) {
- VP8LColorCacheInsert(color_cache, *last_cached++);
- }
+ // Because of the check done above (before 'src' was incremented by
+ // 'length'), the following holds true.
+ assert(src <= src_end);
+ if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row);
+ if (color_cache != NULL) {
+ while (last_cached < src) {
+ VP8LColorCacheInsert(color_cache, *last_cached++);
}
}
- } else if (code < color_cache_limit) { // Color cache.
+ } else if (code < color_cache_limit) { // Color cache
const int key = code - len_code_limit;
assert(color_cache != NULL);
while (last_cached < src) {
@@ -769,33 +1129,38 @@ static int DecodeImageData(VP8LDecoder* const dec,
}
*src = VP8LColorCacheLookup(color_cache, key);
goto AdvanceByOne;
- } else { // Not reached.
- ok = 0;
- goto End;
+ } else { // Not reached
+ goto Error;
}
- ok = !br->error_;
- if (!ok) goto End;
+ assert(br->eos_ == VP8LIsEndOfStream(br));
}
- // Process the remaining rows corresponding to last row-block.
- if (process_func != NULL) process_func(dec, row);
- End:
- if (br->error_ || !ok || (br->eos_ && src < src_end)) {
- ok = 0;
- dec->status_ = (!br->eos_) ?
- VP8_STATUS_BITSTREAM_ERROR : VP8_STATUS_SUSPENDED;
- } else if (src == src_end) {
- dec->state_ = READ_DATA;
+ if (dec->incremental_ && br->eos_ && src < src_end) {
+ RestoreState(dec);
+ } else if (!br->eos_) {
+ // Process the remaining rows corresponding to last row-block.
+ if (process_func != NULL) {
+ process_func(dec, row);
+ }
+ dec->status_ = VP8_STATUS_OK;
+ dec->last_pixel_ = (int)(src - data); // end-of-scan marker
+ } else {
+ // if not incremental, and we are past the end of buffer (eos_=1), then this
+ // is a real bitstream error.
+ goto Error;
}
+ return 1;
- return ok;
+ Error:
+ dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
+ return 0;
}
// -----------------------------------------------------------------------------
// VP8LTransform
static void ClearTransform(VP8LTransform* const transform) {
- free(transform->data_);
+ WebPSafeFree(transform->data_);
transform->data_ = NULL;
}
@@ -819,7 +1184,7 @@ static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {
}
for (; i < 4 * final_num_colors; ++i)
new_data[i] = 0; // black tail.
- free(transform->data_);
+ WebPSafeFree(transform->data_);
transform->data_ = new_color_map;
}
return 1;
@@ -882,16 +1247,18 @@ static int ReadTransform(int* const xsize, int const* ysize,
// VP8LMetadata
static void InitMetadata(VP8LMetadata* const hdr) {
- assert(hdr);
+ assert(hdr != NULL);
memset(hdr, 0, sizeof(*hdr));
}
static void ClearMetadata(VP8LMetadata* const hdr) {
- assert(hdr);
+ assert(hdr != NULL);
- free(hdr->huffman_image_);
- DeleteHtreeGroups(hdr->htree_groups_, hdr->num_htree_groups_);
+ WebPSafeFree(hdr->huffman_image_);
+ WebPSafeFree(hdr->huffman_tables_);
+ VP8LHtreeGroupsFree(hdr->htree_groups_);
VP8LColorCacheClear(&hdr->color_cache_);
+ VP8LColorCacheClear(&hdr->saved_color_cache_);
InitMetadata(hdr);
}
@@ -899,11 +1266,13 @@ static void ClearMetadata(VP8LMetadata* const hdr) {
// VP8LDecoder
VP8LDecoder* VP8LNew(void) {
- VP8LDecoder* const dec = (VP8LDecoder*)calloc(1, sizeof(*dec));
+ VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
if (dec == NULL) return NULL;
dec->status_ = VP8_STATUS_OK;
- dec->action_ = READ_DIM;
dec->state_ = READ_DIM;
+
+ VP8LDspInit(); // Init critical function pointers.
+
return dec;
}
@@ -912,15 +1281,15 @@ void VP8LClear(VP8LDecoder* const dec) {
if (dec == NULL) return;
ClearMetadata(&dec->hdr_);
- free(dec->argb_);
- dec->argb_ = NULL;
+ WebPSafeFree(dec->pixels_);
+ dec->pixels_ = NULL;
for (i = 0; i < dec->next_transform_; ++i) {
ClearTransform(&dec->transforms_[i]);
}
dec->next_transform_ = 0;
dec->transforms_seen_ = 0;
- free(dec->rescaler_memory);
+ WebPSafeFree(dec->rescaler_memory);
dec->rescaler_memory = NULL;
dec->output_ = NULL; // leave no trace behind
@@ -929,7 +1298,7 @@ void VP8LClear(VP8LDecoder* const dec) {
void VP8LDelete(VP8LDecoder* const dec) {
if (dec != NULL) {
VP8LClear(dec);
- free(dec);
+ WebPSafeFree(dec);
}
}
@@ -1009,19 +1378,14 @@ static int DecodeImageStream(int xsize, int ysize,
}
// Use the Huffman trees to decode the LZ77 encoded data.
- ok = DecodeImageData(dec, data, transform_xsize, transform_ysize, NULL);
- ok = ok && !br->error_;
+ ok = DecodeImageData(dec, data, transform_xsize, transform_ysize,
+ transform_ysize, NULL);
+ ok = ok && !br->eos_;
End:
-
if (!ok) {
- free(data);
+ WebPSafeFree(data);
ClearMetadata(hdr);
- // If not enough data (br.eos_) resulted in BIT_STREAM_ERROR, update the
- // status appropriately.
- if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && dec->br_.eos_) {
- dec->status_ = VP8_STATUS_SUSPENDED;
- }
} else {
if (decoded_data != NULL) {
*decoded_data = data;
@@ -1031,41 +1395,52 @@ static int DecodeImageStream(int xsize, int ysize,
assert(data == NULL);
assert(is_level0);
}
+ dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls.
if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind.
}
return ok;
}
//------------------------------------------------------------------------------
-// Allocate dec->argb_ and dec->argb_cache_ using dec->width_ and dec->height_
-
-static int AllocateARGBBuffers(VP8LDecoder* const dec, int final_width) {
+// Allocate internal buffers dec->pixels_ and dec->argb_cache_.
+static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {
const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_;
// Scratch buffer corresponding to top-prediction row for transforming the
- // first row in the row-blocks.
- const uint64_t cache_top_pixels = final_width;
- // Scratch buffer for temporary BGRA storage.
+ // first row in the row-blocks. Not needed for paletted alpha.
+ const uint64_t cache_top_pixels = (uint16_t)final_width;
+ // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha.
const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS;
const uint64_t total_num_pixels =
num_pixels + cache_top_pixels + cache_pixels;
assert(dec->width_ <= final_width);
- dec->argb_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(*dec->argb_));
- if (dec->argb_ == NULL) {
+ dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t));
+ if (dec->pixels_ == NULL) {
dec->argb_cache_ = NULL; // for sanity check
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
return 0;
}
- dec->argb_cache_ = dec->argb_ + num_pixels + cache_top_pixels;
+ dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels;
+ return 1;
+}
+
+static int AllocateInternalBuffers8b(VP8LDecoder* const dec) {
+ const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_;
+ dec->argb_cache_ = NULL; // for sanity check
+ dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t));
+ if (dec->pixels_ == NULL) {
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ return 0;
+ }
return 1;
}
//------------------------------------------------------------------------------
-// Special row-processing that only stores the alpha data.
+// Special row-processing that only stores the alpha data.
static void ExtractAlphaRows(VP8LDecoder* const dec, int row) {
const int num_rows = row - dec->last_row_;
- const uint32_t* const in = dec->argb_ + dec->width_ * dec->last_row_;
+ const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_;
if (num_rows <= 0) return; // Nothing to be done.
ApplyInverseTransforms(dec, num_rows, in);
@@ -1079,44 +1454,77 @@ static void ExtractAlphaRows(VP8LDecoder* const dec, int row) {
int i;
for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff;
}
-
dec->last_row_ = dec->last_out_row_ = row;
}
-int VP8LDecodeAlphaImageStream(int width, int height, const uint8_t* const data,
- size_t data_size, uint8_t* const output) {
- VP8Io io;
+int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
+ const uint8_t* const data, size_t data_size,
+ uint8_t* const output) {
int ok = 0;
- VP8LDecoder* const dec = VP8LNew();
- if (dec == NULL) return 0;
-
- dec->width_ = width;
- dec->height_ = height;
- dec->io_ = &io;
+ VP8LDecoder* dec;
+ VP8Io* io;
+ assert(alph_dec != NULL);
+ alph_dec->vp8l_dec_ = VP8LNew();
+ if (alph_dec->vp8l_dec_ == NULL) return 0;
+ dec = alph_dec->vp8l_dec_;
+
+ dec->width_ = alph_dec->width_;
+ dec->height_ = alph_dec->height_;
+ dec->io_ = &alph_dec->io_;
+ io = dec->io_;
- VP8InitIo(&io);
- WebPInitCustomIo(NULL, &io); // Just a sanity Init. io won't be used.
- io.opaque = output;
- io.width = width;
- io.height = height;
+ VP8InitIo(io);
+ WebPInitCustomIo(NULL, io); // Just a sanity Init. io won't be used.
+ io->opaque = output;
+ io->width = alph_dec->width_;
+ io->height = alph_dec->height_;
dec->status_ = VP8_STATUS_OK;
VP8LInitBitReader(&dec->br_, data, data_size);
- dec->action_ = READ_HDR;
- if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Err;
+ if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) {
+ goto Err;
+ }
- // Allocate output (note that dec->width_ may have changed here).
- if (!AllocateARGBBuffers(dec, width)) goto Err;
+ // Special case: if alpha data uses only the color indexing transform and
+ // doesn't use color cache (a frequent case), we will use DecodeAlphaData()
+ // method that only needs allocation of 1 byte per pixel (alpha channel).
+ if (dec->next_transform_ == 1 &&
+ dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM &&
+ Is8bOptimizable(&dec->hdr_)) {
+ alph_dec->use_8b_decode = 1;
+ ok = AllocateInternalBuffers8b(dec);
+ } else {
+ // Allocate internal buffers (note that dec->width_ may have changed here).
+ alph_dec->use_8b_decode = 0;
+ ok = AllocateInternalBuffers32b(dec, alph_dec->width_);
+ }
- // Decode (with special row processing).
- dec->action_ = READ_DATA;
- ok = DecodeImageData(dec, dec->argb_, dec->width_, dec->height_,
- ExtractAlphaRows);
+ if (!ok) goto Err;
+
+ return 1;
Err:
- VP8LDelete(dec);
- return ok;
+ VP8LDelete(alph_dec->vp8l_dec_);
+ alph_dec->vp8l_dec_ = NULL;
+ return 0;
+}
+
+int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) {
+ VP8LDecoder* const dec = alph_dec->vp8l_dec_;
+ assert(dec != NULL);
+ assert(last_row <= dec->height_);
+
+ if (dec->last_pixel_ == dec->width_ * dec->height_) {
+ return 1; // done
+ }
+
+ // Decode (with special row processing).
+ return alph_dec->use_8b_decode ?
+ DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_,
+ last_row) :
+ DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
+ last_row, ExtractAlphaRows);
}
//------------------------------------------------------------------------------
@@ -1141,14 +1549,13 @@ int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {
io->width = width;
io->height = height;
- dec->action_ = READ_HDR;
if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error;
return 1;
Error:
- VP8LClear(dec);
- assert(dec->status_ != VP8_STATUS_OK);
- return 0;
+ VP8LClear(dec);
+ assert(dec->status_ != VP8_STATUS_OK);
+ return 0;
}
int VP8LDecodeImage(VP8LDecoder* const dec) {
@@ -1158,33 +1565,57 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
// Sanity checks.
if (dec == NULL) return 0;
+ assert(dec->hdr_.huffman_tables_ != NULL);
+ assert(dec->hdr_.htree_groups_ != NULL);
+ assert(dec->hdr_.num_htree_groups_ > 0);
+
io = dec->io_;
assert(io != NULL);
params = (WebPDecParams*)io->opaque;
assert(params != NULL);
- dec->output_ = params->output;
- assert(dec->output_ != NULL);
// Initialization.
- if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {
- dec->status_ = VP8_STATUS_INVALID_PARAM;
- goto Err;
- }
+ if (dec->state_ != READ_DATA) {
+ dec->output_ = params->output;
+ assert(dec->output_ != NULL);
+
+ if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {
+ dec->status_ = VP8_STATUS_INVALID_PARAM;
+ goto Err;
+ }
- if (!AllocateARGBBuffers(dec, io->width)) goto Err;
+ if (!AllocateInternalBuffers32b(dec, io->width)) goto Err;
- if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
+ if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
+
+ if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) {
+ // need the alpha-multiply functions for premultiplied output or rescaling
+ WebPInitAlphaProcessing();
+ }
+ if (!WebPIsRGBMode(dec->output_->colorspace)) {
+ WebPInitConvertARGBToYUV();
+ if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing();
+ }
+ if (dec->incremental_) {
+ if (dec->hdr_.color_cache_size_ > 0 &&
+ dec->hdr_.saved_color_cache_.colors_ == NULL) {
+ if (!VP8LColorCacheInit(&dec->hdr_.saved_color_cache_,
+ dec->hdr_.color_cache_.hash_bits_)) {
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ goto Err;
+ }
+ }
+ }
+ dec->state_ = READ_DATA;
+ }
// Decode.
- dec->action_ = READ_DATA;
- if (!DecodeImageData(dec, dec->argb_, dec->width_, dec->height_,
- ProcessRows)) {
+ if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
+ dec->height_, ProcessRows)) {
goto Err;
}
- // Cleanup.
params->last_y = dec->last_out_row_;
- VP8LClear(dec);
return 1;
Err:
@@ -1194,7 +1625,3 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
}
//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/dec/vp8li.h b/drivers/webp/dec/vp8li.h
index 5f6cd6a01c..8886e47f62 100644
--- a/drivers/webp/dec/vp8li.h
+++ b/drivers/webp/dec/vp8li.h
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Lossless decoder: internal header.
@@ -18,9 +20,8 @@
#include "../utils/bit_reader.h"
#include "../utils/color_cache.h"
#include "../utils/huffman.h"
-#include "../format_constants.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
@@ -40,12 +41,9 @@ struct VP8LTransform {
};
typedef struct {
- HuffmanTree htrees_[HUFFMAN_CODES_PER_META_CODE];
-} HTreeGroup;
-
-typedef struct {
int color_cache_size_;
VP8LColorCache color_cache_;
+ VP8LColorCache saved_color_cache_; // for incremental
int huffman_mask_;
int huffman_subsample_bits_;
@@ -53,24 +51,32 @@ typedef struct {
uint32_t *huffman_image_;
int num_htree_groups_;
HTreeGroup *htree_groups_;
+ HuffmanCode *huffman_tables_;
} VP8LMetadata;
-typedef struct {
+typedef struct VP8LDecoder VP8LDecoder;
+struct VP8LDecoder {
VP8StatusCode status_;
- VP8LDecodeState action_;
VP8LDecodeState state_;
VP8Io *io_;
const WebPDecBuffer *output_; // shortcut to io->opaque->output
- uint32_t *argb_; // Internal data: always in BGRA color mode.
+ uint32_t *pixels_; // Internal data: either uint8_t* for alpha
+ // or uint32_t* for BGRA.
uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage.
VP8LBitReader br_;
+ int incremental_; // if true, incremental decoding is expected
+ VP8LBitReader saved_br_; // note: could be local variables too
+ int saved_last_pixel_;
int width_;
int height_;
int last_row_; // last input row decoded so far.
+ int last_pixel_; // last pixel decoded so far. However, it may
+ // not be transformed, scaled and
+ // color-converted yet.
int last_out_row_; // last row output so far.
VP8LMetadata hdr_;
@@ -82,18 +88,27 @@ typedef struct {
uint8_t *rescaler_memory; // Working memory for rescaling work.
WebPRescaler *rescaler; // Common rescaler for all channels.
-} VP8LDecoder;
+};
//------------------------------------------------------------------------------
// internal functions. Not public.
+struct ALPHDecoder; // Defined in dec/alphai.h.
+
// in vp8l.c
-// Decodes a raw image stream (without header) and store the alpha data
-// into *output, which must be of size width x height. Returns false in case
-// of error.
-int VP8LDecodeAlphaImageStream(int width, int height, const uint8_t* const data,
- size_t data_size, uint8_t* const output);
+// Decodes image header for alpha data stored using lossless compression.
+// Returns false in case of error.
+int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec,
+ const uint8_t* const data, size_t data_size,
+ uint8_t* const output);
+
+// Decodes *at least* 'last_row' rows of alpha. If some of the initial rows are
+// already decoded in previous call(s), it will resume decoding from where it
+// was paused.
+// Returns false in case of bitstream error.
+int VP8LDecodeAlphaImageStream(struct ALPHDecoder* const alph_dec,
+ int last_row);
// Allocates and initialize a new lossless decoder instance.
VP8LDecoder* VP8LNew(void);
@@ -114,7 +129,7 @@ void VP8LDelete(VP8LDecoder* const dec);
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/dec/webp.c b/drivers/webp/dec/webp.c
index f44bc2b8ae..93a113a48d 100644
--- a/drivers/webp/dec/webp.c
+++ b/drivers/webp/dec/webp.c
@@ -1,8 +1,10 @@
// Copyright 2010 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Main decoding functions for WEBP images.
@@ -14,11 +16,8 @@
#include "./vp8i.h"
#include "./vp8li.h"
#include "./webpi.h"
-#include "../format_constants.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+#include "../utils/utils.h"
+#include "webp/mux_types.h" // ALPHA_FLAG
//------------------------------------------------------------------------------
// RIFF layout is:
@@ -40,27 +39,20 @@ extern "C" {
// 20..23 VP8X flags bit-map corresponding to the chunk-types present.
// 24..26 Width of the Canvas Image.
// 27..29 Height of the Canvas Image.
-// There can be extra chunks after the "VP8X" chunk (ICCP, TILE, FRM, VP8,
-// META ...)
+// There can be extra chunks after the "VP8X" chunk (ICCP, FRGM, ANMF, VP8,
+// VP8L, XMP, EXIF ...)
// All sizes are in little-endian order.
// Note: chunk data size must be padded to multiple of 2 when written.
-static WEBP_INLINE uint32_t get_le24(const uint8_t* const data) {
- return data[0] | (data[1] << 8) | (data[2] << 16);
-}
-
-static WEBP_INLINE uint32_t get_le32(const uint8_t* const data) {
- return (uint32_t)get_le24(data) | (data[3] << 24);
-}
-
// Validates the RIFF container (if detected) and skips over it.
-// If a RIFF container is detected,
-// Returns VP8_STATUS_BITSTREAM_ERROR for invalid header, and
-// VP8_STATUS_OK otherwise.
+// If a RIFF container is detected, returns:
+// VP8_STATUS_BITSTREAM_ERROR for invalid header,
+// VP8_STATUS_NOT_ENOUGH_DATA for truncated data if have_all_data is true,
+// and VP8_STATUS_OK otherwise.
// In case there are not enough bytes (partial RIFF container), return 0 for
// *riff_size. Else return the RIFF size extracted from the header.
static VP8StatusCode ParseRIFF(const uint8_t** const data,
- size_t* const data_size,
+ size_t* const data_size, int have_all_data,
size_t* const riff_size) {
assert(data != NULL);
assert(data_size != NULL);
@@ -71,11 +63,17 @@ static VP8StatusCode ParseRIFF(const uint8_t** const data,
if (memcmp(*data + 8, "WEBP", TAG_SIZE)) {
return VP8_STATUS_BITSTREAM_ERROR; // Wrong image file signature.
} else {
- const uint32_t size = get_le32(*data + TAG_SIZE);
+ const uint32_t size = GetLE32(*data + TAG_SIZE);
// Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn").
if (size < TAG_SIZE + CHUNK_HEADER_SIZE) {
return VP8_STATUS_BITSTREAM_ERROR;
}
+ if (size > MAX_CHUNK_PAYLOAD) {
+ return VP8_STATUS_BITSTREAM_ERROR;
+ }
+ if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) {
+ return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream.
+ }
// We have a RIFF container. Skip it.
*riff_size = size;
*data += RIFF_HEADER_SIZE;
@@ -111,7 +109,7 @@ static VP8StatusCode ParseVP8X(const uint8_t** const data,
if (!memcmp(*data, "VP8X", TAG_SIZE)) {
int width, height;
uint32_t flags;
- const uint32_t chunk_size = get_le32(*data + TAG_SIZE);
+ const uint32_t chunk_size = GetLE32(*data + TAG_SIZE);
if (chunk_size != VP8X_CHUNK_SIZE) {
return VP8_STATUS_BITSTREAM_ERROR; // Wrong chunk size.
}
@@ -120,9 +118,9 @@ static VP8StatusCode ParseVP8X(const uint8_t** const data,
if (*data_size < vp8x_size) {
return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data.
}
- flags = get_le32(*data + 8);
- width = 1 + get_le24(*data + 12);
- height = 1 + get_le24(*data + 15);
+ flags = GetLE32(*data + 8);
+ width = 1 + GetLE24(*data + 12);
+ height = 1 + GetLE24(*data + 15);
if (width * (uint64_t)height >= MAX_IMAGE_AREA) {
return VP8_STATUS_BITSTREAM_ERROR; // image is too large
}
@@ -176,7 +174,10 @@ static VP8StatusCode ParseOptionalChunks(const uint8_t** const data,
return VP8_STATUS_NOT_ENOUGH_DATA;
}
- chunk_size = get_le32(buf + TAG_SIZE);
+ chunk_size = GetLE32(buf + TAG_SIZE);
+ if (chunk_size > MAX_CHUNK_PAYLOAD) {
+ return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size.
+ }
// For odd-sized chunk-payload, there's one byte padding at the end.
disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1;
total_size += disk_chunk_size;
@@ -186,6 +187,15 @@ static VP8StatusCode ParseOptionalChunks(const uint8_t** const data,
return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size.
}
+ // Start of a (possibly incomplete) VP8/VP8L chunk implies that we have
+ // parsed all the optional chunks.
+ // Note: This check must occur before the check 'buf_size < disk_chunk_size'
+ // below to allow incomplete VP8/VP8L chunks.
+ if (!memcmp(buf, "VP8 ", TAG_SIZE) ||
+ !memcmp(buf, "VP8L", TAG_SIZE)) {
+ return VP8_STATUS_OK;
+ }
+
if (buf_size < disk_chunk_size) { // Insufficient data.
return VP8_STATUS_NOT_ENOUGH_DATA;
}
@@ -193,9 +203,6 @@ static VP8StatusCode ParseOptionalChunks(const uint8_t** const data,
if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header.
*alpha_data = buf + CHUNK_HEADER_SIZE;
*alpha_size = chunk_size;
- } else if (!memcmp(buf, "VP8 ", TAG_SIZE) ||
- !memcmp(buf, "VP8L", TAG_SIZE)) { // A valid VP8/VP8L header.
- return VP8_STATUS_OK; // Found.
}
// We have a full and valid chunk; skip it.
@@ -213,9 +220,8 @@ static VP8StatusCode ParseOptionalChunks(const uint8_t** const data,
// extracted from the VP8/VP8L chunk header.
// The flag '*is_lossless' is set to 1 in case of VP8L chunk / raw VP8L data.
static VP8StatusCode ParseVP8Header(const uint8_t** const data_ptr,
- size_t* const data_size,
- size_t riff_size,
- size_t* const chunk_size,
+ size_t* const data_size, int have_all_data,
+ size_t riff_size, size_t* const chunk_size,
int* const is_lossless) {
const uint8_t* const data = *data_ptr;
const int is_vp8 = !memcmp(data, "VP8 ", TAG_SIZE);
@@ -234,10 +240,13 @@ static VP8StatusCode ParseVP8Header(const uint8_t** const data_ptr,
if (is_vp8 || is_vp8l) {
// Bitstream contains VP8/VP8L header.
- const uint32_t size = get_le32(data + TAG_SIZE);
+ const uint32_t size = GetLE32(data + TAG_SIZE);
if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) {
return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information.
}
+ if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) {
+ return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream.
+ }
// Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header.
*chunk_size = size;
*data_ptr += CHUNK_HEADER_SIZE;
@@ -270,9 +279,19 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
int* const width,
int* const height,
int* const has_alpha,
+ int* const has_animation,
+ int* const format,
WebPHeaderStructure* const headers) {
+ int canvas_width = 0;
+ int canvas_height = 0;
+ int image_width = 0;
+ int image_height = 0;
int found_riff = 0;
int found_vp8x = 0;
+ int animation_present = 0;
+ int fragments_present = 0;
+ const int have_all_data = (headers != NULL) ? headers->have_all_data : 0;
+
VP8StatusCode status;
WebPHeaderStructure hdrs;
@@ -284,7 +303,7 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
hdrs.data_size = data_size;
// Skip over RIFF header.
- status = ParseRIFF(&data, &data_size, &hdrs.riff_size);
+ status = ParseRIFF(&data, &data_size, have_all_data, &hdrs.riff_size);
if (status != VP8_STATUS_OK) {
return status; // Wrong RIFF header / insufficient data.
}
@@ -293,22 +312,35 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
// Skip over VP8X.
{
uint32_t flags = 0;
- status = ParseVP8X(&data, &data_size, &found_vp8x, width, height, &flags);
+ status = ParseVP8X(&data, &data_size, &found_vp8x,
+ &canvas_width, &canvas_height, &flags);
if (status != VP8_STATUS_OK) {
return status; // Wrong VP8X / insufficient data.
}
+ animation_present = !!(flags & ANIMATION_FLAG);
+ fragments_present = !!(flags & FRAGMENTS_FLAG);
if (!found_riff && found_vp8x) {
// Note: This restriction may be removed in the future, if it becomes
// necessary to send VP8X chunk to the decoder.
return VP8_STATUS_BITSTREAM_ERROR;
}
- if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG_BIT);
- if (found_vp8x && headers == NULL) {
- return VP8_STATUS_OK; // Return features from VP8X header.
+ if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG);
+ if (has_animation != NULL) *has_animation = animation_present;
+ if (format != NULL) *format = 0; // default = undefined
+
+ image_width = canvas_width;
+ image_height = canvas_height;
+ if (found_vp8x && (animation_present || fragments_present) &&
+ headers == NULL) {
+ status = VP8_STATUS_OK;
+ goto ReturnWidthHeight; // Just return features from VP8X header.
}
}
- if (data_size < TAG_SIZE) return VP8_STATUS_NOT_ENOUGH_DATA;
+ if (data_size < TAG_SIZE) {
+ status = VP8_STATUS_NOT_ENOUGH_DATA;
+ goto ReturnWidthHeight;
+ }
// Skip over optional chunks if data started with "RIFF + VP8X" or "ALPH".
if ((found_riff && found_vp8x) ||
@@ -316,43 +348,49 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
status = ParseOptionalChunks(&data, &data_size, hdrs.riff_size,
&hdrs.alpha_data, &hdrs.alpha_data_size);
if (status != VP8_STATUS_OK) {
- return status; // Found an invalid chunk size / insufficient data.
+ goto ReturnWidthHeight; // Invalid chunk size / insufficient data.
}
}
// Skip over VP8/VP8L header.
- status = ParseVP8Header(&data, &data_size, hdrs.riff_size,
+ status = ParseVP8Header(&data, &data_size, have_all_data, hdrs.riff_size,
&hdrs.compressed_size, &hdrs.is_lossless);
if (status != VP8_STATUS_OK) {
- return status; // Wrong VP8/VP8L chunk-header / insufficient data.
+ goto ReturnWidthHeight; // Wrong VP8/VP8L chunk-header / insufficient data.
}
if (hdrs.compressed_size > MAX_CHUNK_PAYLOAD) {
return VP8_STATUS_BITSTREAM_ERROR;
}
+ if (format != NULL && !(animation_present || fragments_present)) {
+ *format = hdrs.is_lossless ? 2 : 1;
+ }
+
if (!hdrs.is_lossless) {
if (data_size < VP8_FRAME_HEADER_SIZE) {
- return VP8_STATUS_NOT_ENOUGH_DATA;
+ status = VP8_STATUS_NOT_ENOUGH_DATA;
+ goto ReturnWidthHeight;
}
// Validates raw VP8 data.
- if (!VP8GetInfo(data, data_size,
- (uint32_t)hdrs.compressed_size, width, height)) {
+ if (!VP8GetInfo(data, data_size, (uint32_t)hdrs.compressed_size,
+ &image_width, &image_height)) {
return VP8_STATUS_BITSTREAM_ERROR;
}
} else {
if (data_size < VP8L_FRAME_HEADER_SIZE) {
- return VP8_STATUS_NOT_ENOUGH_DATA;
+ status = VP8_STATUS_NOT_ENOUGH_DATA;
+ goto ReturnWidthHeight;
}
// Validates raw VP8L data.
- if (!VP8LGetInfo(data, data_size, width, height, has_alpha)) {
+ if (!VP8LGetInfo(data, data_size, &image_width, &image_height, has_alpha)) {
return VP8_STATUS_BITSTREAM_ERROR;
}
}
-
- if (has_alpha != NULL) {
- // If the data did not contain a VP8X/VP8L chunk the only definitive way
- // to set this is by looking for alpha data (from an ALPH chunk).
- *has_alpha |= (hdrs.alpha_data != NULL);
+ // Validates image size coherency.
+ if (found_vp8x) {
+ if (canvas_width != image_width || canvas_height != image_height) {
+ return VP8_STATUS_BITSTREAM_ERROR;
+ }
}
if (headers != NULL) {
*headers = hdrs;
@@ -360,21 +398,44 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD);
assert(headers->offset == headers->data_size - data_size);
}
- return VP8_STATUS_OK; // Return features from VP8 header.
+ ReturnWidthHeight:
+ if (status == VP8_STATUS_OK ||
+ (status == VP8_STATUS_NOT_ENOUGH_DATA && found_vp8x && headers == NULL)) {
+ if (has_alpha != NULL) {
+ // If the data did not contain a VP8X/VP8L chunk the only definitive way
+ // to set this is by looking for alpha data (from an ALPH chunk).
+ *has_alpha |= (hdrs.alpha_data != NULL);
+ }
+ if (width != NULL) *width = image_width;
+ if (height != NULL) *height = image_height;
+ return VP8_STATUS_OK;
+ } else {
+ return status;
+ }
}
VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) {
+ VP8StatusCode status;
+ int has_animation = 0;
assert(headers != NULL);
// fill out headers, ignore width/height/has_alpha.
- return ParseHeadersInternal(headers->data, headers->data_size,
- NULL, NULL, NULL, headers);
+ status = ParseHeadersInternal(headers->data, headers->data_size,
+ NULL, NULL, NULL, &has_animation,
+ NULL, headers);
+ if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) {
+ // TODO(jzern): full support of animation frames will require API additions.
+ if (has_animation) {
+ status = VP8_STATUS_UNSUPPORTED_FEATURE;
+ }
+ }
+ return status;
}
//------------------------------------------------------------------------------
// WebPDecParams
void WebPResetDecParams(WebPDecParams* const params) {
- if (params) {
+ if (params != NULL) {
memset(params, 0, sizeof(*params));
}
}
@@ -391,6 +452,7 @@ static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size,
headers.data = data;
headers.data_size = data_size;
+ headers.have_all_data = 1;
status = WebPParseHeaders(&headers); // Process Pre-VP8 chunks.
if (status != VP8_STATUS_OK) {
return status;
@@ -407,11 +469,6 @@ static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size,
if (dec == NULL) {
return VP8_STATUS_OUT_OF_MEMORY;
}
-#ifdef WEBP_USE_THREAD
- dec->use_threads_ = params->options && (params->options->use_threads > 0);
-#else
- dec->use_threads_ = 0;
-#endif
dec->alpha_data_ = headers.alpha_data;
dec->alpha_data_size_ = headers.alpha_data_size;
@@ -423,6 +480,10 @@ static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size,
status = WebPAllocateDecBuffer(io.width, io.height, params->options,
params->output);
if (status == VP8_STATUS_OK) { // Decode
+ // This change must be done before calling VP8Decode()
+ dec->mt_method_ = VP8GetThreadMethod(params->options, &headers,
+ io.width, io.height);
+ VP8InitDithering(params->options, dec);
if (!VP8Decode(dec, &io)) {
status = dec->status_;
}
@@ -452,6 +513,10 @@ static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size,
if (status != VP8_STATUS_OK) {
WebPFreeDecBuffer(params->output);
}
+
+ if (params->options != NULL && params->options->flip) {
+ status = WebPFlipBuffer(params->output);
+ }
return status;
}
@@ -609,7 +674,6 @@ uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size,
static void DefaultFeatures(WebPBitstreamFeatures* const features) {
assert(features != NULL);
memset(features, 0, sizeof(*features));
- features->bitstream_version = 0;
}
static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size,
@@ -619,10 +683,11 @@ static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size,
}
DefaultFeatures(features);
- // Only parse enough of the data to retrieve width/height/has_alpha.
+ // Only parse enough of the data to retrieve the features.
return ParseHeadersInternal(data, data_size,
&features->width, &features->height,
- &features->has_alpha, NULL);
+ &features->has_alpha, &features->has_animation,
+ &features->format, NULL);
}
//------------------------------------------------------------------------------
@@ -666,19 +731,13 @@ int WebPInitDecoderConfigInternal(WebPDecoderConfig* config,
VP8StatusCode WebPGetFeaturesInternal(const uint8_t* data, size_t data_size,
WebPBitstreamFeatures* features,
int version) {
- VP8StatusCode status;
if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
return VP8_STATUS_INVALID_PARAM; // version mismatch
}
if (features == NULL) {
return VP8_STATUS_INVALID_PARAM;
}
-
- status = GetFeatures(data, data_size, features);
- if (status == VP8_STATUS_NOT_ENOUGH_DATA) {
- return VP8_STATUS_BITSTREAM_ERROR; // Not-enough-data treated as error.
- }
- return status;
+ return GetFeatures(data, data_size, features);
}
VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size,
@@ -722,9 +781,9 @@ int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
h = options->crop_height;
x = options->crop_left;
y = options->crop_top;
- if (!WebPIsRGBMode(src_colorspace)) { // only snap for YUV420 or YUV422
+ if (!WebPIsRGBMode(src_colorspace)) { // only snap for YUV420
x &= ~1;
- y &= ~1; // TODO(later): only for YUV420, not YUV422.
+ y &= ~1;
}
if (x < 0 || y < 0 || w <= 0 || h <= 0 || x + w > W || y + h > H) {
return 0; // out of frame boundary error
@@ -740,11 +799,13 @@ int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
// Scaling
io->use_scaling = (options != NULL) && (options->use_scaling > 0);
if (io->use_scaling) {
- if (options->scaled_width <= 0 || options->scaled_height <= 0) {
+ int scaled_width = options->scaled_width;
+ int scaled_height = options->scaled_height;
+ if (!WebPRescalerGetScaledDimensions(w, h, &scaled_width, &scaled_height)) {
return 0;
}
- io->scaled_width = options->scaled_width;
- io->scaled_height = options->scaled_height;
+ io->scaled_width = scaled_width;
+ io->scaled_height = scaled_height;
}
// Filter
@@ -766,6 +827,3 @@ int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/dec/webpi.h b/drivers/webp/dec/webpi.h
index 44e5744411..c75a2e4a5b 100644
--- a/drivers/webp/dec/webpi.h
+++ b/drivers/webp/dec/webpi.h
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Internal header: WebP decoding parameters and custom IO on buffer
@@ -12,7 +14,7 @@
#ifndef WEBP_DEC_WEBPI_H_
#define WEBP_DEC_WEBPI_H_
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
@@ -24,7 +26,10 @@ extern "C" {
typedef struct WebPDecParams WebPDecParams;
typedef int (*OutputFunc)(const VP8Io* const io, WebPDecParams* const p);
-typedef int (*OutputRowFunc)(WebPDecParams* const p, int y_pos);
+typedef int (*OutputAlphaFunc)(const VP8Io* const io, WebPDecParams* const p,
+ int expected_num_out_lines);
+typedef int (*OutputRowFunc)(WebPDecParams* const p, int y_pos,
+ int max_out_lines);
struct WebPDecParams {
WebPDecBuffer* output; // output buffer.
@@ -38,7 +43,7 @@ struct WebPDecParams {
void* memory; // overall scratch memory for the output work.
OutputFunc emit; // output RGB or YUV samples
- OutputFunc emit_alpha; // output alpha channel
+ OutputAlphaFunc emit_alpha; // output alpha channel
OutputRowFunc emit_alpha_row; // output one line of rescaled alpha values
};
@@ -52,6 +57,7 @@ void WebPResetDecParams(WebPDecParams* const params);
typedef struct {
const uint8_t* data; // input buffer
size_t data_size; // input buffer size
+ int have_all_data; // true if all data is known to be available
size_t offset; // offset to main data chunk (VP8 or VP8L)
const uint8_t* alpha_data; // points to alpha chunk (if present)
size_t alpha_data_size; // alpha chunk size
@@ -61,10 +67,10 @@ typedef struct {
} WebPHeaderStructure;
// Skips over all valid chunks prior to the first VP8/VP8L frame header.
-// Returns VP8_STATUS_OK on success,
-// VP8_STATUS_BITSTREAM_ERROR if an invalid header/chunk is found, and
-// VP8_STATUS_NOT_ENOUGH_DATA if case of insufficient data.
-// In 'headers', compressed_size, offset, alpha_data, alpha_size and lossless
+// Returns: VP8_STATUS_OK, VP8_STATUS_BITSTREAM_ERROR (invalid header/chunk),
+// VP8_STATUS_NOT_ENOUGH_DATA (partial input) or VP8_STATUS_UNSUPPORTED_FEATURE
+// in the case of non-decodable features (animation for instance).
+// In 'headers', compressed_size, offset, alpha_data, alpha_size, and lossless
// fields are updated appropriately upon success.
VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers);
@@ -91,10 +97,15 @@ int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
// dimension / etc.). If *options is not NULL, also verify that the options'
// parameters are valid and apply them to the width/height dimensions of the
// output buffer. This takes cropping / scaling / rotation into account.
+// Also incorporates the options->flip flag to flip the buffer parameters if
+// needed.
VP8StatusCode WebPAllocateDecBuffer(int width, int height,
const WebPDecoderOptions* const options,
WebPDecBuffer* const buffer);
+// Flip buffer vertically by negating the various strides.
+VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer);
+
// Copy 'src' into 'dst' buffer, making sure 'dst' is not marked as owner of the
// memory (still held by 'src').
void WebPCopyDecBuffer(const WebPDecBuffer* const src,
@@ -103,11 +114,9 @@ void WebPCopyDecBuffer(const WebPDecBuffer* const src,
// Copy and transfer ownership from src to dst (beware of parameter order!)
void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst);
-
-
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/decode.h b/drivers/webp/decode.h
index 43b6c58f4f..fa4b13411d 100644
--- a/drivers/webp/decode.h
+++ b/drivers/webp/decode.h
@@ -1,8 +1,10 @@
// Copyright 2010 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Main decoding functions for WebP images.
@@ -14,11 +16,23 @@
#include "./types.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
-#define WEBP_DECODER_ABI_VERSION 0x0200 // MAJOR(8b) + MINOR(8b)
+#define WEBP_DECODER_ABI_VERSION 0x0207 // MAJOR(8b) + MINOR(8b)
+
+// Note: forward declaring enumerations is not allowed in (strict) C and C++,
+// the types are left here for reference.
+// typedef enum VP8StatusCode VP8StatusCode;
+// typedef enum WEBP_CSP_MODE WEBP_CSP_MODE;
+typedef struct WebPRGBABuffer WebPRGBABuffer;
+typedef struct WebPYUVABuffer WebPYUVABuffer;
+typedef struct WebPDecBuffer WebPDecBuffer;
+typedef struct WebPIDecoder WebPIDecoder;
+typedef struct WebPBitstreamFeatures WebPBitstreamFeatures;
+typedef struct WebPDecoderOptions WebPDecoderOptions;
+typedef struct WebPDecoderConfig WebPDecoderConfig;
// Return the decoder's version number, packed in hexadecimal using 8bits for
// each of major/minor/revision. E.g: v2.5.7 is 0x020507.
@@ -34,7 +48,7 @@ WEBP_EXTERN(int) WebPGetInfo(const uint8_t* data, size_t data_size,
// Decodes WebP images pointed to by 'data' and returns RGBA samples, along
// with the dimensions in *width and *height. The ordering of samples in
// memory is R, G, B, A, R, G, B, A... in scan order (endian-independent).
-// The returned pointer should be deleted calling free().
+// The returned pointer should be deleted calling WebPFree().
// Returns NULL in case of error.
WEBP_EXTERN(uint8_t*) WebPDecodeRGBA(const uint8_t* data, size_t data_size,
int* width, int* height);
@@ -59,9 +73,9 @@ WEBP_EXTERN(uint8_t*) WebPDecodeBGR(const uint8_t* data, size_t data_size,
// Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer
// returned is the Y samples buffer. Upon return, *u and *v will point to
-// the U and V chroma data. These U and V buffers need NOT be free()'d,
-// unlike the returned Y luma one. The dimension of the U and V planes
-// are both (*width + 1) / 2 and (*height + 1)/ 2.
+// the U and V chroma data. These U and V buffers need NOT be passed to
+// WebPFree(), unlike the returned Y luma one. The dimension of the U and V
+// planes are both (*width + 1) / 2 and (*height + 1)/ 2.
// Upon return, the Y buffer has a stride returned as '*stride', while U and V
// have a common stride returned as '*uv_stride'.
// Return NULL in case of error.
@@ -71,6 +85,9 @@ WEBP_EXTERN(uint8_t*) WebPDecodeYUV(const uint8_t* data, size_t data_size,
uint8_t** u, uint8_t** v,
int* stride, int* uv_stride);
+// Releases memory returned by the WebPDecode*() functions above.
+WEBP_EXTERN(void) WebPFree(void* ptr);
+
// These five functions are variants of the above ones, that decode the image
// directly into a pre-allocated buffer 'output_buffer'. The maximum storage
// available in this buffer is indicated by 'output_buffer_size'. If this
@@ -118,20 +135,28 @@ WEBP_EXTERN(uint8_t*) WebPDecodeYUVInto(
// Note: the naming describes the byte-ordering of packed samples in memory.
// For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,...
// Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels.
-// RGB-565 and RGBA-4444 are also endian-agnostic and byte-oriented.
-typedef enum { MODE_RGB = 0, MODE_RGBA = 1,
- MODE_BGR = 2, MODE_BGRA = 3,
- MODE_ARGB = 4, MODE_RGBA_4444 = 5,
- MODE_RGB_565 = 6,
- // RGB-premultiplied transparent modes (alpha value is preserved)
- MODE_rgbA = 7,
- MODE_bgrA = 8,
- MODE_Argb = 9,
- MODE_rgbA_4444 = 10,
- // YUV modes must come after RGB ones.
- MODE_YUV = 11, MODE_YUVA = 12, // yuv 4:2:0
- MODE_LAST = 13
- } WEBP_CSP_MODE;
+// RGBA-4444 and RGB-565 colorspaces are represented by following byte-order:
+// RGBA-4444: [r3 r2 r1 r0 g3 g2 g1 g0], [b3 b2 b1 b0 a3 a2 a1 a0], ...
+// RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ...
+// In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for
+// these two modes:
+// RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ...
+// RGB-565: [g2 g1 g0 b4 b3 b2 b1 b0], [r4 r3 r2 r1 r0 g5 g4 g3], ...
+
+typedef enum WEBP_CSP_MODE {
+ MODE_RGB = 0, MODE_RGBA = 1,
+ MODE_BGR = 2, MODE_BGRA = 3,
+ MODE_ARGB = 4, MODE_RGBA_4444 = 5,
+ MODE_RGB_565 = 6,
+ // RGB-premultiplied transparent modes (alpha value is preserved)
+ MODE_rgbA = 7,
+ MODE_bgrA = 8,
+ MODE_Argb = 9,
+ MODE_rgbA_4444 = 10,
+ // YUV modes must come after RGB ones.
+ MODE_YUV = 11, MODE_YUVA = 12, // yuv 4:2:0
+ MODE_LAST = 13
+} WEBP_CSP_MODE;
// Some useful macros:
static WEBP_INLINE int WebPIsPremultipliedMode(WEBP_CSP_MODE mode) {
@@ -152,13 +177,13 @@ static WEBP_INLINE int WebPIsRGBMode(WEBP_CSP_MODE mode) {
//------------------------------------------------------------------------------
// WebPDecBuffer: Generic structure for describing the output sample buffer.
-typedef struct { // view as RGBA
+struct WebPRGBABuffer { // view as RGBA
uint8_t* rgba; // pointer to RGBA samples
int stride; // stride in bytes from one scanline to the next.
size_t size; // total size of the *rgba buffer.
-} WebPRGBABuffer;
+};
-typedef struct { // view as YUVA
+struct WebPYUVABuffer { // view as YUVA
uint8_t* y, *u, *v, *a; // pointer to luma, chroma U/V, alpha samples
int y_stride; // luma stride
int u_stride, v_stride; // chroma strides
@@ -166,10 +191,10 @@ typedef struct { // view as YUVA
size_t y_size; // luma plane size
size_t u_size, v_size; // chroma planes size
size_t a_size; // alpha-plane size
-} WebPYUVABuffer;
+};
// Output buffer
-typedef struct {
+struct WebPDecBuffer {
WEBP_CSP_MODE colorspace; // Colorspace.
int width, height; // Dimensions.
int is_external_memory; // If true, 'internal_memory' pointer is not used.
@@ -182,7 +207,7 @@ typedef struct {
uint8_t* private_memory; // Internally allocated memory (only when
// is_external_memory is false). Should not be used
// externally, but accessed via the buffer union.
-} WebPDecBuffer;
+};
// Internal, version-checked, entry point
WEBP_EXTERN(int) WebPInitDecBufferInternal(WebPDecBuffer*, int);
@@ -200,7 +225,7 @@ WEBP_EXTERN(void) WebPFreeDecBuffer(WebPDecBuffer* buffer);
//------------------------------------------------------------------------------
// Enumeration of the status codes
-typedef enum {
+typedef enum VP8StatusCode {
VP8_STATUS_OK = 0,
VP8_STATUS_OUT_OF_MEMORY,
VP8_STATUS_INVALID_PARAM,
@@ -237,13 +262,17 @@ typedef enum {
// }
// WebPIDelete(idec);
-typedef struct WebPIDecoder WebPIDecoder;
-
// Creates a new incremental decoder with the supplied buffer parameter.
// This output_buffer can be passed NULL, in which case a default output buffer
// is used (with MODE_RGB). Otherwise, an internal reference to 'output_buffer'
// is kept, which means that the lifespan of 'output_buffer' must be larger than
// that of the returned WebPIDecoder object.
+// The supplied 'output_buffer' content MUST NOT be changed between calls to
+// WebPIAppend() or WebPIUpdate() unless 'output_buffer.is_external_memory' is
+// set to 1. In such a case, it is allowed to modify the pointers, size and
+// stride of output_buffer.u.RGBA or output_buffer.u.YUVA, provided they remain
+// within valid bounds.
+// All other fields of WebPDecBuffer MUST remain constant between calls.
// Returns NULL if the allocation failed.
WEBP_EXTERN(WebPIDecoder*) WebPINewDecoder(WebPDecBuffer* output_buffer);
@@ -251,19 +280,27 @@ WEBP_EXTERN(WebPIDecoder*) WebPINewDecoder(WebPDecBuffer* output_buffer);
// will output the RGB/A samples specified by 'csp' into a preallocated
// buffer 'output_buffer'. The size of this buffer is at least
// 'output_buffer_size' and the stride (distance in bytes between two scanlines)
-// is specified by 'output_stride'. Returns NULL if the allocation failed.
+// is specified by 'output_stride'.
+// Additionally, output_buffer can be passed NULL in which case the output
+// buffer will be allocated automatically when the decoding starts. The
+// colorspace 'csp' is taken into account for allocating this buffer. All other
+// parameters are ignored.
+// Returns NULL if the allocation failed, or if some parameters are invalid.
WEBP_EXTERN(WebPIDecoder*) WebPINewRGB(
WEBP_CSP_MODE csp,
uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
// This function allocates and initializes an incremental-decoder object, which
-// will output the raw luma/chroma samples into a preallocated planes. The luma
-// plane is specified by its pointer 'luma', its size 'luma_size' and its stride
-// 'luma_stride'. Similarly, the chroma-u plane is specified by the 'u',
-// 'u_size' and 'u_stride' parameters, and the chroma-v plane by 'v'
-// and 'v_size'. And same for the alpha-plane. The 'a' pointer can be pass
-// NULL in case one is not interested in the transparency plane.
-// Returns NULL if the allocation failed.
+// will output the raw luma/chroma samples into a preallocated planes if
+// supplied. The luma plane is specified by its pointer 'luma', its size
+// 'luma_size' and its stride 'luma_stride'. Similarly, the chroma-u plane
+// is specified by the 'u', 'u_size' and 'u_stride' parameters, and the chroma-v
+// plane by 'v' and 'v_size'. And same for the alpha-plane. The 'a' pointer
+// can be pass NULL in case one is not interested in the transparency plane.
+// Conversely, 'luma' can be passed NULL if no preallocated planes are supplied.
+// In this case, the output buffer will be automatically allocated (using
+// MODE_YUVA) when decoding starts. All parameters are then ignored.
+// Returns NULL if the allocation failed or if a parameter is invalid.
WEBP_EXTERN(WebPIDecoder*) WebPINewYUVA(
uint8_t* luma, size_t luma_size, int luma_stride,
uint8_t* u, size_t u_size, int u_stride,
@@ -344,7 +381,7 @@ WEBP_EXTERN(const WebPDecBuffer*) WebPIDecodedArea(
CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);
// C) Adjust 'config', if needed
- config.no_fancy = 1;
+ config.no_fancy_upsampling = 1;
config.output.colorspace = MODE_BGRA;
// etc.
@@ -365,19 +402,15 @@ WEBP_EXTERN(const WebPDecBuffer*) WebPIDecodedArea(
*/
// Features gathered from the bitstream
-typedef struct {
- int width; // Width in pixels, as read from the bitstream.
- int height; // Height in pixels, as read from the bitstream.
- int has_alpha; // True if the bitstream contains an alpha channel.
-
- // Unused for now:
- int bitstream_version; // should be 0 for now. TODO(later)
- int no_incremental_decoding; // if true, using incremental decoding is not
- // recommended.
- int rotate; // TODO(later)
- int uv_sampling; // should be 0 for now. TODO(later)
- uint32_t pad[3]; // padding for later use
-} WebPBitstreamFeatures;
+struct WebPBitstreamFeatures {
+ int width; // Width in pixels, as read from the bitstream.
+ int height; // Height in pixels, as read from the bitstream.
+ int has_alpha; // True if the bitstream contains an alpha channel.
+ int has_animation; // True if the bitstream is an animation.
+ int format; // 0 = undefined (/mixed), 1 = lossy, 2 = lossless
+
+ uint32_t pad[5]; // padding for later use
+};
// Internal, version-checked, entry point
WEBP_EXTERN(VP8StatusCode) WebPGetFeaturesInternal(
@@ -385,8 +418,9 @@ WEBP_EXTERN(VP8StatusCode) WebPGetFeaturesInternal(
// Retrieve features from the bitstream. The *features structure is filled
// with information gathered from the bitstream.
-// Returns false in case of error or version mismatch.
-// In case of error, features->bitstream_status will reflect the error code.
+// Returns VP8_STATUS_OK when the features are successfully retrieved. Returns
+// VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the
+// features from headers. Returns error in other cases.
static WEBP_INLINE VP8StatusCode WebPGetFeatures(
const uint8_t* data, size_t data_size,
WebPBitstreamFeatures* features) {
@@ -395,7 +429,7 @@ static WEBP_INLINE VP8StatusCode WebPGetFeatures(
}
// Decoding options
-typedef struct {
+struct WebPDecoderOptions {
int bypass_filtering; // if true, skip the in-loop filtering
int no_fancy_upsampling; // if true, use faster pointwise upsampler
int use_cropping; // if true, cropping is applied _first_
@@ -405,19 +439,19 @@ typedef struct {
int use_scaling; // if true, scaling is applied _afterward_
int scaled_width, scaled_height; // final resolution
int use_threads; // if true, use multi-threaded decoding
+ int dithering_strength; // dithering strength (0=Off, 100=full)
+ int flip; // flip output vertically
+ int alpha_dithering_strength; // alpha dithering strength in [0..100]
- // Unused for now:
- int force_rotation; // forced rotation (to be applied _last_)
- int no_enhancement; // if true, discard enhancement layer
- uint32_t pad[6]; // padding for later use
-} WebPDecoderOptions;
+ uint32_t pad[5]; // padding for later use
+};
// Main object storing the configuration for advanced decoding.
-typedef struct {
+struct WebPDecoderConfig {
WebPBitstreamFeatures input; // Immutable bitstream features (optional)
WebPDecBuffer output; // Output buffer (can point to external mem)
WebPDecoderOptions options; // Decoding options
-} WebPDecoderConfig;
+};
// Internal, version-checked, entry point
WEBP_EXTERN(int) WebPInitDecoderConfigInternal(WebPDecoderConfig*, int);
@@ -447,7 +481,7 @@ WEBP_EXTERN(WebPIDecoder*) WebPIDecode(const uint8_t* data, size_t data_size,
WEBP_EXTERN(VP8StatusCode) WebPDecode(const uint8_t* data, size_t data_size,
WebPDecoderConfig* config);
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/demux.h b/drivers/webp/demux.h
new file mode 100644
index 0000000000..6fbe775851
--- /dev/null
+++ b/drivers/webp/demux.h
@@ -0,0 +1,364 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Demux API.
+// Enables extraction of image and extended format data from WebP files.
+
+// Code Example: Demuxing WebP data to extract all the frames, ICC profile
+// and EXIF/XMP metadata.
+/*
+ WebPDemuxer* demux = WebPDemux(&webp_data);
+
+ uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
+ uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
+ // ... (Get information about the features present in the WebP file).
+ uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS);
+
+ // ... (Iterate over all frames).
+ WebPIterator iter;
+ if (WebPDemuxGetFrame(demux, 1, &iter)) {
+ do {
+ // ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(),
+ // ... and get other frame properties like width, height, offsets etc.
+ // ... see 'struct WebPIterator' below for more info).
+ } while (WebPDemuxNextFrame(&iter));
+ WebPDemuxReleaseIterator(&iter);
+ }
+
+ // ... (Extract metadata).
+ WebPChunkIterator chunk_iter;
+ if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter);
+ // ... (Consume the ICC profile in 'chunk_iter.chunk').
+ WebPDemuxReleaseChunkIterator(&chunk_iter);
+ if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter);
+ // ... (Consume the EXIF metadata in 'chunk_iter.chunk').
+ WebPDemuxReleaseChunkIterator(&chunk_iter);
+ if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter);
+ // ... (Consume the XMP metadata in 'chunk_iter.chunk').
+ WebPDemuxReleaseChunkIterator(&chunk_iter);
+ WebPDemuxDelete(demux);
+*/
+
+#ifndef WEBP_WEBP_DEMUX_H_
+#define WEBP_WEBP_DEMUX_H_
+
+#include "./decode.h" // for WEBP_CSP_MODE
+#include "./mux_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define WEBP_DEMUX_ABI_VERSION 0x0105 // MAJOR(8b) + MINOR(8b)
+
+// Note: forward declaring enumerations is not allowed in (strict) C and C++,
+// the types are left here for reference.
+// typedef enum WebPDemuxState WebPDemuxState;
+// typedef enum WebPFormatFeature WebPFormatFeature;
+typedef struct WebPDemuxer WebPDemuxer;
+typedef struct WebPIterator WebPIterator;
+typedef struct WebPChunkIterator WebPChunkIterator;
+typedef struct WebPAnimInfo WebPAnimInfo;
+typedef struct WebPAnimDecoderOptions WebPAnimDecoderOptions;
+
+//------------------------------------------------------------------------------
+
+// Returns the version number of the demux library, packed in hexadecimal using
+// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507.
+WEBP_EXTERN(int) WebPGetDemuxVersion(void);
+
+//------------------------------------------------------------------------------
+// Life of a Demux object
+
+typedef enum WebPDemuxState {
+ WEBP_DEMUX_PARSE_ERROR = -1, // An error occurred while parsing.
+ WEBP_DEMUX_PARSING_HEADER = 0, // Not enough data to parse full header.
+ WEBP_DEMUX_PARSED_HEADER = 1, // Header parsing complete,
+ // data may be available.
+ WEBP_DEMUX_DONE = 2 // Entire file has been parsed.
+} WebPDemuxState;
+
+// Internal, version-checked, entry point
+WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal(
+ const WebPData*, int, WebPDemuxState*, int);
+
+// Parses the full WebP file given by 'data'.
+// Returns a WebPDemuxer object on successful parse, NULL otherwise.
+static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) {
+ return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION);
+}
+
+// Parses the possibly incomplete WebP file given by 'data'.
+// If 'state' is non-NULL it will be set to indicate the status of the demuxer.
+// Returns NULL in case of error or if there isn't enough data to start parsing;
+// and a WebPDemuxer object on successful parse.
+// Note that WebPDemuxer keeps internal pointers to 'data' memory segment.
+// If this data is volatile, the demuxer object should be deleted (by calling
+// WebPDemuxDelete()) and WebPDemuxPartial() called again on the new data.
+// This is usually an inexpensive operation.
+static WEBP_INLINE WebPDemuxer* WebPDemuxPartial(
+ const WebPData* data, WebPDemuxState* state) {
+ return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION);
+}
+
+// Frees memory associated with 'dmux'.
+WEBP_EXTERN(void) WebPDemuxDelete(WebPDemuxer* dmux);
+
+//------------------------------------------------------------------------------
+// Data/information extraction.
+
+typedef enum WebPFormatFeature {
+ WEBP_FF_FORMAT_FLAGS, // Extended format flags present in the 'VP8X' chunk.
+ WEBP_FF_CANVAS_WIDTH,
+ WEBP_FF_CANVAS_HEIGHT,
+ WEBP_FF_LOOP_COUNT,
+ WEBP_FF_BACKGROUND_COLOR,
+ WEBP_FF_FRAME_COUNT // Number of frames present in the demux object.
+ // In case of a partial demux, this is the number of
+ // frames seen so far, with the last frame possibly
+ // being partial.
+} WebPFormatFeature;
+
+// Get the 'feature' value from the 'dmux'.
+// NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial()
+// returned a state > WEBP_DEMUX_PARSING_HEADER.
+WEBP_EXTERN(uint32_t) WebPDemuxGetI(
+ const WebPDemuxer* dmux, WebPFormatFeature feature);
+
+//------------------------------------------------------------------------------
+// Frame iteration.
+
+struct WebPIterator {
+ int frame_num;
+ int num_frames; // equivalent to WEBP_FF_FRAME_COUNT.
+ int fragment_num;
+ int num_fragments;
+ int x_offset, y_offset; // offset relative to the canvas.
+ int width, height; // dimensions of this frame or fragment.
+ int duration; // display duration in milliseconds.
+ WebPMuxAnimDispose dispose_method; // dispose method for the frame.
+ int complete; // true if 'fragment' contains a full frame. partial images
+ // may still be decoded with the WebP incremental decoder.
+ WebPData fragment; // The frame or fragment given by 'frame_num' and
+ // 'fragment_num'.
+ int has_alpha; // True if the frame or fragment contains transparency.
+ WebPMuxAnimBlend blend_method; // Blend operation for the frame.
+
+ uint32_t pad[2]; // padding for later use.
+ void* private_; // for internal use only.
+};
+
+// Retrieves frame 'frame_number' from 'dmux'.
+// 'iter->fragment' points to the first fragment on return from this function.
+// Individual fragments may be extracted using WebPDemuxSelectFragment().
+// Setting 'frame_number' equal to 0 will return the last frame of the image.
+// Returns false if 'dmux' is NULL or frame 'frame_number' is not present.
+// Call WebPDemuxReleaseIterator() when use of the iterator is complete.
+// NOTE: 'dmux' must persist for the lifetime of 'iter'.
+WEBP_EXTERN(int) WebPDemuxGetFrame(
+ const WebPDemuxer* dmux, int frame_number, WebPIterator* iter);
+
+// Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or
+// previous ('iter->frame_num' - 1) frame. These functions do not loop.
+// Returns true on success, false otherwise.
+WEBP_EXTERN(int) WebPDemuxNextFrame(WebPIterator* iter);
+WEBP_EXTERN(int) WebPDemuxPrevFrame(WebPIterator* iter);
+
+// Sets 'iter->fragment' to reflect fragment number 'fragment_num'.
+// Returns true if fragment 'fragment_num' is present, false otherwise.
+WEBP_EXTERN(int) WebPDemuxSelectFragment(WebPIterator* iter, int fragment_num);
+
+// Releases any memory associated with 'iter'.
+// Must be called before any subsequent calls to WebPDemuxGetChunk() on the same
+// iter. Also, must be called before destroying the associated WebPDemuxer with
+// WebPDemuxDelete().
+WEBP_EXTERN(void) WebPDemuxReleaseIterator(WebPIterator* iter);
+
+//------------------------------------------------------------------------------
+// Chunk iteration.
+
+struct WebPChunkIterator {
+ // The current and total number of chunks with the fourcc given to
+ // WebPDemuxGetChunk().
+ int chunk_num;
+ int num_chunks;
+ WebPData chunk; // The payload of the chunk.
+
+ uint32_t pad[6]; // padding for later use
+ void* private_;
+};
+
+// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from
+// 'dmux'.
+// 'fourcc' is a character array containing the fourcc of the chunk to return,
+// e.g., "ICCP", "XMP ", "EXIF", etc.
+// Setting 'chunk_number' equal to 0 will return the last chunk in a set.
+// Returns true if the chunk is found, false otherwise. Image related chunk
+// payloads are accessed through WebPDemuxGetFrame() and related functions.
+// Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete.
+// NOTE: 'dmux' must persist for the lifetime of the iterator.
+WEBP_EXTERN(int) WebPDemuxGetChunk(const WebPDemuxer* dmux,
+ const char fourcc[4], int chunk_number,
+ WebPChunkIterator* iter);
+
+// Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous
+// ('iter->chunk_num' - 1) chunk. These functions do not loop.
+// Returns true on success, false otherwise.
+WEBP_EXTERN(int) WebPDemuxNextChunk(WebPChunkIterator* iter);
+WEBP_EXTERN(int) WebPDemuxPrevChunk(WebPChunkIterator* iter);
+
+// Releases any memory associated with 'iter'.
+// Must be called before destroying the associated WebPDemuxer with
+// WebPDemuxDelete().
+WEBP_EXTERN(void) WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter);
+
+//------------------------------------------------------------------------------
+// WebPAnimDecoder API
+//
+// This API allows decoding (possibly) animated WebP images.
+//
+// Code Example:
+/*
+ WebPAnimDecoderOptions dec_options;
+ WebPAnimDecoderOptionsInit(&dec_options);
+ // Tune 'dec_options' as needed.
+ WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options);
+ WebPAnimInfo anim_info;
+ WebPAnimDecoderGetInfo(dec, &anim_info);
+ for (uint32_t i = 0; i < anim_info.loop_count; ++i) {
+ while (WebPAnimDecoderHasMoreFrames(dec)) {
+ uint8_t* buf;
+ int timestamp;
+ WebPAnimDecoderGetNext(dec, &buf, &timestamp);
+ // ... (Render 'buf' based on 'timestamp').
+ // ... (Do NOT free 'buf', as it is owned by 'dec').
+ }
+ WebPAnimDecoderReset(dec);
+ }
+ const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec);
+ // ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data).
+ WebPAnimDecoderDelete(dec);
+*/
+
+typedef struct WebPAnimDecoder WebPAnimDecoder; // Main opaque object.
+
+// Global options.
+struct WebPAnimDecoderOptions {
+ // Output colorspace. Only the following modes are supported:
+ // MODE_RGBA, MODE_BGRA, MODE_rgbA and MODE_bgrA.
+ WEBP_CSP_MODE color_mode;
+ int use_threads; // If true, use multi-threaded decoding.
+ uint32_t padding[7]; // Padding for later use.
+};
+
+// Internal, version-checked, entry point.
+WEBP_EXTERN(int) WebPAnimDecoderOptionsInitInternal(
+ WebPAnimDecoderOptions*, int);
+
+// Should always be called, to initialize a fresh WebPAnimDecoderOptions
+// structure before modification. Returns false in case of version mismatch.
+// WebPAnimDecoderOptionsInit() must have succeeded before using the
+// 'dec_options' object.
+static WEBP_INLINE int WebPAnimDecoderOptionsInit(
+ WebPAnimDecoderOptions* dec_options) {
+ return WebPAnimDecoderOptionsInitInternal(dec_options,
+ WEBP_DEMUX_ABI_VERSION);
+}
+
+// Internal, version-checked, entry point.
+WEBP_EXTERN(WebPAnimDecoder*) WebPAnimDecoderNewInternal(
+ const WebPData*, const WebPAnimDecoderOptions*, int);
+
+// Creates and initializes a WebPAnimDecoder object.
+// Parameters:
+// webp_data - (in) WebP bitstream. This should remain unchanged during the
+// lifetime of the output WebPAnimDecoder object.
+// dec_options - (in) decoding options. Can be passed NULL to choose
+// reasonable defaults (in particular, color mode MODE_RGBA
+// will be picked).
+// Returns:
+// A pointer to the newly created WebPAnimDecoder object, or NULL in case of
+// parsing error, invalid option or memory error.
+static WEBP_INLINE WebPAnimDecoder* WebPAnimDecoderNew(
+ const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options) {
+ return WebPAnimDecoderNewInternal(webp_data, dec_options,
+ WEBP_DEMUX_ABI_VERSION);
+}
+
+// Global information about the animation..
+struct WebPAnimInfo {
+ uint32_t canvas_width;
+ uint32_t canvas_height;
+ uint32_t loop_count;
+ uint32_t bgcolor;
+ uint32_t frame_count;
+ uint32_t pad[4]; // padding for later use
+};
+
+// Get global information about the animation.
+// Parameters:
+// dec - (in) decoder instance to get information from.
+// info - (out) global information fetched from the animation.
+// Returns:
+// True on success.
+WEBP_EXTERN(int) WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec,
+ WebPAnimInfo* info);
+
+// Fetch the next frame from 'dec' based on options supplied to
+// WebPAnimDecoderNew(). This will be a fully reconstructed canvas of size
+// 'canvas_width * 4 * canvas_height', and not just the frame sub-rectangle. The
+// returned buffer 'buf' is valid only until the next call to
+// WebPAnimDecoderGetNext(), WebPAnimDecoderReset() or WebPAnimDecoderDelete().
+// Parameters:
+// dec - (in/out) decoder instance from which the next frame is to be fetched.
+// buf - (out) decoded frame.
+// timestamp - (out) timestamp of the frame in milliseconds.
+// Returns:
+// False if any of the arguments are NULL, or if there is a parsing or
+// decoding error, or if there are no more frames. Otherwise, returns true.
+WEBP_EXTERN(int) WebPAnimDecoderGetNext(WebPAnimDecoder* dec,
+ uint8_t** buf, int* timestamp);
+
+// Check if there are more frames left to decode.
+// Parameters:
+// dec - (in) decoder instance to be checked.
+// Returns:
+// True if 'dec' is not NULL and some frames are yet to be decoded.
+// Otherwise, returns false.
+WEBP_EXTERN(int) WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec);
+
+// Resets the WebPAnimDecoder object, so that next call to
+// WebPAnimDecoderGetNext() will restart decoding from 1st frame. This would be
+// helpful when all frames need to be decoded multiple times (e.g.
+// info.loop_count times) without destroying and recreating the 'dec' object.
+// Parameters:
+// dec - (in/out) decoder instance to be reset
+WEBP_EXTERN(void) WebPAnimDecoderReset(WebPAnimDecoder* dec);
+
+// Grab the internal demuxer object.
+// Getting the demuxer object can be useful if one wants to use operations only
+// available through demuxer; e.g. to get XMP/EXIF/ICC metadata. The returned
+// demuxer object is owned by 'dec' and is valid only until the next call to
+// WebPAnimDecoderDelete().
+//
+// Parameters:
+// dec - (in) decoder instance from which the demuxer object is to be fetched.
+WEBP_EXTERN(const WebPDemuxer*) WebPAnimDecoderGetDemuxer(
+ const WebPAnimDecoder* dec);
+
+// Deletes the WebPAnimDecoder object.
+// Parameters:
+// dec - (in/out) decoder instance to be deleted
+WEBP_EXTERN(void) WebPAnimDecoderDelete(WebPAnimDecoder* dec);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_WEBP_DEMUX_H_ */
diff --git a/drivers/webp/demux/anim_decode.c b/drivers/webp/demux/anim_decode.c
new file mode 100644
index 0000000000..c81cedfba0
--- /dev/null
+++ b/drivers/webp/demux/anim_decode.c
@@ -0,0 +1,442 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// AnimDecoder implementation.
+//
+
+#ifdef HAVE_CONFIG_H
+#include "webp/config.h"
+#endif
+
+#include <assert.h>
+#include <string.h>
+
+#include "../utils/utils.h"
+#include "webp/decode.h"
+#include "webp/demux.h"
+
+#define NUM_CHANNELS 4
+
+typedef void (*BlendRowFunc)(uint32_t* const, const uint32_t* const, int);
+static void BlendPixelRowNonPremult(uint32_t* const src,
+ const uint32_t* const dst, int num_pixels);
+static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst,
+ int num_pixels);
+
+struct WebPAnimDecoder {
+ WebPDemuxer* demux_; // Demuxer created from given WebP bitstream.
+ WebPDecoderConfig config_; // Decoder config.
+ // Note: we use a pointer to a function blending multiple pixels at a time to
+ // allow possible inlining of per-pixel blending function.
+ BlendRowFunc blend_func_; // Pointer to the chose blend row function.
+ WebPAnimInfo info_; // Global info about the animation.
+ uint8_t* curr_frame_; // Current canvas (not disposed).
+ uint8_t* prev_frame_disposed_; // Previous canvas (properly disposed).
+ int prev_frame_timestamp_; // Previous frame timestamp (milliseconds).
+ WebPIterator prev_iter_; // Iterator object for previous frame.
+ int prev_frame_was_keyframe_; // True if previous frame was a keyframe.
+ int next_frame_; // Index of the next frame to be decoded
+ // (starting from 1).
+};
+
+static void DefaultDecoderOptions(WebPAnimDecoderOptions* const dec_options) {
+ dec_options->color_mode = MODE_RGBA;
+ dec_options->use_threads = 0;
+}
+
+int WebPAnimDecoderOptionsInitInternal(WebPAnimDecoderOptions* dec_options,
+ int abi_version) {
+ if (dec_options == NULL ||
+ WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) {
+ return 0;
+ }
+ DefaultDecoderOptions(dec_options);
+ return 1;
+}
+
+static int ApplyDecoderOptions(const WebPAnimDecoderOptions* const dec_options,
+ WebPAnimDecoder* const dec) {
+ WEBP_CSP_MODE mode;
+ WebPDecoderConfig* config = &dec->config_;
+ assert(dec_options != NULL);
+
+ mode = dec_options->color_mode;
+ if (mode != MODE_RGBA && mode != MODE_BGRA &&
+ mode != MODE_rgbA && mode != MODE_bgrA) {
+ return 0;
+ }
+ dec->blend_func_ = (mode == MODE_RGBA || mode == MODE_BGRA)
+ ? &BlendPixelRowNonPremult
+ : &BlendPixelRowPremult;
+ WebPInitDecoderConfig(config);
+ config->output.colorspace = mode;
+ config->output.is_external_memory = 1;
+ config->options.use_threads = dec_options->use_threads;
+ // Note: config->output.u.RGBA is set at the time of decoding each frame.
+ return 1;
+}
+
+WebPAnimDecoder* WebPAnimDecoderNewInternal(
+ const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options,
+ int abi_version) {
+ WebPAnimDecoderOptions options;
+ WebPAnimDecoder* dec = NULL;
+ if (webp_data == NULL ||
+ WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) {
+ return NULL;
+ }
+
+ // Note: calloc() so that the pointer members are initialized to NULL.
+ dec = (WebPAnimDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
+ if (dec == NULL) goto Error;
+
+ if (dec_options != NULL) {
+ options = *dec_options;
+ } else {
+ DefaultDecoderOptions(&options);
+ }
+ if (!ApplyDecoderOptions(&options, dec)) goto Error;
+
+ dec->demux_ = WebPDemux(webp_data);
+ if (dec->demux_ == NULL) goto Error;
+
+ dec->info_.canvas_width = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_WIDTH);
+ dec->info_.canvas_height = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_HEIGHT);
+ dec->info_.loop_count = WebPDemuxGetI(dec->demux_, WEBP_FF_LOOP_COUNT);
+ dec->info_.bgcolor = WebPDemuxGetI(dec->demux_, WEBP_FF_BACKGROUND_COLOR);
+ dec->info_.frame_count = WebPDemuxGetI(dec->demux_, WEBP_FF_FRAME_COUNT);
+
+ {
+ const int canvas_bytes =
+ dec->info_.canvas_width * NUM_CHANNELS * dec->info_.canvas_height;
+ // Note: calloc() because we fill frame with zeroes as well.
+ dec->curr_frame_ = WebPSafeCalloc(1ULL, canvas_bytes);
+ if (dec->curr_frame_ == NULL) goto Error;
+ dec->prev_frame_disposed_ = WebPSafeCalloc(1ULL, canvas_bytes);
+ if (dec->prev_frame_disposed_ == NULL) goto Error;
+ }
+
+ WebPAnimDecoderReset(dec);
+
+ return dec;
+
+ Error:
+ WebPAnimDecoderDelete(dec);
+ return NULL;
+}
+
+int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, WebPAnimInfo* info) {
+ if (dec == NULL || info == NULL) return 0;
+ *info = dec->info_;
+ return 1;
+}
+
+// Returns true if the frame covers the full canvas.
+static int IsFullFrame(int width, int height, int canvas_width,
+ int canvas_height) {
+ return (width == canvas_width && height == canvas_height);
+}
+
+// Clear the canvas to transparent.
+static void ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width,
+ uint32_t canvas_height) {
+ memset(buf, 0, canvas_width * NUM_CHANNELS * canvas_height);
+}
+
+// Clear given frame rectangle to transparent.
+static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset,
+ int y_offset, int width, int height) {
+ int j;
+ assert(width * NUM_CHANNELS <= buf_stride);
+ buf += y_offset * buf_stride + x_offset * NUM_CHANNELS;
+ for (j = 0; j < height; ++j) {
+ memset(buf, 0, width * NUM_CHANNELS);
+ buf += buf_stride;
+ }
+}
+
+// Copy width * height pixels from 'src' to 'dst'.
+static void CopyCanvas(const uint8_t* src, uint8_t* dst,
+ uint32_t width, uint32_t height) {
+ assert(src != NULL && dst != NULL);
+ memcpy(dst, src, width * NUM_CHANNELS * height);
+}
+
+// Returns true if the current frame is a key-frame.
+static int IsKeyFrame(const WebPIterator* const curr,
+ const WebPIterator* const prev,
+ int prev_frame_was_key_frame,
+ int canvas_width, int canvas_height) {
+ if (curr->frame_num == 1) {
+ return 1;
+ } else if ((!curr->has_alpha || curr->blend_method == WEBP_MUX_NO_BLEND) &&
+ IsFullFrame(curr->width, curr->height,
+ canvas_width, canvas_height)) {
+ return 1;
+ } else {
+ return (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) &&
+ (IsFullFrame(prev->width, prev->height, canvas_width,
+ canvas_height) ||
+ prev_frame_was_key_frame);
+ }
+}
+
+
+// Blend a single channel of 'src' over 'dst', given their alpha channel values.
+// 'src' and 'dst' are assumed to be NOT pre-multiplied by alpha.
+static uint8_t BlendChannelNonPremult(uint32_t src, uint8_t src_a,
+ uint32_t dst, uint8_t dst_a,
+ uint32_t scale, int shift) {
+ const uint8_t src_channel = (src >> shift) & 0xff;
+ const uint8_t dst_channel = (dst >> shift) & 0xff;
+ const uint32_t blend_unscaled = src_channel * src_a + dst_channel * dst_a;
+ assert(blend_unscaled < (1ULL << 32) / scale);
+ return (blend_unscaled * scale) >> 24;
+}
+
+// Blend 'src' over 'dst' assuming they are NOT pre-multiplied by alpha.
+static uint32_t BlendPixelNonPremult(uint32_t src, uint32_t dst) {
+ const uint8_t src_a = (src >> 24) & 0xff;
+
+ if (src_a == 0) {
+ return dst;
+ } else {
+ const uint8_t dst_a = (dst >> 24) & 0xff;
+ // This is the approximate integer arithmetic for the actual formula:
+ // dst_factor_a = (dst_a * (255 - src_a)) / 255.
+ const uint8_t dst_factor_a = (dst_a * (256 - src_a)) >> 8;
+ const uint8_t blend_a = src_a + dst_factor_a;
+ const uint32_t scale = (1UL << 24) / blend_a;
+
+ const uint8_t blend_r =
+ BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 0);
+ const uint8_t blend_g =
+ BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 8);
+ const uint8_t blend_b =
+ BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 16);
+ assert(src_a + dst_factor_a < 256);
+
+ return (blend_r << 0) |
+ (blend_g << 8) |
+ (blend_b << 16) |
+ ((uint32_t)blend_a << 24);
+ }
+}
+
+// Blend 'num_pixels' in 'src' over 'dst' assuming they are NOT pre-multiplied
+// by alpha.
+static void BlendPixelRowNonPremult(uint32_t* const src,
+ const uint32_t* const dst, int num_pixels) {
+ int i;
+ for (i = 0; i < num_pixels; ++i) {
+ const uint8_t src_alpha = (src[i] >> 24) & 0xff;
+ if (src_alpha != 0xff) {
+ src[i] = BlendPixelNonPremult(src[i], dst[i]);
+ }
+ }
+}
+
+// Individually multiply each channel in 'pix' by 'scale'.
+static WEBP_INLINE uint32_t ChannelwiseMultiply(uint32_t pix, uint32_t scale) {
+ uint32_t mask = 0x00FF00FF;
+ uint32_t rb = ((pix & mask) * scale) >> 8;
+ uint32_t ag = ((pix >> 8) & mask) * scale;
+ return (rb & mask) | (ag & ~mask);
+}
+
+// Blend 'src' over 'dst' assuming they are pre-multiplied by alpha.
+static uint32_t BlendPixelPremult(uint32_t src, uint32_t dst) {
+ const uint8_t src_a = (src >> 24) & 0xff;
+ return src + ChannelwiseMultiply(dst, 256 - src_a);
+}
+
+// Blend 'num_pixels' in 'src' over 'dst' assuming they are pre-multiplied by
+// alpha.
+static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst,
+ int num_pixels) {
+ int i;
+ for (i = 0; i < num_pixels; ++i) {
+ const uint8_t src_alpha = (src[i] >> 24) & 0xff;
+ if (src_alpha != 0xff) {
+ src[i] = BlendPixelPremult(src[i], dst[i]);
+ }
+ }
+}
+
+// Returns two ranges (<left, width> pairs) at row 'canvas_y', that belong to
+// 'src' but not 'dst'. A point range is empty if the corresponding width is 0.
+static void FindBlendRangeAtRow(const WebPIterator* const src,
+ const WebPIterator* const dst, int canvas_y,
+ int* const left1, int* const width1,
+ int* const left2, int* const width2) {
+ const int src_max_x = src->x_offset + src->width;
+ const int dst_max_x = dst->x_offset + dst->width;
+ const int dst_max_y = dst->y_offset + dst->height;
+ assert(canvas_y >= src->y_offset && canvas_y < (src->y_offset + src->height));
+ *left1 = -1;
+ *width1 = 0;
+ *left2 = -1;
+ *width2 = 0;
+
+ if (canvas_y < dst->y_offset || canvas_y >= dst_max_y ||
+ src->x_offset >= dst_max_x || src_max_x <= dst->x_offset) {
+ *left1 = src->x_offset;
+ *width1 = src->width;
+ return;
+ }
+
+ if (src->x_offset < dst->x_offset) {
+ *left1 = src->x_offset;
+ *width1 = dst->x_offset - src->x_offset;
+ }
+
+ if (src_max_x > dst_max_x) {
+ *left2 = dst_max_x;
+ *width2 = src_max_x - dst_max_x;
+ }
+}
+
+int WebPAnimDecoderGetNext(WebPAnimDecoder* dec,
+ uint8_t** buf_ptr, int* timestamp_ptr) {
+ WebPIterator iter;
+ uint32_t width;
+ uint32_t height;
+ int is_key_frame;
+ int timestamp;
+ BlendRowFunc blend_row;
+
+ if (dec == NULL || buf_ptr == NULL || timestamp_ptr == NULL) return 0;
+ if (!WebPAnimDecoderHasMoreFrames(dec)) return 0;
+
+ width = dec->info_.canvas_width;
+ height = dec->info_.canvas_height;
+ blend_row = dec->blend_func_;
+
+ // Get compressed frame.
+ if (!WebPDemuxGetFrame(dec->demux_, dec->next_frame_, &iter)) {
+ return 0;
+ }
+ timestamp = dec->prev_frame_timestamp_ + iter.duration;
+
+ // Initialize.
+ is_key_frame = IsKeyFrame(&iter, &dec->prev_iter_,
+ dec->prev_frame_was_keyframe_, width, height);
+ if (is_key_frame) {
+ ZeroFillCanvas(dec->curr_frame_, width, height);
+ } else {
+ CopyCanvas(dec->prev_frame_disposed_, dec->curr_frame_, width, height);
+ }
+
+ // Decode.
+ {
+ const uint8_t* in = iter.fragment.bytes;
+ const size_t in_size = iter.fragment.size;
+ const size_t out_offset =
+ (iter.y_offset * width + iter.x_offset) * NUM_CHANNELS;
+ WebPDecoderConfig* const config = &dec->config_;
+ WebPRGBABuffer* const buf = &config->output.u.RGBA;
+ buf->stride = NUM_CHANNELS * width;
+ buf->size = buf->stride * iter.height;
+ buf->rgba = dec->curr_frame_ + out_offset;
+
+ if (WebPDecode(in, in_size, config) != VP8_STATUS_OK) {
+ goto Error;
+ }
+ }
+
+ // During the decoding of current frame, we may have set some pixels to be
+ // transparent (i.e. alpha < 255). However, the value of each of these
+ // pixels should have been determined by blending it against the value of
+ // that pixel in the previous frame if blending method of is WEBP_MUX_BLEND.
+ if (iter.frame_num > 1 && iter.blend_method == WEBP_MUX_BLEND &&
+ !is_key_frame) {
+ if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_NONE) {
+ int y;
+ // Blend transparent pixels with pixels in previous canvas.
+ for (y = 0; y < iter.height; ++y) {
+ const size_t offset =
+ (iter.y_offset + y) * width + iter.x_offset;
+ blend_row((uint32_t*)dec->curr_frame_ + offset,
+ (uint32_t*)dec->prev_frame_disposed_ + offset, iter.width);
+ }
+ } else {
+ int y;
+ assert(dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND);
+ // We need to blend a transparent pixel with its value just after
+ // initialization. That is, blend it with:
+ // * Fully transparent pixel if it belongs to prevRect <-- No-op.
+ // * The pixel in the previous canvas otherwise <-- Need alpha-blending.
+ for (y = 0; y < iter.height; ++y) {
+ const int canvas_y = iter.y_offset + y;
+ int left1, width1, left2, width2;
+ FindBlendRangeAtRow(&iter, &dec->prev_iter_, canvas_y, &left1, &width1,
+ &left2, &width2);
+ if (width1 > 0) {
+ const size_t offset1 = canvas_y * width + left1;
+ blend_row((uint32_t*)dec->curr_frame_ + offset1,
+ (uint32_t*)dec->prev_frame_disposed_ + offset1, width1);
+ }
+ if (width2 > 0) {
+ const size_t offset2 = canvas_y * width + left2;
+ blend_row((uint32_t*)dec->curr_frame_ + offset2,
+ (uint32_t*)dec->prev_frame_disposed_ + offset2, width2);
+ }
+ }
+ }
+ }
+
+ // Update info of the previous frame and dispose it for the next iteration.
+ dec->prev_frame_timestamp_ = timestamp;
+ dec->prev_iter_ = iter;
+ dec->prev_frame_was_keyframe_ = is_key_frame;
+ CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height);
+ if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
+ ZeroFillFrameRect(dec->prev_frame_disposed_, width * NUM_CHANNELS,
+ dec->prev_iter_.x_offset, dec->prev_iter_.y_offset,
+ dec->prev_iter_.width, dec->prev_iter_.height);
+ }
+ ++dec->next_frame_;
+
+ // All OK, fill in the values.
+ *buf_ptr = dec->curr_frame_;
+ *timestamp_ptr = timestamp;
+ return 1;
+
+ Error:
+ WebPDemuxReleaseIterator(&iter);
+ return 0;
+}
+
+int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec) {
+ if (dec == NULL) return 0;
+ return (dec->next_frame_ <= (int)dec->info_.frame_count);
+}
+
+void WebPAnimDecoderReset(WebPAnimDecoder* dec) {
+ if (dec != NULL) {
+ dec->prev_frame_timestamp_ = 0;
+ memset(&dec->prev_iter_, 0, sizeof(dec->prev_iter_));
+ dec->prev_frame_was_keyframe_ = 0;
+ dec->next_frame_ = 1;
+ }
+}
+
+const WebPDemuxer* WebPAnimDecoderGetDemuxer(const WebPAnimDecoder* dec) {
+ if (dec == NULL) return NULL;
+ return dec->demux_;
+}
+
+void WebPAnimDecoderDelete(WebPAnimDecoder* dec) {
+ if (dec != NULL) {
+ WebPDemuxDelete(dec->demux_);
+ WebPSafeFree(dec->curr_frame_);
+ WebPSafeFree(dec->prev_frame_disposed_);
+ WebPSafeFree(dec);
+ }
+}
diff --git a/drivers/webp/demux/demux.c b/drivers/webp/demux/demux.c
new file mode 100644
index 0000000000..3717e21165
--- /dev/null
+++ b/drivers/webp/demux/demux.c
@@ -0,0 +1,957 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// WebP container demux.
+//
+
+#ifdef HAVE_CONFIG_H
+#include "webp/config.h"
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../utils/utils.h"
+#include "webp/decode.h" // WebPGetFeatures
+#include "webp/demux.h"
+#include "webp/format_constants.h"
+
+#define DMUX_MAJ_VERSION 0
+#define DMUX_MIN_VERSION 2
+#define DMUX_REV_VERSION 2
+
+typedef struct {
+ size_t start_; // start location of the data
+ size_t end_; // end location
+ size_t riff_end_; // riff chunk end location, can be > end_.
+ size_t buf_size_; // size of the buffer
+ const uint8_t* buf_;
+} MemBuffer;
+
+typedef struct {
+ size_t offset_;
+ size_t size_;
+} ChunkData;
+
+typedef struct Frame {
+ int x_offset_, y_offset_;
+ int width_, height_;
+ int has_alpha_;
+ int duration_;
+ WebPMuxAnimDispose dispose_method_;
+ WebPMuxAnimBlend blend_method_;
+ int is_fragment_; // this is a frame fragment (and not a full frame).
+ int frame_num_; // the referent frame number for use in assembling fragments.
+ int complete_; // img_components_ contains a full image.
+ ChunkData img_components_[2]; // 0=VP8{,L} 1=ALPH
+ struct Frame* next_;
+} Frame;
+
+typedef struct Chunk {
+ ChunkData data_;
+ struct Chunk* next_;
+} Chunk;
+
+struct WebPDemuxer {
+ MemBuffer mem_;
+ WebPDemuxState state_;
+ int is_ext_format_;
+ uint32_t feature_flags_;
+ int canvas_width_, canvas_height_;
+ int loop_count_;
+ uint32_t bgcolor_;
+ int num_frames_;
+ Frame* frames_;
+ Frame** frames_tail_;
+ Chunk* chunks_; // non-image chunks
+ Chunk** chunks_tail_;
+};
+
+typedef enum {
+ PARSE_OK,
+ PARSE_NEED_MORE_DATA,
+ PARSE_ERROR
+} ParseStatus;
+
+typedef struct ChunkParser {
+ uint8_t id[4];
+ ParseStatus (*parse)(WebPDemuxer* const dmux);
+ int (*valid)(const WebPDemuxer* const dmux);
+} ChunkParser;
+
+static ParseStatus ParseSingleImage(WebPDemuxer* const dmux);
+static ParseStatus ParseVP8X(WebPDemuxer* const dmux);
+static int IsValidSimpleFormat(const WebPDemuxer* const dmux);
+static int IsValidExtendedFormat(const WebPDemuxer* const dmux);
+
+static const ChunkParser kMasterChunks[] = {
+ { { 'V', 'P', '8', ' ' }, ParseSingleImage, IsValidSimpleFormat },
+ { { 'V', 'P', '8', 'L' }, ParseSingleImage, IsValidSimpleFormat },
+ { { 'V', 'P', '8', 'X' }, ParseVP8X, IsValidExtendedFormat },
+ { { '0', '0', '0', '0' }, NULL, NULL },
+};
+
+//------------------------------------------------------------------------------
+
+int WebPGetDemuxVersion(void) {
+ return (DMUX_MAJ_VERSION << 16) | (DMUX_MIN_VERSION << 8) | DMUX_REV_VERSION;
+}
+
+// -----------------------------------------------------------------------------
+// MemBuffer
+
+static int RemapMemBuffer(MemBuffer* const mem,
+ const uint8_t* data, size_t size) {
+ if (size < mem->buf_size_) return 0; // can't remap to a shorter buffer!
+
+ mem->buf_ = data;
+ mem->end_ = mem->buf_size_ = size;
+ return 1;
+}
+
+static int InitMemBuffer(MemBuffer* const mem,
+ const uint8_t* data, size_t size) {
+ memset(mem, 0, sizeof(*mem));
+ return RemapMemBuffer(mem, data, size);
+}
+
+// Return the remaining data size available in 'mem'.
+static WEBP_INLINE size_t MemDataSize(const MemBuffer* const mem) {
+ return (mem->end_ - mem->start_);
+}
+
+// Return true if 'size' exceeds the end of the RIFF chunk.
+static WEBP_INLINE int SizeIsInvalid(const MemBuffer* const mem, size_t size) {
+ return (size > mem->riff_end_ - mem->start_);
+}
+
+static WEBP_INLINE void Skip(MemBuffer* const mem, size_t size) {
+ mem->start_ += size;
+}
+
+static WEBP_INLINE void Rewind(MemBuffer* const mem, size_t size) {
+ mem->start_ -= size;
+}
+
+static WEBP_INLINE const uint8_t* GetBuffer(MemBuffer* const mem) {
+ return mem->buf_ + mem->start_;
+}
+
+// Read from 'mem' and skip the read bytes.
+static WEBP_INLINE uint8_t ReadByte(MemBuffer* const mem) {
+ const uint8_t byte = mem->buf_[mem->start_];
+ Skip(mem, 1);
+ return byte;
+}
+
+static WEBP_INLINE int ReadLE16s(MemBuffer* const mem) {
+ const uint8_t* const data = mem->buf_ + mem->start_;
+ const int val = GetLE16(data);
+ Skip(mem, 2);
+ return val;
+}
+
+static WEBP_INLINE int ReadLE24s(MemBuffer* const mem) {
+ const uint8_t* const data = mem->buf_ + mem->start_;
+ const int val = GetLE24(data);
+ Skip(mem, 3);
+ return val;
+}
+
+static WEBP_INLINE uint32_t ReadLE32(MemBuffer* const mem) {
+ const uint8_t* const data = mem->buf_ + mem->start_;
+ const uint32_t val = GetLE32(data);
+ Skip(mem, 4);
+ return val;
+}
+
+// -----------------------------------------------------------------------------
+// Secondary chunk parsing
+
+static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) {
+ *dmux->chunks_tail_ = chunk;
+ chunk->next_ = NULL;
+ dmux->chunks_tail_ = &chunk->next_;
+}
+
+// Add a frame to the end of the list, ensuring the last frame is complete.
+// Returns true on success, false otherwise.
+static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) {
+ const Frame* const last_frame = *dmux->frames_tail_;
+ if (last_frame != NULL && !last_frame->complete_) return 0;
+
+ *dmux->frames_tail_ = frame;
+ frame->next_ = NULL;
+ dmux->frames_tail_ = &frame->next_;
+ return 1;
+}
+
+// Store image bearing chunks to 'frame'.
+static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
+ MemBuffer* const mem, Frame* const frame) {
+ int alpha_chunks = 0;
+ int image_chunks = 0;
+ int done = (MemDataSize(mem) < min_size);
+ ParseStatus status = PARSE_OK;
+
+ if (done) return PARSE_NEED_MORE_DATA;
+
+ do {
+ const size_t chunk_start_offset = mem->start_;
+ const uint32_t fourcc = ReadLE32(mem);
+ const uint32_t payload_size = ReadLE32(mem);
+ const uint32_t payload_size_padded = payload_size + (payload_size & 1);
+ const size_t payload_available = (payload_size_padded > MemDataSize(mem))
+ ? MemDataSize(mem) : payload_size_padded;
+ const size_t chunk_size = CHUNK_HEADER_SIZE + payload_available;
+
+ if (payload_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
+ if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR;
+ if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA;
+
+ switch (fourcc) {
+ case MKFOURCC('A', 'L', 'P', 'H'):
+ if (alpha_chunks == 0) {
+ ++alpha_chunks;
+ frame->img_components_[1].offset_ = chunk_start_offset;
+ frame->img_components_[1].size_ = chunk_size;
+ frame->has_alpha_ = 1;
+ frame->frame_num_ = frame_num;
+ Skip(mem, payload_available);
+ } else {
+ goto Done;
+ }
+ break;
+ case MKFOURCC('V', 'P', '8', 'L'):
+ if (alpha_chunks > 0) return PARSE_ERROR; // VP8L has its own alpha
+ // fall through
+ case MKFOURCC('V', 'P', '8', ' '):
+ if (image_chunks == 0) {
+ // Extract the bitstream features, tolerating failures when the data
+ // is incomplete.
+ WebPBitstreamFeatures features;
+ const VP8StatusCode vp8_status =
+ WebPGetFeatures(mem->buf_ + chunk_start_offset, chunk_size,
+ &features);
+ if (status == PARSE_NEED_MORE_DATA &&
+ vp8_status == VP8_STATUS_NOT_ENOUGH_DATA) {
+ return PARSE_NEED_MORE_DATA;
+ } else if (vp8_status != VP8_STATUS_OK) {
+ // We have enough data, and yet WebPGetFeatures() failed.
+ return PARSE_ERROR;
+ }
+ ++image_chunks;
+ frame->img_components_[0].offset_ = chunk_start_offset;
+ frame->img_components_[0].size_ = chunk_size;
+ frame->width_ = features.width;
+ frame->height_ = features.height;
+ frame->has_alpha_ |= features.has_alpha;
+ frame->frame_num_ = frame_num;
+ frame->complete_ = (status == PARSE_OK);
+ Skip(mem, payload_available);
+ } else {
+ goto Done;
+ }
+ break;
+ Done:
+ default:
+ // Restore fourcc/size when moving up one level in parsing.
+ Rewind(mem, CHUNK_HEADER_SIZE);
+ done = 1;
+ break;
+ }
+
+ if (mem->start_ == mem->riff_end_) {
+ done = 1;
+ } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) {
+ status = PARSE_NEED_MORE_DATA;
+ }
+ } while (!done && status == PARSE_OK);
+
+ return status;
+}
+
+// Creates a new Frame if 'actual_size' is within bounds and 'mem' contains
+// enough data ('min_size') to parse the payload.
+// Returns PARSE_OK on success with *frame pointing to the new Frame.
+// Returns PARSE_NEED_MORE_DATA with insufficient data, PARSE_ERROR otherwise.
+static ParseStatus NewFrame(const MemBuffer* const mem,
+ uint32_t min_size, uint32_t actual_size,
+ Frame** frame) {
+ if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR;
+ if (actual_size < min_size) return PARSE_ERROR;
+ if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
+
+ *frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(**frame));
+ return (*frame == NULL) ? PARSE_ERROR : PARSE_OK;
+}
+
+// Parse a 'ANMF' chunk and any image bearing chunks that immediately follow.
+// 'frame_chunk_size' is the previously validated, padded chunk size.
+static ParseStatus ParseAnimationFrame(
+ WebPDemuxer* const dmux, uint32_t frame_chunk_size) {
+ const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG);
+ const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE;
+ int added_frame = 0;
+ int bits;
+ MemBuffer* const mem = &dmux->mem_;
+ Frame* frame;
+ ParseStatus status =
+ NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame);
+ if (status != PARSE_OK) return status;
+
+ frame->x_offset_ = 2 * ReadLE24s(mem);
+ frame->y_offset_ = 2 * ReadLE24s(mem);
+ frame->width_ = 1 + ReadLE24s(mem);
+ frame->height_ = 1 + ReadLE24s(mem);
+ frame->duration_ = ReadLE24s(mem);
+ bits = ReadByte(mem);
+ frame->dispose_method_ =
+ (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE;
+ frame->blend_method_ = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND;
+ if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) {
+ WebPSafeFree(frame);
+ return PARSE_ERROR;
+ }
+
+ // Store a frame only if the animation flag is set there is some data for
+ // this frame is available.
+ status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame);
+ if (status != PARSE_ERROR && is_animation && frame->frame_num_ > 0) {
+ added_frame = AddFrame(dmux, frame);
+ if (added_frame) {
+ ++dmux->num_frames_;
+ } else {
+ status = PARSE_ERROR;
+ }
+ }
+
+ if (!added_frame) WebPSafeFree(frame);
+ return status;
+}
+
+// General chunk storage, starting with the header at 'start_offset', allowing
+// the user to request the payload via a fourcc string. 'size' includes the
+// header and the unpadded payload size.
+// Returns true on success, false otherwise.
+static int StoreChunk(WebPDemuxer* const dmux,
+ size_t start_offset, uint32_t size) {
+ Chunk* const chunk = (Chunk*)WebPSafeCalloc(1ULL, sizeof(*chunk));
+ if (chunk == NULL) return 0;
+
+ chunk->data_.offset_ = start_offset;
+ chunk->data_.size_ = size;
+ AddChunk(dmux, chunk);
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+// Primary chunk parsing
+
+static ParseStatus ReadHeader(MemBuffer* const mem) {
+ const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE;
+ uint32_t riff_size;
+
+ // Basic file level validation.
+ if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
+ if (memcmp(GetBuffer(mem), "RIFF", CHUNK_SIZE_BYTES) ||
+ memcmp(GetBuffer(mem) + CHUNK_HEADER_SIZE, "WEBP", CHUNK_SIZE_BYTES)) {
+ return PARSE_ERROR;
+ }
+
+ riff_size = GetLE32(GetBuffer(mem) + TAG_SIZE);
+ if (riff_size < CHUNK_HEADER_SIZE) return PARSE_ERROR;
+ if (riff_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
+
+ // There's no point in reading past the end of the RIFF chunk
+ mem->riff_end_ = riff_size + CHUNK_HEADER_SIZE;
+ if (mem->buf_size_ > mem->riff_end_) {
+ mem->buf_size_ = mem->end_ = mem->riff_end_;
+ }
+
+ Skip(mem, RIFF_HEADER_SIZE);
+ return PARSE_OK;
+}
+
+static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) {
+ const size_t min_size = CHUNK_HEADER_SIZE;
+ MemBuffer* const mem = &dmux->mem_;
+ Frame* frame;
+ ParseStatus status;
+ int image_added = 0;
+
+ if (dmux->frames_ != NULL) return PARSE_ERROR;
+ if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR;
+ if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
+
+ frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame));
+ if (frame == NULL) return PARSE_ERROR;
+
+ // For the single image case we allow parsing of a partial frame, but we need
+ // at least CHUNK_HEADER_SIZE for parsing.
+ status = StoreFrame(1, CHUNK_HEADER_SIZE, &dmux->mem_, frame);
+ if (status != PARSE_ERROR) {
+ const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG);
+ // Clear any alpha when the alpha flag is missing.
+ if (!has_alpha && frame->img_components_[1].size_ > 0) {
+ frame->img_components_[1].offset_ = 0;
+ frame->img_components_[1].size_ = 0;
+ frame->has_alpha_ = 0;
+ }
+
+ // Use the frame width/height as the canvas values for non-vp8x files.
+ // Also, set ALPHA_FLAG if this is a lossless image with alpha.
+ if (!dmux->is_ext_format_ && frame->width_ > 0 && frame->height_ > 0) {
+ dmux->state_ = WEBP_DEMUX_PARSED_HEADER;
+ dmux->canvas_width_ = frame->width_;
+ dmux->canvas_height_ = frame->height_;
+ dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0;
+ }
+ if (!AddFrame(dmux, frame)) {
+ status = PARSE_ERROR; // last frame was left incomplete
+ } else {
+ image_added = 1;
+ dmux->num_frames_ = 1;
+ }
+ }
+
+ if (!image_added) WebPSafeFree(frame);
+ return status;
+}
+
+static ParseStatus ParseVP8XChunks(WebPDemuxer* const dmux) {
+ const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG);
+ MemBuffer* const mem = &dmux->mem_;
+ int anim_chunks = 0;
+ ParseStatus status = PARSE_OK;
+
+ do {
+ int store_chunk = 1;
+ const size_t chunk_start_offset = mem->start_;
+ const uint32_t fourcc = ReadLE32(mem);
+ const uint32_t chunk_size = ReadLE32(mem);
+ const uint32_t chunk_size_padded = chunk_size + (chunk_size & 1);
+
+ if (chunk_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
+ if (SizeIsInvalid(mem, chunk_size_padded)) return PARSE_ERROR;
+
+ switch (fourcc) {
+ case MKFOURCC('V', 'P', '8', 'X'): {
+ return PARSE_ERROR;
+ }
+ case MKFOURCC('A', 'L', 'P', 'H'):
+ case MKFOURCC('V', 'P', '8', ' '):
+ case MKFOURCC('V', 'P', '8', 'L'): {
+ // check that this isn't an animation (all frames should be in an ANMF).
+ if (anim_chunks > 0 || is_animation) return PARSE_ERROR;
+
+ Rewind(mem, CHUNK_HEADER_SIZE);
+ status = ParseSingleImage(dmux);
+ break;
+ }
+ case MKFOURCC('A', 'N', 'I', 'M'): {
+ if (chunk_size_padded < ANIM_CHUNK_SIZE) return PARSE_ERROR;
+
+ if (MemDataSize(mem) < chunk_size_padded) {
+ status = PARSE_NEED_MORE_DATA;
+ } else if (anim_chunks == 0) {
+ ++anim_chunks;
+ dmux->bgcolor_ = ReadLE32(mem);
+ dmux->loop_count_ = ReadLE16s(mem);
+ Skip(mem, chunk_size_padded - ANIM_CHUNK_SIZE);
+ } else {
+ store_chunk = 0;
+ goto Skip;
+ }
+ break;
+ }
+ case MKFOURCC('A', 'N', 'M', 'F'): {
+ if (anim_chunks == 0) return PARSE_ERROR; // 'ANIM' precedes frames.
+ status = ParseAnimationFrame(dmux, chunk_size_padded);
+ break;
+ }
+ case MKFOURCC('I', 'C', 'C', 'P'): {
+ store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG);
+ goto Skip;
+ }
+ case MKFOURCC('E', 'X', 'I', 'F'): {
+ store_chunk = !!(dmux->feature_flags_ & EXIF_FLAG);
+ goto Skip;
+ }
+ case MKFOURCC('X', 'M', 'P', ' '): {
+ store_chunk = !!(dmux->feature_flags_ & XMP_FLAG);
+ goto Skip;
+ }
+ Skip:
+ default: {
+ if (chunk_size_padded <= MemDataSize(mem)) {
+ if (store_chunk) {
+ // Store only the chunk header and unpadded size as only the payload
+ // will be returned to the user.
+ if (!StoreChunk(dmux, chunk_start_offset,
+ CHUNK_HEADER_SIZE + chunk_size)) {
+ return PARSE_ERROR;
+ }
+ }
+ Skip(mem, chunk_size_padded);
+ } else {
+ status = PARSE_NEED_MORE_DATA;
+ }
+ }
+ }
+
+ if (mem->start_ == mem->riff_end_) {
+ break;
+ } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) {
+ status = PARSE_NEED_MORE_DATA;
+ }
+ } while (status == PARSE_OK);
+
+ return status;
+}
+
+static ParseStatus ParseVP8X(WebPDemuxer* const dmux) {
+ MemBuffer* const mem = &dmux->mem_;
+ uint32_t vp8x_size;
+
+ if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA;
+
+ dmux->is_ext_format_ = 1;
+ Skip(mem, TAG_SIZE); // VP8X
+ vp8x_size = ReadLE32(mem);
+ if (vp8x_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
+ if (vp8x_size < VP8X_CHUNK_SIZE) return PARSE_ERROR;
+ vp8x_size += vp8x_size & 1;
+ if (SizeIsInvalid(mem, vp8x_size)) return PARSE_ERROR;
+ if (MemDataSize(mem) < vp8x_size) return PARSE_NEED_MORE_DATA;
+
+ dmux->feature_flags_ = ReadByte(mem);
+ Skip(mem, 3); // Reserved.
+ dmux->canvas_width_ = 1 + ReadLE24s(mem);
+ dmux->canvas_height_ = 1 + ReadLE24s(mem);
+ if (dmux->canvas_width_ * (uint64_t)dmux->canvas_height_ >= MAX_IMAGE_AREA) {
+ return PARSE_ERROR; // image final dimension is too large
+ }
+ Skip(mem, vp8x_size - VP8X_CHUNK_SIZE); // skip any trailing data.
+ dmux->state_ = WEBP_DEMUX_PARSED_HEADER;
+
+ if (SizeIsInvalid(mem, CHUNK_HEADER_SIZE)) return PARSE_ERROR;
+ if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA;
+
+ return ParseVP8XChunks(dmux);
+}
+
+// -----------------------------------------------------------------------------
+// Format validation
+
+static int IsValidSimpleFormat(const WebPDemuxer* const dmux) {
+ const Frame* const frame = dmux->frames_;
+ if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1;
+
+ if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0;
+ if (dmux->state_ == WEBP_DEMUX_DONE && frame == NULL) return 0;
+
+ if (frame->width_ <= 0 || frame->height_ <= 0) return 0;
+ return 1;
+}
+
+// If 'exact' is true, check that the image resolution matches the canvas.
+// If 'exact' is false, check that the x/y offsets do not exceed the canvas.
+// TODO(jzern): this is insufficient in the fragmented image case if the
+// expectation is that the fragments completely cover the canvas.
+static int CheckFrameBounds(const Frame* const frame, int exact,
+ int canvas_width, int canvas_height) {
+ if (exact) {
+ if (frame->x_offset_ != 0 || frame->y_offset_ != 0) {
+ return 0;
+ }
+ if (frame->width_ != canvas_width || frame->height_ != canvas_height) {
+ return 0;
+ }
+ } else {
+ if (frame->x_offset_ < 0 || frame->y_offset_ < 0) return 0;
+ if (frame->width_ + frame->x_offset_ > canvas_width) return 0;
+ if (frame->height_ + frame->y_offset_ > canvas_height) return 0;
+ }
+ return 1;
+}
+
+static int IsValidExtendedFormat(const WebPDemuxer* const dmux) {
+ const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG);
+ const int is_fragmented = !!(dmux->feature_flags_ & FRAGMENTS_FLAG);
+ const Frame* f = dmux->frames_;
+
+ if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1;
+
+ if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0;
+ if (dmux->loop_count_ < 0) return 0;
+ if (dmux->state_ == WEBP_DEMUX_DONE && dmux->frames_ == NULL) return 0;
+ if (is_fragmented) return 0;
+
+ while (f != NULL) {
+ const int cur_frame_set = f->frame_num_;
+ int frame_count = 0, fragment_count = 0;
+
+ // Check frame properties and if the image is composed of fragments that
+ // each fragment came from a fragment.
+ for (; f != NULL && f->frame_num_ == cur_frame_set; f = f->next_) {
+ const ChunkData* const image = f->img_components_;
+ const ChunkData* const alpha = f->img_components_ + 1;
+
+ if (is_fragmented && !f->is_fragment_) return 0;
+ if (!is_fragmented && f->is_fragment_) return 0;
+ if (!is_animation && f->frame_num_ > 1) return 0;
+
+ if (f->complete_) {
+ if (alpha->size_ == 0 && image->size_ == 0) return 0;
+ // Ensure alpha precedes image bitstream.
+ if (alpha->size_ > 0 && alpha->offset_ > image->offset_) {
+ return 0;
+ }
+
+ if (f->width_ <= 0 || f->height_ <= 0) return 0;
+ } else {
+ // There shouldn't be a partial frame in a complete file.
+ if (dmux->state_ == WEBP_DEMUX_DONE) return 0;
+
+ // Ensure alpha precedes image bitstream.
+ if (alpha->size_ > 0 && image->size_ > 0 &&
+ alpha->offset_ > image->offset_) {
+ return 0;
+ }
+ // There shouldn't be any frames after an incomplete one.
+ if (f->next_ != NULL) return 0;
+ }
+
+ if (f->width_ > 0 && f->height_ > 0 &&
+ !CheckFrameBounds(f, !(is_animation || is_fragmented),
+ dmux->canvas_width_, dmux->canvas_height_)) {
+ return 0;
+ }
+
+ fragment_count += f->is_fragment_;
+ ++frame_count;
+ }
+ if (!is_fragmented && frame_count > 1) return 0;
+ if (fragment_count > 0 && frame_count != fragment_count) return 0;
+ }
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+// WebPDemuxer object
+
+static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) {
+ dmux->state_ = WEBP_DEMUX_PARSING_HEADER;
+ dmux->loop_count_ = 1;
+ dmux->bgcolor_ = 0xFFFFFFFF; // White background by default.
+ dmux->canvas_width_ = -1;
+ dmux->canvas_height_ = -1;
+ dmux->frames_tail_ = &dmux->frames_;
+ dmux->chunks_tail_ = &dmux->chunks_;
+ dmux->mem_ = *mem;
+}
+
+WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial,
+ WebPDemuxState* state, int version) {
+ const ChunkParser* parser;
+ int partial;
+ ParseStatus status = PARSE_ERROR;
+ MemBuffer mem;
+ WebPDemuxer* dmux;
+
+ if (state != NULL) *state = WEBP_DEMUX_PARSE_ERROR;
+
+ if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DEMUX_ABI_VERSION)) return NULL;
+ if (data == NULL || data->bytes == NULL || data->size == 0) return NULL;
+
+ if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL;
+ status = ReadHeader(&mem);
+ if (status != PARSE_OK) {
+ if (state != NULL) {
+ *state = (status == PARSE_NEED_MORE_DATA) ? WEBP_DEMUX_PARSING_HEADER
+ : WEBP_DEMUX_PARSE_ERROR;
+ }
+ return NULL;
+ }
+
+ partial = (mem.buf_size_ < mem.riff_end_);
+ if (!allow_partial && partial) return NULL;
+
+ dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux));
+ if (dmux == NULL) return NULL;
+ InitDemux(dmux, &mem);
+
+ status = PARSE_ERROR;
+ for (parser = kMasterChunks; parser->parse != NULL; ++parser) {
+ if (!memcmp(parser->id, GetBuffer(&dmux->mem_), TAG_SIZE)) {
+ status = parser->parse(dmux);
+ if (status == PARSE_OK) dmux->state_ = WEBP_DEMUX_DONE;
+ if (status == PARSE_NEED_MORE_DATA && !partial) status = PARSE_ERROR;
+ if (status != PARSE_ERROR && !parser->valid(dmux)) status = PARSE_ERROR;
+ if (status == PARSE_ERROR) dmux->state_ = WEBP_DEMUX_PARSE_ERROR;
+ break;
+ }
+ }
+ if (state != NULL) *state = dmux->state_;
+
+ if (status == PARSE_ERROR) {
+ WebPDemuxDelete(dmux);
+ return NULL;
+ }
+ return dmux;
+}
+
+void WebPDemuxDelete(WebPDemuxer* dmux) {
+ Chunk* c;
+ Frame* f;
+ if (dmux == NULL) return;
+
+ for (f = dmux->frames_; f != NULL;) {
+ Frame* const cur_frame = f;
+ f = f->next_;
+ WebPSafeFree(cur_frame);
+ }
+ for (c = dmux->chunks_; c != NULL;) {
+ Chunk* const cur_chunk = c;
+ c = c->next_;
+ WebPSafeFree(cur_chunk);
+ }
+ WebPSafeFree(dmux);
+}
+
+// -----------------------------------------------------------------------------
+
+uint32_t WebPDemuxGetI(const WebPDemuxer* dmux, WebPFormatFeature feature) {
+ if (dmux == NULL) return 0;
+
+ switch (feature) {
+ case WEBP_FF_FORMAT_FLAGS: return dmux->feature_flags_;
+ case WEBP_FF_CANVAS_WIDTH: return (uint32_t)dmux->canvas_width_;
+ case WEBP_FF_CANVAS_HEIGHT: return (uint32_t)dmux->canvas_height_;
+ case WEBP_FF_LOOP_COUNT: return (uint32_t)dmux->loop_count_;
+ case WEBP_FF_BACKGROUND_COLOR: return dmux->bgcolor_;
+ case WEBP_FF_FRAME_COUNT: return (uint32_t)dmux->num_frames_;
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+// Frame iteration
+
+// Find the first 'frame_num' frame. There may be multiple such frames in a
+// fragmented frame.
+static const Frame* GetFrame(const WebPDemuxer* const dmux, int frame_num) {
+ const Frame* f;
+ for (f = dmux->frames_; f != NULL; f = f->next_) {
+ if (frame_num == f->frame_num_) break;
+ }
+ return f;
+}
+
+// Returns fragment 'fragment_num' and the total count.
+static const Frame* GetFragment(
+ const Frame* const frame_set, int fragment_num, int* const count) {
+ const int this_frame = frame_set->frame_num_;
+ const Frame* f = frame_set;
+ const Frame* fragment = NULL;
+ int total;
+
+ for (total = 0; f != NULL && f->frame_num_ == this_frame; f = f->next_) {
+ if (++total == fragment_num) fragment = f;
+ }
+ *count = total;
+ return fragment;
+}
+
+static const uint8_t* GetFramePayload(const uint8_t* const mem_buf,
+ const Frame* const frame,
+ size_t* const data_size) {
+ *data_size = 0;
+ if (frame != NULL) {
+ const ChunkData* const image = frame->img_components_;
+ const ChunkData* const alpha = frame->img_components_ + 1;
+ size_t start_offset = image->offset_;
+ *data_size = image->size_;
+
+ // if alpha exists it precedes image, update the size allowing for
+ // intervening chunks.
+ if (alpha->size_ > 0) {
+ const size_t inter_size = (image->offset_ > 0)
+ ? image->offset_ - (alpha->offset_ + alpha->size_)
+ : 0;
+ start_offset = alpha->offset_;
+ *data_size += alpha->size_ + inter_size;
+ }
+ return mem_buf + start_offset;
+ }
+ return NULL;
+}
+
+// Create a whole 'frame' from VP8 (+ alpha) or lossless.
+static int SynthesizeFrame(const WebPDemuxer* const dmux,
+ const Frame* const first_frame,
+ int fragment_num, WebPIterator* const iter) {
+ const uint8_t* const mem_buf = dmux->mem_.buf_;
+ int num_fragments;
+ size_t payload_size = 0;
+ const Frame* const fragment =
+ GetFragment(first_frame, fragment_num, &num_fragments);
+ const uint8_t* const payload =
+ GetFramePayload(mem_buf, fragment, &payload_size);
+ if (payload == NULL) return 0;
+ assert(first_frame != NULL);
+
+ iter->frame_num = first_frame->frame_num_;
+ iter->num_frames = dmux->num_frames_;
+ iter->fragment_num = fragment_num;
+ iter->num_fragments = num_fragments;
+ iter->x_offset = fragment->x_offset_;
+ iter->y_offset = fragment->y_offset_;
+ iter->width = fragment->width_;
+ iter->height = fragment->height_;
+ iter->has_alpha = fragment->has_alpha_;
+ iter->duration = fragment->duration_;
+ iter->dispose_method = fragment->dispose_method_;
+ iter->blend_method = fragment->blend_method_;
+ iter->complete = fragment->complete_;
+ iter->fragment.bytes = payload;
+ iter->fragment.size = payload_size;
+ return 1;
+}
+
+static int SetFrame(int frame_num, WebPIterator* const iter) {
+ const Frame* frame;
+ const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_;
+ if (dmux == NULL || frame_num < 0) return 0;
+ if (frame_num > dmux->num_frames_) return 0;
+ if (frame_num == 0) frame_num = dmux->num_frames_;
+
+ frame = GetFrame(dmux, frame_num);
+ if (frame == NULL) return 0;
+
+ return SynthesizeFrame(dmux, frame, 1, iter);
+}
+
+int WebPDemuxGetFrame(const WebPDemuxer* dmux, int frame, WebPIterator* iter) {
+ if (iter == NULL) return 0;
+
+ memset(iter, 0, sizeof(*iter));
+ iter->private_ = (void*)dmux;
+ return SetFrame(frame, iter);
+}
+
+int WebPDemuxNextFrame(WebPIterator* iter) {
+ if (iter == NULL) return 0;
+ return SetFrame(iter->frame_num + 1, iter);
+}
+
+int WebPDemuxPrevFrame(WebPIterator* iter) {
+ if (iter == NULL) return 0;
+ if (iter->frame_num <= 1) return 0;
+ return SetFrame(iter->frame_num - 1, iter);
+}
+
+int WebPDemuxSelectFragment(WebPIterator* iter, int fragment_num) {
+ if (iter != NULL && iter->private_ != NULL && fragment_num > 0) {
+ const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_;
+ const Frame* const frame = GetFrame(dmux, iter->frame_num);
+ if (frame == NULL) return 0;
+
+ return SynthesizeFrame(dmux, frame, fragment_num, iter);
+ }
+ return 0;
+}
+
+void WebPDemuxReleaseIterator(WebPIterator* iter) {
+ (void)iter;
+}
+
+// -----------------------------------------------------------------------------
+// Chunk iteration
+
+static int ChunkCount(const WebPDemuxer* const dmux, const char fourcc[4]) {
+ const uint8_t* const mem_buf = dmux->mem_.buf_;
+ const Chunk* c;
+ int count = 0;
+ for (c = dmux->chunks_; c != NULL; c = c->next_) {
+ const uint8_t* const header = mem_buf + c->data_.offset_;
+ if (!memcmp(header, fourcc, TAG_SIZE)) ++count;
+ }
+ return count;
+}
+
+static const Chunk* GetChunk(const WebPDemuxer* const dmux,
+ const char fourcc[4], int chunk_num) {
+ const uint8_t* const mem_buf = dmux->mem_.buf_;
+ const Chunk* c;
+ int count = 0;
+ for (c = dmux->chunks_; c != NULL; c = c->next_) {
+ const uint8_t* const header = mem_buf + c->data_.offset_;
+ if (!memcmp(header, fourcc, TAG_SIZE)) ++count;
+ if (count == chunk_num) break;
+ }
+ return c;
+}
+
+static int SetChunk(const char fourcc[4], int chunk_num,
+ WebPChunkIterator* const iter) {
+ const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_;
+ int count;
+
+ if (dmux == NULL || fourcc == NULL || chunk_num < 0) return 0;
+ count = ChunkCount(dmux, fourcc);
+ if (count == 0) return 0;
+ if (chunk_num == 0) chunk_num = count;
+
+ if (chunk_num <= count) {
+ const uint8_t* const mem_buf = dmux->mem_.buf_;
+ const Chunk* const chunk = GetChunk(dmux, fourcc, chunk_num);
+ iter->chunk.bytes = mem_buf + chunk->data_.offset_ + CHUNK_HEADER_SIZE;
+ iter->chunk.size = chunk->data_.size_ - CHUNK_HEADER_SIZE;
+ iter->num_chunks = count;
+ iter->chunk_num = chunk_num;
+ return 1;
+ }
+ return 0;
+}
+
+int WebPDemuxGetChunk(const WebPDemuxer* dmux,
+ const char fourcc[4], int chunk_num,
+ WebPChunkIterator* iter) {
+ if (iter == NULL) return 0;
+
+ memset(iter, 0, sizeof(*iter));
+ iter->private_ = (void*)dmux;
+ return SetChunk(fourcc, chunk_num, iter);
+}
+
+int WebPDemuxNextChunk(WebPChunkIterator* iter) {
+ if (iter != NULL) {
+ const char* const fourcc =
+ (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE;
+ return SetChunk(fourcc, iter->chunk_num + 1, iter);
+ }
+ return 0;
+}
+
+int WebPDemuxPrevChunk(WebPChunkIterator* iter) {
+ if (iter != NULL && iter->chunk_num > 1) {
+ const char* const fourcc =
+ (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE;
+ return SetChunk(fourcc, iter->chunk_num - 1, iter);
+ }
+ return 0;
+}
+
+void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter) {
+ (void)iter;
+}
+
diff --git a/drivers/webp/dsp/alpha_processing.c b/drivers/webp/dsp/alpha_processing.c
new file mode 100644
index 0000000000..1716cace8d
--- /dev/null
+++ b/drivers/webp/dsp/alpha_processing.c
@@ -0,0 +1,383 @@
+// Copyright 2013 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Utilities for processing transparent channel.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include "./dsp.h"
+
+// Tables can be faster on some platform but incur some extra binary size (~2k).
+// #define USE_TABLES_FOR_ALPHA_MULT
+
+// -----------------------------------------------------------------------------
+
+#define MFIX 24 // 24bit fixed-point arithmetic
+#define HALF ((1u << MFIX) >> 1)
+#define KINV_255 ((1u << MFIX) / 255u)
+
+static uint32_t Mult(uint8_t x, uint32_t mult) {
+ const uint32_t v = (x * mult + HALF) >> MFIX;
+ assert(v <= 255); // <- 24bit precision is enough to ensure that.
+ return v;
+}
+
+#ifdef USE_TABLES_FOR_ALPHA_MULT
+
+static const uint32_t kMultTables[2][256] = {
+ { // (255u << MFIX) / alpha
+ 0x00000000, 0xff000000, 0x7f800000, 0x55000000, 0x3fc00000, 0x33000000,
+ 0x2a800000, 0x246db6db, 0x1fe00000, 0x1c555555, 0x19800000, 0x172e8ba2,
+ 0x15400000, 0x139d89d8, 0x1236db6d, 0x11000000, 0x0ff00000, 0x0f000000,
+ 0x0e2aaaaa, 0x0d6bca1a, 0x0cc00000, 0x0c249249, 0x0b9745d1, 0x0b1642c8,
+ 0x0aa00000, 0x0a333333, 0x09cec4ec, 0x0971c71c, 0x091b6db6, 0x08cb08d3,
+ 0x08800000, 0x0839ce73, 0x07f80000, 0x07ba2e8b, 0x07800000, 0x07492492,
+ 0x07155555, 0x06e45306, 0x06b5e50d, 0x0689d89d, 0x06600000, 0x063831f3,
+ 0x06124924, 0x05ee23b8, 0x05cba2e8, 0x05aaaaaa, 0x058b2164, 0x056cefa8,
+ 0x05500000, 0x05343eb1, 0x05199999, 0x05000000, 0x04e76276, 0x04cfb2b7,
+ 0x04b8e38e, 0x04a2e8ba, 0x048db6db, 0x0479435e, 0x04658469, 0x045270d0,
+ 0x04400000, 0x042e29f7, 0x041ce739, 0x040c30c3, 0x03fc0000, 0x03ec4ec4,
+ 0x03dd1745, 0x03ce540f, 0x03c00000, 0x03b21642, 0x03a49249, 0x03976fc6,
+ 0x038aaaaa, 0x037e3f1f, 0x03722983, 0x03666666, 0x035af286, 0x034fcace,
+ 0x0344ec4e, 0x033a5440, 0x03300000, 0x0325ed09, 0x031c18f9, 0x0312818a,
+ 0x03092492, 0x03000000, 0x02f711dc, 0x02ee5846, 0x02e5d174, 0x02dd7baf,
+ 0x02d55555, 0x02cd5cd5, 0x02c590b2, 0x02bdef7b, 0x02b677d4, 0x02af286b,
+ 0x02a80000, 0x02a0fd5c, 0x029a1f58, 0x029364d9, 0x028ccccc, 0x0286562d,
+ 0x02800000, 0x0279c952, 0x0273b13b, 0x026db6db, 0x0267d95b, 0x026217ec,
+ 0x025c71c7, 0x0256e62a, 0x0251745d, 0x024c1bac, 0x0246db6d, 0x0241b2f9,
+ 0x023ca1af, 0x0237a6f4, 0x0232c234, 0x022df2df, 0x02293868, 0x02249249,
+ 0x02200000, 0x021b810e, 0x021714fb, 0x0212bb51, 0x020e739c, 0x020a3d70,
+ 0x02061861, 0x02020408, 0x01fe0000, 0x01fa0be8, 0x01f62762, 0x01f25213,
+ 0x01ee8ba2, 0x01ead3ba, 0x01e72a07, 0x01e38e38, 0x01e00000, 0x01dc7f10,
+ 0x01d90b21, 0x01d5a3e9, 0x01d24924, 0x01cefa8d, 0x01cbb7e3, 0x01c880e5,
+ 0x01c55555, 0x01c234f7, 0x01bf1f8f, 0x01bc14e5, 0x01b914c1, 0x01b61eed,
+ 0x01b33333, 0x01b05160, 0x01ad7943, 0x01aaaaaa, 0x01a7e567, 0x01a5294a,
+ 0x01a27627, 0x019fcbd2, 0x019d2a20, 0x019a90e7, 0x01980000, 0x01957741,
+ 0x0192f684, 0x01907da4, 0x018e0c7c, 0x018ba2e8, 0x018940c5, 0x0186e5f0,
+ 0x01849249, 0x018245ae, 0x01800000, 0x017dc11f, 0x017b88ee, 0x0179574e,
+ 0x01772c23, 0x01750750, 0x0172e8ba, 0x0170d045, 0x016ebdd7, 0x016cb157,
+ 0x016aaaaa, 0x0168a9b9, 0x0166ae6a, 0x0164b8a7, 0x0162c859, 0x0160dd67,
+ 0x015ef7bd, 0x015d1745, 0x015b3bea, 0x01596596, 0x01579435, 0x0155c7b4,
+ 0x01540000, 0x01523d03, 0x01507eae, 0x014ec4ec, 0x014d0fac, 0x014b5edc,
+ 0x0149b26c, 0x01480a4a, 0x01466666, 0x0144c6af, 0x01432b16, 0x0141938b,
+ 0x01400000, 0x013e7063, 0x013ce4a9, 0x013b5cc0, 0x0139d89d, 0x01385830,
+ 0x0136db6d, 0x01356246, 0x0133ecad, 0x01327a97, 0x01310bf6, 0x012fa0be,
+ 0x012e38e3, 0x012cd459, 0x012b7315, 0x012a150a, 0x0128ba2e, 0x01276276,
+ 0x01260dd6, 0x0124bc44, 0x01236db6, 0x01222222, 0x0120d97c, 0x011f93bc,
+ 0x011e50d7, 0x011d10c4, 0x011bd37a, 0x011a98ef, 0x0119611a, 0x01182bf2,
+ 0x0116f96f, 0x0115c988, 0x01149c34, 0x0113716a, 0x01124924, 0x01112358,
+ 0x01100000, 0x010edf12, 0x010dc087, 0x010ca458, 0x010b8a7d, 0x010a72f0,
+ 0x01095da8, 0x01084a9f, 0x010739ce, 0x01062b2e, 0x01051eb8, 0x01041465,
+ 0x01030c30, 0x01020612, 0x01010204, 0x01000000 },
+ { // alpha * KINV_255
+ 0x00000000, 0x00010101, 0x00020202, 0x00030303, 0x00040404, 0x00050505,
+ 0x00060606, 0x00070707, 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b,
+ 0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, 0x00101010, 0x00111111,
+ 0x00121212, 0x00131313, 0x00141414, 0x00151515, 0x00161616, 0x00171717,
+ 0x00181818, 0x00191919, 0x001a1a1a, 0x001b1b1b, 0x001c1c1c, 0x001d1d1d,
+ 0x001e1e1e, 0x001f1f1f, 0x00202020, 0x00212121, 0x00222222, 0x00232323,
+ 0x00242424, 0x00252525, 0x00262626, 0x00272727, 0x00282828, 0x00292929,
+ 0x002a2a2a, 0x002b2b2b, 0x002c2c2c, 0x002d2d2d, 0x002e2e2e, 0x002f2f2f,
+ 0x00303030, 0x00313131, 0x00323232, 0x00333333, 0x00343434, 0x00353535,
+ 0x00363636, 0x00373737, 0x00383838, 0x00393939, 0x003a3a3a, 0x003b3b3b,
+ 0x003c3c3c, 0x003d3d3d, 0x003e3e3e, 0x003f3f3f, 0x00404040, 0x00414141,
+ 0x00424242, 0x00434343, 0x00444444, 0x00454545, 0x00464646, 0x00474747,
+ 0x00484848, 0x00494949, 0x004a4a4a, 0x004b4b4b, 0x004c4c4c, 0x004d4d4d,
+ 0x004e4e4e, 0x004f4f4f, 0x00505050, 0x00515151, 0x00525252, 0x00535353,
+ 0x00545454, 0x00555555, 0x00565656, 0x00575757, 0x00585858, 0x00595959,
+ 0x005a5a5a, 0x005b5b5b, 0x005c5c5c, 0x005d5d5d, 0x005e5e5e, 0x005f5f5f,
+ 0x00606060, 0x00616161, 0x00626262, 0x00636363, 0x00646464, 0x00656565,
+ 0x00666666, 0x00676767, 0x00686868, 0x00696969, 0x006a6a6a, 0x006b6b6b,
+ 0x006c6c6c, 0x006d6d6d, 0x006e6e6e, 0x006f6f6f, 0x00707070, 0x00717171,
+ 0x00727272, 0x00737373, 0x00747474, 0x00757575, 0x00767676, 0x00777777,
+ 0x00787878, 0x00797979, 0x007a7a7a, 0x007b7b7b, 0x007c7c7c, 0x007d7d7d,
+ 0x007e7e7e, 0x007f7f7f, 0x00808080, 0x00818181, 0x00828282, 0x00838383,
+ 0x00848484, 0x00858585, 0x00868686, 0x00878787, 0x00888888, 0x00898989,
+ 0x008a8a8a, 0x008b8b8b, 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, 0x008f8f8f,
+ 0x00909090, 0x00919191, 0x00929292, 0x00939393, 0x00949494, 0x00959595,
+ 0x00969696, 0x00979797, 0x00989898, 0x00999999, 0x009a9a9a, 0x009b9b9b,
+ 0x009c9c9c, 0x009d9d9d, 0x009e9e9e, 0x009f9f9f, 0x00a0a0a0, 0x00a1a1a1,
+ 0x00a2a2a2, 0x00a3a3a3, 0x00a4a4a4, 0x00a5a5a5, 0x00a6a6a6, 0x00a7a7a7,
+ 0x00a8a8a8, 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, 0x00acacac, 0x00adadad,
+ 0x00aeaeae, 0x00afafaf, 0x00b0b0b0, 0x00b1b1b1, 0x00b2b2b2, 0x00b3b3b3,
+ 0x00b4b4b4, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, 0x00b8b8b8, 0x00b9b9b9,
+ 0x00bababa, 0x00bbbbbb, 0x00bcbcbc, 0x00bdbdbd, 0x00bebebe, 0x00bfbfbf,
+ 0x00c0c0c0, 0x00c1c1c1, 0x00c2c2c2, 0x00c3c3c3, 0x00c4c4c4, 0x00c5c5c5,
+ 0x00c6c6c6, 0x00c7c7c7, 0x00c8c8c8, 0x00c9c9c9, 0x00cacaca, 0x00cbcbcb,
+ 0x00cccccc, 0x00cdcdcd, 0x00cecece, 0x00cfcfcf, 0x00d0d0d0, 0x00d1d1d1,
+ 0x00d2d2d2, 0x00d3d3d3, 0x00d4d4d4, 0x00d5d5d5, 0x00d6d6d6, 0x00d7d7d7,
+ 0x00d8d8d8, 0x00d9d9d9, 0x00dadada, 0x00dbdbdb, 0x00dcdcdc, 0x00dddddd,
+ 0x00dedede, 0x00dfdfdf, 0x00e0e0e0, 0x00e1e1e1, 0x00e2e2e2, 0x00e3e3e3,
+ 0x00e4e4e4, 0x00e5e5e5, 0x00e6e6e6, 0x00e7e7e7, 0x00e8e8e8, 0x00e9e9e9,
+ 0x00eaeaea, 0x00ebebeb, 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef,
+ 0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, 0x00f4f4f4, 0x00f5f5f5,
+ 0x00f6f6f6, 0x00f7f7f7, 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb,
+ 0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff }
+};
+
+static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) {
+ return kMultTables[!inverse][a];
+}
+
+#else
+
+static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) {
+ return inverse ? (255u << MFIX) / a : a * KINV_255;
+}
+
+#endif // USE_TABLES_FOR_ALPHA_MULT
+
+void WebPMultARGBRowC(uint32_t* const ptr, int width, int inverse) {
+ int x;
+ for (x = 0; x < width; ++x) {
+ const uint32_t argb = ptr[x];
+ if (argb < 0xff000000u) { // alpha < 255
+ if (argb <= 0x00ffffffu) { // alpha == 0
+ ptr[x] = 0;
+ } else {
+ const uint32_t alpha = (argb >> 24) & 0xff;
+ const uint32_t scale = GetScale(alpha, inverse);
+ uint32_t out = argb & 0xff000000u;
+ out |= Mult(argb >> 0, scale) << 0;
+ out |= Mult(argb >> 8, scale) << 8;
+ out |= Mult(argb >> 16, scale) << 16;
+ ptr[x] = out;
+ }
+ }
+ }
+}
+
+void WebPMultRowC(uint8_t* const ptr, const uint8_t* const alpha,
+ int width, int inverse) {
+ int x;
+ for (x = 0; x < width; ++x) {
+ const uint32_t a = alpha[x];
+ if (a != 255) {
+ if (a == 0) {
+ ptr[x] = 0;
+ } else {
+ const uint32_t scale = GetScale(a, inverse);
+ ptr[x] = Mult(ptr[x], scale);
+ }
+ }
+ }
+}
+
+#undef KINV_255
+#undef HALF
+#undef MFIX
+
+void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse);
+void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha,
+ int width, int inverse);
+
+//------------------------------------------------------------------------------
+// Generic per-plane calls
+
+void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows,
+ int inverse) {
+ int n;
+ for (n = 0; n < num_rows; ++n) {
+ WebPMultARGBRow((uint32_t*)ptr, width, inverse);
+ ptr += stride;
+ }
+}
+
+void WebPMultRows(uint8_t* ptr, int stride,
+ const uint8_t* alpha, int alpha_stride,
+ int width, int num_rows, int inverse) {
+ int n;
+ for (n = 0; n < num_rows; ++n) {
+ WebPMultRow(ptr, alpha, width, inverse);
+ ptr += stride;
+ alpha += alpha_stride;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Premultiplied modes
+
+// non dithered-modes
+
+// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.)
+// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5),
+// one can use instead: (x * a * 65793 + (1 << 23)) >> 24
+#if 1 // (int)(x * a / 255.)
+#define MULTIPLIER(a) ((a) * 32897U)
+#define PREMULTIPLY(x, m) (((x) * (m)) >> 23)
+#else // (int)(x * a / 255. + .5)
+#define MULTIPLIER(a) ((a) * 65793U)
+#define PREMULTIPLY(x, m) (((x) * (m) + (1U << 23)) >> 24)
+#endif
+
+static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first,
+ int w, int h, int stride) {
+ while (h-- > 0) {
+ uint8_t* const rgb = rgba + (alpha_first ? 1 : 0);
+ const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3);
+ int i;
+ for (i = 0; i < w; ++i) {
+ const uint32_t a = alpha[4 * i];
+ if (a != 0xff) {
+ const uint32_t mult = MULTIPLIER(a);
+ rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult);
+ rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult);
+ rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult);
+ }
+ }
+ rgba += stride;
+ }
+}
+#undef MULTIPLIER
+#undef PREMULTIPLY
+
+// rgbA4444
+
+#define MULTIPLIER(a) ((a) * 0x1111) // 0x1111 ~= (1 << 16) / 15
+
+static WEBP_INLINE uint8_t dither_hi(uint8_t x) {
+ return (x & 0xf0) | (x >> 4);
+}
+
+static WEBP_INLINE uint8_t dither_lo(uint8_t x) {
+ return (x & 0x0f) | (x << 4);
+}
+
+static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) {
+ return (x * m) >> 16;
+}
+
+static WEBP_INLINE void ApplyAlphaMultiply4444(uint8_t* rgba4444,
+ int w, int h, int stride,
+ int rg_byte_pos /* 0 or 1 */) {
+ while (h-- > 0) {
+ int i;
+ for (i = 0; i < w; ++i) {
+ const uint32_t rg = rgba4444[2 * i + rg_byte_pos];
+ const uint32_t ba = rgba4444[2 * i + (rg_byte_pos ^ 1)];
+ const uint8_t a = ba & 0x0f;
+ const uint32_t mult = MULTIPLIER(a);
+ const uint8_t r = multiply(dither_hi(rg), mult);
+ const uint8_t g = multiply(dither_lo(rg), mult);
+ const uint8_t b = multiply(dither_hi(ba), mult);
+ rgba4444[2 * i + rg_byte_pos] = (r & 0xf0) | ((g >> 4) & 0x0f);
+ rgba4444[2 * i + (rg_byte_pos ^ 1)] = (b & 0xf0) | a;
+ }
+ rgba4444 += stride;
+ }
+}
+#undef MULTIPLIER
+
+static void ApplyAlphaMultiply_16b(uint8_t* rgba4444,
+ int w, int h, int stride) {
+#ifdef WEBP_SWAP_16BIT_CSP
+ ApplyAlphaMultiply4444(rgba4444, w, h, stride, 1);
+#else
+ ApplyAlphaMultiply4444(rgba4444, w, h, stride, 0);
+#endif
+}
+
+static int DispatchAlpha(const uint8_t* alpha, int alpha_stride,
+ int width, int height,
+ uint8_t* dst, int dst_stride) {
+ uint32_t alpha_mask = 0xff;
+ int i, j;
+
+ for (j = 0; j < height; ++j) {
+ for (i = 0; i < width; ++i) {
+ const uint32_t alpha_value = alpha[i];
+ dst[4 * i] = alpha_value;
+ alpha_mask &= alpha_value;
+ }
+ alpha += alpha_stride;
+ dst += dst_stride;
+ }
+
+ return (alpha_mask != 0xff);
+}
+
+static void DispatchAlphaToGreen(const uint8_t* alpha, int alpha_stride,
+ int width, int height,
+ uint32_t* dst, int dst_stride) {
+ int i, j;
+ for (j = 0; j < height; ++j) {
+ for (i = 0; i < width; ++i) {
+ dst[i] = alpha[i] << 8; // leave A/R/B channels zero'd.
+ }
+ alpha += alpha_stride;
+ dst += dst_stride;
+ }
+}
+
+static int ExtractAlpha(const uint8_t* argb, int argb_stride,
+ int width, int height,
+ uint8_t* alpha, int alpha_stride) {
+ uint8_t alpha_mask = 0xff;
+ int i, j;
+
+ for (j = 0; j < height; ++j) {
+ for (i = 0; i < width; ++i) {
+ const uint8_t alpha_value = argb[4 * i];
+ alpha[i] = alpha_value;
+ alpha_mask &= alpha_value;
+ }
+ argb += argb_stride;
+ alpha += alpha_stride;
+ }
+ return (alpha_mask == 0xff);
+}
+
+void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int);
+void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int);
+int (*WebPDispatchAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
+void (*WebPDispatchAlphaToGreen)(const uint8_t*, int, int, int, uint32_t*, int);
+int (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
+
+//------------------------------------------------------------------------------
+// Init function
+
+extern void WebPInitAlphaProcessingMIPSdspR2(void);
+extern void WebPInitAlphaProcessingSSE2(void);
+extern void WebPInitAlphaProcessingSSE41(void);
+
+static volatile VP8CPUInfo alpha_processing_last_cpuinfo_used =
+ (VP8CPUInfo)&alpha_processing_last_cpuinfo_used;
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) {
+ if (alpha_processing_last_cpuinfo_used == VP8GetCPUInfo) return;
+
+ WebPMultARGBRow = WebPMultARGBRowC;
+ WebPMultRow = WebPMultRowC;
+ WebPApplyAlphaMultiply = ApplyAlphaMultiply;
+ WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b;
+ WebPDispatchAlpha = DispatchAlpha;
+ WebPDispatchAlphaToGreen = DispatchAlphaToGreen;
+ WebPExtractAlpha = ExtractAlpha;
+
+ // If defined, use CPUInfo() to overwrite some pointers with faster versions.
+ if (VP8GetCPUInfo != NULL) {
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ WebPInitAlphaProcessingSSE2();
+#if defined(WEBP_USE_SSE41)
+ if (VP8GetCPUInfo(kSSE4_1)) {
+ WebPInitAlphaProcessingSSE41();
+ }
+#endif
+ }
+#endif
+#if defined(WEBP_USE_MIPS_DSP_R2)
+ if (VP8GetCPUInfo(kMIPSdspR2)) {
+ WebPInitAlphaProcessingMIPSdspR2();
+ }
+#endif
+ }
+ alpha_processing_last_cpuinfo_used = VP8GetCPUInfo;
+}
diff --git a/drivers/webp/dsp/alpha_processing_mips_dsp_r2.c b/drivers/webp/dsp/alpha_processing_mips_dsp_r2.c
new file mode 100644
index 0000000000..c631d78905
--- /dev/null
+++ b/drivers/webp/dsp/alpha_processing_mips_dsp_r2.c
@@ -0,0 +1,141 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Utilities for processing transparent channel.
+//
+// Author(s): Branimir Vasic (branimir.vasic@imgtec.com)
+// Djordje Pesut (djordje.pesut@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS_DSP_R2)
+
+static int DispatchAlpha(const uint8_t* alpha, int alpha_stride,
+ int width, int height,
+ uint8_t* dst, int dst_stride) {
+ uint32_t alpha_mask = 0xffffffff;
+ int i, j, temp0;
+
+ for (j = 0; j < height; ++j) {
+ uint8_t* pdst = dst;
+ const uint8_t* palpha = alpha;
+ for (i = 0; i < (width >> 2); ++i) {
+ int temp1, temp2, temp3;
+
+ __asm__ volatile (
+ "ulw %[temp0], 0(%[palpha]) \n\t"
+ "addiu %[palpha], %[palpha], 4 \n\t"
+ "addiu %[pdst], %[pdst], 16 \n\t"
+ "srl %[temp1], %[temp0], 8 \n\t"
+ "srl %[temp2], %[temp0], 16 \n\t"
+ "srl %[temp3], %[temp0], 24 \n\t"
+ "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t"
+ "sb %[temp0], -16(%[pdst]) \n\t"
+ "sb %[temp1], -12(%[pdst]) \n\t"
+ "sb %[temp2], -8(%[pdst]) \n\t"
+ "sb %[temp3], -4(%[pdst]) \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [palpha]"+r"(palpha), [pdst]"+r"(pdst),
+ [alpha_mask]"+r"(alpha_mask)
+ :
+ : "memory"
+ );
+ }
+
+ for (i = 0; i < (width & 3); ++i) {
+ __asm__ volatile (
+ "lbu %[temp0], 0(%[palpha]) \n\t"
+ "addiu %[palpha], %[palpha], 1 \n\t"
+ "sb %[temp0], 0(%[pdst]) \n\t"
+ "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t"
+ "addiu %[pdst], %[pdst], 4 \n\t"
+ : [temp0]"=&r"(temp0), [palpha]"+r"(palpha), [pdst]"+r"(pdst),
+ [alpha_mask]"+r"(alpha_mask)
+ :
+ : "memory"
+ );
+ }
+ alpha += alpha_stride;
+ dst += dst_stride;
+ }
+
+ __asm__ volatile (
+ "ext %[temp0], %[alpha_mask], 0, 16 \n\t"
+ "srl %[alpha_mask], %[alpha_mask], 16 \n\t"
+ "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t"
+ "ext %[temp0], %[alpha_mask], 0, 8 \n\t"
+ "srl %[alpha_mask], %[alpha_mask], 8 \n\t"
+ "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t"
+ : [temp0]"=&r"(temp0), [alpha_mask]"+r"(alpha_mask)
+ :
+ );
+
+ return (alpha_mask != 0xff);
+}
+
+static void MultARGBRow(uint32_t* const ptr, int width, int inverse) {
+ int x;
+ const uint32_t c_00ffffff = 0x00ffffffu;
+ const uint32_t c_ff000000 = 0xff000000u;
+ const uint32_t c_8000000 = 0x00800000u;
+ const uint32_t c_8000080 = 0x00800080u;
+ for (x = 0; x < width; ++x) {
+ const uint32_t argb = ptr[x];
+ if (argb < 0xff000000u) { // alpha < 255
+ if (argb <= 0x00ffffffu) { // alpha == 0
+ ptr[x] = 0;
+ } else {
+ int temp0, temp1, temp2, temp3, alpha;
+ __asm__ volatile (
+ "srl %[alpha], %[argb], 24 \n\t"
+ "replv.qb %[temp0], %[alpha] \n\t"
+ "and %[temp0], %[temp0], %[c_00ffffff] \n\t"
+ "beqz %[inverse], 0f \n\t"
+ "divu $zero, %[c_ff000000], %[alpha] \n\t"
+ "mflo %[temp0] \n\t"
+ "0: \n\t"
+ "andi %[temp1], %[argb], 0xff \n\t"
+ "ext %[temp2], %[argb], 8, 8 \n\t"
+ "ext %[temp3], %[argb], 16, 8 \n\t"
+ "mul %[temp1], %[temp1], %[temp0] \n\t"
+ "mul %[temp2], %[temp2], %[temp0] \n\t"
+ "mul %[temp3], %[temp3], %[temp0] \n\t"
+ "precrq.ph.w %[temp1], %[temp2], %[temp1] \n\t"
+ "addu %[temp3], %[temp3], %[c_8000000] \n\t"
+ "addu %[temp1], %[temp1], %[c_8000080] \n\t"
+ "precrq.ph.w %[temp3], %[argb], %[temp3] \n\t"
+ "precrq.qb.ph %[temp1], %[temp3], %[temp1] \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [alpha]"=&r"(alpha)
+ : [inverse]"r"(inverse), [c_00ffffff]"r"(c_00ffffff),
+ [c_8000000]"r"(c_8000000), [c_8000080]"r"(c_8000080),
+ [c_ff000000]"r"(c_ff000000), [argb]"r"(argb)
+ : "memory", "hi", "lo"
+ );
+ ptr[x] = temp1;
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void WebPInitAlphaProcessingMIPSdspR2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingMIPSdspR2(void) {
+ WebPDispatchAlpha = DispatchAlpha;
+ WebPMultARGBRow = MultARGBRow;
+}
+
+#else // !WEBP_USE_MIPS_DSP_R2
+
+WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingMIPSdspR2)
+
+#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/alpha_processing_sse2.c b/drivers/webp/dsp/alpha_processing_sse2.c
new file mode 100644
index 0000000000..5acb481dcd
--- /dev/null
+++ b/drivers/webp/dsp/alpha_processing_sse2.c
@@ -0,0 +1,298 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Utilities for processing transparent channel.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_SSE2)
+#include <emmintrin.h>
+
+//------------------------------------------------------------------------------
+
+static int DispatchAlpha(const uint8_t* alpha, int alpha_stride,
+ int width, int height,
+ uint8_t* dst, int dst_stride) {
+ // alpha_and stores an 'and' operation of all the alpha[] values. The final
+ // value is not 0xff if any of the alpha[] is not equal to 0xff.
+ uint32_t alpha_and = 0xff;
+ int i, j;
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i rgb_mask = _mm_set1_epi32(0xffffff00u); // to preserve RGB
+ const __m128i all_0xff = _mm_set_epi32(0, 0, ~0u, ~0u);
+ __m128i all_alphas = all_0xff;
+
+ // We must be able to access 3 extra bytes after the last written byte
+ // 'dst[4 * width - 4]', because we don't know if alpha is the first or the
+ // last byte of the quadruplet.
+ const int limit = (width - 1) & ~7;
+
+ for (j = 0; j < height; ++j) {
+ __m128i* out = (__m128i*)dst;
+ for (i = 0; i < limit; i += 8) {
+ // load 8 alpha bytes
+ const __m128i a0 = _mm_loadl_epi64((const __m128i*)&alpha[i]);
+ const __m128i a1 = _mm_unpacklo_epi8(a0, zero);
+ const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero);
+ const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero);
+ // load 8 dst pixels (32 bytes)
+ const __m128i b0_lo = _mm_loadu_si128(out + 0);
+ const __m128i b0_hi = _mm_loadu_si128(out + 1);
+ // mask dst alpha values
+ const __m128i b1_lo = _mm_and_si128(b0_lo, rgb_mask);
+ const __m128i b1_hi = _mm_and_si128(b0_hi, rgb_mask);
+ // combine
+ const __m128i b2_lo = _mm_or_si128(b1_lo, a2_lo);
+ const __m128i b2_hi = _mm_or_si128(b1_hi, a2_hi);
+ // store
+ _mm_storeu_si128(out + 0, b2_lo);
+ _mm_storeu_si128(out + 1, b2_hi);
+ // accumulate eight alpha 'and' in parallel
+ all_alphas = _mm_and_si128(all_alphas, a0);
+ out += 2;
+ }
+ for (; i < width; ++i) {
+ const uint32_t alpha_value = alpha[i];
+ dst[4 * i] = alpha_value;
+ alpha_and &= alpha_value;
+ }
+ alpha += alpha_stride;
+ dst += dst_stride;
+ }
+ // Combine the eight alpha 'and' into a 8-bit mask.
+ alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff));
+ return (alpha_and != 0xff);
+}
+
+static void DispatchAlphaToGreen(const uint8_t* alpha, int alpha_stride,
+ int width, int height,
+ uint32_t* dst, int dst_stride) {
+ int i, j;
+ const __m128i zero = _mm_setzero_si128();
+ const int limit = width & ~15;
+ for (j = 0; j < height; ++j) {
+ for (i = 0; i < limit; i += 16) { // process 16 alpha bytes
+ const __m128i a0 = _mm_loadu_si128((const __m128i*)&alpha[i]);
+ const __m128i a1 = _mm_unpacklo_epi8(zero, a0); // note the 'zero' first!
+ const __m128i b1 = _mm_unpackhi_epi8(zero, a0);
+ const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero);
+ const __m128i b2_lo = _mm_unpacklo_epi16(b1, zero);
+ const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero);
+ const __m128i b2_hi = _mm_unpackhi_epi16(b1, zero);
+ _mm_storeu_si128((__m128i*)&dst[i + 0], a2_lo);
+ _mm_storeu_si128((__m128i*)&dst[i + 4], a2_hi);
+ _mm_storeu_si128((__m128i*)&dst[i + 8], b2_lo);
+ _mm_storeu_si128((__m128i*)&dst[i + 12], b2_hi);
+ }
+ for (; i < width; ++i) dst[i] = alpha[i] << 8;
+ alpha += alpha_stride;
+ dst += dst_stride;
+ }
+}
+
+static int ExtractAlpha(const uint8_t* argb, int argb_stride,
+ int width, int height,
+ uint8_t* alpha, int alpha_stride) {
+ // alpha_and stores an 'and' operation of all the alpha[] values. The final
+ // value is not 0xff if any of the alpha[] is not equal to 0xff.
+ uint32_t alpha_and = 0xff;
+ int i, j;
+ const __m128i a_mask = _mm_set1_epi32(0xffu); // to preserve alpha
+ const __m128i all_0xff = _mm_set_epi32(0, 0, ~0u, ~0u);
+ __m128i all_alphas = all_0xff;
+
+ // We must be able to access 3 extra bytes after the last written byte
+ // 'src[4 * width - 4]', because we don't know if alpha is the first or the
+ // last byte of the quadruplet.
+ const int limit = (width - 1) & ~7;
+
+ for (j = 0; j < height; ++j) {
+ const __m128i* src = (const __m128i*)argb;
+ for (i = 0; i < limit; i += 8) {
+ // load 32 argb bytes
+ const __m128i a0 = _mm_loadu_si128(src + 0);
+ const __m128i a1 = _mm_loadu_si128(src + 1);
+ const __m128i b0 = _mm_and_si128(a0, a_mask);
+ const __m128i b1 = _mm_and_si128(a1, a_mask);
+ const __m128i c0 = _mm_packs_epi32(b0, b1);
+ const __m128i d0 = _mm_packus_epi16(c0, c0);
+ // store
+ _mm_storel_epi64((__m128i*)&alpha[i], d0);
+ // accumulate eight alpha 'and' in parallel
+ all_alphas = _mm_and_si128(all_alphas, d0);
+ src += 2;
+ }
+ for (; i < width; ++i) {
+ const uint32_t alpha_value = argb[4 * i];
+ alpha[i] = alpha_value;
+ alpha_and &= alpha_value;
+ }
+ argb += argb_stride;
+ alpha += alpha_stride;
+ }
+ // Combine the eight alpha 'and' into a 8-bit mask.
+ alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff));
+ return (alpha_and == 0xff);
+}
+
+//------------------------------------------------------------------------------
+// Non-dither premultiplied modes
+
+#define MULTIPLIER(a) ((a) * 0x8081)
+#define PREMULTIPLY(x, m) (((x) * (m)) >> 23)
+
+// We can't use a 'const int' for the SHUFFLE value, because it has to be an
+// immediate in the _mm_shufflexx_epi16() instruction. We really a macro here.
+#define APPLY_ALPHA(RGBX, SHUFFLE, MASK, MULT) do { \
+ const __m128i argb0 = _mm_loadl_epi64((__m128i*)&(RGBX)); \
+ const __m128i argb1 = _mm_unpacklo_epi8(argb0, zero); \
+ const __m128i alpha0 = _mm_and_si128(argb1, MASK); \
+ const __m128i alpha1 = _mm_shufflelo_epi16(alpha0, SHUFFLE); \
+ const __m128i alpha2 = _mm_shufflehi_epi16(alpha1, SHUFFLE); \
+ /* alpha2 = [0 a0 a0 a0][0 a1 a1 a1] */ \
+ const __m128i scale0 = _mm_mullo_epi16(alpha2, MULT); \
+ const __m128i scale1 = _mm_mulhi_epu16(alpha2, MULT); \
+ const __m128i argb2 = _mm_mulhi_epu16(argb1, scale0); \
+ const __m128i argb3 = _mm_mullo_epi16(argb1, scale1); \
+ const __m128i argb4 = _mm_adds_epu16(argb2, argb3); \
+ const __m128i argb5 = _mm_srli_epi16(argb4, 7); \
+ const __m128i argb6 = _mm_or_si128(argb5, alpha0); \
+ const __m128i argb7 = _mm_packus_epi16(argb6, zero); \
+ _mm_storel_epi64((__m128i*)&(RGBX), argb7); \
+} while (0)
+
+static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first,
+ int w, int h, int stride) {
+ const __m128i zero = _mm_setzero_si128();
+ const int kSpan = 2;
+ const int w2 = w & ~(kSpan - 1);
+ while (h-- > 0) {
+ uint32_t* const rgbx = (uint32_t*)rgba;
+ int i;
+ if (!alpha_first) {
+ const __m128i kMask = _mm_set_epi16(0xff, 0, 0, 0, 0xff, 0, 0, 0);
+ const __m128i kMult =
+ _mm_set_epi16(0, 0x8081, 0x8081, 0x8081, 0, 0x8081, 0x8081, 0x8081);
+ for (i = 0; i < w2; i += kSpan) {
+ APPLY_ALPHA(rgbx[i], _MM_SHUFFLE(0, 3, 3, 3), kMask, kMult);
+ }
+ } else {
+ const __m128i kMask = _mm_set_epi16(0, 0, 0, 0xff, 0, 0, 0, 0xff);
+ const __m128i kMult =
+ _mm_set_epi16(0x8081, 0x8081, 0x8081, 0, 0x8081, 0x8081, 0x8081, 0);
+ for (i = 0; i < w2; i += kSpan) {
+ APPLY_ALPHA(rgbx[i], _MM_SHUFFLE(0, 0, 0, 3), kMask, kMult);
+ }
+ }
+ // Finish with left-overs.
+ for (; i < w; ++i) {
+ uint8_t* const rgb = rgba + (alpha_first ? 1 : 0);
+ const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3);
+ const uint32_t a = alpha[4 * i];
+ if (a != 0xff) {
+ const uint32_t mult = MULTIPLIER(a);
+ rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult);
+ rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult);
+ rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult);
+ }
+ }
+ rgba += stride;
+ }
+}
+#undef MULTIPLIER
+#undef PREMULTIPLY
+
+// -----------------------------------------------------------------------------
+// Apply alpha value to rows
+
+// We use: kINV255 = (1 << 24) / 255 = 0x010101
+// So: a * kINV255 = (a << 16) | [(a << 8) | a]
+// -> _mm_mulhi_epu16() takes care of the (a<<16) part,
+// and _mm_mullo_epu16(a * 0x0101,...) takes care of the "(a << 8) | a" one.
+
+static void MultARGBRow(uint32_t* const ptr, int width, int inverse) {
+ int x = 0;
+ if (!inverse) {
+ const int kSpan = 2;
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i kRound =
+ _mm_set_epi16(0, 1 << 7, 1 << 7, 1 << 7, 0, 1 << 7, 1 << 7, 1 << 7);
+ const __m128i kMult =
+ _mm_set_epi16(0, 0x0101, 0x0101, 0x0101, 0, 0x0101, 0x0101, 0x0101);
+ const __m128i kOne64 = _mm_set_epi16(1u << 8, 0, 0, 0, 1u << 8, 0, 0, 0);
+ const int w2 = width & ~(kSpan - 1);
+ for (x = 0; x < w2; x += kSpan) {
+ const __m128i argb0 = _mm_loadl_epi64((__m128i*)&ptr[x]);
+ const __m128i argb1 = _mm_unpacklo_epi8(argb0, zero);
+ const __m128i tmp0 = _mm_shufflelo_epi16(argb1, _MM_SHUFFLE(3, 3, 3, 3));
+ const __m128i tmp1 = _mm_shufflehi_epi16(tmp0, _MM_SHUFFLE(3, 3, 3, 3));
+ const __m128i tmp2 = _mm_srli_epi64(tmp1, 16);
+ const __m128i scale0 = _mm_mullo_epi16(tmp1, kMult);
+ const __m128i scale1 = _mm_or_si128(tmp2, kOne64);
+ const __m128i argb2 = _mm_mulhi_epu16(argb1, scale0);
+ const __m128i argb3 = _mm_mullo_epi16(argb1, scale1);
+ const __m128i argb4 = _mm_adds_epu16(argb2, argb3);
+ const __m128i argb5 = _mm_adds_epu16(argb4, kRound);
+ const __m128i argb6 = _mm_srli_epi16(argb5, 8);
+ const __m128i argb7 = _mm_packus_epi16(argb6, zero);
+ _mm_storel_epi64((__m128i*)&ptr[x], argb7);
+ }
+ }
+ width -= x;
+ if (width > 0) WebPMultARGBRowC(ptr + x, width, inverse);
+}
+
+static void MultRow(uint8_t* const ptr, const uint8_t* const alpha,
+ int width, int inverse) {
+ int x = 0;
+ if (!inverse) {
+ const int kSpan = 8;
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i kRound = _mm_set1_epi16(1 << 7);
+ const int w2 = width & ~(kSpan - 1);
+ for (x = 0; x < w2; x += kSpan) {
+ const __m128i v0 = _mm_loadl_epi64((__m128i*)&ptr[x]);
+ const __m128i v1 = _mm_unpacklo_epi8(v0, zero);
+ const __m128i alpha0 = _mm_loadl_epi64((const __m128i*)&alpha[x]);
+ const __m128i alpha1 = _mm_unpacklo_epi8(alpha0, zero);
+ const __m128i alpha2 = _mm_unpacklo_epi8(alpha0, alpha0);
+ const __m128i v2 = _mm_mulhi_epu16(v1, alpha2);
+ const __m128i v3 = _mm_mullo_epi16(v1, alpha1);
+ const __m128i v4 = _mm_adds_epu16(v2, v3);
+ const __m128i v5 = _mm_adds_epu16(v4, kRound);
+ const __m128i v6 = _mm_srli_epi16(v5, 8);
+ const __m128i v7 = _mm_packus_epi16(v6, zero);
+ _mm_storel_epi64((__m128i*)&ptr[x], v7);
+ }
+ }
+ width -= x;
+ if (width > 0) WebPMultRowC(ptr + x, alpha + x, width, inverse);
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void WebPInitAlphaProcessingSSE2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE2(void) {
+ WebPMultARGBRow = MultARGBRow;
+ WebPMultRow = MultRow;
+ WebPApplyAlphaMultiply = ApplyAlphaMultiply;
+ WebPDispatchAlpha = DispatchAlpha;
+ WebPDispatchAlphaToGreen = DispatchAlphaToGreen;
+ WebPExtractAlpha = ExtractAlpha;
+}
+
+#else // !WEBP_USE_SSE2
+
+WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingSSE2)
+
+#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/alpha_processing_sse41.c b/drivers/webp/dsp/alpha_processing_sse41.c
new file mode 100644
index 0000000000..986fde94ed
--- /dev/null
+++ b/drivers/webp/dsp/alpha_processing_sse41.c
@@ -0,0 +1,92 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Utilities for processing transparent channel, SSE4.1 variant.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_SSE41)
+
+#include <smmintrin.h>
+
+//------------------------------------------------------------------------------
+
+static int ExtractAlpha(const uint8_t* argb, int argb_stride,
+ int width, int height,
+ uint8_t* alpha, int alpha_stride) {
+ // alpha_and stores an 'and' operation of all the alpha[] values. The final
+ // value is not 0xff if any of the alpha[] is not equal to 0xff.
+ uint32_t alpha_and = 0xff;
+ int i, j;
+ const __m128i all_0xff = _mm_set1_epi32(~0u);
+ __m128i all_alphas = all_0xff;
+
+ // We must be able to access 3 extra bytes after the last written byte
+ // 'src[4 * width - 4]', because we don't know if alpha is the first or the
+ // last byte of the quadruplet.
+ const int limit = (width - 1) & ~15;
+ const __m128i kCstAlpha0 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 12, 8, 4, 0);
+ const __m128i kCstAlpha1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1,
+ 12, 8, 4, 0, -1, -1, -1, -1);
+ const __m128i kCstAlpha2 = _mm_set_epi8(-1, -1, -1, -1, 12, 8, 4, 0,
+ -1, -1, -1, -1, -1, -1, -1, -1);
+ const __m128i kCstAlpha3 = _mm_set_epi8(12, 8, 4, 0, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1);
+ for (j = 0; j < height; ++j) {
+ const __m128i* src = (const __m128i*)argb;
+ for (i = 0; i < limit; i += 16) {
+ // load 64 argb bytes
+ const __m128i a0 = _mm_loadu_si128(src + 0);
+ const __m128i a1 = _mm_loadu_si128(src + 1);
+ const __m128i a2 = _mm_loadu_si128(src + 2);
+ const __m128i a3 = _mm_loadu_si128(src + 3);
+ const __m128i b0 = _mm_shuffle_epi8(a0, kCstAlpha0);
+ const __m128i b1 = _mm_shuffle_epi8(a1, kCstAlpha1);
+ const __m128i b2 = _mm_shuffle_epi8(a2, kCstAlpha2);
+ const __m128i b3 = _mm_shuffle_epi8(a3, kCstAlpha3);
+ const __m128i c0 = _mm_or_si128(b0, b1);
+ const __m128i c1 = _mm_or_si128(b2, b3);
+ const __m128i d0 = _mm_or_si128(c0, c1);
+ // store
+ _mm_storeu_si128((__m128i*)&alpha[i], d0);
+ // accumulate sixteen alpha 'and' in parallel
+ all_alphas = _mm_and_si128(all_alphas, d0);
+ src += 4;
+ }
+ for (; i < width; ++i) {
+ const uint32_t alpha_value = argb[4 * i];
+ alpha[i] = alpha_value;
+ alpha_and &= alpha_value;
+ }
+ argb += argb_stride;
+ alpha += alpha_stride;
+ }
+ // Combine the sixteen alpha 'and' into an 8-bit mask.
+ alpha_and |= 0xff00u; // pretend the upper bits [8..15] were tested ok.
+ alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff));
+ return (alpha_and == 0xffffu);
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void WebPInitAlphaProcessingSSE41(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE41(void) {
+ WebPExtractAlpha = ExtractAlpha;
+}
+
+#else // !WEBP_USE_SSE41
+
+WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingSSE41)
+
+#endif // WEBP_USE_SSE41
diff --git a/drivers/webp/dsp/argb.c b/drivers/webp/dsp/argb.c
new file mode 100644
index 0000000000..cc1f9a96c3
--- /dev/null
+++ b/drivers/webp/dsp/argb.c
@@ -0,0 +1,68 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// ARGB making functions.
+//
+// Author: Djordje Pesut (djordje.pesut@imgtec.com)
+
+#include "./dsp.h"
+
+static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) {
+ return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b);
+}
+
+static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g,
+ const uint8_t* b, int len, uint32_t* out) {
+ int i;
+ for (i = 0; i < len; ++i) {
+ out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]);
+ }
+}
+
+static void PackRGB(const uint8_t* r, const uint8_t* g, const uint8_t* b,
+ int len, int step, uint32_t* out) {
+ int i, offset = 0;
+ for (i = 0; i < len; ++i) {
+ out[i] = MakeARGB32(0xff, r[offset], g[offset], b[offset]);
+ offset += step;
+ }
+}
+
+void (*VP8PackARGB)(const uint8_t*, const uint8_t*, const uint8_t*,
+ const uint8_t*, int, uint32_t*);
+void (*VP8PackRGB)(const uint8_t*, const uint8_t*, const uint8_t*,
+ int, int, uint32_t*);
+
+extern void VP8EncDspARGBInitMIPSdspR2(void);
+extern void VP8EncDspARGBInitSSE2(void);
+
+static volatile VP8CPUInfo argb_last_cpuinfo_used =
+ (VP8CPUInfo)&argb_last_cpuinfo_used;
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInit(void) {
+ if (argb_last_cpuinfo_used == VP8GetCPUInfo) return;
+
+ VP8PackARGB = PackARGB;
+ VP8PackRGB = PackRGB;
+
+ // If defined, use CPUInfo() to overwrite some pointers with faster versions.
+ if (VP8GetCPUInfo != NULL) {
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ VP8EncDspARGBInitSSE2();
+ }
+#endif
+#if defined(WEBP_USE_MIPS_DSP_R2)
+ if (VP8GetCPUInfo(kMIPSdspR2)) {
+ VP8EncDspARGBInitMIPSdspR2();
+ }
+#endif
+ }
+ argb_last_cpuinfo_used = VP8GetCPUInfo;
+}
diff --git a/drivers/webp/dsp/argb_mips_dsp_r2.c b/drivers/webp/dsp/argb_mips_dsp_r2.c
new file mode 100644
index 0000000000..af65acb8ff
--- /dev/null
+++ b/drivers/webp/dsp/argb_mips_dsp_r2.c
@@ -0,0 +1,110 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// ARGB making functions (mips version).
+//
+// Author: Djordje Pesut (djordje.pesut@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS_DSP_R2)
+
+static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g,
+ const uint8_t* b, int len, uint32_t* out) {
+ int temp0, temp1, temp2, temp3, offset;
+ const int rest = len & 1;
+ const uint32_t* const loop_end = out + len - rest;
+ const int step = 4;
+ __asm__ volatile (
+ "xor %[offset], %[offset], %[offset] \n\t"
+ "beq %[loop_end], %[out], 0f \n\t"
+ "2: \n\t"
+ "lbux %[temp0], %[offset](%[a]) \n\t"
+ "lbux %[temp1], %[offset](%[r]) \n\t"
+ "lbux %[temp2], %[offset](%[g]) \n\t"
+ "lbux %[temp3], %[offset](%[b]) \n\t"
+ "ins %[temp1], %[temp0], 16, 16 \n\t"
+ "ins %[temp3], %[temp2], 16, 16 \n\t"
+ "addiu %[out], %[out], 4 \n\t"
+ "precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t"
+ "sw %[temp0], -4(%[out]) \n\t"
+ "addu %[offset], %[offset], %[step] \n\t"
+ "bne %[loop_end], %[out], 2b \n\t"
+ "0: \n\t"
+ "beq %[rest], $zero, 1f \n\t"
+ "lbux %[temp0], %[offset](%[a]) \n\t"
+ "lbux %[temp1], %[offset](%[r]) \n\t"
+ "lbux %[temp2], %[offset](%[g]) \n\t"
+ "lbux %[temp3], %[offset](%[b]) \n\t"
+ "ins %[temp1], %[temp0], 16, 16 \n\t"
+ "ins %[temp3], %[temp2], 16, 16 \n\t"
+ "precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t"
+ "sw %[temp0], 0(%[out]) \n\t"
+ "1: \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [offset]"=&r"(offset), [out]"+&r"(out)
+ : [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step),
+ [loop_end]"r"(loop_end), [rest]"r"(rest)
+ : "memory"
+ );
+}
+
+static void PackRGB(const uint8_t* r, const uint8_t* g, const uint8_t* b,
+ int len, int step, uint32_t* out) {
+ int temp0, temp1, temp2, offset;
+ const int rest = len & 1;
+ const int a = 0xff;
+ const uint32_t* const loop_end = out + len - rest;
+ __asm__ volatile (
+ "xor %[offset], %[offset], %[offset] \n\t"
+ "beq %[loop_end], %[out], 0f \n\t"
+ "2: \n\t"
+ "lbux %[temp0], %[offset](%[r]) \n\t"
+ "lbux %[temp1], %[offset](%[g]) \n\t"
+ "lbux %[temp2], %[offset](%[b]) \n\t"
+ "ins %[temp0], %[a], 16, 16 \n\t"
+ "ins %[temp2], %[temp1], 16, 16 \n\t"
+ "addiu %[out], %[out], 4 \n\t"
+ "precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t"
+ "sw %[temp0], -4(%[out]) \n\t"
+ "addu %[offset], %[offset], %[step] \n\t"
+ "bne %[loop_end], %[out], 2b \n\t"
+ "0: \n\t"
+ "beq %[rest], $zero, 1f \n\t"
+ "lbux %[temp0], %[offset](%[r]) \n\t"
+ "lbux %[temp1], %[offset](%[g]) \n\t"
+ "lbux %[temp2], %[offset](%[b]) \n\t"
+ "ins %[temp0], %[a], 16, 16 \n\t"
+ "ins %[temp2], %[temp1], 16, 16 \n\t"
+ "precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t"
+ "sw %[temp0], 0(%[out]) \n\t"
+ "1: \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [offset]"=&r"(offset), [out]"+&r"(out)
+ : [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step),
+ [loop_end]"r"(loop_end), [rest]"r"(rest)
+ : "memory"
+ );
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8EncDspARGBInitMIPSdspR2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInitMIPSdspR2(void) {
+ VP8PackARGB = PackARGB;
+ VP8PackRGB = PackRGB;
+}
+
+#else // !WEBP_USE_MIPS_DSP_R2
+
+WEBP_DSP_INIT_STUB(VP8EncDspARGBInitMIPSdspR2)
+
+#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/argb_sse2.c b/drivers/webp/dsp/argb_sse2.c
new file mode 100644
index 0000000000..afcb1957e7
--- /dev/null
+++ b/drivers/webp/dsp/argb_sse2.c
@@ -0,0 +1,67 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// ARGB making functions (SSE2 version).
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_SSE2)
+
+#include <assert.h>
+#include <emmintrin.h>
+#include <string.h>
+
+static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) {
+ return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b);
+}
+
+static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g,
+ const uint8_t* b, int len, uint32_t* out) {
+ if (g == r + 1) { // RGBA input order. Need to swap R and B.
+ int i = 0;
+ const int len_max = len & ~3; // max length processed in main loop
+ const __m128i red_blue_mask = _mm_set1_epi32(0x00ff00ffu);
+ assert(b == r + 2);
+ assert(a == r + 3);
+ for (; i < len_max; i += 4) {
+ const __m128i A = _mm_loadu_si128((const __m128i*)(r + 4 * i));
+ const __m128i B = _mm_and_si128(A, red_blue_mask); // R 0 B 0
+ const __m128i C = _mm_andnot_si128(red_blue_mask, A); // 0 G 0 A
+ const __m128i D = _mm_shufflelo_epi16(B, _MM_SHUFFLE(2, 3, 0, 1));
+ const __m128i E = _mm_shufflehi_epi16(D, _MM_SHUFFLE(2, 3, 0, 1));
+ const __m128i F = _mm_or_si128(E, C);
+ _mm_storeu_si128((__m128i*)(out + i), F);
+ }
+ for (; i < len; ++i) {
+ out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]);
+ }
+ } else {
+ assert(g == b + 1);
+ assert(r == b + 2);
+ assert(a == b + 3);
+ memcpy(out, b, len * 4);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8EncDspARGBInitSSE2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInitSSE2(void) {
+ VP8PackARGB = PackARGB;
+}
+
+#else // !WEBP_USE_SSE2
+
+WEBP_DSP_INIT_STUB(VP8EncDspARGBInitSSE2)
+
+#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/cost.c b/drivers/webp/dsp/cost.c
new file mode 100644
index 0000000000..fe72d26e79
--- /dev/null
+++ b/drivers/webp/dsp/cost.c
@@ -0,0 +1,412 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+#include "../enc/cost.h"
+
+//------------------------------------------------------------------------------
+// Boolean-cost cost table
+
+const uint16_t VP8EntropyCost[256] = {
+ 1792, 1792, 1792, 1536, 1536, 1408, 1366, 1280, 1280, 1216,
+ 1178, 1152, 1110, 1076, 1061, 1024, 1024, 992, 968, 951,
+ 939, 911, 896, 878, 871, 854, 838, 820, 811, 794,
+ 786, 768, 768, 752, 740, 732, 720, 709, 704, 690,
+ 683, 672, 666, 655, 647, 640, 631, 622, 615, 607,
+ 598, 592, 586, 576, 572, 564, 559, 555, 547, 541,
+ 534, 528, 522, 512, 512, 504, 500, 494, 488, 483,
+ 477, 473, 467, 461, 458, 452, 448, 443, 438, 434,
+ 427, 424, 419, 415, 410, 406, 403, 399, 394, 390,
+ 384, 384, 377, 374, 370, 366, 362, 359, 355, 351,
+ 347, 342, 342, 336, 333, 330, 326, 323, 320, 316,
+ 312, 308, 305, 302, 299, 296, 293, 288, 287, 283,
+ 280, 277, 274, 272, 268, 266, 262, 256, 256, 256,
+ 251, 248, 245, 242, 240, 237, 234, 232, 228, 226,
+ 223, 221, 218, 216, 214, 211, 208, 205, 203, 201,
+ 198, 196, 192, 191, 188, 187, 183, 181, 179, 176,
+ 175, 171, 171, 168, 165, 163, 160, 159, 156, 154,
+ 152, 150, 148, 146, 144, 142, 139, 138, 135, 133,
+ 131, 128, 128, 125, 123, 121, 119, 117, 115, 113,
+ 111, 110, 107, 105, 103, 102, 100, 98, 96, 94,
+ 92, 91, 89, 86, 86, 83, 82, 80, 77, 76,
+ 74, 73, 71, 69, 67, 66, 64, 63, 61, 59,
+ 57, 55, 54, 52, 51, 49, 47, 46, 44, 43,
+ 41, 40, 38, 36, 35, 33, 32, 30, 29, 27,
+ 25, 24, 22, 21, 19, 18, 16, 15, 13, 12,
+ 10, 9, 7, 6, 4, 3
+};
+
+//------------------------------------------------------------------------------
+// Level cost tables
+
+// fixed costs for coding levels, deduce from the coding tree.
+// This is only the part that doesn't depend on the probability state.
+const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1] = {
+ 0, 256, 256, 256, 256, 432, 618, 630,
+ 731, 640, 640, 828, 901, 948, 1021, 1101,
+ 1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202,
+ 1245, 1275, 1318, 1337, 1380, 1410, 1453, 1497,
+ 1540, 1570, 1613, 1280, 1295, 1317, 1332, 1358,
+ 1373, 1395, 1410, 1454, 1469, 1491, 1506, 1532,
+ 1547, 1569, 1584, 1601, 1616, 1638, 1653, 1679,
+ 1694, 1716, 1731, 1775, 1790, 1812, 1827, 1853,
+ 1868, 1890, 1905, 1727, 1733, 1742, 1748, 1759,
+ 1765, 1774, 1780, 1800, 1806, 1815, 1821, 1832,
+ 1838, 1847, 1853, 1878, 1884, 1893, 1899, 1910,
+ 1916, 1925, 1931, 1951, 1957, 1966, 1972, 1983,
+ 1989, 1998, 2004, 2027, 2033, 2042, 2048, 2059,
+ 2065, 2074, 2080, 2100, 2106, 2115, 2121, 2132,
+ 2138, 2147, 2153, 2178, 2184, 2193, 2199, 2210,
+ 2216, 2225, 2231, 2251, 2257, 2266, 2272, 2283,
+ 2289, 2298, 2304, 2168, 2174, 2183, 2189, 2200,
+ 2206, 2215, 2221, 2241, 2247, 2256, 2262, 2273,
+ 2279, 2288, 2294, 2319, 2325, 2334, 2340, 2351,
+ 2357, 2366, 2372, 2392, 2398, 2407, 2413, 2424,
+ 2430, 2439, 2445, 2468, 2474, 2483, 2489, 2500,
+ 2506, 2515, 2521, 2541, 2547, 2556, 2562, 2573,
+ 2579, 2588, 2594, 2619, 2625, 2634, 2640, 2651,
+ 2657, 2666, 2672, 2692, 2698, 2707, 2713, 2724,
+ 2730, 2739, 2745, 2540, 2546, 2555, 2561, 2572,
+ 2578, 2587, 2593, 2613, 2619, 2628, 2634, 2645,
+ 2651, 2660, 2666, 2691, 2697, 2706, 2712, 2723,
+ 2729, 2738, 2744, 2764, 2770, 2779, 2785, 2796,
+ 2802, 2811, 2817, 2840, 2846, 2855, 2861, 2872,
+ 2878, 2887, 2893, 2913, 2919, 2928, 2934, 2945,
+ 2951, 2960, 2966, 2991, 2997, 3006, 3012, 3023,
+ 3029, 3038, 3044, 3064, 3070, 3079, 3085, 3096,
+ 3102, 3111, 3117, 2981, 2987, 2996, 3002, 3013,
+ 3019, 3028, 3034, 3054, 3060, 3069, 3075, 3086,
+ 3092, 3101, 3107, 3132, 3138, 3147, 3153, 3164,
+ 3170, 3179, 3185, 3205, 3211, 3220, 3226, 3237,
+ 3243, 3252, 3258, 3281, 3287, 3296, 3302, 3313,
+ 3319, 3328, 3334, 3354, 3360, 3369, 3375, 3386,
+ 3392, 3401, 3407, 3432, 3438, 3447, 3453, 3464,
+ 3470, 3479, 3485, 3505, 3511, 3520, 3526, 3537,
+ 3543, 3552, 3558, 2816, 2822, 2831, 2837, 2848,
+ 2854, 2863, 2869, 2889, 2895, 2904, 2910, 2921,
+ 2927, 2936, 2942, 2967, 2973, 2982, 2988, 2999,
+ 3005, 3014, 3020, 3040, 3046, 3055, 3061, 3072,
+ 3078, 3087, 3093, 3116, 3122, 3131, 3137, 3148,
+ 3154, 3163, 3169, 3189, 3195, 3204, 3210, 3221,
+ 3227, 3236, 3242, 3267, 3273, 3282, 3288, 3299,
+ 3305, 3314, 3320, 3340, 3346, 3355, 3361, 3372,
+ 3378, 3387, 3393, 3257, 3263, 3272, 3278, 3289,
+ 3295, 3304, 3310, 3330, 3336, 3345, 3351, 3362,
+ 3368, 3377, 3383, 3408, 3414, 3423, 3429, 3440,
+ 3446, 3455, 3461, 3481, 3487, 3496, 3502, 3513,
+ 3519, 3528, 3534, 3557, 3563, 3572, 3578, 3589,
+ 3595, 3604, 3610, 3630, 3636, 3645, 3651, 3662,
+ 3668, 3677, 3683, 3708, 3714, 3723, 3729, 3740,
+ 3746, 3755, 3761, 3781, 3787, 3796, 3802, 3813,
+ 3819, 3828, 3834, 3629, 3635, 3644, 3650, 3661,
+ 3667, 3676, 3682, 3702, 3708, 3717, 3723, 3734,
+ 3740, 3749, 3755, 3780, 3786, 3795, 3801, 3812,
+ 3818, 3827, 3833, 3853, 3859, 3868, 3874, 3885,
+ 3891, 3900, 3906, 3929, 3935, 3944, 3950, 3961,
+ 3967, 3976, 3982, 4002, 4008, 4017, 4023, 4034,
+ 4040, 4049, 4055, 4080, 4086, 4095, 4101, 4112,
+ 4118, 4127, 4133, 4153, 4159, 4168, 4174, 4185,
+ 4191, 4200, 4206, 4070, 4076, 4085, 4091, 4102,
+ 4108, 4117, 4123, 4143, 4149, 4158, 4164, 4175,
+ 4181, 4190, 4196, 4221, 4227, 4236, 4242, 4253,
+ 4259, 4268, 4274, 4294, 4300, 4309, 4315, 4326,
+ 4332, 4341, 4347, 4370, 4376, 4385, 4391, 4402,
+ 4408, 4417, 4423, 4443, 4449, 4458, 4464, 4475,
+ 4481, 4490, 4496, 4521, 4527, 4536, 4542, 4553,
+ 4559, 4568, 4574, 4594, 4600, 4609, 4615, 4626,
+ 4632, 4641, 4647, 3515, 3521, 3530, 3536, 3547,
+ 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620,
+ 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698,
+ 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771,
+ 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847,
+ 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920,
+ 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998,
+ 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071,
+ 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988,
+ 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061,
+ 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139,
+ 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212,
+ 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288,
+ 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361,
+ 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439,
+ 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512,
+ 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360,
+ 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433,
+ 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511,
+ 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584,
+ 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660,
+ 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733,
+ 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811,
+ 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884,
+ 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801,
+ 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874,
+ 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952,
+ 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025,
+ 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101,
+ 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174,
+ 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252,
+ 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325,
+ 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636,
+ 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709,
+ 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787,
+ 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860,
+ 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936,
+ 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009,
+ 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087,
+ 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160,
+ 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077,
+ 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150,
+ 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228,
+ 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301,
+ 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377,
+ 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450,
+ 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528,
+ 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601,
+ 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449,
+ 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522,
+ 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600,
+ 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673,
+ 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749,
+ 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822,
+ 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900,
+ 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973,
+ 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890,
+ 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963,
+ 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041,
+ 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114,
+ 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190,
+ 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263,
+ 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341,
+ 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414,
+ 6420, 6429, 6435, 3515, 3521, 3530, 3536, 3547,
+ 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620,
+ 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698,
+ 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771,
+ 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847,
+ 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920,
+ 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998,
+ 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071,
+ 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988,
+ 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061,
+ 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139,
+ 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212,
+ 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288,
+ 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361,
+ 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439,
+ 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512,
+ 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360,
+ 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433,
+ 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511,
+ 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584,
+ 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660,
+ 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733,
+ 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811,
+ 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884,
+ 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801,
+ 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874,
+ 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952,
+ 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025,
+ 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101,
+ 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174,
+ 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252,
+ 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325,
+ 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636,
+ 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709,
+ 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787,
+ 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860,
+ 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936,
+ 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009,
+ 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087,
+ 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160,
+ 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077,
+ 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150,
+ 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228,
+ 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301,
+ 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377,
+ 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450,
+ 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528,
+ 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601,
+ 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449,
+ 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522,
+ 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600,
+ 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673,
+ 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749,
+ 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822,
+ 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900,
+ 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973,
+ 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890,
+ 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963,
+ 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041,
+ 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114,
+ 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190,
+ 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263,
+ 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341,
+ 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414,
+ 6420, 6429, 6435, 5303, 5309, 5318, 5324, 5335,
+ 5341, 5350, 5356, 5376, 5382, 5391, 5397, 5408,
+ 5414, 5423, 5429, 5454, 5460, 5469, 5475, 5486,
+ 5492, 5501, 5507, 5527, 5533, 5542, 5548, 5559,
+ 5565, 5574, 5580, 5603, 5609, 5618, 5624, 5635,
+ 5641, 5650, 5656, 5676, 5682, 5691, 5697, 5708,
+ 5714, 5723, 5729, 5754, 5760, 5769, 5775, 5786,
+ 5792, 5801, 5807, 5827, 5833, 5842, 5848, 5859,
+ 5865, 5874, 5880, 5744, 5750, 5759, 5765, 5776,
+ 5782, 5791, 5797, 5817, 5823, 5832, 5838, 5849,
+ 5855, 5864, 5870, 5895, 5901, 5910, 5916, 5927,
+ 5933, 5942, 5948, 5968, 5974, 5983, 5989, 6000,
+ 6006, 6015, 6021, 6044, 6050, 6059, 6065, 6076,
+ 6082, 6091, 6097, 6117, 6123, 6132, 6138, 6149,
+ 6155, 6164, 6170, 6195, 6201, 6210, 6216, 6227,
+ 6233, 6242, 6248, 6268, 6274, 6283, 6289, 6300,
+ 6306, 6315, 6321, 6116, 6122, 6131, 6137, 6148,
+ 6154, 6163, 6169, 6189, 6195, 6204, 6210, 6221,
+ 6227, 6236, 6242, 6267, 6273, 6282, 6288, 6299,
+ 6305, 6314, 6320, 6340, 6346, 6355, 6361, 6372,
+ 6378, 6387, 6393, 6416, 6422, 6431, 6437, 6448,
+ 6454, 6463, 6469, 6489, 6495, 6504, 6510, 6521,
+ 6527, 6536, 6542, 6567, 6573, 6582, 6588, 6599,
+ 6605, 6614, 6620, 6640, 6646, 6655, 6661, 6672,
+ 6678, 6687, 6693, 6557, 6563, 6572, 6578, 6589,
+ 6595, 6604, 6610, 6630, 6636, 6645, 6651, 6662,
+ 6668, 6677, 6683, 6708, 6714, 6723, 6729, 6740,
+ 6746, 6755, 6761, 6781, 6787, 6796, 6802, 6813,
+ 6819, 6828, 6834, 6857, 6863, 6872, 6878, 6889,
+ 6895, 6904, 6910, 6930, 6936, 6945, 6951, 6962,
+ 6968, 6977, 6983, 7008, 7014, 7023, 7029, 7040,
+ 7046, 7055, 7061, 7081, 7087, 7096, 7102, 7113,
+ 7119, 7128, 7134, 6392, 6398, 6407, 6413, 6424,
+ 6430, 6439, 6445, 6465, 6471, 6480, 6486, 6497,
+ 6503, 6512, 6518, 6543, 6549, 6558, 6564, 6575,
+ 6581, 6590, 6596, 6616, 6622, 6631, 6637, 6648,
+ 6654, 6663, 6669, 6692, 6698, 6707, 6713, 6724,
+ 6730, 6739, 6745, 6765, 6771, 6780, 6786, 6797,
+ 6803, 6812, 6818, 6843, 6849, 6858, 6864, 6875,
+ 6881, 6890, 6896, 6916, 6922, 6931, 6937, 6948,
+ 6954, 6963, 6969, 6833, 6839, 6848, 6854, 6865,
+ 6871, 6880, 6886, 6906, 6912, 6921, 6927, 6938,
+ 6944, 6953, 6959, 6984, 6990, 6999, 7005, 7016,
+ 7022, 7031, 7037, 7057, 7063, 7072, 7078, 7089,
+ 7095, 7104, 7110, 7133, 7139, 7148, 7154, 7165,
+ 7171, 7180, 7186, 7206, 7212, 7221, 7227, 7238,
+ 7244, 7253, 7259, 7284, 7290, 7299, 7305, 7316,
+ 7322, 7331, 7337, 7357, 7363, 7372, 7378, 7389,
+ 7395, 7404, 7410, 7205, 7211, 7220, 7226, 7237,
+ 7243, 7252, 7258, 7278, 7284, 7293, 7299, 7310,
+ 7316, 7325, 7331, 7356, 7362, 7371, 7377, 7388,
+ 7394, 7403, 7409, 7429, 7435, 7444, 7450, 7461,
+ 7467, 7476, 7482, 7505, 7511, 7520, 7526, 7537,
+ 7543, 7552, 7558, 7578, 7584, 7593, 7599, 7610,
+ 7616, 7625, 7631, 7656, 7662, 7671, 7677, 7688,
+ 7694, 7703, 7709, 7729, 7735, 7744, 7750, 7761
+};
+
+//------------------------------------------------------------------------------
+// Tables for level coding
+
+const uint8_t VP8EncBands[16 + 1] = {
+ 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
+ 0 // sentinel
+};
+
+//------------------------------------------------------------------------------
+// Mode costs
+
+static int GetResidualCost(int ctx0, const VP8Residual* const res) {
+ int n = res->first;
+ // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
+ const int p0 = res->prob[n][ctx0][0];
+ CostArrayPtr const costs = res->costs;
+ const uint16_t* t = costs[n][ctx0];
+ // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0
+ // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll
+ // be missing during the loop.
+ int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0;
+
+ if (res->last < 0) {
+ return VP8BitCost(0, p0);
+ }
+ for (; n < res->last; ++n) {
+ const int v = abs(res->coeffs[n]);
+ const int ctx = (v >= 2) ? 2 : v;
+ cost += VP8LevelCost(t, v);
+ t = costs[n + 1][ctx];
+ }
+ // Last coefficient is always non-zero
+ {
+ const int v = abs(res->coeffs[n]);
+ assert(v != 0);
+ cost += VP8LevelCost(t, v);
+ if (n < 15) {
+ const int b = VP8EncBands[n + 1];
+ const int ctx = (v == 1) ? 1 : 2;
+ const int last_p0 = res->prob[b][ctx][0];
+ cost += VP8BitCost(0, last_p0);
+ }
+ }
+ return cost;
+}
+
+static void SetResidualCoeffs(const int16_t* const coeffs,
+ VP8Residual* const res) {
+ int n;
+ res->last = -1;
+ assert(res->first == 0 || coeffs[0] == 0);
+ for (n = 15; n >= 0; --n) {
+ if (coeffs[n]) {
+ res->last = n;
+ break;
+ }
+ }
+ res->coeffs = coeffs;
+}
+
+//------------------------------------------------------------------------------
+// init function
+
+VP8GetResidualCostFunc VP8GetResidualCost;
+VP8SetResidualCoeffsFunc VP8SetResidualCoeffs;
+
+extern void VP8EncDspCostInitMIPS32(void);
+extern void VP8EncDspCostInitMIPSdspR2(void);
+extern void VP8EncDspCostInitSSE2(void);
+
+static volatile VP8CPUInfo cost_last_cpuinfo_used =
+ (VP8CPUInfo)&cost_last_cpuinfo_used;
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInit(void) {
+ if (cost_last_cpuinfo_used == VP8GetCPUInfo) return;
+
+ VP8GetResidualCost = GetResidualCost;
+ VP8SetResidualCoeffs = SetResidualCoeffs;
+
+ // If defined, use CPUInfo() to overwrite some pointers with faster versions.
+ if (VP8GetCPUInfo != NULL) {
+#if defined(WEBP_USE_MIPS32)
+ if (VP8GetCPUInfo(kMIPS32)) {
+ VP8EncDspCostInitMIPS32();
+ }
+#endif
+#if defined(WEBP_USE_MIPS_DSP_R2)
+ if (VP8GetCPUInfo(kMIPSdspR2)) {
+ VP8EncDspCostInitMIPSdspR2();
+ }
+#endif
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ VP8EncDspCostInitSSE2();
+ }
+#endif
+ }
+
+ cost_last_cpuinfo_used = VP8GetCPUInfo;
+}
+
+//------------------------------------------------------------------------------
diff --git a/drivers/webp/dsp/cost_mips32.c b/drivers/webp/dsp/cost_mips32.c
new file mode 100644
index 0000000000..d1e240e191
--- /dev/null
+++ b/drivers/webp/dsp/cost_mips32.c
@@ -0,0 +1,154 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Author: Djordje Pesut (djordje.pesut@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS32)
+
+#include "../enc/cost.h"
+
+static int GetResidualCost(int ctx0, const VP8Residual* const res) {
+ int temp0, temp1;
+ int v_reg, ctx_reg;
+ int n = res->first;
+ // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
+ int p0 = res->prob[n][ctx0][0];
+ CostArrayPtr const costs = res->costs;
+ const uint16_t* t = costs[n][ctx0];
+ // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0
+ // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll
+ // be missing during the loop.
+ int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0;
+ const int16_t* res_coeffs = res->coeffs;
+ const int res_last = res->last;
+ const int const_max_level = MAX_VARIABLE_LEVEL;
+ const int const_2 = 2;
+ const uint16_t** p_costs = &costs[n][0];
+ const size_t inc_p_costs = NUM_CTX * sizeof(*p_costs);
+
+ if (res->last < 0) {
+ return VP8BitCost(0, p0);
+ }
+
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "subu %[temp1], %[res_last], %[n] \n\t"
+ "sll %[temp0], %[n], 1 \n\t"
+ "blez %[temp1], 2f \n\t"
+ " addu %[res_coeffs], %[res_coeffs], %[temp0] \n\t"
+ "1: \n\t"
+ "lh %[v_reg], 0(%[res_coeffs]) \n\t"
+ "addiu %[n], %[n], 1 \n\t"
+ "negu %[temp0], %[v_reg] \n\t"
+ "slti %[temp1], %[v_reg], 0 \n\t"
+ "movn %[v_reg], %[temp0], %[temp1] \n\t"
+ "sltiu %[temp0], %[v_reg], 2 \n\t"
+ "move %[ctx_reg], %[v_reg] \n\t"
+ "movz %[ctx_reg], %[const_2], %[temp0] \n\t"
+ "sll %[temp1], %[v_reg], 1 \n\t"
+ "addu %[temp1], %[temp1], %[VP8LevelFixedCosts] \n\t"
+ "lhu %[temp1], 0(%[temp1]) \n\t"
+ "slt %[temp0], %[v_reg], %[const_max_level] \n\t"
+ "movz %[v_reg], %[const_max_level], %[temp0] \n\t"
+ "addu %[cost], %[cost], %[temp1] \n\t"
+ "sll %[v_reg], %[v_reg], 1 \n\t"
+ "sll %[ctx_reg], %[ctx_reg], 2 \n\t"
+ "addu %[v_reg], %[v_reg], %[t] \n\t"
+ "lhu %[temp0], 0(%[v_reg]) \n\t"
+ "addu %[p_costs], %[p_costs], %[inc_p_costs] \n\t"
+ "addu %[t], %[p_costs], %[ctx_reg] \n\t"
+ "addu %[cost], %[cost], %[temp0] \n\t"
+ "addiu %[res_coeffs], %[res_coeffs], 2 \n\t"
+ "bne %[n], %[res_last], 1b \n\t"
+ " lw %[t], 0(%[t]) \n\t"
+ "2: \n\t"
+ ".set pop \n\t"
+ : [cost]"+&r"(cost), [t]"+&r"(t), [n]"+&r"(n), [v_reg]"=&r"(v_reg),
+ [ctx_reg]"=&r"(ctx_reg), [p_costs]"+&r"(p_costs), [temp0]"=&r"(temp0),
+ [temp1]"=&r"(temp1), [res_coeffs]"+&r"(res_coeffs)
+ : [const_2]"r"(const_2), [const_max_level]"r"(const_max_level),
+ [VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_last]"r"(res_last),
+ [inc_p_costs]"r"(inc_p_costs)
+ : "memory"
+ );
+
+ // Last coefficient is always non-zero
+ {
+ const int v = abs(res->coeffs[n]);
+ assert(v != 0);
+ cost += VP8LevelCost(t, v);
+ if (n < 15) {
+ const int b = VP8EncBands[n + 1];
+ const int ctx = (v == 1) ? 1 : 2;
+ const int last_p0 = res->prob[b][ctx][0];
+ cost += VP8BitCost(0, last_p0);
+ }
+ }
+ return cost;
+}
+
+static void SetResidualCoeffs(const int16_t* const coeffs,
+ VP8Residual* const res) {
+ const int16_t* p_coeffs = (int16_t*)coeffs;
+ int temp0, temp1, temp2, n, n1;
+ assert(res->first == 0 || coeffs[0] == 0);
+
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "addiu %[p_coeffs], %[p_coeffs], 28 \n\t"
+ "li %[n], 15 \n\t"
+ "li %[temp2], -1 \n\t"
+ "0: \n\t"
+ "ulw %[temp0], 0(%[p_coeffs]) \n\t"
+ "beqz %[temp0], 1f \n\t"
+#if defined(WORDS_BIGENDIAN)
+ " sll %[temp1], %[temp0], 16 \n\t"
+#else
+ " srl %[temp1], %[temp0], 16 \n\t"
+#endif
+ "addiu %[n1], %[n], -1 \n\t"
+ "movz %[temp0], %[n1], %[temp1] \n\t"
+ "movn %[temp0], %[n], %[temp1] \n\t"
+ "j 2f \n\t"
+ " addiu %[temp2], %[temp0], 0 \n\t"
+ "1: \n\t"
+ "addiu %[n], %[n], -2 \n\t"
+ "bgtz %[n], 0b \n\t"
+ " addiu %[p_coeffs], %[p_coeffs], -4 \n\t"
+ "2: \n\t"
+ ".set pop \n\t"
+ : [p_coeffs]"+&r"(p_coeffs), [temp0]"=&r"(temp0),
+ [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [n]"=&r"(n), [n1]"=&r"(n1)
+ :
+ : "memory"
+ );
+ res->last = temp2;
+ res->coeffs = coeffs;
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8EncDspCostInitMIPS32(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitMIPS32(void) {
+ VP8GetResidualCost = GetResidualCost;
+ VP8SetResidualCoeffs = SetResidualCoeffs;
+}
+
+#else // !WEBP_USE_MIPS32
+
+WEBP_DSP_INIT_STUB(VP8EncDspCostInitMIPS32)
+
+#endif // WEBP_USE_MIPS32
diff --git a/drivers/webp/dsp/cost_mips_dsp_r2.c b/drivers/webp/dsp/cost_mips_dsp_r2.c
new file mode 100644
index 0000000000..ce64067756
--- /dev/null
+++ b/drivers/webp/dsp/cost_mips_dsp_r2.c
@@ -0,0 +1,107 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Author: Djordje Pesut (djordje.pesut@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS_DSP_R2)
+
+#include "../enc/cost.h"
+
+static int GetResidualCost(int ctx0, const VP8Residual* const res) {
+ int temp0, temp1;
+ int v_reg, ctx_reg;
+ int n = res->first;
+ // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
+ int p0 = res->prob[n][ctx0][0];
+ CostArrayPtr const costs = res->costs;
+ const uint16_t* t = costs[n][ctx0];
+ // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0
+ // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll
+ // be missing during the loop.
+ int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0;
+ const int16_t* res_coeffs = res->coeffs;
+ const int res_last = res->last;
+ const int const_max_level = MAX_VARIABLE_LEVEL;
+ const int const_2 = 2;
+ const uint16_t** p_costs = &costs[n][0];
+ const size_t inc_p_costs = NUM_CTX * sizeof(*p_costs);
+
+ if (res->last < 0) {
+ return VP8BitCost(0, p0);
+ }
+
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "subu %[temp1], %[res_last], %[n] \n\t"
+ "blez %[temp1], 2f \n\t"
+ " nop \n\t"
+ "1: \n\t"
+ "sll %[temp0], %[n], 1 \n\t"
+ "lhx %[v_reg], %[temp0](%[res_coeffs]) \n\t"
+ "addiu %[n], %[n], 1 \n\t"
+ "absq_s.w %[v_reg], %[v_reg] \n\t"
+ "sltiu %[temp0], %[v_reg], 2 \n\t"
+ "move %[ctx_reg], %[v_reg] \n\t"
+ "movz %[ctx_reg], %[const_2], %[temp0] \n\t"
+ "sll %[temp1], %[v_reg], 1 \n\t"
+ "lhx %[temp1], %[temp1](%[VP8LevelFixedCosts]) \n\t"
+ "slt %[temp0], %[v_reg], %[const_max_level] \n\t"
+ "movz %[v_reg], %[const_max_level], %[temp0] \n\t"
+ "addu %[cost], %[cost], %[temp1] \n\t"
+ "sll %[v_reg], %[v_reg], 1 \n\t"
+ "sll %[ctx_reg], %[ctx_reg], 2 \n\t"
+ "lhx %[temp0], %[v_reg](%[t]) \n\t"
+ "addu %[p_costs], %[p_costs], %[inc_p_costs] \n\t"
+ "addu %[t], %[p_costs], %[ctx_reg] \n\t"
+ "addu %[cost], %[cost], %[temp0] \n\t"
+ "bne %[n], %[res_last], 1b \n\t"
+ " lw %[t], 0(%[t]) \n\t"
+ "2: \n\t"
+ ".set pop \n\t"
+ : [cost]"+&r"(cost), [t]"+&r"(t), [n]"+&r"(n), [v_reg]"=&r"(v_reg),
+ [ctx_reg]"=&r"(ctx_reg), [p_costs]"+&r"(p_costs), [temp0]"=&r"(temp0),
+ [temp1]"=&r"(temp1)
+ : [const_2]"r"(const_2), [const_max_level]"r"(const_max_level),
+ [VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_last]"r"(res_last),
+ [res_coeffs]"r"(res_coeffs), [inc_p_costs]"r"(inc_p_costs)
+ : "memory"
+ );
+
+ // Last coefficient is always non-zero
+ {
+ const int v = abs(res->coeffs[n]);
+ assert(v != 0);
+ cost += VP8LevelCost(t, v);
+ if (n < 15) {
+ const int b = VP8EncBands[n + 1];
+ const int ctx = (v == 1) ? 1 : 2;
+ const int last_p0 = res->prob[b][ctx][0];
+ cost += VP8BitCost(0, last_p0);
+ }
+ }
+ return cost;
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8EncDspCostInitMIPSdspR2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitMIPSdspR2(void) {
+ VP8GetResidualCost = GetResidualCost;
+}
+
+#else // !WEBP_USE_MIPS_DSP_R2
+
+WEBP_DSP_INIT_STUB(VP8EncDspCostInitMIPSdspR2)
+
+#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/cost_sse2.c b/drivers/webp/dsp/cost_sse2.c
new file mode 100644
index 0000000000..0cb1c1fa04
--- /dev/null
+++ b/drivers/webp/dsp/cost_sse2.c
@@ -0,0 +1,119 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// SSE2 version of cost functions
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_SSE2)
+#include <emmintrin.h>
+
+#include "../enc/cost.h"
+#include "../enc/vp8enci.h"
+#include "../utils/utils.h"
+
+//------------------------------------------------------------------------------
+
+static void SetResidualCoeffsSSE2(const int16_t* const coeffs,
+ VP8Residual* const res) {
+ const __m128i c0 = _mm_loadu_si128((const __m128i*)(coeffs + 0));
+ const __m128i c1 = _mm_loadu_si128((const __m128i*)(coeffs + 8));
+ // Use SSE2 to compare 16 values with a single instruction.
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i m0 = _mm_packs_epi16(c0, c1);
+ const __m128i m1 = _mm_cmpeq_epi8(m0, zero);
+ // Get the comparison results as a bitmask into 16bits. Negate the mask to get
+ // the position of entries that are not equal to zero. We don't need to mask
+ // out least significant bits according to res->first, since coeffs[0] is 0
+ // if res->first > 0.
+ const uint32_t mask = 0x0000ffffu ^ (uint32_t)_mm_movemask_epi8(m1);
+ // The position of the most significant non-zero bit indicates the position of
+ // the last non-zero value.
+ assert(res->first == 0 || coeffs[0] == 0);
+ res->last = mask ? BitsLog2Floor(mask) : -1;
+ res->coeffs = coeffs;
+}
+
+static int GetResidualCostSSE2(int ctx0, const VP8Residual* const res) {
+ uint8_t levels[16], ctxs[16];
+ uint16_t abs_levels[16];
+ int n = res->first;
+ // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
+ const int p0 = res->prob[n][ctx0][0];
+ CostArrayPtr const costs = res->costs;
+ const uint16_t* t = costs[n][ctx0];
+ // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0
+ // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll
+ // be missing during the loop.
+ int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0;
+
+ if (res->last < 0) {
+ return VP8BitCost(0, p0);
+ }
+
+ { // precompute clamped levels and contexts, packed to 8b.
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i kCst2 = _mm_set1_epi8(2);
+ const __m128i kCst67 = _mm_set1_epi8(MAX_VARIABLE_LEVEL);
+ const __m128i c0 = _mm_loadu_si128((const __m128i*)&res->coeffs[0]);
+ const __m128i c1 = _mm_loadu_si128((const __m128i*)&res->coeffs[8]);
+ const __m128i D0 = _mm_sub_epi16(zero, c0);
+ const __m128i D1 = _mm_sub_epi16(zero, c1);
+ const __m128i E0 = _mm_max_epi16(c0, D0); // abs(v), 16b
+ const __m128i E1 = _mm_max_epi16(c1, D1);
+ const __m128i F = _mm_packs_epi16(E0, E1);
+ const __m128i G = _mm_min_epu8(F, kCst2); // context = 0,1,2
+ const __m128i H = _mm_min_epu8(F, kCst67); // clamp_level in [0..67]
+
+ _mm_storeu_si128((__m128i*)&ctxs[0], G);
+ _mm_storeu_si128((__m128i*)&levels[0], H);
+
+ _mm_storeu_si128((__m128i*)&abs_levels[0], E0);
+ _mm_storeu_si128((__m128i*)&abs_levels[8], E1);
+ }
+ for (; n < res->last; ++n) {
+ const int ctx = ctxs[n];
+ const int level = levels[n];
+ const int flevel = abs_levels[n]; // full level
+ cost += VP8LevelFixedCosts[flevel] + t[level]; // simplified VP8LevelCost()
+ t = costs[n + 1][ctx];
+ }
+ // Last coefficient is always non-zero
+ {
+ const int level = levels[n];
+ const int flevel = abs_levels[n];
+ assert(flevel != 0);
+ cost += VP8LevelFixedCosts[flevel] + t[level];
+ if (n < 15) {
+ const int b = VP8EncBands[n + 1];
+ const int ctx = ctxs[n];
+ const int last_p0 = res->prob[b][ctx][0];
+ cost += VP8BitCost(0, last_p0);
+ }
+ }
+ return cost;
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8EncDspCostInitSSE2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitSSE2(void) {
+ VP8SetResidualCoeffs = SetResidualCoeffsSSE2;
+ VP8GetResidualCost = GetResidualCostSSE2;
+}
+
+#else // !WEBP_USE_SSE2
+
+WEBP_DSP_INIT_STUB(VP8EncDspCostInitSSE2)
+
+#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/cpu.c b/drivers/webp/dsp/cpu.c
index 0228734457..35c2af7f58 100644
--- a/drivers/webp/dsp/cpu.c
+++ b/drivers/webp/dsp/cpu.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// CPU detection
@@ -11,14 +13,10 @@
#include "./dsp.h"
-#if defined(__ANDROID__)
+#if defined(WEBP_ANDROID_NEON)
#include <cpu-features.h>
#endif
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
//------------------------------------------------------------------------------
// SSE2 detection.
//
@@ -31,22 +29,66 @@ static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
"cpuid\n"
"xchg %%edi, %%ebx\n"
: "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
- : "a"(info_type));
+ : "a"(info_type), "c"(0));
}
#elif defined(__i386__) || defined(__x86_64__)
static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
__asm__ volatile (
"cpuid\n"
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
- : "a"(info_type));
+ : "a"(info_type), "c"(0));
}
+#elif (defined(_M_X64) || defined(_M_IX86)) && \
+ defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1
+#include <intrin.h>
+#define GetCPUInfo(info, type) __cpuidex(info, type, 0) // set ecx=0
#elif defined(WEBP_MSC_SSE2)
#define GetCPUInfo __cpuid
#endif
+// NaCl has no support for xgetbv or the raw opcode.
+#if !defined(__native_client__) && (defined(__i386__) || defined(__x86_64__))
+static WEBP_INLINE uint64_t xgetbv(void) {
+ const uint32_t ecx = 0;
+ uint32_t eax, edx;
+ // Use the raw opcode for xgetbv for compatibility with older toolchains.
+ __asm__ volatile (
+ ".byte 0x0f, 0x01, 0xd0\n"
+ : "=a"(eax), "=d"(edx) : "c" (ecx));
+ return ((uint64_t)edx << 32) | eax;
+}
+#elif (defined(_M_X64) || defined(_M_IX86)) && \
+ defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1
+#include <immintrin.h>
+#define xgetbv() _xgetbv(0)
+#elif defined(_MSC_VER) && defined(_M_IX86)
+static WEBP_INLINE uint64_t xgetbv(void) {
+ uint32_t eax_, edx_;
+ __asm {
+ xor ecx, ecx // ecx = 0
+ // Use the raw opcode for xgetbv for compatibility with older toolchains.
+ __asm _emit 0x0f __asm _emit 0x01 __asm _emit 0xd0
+ mov eax_, eax
+ mov edx_, edx
+ }
+ return ((uint64_t)edx_ << 32) | eax_;
+}
+#else
+#define xgetbv() 0U // no AVX for older x64 or unrecognized toolchains.
+#endif
+
#if defined(__i386__) || defined(__x86_64__) || defined(WEBP_MSC_SSE2)
static int x86CPUInfo(CPUFeature feature) {
+ int max_cpuid_value;
int cpu_info[4];
+
+ // get the highest feature value cpuid supports
+ GetCPUInfo(cpu_info, 0);
+ max_cpuid_value = cpu_info[0];
+ if (max_cpuid_value < 1) {
+ return 0;
+ }
+
GetCPUInfo(cpu_info, 1);
if (feature == kSSE2) {
return 0 != (cpu_info[3] & 0x04000000);
@@ -54,10 +96,26 @@ static int x86CPUInfo(CPUFeature feature) {
if (feature == kSSE3) {
return 0 != (cpu_info[2] & 0x00000001);
}
+ if (feature == kSSE4_1) {
+ return 0 != (cpu_info[2] & 0x00080000);
+ }
+ if (feature == kAVX) {
+ // bits 27 (OSXSAVE) & 28 (256-bit AVX)
+ if ((cpu_info[2] & 0x18000000) == 0x18000000) {
+ // XMM state and YMM state enabled by the OS.
+ return (xgetbv() & 0x6) == 0x6;
+ }
+ }
+ if (feature == kAVX2) {
+ if (x86CPUInfo(kAVX) && max_cpuid_value >= 7) {
+ GetCPUInfo(cpu_info, 7);
+ return ((cpu_info[1] & 0x00000020) == 0x00000020);
+ }
+ }
return 0;
}
VP8CPUInfo VP8GetCPUInfo = x86CPUInfo;
-#elif defined(WEBP_ANDROID_NEON)
+#elif defined(WEBP_ANDROID_NEON) // NB: needs to be before generic NEON test.
static int AndroidCPUInfo(CPUFeature feature) {
const AndroidCpuFamily cpu_family = android_getCpuFamily();
const uint64_t cpu_features = android_getCpuFeatures();
@@ -68,7 +126,7 @@ static int AndroidCPUInfo(CPUFeature feature) {
return 0;
}
VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo;
-#elif defined(__ARM_NEON__)
+#elif defined(WEBP_USE_NEON)
// define a dummy function to enable turning off NEON at runtime by setting
// VP8DecGetCPUInfo = NULL
static int armCPUInfo(CPUFeature feature) {
@@ -76,10 +134,17 @@ static int armCPUInfo(CPUFeature feature) {
return 1;
}
VP8CPUInfo VP8GetCPUInfo = armCPUInfo;
+#elif defined(WEBP_USE_MIPS32) || defined(WEBP_USE_MIPS_DSP_R2)
+static int mipsCPUInfo(CPUFeature feature) {
+ if ((feature == kMIPS32) || (feature == kMIPSdspR2)) {
+ return 1;
+ } else {
+ return 0;
+ }
+
+}
+VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo;
#else
VP8CPUInfo VP8GetCPUInfo = NULL;
#endif
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/dsp/dec.c b/drivers/webp/dsp/dec.c
index 9ae7b6fa76..77a00381c5 100644
--- a/drivers/webp/dsp/dec.c
+++ b/drivers/webp/dsp/dec.c
@@ -1,53 +1,20 @@
// Copyright 2010 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
-// Speed-critical decoding functions.
+// Speed-critical decoding functions, default plain-C implementations.
//
// Author: Skal (pascal.massimino@gmail.com)
#include "./dsp.h"
#include "../dec/vp8i.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
//------------------------------------------------------------------------------
-// run-time tables (~4k)
-
-static uint8_t abs0[255 + 255 + 1]; // abs(i)
-static uint8_t abs1[255 + 255 + 1]; // abs(i)>>1
-static int8_t sclip1[1020 + 1020 + 1]; // clips [-1020, 1020] to [-128, 127]
-static int8_t sclip2[112 + 112 + 1]; // clips [-112, 112] to [-16, 15]
-static uint8_t clip1[255 + 510 + 1]; // clips [-255,510] to [0,255]
-
-// We declare this variable 'volatile' to prevent instruction reordering
-// and make sure it's set to true _last_ (so as to be thread-safe)
-static volatile int tables_ok = 0;
-
-static void DspInitTables(void) {
- if (!tables_ok) {
- int i;
- for (i = -255; i <= 255; ++i) {
- abs0[255 + i] = (i < 0) ? -i : i;
- abs1[255 + i] = abs0[255 + i] >> 1;
- }
- for (i = -1020; i <= 1020; ++i) {
- sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i;
- }
- for (i = -112; i <= 112; ++i) {
- sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i;
- }
- for (i = -255; i <= 255 + 255; ++i) {
- clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i;
- }
- tables_ok = 1;
- }
-}
static WEBP_INLINE uint8_t clip_8b(int v) {
return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255;
@@ -59,9 +26,16 @@ static WEBP_INLINE uint8_t clip_8b(int v) {
#define STORE(x, y, v) \
dst[x + y * BPS] = clip_8b(dst[x + y * BPS] + ((v) >> 3))
-static const int kC1 = 20091 + (1 << 16);
-static const int kC2 = 35468;
-#define MUL(a, b) (((a) * (b)) >> 16)
+#define STORE2(y, dc, d, c) do { \
+ const int DC = (dc); \
+ STORE(0, y, DC + (d)); \
+ STORE(1, y, DC + (c)); \
+ STORE(2, y, DC - (c)); \
+ STORE(3, y, DC - (d)); \
+} while (0)
+
+#define MUL1(a) ((((a) * 20091) >> 16) + (a))
+#define MUL2(a) (((a) * 35468) >> 16)
static void TransformOne(const int16_t* in, uint8_t* dst) {
int C[4 * 4], *tmp;
@@ -70,8 +44,8 @@ static void TransformOne(const int16_t* in, uint8_t* dst) {
for (i = 0; i < 4; ++i) { // vertical pass
const int a = in[0] + in[8]; // [-4096, 4094]
const int b = in[0] - in[8]; // [-4095, 4095]
- const int c = MUL(in[4], kC2) - MUL(in[12], kC1); // [-3783, 3783]
- const int d = MUL(in[4], kC1) + MUL(in[12], kC2); // [-3785, 3781]
+ const int c = MUL2(in[4]) - MUL1(in[12]); // [-3783, 3783]
+ const int d = MUL1(in[4]) + MUL2(in[12]); // [-3785, 3781]
tmp[0] = a + d; // [-7881, 7875]
tmp[1] = b + c; // [-7878, 7878]
tmp[2] = b - c; // [-7878, 7878]
@@ -80,7 +54,7 @@ static void TransformOne(const int16_t* in, uint8_t* dst) {
in++;
}
// Each pass is expanding the dynamic range by ~3.85 (upper bound).
- // The exact value is (2. + (kC1 + kC2) / 65536).
+ // The exact value is (2. + (20091 + 35468) / 65536).
// After the second pass, maximum interval is [-3794, 3794], assuming
// an input in [-2048, 2047] interval. We then need to add a dst value
// in the [0, 255] range.
@@ -91,8 +65,8 @@ static void TransformOne(const int16_t* in, uint8_t* dst) {
const int dc = tmp[0] + 4;
const int a = dc + tmp[8];
const int b = dc - tmp[8];
- const int c = MUL(tmp[4], kC2) - MUL(tmp[12], kC1);
- const int d = MUL(tmp[4], kC1) + MUL(tmp[12], kC2);
+ const int c = MUL2(tmp[4]) - MUL1(tmp[12]);
+ const int d = MUL1(tmp[4]) + MUL2(tmp[12]);
STORE(0, 0, a + d);
STORE(1, 0, b + c);
STORE(2, 0, b - c);
@@ -101,7 +75,22 @@ static void TransformOne(const int16_t* in, uint8_t* dst) {
dst += BPS;
}
}
-#undef MUL
+
+// Simplified transform when only in[0], in[1] and in[4] are non-zero
+static void TransformAC3(const int16_t* in, uint8_t* dst) {
+ const int a = in[0] + 4;
+ const int c4 = MUL2(in[4]);
+ const int d4 = MUL1(in[4]);
+ const int c1 = MUL2(in[1]);
+ const int d1 = MUL1(in[1]);
+ STORE2(0, a + d4, d1, c1);
+ STORE2(1, a + c4, d1, c1);
+ STORE2(2, a - c4, d1, c1);
+ STORE2(3, a - d4, d1, c1);
+}
+#undef MUL1
+#undef MUL2
+#undef STORE2
static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
TransformOne(in, dst);
@@ -115,7 +104,7 @@ static void TransformUV(const int16_t* in, uint8_t* dst) {
VP8Transform(in + 2 * 16, dst + 4 * BPS, 1);
}
-static void TransformDC(const int16_t *in, uint8_t* dst) {
+static void TransformDC(const int16_t* in, uint8_t* dst) {
const int DC = in[0] + 4;
int i, j;
for (j = 0; j < 4; ++j) {
@@ -126,10 +115,10 @@ static void TransformDC(const int16_t *in, uint8_t* dst) {
}
static void TransformDCUV(const int16_t* in, uint8_t* dst) {
- if (in[0 * 16]) TransformDC(in + 0 * 16, dst);
- if (in[1 * 16]) TransformDC(in + 1 * 16, dst + 4);
- if (in[2 * 16]) TransformDC(in + 2 * 16, dst + 4 * BPS);
- if (in[3 * 16]) TransformDC(in + 3 * 16, dst + 4 * BPS + 4);
+ if (in[0 * 16]) VP8TransformDC(in + 0 * 16, dst);
+ if (in[1 * 16]) VP8TransformDC(in + 1 * 16, dst + 4);
+ if (in[2 * 16]) VP8TransformDC(in + 2 * 16, dst + 4 * BPS);
+ if (in[3 * 16]) VP8TransformDC(in + 3 * 16, dst + 4 * BPS + 4);
}
#undef STORE
@@ -164,16 +153,16 @@ static void TransformWHT(const int16_t* in, int16_t* out) {
}
}
-void (*VP8TransformWHT)(const int16_t* in, int16_t* out) = TransformWHT;
+void (*VP8TransformWHT)(const int16_t* in, int16_t* out);
//------------------------------------------------------------------------------
// Intra predictions
#define DST(x, y) dst[(x) + (y) * BPS]
-static WEBP_INLINE void TrueMotion(uint8_t *dst, int size) {
+static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) {
const uint8_t* top = dst - BPS;
- const uint8_t* const clip0 = clip1 + 255 - top[-1];
+ const uint8_t* const clip0 = VP8kclip1 - top[-1];
int y;
for (y = 0; y < size; ++y) {
const uint8_t* const clip = clip0 + dst[-1];
@@ -184,21 +173,21 @@ static WEBP_INLINE void TrueMotion(uint8_t *dst, int size) {
dst += BPS;
}
}
-static void TM4(uint8_t *dst) { TrueMotion(dst, 4); }
-static void TM8uv(uint8_t *dst) { TrueMotion(dst, 8); }
-static void TM16(uint8_t *dst) { TrueMotion(dst, 16); }
+static void TM4(uint8_t* dst) { TrueMotion(dst, 4); }
+static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); }
+static void TM16(uint8_t* dst) { TrueMotion(dst, 16); }
//------------------------------------------------------------------------------
// 16x16
-static void VE16(uint8_t *dst) { // vertical
+static void VE16(uint8_t* dst) { // vertical
int j;
for (j = 0; j < 16; ++j) {
memcpy(dst + j * BPS, dst - BPS, 16);
}
}
-static void HE16(uint8_t *dst) { // horizontal
+static void HE16(uint8_t* dst) { // horizontal
int j;
for (j = 16; j > 0; --j) {
memset(dst, dst[-1], 16);
@@ -213,7 +202,7 @@ static WEBP_INLINE void Put16(int v, uint8_t* dst) {
}
}
-static void DC16(uint8_t *dst) { // DC
+static void DC16(uint8_t* dst) { // DC
int DC = 16;
int j;
for (j = 0; j < 16; ++j) {
@@ -222,7 +211,7 @@ static void DC16(uint8_t *dst) { // DC
Put16(DC >> 5, dst);
}
-static void DC16NoTop(uint8_t *dst) { // DC with top samples not available
+static void DC16NoTop(uint8_t* dst) { // DC with top samples not available
int DC = 8;
int j;
for (j = 0; j < 16; ++j) {
@@ -231,7 +220,7 @@ static void DC16NoTop(uint8_t *dst) { // DC with top samples not available
Put16(DC >> 4, dst);
}
-static void DC16NoLeft(uint8_t *dst) { // DC with left samples not available
+static void DC16NoLeft(uint8_t* dst) { // DC with left samples not available
int DC = 8;
int i;
for (i = 0; i < 16; ++i) {
@@ -240,17 +229,19 @@ static void DC16NoLeft(uint8_t *dst) { // DC with left samples not available
Put16(DC >> 4, dst);
}
-static void DC16NoTopLeft(uint8_t *dst) { // DC with no top and left samples
+static void DC16NoTopLeft(uint8_t* dst) { // DC with no top and left samples
Put16(0x80, dst);
}
+VP8PredFunc VP8PredLuma16[NUM_B_DC_MODES];
+
//------------------------------------------------------------------------------
// 4x4
#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2)
#define AVG2(a, b) (((a) + (b) + 1) >> 1)
-static void VE4(uint8_t *dst) { // vertical
+static void VE4(uint8_t* dst) { // vertical
const uint8_t* top = dst - BPS;
const uint8_t vals[4] = {
AVG3(top[-1], top[0], top[1]),
@@ -264,7 +255,7 @@ static void VE4(uint8_t *dst) { // vertical
}
}
-static void HE4(uint8_t *dst) { // horizontal
+static void HE4(uint8_t* dst) { // horizontal
const int A = dst[-1 - BPS];
const int B = dst[-1];
const int C = dst[-1 + BPS];
@@ -276,7 +267,7 @@ static void HE4(uint8_t *dst) { // horizontal
*(uint32_t*)(dst + 3 * BPS) = 0x01010101U * AVG3(D, E, E);
}
-static void DC4(uint8_t *dst) { // DC
+static void DC4(uint8_t* dst) { // DC
uint32_t dc = 4;
int i;
for (i = 0; i < 4; ++i) dc += dst[i - BPS] + dst[-1 + i * BPS];
@@ -284,7 +275,7 @@ static void DC4(uint8_t *dst) { // DC
for (i = 0; i < 4; ++i) memset(dst + i * BPS, dc, 4);
}
-static void RD4(uint8_t *dst) { // Down-right
+static void RD4(uint8_t* dst) { // Down-right
const int I = dst[-1 + 0 * BPS];
const int J = dst[-1 + 1 * BPS];
const int K = dst[-1 + 2 * BPS];
@@ -295,15 +286,15 @@ static void RD4(uint8_t *dst) { // Down-right
const int C = dst[2 - BPS];
const int D = dst[3 - BPS];
DST(0, 3) = AVG3(J, K, L);
- DST(0, 2) = DST(1, 3) = AVG3(I, J, K);
- DST(0, 1) = DST(1, 2) = DST(2, 3) = AVG3(X, I, J);
- DST(0, 0) = DST(1, 1) = DST(2, 2) = DST(3, 3) = AVG3(A, X, I);
- DST(1, 0) = DST(2, 1) = DST(3, 2) = AVG3(B, A, X);
- DST(2, 0) = DST(3, 1) = AVG3(C, B, A);
- DST(3, 0) = AVG3(D, C, B);
+ DST(1, 3) = DST(0, 2) = AVG3(I, J, K);
+ DST(2, 3) = DST(1, 2) = DST(0, 1) = AVG3(X, I, J);
+ DST(3, 3) = DST(2, 2) = DST(1, 1) = DST(0, 0) = AVG3(A, X, I);
+ DST(3, 2) = DST(2, 1) = DST(1, 0) = AVG3(B, A, X);
+ DST(3, 1) = DST(2, 0) = AVG3(C, B, A);
+ DST(3, 0) = AVG3(D, C, B);
}
-static void LD4(uint8_t *dst) { // Down-Left
+static void LD4(uint8_t* dst) { // Down-Left
const int A = dst[0 - BPS];
const int B = dst[1 - BPS];
const int C = dst[2 - BPS];
@@ -316,12 +307,12 @@ static void LD4(uint8_t *dst) { // Down-Left
DST(1, 0) = DST(0, 1) = AVG3(B, C, D);
DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E);
DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F);
- DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G);
- DST(3, 2) = DST(2, 3) = AVG3(F, G, H);
- DST(3, 3) = AVG3(G, H, H);
+ DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G);
+ DST(3, 2) = DST(2, 3) = AVG3(F, G, H);
+ DST(3, 3) = AVG3(G, H, H);
}
-static void VR4(uint8_t *dst) { // Vertical-Right
+static void VR4(uint8_t* dst) { // Vertical-Right
const int I = dst[-1 + 0 * BPS];
const int J = dst[-1 + 1 * BPS];
const int K = dst[-1 + 2 * BPS];
@@ -343,7 +334,7 @@ static void VR4(uint8_t *dst) { // Vertical-Right
DST(3, 1) = AVG3(B, C, D);
}
-static void VL4(uint8_t *dst) { // Vertical-Left
+static void VL4(uint8_t* dst) { // Vertical-Left
const int A = dst[0 - BPS];
const int B = dst[1 - BPS];
const int C = dst[2 - BPS];
@@ -365,7 +356,7 @@ static void VL4(uint8_t *dst) { // Vertical-Left
DST(3, 3) = AVG3(F, G, H);
}
-static void HU4(uint8_t *dst) { // Horizontal-Up
+static void HU4(uint8_t* dst) { // Horizontal-Up
const int I = dst[-1 + 0 * BPS];
const int J = dst[-1 + 1 * BPS];
const int K = dst[-1 + 2 * BPS];
@@ -380,7 +371,7 @@ static void HU4(uint8_t *dst) { // Horizontal-Up
DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
}
-static void HD4(uint8_t *dst) { // Horizontal-Down
+static void HD4(uint8_t* dst) { // Horizontal-Down
const int I = dst[-1 + 0 * BPS];
const int J = dst[-1 + 1 * BPS];
const int K = dst[-1 + 2 * BPS];
@@ -407,17 +398,19 @@ static void HD4(uint8_t *dst) { // Horizontal-Down
#undef AVG3
#undef AVG2
+VP8PredFunc VP8PredLuma4[NUM_BMODES];
+
//------------------------------------------------------------------------------
// Chroma
-static void VE8uv(uint8_t *dst) { // vertical
+static void VE8uv(uint8_t* dst) { // vertical
int j;
for (j = 0; j < 8; ++j) {
memcpy(dst + j * BPS, dst - BPS, 8);
}
}
-static void HE8uv(uint8_t *dst) { // horizontal
+static void HE8uv(uint8_t* dst) { // horizontal
int j;
for (j = 0; j < 8; ++j) {
memset(dst, dst[-1], 8);
@@ -426,60 +419,45 @@ static void HE8uv(uint8_t *dst) { // horizontal
}
// helper for chroma-DC predictions
-static WEBP_INLINE void Put8x8uv(uint64_t v, uint8_t* dst) {
+static WEBP_INLINE void Put8x8uv(uint8_t value, uint8_t* dst) {
int j;
for (j = 0; j < 8; ++j) {
- *(uint64_t*)(dst + j * BPS) = v;
+ memset(dst + j * BPS, value, 8);
}
}
-static void DC8uv(uint8_t *dst) { // DC
+static void DC8uv(uint8_t* dst) { // DC
int dc0 = 8;
int i;
for (i = 0; i < 8; ++i) {
dc0 += dst[i - BPS] + dst[-1 + i * BPS];
}
- Put8x8uv((uint64_t)((dc0 >> 4) * 0x0101010101010101ULL), dst);
+ Put8x8uv(dc0 >> 4, dst);
}
-static void DC8uvNoLeft(uint8_t *dst) { // DC with no left samples
+static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples
int dc0 = 4;
int i;
for (i = 0; i < 8; ++i) {
dc0 += dst[i - BPS];
}
- Put8x8uv((uint64_t)((dc0 >> 3) * 0x0101010101010101ULL), dst);
+ Put8x8uv(dc0 >> 3, dst);
}
-static void DC8uvNoTop(uint8_t *dst) { // DC with no top samples
+static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples
int dc0 = 4;
int i;
for (i = 0; i < 8; ++i) {
dc0 += dst[-1 + i * BPS];
}
- Put8x8uv((uint64_t)((dc0 >> 3) * 0x0101010101010101ULL), dst);
+ Put8x8uv(dc0 >> 3, dst);
}
-static void DC8uvNoTopLeft(uint8_t *dst) { // DC with nothing
- Put8x8uv(0x8080808080808080ULL, dst);
+static void DC8uvNoTopLeft(uint8_t* dst) { // DC with nothing
+ Put8x8uv(0x80, dst);
}
-//------------------------------------------------------------------------------
-// default C implementations
-
-const VP8PredFunc VP8PredLuma4[NUM_BMODES] = {
- DC4, TM4, VE4, HE4, RD4, VR4, LD4, VL4, HD4, HU4
-};
-
-const VP8PredFunc VP8PredLuma16[NUM_B_DC_MODES] = {
- DC16, TM16, VE16, HE16,
- DC16NoTop, DC16NoLeft, DC16NoTopLeft
-};
-
-const VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES] = {
- DC8uv, TM8uv, VE8uv, HE8uv,
- DC8uvNoTop, DC8uvNoLeft, DC8uvNoTopLeft
-};
+VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES];
//------------------------------------------------------------------------------
// Edge filtering functions
@@ -487,61 +465,62 @@ const VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES] = {
// 4 pixels in, 2 pixels out
static WEBP_INLINE void do_filter2(uint8_t* p, int step) {
const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
- const int a = 3 * (q0 - p0) + sclip1[1020 + p1 - q1];
- const int a1 = sclip2[112 + ((a + 4) >> 3)];
- const int a2 = sclip2[112 + ((a + 3) >> 3)];
- p[-step] = clip1[255 + p0 + a2];
- p[ 0] = clip1[255 + q0 - a1];
+ const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1]; // in [-893,892]
+ const int a1 = VP8ksclip2[(a + 4) >> 3]; // in [-16,15]
+ const int a2 = VP8ksclip2[(a + 3) >> 3];
+ p[-step] = VP8kclip1[p0 + a2];
+ p[ 0] = VP8kclip1[q0 - a1];
}
// 4 pixels in, 4 pixels out
static WEBP_INLINE void do_filter4(uint8_t* p, int step) {
const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
const int a = 3 * (q0 - p0);
- const int a1 = sclip2[112 + ((a + 4) >> 3)];
- const int a2 = sclip2[112 + ((a + 3) >> 3)];
+ const int a1 = VP8ksclip2[(a + 4) >> 3];
+ const int a2 = VP8ksclip2[(a + 3) >> 3];
const int a3 = (a1 + 1) >> 1;
- p[-2*step] = clip1[255 + p1 + a3];
- p[- step] = clip1[255 + p0 + a2];
- p[ 0] = clip1[255 + q0 - a1];
- p[ step] = clip1[255 + q1 - a3];
+ p[-2*step] = VP8kclip1[p1 + a3];
+ p[- step] = VP8kclip1[p0 + a2];
+ p[ 0] = VP8kclip1[q0 - a1];
+ p[ step] = VP8kclip1[q1 - a3];
}
// 6 pixels in, 6 pixels out
static WEBP_INLINE void do_filter6(uint8_t* p, int step) {
const int p2 = p[-3*step], p1 = p[-2*step], p0 = p[-step];
const int q0 = p[0], q1 = p[step], q2 = p[2*step];
- const int a = sclip1[1020 + 3 * (q0 - p0) + sclip1[1020 + p1 - q1]];
+ const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]];
+ // a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9]
const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7
const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7
const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7
- p[-3*step] = clip1[255 + p2 + a3];
- p[-2*step] = clip1[255 + p1 + a2];
- p[- step] = clip1[255 + p0 + a1];
- p[ 0] = clip1[255 + q0 - a1];
- p[ step] = clip1[255 + q1 - a2];
- p[ 2*step] = clip1[255 + q2 - a3];
+ p[-3*step] = VP8kclip1[p2 + a3];
+ p[-2*step] = VP8kclip1[p1 + a2];
+ p[- step] = VP8kclip1[p0 + a1];
+ p[ 0] = VP8kclip1[q0 - a1];
+ p[ step] = VP8kclip1[q1 - a2];
+ p[ 2*step] = VP8kclip1[q2 - a3];
}
static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) {
const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
- return (abs0[255 + p1 - p0] > thresh) || (abs0[255 + q1 - q0] > thresh);
+ return (VP8kabs0[p1 - p0] > thresh) || (VP8kabs0[q1 - q0] > thresh);
}
-static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int thresh) {
- const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
- return (2 * abs0[255 + p0 - q0] + abs1[255 + p1 - q1]) <= thresh;
+static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int t) {
+ const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
+ return ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) <= t);
}
static WEBP_INLINE int needs_filter2(const uint8_t* p,
int step, int t, int it) {
- const int p3 = p[-4*step], p2 = p[-3*step], p1 = p[-2*step], p0 = p[-step];
- const int q0 = p[0], q1 = p[step], q2 = p[2*step], q3 = p[3*step];
- if ((2 * abs0[255 + p0 - q0] + abs1[255 + p1 - q1]) > t)
- return 0;
- return abs0[255 + p3 - p2] <= it && abs0[255 + p2 - p1] <= it &&
- abs0[255 + p1 - p0] <= it && abs0[255 + q3 - q2] <= it &&
- abs0[255 + q2 - q1] <= it && abs0[255 + q1 - q0] <= it;
+ const int p3 = p[-4 * step], p2 = p[-3 * step], p1 = p[-2 * step];
+ const int p0 = p[-step], q0 = p[0];
+ const int q1 = p[step], q2 = p[2 * step], q3 = p[3 * step];
+ if ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) > t) return 0;
+ return VP8kabs0[p3 - p2] <= it && VP8kabs0[p2 - p1] <= it &&
+ VP8kabs0[p1 - p0] <= it && VP8kabs0[q3 - q2] <= it &&
+ VP8kabs0[q2 - q1] <= it && VP8kabs0[q1 - q0] <= it;
}
//------------------------------------------------------------------------------
@@ -549,8 +528,9 @@ static WEBP_INLINE int needs_filter2(const uint8_t* p,
static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
int i;
+ const int thresh2 = 2 * thresh + 1;
for (i = 0; i < 16; ++i) {
- if (needs_filter(p + i, stride, thresh)) {
+ if (needs_filter(p + i, stride, thresh2)) {
do_filter2(p + i, stride);
}
}
@@ -558,8 +538,9 @@ static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
int i;
+ const int thresh2 = 2 * thresh + 1;
for (i = 0; i < 16; ++i) {
- if (needs_filter(p + i * stride, 1, thresh)) {
+ if (needs_filter(p + i * stride, 1, thresh2)) {
do_filter2(p + i * stride, 1);
}
}
@@ -587,8 +568,9 @@ static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
static WEBP_INLINE void FilterLoop26(uint8_t* p,
int hstride, int vstride, int size,
int thresh, int ithresh, int hev_thresh) {
+ const int thresh2 = 2 * thresh + 1;
while (size-- > 0) {
- if (needs_filter2(p, hstride, thresh, ithresh)) {
+ if (needs_filter2(p, hstride, thresh2, ithresh)) {
if (hev(p, hstride, hev_thresh)) {
do_filter2(p, hstride);
} else {
@@ -602,8 +584,9 @@ static WEBP_INLINE void FilterLoop26(uint8_t* p,
static WEBP_INLINE void FilterLoop24(uint8_t* p,
int hstride, int vstride, int size,
int thresh, int ithresh, int hev_thresh) {
+ const int thresh2 = 2 * thresh + 1;
while (size-- > 0) {
- if (needs_filter2(p, hstride, thresh, ithresh)) {
+ if (needs_filter2(p, hstride, thresh2, ithresh)) {
if (hev(p, hstride, hev_thresh)) {
do_filter2(p, hstride);
} else {
@@ -672,6 +655,7 @@ static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
//------------------------------------------------------------------------------
VP8DecIdct2 VP8Transform;
+VP8DecIdct VP8TransformAC3;
VP8DecIdct VP8TransformUV;
VP8DecIdct VP8TransformDC;
VP8DecIdct VP8TransformDCUV;
@@ -690,15 +674,25 @@ VP8SimpleFilterFunc VP8SimpleVFilter16i;
VP8SimpleFilterFunc VP8SimpleHFilter16i;
extern void VP8DspInitSSE2(void);
+extern void VP8DspInitSSE41(void);
extern void VP8DspInitNEON(void);
+extern void VP8DspInitMIPS32(void);
+extern void VP8DspInitMIPSdspR2(void);
+
+static volatile VP8CPUInfo dec_last_cpuinfo_used =
+ (VP8CPUInfo)&dec_last_cpuinfo_used;
-void VP8DspInit(void) {
- DspInitTables();
+WEBP_TSAN_IGNORE_FUNCTION void VP8DspInit(void) {
+ if (dec_last_cpuinfo_used == VP8GetCPUInfo) return;
+ VP8InitClipTables();
+
+ VP8TransformWHT = TransformWHT;
VP8Transform = TransformTwo;
VP8TransformUV = TransformUV;
VP8TransformDC = TransformDC;
VP8TransformDCUV = TransformDCUV;
+ VP8TransformAC3 = TransformAC3;
VP8VFilter16 = VFilter16;
VP8HFilter16 = HFilter16;
@@ -713,20 +707,60 @@ void VP8DspInit(void) {
VP8SimpleVFilter16i = SimpleVFilter16i;
VP8SimpleHFilter16i = SimpleHFilter16i;
+ VP8PredLuma4[0] = DC4;
+ VP8PredLuma4[1] = TM4;
+ VP8PredLuma4[2] = VE4;
+ VP8PredLuma4[3] = HE4;
+ VP8PredLuma4[4] = RD4;
+ VP8PredLuma4[5] = VR4;
+ VP8PredLuma4[6] = LD4;
+ VP8PredLuma4[7] = VL4;
+ VP8PredLuma4[8] = HD4;
+ VP8PredLuma4[9] = HU4;
+
+ VP8PredLuma16[0] = DC16;
+ VP8PredLuma16[1] = TM16;
+ VP8PredLuma16[2] = VE16;
+ VP8PredLuma16[3] = HE16;
+ VP8PredLuma16[4] = DC16NoTop;
+ VP8PredLuma16[5] = DC16NoLeft;
+ VP8PredLuma16[6] = DC16NoTopLeft;
+
+ VP8PredChroma8[0] = DC8uv;
+ VP8PredChroma8[1] = TM8uv;
+ VP8PredChroma8[2] = VE8uv;
+ VP8PredChroma8[3] = HE8uv;
+ VP8PredChroma8[4] = DC8uvNoTop;
+ VP8PredChroma8[5] = DC8uvNoLeft;
+ VP8PredChroma8[6] = DC8uvNoTopLeft;
+
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
- if (VP8GetCPUInfo) {
+ if (VP8GetCPUInfo != NULL) {
#if defined(WEBP_USE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
VP8DspInitSSE2();
+#if defined(WEBP_USE_SSE41)
+ if (VP8GetCPUInfo(kSSE4_1)) {
+ VP8DspInitSSE41();
+ }
+#endif
}
-#elif defined(WEBP_USE_NEON)
+#endif
+#if defined(WEBP_USE_NEON)
if (VP8GetCPUInfo(kNEON)) {
VP8DspInitNEON();
}
#endif
+#if defined(WEBP_USE_MIPS32)
+ if (VP8GetCPUInfo(kMIPS32)) {
+ VP8DspInitMIPS32();
+ }
+#endif
+#if defined(WEBP_USE_MIPS_DSP_R2)
+ if (VP8GetCPUInfo(kMIPSdspR2)) {
+ VP8DspInitMIPSdspR2();
+ }
+#endif
}
+ dec_last_cpuinfo_used = VP8GetCPUInfo;
}
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/dsp/dec_clip_tables.c b/drivers/webp/dsp/dec_clip_tables.c
new file mode 100644
index 0000000000..3b6dde86ba
--- /dev/null
+++ b/drivers/webp/dsp/dec_clip_tables.c
@@ -0,0 +1,366 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Clipping tables for filtering
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#define USE_STATIC_TABLES // undefine to have run-time table initialization
+
+#ifdef USE_STATIC_TABLES
+
+static const uint8_t abs0[255 + 255 + 1] = {
+ 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4,
+ 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8,
+ 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc,
+ 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0,
+ 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4,
+ 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
+ 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac,
+ 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0,
+ 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94,
+ 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88,
+ 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c,
+ 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70,
+ 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64,
+ 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58,
+ 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c,
+ 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40,
+ 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34,
+ 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28,
+ 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c,
+ 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04,
+ 0x03, 0x02, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
+ 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
+ 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44,
+ 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c,
+ 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74,
+ 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
+ 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c,
+ 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4,
+ 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
+ 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc,
+ 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
+ 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
+ 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec,
+ 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+static const int8_t sclip1[1020 + 1020 + 1] = {
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93,
+ 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
+ 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb,
+ 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3,
+ 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+ 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53,
+ 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
+ 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f
+};
+
+static const int8_t sclip2[112 + 112 + 1] = {
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
+ 0xfc, 0xfd, 0xfe, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f
+};
+
+static const uint8_t clip1[255 + 511 + 1] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
+ 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
+ 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44,
+ 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c,
+ 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74,
+ 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
+ 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c,
+ 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4,
+ 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
+ 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc,
+ 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
+ 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
+ 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec,
+ 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+#else
+
+// uninitialized tables
+static uint8_t abs0[255 + 255 + 1];
+static int8_t sclip1[1020 + 1020 + 1];
+static int8_t sclip2[112 + 112 + 1];
+static uint8_t clip1[255 + 511 + 1];
+
+// We declare this variable 'volatile' to prevent instruction reordering
+// and make sure it's set to true _last_ (so as to be thread-safe)
+static volatile int tables_ok = 0;
+
+#endif
+
+const int8_t* const VP8ksclip1 = &sclip1[1020];
+const int8_t* const VP8ksclip2 = &sclip2[112];
+const uint8_t* const VP8kclip1 = &clip1[255];
+const uint8_t* const VP8kabs0 = &abs0[255];
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8InitClipTables(void) {
+#if !defined(USE_STATIC_TABLES)
+ int i;
+ if (!tables_ok) {
+ for (i = -255; i <= 255; ++i) {
+ abs0[255 + i] = (i < 0) ? -i : i;
+ }
+ for (i = -1020; i <= 1020; ++i) {
+ sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i;
+ }
+ for (i = -112; i <= 112; ++i) {
+ sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i;
+ }
+ for (i = -255; i <= 255 + 255; ++i) {
+ clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i;
+ }
+ tables_ok = 1;
+ }
+#endif // USE_STATIC_TABLES
+}
diff --git a/drivers/webp/dsp/dec_mips32.c b/drivers/webp/dsp/dec_mips32.c
new file mode 100644
index 0000000000..4e9ef42605
--- /dev/null
+++ b/drivers/webp/dsp/dec_mips32.c
@@ -0,0 +1,587 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// MIPS version of dsp functions
+//
+// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
+// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS32)
+
+#include "./mips_macro.h"
+
+static const int kC1 = 20091 + (1 << 16);
+static const int kC2 = 35468;
+
+static WEBP_INLINE int abs_mips32(int x) {
+ const int sign = x >> 31;
+ return (x ^ sign) - sign;
+}
+
+// 4 pixels in, 2 pixels out
+static WEBP_INLINE void do_filter2(uint8_t* p, int step) {
+ const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
+ const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1];
+ const int a1 = VP8ksclip2[(a + 4) >> 3];
+ const int a2 = VP8ksclip2[(a + 3) >> 3];
+ p[-step] = VP8kclip1[p0 + a2];
+ p[ 0] = VP8kclip1[q0 - a1];
+}
+
+// 4 pixels in, 4 pixels out
+static WEBP_INLINE void do_filter4(uint8_t* p, int step) {
+ const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
+ const int a = 3 * (q0 - p0);
+ const int a1 = VP8ksclip2[(a + 4) >> 3];
+ const int a2 = VP8ksclip2[(a + 3) >> 3];
+ const int a3 = (a1 + 1) >> 1;
+ p[-2 * step] = VP8kclip1[p1 + a3];
+ p[- step] = VP8kclip1[p0 + a2];
+ p[ 0] = VP8kclip1[q0 - a1];
+ p[ step] = VP8kclip1[q1 - a3];
+}
+
+// 6 pixels in, 6 pixels out
+static WEBP_INLINE void do_filter6(uint8_t* p, int step) {
+ const int p2 = p[-3 * step], p1 = p[-2 * step], p0 = p[-step];
+ const int q0 = p[0], q1 = p[step], q2 = p[2 * step];
+ const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]];
+ // a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9]
+ const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7
+ const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7
+ const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7
+ p[-3 * step] = VP8kclip1[p2 + a3];
+ p[-2 * step] = VP8kclip1[p1 + a2];
+ p[- step] = VP8kclip1[p0 + a1];
+ p[ 0] = VP8kclip1[q0 - a1];
+ p[ step] = VP8kclip1[q1 - a2];
+ p[ 2 * step] = VP8kclip1[q2 - a3];
+}
+
+static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) {
+ const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
+ return (abs_mips32(p1 - p0) > thresh) || (abs_mips32(q1 - q0) > thresh);
+}
+
+static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int t) {
+ const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
+ return ((4 * abs_mips32(p0 - q0) + abs_mips32(p1 - q1)) <= t);
+}
+
+static WEBP_INLINE int needs_filter2(const uint8_t* p,
+ int step, int t, int it) {
+ const int p3 = p[-4 * step], p2 = p[-3 * step];
+ const int p1 = p[-2 * step], p0 = p[-step];
+ const int q0 = p[0], q1 = p[step], q2 = p[2 * step], q3 = p[3 * step];
+ if ((4 * abs_mips32(p0 - q0) + abs_mips32(p1 - q1)) > t) {
+ return 0;
+ }
+ return abs_mips32(p3 - p2) <= it && abs_mips32(p2 - p1) <= it &&
+ abs_mips32(p1 - p0) <= it && abs_mips32(q3 - q2) <= it &&
+ abs_mips32(q2 - q1) <= it && abs_mips32(q1 - q0) <= it;
+}
+
+static WEBP_INLINE void FilterLoop26(uint8_t* p,
+ int hstride, int vstride, int size,
+ int thresh, int ithresh, int hev_thresh) {
+ const int thresh2 = 2 * thresh + 1;
+ while (size-- > 0) {
+ if (needs_filter2(p, hstride, thresh2, ithresh)) {
+ if (hev(p, hstride, hev_thresh)) {
+ do_filter2(p, hstride);
+ } else {
+ do_filter6(p, hstride);
+ }
+ }
+ p += vstride;
+ }
+}
+
+static WEBP_INLINE void FilterLoop24(uint8_t* p,
+ int hstride, int vstride, int size,
+ int thresh, int ithresh, int hev_thresh) {
+ const int thresh2 = 2 * thresh + 1;
+ while (size-- > 0) {
+ if (needs_filter2(p, hstride, thresh2, ithresh)) {
+ if (hev(p, hstride, hev_thresh)) {
+ do_filter2(p, hstride);
+ } else {
+ do_filter4(p, hstride);
+ }
+ }
+ p += vstride;
+ }
+}
+
+// on macroblock edges
+static void VFilter16(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh);
+}
+
+static void HFilter16(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh);
+}
+
+// 8-pixels wide variant, for chroma filtering
+static void VFilter8(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh);
+ FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh);
+}
+
+static void HFilter8(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh);
+ FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh);
+}
+
+static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
+ FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
+}
+
+static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
+ FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
+}
+
+// on three inner edges
+static void VFilter16i(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4 * stride;
+ FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh);
+ }
+}
+
+static void HFilter16i(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4;
+ FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Simple In-loop filtering (Paragraph 15.2)
+
+static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
+ int i;
+ const int thresh2 = 2 * thresh + 1;
+ for (i = 0; i < 16; ++i) {
+ if (needs_filter(p + i, stride, thresh2)) {
+ do_filter2(p + i, stride);
+ }
+ }
+}
+
+static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
+ int i;
+ const int thresh2 = 2 * thresh + 1;
+ for (i = 0; i < 16; ++i) {
+ if (needs_filter(p + i * stride, 1, thresh2)) {
+ do_filter2(p + i * stride, 1);
+ }
+ }
+}
+
+static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4 * stride;
+ SimpleVFilter16(p, stride, thresh);
+ }
+}
+
+static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4;
+ SimpleHFilter16(p, stride, thresh);
+ }
+}
+
+static void TransformOne(const int16_t* in, uint8_t* dst) {
+ int temp0, temp1, temp2, temp3, temp4;
+ int temp5, temp6, temp7, temp8, temp9;
+ int temp10, temp11, temp12, temp13, temp14;
+ int temp15, temp16, temp17, temp18;
+ int16_t* p_in = (int16_t*)in;
+
+ // loops unrolled and merged to avoid usage of tmp buffer
+ // and to reduce number of stalls. MUL macro is written
+ // in assembler and inlined
+ __asm__ volatile(
+ "lh %[temp0], 0(%[in]) \n\t"
+ "lh %[temp8], 16(%[in]) \n\t"
+ "lh %[temp4], 8(%[in]) \n\t"
+ "lh %[temp12], 24(%[in]) \n\t"
+ "addu %[temp16], %[temp0], %[temp8] \n\t"
+ "subu %[temp0], %[temp0], %[temp8] \n\t"
+ "mul %[temp8], %[temp4], %[kC2] \n\t"
+ "mul %[temp17], %[temp12], %[kC1] \n\t"
+ "mul %[temp4], %[temp4], %[kC1] \n\t"
+ "mul %[temp12], %[temp12], %[kC2] \n\t"
+ "lh %[temp1], 2(%[in]) \n\t"
+ "lh %[temp5], 10(%[in]) \n\t"
+ "lh %[temp9], 18(%[in]) \n\t"
+ "lh %[temp13], 26(%[in]) \n\t"
+ "sra %[temp8], %[temp8], 16 \n\t"
+ "sra %[temp17], %[temp17], 16 \n\t"
+ "sra %[temp4], %[temp4], 16 \n\t"
+ "sra %[temp12], %[temp12], 16 \n\t"
+ "lh %[temp2], 4(%[in]) \n\t"
+ "lh %[temp6], 12(%[in]) \n\t"
+ "lh %[temp10], 20(%[in]) \n\t"
+ "lh %[temp14], 28(%[in]) \n\t"
+ "subu %[temp17], %[temp8], %[temp17] \n\t"
+ "addu %[temp4], %[temp4], %[temp12] \n\t"
+ "addu %[temp8], %[temp16], %[temp4] \n\t"
+ "subu %[temp4], %[temp16], %[temp4] \n\t"
+ "addu %[temp16], %[temp1], %[temp9] \n\t"
+ "subu %[temp1], %[temp1], %[temp9] \n\t"
+ "lh %[temp3], 6(%[in]) \n\t"
+ "lh %[temp7], 14(%[in]) \n\t"
+ "lh %[temp11], 22(%[in]) \n\t"
+ "lh %[temp15], 30(%[in]) \n\t"
+ "addu %[temp12], %[temp0], %[temp17] \n\t"
+ "subu %[temp0], %[temp0], %[temp17] \n\t"
+ "mul %[temp9], %[temp5], %[kC2] \n\t"
+ "mul %[temp17], %[temp13], %[kC1] \n\t"
+ "mul %[temp5], %[temp5], %[kC1] \n\t"
+ "mul %[temp13], %[temp13], %[kC2] \n\t"
+ "sra %[temp9], %[temp9], 16 \n\t"
+ "sra %[temp17], %[temp17], 16 \n\t"
+ "subu %[temp17], %[temp9], %[temp17] \n\t"
+ "sra %[temp5], %[temp5], 16 \n\t"
+ "sra %[temp13], %[temp13], 16 \n\t"
+ "addu %[temp5], %[temp5], %[temp13] \n\t"
+ "addu %[temp13], %[temp1], %[temp17] \n\t"
+ "subu %[temp1], %[temp1], %[temp17] \n\t"
+ "mul %[temp17], %[temp14], %[kC1] \n\t"
+ "mul %[temp14], %[temp14], %[kC2] \n\t"
+ "addu %[temp9], %[temp16], %[temp5] \n\t"
+ "subu %[temp5], %[temp16], %[temp5] \n\t"
+ "addu %[temp16], %[temp2], %[temp10] \n\t"
+ "subu %[temp2], %[temp2], %[temp10] \n\t"
+ "mul %[temp10], %[temp6], %[kC2] \n\t"
+ "mul %[temp6], %[temp6], %[kC1] \n\t"
+ "sra %[temp17], %[temp17], 16 \n\t"
+ "sra %[temp14], %[temp14], 16 \n\t"
+ "sra %[temp10], %[temp10], 16 \n\t"
+ "sra %[temp6], %[temp6], 16 \n\t"
+ "subu %[temp17], %[temp10], %[temp17] \n\t"
+ "addu %[temp6], %[temp6], %[temp14] \n\t"
+ "addu %[temp10], %[temp16], %[temp6] \n\t"
+ "subu %[temp6], %[temp16], %[temp6] \n\t"
+ "addu %[temp14], %[temp2], %[temp17] \n\t"
+ "subu %[temp2], %[temp2], %[temp17] \n\t"
+ "mul %[temp17], %[temp15], %[kC1] \n\t"
+ "mul %[temp15], %[temp15], %[kC2] \n\t"
+ "addu %[temp16], %[temp3], %[temp11] \n\t"
+ "subu %[temp3], %[temp3], %[temp11] \n\t"
+ "mul %[temp11], %[temp7], %[kC2] \n\t"
+ "mul %[temp7], %[temp7], %[kC1] \n\t"
+ "addiu %[temp8], %[temp8], 4 \n\t"
+ "addiu %[temp12], %[temp12], 4 \n\t"
+ "addiu %[temp0], %[temp0], 4 \n\t"
+ "addiu %[temp4], %[temp4], 4 \n\t"
+ "sra %[temp17], %[temp17], 16 \n\t"
+ "sra %[temp15], %[temp15], 16 \n\t"
+ "sra %[temp11], %[temp11], 16 \n\t"
+ "sra %[temp7], %[temp7], 16 \n\t"
+ "subu %[temp17], %[temp11], %[temp17] \n\t"
+ "addu %[temp7], %[temp7], %[temp15] \n\t"
+ "addu %[temp15], %[temp3], %[temp17] \n\t"
+ "subu %[temp3], %[temp3], %[temp17] \n\t"
+ "addu %[temp11], %[temp16], %[temp7] \n\t"
+ "subu %[temp7], %[temp16], %[temp7] \n\t"
+ "addu %[temp16], %[temp8], %[temp10] \n\t"
+ "subu %[temp8], %[temp8], %[temp10] \n\t"
+ "mul %[temp10], %[temp9], %[kC2] \n\t"
+ "mul %[temp17], %[temp11], %[kC1] \n\t"
+ "mul %[temp9], %[temp9], %[kC1] \n\t"
+ "mul %[temp11], %[temp11], %[kC2] \n\t"
+ "sra %[temp10], %[temp10], 16 \n\t"
+ "sra %[temp17], %[temp17], 16 \n\t"
+ "sra %[temp9], %[temp9], 16 \n\t"
+ "sra %[temp11], %[temp11], 16 \n\t"
+ "subu %[temp17], %[temp10], %[temp17] \n\t"
+ "addu %[temp11], %[temp9], %[temp11] \n\t"
+ "addu %[temp10], %[temp12], %[temp14] \n\t"
+ "subu %[temp12], %[temp12], %[temp14] \n\t"
+ "mul %[temp14], %[temp13], %[kC2] \n\t"
+ "mul %[temp9], %[temp15], %[kC1] \n\t"
+ "mul %[temp13], %[temp13], %[kC1] \n\t"
+ "mul %[temp15], %[temp15], %[kC2] \n\t"
+ "sra %[temp14], %[temp14], 16 \n\t"
+ "sra %[temp9], %[temp9], 16 \n\t"
+ "sra %[temp13], %[temp13], 16 \n\t"
+ "sra %[temp15], %[temp15], 16 \n\t"
+ "subu %[temp9], %[temp14], %[temp9] \n\t"
+ "addu %[temp15], %[temp13], %[temp15] \n\t"
+ "addu %[temp14], %[temp0], %[temp2] \n\t"
+ "subu %[temp0], %[temp0], %[temp2] \n\t"
+ "mul %[temp2], %[temp1], %[kC2] \n\t"
+ "mul %[temp13], %[temp3], %[kC1] \n\t"
+ "mul %[temp1], %[temp1], %[kC1] \n\t"
+ "mul %[temp3], %[temp3], %[kC2] \n\t"
+ "sra %[temp2], %[temp2], 16 \n\t"
+ "sra %[temp13], %[temp13], 16 \n\t"
+ "sra %[temp1], %[temp1], 16 \n\t"
+ "sra %[temp3], %[temp3], 16 \n\t"
+ "subu %[temp13], %[temp2], %[temp13] \n\t"
+ "addu %[temp3], %[temp1], %[temp3] \n\t"
+ "addu %[temp2], %[temp4], %[temp6] \n\t"
+ "subu %[temp4], %[temp4], %[temp6] \n\t"
+ "mul %[temp6], %[temp5], %[kC2] \n\t"
+ "mul %[temp1], %[temp7], %[kC1] \n\t"
+ "mul %[temp5], %[temp5], %[kC1] \n\t"
+ "mul %[temp7], %[temp7], %[kC2] \n\t"
+ "sra %[temp6], %[temp6], 16 \n\t"
+ "sra %[temp1], %[temp1], 16 \n\t"
+ "sra %[temp5], %[temp5], 16 \n\t"
+ "sra %[temp7], %[temp7], 16 \n\t"
+ "subu %[temp1], %[temp6], %[temp1] \n\t"
+ "addu %[temp7], %[temp5], %[temp7] \n\t"
+ "addu %[temp5], %[temp16], %[temp11] \n\t"
+ "subu %[temp16], %[temp16], %[temp11] \n\t"
+ "addu %[temp11], %[temp8], %[temp17] \n\t"
+ "subu %[temp8], %[temp8], %[temp17] \n\t"
+ "sra %[temp5], %[temp5], 3 \n\t"
+ "sra %[temp16], %[temp16], 3 \n\t"
+ "sra %[temp11], %[temp11], 3 \n\t"
+ "sra %[temp8], %[temp8], 3 \n\t"
+ "addu %[temp17], %[temp10], %[temp15] \n\t"
+ "subu %[temp10], %[temp10], %[temp15] \n\t"
+ "addu %[temp15], %[temp12], %[temp9] \n\t"
+ "subu %[temp12], %[temp12], %[temp9] \n\t"
+ "sra %[temp17], %[temp17], 3 \n\t"
+ "sra %[temp10], %[temp10], 3 \n\t"
+ "sra %[temp15], %[temp15], 3 \n\t"
+ "sra %[temp12], %[temp12], 3 \n\t"
+ "addu %[temp9], %[temp14], %[temp3] \n\t"
+ "subu %[temp14], %[temp14], %[temp3] \n\t"
+ "addu %[temp3], %[temp0], %[temp13] \n\t"
+ "subu %[temp0], %[temp0], %[temp13] \n\t"
+ "sra %[temp9], %[temp9], 3 \n\t"
+ "sra %[temp14], %[temp14], 3 \n\t"
+ "sra %[temp3], %[temp3], 3 \n\t"
+ "sra %[temp0], %[temp0], 3 \n\t"
+ "addu %[temp13], %[temp2], %[temp7] \n\t"
+ "subu %[temp2], %[temp2], %[temp7] \n\t"
+ "addu %[temp7], %[temp4], %[temp1] \n\t"
+ "subu %[temp4], %[temp4], %[temp1] \n\t"
+ "sra %[temp13], %[temp13], 3 \n\t"
+ "sra %[temp2], %[temp2], 3 \n\t"
+ "sra %[temp7], %[temp7], 3 \n\t"
+ "sra %[temp4], %[temp4], 3 \n\t"
+ "addiu %[temp6], $zero, 255 \n\t"
+ "lbu %[temp1], 0+0*" XSTR(BPS) "(%[dst]) \n\t"
+ "addu %[temp1], %[temp1], %[temp5] \n\t"
+ "sra %[temp5], %[temp1], 8 \n\t"
+ "sra %[temp18], %[temp1], 31 \n\t"
+ "beqz %[temp5], 1f \n\t"
+ "xor %[temp1], %[temp1], %[temp1] \n\t"
+ "movz %[temp1], %[temp6], %[temp18] \n\t"
+ "1: \n\t"
+ "lbu %[temp18], 1+0*" XSTR(BPS) "(%[dst]) \n\t"
+ "sb %[temp1], 0+0*" XSTR(BPS) "(%[dst]) \n\t"
+ "addu %[temp18], %[temp18], %[temp11] \n\t"
+ "sra %[temp11], %[temp18], 8 \n\t"
+ "sra %[temp1], %[temp18], 31 \n\t"
+ "beqz %[temp11], 2f \n\t"
+ "xor %[temp18], %[temp18], %[temp18] \n\t"
+ "movz %[temp18], %[temp6], %[temp1] \n\t"
+ "2: \n\t"
+ "lbu %[temp1], 2+0*" XSTR(BPS) "(%[dst]) \n\t"
+ "sb %[temp18], 1+0*" XSTR(BPS) "(%[dst]) \n\t"
+ "addu %[temp1], %[temp1], %[temp8] \n\t"
+ "sra %[temp8], %[temp1], 8 \n\t"
+ "sra %[temp18], %[temp1], 31 \n\t"
+ "beqz %[temp8], 3f \n\t"
+ "xor %[temp1], %[temp1], %[temp1] \n\t"
+ "movz %[temp1], %[temp6], %[temp18] \n\t"
+ "3: \n\t"
+ "lbu %[temp18], 3+0*" XSTR(BPS) "(%[dst]) \n\t"
+ "sb %[temp1], 2+0*" XSTR(BPS) "(%[dst]) \n\t"
+ "addu %[temp18], %[temp18], %[temp16] \n\t"
+ "sra %[temp16], %[temp18], 8 \n\t"
+ "sra %[temp1], %[temp18], 31 \n\t"
+ "beqz %[temp16], 4f \n\t"
+ "xor %[temp18], %[temp18], %[temp18] \n\t"
+ "movz %[temp18], %[temp6], %[temp1] \n\t"
+ "4: \n\t"
+ "sb %[temp18], 3+0*" XSTR(BPS) "(%[dst]) \n\t"
+ "lbu %[temp5], 0+1*" XSTR(BPS) "(%[dst]) \n\t"
+ "lbu %[temp8], 1+1*" XSTR(BPS) "(%[dst]) \n\t"
+ "lbu %[temp11], 2+1*" XSTR(BPS) "(%[dst]) \n\t"
+ "lbu %[temp16], 3+1*" XSTR(BPS) "(%[dst]) \n\t"
+ "addu %[temp5], %[temp5], %[temp17] \n\t"
+ "addu %[temp8], %[temp8], %[temp15] \n\t"
+ "addu %[temp11], %[temp11], %[temp12] \n\t"
+ "addu %[temp16], %[temp16], %[temp10] \n\t"
+ "sra %[temp18], %[temp5], 8 \n\t"
+ "sra %[temp1], %[temp5], 31 \n\t"
+ "beqz %[temp18], 5f \n\t"
+ "xor %[temp5], %[temp5], %[temp5] \n\t"
+ "movz %[temp5], %[temp6], %[temp1] \n\t"
+ "5: \n\t"
+ "sra %[temp18], %[temp8], 8 \n\t"
+ "sra %[temp1], %[temp8], 31 \n\t"
+ "beqz %[temp18], 6f \n\t"
+ "xor %[temp8], %[temp8], %[temp8] \n\t"
+ "movz %[temp8], %[temp6], %[temp1] \n\t"
+ "6: \n\t"
+ "sra %[temp18], %[temp11], 8 \n\t"
+ "sra %[temp1], %[temp11], 31 \n\t"
+ "sra %[temp17], %[temp16], 8 \n\t"
+ "sra %[temp15], %[temp16], 31 \n\t"
+ "beqz %[temp18], 7f \n\t"
+ "xor %[temp11], %[temp11], %[temp11] \n\t"
+ "movz %[temp11], %[temp6], %[temp1] \n\t"
+ "7: \n\t"
+ "beqz %[temp17], 8f \n\t"
+ "xor %[temp16], %[temp16], %[temp16] \n\t"
+ "movz %[temp16], %[temp6], %[temp15] \n\t"
+ "8: \n\t"
+ "sb %[temp5], 0+1*" XSTR(BPS) "(%[dst]) \n\t"
+ "sb %[temp8], 1+1*" XSTR(BPS) "(%[dst]) \n\t"
+ "sb %[temp11], 2+1*" XSTR(BPS) "(%[dst]) \n\t"
+ "sb %[temp16], 3+1*" XSTR(BPS) "(%[dst]) \n\t"
+ "lbu %[temp5], 0+2*" XSTR(BPS) "(%[dst]) \n\t"
+ "lbu %[temp8], 1+2*" XSTR(BPS) "(%[dst]) \n\t"
+ "lbu %[temp11], 2+2*" XSTR(BPS) "(%[dst]) \n\t"
+ "lbu %[temp16], 3+2*" XSTR(BPS) "(%[dst]) \n\t"
+ "addu %[temp5], %[temp5], %[temp9] \n\t"
+ "addu %[temp8], %[temp8], %[temp3] \n\t"
+ "addu %[temp11], %[temp11], %[temp0] \n\t"
+ "addu %[temp16], %[temp16], %[temp14] \n\t"
+ "sra %[temp18], %[temp5], 8 \n\t"
+ "sra %[temp1], %[temp5], 31 \n\t"
+ "sra %[temp17], %[temp8], 8 \n\t"
+ "sra %[temp15], %[temp8], 31 \n\t"
+ "sra %[temp12], %[temp11], 8 \n\t"
+ "sra %[temp10], %[temp11], 31 \n\t"
+ "sra %[temp9], %[temp16], 8 \n\t"
+ "sra %[temp3], %[temp16], 31 \n\t"
+ "beqz %[temp18], 9f \n\t"
+ "xor %[temp5], %[temp5], %[temp5] \n\t"
+ "movz %[temp5], %[temp6], %[temp1] \n\t"
+ "9: \n\t"
+ "beqz %[temp17], 10f \n\t"
+ "xor %[temp8], %[temp8], %[temp8] \n\t"
+ "movz %[temp8], %[temp6], %[temp15] \n\t"
+ "10: \n\t"
+ "beqz %[temp12], 11f \n\t"
+ "xor %[temp11], %[temp11], %[temp11] \n\t"
+ "movz %[temp11], %[temp6], %[temp10] \n\t"
+ "11: \n\t"
+ "beqz %[temp9], 12f \n\t"
+ "xor %[temp16], %[temp16], %[temp16] \n\t"
+ "movz %[temp16], %[temp6], %[temp3] \n\t"
+ "12: \n\t"
+ "sb %[temp5], 0+2*" XSTR(BPS) "(%[dst]) \n\t"
+ "sb %[temp8], 1+2*" XSTR(BPS) "(%[dst]) \n\t"
+ "sb %[temp11], 2+2*" XSTR(BPS) "(%[dst]) \n\t"
+ "sb %[temp16], 3+2*" XSTR(BPS) "(%[dst]) \n\t"
+ "lbu %[temp5], 0+3*" XSTR(BPS) "(%[dst]) \n\t"
+ "lbu %[temp8], 1+3*" XSTR(BPS) "(%[dst]) \n\t"
+ "lbu %[temp11], 2+3*" XSTR(BPS) "(%[dst]) \n\t"
+ "lbu %[temp16], 3+3*" XSTR(BPS) "(%[dst]) \n\t"
+ "addu %[temp5], %[temp5], %[temp13] \n\t"
+ "addu %[temp8], %[temp8], %[temp7] \n\t"
+ "addu %[temp11], %[temp11], %[temp4] \n\t"
+ "addu %[temp16], %[temp16], %[temp2] \n\t"
+ "sra %[temp18], %[temp5], 8 \n\t"
+ "sra %[temp1], %[temp5], 31 \n\t"
+ "sra %[temp17], %[temp8], 8 \n\t"
+ "sra %[temp15], %[temp8], 31 \n\t"
+ "sra %[temp12], %[temp11], 8 \n\t"
+ "sra %[temp10], %[temp11], 31 \n\t"
+ "sra %[temp9], %[temp16], 8 \n\t"
+ "sra %[temp3], %[temp16], 31 \n\t"
+ "beqz %[temp18], 13f \n\t"
+ "xor %[temp5], %[temp5], %[temp5] \n\t"
+ "movz %[temp5], %[temp6], %[temp1] \n\t"
+ "13: \n\t"
+ "beqz %[temp17], 14f \n\t"
+ "xor %[temp8], %[temp8], %[temp8] \n\t"
+ "movz %[temp8], %[temp6], %[temp15] \n\t"
+ "14: \n\t"
+ "beqz %[temp12], 15f \n\t"
+ "xor %[temp11], %[temp11], %[temp11] \n\t"
+ "movz %[temp11], %[temp6], %[temp10] \n\t"
+ "15: \n\t"
+ "beqz %[temp9], 16f \n\t"
+ "xor %[temp16], %[temp16], %[temp16] \n\t"
+ "movz %[temp16], %[temp6], %[temp3] \n\t"
+ "16: \n\t"
+ "sb %[temp5], 0+3*" XSTR(BPS) "(%[dst]) \n\t"
+ "sb %[temp8], 1+3*" XSTR(BPS) "(%[dst]) \n\t"
+ "sb %[temp11], 2+3*" XSTR(BPS) "(%[dst]) \n\t"
+ "sb %[temp16], 3+3*" XSTR(BPS) "(%[dst]) \n\t"
+
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
+ [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11),
+ [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14),
+ [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17),
+ [temp18]"=&r"(temp18)
+ : [in]"r"(p_in), [kC1]"r"(kC1), [kC2]"r"(kC2), [dst]"r"(dst)
+ : "memory", "hi", "lo"
+ );
+}
+
+static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
+ TransformOne(in, dst);
+ if (do_two) {
+ TransformOne(in + 16, dst + 4);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8DspInitMIPS32(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMIPS32(void) {
+ VP8InitClipTables();
+
+ VP8Transform = TransformTwo;
+
+ VP8VFilter16 = VFilter16;
+ VP8HFilter16 = HFilter16;
+ VP8VFilter8 = VFilter8;
+ VP8HFilter8 = HFilter8;
+ VP8VFilter16i = VFilter16i;
+ VP8HFilter16i = HFilter16i;
+ VP8VFilter8i = VFilter8i;
+ VP8HFilter8i = HFilter8i;
+
+ VP8SimpleVFilter16 = SimpleVFilter16;
+ VP8SimpleHFilter16 = SimpleHFilter16;
+ VP8SimpleVFilter16i = SimpleVFilter16i;
+ VP8SimpleHFilter16i = SimpleHFilter16i;
+}
+
+#else // !WEBP_USE_MIPS32
+
+WEBP_DSP_INIT_STUB(VP8DspInitMIPS32)
+
+#endif // WEBP_USE_MIPS32
diff --git a/drivers/webp/dsp/dec_mips_dsp_r2.c b/drivers/webp/dsp/dec_mips_dsp_r2.c
new file mode 100644
index 0000000000..db5c657228
--- /dev/null
+++ b/drivers/webp/dsp/dec_mips_dsp_r2.c
@@ -0,0 +1,994 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// MIPS version of dsp functions
+//
+// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
+// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS_DSP_R2)
+
+#include "./mips_macro.h"
+
+static const int kC1 = 20091 + (1 << 16);
+static const int kC2 = 35468;
+
+#define MUL(a, b) (((a) * (b)) >> 16)
+
+static void TransformDC(const int16_t* in, uint8_t* dst) {
+ int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10;
+
+ __asm__ volatile (
+ LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, dst,
+ 0, 0, 0, 0,
+ 0, 1, 2, 3,
+ BPS)
+ "lh %[temp5], 0(%[in]) \n\t"
+ "addiu %[temp5], %[temp5], 4 \n\t"
+ "ins %[temp5], %[temp5], 16, 16 \n\t"
+ "shra.ph %[temp5], %[temp5], 3 \n\t"
+ CONVERT_2_BYTES_TO_HALF(temp6, temp7, temp8, temp9, temp10, temp1, temp2,
+ temp3, temp1, temp2, temp3, temp4)
+ STORE_SAT_SUM_X2(temp6, temp7, temp8, temp9, temp10, temp1, temp2, temp3,
+ temp5, temp5, temp5, temp5, temp5, temp5, temp5, temp5,
+ dst, 0, 1, 2, 3, BPS)
+
+ OUTPUT_EARLY_CLOBBER_REGS_10()
+ : [in]"r"(in), [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+static void TransformAC3(const int16_t* in, uint8_t* dst) {
+ const int a = in[0] + 4;
+ int c4 = MUL(in[4], kC2);
+ const int d4 = MUL(in[4], kC1);
+ const int c1 = MUL(in[1], kC2);
+ const int d1 = MUL(in[1], kC1);
+ int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
+ int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
+
+ __asm__ volatile (
+ "ins %[c4], %[d4], 16, 16 \n\t"
+ "replv.ph %[temp1], %[a] \n\t"
+ "replv.ph %[temp4], %[d1] \n\t"
+ ADD_SUB_HALVES(temp2, temp3, temp1, c4)
+ "replv.ph %[temp5], %[c1] \n\t"
+ SHIFT_R_SUM_X2(temp1, temp6, temp7, temp8, temp2, temp9, temp10, temp4,
+ temp2, temp2, temp3, temp3, temp4, temp5, temp4, temp5)
+ LOAD_WITH_OFFSET_X4(temp3, temp5, temp11, temp12, dst,
+ 0, 0, 0, 0,
+ 0, 1, 2, 3,
+ BPS)
+ CONVERT_2_BYTES_TO_HALF(temp13, temp14, temp3, temp15, temp5, temp16,
+ temp11, temp17, temp3, temp5, temp11, temp12)
+ PACK_2_HALVES_TO_WORD(temp12, temp18, temp7, temp6, temp1, temp8, temp2,
+ temp4, temp7, temp6, temp10, temp9)
+ STORE_SAT_SUM_X2(temp13, temp14, temp3, temp15, temp5, temp16, temp11,
+ temp17, temp12, temp18, temp1, temp8, temp2, temp4,
+ temp7, temp6, dst, 0, 1, 2, 3, BPS)
+
+ OUTPUT_EARLY_CLOBBER_REGS_18(),
+ [c4]"+&r"(c4)
+ : [dst]"r"(dst), [a]"r"(a), [d1]"r"(d1), [d4]"r"(d4), [c1]"r"(c1)
+ : "memory"
+ );
+}
+
+static void TransformOne(const int16_t* in, uint8_t* dst) {
+ int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
+ int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
+
+ __asm__ volatile (
+ "ulw %[temp1], 0(%[in]) \n\t"
+ "ulw %[temp2], 16(%[in]) \n\t"
+ LOAD_IN_X2(temp5, temp6, 24, 26)
+ ADD_SUB_HALVES(temp3, temp4, temp1, temp2)
+ LOAD_IN_X2(temp1, temp2, 8, 10)
+ MUL_SHIFT_SUM(temp7, temp8, temp9, temp10, temp11, temp12, temp13, temp14,
+ temp10, temp8, temp9, temp7, temp1, temp2, temp5, temp6,
+ temp13, temp11, temp14, temp12)
+ INSERT_HALF_X2(temp8, temp7, temp10, temp9)
+ "ulw %[temp17], 4(%[in]) \n\t"
+ "ulw %[temp18], 20(%[in]) \n\t"
+ ADD_SUB_HALVES(temp1, temp2, temp3, temp8)
+ ADD_SUB_HALVES(temp5, temp6, temp4, temp7)
+ ADD_SUB_HALVES(temp7, temp8, temp17, temp18)
+ LOAD_IN_X2(temp17, temp18, 12, 14)
+ LOAD_IN_X2(temp9, temp10, 28, 30)
+ MUL_SHIFT_SUM(temp11, temp12, temp13, temp14, temp15, temp16, temp4, temp17,
+ temp12, temp14, temp11, temp13, temp17, temp18, temp9, temp10,
+ temp15, temp4, temp16, temp17)
+ INSERT_HALF_X2(temp11, temp12, temp13, temp14)
+ ADD_SUB_HALVES(temp17, temp8, temp8, temp11)
+ ADD_SUB_HALVES(temp3, temp4, temp7, temp12)
+
+ // horizontal
+ SRA_16(temp9, temp10, temp11, temp12, temp1, temp2, temp5, temp6)
+ INSERT_HALF_X2(temp1, temp6, temp5, temp2)
+ SRA_16(temp13, temp14, temp15, temp16, temp3, temp4, temp17, temp8)
+ "repl.ph %[temp2], 0x4 \n\t"
+ INSERT_HALF_X2(temp3, temp8, temp17, temp4)
+ "addq.ph %[temp1], %[temp1], %[temp2] \n\t"
+ "addq.ph %[temp6], %[temp6], %[temp2] \n\t"
+ ADD_SUB_HALVES(temp2, temp4, temp1, temp3)
+ ADD_SUB_HALVES(temp5, temp7, temp6, temp8)
+ MUL_SHIFT_SUM(temp1, temp3, temp6, temp8, temp9, temp13, temp17, temp18,
+ temp3, temp13, temp1, temp9, temp9, temp13, temp11, temp15,
+ temp6, temp17, temp8, temp18)
+ MUL_SHIFT_SUM(temp6, temp8, temp18, temp17, temp11, temp15, temp12, temp16,
+ temp8, temp15, temp6, temp11, temp12, temp16, temp10, temp14,
+ temp18, temp12, temp17, temp16)
+ INSERT_HALF_X2(temp1, temp3, temp9, temp13)
+ INSERT_HALF_X2(temp6, temp8, temp11, temp15)
+ SHIFT_R_SUM_X2(temp9, temp10, temp11, temp12, temp13, temp14, temp15,
+ temp16, temp2, temp4, temp5, temp7, temp3, temp1, temp8,
+ temp6)
+ PACK_2_HALVES_TO_WORD(temp1, temp2, temp3, temp4, temp9, temp12, temp13,
+ temp16, temp11, temp10, temp15, temp14)
+ LOAD_WITH_OFFSET_X4(temp10, temp11, temp14, temp15, dst,
+ 0, 0, 0, 0,
+ 0, 1, 2, 3,
+ BPS)
+ CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp17, temp18, temp10,
+ temp11, temp10, temp11, temp14, temp15)
+ STORE_SAT_SUM_X2(temp5, temp6, temp7, temp8, temp17, temp18, temp10, temp11,
+ temp9, temp12, temp1, temp2, temp13, temp16, temp3, temp4,
+ dst, 0, 1, 2, 3, BPS)
+
+ OUTPUT_EARLY_CLOBBER_REGS_18()
+ : [dst]"r"(dst), [in]"r"(in), [kC1]"r"(kC1), [kC2]"r"(kC2)
+ : "memory", "hi", "lo"
+ );
+}
+
+static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
+ TransformOne(in, dst);
+ if (do_two) {
+ TransformOne(in + 16, dst + 4);
+ }
+}
+
+static WEBP_INLINE void FilterLoop26(uint8_t* p,
+ int hstride, int vstride, int size,
+ int thresh, int ithresh, int hev_thresh) {
+ const int thresh2 = 2 * thresh + 1;
+ int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
+ int temp10, temp11, temp12, temp13, temp14, temp15;
+
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "1: \n\t"
+ "negu %[temp1], %[hstride] \n\t"
+ "addiu %[size], %[size], -1 \n\t"
+ "sll %[temp2], %[hstride], 1 \n\t"
+ "sll %[temp3], %[temp1], 1 \n\t"
+ "addu %[temp4], %[temp2], %[hstride] \n\t"
+ "addu %[temp5], %[temp3], %[temp1] \n\t"
+ "lbu %[temp7], 0(%[p]) \n\t"
+ "sll %[temp6], %[temp3], 1 \n\t"
+ "lbux %[temp8], %[temp5](%[p]) \n\t"
+ "lbux %[temp9], %[temp3](%[p]) \n\t"
+ "lbux %[temp10], %[temp1](%[p]) \n\t"
+ "lbux %[temp11], %[temp6](%[p]) \n\t"
+ "lbux %[temp12], %[hstride](%[p]) \n\t"
+ "lbux %[temp13], %[temp2](%[p]) \n\t"
+ "lbux %[temp14], %[temp4](%[p]) \n\t"
+ "subu %[temp1], %[temp10], %[temp7] \n\t"
+ "subu %[temp2], %[temp9], %[temp12] \n\t"
+ "absq_s.w %[temp3], %[temp1] \n\t"
+ "absq_s.w %[temp4], %[temp2] \n\t"
+ "negu %[temp1], %[temp1] \n\t"
+ "sll %[temp3], %[temp3], 2 \n\t"
+ "addu %[temp15], %[temp3], %[temp4] \n\t"
+ "subu %[temp3], %[temp15], %[thresh2] \n\t"
+ "sll %[temp6], %[temp1], 1 \n\t"
+ "bgtz %[temp3], 3f \n\t"
+ " subu %[temp4], %[temp11], %[temp8] \n\t"
+ "absq_s.w %[temp4], %[temp4] \n\t"
+ "shll_s.w %[temp2], %[temp2], 24 \n\t"
+ "subu %[temp4], %[temp4], %[ithresh] \n\t"
+ "bgtz %[temp4], 3f \n\t"
+ " subu %[temp3], %[temp8], %[temp9] \n\t"
+ "absq_s.w %[temp3], %[temp3] \n\t"
+ "subu %[temp3], %[temp3], %[ithresh] \n\t"
+ "bgtz %[temp3], 3f \n\t"
+ " subu %[temp5], %[temp9], %[temp10] \n\t"
+ "absq_s.w %[temp3], %[temp5] \n\t"
+ "absq_s.w %[temp5], %[temp5] \n\t"
+ "subu %[temp3], %[temp3], %[ithresh] \n\t"
+ "bgtz %[temp3], 3f \n\t"
+ " subu %[temp3], %[temp14], %[temp13] \n\t"
+ "absq_s.w %[temp3], %[temp3] \n\t"
+ "slt %[temp5], %[hev_thresh], %[temp5] \n\t"
+ "subu %[temp3], %[temp3], %[ithresh] \n\t"
+ "bgtz %[temp3], 3f \n\t"
+ " subu %[temp3], %[temp13], %[temp12] \n\t"
+ "absq_s.w %[temp3], %[temp3] \n\t"
+ "sra %[temp4], %[temp2], 24 \n\t"
+ "subu %[temp3], %[temp3], %[ithresh] \n\t"
+ "bgtz %[temp3], 3f \n\t"
+ " subu %[temp15], %[temp12], %[temp7] \n\t"
+ "absq_s.w %[temp3], %[temp15] \n\t"
+ "absq_s.w %[temp15], %[temp15] \n\t"
+ "subu %[temp3], %[temp3], %[ithresh] \n\t"
+ "bgtz %[temp3], 3f \n\t"
+ " slt %[temp15], %[hev_thresh], %[temp15] \n\t"
+ "addu %[temp3], %[temp6], %[temp1] \n\t"
+ "or %[temp2], %[temp5], %[temp15] \n\t"
+ "addu %[temp5], %[temp4], %[temp3] \n\t"
+ "beqz %[temp2], 4f \n\t"
+ " shra_r.w %[temp1], %[temp5], 3 \n\t"
+ "addiu %[temp2], %[temp5], 3 \n\t"
+ "sra %[temp2], %[temp2], 3 \n\t"
+ "shll_s.w %[temp1], %[temp1], 27 \n\t"
+ "shll_s.w %[temp2], %[temp2], 27 \n\t"
+ "subu %[temp3], %[p], %[hstride] \n\t"
+ "sra %[temp1], %[temp1], 27 \n\t"
+ "sra %[temp2], %[temp2], 27 \n\t"
+ "subu %[temp1], %[temp7], %[temp1] \n\t"
+ "addu %[temp2], %[temp10], %[temp2] \n\t"
+ "lbux %[temp2], %[temp2](%[VP8kclip1]) \n\t"
+ "lbux %[temp1], %[temp1](%[VP8kclip1]) \n\t"
+ "sb %[temp2], 0(%[temp3]) \n\t"
+ "j 3f \n\t"
+ " sb %[temp1], 0(%[p]) \n\t"
+ "4: \n\t"
+ "shll_s.w %[temp5], %[temp5], 24 \n\t"
+ "subu %[temp14], %[p], %[hstride] \n\t"
+ "subu %[temp11], %[temp14], %[hstride] \n\t"
+ "sra %[temp6], %[temp5], 24 \n\t"
+ "sll %[temp1], %[temp6], 3 \n\t"
+ "subu %[temp15], %[temp11], %[hstride] \n\t"
+ "addu %[temp2], %[temp6], %[temp1] \n\t"
+ "sll %[temp3], %[temp2], 1 \n\t"
+ "addu %[temp4], %[temp3], %[temp2] \n\t"
+ "addiu %[temp2], %[temp2], 63 \n\t"
+ "addiu %[temp3], %[temp3], 63 \n\t"
+ "addiu %[temp4], %[temp4], 63 \n\t"
+ "sra %[temp2], %[temp2], 7 \n\t"
+ "sra %[temp3], %[temp3], 7 \n\t"
+ "sra %[temp4], %[temp4], 7 \n\t"
+ "addu %[temp1], %[temp8], %[temp2] \n\t"
+ "addu %[temp5], %[temp9], %[temp3] \n\t"
+ "addu %[temp6], %[temp10], %[temp4] \n\t"
+ "subu %[temp8], %[temp7], %[temp4] \n\t"
+ "subu %[temp7], %[temp12], %[temp3] \n\t"
+ "addu %[temp10], %[p], %[hstride] \n\t"
+ "subu %[temp9], %[temp13], %[temp2] \n\t"
+ "addu %[temp12], %[temp10], %[hstride] \n\t"
+ "lbux %[temp2], %[temp1](%[VP8kclip1]) \n\t"
+ "lbux %[temp3], %[temp5](%[VP8kclip1]) \n\t"
+ "lbux %[temp4], %[temp6](%[VP8kclip1]) \n\t"
+ "lbux %[temp5], %[temp8](%[VP8kclip1]) \n\t"
+ "lbux %[temp6], %[temp7](%[VP8kclip1]) \n\t"
+ "lbux %[temp8], %[temp9](%[VP8kclip1]) \n\t"
+ "sb %[temp2], 0(%[temp15]) \n\t"
+ "sb %[temp3], 0(%[temp11]) \n\t"
+ "sb %[temp4], 0(%[temp14]) \n\t"
+ "sb %[temp5], 0(%[p]) \n\t"
+ "sb %[temp6], 0(%[temp10]) \n\t"
+ "sb %[temp8], 0(%[temp12]) \n\t"
+ "3: \n\t"
+ "bgtz %[size], 1b \n\t"
+ " addu %[p], %[p], %[vstride] \n\t"
+ ".set pop \n\t"
+ : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),[temp3]"=&r"(temp3),
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6),
+ [temp7]"=&r"(temp7),[temp8]"=&r"(temp8),[temp9]"=&r"(temp9),
+ [temp10]"=&r"(temp10),[temp11]"=&r"(temp11),[temp12]"=&r"(temp12),
+ [temp13]"=&r"(temp13),[temp14]"=&r"(temp14),[temp15]"=&r"(temp15),
+ [size]"+&r"(size), [p]"+&r"(p)
+ : [hstride]"r"(hstride), [thresh2]"r"(thresh2),
+ [ithresh]"r"(ithresh),[vstride]"r"(vstride), [hev_thresh]"r"(hev_thresh),
+ [VP8kclip1]"r"(VP8kclip1)
+ : "memory"
+ );
+}
+
+static WEBP_INLINE void FilterLoop24(uint8_t* p,
+ int hstride, int vstride, int size,
+ int thresh, int ithresh, int hev_thresh) {
+ int p0, q0, p1, q1, p2, q2, p3, q3;
+ int step1, step2, temp1, temp2, temp3, temp4;
+ uint8_t* pTemp0;
+ uint8_t* pTemp1;
+ const int thresh2 = 2 * thresh + 1;
+
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "bltz %[size], 3f \n\t"
+ " nop \n\t"
+ "2: \n\t"
+ "negu %[step1], %[hstride] \n\t"
+ "lbu %[q0], 0(%[p]) \n\t"
+ "lbux %[p0], %[step1](%[p]) \n\t"
+ "subu %[step1], %[step1], %[hstride] \n\t"
+ "lbux %[q1], %[hstride](%[p]) \n\t"
+ "subu %[temp1], %[p0], %[q0] \n\t"
+ "lbux %[p1], %[step1](%[p]) \n\t"
+ "addu %[step2], %[hstride], %[hstride] \n\t"
+ "absq_s.w %[temp2], %[temp1] \n\t"
+ "subu %[temp3], %[p1], %[q1] \n\t"
+ "absq_s.w %[temp4], %[temp3] \n\t"
+ "sll %[temp2], %[temp2], 2 \n\t"
+ "addu %[temp2], %[temp2], %[temp4] \n\t"
+ "subu %[temp4], %[temp2], %[thresh2] \n\t"
+ "subu %[step1], %[step1], %[hstride] \n\t"
+ "bgtz %[temp4], 0f \n\t"
+ " lbux %[p2], %[step1](%[p]) \n\t"
+ "subu %[step1], %[step1], %[hstride] \n\t"
+ "lbux %[q2], %[step2](%[p]) \n\t"
+ "lbux %[p3], %[step1](%[p]) \n\t"
+ "subu %[temp4], %[p2], %[p1] \n\t"
+ "addu %[step2], %[step2], %[hstride] \n\t"
+ "subu %[temp2], %[p3], %[p2] \n\t"
+ "absq_s.w %[temp4], %[temp4] \n\t"
+ "absq_s.w %[temp2], %[temp2] \n\t"
+ "lbux %[q3], %[step2](%[p]) \n\t"
+ "subu %[temp4], %[temp4], %[ithresh] \n\t"
+ "negu %[temp1], %[temp1] \n\t"
+ "bgtz %[temp4], 0f \n\t"
+ " subu %[temp2], %[temp2], %[ithresh] \n\t"
+ "subu %[p3], %[p1], %[p0] \n\t"
+ "bgtz %[temp2], 0f \n\t"
+ " absq_s.w %[p3], %[p3] \n\t"
+ "subu %[temp4], %[q3], %[q2] \n\t"
+ "subu %[pTemp0], %[p], %[hstride] \n\t"
+ "absq_s.w %[temp4], %[temp4] \n\t"
+ "subu %[temp2], %[p3], %[ithresh] \n\t"
+ "sll %[step1], %[temp1], 1 \n\t"
+ "bgtz %[temp2], 0f \n\t"
+ " subu %[temp4], %[temp4], %[ithresh] \n\t"
+ "subu %[temp2], %[q2], %[q1] \n\t"
+ "bgtz %[temp4], 0f \n\t"
+ " absq_s.w %[temp2], %[temp2] \n\t"
+ "subu %[q3], %[q1], %[q0] \n\t"
+ "absq_s.w %[q3], %[q3] \n\t"
+ "subu %[temp2], %[temp2], %[ithresh] \n\t"
+ "addu %[temp1], %[temp1], %[step1] \n\t"
+ "bgtz %[temp2], 0f \n\t"
+ " subu %[temp4], %[q3], %[ithresh] \n\t"
+ "slt %[p3], %[hev_thresh], %[p3] \n\t"
+ "bgtz %[temp4], 0f \n\t"
+ " slt %[q3], %[hev_thresh], %[q3] \n\t"
+ "or %[q3], %[q3], %[p3] \n\t"
+ "bgtz %[q3], 1f \n\t"
+ " shra_r.w %[temp2], %[temp1], 3 \n\t"
+ "addiu %[temp1], %[temp1], 3 \n\t"
+ "sra %[temp1], %[temp1], 3 \n\t"
+ "shll_s.w %[temp2], %[temp2], 27 \n\t"
+ "shll_s.w %[temp1], %[temp1], 27 \n\t"
+ "addu %[pTemp1], %[p], %[hstride] \n\t"
+ "sra %[temp2], %[temp2], 27 \n\t"
+ "sra %[temp1], %[temp1], 27 \n\t"
+ "addiu %[step1], %[temp2], 1 \n\t"
+ "sra %[step1], %[step1], 1 \n\t"
+ "addu %[p0], %[p0], %[temp1] \n\t"
+ "addu %[p1], %[p1], %[step1] \n\t"
+ "subu %[q0], %[q0], %[temp2] \n\t"
+ "subu %[q1], %[q1], %[step1] \n\t"
+ "lbux %[temp2], %[p0](%[VP8kclip1]) \n\t"
+ "lbux %[temp3], %[q0](%[VP8kclip1]) \n\t"
+ "lbux %[temp4], %[q1](%[VP8kclip1]) \n\t"
+ "sb %[temp2], 0(%[pTemp0]) \n\t"
+ "lbux %[temp1], %[p1](%[VP8kclip1]) \n\t"
+ "subu %[pTemp0], %[pTemp0], %[hstride] \n\t"
+ "sb %[temp3], 0(%[p]) \n\t"
+ "sb %[temp4], 0(%[pTemp1]) \n\t"
+ "j 0f \n\t"
+ " sb %[temp1], 0(%[pTemp0]) \n\t"
+ "1: \n\t"
+ "shll_s.w %[temp3], %[temp3], 24 \n\t"
+ "sra %[temp3], %[temp3], 24 \n\t"
+ "addu %[temp1], %[temp1], %[temp3] \n\t"
+ "shra_r.w %[temp2], %[temp1], 3 \n\t"
+ "addiu %[temp1], %[temp1], 3 \n\t"
+ "shll_s.w %[temp2], %[temp2], 27 \n\t"
+ "sra %[temp1], %[temp1], 3 \n\t"
+ "shll_s.w %[temp1], %[temp1], 27 \n\t"
+ "sra %[temp2], %[temp2], 27 \n\t"
+ "sra %[temp1], %[temp1], 27 \n\t"
+ "addu %[p0], %[p0], %[temp1] \n\t"
+ "subu %[q0], %[q0], %[temp2] \n\t"
+ "lbux %[temp1], %[p0](%[VP8kclip1]) \n\t"
+ "lbux %[temp2], %[q0](%[VP8kclip1]) \n\t"
+ "sb %[temp2], 0(%[p]) \n\t"
+ "sb %[temp1], 0(%[pTemp0]) \n\t"
+ "0: \n\t"
+ "subu %[size], %[size], 1 \n\t"
+ "bgtz %[size], 2b \n\t"
+ " addu %[p], %[p], %[vstride] \n\t"
+ "3: \n\t"
+ ".set pop \n\t"
+ : [p0]"=&r"(p0), [q0]"=&r"(q0), [p1]"=&r"(p1), [q1]"=&r"(q1),
+ [p2]"=&r"(p2), [q2]"=&r"(q2), [p3]"=&r"(p3), [q3]"=&r"(q3),
+ [step2]"=&r"(step2), [step1]"=&r"(step1), [temp1]"=&r"(temp1),
+ [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4),
+ [pTemp0]"=&r"(pTemp0), [pTemp1]"=&r"(pTemp1), [p]"+&r"(p),
+ [size]"+&r"(size)
+ : [vstride]"r"(vstride), [ithresh]"r"(ithresh),
+ [hev_thresh]"r"(hev_thresh), [hstride]"r"(hstride),
+ [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2)
+ : "memory"
+ );
+}
+
+// on macroblock edges
+static void VFilter16(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh);
+}
+
+static void HFilter16(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh);
+}
+
+// 8-pixels wide variant, for chroma filtering
+static void VFilter8(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh);
+ FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh);
+}
+
+static void HFilter8(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh);
+ FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh);
+}
+
+// on three inner edges
+static void VFilter16i(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4 * stride;
+ FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh);
+ }
+}
+
+static void HFilter16i(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4;
+ FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh);
+ }
+}
+
+static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
+ FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
+}
+
+static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
+ FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
+}
+
+#undef MUL
+
+//------------------------------------------------------------------------------
+// Simple In-loop filtering (Paragraph 15.2)
+
+static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
+ int i;
+ const int thresh2 = 2 * thresh + 1;
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
+ uint8_t* p1 = p - stride;
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "li %[i], 16 \n\t"
+ "0: \n\t"
+ "negu %[temp4], %[stride] \n\t"
+ "sll %[temp5], %[temp4], 1 \n\t"
+ "lbu %[temp2], 0(%[p]) \n\t"
+ "lbux %[temp3], %[stride](%[p]) \n\t"
+ "lbux %[temp1], %[temp4](%[p]) \n\t"
+ "lbux %[temp0], %[temp5](%[p]) \n\t"
+ "subu %[temp7], %[temp1], %[temp2] \n\t"
+ "subu %[temp6], %[temp0], %[temp3] \n\t"
+ "absq_s.w %[temp4], %[temp7] \n\t"
+ "absq_s.w %[temp5], %[temp6] \n\t"
+ "sll %[temp4], %[temp4], 2 \n\t"
+ "subu %[temp5], %[temp5], %[thresh2] \n\t"
+ "addu %[temp5], %[temp4], %[temp5] \n\t"
+ "negu %[temp8], %[temp7] \n\t"
+ "bgtz %[temp5], 1f \n\t"
+ " addiu %[i], %[i], -1 \n\t"
+ "sll %[temp4], %[temp8], 1 \n\t"
+ "shll_s.w %[temp5], %[temp6], 24 \n\t"
+ "addu %[temp3], %[temp4], %[temp8] \n\t"
+ "sra %[temp5], %[temp5], 24 \n\t"
+ "addu %[temp3], %[temp3], %[temp5] \n\t"
+ "addiu %[temp7], %[temp3], 3 \n\t"
+ "sra %[temp7], %[temp7], 3 \n\t"
+ "shra_r.w %[temp8], %[temp3], 3 \n\t"
+ "shll_s.w %[temp0], %[temp7], 27 \n\t"
+ "shll_s.w %[temp4], %[temp8], 27 \n\t"
+ "sra %[temp0], %[temp0], 27 \n\t"
+ "sra %[temp4], %[temp4], 27 \n\t"
+ "addu %[temp7], %[temp1], %[temp0] \n\t"
+ "subu %[temp2], %[temp2], %[temp4] \n\t"
+ "lbux %[temp3], %[temp7](%[VP8kclip1]) \n\t"
+ "lbux %[temp4], %[temp2](%[VP8kclip1]) \n\t"
+ "sb %[temp3], 0(%[p1]) \n\t"
+ "sb %[temp4], 0(%[p]) \n\t"
+ "1: \n\t"
+ "addiu %[p1], %[p1], 1 \n\t"
+ "bgtz %[i], 0b \n\t"
+ " addiu %[p], %[p], 1 \n\t"
+ " .set pop \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
+ [p]"+&r"(p), [i]"=&r"(i), [p1]"+&r"(p1)
+ : [stride]"r"(stride), [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2)
+ : "memory"
+ );
+}
+
+// TEMP0 = SRC[A + A1 * BPS]
+// TEMP1 = SRC[B + B1 * BPS]
+// TEMP2 = SRC[C + C1 * BPS]
+// TEMP3 = SRC[D + D1 * BPS]
+#define LOAD_4_BYTES(TEMP0, TEMP1, TEMP2, TEMP3, \
+ A, A1, B, B1, C, C1, D, D1, SRC) \
+ "lbu %[" #TEMP0 "], " #A "+" #A1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
+ "lbu %[" #TEMP1 "], " #B "+" #B1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
+ "lbu %[" #TEMP2 "], " #C "+" #C1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
+ "lbu %[" #TEMP3 "], " #D "+" #D1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
+
+static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
+ int i;
+ const int thresh2 = 2 * thresh + 1;
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "li %[i], 16 \n\t"
+ "0: \n\t"
+ LOAD_4_BYTES(temp0, temp1, temp2, temp3, -2, 0, -1, 0, 0, 0, 1, 0, p)
+ "subu %[temp7], %[temp1], %[temp2] \n\t"
+ "subu %[temp6], %[temp0], %[temp3] \n\t"
+ "absq_s.w %[temp4], %[temp7] \n\t"
+ "absq_s.w %[temp5], %[temp6] \n\t"
+ "sll %[temp4], %[temp4], 2 \n\t"
+ "addu %[temp5], %[temp4], %[temp5] \n\t"
+ "subu %[temp5], %[temp5], %[thresh2] \n\t"
+ "negu %[temp8], %[temp7] \n\t"
+ "bgtz %[temp5], 1f \n\t"
+ " addiu %[i], %[i], -1 \n\t"
+ "sll %[temp4], %[temp8], 1 \n\t"
+ "shll_s.w %[temp5], %[temp6], 24 \n\t"
+ "addu %[temp3], %[temp4], %[temp8] \n\t"
+ "sra %[temp5], %[temp5], 24 \n\t"
+ "addu %[temp3], %[temp3], %[temp5] \n\t"
+ "addiu %[temp7], %[temp3], 3 \n\t"
+ "sra %[temp7], %[temp7], 3 \n\t"
+ "shra_r.w %[temp8], %[temp3], 3 \n\t"
+ "shll_s.w %[temp0], %[temp7], 27 \n\t"
+ "shll_s.w %[temp4], %[temp8], 27 \n\t"
+ "sra %[temp0], %[temp0], 27 \n\t"
+ "sra %[temp4], %[temp4], 27 \n\t"
+ "addu %[temp7], %[temp1], %[temp0] \n\t"
+ "subu %[temp2], %[temp2], %[temp4] \n\t"
+ "lbux %[temp3], %[temp7](%[VP8kclip1]) \n\t"
+ "lbux %[temp4], %[temp2](%[VP8kclip1]) \n\t"
+ "sb %[temp3], -1(%[p]) \n\t"
+ "sb %[temp4], 0(%[p]) \n\t"
+ "1: \n\t"
+ "bgtz %[i], 0b \n\t"
+ " addu %[p], %[p], %[stride] \n\t"
+ ".set pop \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
+ [p]"+&r"(p), [i]"=&r"(i)
+ : [stride]"r"(stride), [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2)
+ : "memory"
+ );
+}
+
+static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4 * stride;
+ SimpleVFilter16(p, stride, thresh);
+ }
+}
+
+static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4;
+ SimpleHFilter16(p, stride, thresh);
+ }
+}
+
+// DST[A * BPS] = TEMP0
+// DST[B + C * BPS] = TEMP1
+#define STORE_8_BYTES(TEMP0, TEMP1, A, B, C, DST) \
+ "usw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #DST "]) \n\t" \
+ "usw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #DST "]) \n\t"
+
+static void VE4(uint8_t* dst) { // vertical
+ const uint8_t* top = dst - BPS;
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6;
+ __asm__ volatile (
+ "ulw %[temp0], -1(%[top]) \n\t"
+ "ulh %[temp1], 3(%[top]) \n\t"
+ "preceu.ph.qbr %[temp2], %[temp0] \n\t"
+ "preceu.ph.qbl %[temp3], %[temp0] \n\t"
+ "preceu.ph.qbr %[temp4], %[temp1] \n\t"
+ "packrl.ph %[temp5], %[temp3], %[temp2] \n\t"
+ "packrl.ph %[temp6], %[temp4], %[temp3] \n\t"
+ "shll.ph %[temp5], %[temp5], 1 \n\t"
+ "shll.ph %[temp6], %[temp6], 1 \n\t"
+ "addq.ph %[temp2], %[temp5], %[temp2] \n\t"
+ "addq.ph %[temp6], %[temp6], %[temp4] \n\t"
+ "addq.ph %[temp2], %[temp2], %[temp3] \n\t"
+ "addq.ph %[temp6], %[temp6], %[temp3] \n\t"
+ "shra_r.ph %[temp2], %[temp2], 2 \n\t"
+ "shra_r.ph %[temp6], %[temp6], 2 \n\t"
+ "precr.qb.ph %[temp4], %[temp6], %[temp2] \n\t"
+ STORE_8_BYTES(temp4, temp4, 0, 0, 1, dst)
+ STORE_8_BYTES(temp4, temp4, 2, 0, 3, dst)
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6)
+ : [top]"r"(top), [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+static void DC4(uint8_t* dst) { // DC
+ int temp0, temp1, temp2, temp3, temp4;
+ __asm__ volatile (
+ "ulw %[temp0], -1*" XSTR(BPS) "(%[dst]) \n\t"
+ LOAD_4_BYTES(temp1, temp2, temp3, temp4, -1, 0, -1, 1, -1, 2, -1, 3, dst)
+ "ins %[temp1], %[temp2], 8, 8 \n\t"
+ "ins %[temp1], %[temp3], 16, 8 \n\t"
+ "ins %[temp1], %[temp4], 24, 8 \n\t"
+ "raddu.w.qb %[temp0], %[temp0] \n\t"
+ "raddu.w.qb %[temp1], %[temp1] \n\t"
+ "addu %[temp0], %[temp0], %[temp1] \n\t"
+ "shra_r.w %[temp0], %[temp0], 3 \n\t"
+ "replv.qb %[temp0], %[temp0] \n\t"
+ STORE_8_BYTES(temp0, temp0, 0, 0, 1, dst)
+ STORE_8_BYTES(temp0, temp0, 2, 0, 3, dst)
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4)
+ : [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+static void RD4(uint8_t* dst) { // Down-right
+ int temp0, temp1, temp2, temp3, temp4;
+ int temp5, temp6, temp7, temp8;
+ __asm__ volatile (
+ LOAD_4_BYTES(temp0, temp1, temp2, temp3, -1, 0, -1, 1, -1, 2, -1, 3, dst)
+ "ulw %[temp7], -1-" XSTR(BPS) "(%[dst]) \n\t"
+ "ins %[temp1], %[temp0], 16, 16 \n\t"
+ "preceu.ph.qbr %[temp5], %[temp7] \n\t"
+ "ins %[temp2], %[temp1], 16, 16 \n\t"
+ "preceu.ph.qbl %[temp4], %[temp7] \n\t"
+ "ins %[temp3], %[temp2], 16, 16 \n\t"
+ "shll.ph %[temp2], %[temp2], 1 \n\t"
+ "addq.ph %[temp3], %[temp3], %[temp1] \n\t"
+ "packrl.ph %[temp6], %[temp5], %[temp1] \n\t"
+ "addq.ph %[temp3], %[temp3], %[temp2] \n\t"
+ "addq.ph %[temp1], %[temp1], %[temp5] \n\t"
+ "shll.ph %[temp6], %[temp6], 1 \n\t"
+ "addq.ph %[temp1], %[temp1], %[temp6] \n\t"
+ "packrl.ph %[temp0], %[temp4], %[temp5] \n\t"
+ "addq.ph %[temp8], %[temp5], %[temp4] \n\t"
+ "shra_r.ph %[temp3], %[temp3], 2 \n\t"
+ "shll.ph %[temp0], %[temp0], 1 \n\t"
+ "shra_r.ph %[temp1], %[temp1], 2 \n\t"
+ "addq.ph %[temp8], %[temp0], %[temp8] \n\t"
+ "lbu %[temp5], 3-" XSTR(BPS) "(%[dst]) \n\t"
+ "precrq.ph.w %[temp7], %[temp7], %[temp7] \n\t"
+ "shra_r.ph %[temp8], %[temp8], 2 \n\t"
+ "ins %[temp7], %[temp5], 0, 8 \n\t"
+ "precr.qb.ph %[temp2], %[temp1], %[temp3] \n\t"
+ "raddu.w.qb %[temp4], %[temp7] \n\t"
+ "precr.qb.ph %[temp6], %[temp8], %[temp1] \n\t"
+ "shra_r.w %[temp4], %[temp4], 2 \n\t"
+ STORE_8_BYTES(temp2, temp6, 3, 0, 1, dst)
+ "prepend %[temp2], %[temp8], 8 \n\t"
+ "prepend %[temp6], %[temp4], 8 \n\t"
+ STORE_8_BYTES(temp2, temp6, 2, 0, 0, dst)
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8)
+ : [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+// TEMP0 = SRC[A * BPS]
+// TEMP1 = SRC[B + C * BPS]
+#define LOAD_8_BYTES(TEMP0, TEMP1, A, B, C, SRC) \
+ "ulw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
+ "ulw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #SRC "]) \n\t"
+
+static void LD4(uint8_t* dst) { // Down-Left
+ int temp0, temp1, temp2, temp3, temp4;
+ int temp5, temp6, temp7, temp8, temp9;
+ __asm__ volatile (
+ LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst)
+ "preceu.ph.qbl %[temp2], %[temp0] \n\t"
+ "preceu.ph.qbr %[temp3], %[temp0] \n\t"
+ "preceu.ph.qbr %[temp4], %[temp1] \n\t"
+ "preceu.ph.qbl %[temp5], %[temp1] \n\t"
+ "packrl.ph %[temp6], %[temp2], %[temp3] \n\t"
+ "packrl.ph %[temp7], %[temp4], %[temp2] \n\t"
+ "packrl.ph %[temp8], %[temp5], %[temp4] \n\t"
+ "shll.ph %[temp6], %[temp6], 1 \n\t"
+ "addq.ph %[temp9], %[temp2], %[temp6] \n\t"
+ "shll.ph %[temp7], %[temp7], 1 \n\t"
+ "addq.ph %[temp9], %[temp9], %[temp3] \n\t"
+ "shll.ph %[temp8], %[temp8], 1 \n\t"
+ "shra_r.ph %[temp9], %[temp9], 2 \n\t"
+ "addq.ph %[temp3], %[temp4], %[temp7] \n\t"
+ "addq.ph %[temp0], %[temp5], %[temp8] \n\t"
+ "addq.ph %[temp3], %[temp3], %[temp2] \n\t"
+ "addq.ph %[temp0], %[temp0], %[temp4] \n\t"
+ "shra_r.ph %[temp3], %[temp3], 2 \n\t"
+ "shra_r.ph %[temp0], %[temp0], 2 \n\t"
+ "srl %[temp1], %[temp1], 24 \n\t"
+ "sll %[temp1], %[temp1], 1 \n\t"
+ "raddu.w.qb %[temp5], %[temp5] \n\t"
+ "precr.qb.ph %[temp9], %[temp3], %[temp9] \n\t"
+ "precr.qb.ph %[temp3], %[temp0], %[temp3] \n\t"
+ "addu %[temp1], %[temp1], %[temp5] \n\t"
+ "shra_r.w %[temp1], %[temp1], 2 \n\t"
+ STORE_8_BYTES(temp9, temp3, 0, 0, 2, dst)
+ "prepend %[temp9], %[temp0], 8 \n\t"
+ "prepend %[temp3], %[temp1], 8 \n\t"
+ STORE_8_BYTES(temp9, temp3, 1, 0, 3, dst)
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
+ [temp9]"=&r"(temp9)
+ : [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+//------------------------------------------------------------------------------
+// Chroma
+
+static void DC8uv(uint8_t* dst) { // DC
+ int temp0, temp1, temp2, temp3, temp4;
+ int temp5, temp6, temp7, temp8, temp9;
+ __asm__ volatile (
+ LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst)
+ LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst)
+ LOAD_4_BYTES(temp6, temp7, temp8, temp9, -1, 4, -1, 5, -1, 6, -1, 7, dst)
+ "raddu.w.qb %[temp0], %[temp0] \n\t"
+ "raddu.w.qb %[temp1], %[temp1] \n\t"
+ "addu %[temp2], %[temp2], %[temp3] \n\t"
+ "addu %[temp4], %[temp4], %[temp5] \n\t"
+ "addu %[temp6], %[temp6], %[temp7] \n\t"
+ "addu %[temp8], %[temp8], %[temp9] \n\t"
+ "addu %[temp0], %[temp0], %[temp1] \n\t"
+ "addu %[temp2], %[temp2], %[temp4] \n\t"
+ "addu %[temp6], %[temp6], %[temp8] \n\t"
+ "addu %[temp0], %[temp0], %[temp2] \n\t"
+ "addu %[temp0], %[temp0], %[temp6] \n\t"
+ "shra_r.w %[temp0], %[temp0], 4 \n\t"
+ "replv.qb %[temp0], %[temp0] \n\t"
+ STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst)
+ STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst)
+ STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst)
+ STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst)
+ STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst)
+ STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst)
+ STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst)
+ STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst)
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
+ [temp9]"=&r"(temp9)
+ : [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples
+ int temp0, temp1;
+ __asm__ volatile (
+ LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst)
+ "raddu.w.qb %[temp0], %[temp0] \n\t"
+ "raddu.w.qb %[temp1], %[temp1] \n\t"
+ "addu %[temp0], %[temp0], %[temp1] \n\t"
+ "shra_r.w %[temp0], %[temp0], 3 \n\t"
+ "replv.qb %[temp0], %[temp0] \n\t"
+ STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst)
+ STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst)
+ STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst)
+ STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst)
+ STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst)
+ STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst)
+ STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst)
+ STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst)
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1)
+ : [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples
+ int temp0, temp1, temp2, temp3, temp4;
+ int temp5, temp6, temp7, temp8;
+ __asm__ volatile (
+ LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst)
+ LOAD_4_BYTES(temp6, temp7, temp8, temp1, -1, 4, -1, 5, -1, 6, -1, 7, dst)
+ "addu %[temp2], %[temp2], %[temp3] \n\t"
+ "addu %[temp4], %[temp4], %[temp5] \n\t"
+ "addu %[temp6], %[temp6], %[temp7] \n\t"
+ "addu %[temp8], %[temp8], %[temp1] \n\t"
+ "addu %[temp2], %[temp2], %[temp4] \n\t"
+ "addu %[temp6], %[temp6], %[temp8] \n\t"
+ "addu %[temp0], %[temp6], %[temp2] \n\t"
+ "shra_r.w %[temp0], %[temp0], 3 \n\t"
+ "replv.qb %[temp0], %[temp0] \n\t"
+ STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst)
+ STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst)
+ STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst)
+ STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst)
+ STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst)
+ STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst)
+ STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst)
+ STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst)
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8)
+ : [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+#undef LOAD_8_BYTES
+#undef STORE_8_BYTES
+#undef LOAD_4_BYTES
+
+#define CLIPPING(SIZE) \
+ "preceu.ph.qbl %[temp2], %[temp0] \n\t" \
+ "preceu.ph.qbr %[temp0], %[temp0] \n\t" \
+".if " #SIZE " == 8 \n\t" \
+ "preceu.ph.qbl %[temp3], %[temp1] \n\t" \
+ "preceu.ph.qbr %[temp1], %[temp1] \n\t" \
+".endif \n\t" \
+ "addu.ph %[temp2], %[temp2], %[dst_1] \n\t" \
+ "addu.ph %[temp0], %[temp0], %[dst_1] \n\t" \
+".if " #SIZE " == 8 \n\t" \
+ "addu.ph %[temp3], %[temp3], %[dst_1] \n\t" \
+ "addu.ph %[temp1], %[temp1], %[dst_1] \n\t" \
+".endif \n\t" \
+ "shll_s.ph %[temp2], %[temp2], 7 \n\t" \
+ "shll_s.ph %[temp0], %[temp0], 7 \n\t" \
+".if " #SIZE " == 8 \n\t" \
+ "shll_s.ph %[temp3], %[temp3], 7 \n\t" \
+ "shll_s.ph %[temp1], %[temp1], 7 \n\t" \
+".endif \n\t" \
+ "precrqu_s.qb.ph %[temp0], %[temp2], %[temp0] \n\t" \
+".if " #SIZE " == 8 \n\t" \
+ "precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t" \
+".endif \n\t"
+
+
+#define CLIP_8B_TO_DST(DST, TOP, SIZE) do { \
+ int dst_1 = ((int)(DST)[-1] << 16) + (DST)[-1]; \
+ int temp0, temp1, temp2, temp3; \
+ __asm__ volatile ( \
+ ".if " #SIZE " < 8 \n\t" \
+ "ulw %[temp0], 0(%[top]) \n\t" \
+ "subu.ph %[dst_1], %[dst_1], %[top_1] \n\t" \
+ CLIPPING(4) \
+ "usw %[temp0], 0(%[dst]) \n\t" \
+ ".else \n\t" \
+ "ulw %[temp0], 0(%[top]) \n\t" \
+ "ulw %[temp1], 4(%[top]) \n\t" \
+ "subu.ph %[dst_1], %[dst_1], %[top_1] \n\t" \
+ CLIPPING(8) \
+ "usw %[temp0], 0(%[dst]) \n\t" \
+ "usw %[temp1], 4(%[dst]) \n\t" \
+ ".if " #SIZE " == 16 \n\t" \
+ "ulw %[temp0], 8(%[top]) \n\t" \
+ "ulw %[temp1], 12(%[top]) \n\t" \
+ CLIPPING(8) \
+ "usw %[temp0], 8(%[dst]) \n\t" \
+ "usw %[temp1], 12(%[dst]) \n\t" \
+ ".endif \n\t" \
+ ".endif \n\t" \
+ : [dst_1]"+&r"(dst_1), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \
+ [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \
+ : [top_1]"r"(top_1), [top]"r"((TOP)), [dst]"r"((DST)) \
+ : "memory" \
+ ); \
+} while (0)
+
+#define CLIP_TO_DST(DST, SIZE) do { \
+ int y; \
+ const uint8_t* top = (DST) - BPS; \
+ const int top_1 = ((int)top[-1] << 16) + top[-1]; \
+ for (y = 0; y < (SIZE); ++y) { \
+ CLIP_8B_TO_DST((DST), top, (SIZE)); \
+ (DST) += BPS; \
+ } \
+} while (0)
+
+#define TRUE_MOTION(DST, SIZE) \
+static void TrueMotion##SIZE(uint8_t* (DST)) { \
+ CLIP_TO_DST((DST), (SIZE)); \
+}
+
+TRUE_MOTION(dst, 4)
+TRUE_MOTION(dst, 8)
+TRUE_MOTION(dst, 16)
+
+#undef TRUE_MOTION
+#undef CLIP_TO_DST
+#undef CLIP_8B_TO_DST
+#undef CLIPPING
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8DspInitMIPSdspR2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMIPSdspR2(void) {
+ VP8TransformDC = TransformDC;
+ VP8TransformAC3 = TransformAC3;
+ VP8Transform = TransformTwo;
+
+ VP8VFilter16 = VFilter16;
+ VP8HFilter16 = HFilter16;
+ VP8VFilter8 = VFilter8;
+ VP8HFilter8 = HFilter8;
+ VP8VFilter16i = VFilter16i;
+ VP8HFilter16i = HFilter16i;
+ VP8VFilter8i = VFilter8i;
+ VP8HFilter8i = HFilter8i;
+ VP8SimpleVFilter16 = SimpleVFilter16;
+ VP8SimpleHFilter16 = SimpleHFilter16;
+ VP8SimpleVFilter16i = SimpleVFilter16i;
+ VP8SimpleHFilter16i = SimpleHFilter16i;
+
+ VP8PredLuma4[0] = DC4;
+ VP8PredLuma4[1] = TrueMotion4;
+ VP8PredLuma4[2] = VE4;
+ VP8PredLuma4[4] = RD4;
+ VP8PredLuma4[6] = LD4;
+
+ VP8PredChroma8[0] = DC8uv;
+ VP8PredChroma8[1] = TrueMotion8;
+ VP8PredChroma8[4] = DC8uvNoTop;
+ VP8PredChroma8[5] = DC8uvNoLeft;
+
+ VP8PredLuma16[1] = TrueMotion16;
+}
+
+#else // !WEBP_USE_MIPS_DSP_R2
+
+WEBP_DSP_INIT_STUB(VP8DspInitMIPSdspR2)
+
+#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/dec_neon.c b/drivers/webp/dsp/dec_neon.c
index ec824b790b..a63f43fe17 100644
--- a/drivers/webp/dsp/dec_neon.c
+++ b/drivers/webp/dsp/dec_neon.c
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// ARM NEON version of dsp functions and loop filtering.
@@ -14,13 +16,535 @@
#if defined(WEBP_USE_NEON)
+#include "./neon.h"
#include "../dec/vp8i.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+//------------------------------------------------------------------------------
+// NxM Loading functions
+
+// Load/Store vertical edge
+#define LOAD8x4(c1, c2, c3, c4, b1, b2, stride) \
+ "vld4.8 {" #c1 "[0]," #c2 "[0]," #c3 "[0]," #c4 "[0]}," #b1 "," #stride "\n" \
+ "vld4.8 {" #c1 "[1]," #c2 "[1]," #c3 "[1]," #c4 "[1]}," #b2 "," #stride "\n" \
+ "vld4.8 {" #c1 "[2]," #c2 "[2]," #c3 "[2]," #c4 "[2]}," #b1 "," #stride "\n" \
+ "vld4.8 {" #c1 "[3]," #c2 "[3]," #c3 "[3]," #c4 "[3]}," #b2 "," #stride "\n" \
+ "vld4.8 {" #c1 "[4]," #c2 "[4]," #c3 "[4]," #c4 "[4]}," #b1 "," #stride "\n" \
+ "vld4.8 {" #c1 "[5]," #c2 "[5]," #c3 "[5]," #c4 "[5]}," #b2 "," #stride "\n" \
+ "vld4.8 {" #c1 "[6]," #c2 "[6]," #c3 "[6]," #c4 "[6]}," #b1 "," #stride "\n" \
+ "vld4.8 {" #c1 "[7]," #c2 "[7]," #c3 "[7]," #c4 "[7]}," #b2 "," #stride "\n"
+
+#define STORE8x2(c1, c2, p, stride) \
+ "vst2.8 {" #c1 "[0], " #c2 "[0]}," #p "," #stride " \n" \
+ "vst2.8 {" #c1 "[1], " #c2 "[1]}," #p "," #stride " \n" \
+ "vst2.8 {" #c1 "[2], " #c2 "[2]}," #p "," #stride " \n" \
+ "vst2.8 {" #c1 "[3], " #c2 "[3]}," #p "," #stride " \n" \
+ "vst2.8 {" #c1 "[4], " #c2 "[4]}," #p "," #stride " \n" \
+ "vst2.8 {" #c1 "[5], " #c2 "[5]}," #p "," #stride " \n" \
+ "vst2.8 {" #c1 "[6], " #c2 "[6]}," #p "," #stride " \n" \
+ "vst2.8 {" #c1 "[7], " #c2 "[7]}," #p "," #stride " \n"
+
+#if !defined(WORK_AROUND_GCC)
+
+// This intrinsics version makes gcc-4.6.3 crash during Load4x??() compilation
+// (register alloc, probably). The variants somewhat mitigate the problem, but
+// not quite. HFilter16i() remains problematic.
+static WEBP_INLINE uint8x8x4_t Load4x8(const uint8_t* const src, int stride) {
+ const uint8x8_t zero = vdup_n_u8(0);
+ uint8x8x4_t out;
+ INIT_VECTOR4(out, zero, zero, zero, zero);
+ out = vld4_lane_u8(src + 0 * stride, out, 0);
+ out = vld4_lane_u8(src + 1 * stride, out, 1);
+ out = vld4_lane_u8(src + 2 * stride, out, 2);
+ out = vld4_lane_u8(src + 3 * stride, out, 3);
+ out = vld4_lane_u8(src + 4 * stride, out, 4);
+ out = vld4_lane_u8(src + 5 * stride, out, 5);
+ out = vld4_lane_u8(src + 6 * stride, out, 6);
+ out = vld4_lane_u8(src + 7 * stride, out, 7);
+ return out;
+}
+
+static WEBP_INLINE void Load4x16(const uint8_t* const src, int stride,
+ uint8x16_t* const p1, uint8x16_t* const p0,
+ uint8x16_t* const q0, uint8x16_t* const q1) {
+ // row0 = p1[0..7]|p0[0..7]|q0[0..7]|q1[0..7]
+ // row8 = p1[8..15]|p0[8..15]|q0[8..15]|q1[8..15]
+ const uint8x8x4_t row0 = Load4x8(src - 2 + 0 * stride, stride);
+ const uint8x8x4_t row8 = Load4x8(src - 2 + 8 * stride, stride);
+ *p1 = vcombine_u8(row0.val[0], row8.val[0]);
+ *p0 = vcombine_u8(row0.val[1], row8.val[1]);
+ *q0 = vcombine_u8(row0.val[2], row8.val[2]);
+ *q1 = vcombine_u8(row0.val[3], row8.val[3]);
+}
+
+#else // WORK_AROUND_GCC
+
+#define LOADQ_LANE_32b(VALUE, LANE) do { \
+ (VALUE) = vld1q_lane_u32((const uint32_t*)src, (VALUE), (LANE)); \
+ src += stride; \
+} while (0)
+
+static WEBP_INLINE void Load4x16(const uint8_t* src, int stride,
+ uint8x16_t* const p1, uint8x16_t* const p0,
+ uint8x16_t* const q0, uint8x16_t* const q1) {
+ const uint32x4_t zero = vdupq_n_u32(0);
+ uint32x4x4_t in;
+ INIT_VECTOR4(in, zero, zero, zero, zero);
+ src -= 2;
+ LOADQ_LANE_32b(in.val[0], 0);
+ LOADQ_LANE_32b(in.val[1], 0);
+ LOADQ_LANE_32b(in.val[2], 0);
+ LOADQ_LANE_32b(in.val[3], 0);
+ LOADQ_LANE_32b(in.val[0], 1);
+ LOADQ_LANE_32b(in.val[1], 1);
+ LOADQ_LANE_32b(in.val[2], 1);
+ LOADQ_LANE_32b(in.val[3], 1);
+ LOADQ_LANE_32b(in.val[0], 2);
+ LOADQ_LANE_32b(in.val[1], 2);
+ LOADQ_LANE_32b(in.val[2], 2);
+ LOADQ_LANE_32b(in.val[3], 2);
+ LOADQ_LANE_32b(in.val[0], 3);
+ LOADQ_LANE_32b(in.val[1], 3);
+ LOADQ_LANE_32b(in.val[2], 3);
+ LOADQ_LANE_32b(in.val[3], 3);
+ // Transpose four 4x4 parts:
+ {
+ const uint8x16x2_t row01 = vtrnq_u8(vreinterpretq_u8_u32(in.val[0]),
+ vreinterpretq_u8_u32(in.val[1]));
+ const uint8x16x2_t row23 = vtrnq_u8(vreinterpretq_u8_u32(in.val[2]),
+ vreinterpretq_u8_u32(in.val[3]));
+ const uint16x8x2_t row02 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[0]),
+ vreinterpretq_u16_u8(row23.val[0]));
+ const uint16x8x2_t row13 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[1]),
+ vreinterpretq_u16_u8(row23.val[1]));
+ *p1 = vreinterpretq_u8_u16(row02.val[0]);
+ *p0 = vreinterpretq_u8_u16(row13.val[0]);
+ *q0 = vreinterpretq_u8_u16(row02.val[1]);
+ *q1 = vreinterpretq_u8_u16(row13.val[1]);
+ }
+}
+#undef LOADQ_LANE_32b
+
+#endif // !WORK_AROUND_GCC
+
+static WEBP_INLINE void Load8x16(const uint8_t* const src, int stride,
+ uint8x16_t* const p3, uint8x16_t* const p2,
+ uint8x16_t* const p1, uint8x16_t* const p0,
+ uint8x16_t* const q0, uint8x16_t* const q1,
+ uint8x16_t* const q2, uint8x16_t* const q3) {
+ Load4x16(src - 2, stride, p3, p2, p1, p0);
+ Load4x16(src + 2, stride, q0, q1, q2, q3);
+}
+
+static WEBP_INLINE void Load16x4(const uint8_t* const src, int stride,
+ uint8x16_t* const p1, uint8x16_t* const p0,
+ uint8x16_t* const q0, uint8x16_t* const q1) {
+ *p1 = vld1q_u8(src - 2 * stride);
+ *p0 = vld1q_u8(src - 1 * stride);
+ *q0 = vld1q_u8(src + 0 * stride);
+ *q1 = vld1q_u8(src + 1 * stride);
+}
+
+static WEBP_INLINE void Load16x8(const uint8_t* const src, int stride,
+ uint8x16_t* const p3, uint8x16_t* const p2,
+ uint8x16_t* const p1, uint8x16_t* const p0,
+ uint8x16_t* const q0, uint8x16_t* const q1,
+ uint8x16_t* const q2, uint8x16_t* const q3) {
+ Load16x4(src - 2 * stride, stride, p3, p2, p1, p0);
+ Load16x4(src + 2 * stride, stride, q0, q1, q2, q3);
+}
+
+static WEBP_INLINE void Load8x8x2(const uint8_t* const u,
+ const uint8_t* const v,
+ int stride,
+ uint8x16_t* const p3, uint8x16_t* const p2,
+ uint8x16_t* const p1, uint8x16_t* const p0,
+ uint8x16_t* const q0, uint8x16_t* const q1,
+ uint8x16_t* const q2, uint8x16_t* const q3) {
+ // We pack the 8x8 u-samples in the lower half of the uint8x16_t destination
+ // and the v-samples on the higher half.
+ *p3 = vcombine_u8(vld1_u8(u - 4 * stride), vld1_u8(v - 4 * stride));
+ *p2 = vcombine_u8(vld1_u8(u - 3 * stride), vld1_u8(v - 3 * stride));
+ *p1 = vcombine_u8(vld1_u8(u - 2 * stride), vld1_u8(v - 2 * stride));
+ *p0 = vcombine_u8(vld1_u8(u - 1 * stride), vld1_u8(v - 1 * stride));
+ *q0 = vcombine_u8(vld1_u8(u + 0 * stride), vld1_u8(v + 0 * stride));
+ *q1 = vcombine_u8(vld1_u8(u + 1 * stride), vld1_u8(v + 1 * stride));
+ *q2 = vcombine_u8(vld1_u8(u + 2 * stride), vld1_u8(v + 2 * stride));
+ *q3 = vcombine_u8(vld1_u8(u + 3 * stride), vld1_u8(v + 3 * stride));
+}
+
+#if !defined(WORK_AROUND_GCC)
+
+#define LOAD_UV_8(ROW) \
+ vcombine_u8(vld1_u8(u - 4 + (ROW) * stride), vld1_u8(v - 4 + (ROW) * stride))
+
+static WEBP_INLINE void Load8x8x2T(const uint8_t* const u,
+ const uint8_t* const v,
+ int stride,
+ uint8x16_t* const p3, uint8x16_t* const p2,
+ uint8x16_t* const p1, uint8x16_t* const p0,
+ uint8x16_t* const q0, uint8x16_t* const q1,
+ uint8x16_t* const q2, uint8x16_t* const q3) {
+ // We pack the 8x8 u-samples in the lower half of the uint8x16_t destination
+ // and the v-samples on the higher half.
+ const uint8x16_t row0 = LOAD_UV_8(0);
+ const uint8x16_t row1 = LOAD_UV_8(1);
+ const uint8x16_t row2 = LOAD_UV_8(2);
+ const uint8x16_t row3 = LOAD_UV_8(3);
+ const uint8x16_t row4 = LOAD_UV_8(4);
+ const uint8x16_t row5 = LOAD_UV_8(5);
+ const uint8x16_t row6 = LOAD_UV_8(6);
+ const uint8x16_t row7 = LOAD_UV_8(7);
+ // Perform two side-by-side 8x8 transposes
+ // u00 u01 u02 u03 u04 u05 u06 u07 | v00 v01 v02 v03 v04 v05 v06 v07
+ // u10 u11 u12 u13 u14 u15 u16 u17 | v10 v11 v12 ...
+ // u20 u21 u22 u23 u24 u25 u26 u27 | v20 v21 ...
+ // u30 u31 u32 u33 u34 u35 u36 u37 | ...
+ // u40 u41 u42 u43 u44 u45 u46 u47 | ...
+ // u50 u51 u52 u53 u54 u55 u56 u57 | ...
+ // u60 u61 u62 u63 u64 u65 u66 u67 | v60 ...
+ // u70 u71 u72 u73 u74 u75 u76 u77 | v70 v71 v72 ...
+ const uint8x16x2_t row01 = vtrnq_u8(row0, row1); // u00 u10 u02 u12 ...
+ // u01 u11 u03 u13 ...
+ const uint8x16x2_t row23 = vtrnq_u8(row2, row3); // u20 u30 u22 u32 ...
+ // u21 u31 u23 u33 ...
+ const uint8x16x2_t row45 = vtrnq_u8(row4, row5); // ...
+ const uint8x16x2_t row67 = vtrnq_u8(row6, row7); // ...
+ const uint16x8x2_t row02 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[0]),
+ vreinterpretq_u16_u8(row23.val[0]));
+ const uint16x8x2_t row13 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[1]),
+ vreinterpretq_u16_u8(row23.val[1]));
+ const uint16x8x2_t row46 = vtrnq_u16(vreinterpretq_u16_u8(row45.val[0]),
+ vreinterpretq_u16_u8(row67.val[0]));
+ const uint16x8x2_t row57 = vtrnq_u16(vreinterpretq_u16_u8(row45.val[1]),
+ vreinterpretq_u16_u8(row67.val[1]));
+ const uint32x4x2_t row04 = vtrnq_u32(vreinterpretq_u32_u16(row02.val[0]),
+ vreinterpretq_u32_u16(row46.val[0]));
+ const uint32x4x2_t row26 = vtrnq_u32(vreinterpretq_u32_u16(row02.val[1]),
+ vreinterpretq_u32_u16(row46.val[1]));
+ const uint32x4x2_t row15 = vtrnq_u32(vreinterpretq_u32_u16(row13.val[0]),
+ vreinterpretq_u32_u16(row57.val[0]));
+ const uint32x4x2_t row37 = vtrnq_u32(vreinterpretq_u32_u16(row13.val[1]),
+ vreinterpretq_u32_u16(row57.val[1]));
+ *p3 = vreinterpretq_u8_u32(row04.val[0]);
+ *p2 = vreinterpretq_u8_u32(row15.val[0]);
+ *p1 = vreinterpretq_u8_u32(row26.val[0]);
+ *p0 = vreinterpretq_u8_u32(row37.val[0]);
+ *q0 = vreinterpretq_u8_u32(row04.val[1]);
+ *q1 = vreinterpretq_u8_u32(row15.val[1]);
+ *q2 = vreinterpretq_u8_u32(row26.val[1]);
+ *q3 = vreinterpretq_u8_u32(row37.val[1]);
+}
+#undef LOAD_UV_8
+
+#endif // !WORK_AROUND_GCC
+
+static WEBP_INLINE void Store2x8(const uint8x8x2_t v,
+ uint8_t* const dst, int stride) {
+ vst2_lane_u8(dst + 0 * stride, v, 0);
+ vst2_lane_u8(dst + 1 * stride, v, 1);
+ vst2_lane_u8(dst + 2 * stride, v, 2);
+ vst2_lane_u8(dst + 3 * stride, v, 3);
+ vst2_lane_u8(dst + 4 * stride, v, 4);
+ vst2_lane_u8(dst + 5 * stride, v, 5);
+ vst2_lane_u8(dst + 6 * stride, v, 6);
+ vst2_lane_u8(dst + 7 * stride, v, 7);
+}
-#define QRegs "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", \
+static WEBP_INLINE void Store2x16(const uint8x16_t p0, const uint8x16_t q0,
+ uint8_t* const dst, int stride) {
+ uint8x8x2_t lo, hi;
+ lo.val[0] = vget_low_u8(p0);
+ lo.val[1] = vget_low_u8(q0);
+ hi.val[0] = vget_high_u8(p0);
+ hi.val[1] = vget_high_u8(q0);
+ Store2x8(lo, dst - 1 + 0 * stride, stride);
+ Store2x8(hi, dst - 1 + 8 * stride, stride);
+}
+
+#if !defined(WORK_AROUND_GCC)
+static WEBP_INLINE void Store4x8(const uint8x8x4_t v,
+ uint8_t* const dst, int stride) {
+ vst4_lane_u8(dst + 0 * stride, v, 0);
+ vst4_lane_u8(dst + 1 * stride, v, 1);
+ vst4_lane_u8(dst + 2 * stride, v, 2);
+ vst4_lane_u8(dst + 3 * stride, v, 3);
+ vst4_lane_u8(dst + 4 * stride, v, 4);
+ vst4_lane_u8(dst + 5 * stride, v, 5);
+ vst4_lane_u8(dst + 6 * stride, v, 6);
+ vst4_lane_u8(dst + 7 * stride, v, 7);
+}
+
+static WEBP_INLINE void Store4x16(const uint8x16_t p1, const uint8x16_t p0,
+ const uint8x16_t q0, const uint8x16_t q1,
+ uint8_t* const dst, int stride) {
+ uint8x8x4_t lo, hi;
+ INIT_VECTOR4(lo,
+ vget_low_u8(p1), vget_low_u8(p0),
+ vget_low_u8(q0), vget_low_u8(q1));
+ INIT_VECTOR4(hi,
+ vget_high_u8(p1), vget_high_u8(p0),
+ vget_high_u8(q0), vget_high_u8(q1));
+ Store4x8(lo, dst - 2 + 0 * stride, stride);
+ Store4x8(hi, dst - 2 + 8 * stride, stride);
+}
+#endif // !WORK_AROUND_GCC
+
+static WEBP_INLINE void Store16x2(const uint8x16_t p0, const uint8x16_t q0,
+ uint8_t* const dst, int stride) {
+ vst1q_u8(dst - stride, p0);
+ vst1q_u8(dst, q0);
+}
+
+static WEBP_INLINE void Store16x4(const uint8x16_t p1, const uint8x16_t p0,
+ const uint8x16_t q0, const uint8x16_t q1,
+ uint8_t* const dst, int stride) {
+ Store16x2(p1, p0, dst - stride, stride);
+ Store16x2(q0, q1, dst + stride, stride);
+}
+
+static WEBP_INLINE void Store8x2x2(const uint8x16_t p0, const uint8x16_t q0,
+ uint8_t* const u, uint8_t* const v,
+ int stride) {
+ // p0 and q0 contain the u+v samples packed in low/high halves.
+ vst1_u8(u - stride, vget_low_u8(p0));
+ vst1_u8(u, vget_low_u8(q0));
+ vst1_u8(v - stride, vget_high_u8(p0));
+ vst1_u8(v, vget_high_u8(q0));
+}
+
+static WEBP_INLINE void Store8x4x2(const uint8x16_t p1, const uint8x16_t p0,
+ const uint8x16_t q0, const uint8x16_t q1,
+ uint8_t* const u, uint8_t* const v,
+ int stride) {
+ // The p1...q1 registers contain the u+v samples packed in low/high halves.
+ Store8x2x2(p1, p0, u - stride, v - stride, stride);
+ Store8x2x2(q0, q1, u + stride, v + stride, stride);
+}
+
+#if !defined(WORK_AROUND_GCC)
+
+#define STORE6_LANE(DST, VAL0, VAL1, LANE) do { \
+ vst3_lane_u8((DST) - 3, (VAL0), (LANE)); \
+ vst3_lane_u8((DST) + 0, (VAL1), (LANE)); \
+ (DST) += stride; \
+} while (0)
+
+static WEBP_INLINE void Store6x8x2(const uint8x16_t p2, const uint8x16_t p1,
+ const uint8x16_t p0, const uint8x16_t q0,
+ const uint8x16_t q1, const uint8x16_t q2,
+ uint8_t* u, uint8_t* v,
+ int stride) {
+ uint8x8x3_t u0, u1, v0, v1;
+ INIT_VECTOR3(u0, vget_low_u8(p2), vget_low_u8(p1), vget_low_u8(p0));
+ INIT_VECTOR3(u1, vget_low_u8(q0), vget_low_u8(q1), vget_low_u8(q2));
+ INIT_VECTOR3(v0, vget_high_u8(p2), vget_high_u8(p1), vget_high_u8(p0));
+ INIT_VECTOR3(v1, vget_high_u8(q0), vget_high_u8(q1), vget_high_u8(q2));
+ STORE6_LANE(u, u0, u1, 0);
+ STORE6_LANE(u, u0, u1, 1);
+ STORE6_LANE(u, u0, u1, 2);
+ STORE6_LANE(u, u0, u1, 3);
+ STORE6_LANE(u, u0, u1, 4);
+ STORE6_LANE(u, u0, u1, 5);
+ STORE6_LANE(u, u0, u1, 6);
+ STORE6_LANE(u, u0, u1, 7);
+ STORE6_LANE(v, v0, v1, 0);
+ STORE6_LANE(v, v0, v1, 1);
+ STORE6_LANE(v, v0, v1, 2);
+ STORE6_LANE(v, v0, v1, 3);
+ STORE6_LANE(v, v0, v1, 4);
+ STORE6_LANE(v, v0, v1, 5);
+ STORE6_LANE(v, v0, v1, 6);
+ STORE6_LANE(v, v0, v1, 7);
+}
+#undef STORE6_LANE
+
+static WEBP_INLINE void Store4x8x2(const uint8x16_t p1, const uint8x16_t p0,
+ const uint8x16_t q0, const uint8x16_t q1,
+ uint8_t* const u, uint8_t* const v,
+ int stride) {
+ uint8x8x4_t u0, v0;
+ INIT_VECTOR4(u0,
+ vget_low_u8(p1), vget_low_u8(p0),
+ vget_low_u8(q0), vget_low_u8(q1));
+ INIT_VECTOR4(v0,
+ vget_high_u8(p1), vget_high_u8(p0),
+ vget_high_u8(q0), vget_high_u8(q1));
+ vst4_lane_u8(u - 2 + 0 * stride, u0, 0);
+ vst4_lane_u8(u - 2 + 1 * stride, u0, 1);
+ vst4_lane_u8(u - 2 + 2 * stride, u0, 2);
+ vst4_lane_u8(u - 2 + 3 * stride, u0, 3);
+ vst4_lane_u8(u - 2 + 4 * stride, u0, 4);
+ vst4_lane_u8(u - 2 + 5 * stride, u0, 5);
+ vst4_lane_u8(u - 2 + 6 * stride, u0, 6);
+ vst4_lane_u8(u - 2 + 7 * stride, u0, 7);
+ vst4_lane_u8(v - 2 + 0 * stride, v0, 0);
+ vst4_lane_u8(v - 2 + 1 * stride, v0, 1);
+ vst4_lane_u8(v - 2 + 2 * stride, v0, 2);
+ vst4_lane_u8(v - 2 + 3 * stride, v0, 3);
+ vst4_lane_u8(v - 2 + 4 * stride, v0, 4);
+ vst4_lane_u8(v - 2 + 5 * stride, v0, 5);
+ vst4_lane_u8(v - 2 + 6 * stride, v0, 6);
+ vst4_lane_u8(v - 2 + 7 * stride, v0, 7);
+}
+
+#endif // !WORK_AROUND_GCC
+
+// Zero extend 'v' to an int16x8_t.
+static WEBP_INLINE int16x8_t ConvertU8ToS16(uint8x8_t v) {
+ return vreinterpretq_s16_u16(vmovl_u8(v));
+}
+
+// Performs unsigned 8b saturation on 'dst01' and 'dst23' storing the result
+// to the corresponding rows of 'dst'.
+static WEBP_INLINE void SaturateAndStore4x4(uint8_t* const dst,
+ const int16x8_t dst01,
+ const int16x8_t dst23) {
+ // Unsigned saturate to 8b.
+ const uint8x8_t dst01_u8 = vqmovun_s16(dst01);
+ const uint8x8_t dst23_u8 = vqmovun_s16(dst23);
+
+ // Store the results.
+ vst1_lane_u32((uint32_t*)(dst + 0 * BPS), vreinterpret_u32_u8(dst01_u8), 0);
+ vst1_lane_u32((uint32_t*)(dst + 1 * BPS), vreinterpret_u32_u8(dst01_u8), 1);
+ vst1_lane_u32((uint32_t*)(dst + 2 * BPS), vreinterpret_u32_u8(dst23_u8), 0);
+ vst1_lane_u32((uint32_t*)(dst + 3 * BPS), vreinterpret_u32_u8(dst23_u8), 1);
+}
+
+static WEBP_INLINE void Add4x4(const int16x8_t row01, const int16x8_t row23,
+ uint8_t* const dst) {
+ uint32x2_t dst01 = vdup_n_u32(0);
+ uint32x2_t dst23 = vdup_n_u32(0);
+
+ // Load the source pixels.
+ dst01 = vld1_lane_u32((uint32_t*)(dst + 0 * BPS), dst01, 0);
+ dst23 = vld1_lane_u32((uint32_t*)(dst + 2 * BPS), dst23, 0);
+ dst01 = vld1_lane_u32((uint32_t*)(dst + 1 * BPS), dst01, 1);
+ dst23 = vld1_lane_u32((uint32_t*)(dst + 3 * BPS), dst23, 1);
+
+ {
+ // Convert to 16b.
+ const int16x8_t dst01_s16 = ConvertU8ToS16(vreinterpret_u8_u32(dst01));
+ const int16x8_t dst23_s16 = ConvertU8ToS16(vreinterpret_u8_u32(dst23));
+
+ // Descale with rounding.
+ const int16x8_t out01 = vrsraq_n_s16(dst01_s16, row01, 3);
+ const int16x8_t out23 = vrsraq_n_s16(dst23_s16, row23, 3);
+ // Add the inverse transform.
+ SaturateAndStore4x4(dst, out01, out23);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Simple In-loop filtering (Paragraph 15.2)
+
+static uint8x16_t NeedsFilter(const uint8x16_t p1, const uint8x16_t p0,
+ const uint8x16_t q0, const uint8x16_t q1,
+ int thresh) {
+ const uint8x16_t thresh_v = vdupq_n_u8((uint8_t)thresh);
+ const uint8x16_t a_p0_q0 = vabdq_u8(p0, q0); // abs(p0-q0)
+ const uint8x16_t a_p1_q1 = vabdq_u8(p1, q1); // abs(p1-q1)
+ const uint8x16_t a_p0_q0_2 = vqaddq_u8(a_p0_q0, a_p0_q0); // 2 * abs(p0-q0)
+ const uint8x16_t a_p1_q1_2 = vshrq_n_u8(a_p1_q1, 1); // abs(p1-q1) / 2
+ const uint8x16_t sum = vqaddq_u8(a_p0_q0_2, a_p1_q1_2);
+ const uint8x16_t mask = vcgeq_u8(thresh_v, sum);
+ return mask;
+}
+
+static int8x16_t FlipSign(const uint8x16_t v) {
+ const uint8x16_t sign_bit = vdupq_n_u8(0x80);
+ return vreinterpretq_s8_u8(veorq_u8(v, sign_bit));
+}
+
+static uint8x16_t FlipSignBack(const int8x16_t v) {
+ const int8x16_t sign_bit = vdupq_n_s8(0x80);
+ return vreinterpretq_u8_s8(veorq_s8(v, sign_bit));
+}
+
+static int8x16_t GetBaseDelta(const int8x16_t p1, const int8x16_t p0,
+ const int8x16_t q0, const int8x16_t q1) {
+ const int8x16_t q0_p0 = vqsubq_s8(q0, p0); // (q0-p0)
+ const int8x16_t p1_q1 = vqsubq_s8(p1, q1); // (p1-q1)
+ const int8x16_t s1 = vqaddq_s8(p1_q1, q0_p0); // (p1-q1) + 1 * (q0 - p0)
+ const int8x16_t s2 = vqaddq_s8(q0_p0, s1); // (p1-q1) + 2 * (q0 - p0)
+ const int8x16_t s3 = vqaddq_s8(q0_p0, s2); // (p1-q1) + 3 * (q0 - p0)
+ return s3;
+}
+
+static int8x16_t GetBaseDelta0(const int8x16_t p0, const int8x16_t q0) {
+ const int8x16_t q0_p0 = vqsubq_s8(q0, p0); // (q0-p0)
+ const int8x16_t s1 = vqaddq_s8(q0_p0, q0_p0); // 2 * (q0 - p0)
+ const int8x16_t s2 = vqaddq_s8(q0_p0, s1); // 3 * (q0 - p0)
+ return s2;
+}
+
+//------------------------------------------------------------------------------
+
+static void ApplyFilter2NoFlip(const int8x16_t p0s, const int8x16_t q0s,
+ const int8x16_t delta,
+ int8x16_t* const op0, int8x16_t* const oq0) {
+ const int8x16_t kCst3 = vdupq_n_s8(0x03);
+ const int8x16_t kCst4 = vdupq_n_s8(0x04);
+ const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3);
+ const int8x16_t delta_p4 = vqaddq_s8(delta, kCst4);
+ const int8x16_t delta3 = vshrq_n_s8(delta_p3, 3);
+ const int8x16_t delta4 = vshrq_n_s8(delta_p4, 3);
+ *op0 = vqaddq_s8(p0s, delta3);
+ *oq0 = vqsubq_s8(q0s, delta4);
+}
+
+#if defined(WEBP_USE_INTRINSICS)
+
+static void ApplyFilter2(const int8x16_t p0s, const int8x16_t q0s,
+ const int8x16_t delta,
+ uint8x16_t* const op0, uint8x16_t* const oq0) {
+ const int8x16_t kCst3 = vdupq_n_s8(0x03);
+ const int8x16_t kCst4 = vdupq_n_s8(0x04);
+ const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3);
+ const int8x16_t delta_p4 = vqaddq_s8(delta, kCst4);
+ const int8x16_t delta3 = vshrq_n_s8(delta_p3, 3);
+ const int8x16_t delta4 = vshrq_n_s8(delta_p4, 3);
+ const int8x16_t sp0 = vqaddq_s8(p0s, delta3);
+ const int8x16_t sq0 = vqsubq_s8(q0s, delta4);
+ *op0 = FlipSignBack(sp0);
+ *oq0 = FlipSignBack(sq0);
+}
+
+static void DoFilter2(const uint8x16_t p1, const uint8x16_t p0,
+ const uint8x16_t q0, const uint8x16_t q1,
+ const uint8x16_t mask,
+ uint8x16_t* const op0, uint8x16_t* const oq0) {
+ const int8x16_t p1s = FlipSign(p1);
+ const int8x16_t p0s = FlipSign(p0);
+ const int8x16_t q0s = FlipSign(q0);
+ const int8x16_t q1s = FlipSign(q1);
+ const int8x16_t delta0 = GetBaseDelta(p1s, p0s, q0s, q1s);
+ const int8x16_t delta1 = vandq_s8(delta0, vreinterpretq_s8_u8(mask));
+ ApplyFilter2(p0s, q0s, delta1, op0, oq0);
+}
+
+static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
+ uint8x16_t p1, p0, q0, q1, op0, oq0;
+ Load16x4(p, stride, &p1, &p0, &q0, &q1);
+ {
+ const uint8x16_t mask = NeedsFilter(p1, p0, q0, q1, thresh);
+ DoFilter2(p1, p0, q0, q1, mask, &op0, &oq0);
+ }
+ Store16x2(op0, oq0, p, stride);
+}
+
+static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
+ uint8x16_t p1, p0, q0, q1, oq0, op0;
+ Load4x16(p, stride, &p1, &p0, &q0, &q1);
+ {
+ const uint8x16_t mask = NeedsFilter(p1, p0, q0, q1, thresh);
+ DoFilter2(p1, p0, q0, q1, mask, &op0, &oq0);
+ }
+ Store2x16(op0, oq0, p, stride);
+}
+
+#else
+
+#define QRegs "q0", "q1", "q2", "q3", \
"q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
#define FLIP_SIGN_BIT2(a, b, s) \
@@ -68,40 +592,16 @@ extern "C" {
DO_SIMPLE_FILTER(p0, q0, q9) /* apply filter */ \
FLIP_SIGN_BIT2(p0, q0, q10)
-// Load/Store vertical edge
-#define LOAD8x4(c1, c2, c3, c4, b1, b2, stride) \
- "vld4.8 {" #c1"[0], " #c2"[0], " #c3"[0], " #c4"[0]}," #b1 "," #stride"\n" \
- "vld4.8 {" #c1"[1], " #c2"[1], " #c3"[1], " #c4"[1]}," #b2 "," #stride"\n" \
- "vld4.8 {" #c1"[2], " #c2"[2], " #c3"[2], " #c4"[2]}," #b1 "," #stride"\n" \
- "vld4.8 {" #c1"[3], " #c2"[3], " #c3"[3], " #c4"[3]}," #b2 "," #stride"\n" \
- "vld4.8 {" #c1"[4], " #c2"[4], " #c3"[4], " #c4"[4]}," #b1 "," #stride"\n" \
- "vld4.8 {" #c1"[5], " #c2"[5], " #c3"[5], " #c4"[5]}," #b2 "," #stride"\n" \
- "vld4.8 {" #c1"[6], " #c2"[6], " #c3"[6], " #c4"[6]}," #b1 "," #stride"\n" \
- "vld4.8 {" #c1"[7], " #c2"[7], " #c3"[7], " #c4"[7]}," #b2 "," #stride"\n"
-
-#define STORE8x2(c1, c2, p,stride) \
- "vst2.8 {" #c1"[0], " #c2"[0]}," #p "," #stride " \n" \
- "vst2.8 {" #c1"[1], " #c2"[1]}," #p "," #stride " \n" \
- "vst2.8 {" #c1"[2], " #c2"[2]}," #p "," #stride " \n" \
- "vst2.8 {" #c1"[3], " #c2"[3]}," #p "," #stride " \n" \
- "vst2.8 {" #c1"[4], " #c2"[4]}," #p "," #stride " \n" \
- "vst2.8 {" #c1"[5], " #c2"[5]}," #p "," #stride " \n" \
- "vst2.8 {" #c1"[6], " #c2"[6]}," #p "," #stride " \n" \
- "vst2.8 {" #c1"[7], " #c2"[7]}," #p "," #stride " \n"
-
-//-----------------------------------------------------------------------------
-// Simple In-loop filtering (Paragraph 15.2)
-
-static void SimpleVFilter16NEON(uint8_t* p, int stride, int thresh) {
+static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
__asm__ volatile (
"sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride
"vld1.u8 {q1}, [%[p]], %[stride] \n" // p1
"vld1.u8 {q2}, [%[p]], %[stride] \n" // p0
"vld1.u8 {q3}, [%[p]], %[stride] \n" // q0
- "vld1.u8 {q4}, [%[p]] \n" // q1
+ "vld1.u8 {q12}, [%[p]] \n" // q1
- DO_FILTER2(q1, q2, q3, q4, %[thresh])
+ DO_FILTER2(q1, q2, q3, q12, %[thresh])
"sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride
@@ -113,25 +613,25 @@ static void SimpleVFilter16NEON(uint8_t* p, int stride, int thresh) {
);
}
-static void SimpleHFilter16NEON(uint8_t* p, int stride, int thresh) {
+static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
__asm__ volatile (
"sub r4, %[p], #2 \n" // base1 = p - 2
"lsl r6, %[stride], #1 \n" // r6 = 2 * stride
"add r5, r4, %[stride] \n" // base2 = base1 + stride
LOAD8x4(d2, d3, d4, d5, [r4], [r5], r6)
- LOAD8x4(d6, d7, d8, d9, [r4], [r5], r6)
- "vswp d3, d6 \n" // p1:q1 p0:q3
- "vswp d5, d8 \n" // q0:q2 q1:q4
- "vswp q2, q3 \n" // p1:q1 p0:q2 q0:q3 q1:q4
+ LOAD8x4(d24, d25, d26, d27, [r4], [r5], r6)
+ "vswp d3, d24 \n" // p1:q1 p0:q3
+ "vswp d5, d26 \n" // q0:q2 q1:q4
+ "vswp q2, q12 \n" // p1:q1 p0:q2 q0:q3 q1:q4
- DO_FILTER2(q1, q2, q3, q4, %[thresh])
+ DO_FILTER2(q1, q2, q12, q13, %[thresh])
"sub %[p], %[p], #1 \n" // p - 1
- "vswp d5, d6 \n"
+ "vswp d5, d24 \n"
STORE8x2(d4, d5, [%[p]], %[stride])
- STORE8x2(d6, d7, [%[p]], %[stride])
+ STORE8x2(d24, d25, [%[p]], %[stride])
: [p] "+r"(p)
: [stride] "r"(stride), [thresh] "r"(thresh)
@@ -139,44 +639,408 @@ static void SimpleHFilter16NEON(uint8_t* p, int stride, int thresh) {
);
}
-static void SimpleVFilter16iNEON(uint8_t* p, int stride, int thresh) {
- int k;
- for (k = 3; k > 0; --k) {
+#endif // WEBP_USE_INTRINSICS
+
+static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) {
+ uint32_t k;
+ for (k = 3; k != 0; --k) {
p += 4 * stride;
- SimpleVFilter16NEON(p, stride, thresh);
+ SimpleVFilter16(p, stride, thresh);
}
}
-static void SimpleHFilter16iNEON(uint8_t* p, int stride, int thresh) {
- int k;
- for (k = 3; k > 0; --k) {
+static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
+ uint32_t k;
+ for (k = 3; k != 0; --k) {
p += 4;
- SimpleHFilter16NEON(p, stride, thresh);
+ SimpleHFilter16(p, stride, thresh);
}
}
-static void TransformOneNEON(const int16_t *in, uint8_t *dst) {
- const int kBPS = BPS;
- const int16_t constants[] = {20091, 17734, 0, 0};
- /* kC1, kC2. Padded because vld1.16 loads 8 bytes
- * Technically these are unsigned but vqdmulh is only available in signed.
- * vqdmulh returns high half (effectively >> 16) but also doubles the value,
- * changing the >> 16 to >> 15 and requiring an additional >> 1.
- * We use this to our advantage with kC2. The canonical value is 35468.
- * However, the high bit is set so treating it as signed will give incorrect
- * results. We avoid this by down shifting by 1 here to clear the highest bit.
- * Combined with the doubling effect of vqdmulh we get >> 16.
- * This can not be applied to kC1 because the lowest bit is set. Down shifting
- * the constant would reduce precision.
- */
-
- /* libwebp uses a trick to avoid some extra addition that libvpx does.
- * Instead of:
- * temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1) >> 16);
- * libwebp adds 1 << 16 to cospi8sqrt2minus1 (kC1). However, this causes the
- * same issue with kC1 and vqdmulh that we work around by down shifting kC2
- */
+//------------------------------------------------------------------------------
+// Complex In-loop filtering (Paragraph 15.3)
+
+static uint8x16_t NeedsHev(const uint8x16_t p1, const uint8x16_t p0,
+ const uint8x16_t q0, const uint8x16_t q1,
+ int hev_thresh) {
+ const uint8x16_t hev_thresh_v = vdupq_n_u8((uint8_t)hev_thresh);
+ const uint8x16_t a_p1_p0 = vabdq_u8(p1, p0); // abs(p1 - p0)
+ const uint8x16_t a_q1_q0 = vabdq_u8(q1, q0); // abs(q1 - q0)
+ const uint8x16_t mask1 = vcgtq_u8(a_p1_p0, hev_thresh_v);
+ const uint8x16_t mask2 = vcgtq_u8(a_q1_q0, hev_thresh_v);
+ const uint8x16_t mask = vorrq_u8(mask1, mask2);
+ return mask;
+}
+
+static uint8x16_t NeedsFilter2(const uint8x16_t p3, const uint8x16_t p2,
+ const uint8x16_t p1, const uint8x16_t p0,
+ const uint8x16_t q0, const uint8x16_t q1,
+ const uint8x16_t q2, const uint8x16_t q3,
+ int ithresh, int thresh) {
+ const uint8x16_t ithresh_v = vdupq_n_u8((uint8_t)ithresh);
+ const uint8x16_t a_p3_p2 = vabdq_u8(p3, p2); // abs(p3 - p2)
+ const uint8x16_t a_p2_p1 = vabdq_u8(p2, p1); // abs(p2 - p1)
+ const uint8x16_t a_p1_p0 = vabdq_u8(p1, p0); // abs(p1 - p0)
+ const uint8x16_t a_q3_q2 = vabdq_u8(q3, q2); // abs(q3 - q2)
+ const uint8x16_t a_q2_q1 = vabdq_u8(q2, q1); // abs(q2 - q1)
+ const uint8x16_t a_q1_q0 = vabdq_u8(q1, q0); // abs(q1 - q0)
+ const uint8x16_t max1 = vmaxq_u8(a_p3_p2, a_p2_p1);
+ const uint8x16_t max2 = vmaxq_u8(a_p1_p0, a_q3_q2);
+ const uint8x16_t max3 = vmaxq_u8(a_q2_q1, a_q1_q0);
+ const uint8x16_t max12 = vmaxq_u8(max1, max2);
+ const uint8x16_t max123 = vmaxq_u8(max12, max3);
+ const uint8x16_t mask2 = vcgeq_u8(ithresh_v, max123);
+ const uint8x16_t mask1 = NeedsFilter(p1, p0, q0, q1, thresh);
+ const uint8x16_t mask = vandq_u8(mask1, mask2);
+ return mask;
+}
+
+// 4-points filter
+
+static void ApplyFilter4(
+ const int8x16_t p1, const int8x16_t p0,
+ const int8x16_t q0, const int8x16_t q1,
+ const int8x16_t delta0,
+ uint8x16_t* const op1, uint8x16_t* const op0,
+ uint8x16_t* const oq0, uint8x16_t* const oq1) {
+ const int8x16_t kCst3 = vdupq_n_s8(0x03);
+ const int8x16_t kCst4 = vdupq_n_s8(0x04);
+ const int8x16_t delta1 = vqaddq_s8(delta0, kCst4);
+ const int8x16_t delta2 = vqaddq_s8(delta0, kCst3);
+ const int8x16_t a1 = vshrq_n_s8(delta1, 3);
+ const int8x16_t a2 = vshrq_n_s8(delta2, 3);
+ const int8x16_t a3 = vrshrq_n_s8(a1, 1); // a3 = (a1 + 1) >> 1
+ *op0 = FlipSignBack(vqaddq_s8(p0, a2)); // clip(p0 + a2)
+ *oq0 = FlipSignBack(vqsubq_s8(q0, a1)); // clip(q0 - a1)
+ *op1 = FlipSignBack(vqaddq_s8(p1, a3)); // clip(p1 + a3)
+ *oq1 = FlipSignBack(vqsubq_s8(q1, a3)); // clip(q1 - a3)
+}
+
+static void DoFilter4(
+ const uint8x16_t p1, const uint8x16_t p0,
+ const uint8x16_t q0, const uint8x16_t q1,
+ const uint8x16_t mask, const uint8x16_t hev_mask,
+ uint8x16_t* const op1, uint8x16_t* const op0,
+ uint8x16_t* const oq0, uint8x16_t* const oq1) {
+ // This is a fused version of DoFilter2() calling ApplyFilter2 directly
+ const int8x16_t p1s = FlipSign(p1);
+ int8x16_t p0s = FlipSign(p0);
+ int8x16_t q0s = FlipSign(q0);
+ const int8x16_t q1s = FlipSign(q1);
+ const uint8x16_t simple_lf_mask = vandq_u8(mask, hev_mask);
+
+ // do_filter2 part (simple loopfilter on pixels with hev)
+ {
+ const int8x16_t delta = GetBaseDelta(p1s, p0s, q0s, q1s);
+ const int8x16_t simple_lf_delta =
+ vandq_s8(delta, vreinterpretq_s8_u8(simple_lf_mask));
+ ApplyFilter2NoFlip(p0s, q0s, simple_lf_delta, &p0s, &q0s);
+ }
+
+ // do_filter4 part (complex loopfilter on pixels without hev)
+ {
+ const int8x16_t delta0 = GetBaseDelta0(p0s, q0s);
+ // we use: (mask & hev_mask) ^ mask = mask & !hev_mask
+ const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask);
+ const int8x16_t complex_lf_delta =
+ vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask));
+ ApplyFilter4(p1s, p0s, q0s, q1s, complex_lf_delta, op1, op0, oq0, oq1);
+ }
+}
+
+// 6-points filter
+
+static void ApplyFilter6(
+ const int8x16_t p2, const int8x16_t p1, const int8x16_t p0,
+ const int8x16_t q0, const int8x16_t q1, const int8x16_t q2,
+ const int8x16_t delta,
+ uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0,
+ uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) {
+ const int16x8_t kCst63 = vdupq_n_s16(63);
+ const int8x8_t kCst27 = vdup_n_s8(27);
+ const int8x8_t kCst18 = vdup_n_s8(18);
+ const int8x8_t kCst9 = vdup_n_s8(9);
+ const int8x8_t delta_lo = vget_low_s8(delta);
+ const int8x8_t delta_hi = vget_high_s8(delta);
+ const int16x8_t s1_lo = vmlal_s8(kCst63, kCst27, delta_lo); // 63 + 27 * a
+ const int16x8_t s1_hi = vmlal_s8(kCst63, kCst27, delta_hi); // 63 + 27 * a
+ const int16x8_t s2_lo = vmlal_s8(kCst63, kCst18, delta_lo); // 63 + 18 * a
+ const int16x8_t s2_hi = vmlal_s8(kCst63, kCst18, delta_hi); // 63 + 18 * a
+ const int16x8_t s3_lo = vmlal_s8(kCst63, kCst9, delta_lo); // 63 + 9 * a
+ const int16x8_t s3_hi = vmlal_s8(kCst63, kCst9, delta_hi); // 63 + 9 * a
+ const int8x8_t a1_lo = vqshrn_n_s16(s1_lo, 7);
+ const int8x8_t a1_hi = vqshrn_n_s16(s1_hi, 7);
+ const int8x8_t a2_lo = vqshrn_n_s16(s2_lo, 7);
+ const int8x8_t a2_hi = vqshrn_n_s16(s2_hi, 7);
+ const int8x8_t a3_lo = vqshrn_n_s16(s3_lo, 7);
+ const int8x8_t a3_hi = vqshrn_n_s16(s3_hi, 7);
+ const int8x16_t a1 = vcombine_s8(a1_lo, a1_hi);
+ const int8x16_t a2 = vcombine_s8(a2_lo, a2_hi);
+ const int8x16_t a3 = vcombine_s8(a3_lo, a3_hi);
+
+ *op0 = FlipSignBack(vqaddq_s8(p0, a1)); // clip(p0 + a1)
+ *oq0 = FlipSignBack(vqsubq_s8(q0, a1)); // clip(q0 - q1)
+ *oq1 = FlipSignBack(vqsubq_s8(q1, a2)); // clip(q1 - a2)
+ *op1 = FlipSignBack(vqaddq_s8(p1, a2)); // clip(p1 + a2)
+ *oq2 = FlipSignBack(vqsubq_s8(q2, a3)); // clip(q2 - a3)
+ *op2 = FlipSignBack(vqaddq_s8(p2, a3)); // clip(p2 + a3)
+}
+
+static void DoFilter6(
+ const uint8x16_t p2, const uint8x16_t p1, const uint8x16_t p0,
+ const uint8x16_t q0, const uint8x16_t q1, const uint8x16_t q2,
+ const uint8x16_t mask, const uint8x16_t hev_mask,
+ uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0,
+ uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) {
+ // This is a fused version of DoFilter2() calling ApplyFilter2 directly
+ const int8x16_t p2s = FlipSign(p2);
+ const int8x16_t p1s = FlipSign(p1);
+ int8x16_t p0s = FlipSign(p0);
+ int8x16_t q0s = FlipSign(q0);
+ const int8x16_t q1s = FlipSign(q1);
+ const int8x16_t q2s = FlipSign(q2);
+ const uint8x16_t simple_lf_mask = vandq_u8(mask, hev_mask);
+ const int8x16_t delta0 = GetBaseDelta(p1s, p0s, q0s, q1s);
+
+ // do_filter2 part (simple loopfilter on pixels with hev)
+ {
+ const int8x16_t simple_lf_delta =
+ vandq_s8(delta0, vreinterpretq_s8_u8(simple_lf_mask));
+ ApplyFilter2NoFlip(p0s, q0s, simple_lf_delta, &p0s, &q0s);
+ }
+
+ // do_filter6 part (complex loopfilter on pixels without hev)
+ {
+ // we use: (mask & hev_mask) ^ mask = mask & !hev_mask
+ const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask);
+ const int8x16_t complex_lf_delta =
+ vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask));
+ ApplyFilter6(p2s, p1s, p0s, q0s, q1s, q2s, complex_lf_delta,
+ op2, op1, op0, oq0, oq1, oq2);
+ }
+}
+
+// on macroblock edges
+
+static void VFilter16(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
+ Load16x8(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
+ {
+ const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3,
+ ithresh, thresh);
+ const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
+ uint8x16_t op2, op1, op0, oq0, oq1, oq2;
+ DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask,
+ &op2, &op1, &op0, &oq0, &oq1, &oq2);
+ Store16x2(op2, op1, p - 2 * stride, stride);
+ Store16x2(op0, oq0, p + 0 * stride, stride);
+ Store16x2(oq1, oq2, p + 2 * stride, stride);
+ }
+}
+
+static void HFilter16(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
+ Load8x16(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
+ {
+ const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3,
+ ithresh, thresh);
+ const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
+ uint8x16_t op2, op1, op0, oq0, oq1, oq2;
+ DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask,
+ &op2, &op1, &op0, &oq0, &oq1, &oq2);
+ Store2x16(op2, op1, p - 2, stride);
+ Store2x16(op0, oq0, p + 0, stride);
+ Store2x16(oq1, oq2, p + 2, stride);
+ }
+}
+
+// on three inner edges
+static void VFilter16i(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ uint32_t k;
+ uint8x16_t p3, p2, p1, p0;
+ Load16x4(p + 2 * stride, stride, &p3, &p2, &p1, &p0);
+ for (k = 3; k != 0; --k) {
+ uint8x16_t q0, q1, q2, q3;
+ p += 4 * stride;
+ Load16x4(p + 2 * stride, stride, &q0, &q1, &q2, &q3);
+ {
+ const uint8x16_t mask =
+ NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh);
+ const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
+ // p3 and p2 are not just temporary variables here: they will be
+ // re-used for next span. And q2/q3 will become p1/p0 accordingly.
+ DoFilter4(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2);
+ Store16x4(p1, p0, p3, p2, p, stride);
+ p1 = q2;
+ p0 = q3;
+ }
+ }
+}
+
+#if !defined(WORK_AROUND_GCC)
+static void HFilter16i(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ uint32_t k;
+ uint8x16_t p3, p2, p1, p0;
+ Load4x16(p + 2, stride, &p3, &p2, &p1, &p0);
+ for (k = 3; k != 0; --k) {
+ uint8x16_t q0, q1, q2, q3;
+ p += 4;
+ Load4x16(p + 2, stride, &q0, &q1, &q2, &q3);
+ {
+ const uint8x16_t mask =
+ NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh);
+ const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
+ DoFilter4(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2);
+ Store4x16(p1, p0, p3, p2, p, stride);
+ p1 = q2;
+ p0 = q3;
+ }
+ }
+}
+#endif // !WORK_AROUND_GCC
+
+// 8-pixels wide variant, for chroma filtering
+static void VFilter8(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
+ Load8x8x2(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
+ {
+ const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3,
+ ithresh, thresh);
+ const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
+ uint8x16_t op2, op1, op0, oq0, oq1, oq2;
+ DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask,
+ &op2, &op1, &op0, &oq0, &oq1, &oq2);
+ Store8x2x2(op2, op1, u - 2 * stride, v - 2 * stride, stride);
+ Store8x2x2(op0, oq0, u + 0 * stride, v + 0 * stride, stride);
+ Store8x2x2(oq1, oq2, u + 2 * stride, v + 2 * stride, stride);
+ }
+}
+static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
+ u += 4 * stride;
+ v += 4 * stride;
+ Load8x8x2(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
+ {
+ const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3,
+ ithresh, thresh);
+ const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
+ uint8x16_t op1, op0, oq0, oq1;
+ DoFilter4(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1);
+ Store8x4x2(op1, op0, oq0, oq1, u, v, stride);
+ }
+}
+
+#if !defined(WORK_AROUND_GCC)
+static void HFilter8(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
+ Load8x8x2T(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
+ {
+ const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3,
+ ithresh, thresh);
+ const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
+ uint8x16_t op2, op1, op0, oq0, oq1, oq2;
+ DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask,
+ &op2, &op1, &op0, &oq0, &oq1, &oq2);
+ Store6x8x2(op2, op1, op0, oq0, oq1, oq2, u, v, stride);
+ }
+}
+
+static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
+ u += 4;
+ v += 4;
+ Load8x8x2T(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
+ {
+ const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3,
+ ithresh, thresh);
+ const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
+ uint8x16_t op1, op0, oq0, oq1;
+ DoFilter4(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1);
+ Store4x8x2(op1, op0, oq0, oq1, u, v, stride);
+ }
+}
+#endif // !WORK_AROUND_GCC
+
+//-----------------------------------------------------------------------------
+// Inverse transforms (Paragraph 14.4)
+
+// Technically these are unsigned but vqdmulh is only available in signed.
+// vqdmulh returns high half (effectively >> 16) but also doubles the value,
+// changing the >> 16 to >> 15 and requiring an additional >> 1.
+// We use this to our advantage with kC2. The canonical value is 35468.
+// However, the high bit is set so treating it as signed will give incorrect
+// results. We avoid this by down shifting by 1 here to clear the highest bit.
+// Combined with the doubling effect of vqdmulh we get >> 16.
+// This can not be applied to kC1 because the lowest bit is set. Down shifting
+// the constant would reduce precision.
+
+// libwebp uses a trick to avoid some extra addition that libvpx does.
+// Instead of:
+// temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1) >> 16);
+// libwebp adds 1 << 16 to cospi8sqrt2minus1 (kC1). However, this causes the
+// same issue with kC1 and vqdmulh that we work around by down shifting kC2
+static const int16_t kC1 = 20091;
+static const int16_t kC2 = 17734; // half of kC2, actually. See comment above.
+
+#if defined(WEBP_USE_INTRINSICS)
+static WEBP_INLINE void Transpose8x2(const int16x8_t in0, const int16x8_t in1,
+ int16x8x2_t* const out) {
+ // a0 a1 a2 a3 | b0 b1 b2 b3 => a0 b0 c0 d0 | a1 b1 c1 d1
+ // c0 c1 c2 c3 | d0 d1 d2 d3 a2 b2 c2 d2 | a3 b3 c3 d3
+ const int16x8x2_t tmp0 = vzipq_s16(in0, in1); // a0 c0 a1 c1 a2 c2 ...
+ // b0 d0 b1 d1 b2 d2 ...
+ *out = vzipq_s16(tmp0.val[0], tmp0.val[1]);
+}
+
+static WEBP_INLINE void TransformPass(int16x8x2_t* const rows) {
+ // {rows} = in0 | in4
+ // in8 | in12
+ // B1 = in4 | in12
+ const int16x8_t B1 =
+ vcombine_s16(vget_high_s16(rows->val[0]), vget_high_s16(rows->val[1]));
+ // C0 = kC1 * in4 | kC1 * in12
+ // C1 = kC2 * in4 | kC2 * in12
+ const int16x8_t C0 = vsraq_n_s16(B1, vqdmulhq_n_s16(B1, kC1), 1);
+ const int16x8_t C1 = vqdmulhq_n_s16(B1, kC2);
+ const int16x4_t a = vqadd_s16(vget_low_s16(rows->val[0]),
+ vget_low_s16(rows->val[1])); // in0 + in8
+ const int16x4_t b = vqsub_s16(vget_low_s16(rows->val[0]),
+ vget_low_s16(rows->val[1])); // in0 - in8
+ // c = kC2 * in4 - kC1 * in12
+ // d = kC1 * in4 + kC2 * in12
+ const int16x4_t c = vqsub_s16(vget_low_s16(C1), vget_high_s16(C0));
+ const int16x4_t d = vqadd_s16(vget_low_s16(C0), vget_high_s16(C1));
+ const int16x8_t D0 = vcombine_s16(a, b); // D0 = a | b
+ const int16x8_t D1 = vcombine_s16(d, c); // D1 = d | c
+ const int16x8_t E0 = vqaddq_s16(D0, D1); // a+d | b+c
+ const int16x8_t E_tmp = vqsubq_s16(D0, D1); // a-d | b-c
+ const int16x8_t E1 = vcombine_s16(vget_high_s16(E_tmp), vget_low_s16(E_tmp));
+ Transpose8x2(E0, E1, rows);
+}
+
+static void TransformOne(const int16_t* in, uint8_t* dst) {
+ int16x8x2_t rows;
+ INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8));
+ TransformPass(&rows);
+ TransformPass(&rows);
+ Add4x4(rows.val[0], rows.val[1], dst);
+}
+
+#else
+
+static void TransformOne(const int16_t* in, uint8_t* dst) {
+ const int kBPS = BPS;
+ // kC1, kC2. Padded because vld1.16 loads 8 bytes
+ const int16_t constants[4] = { kC1, kC2, 0, 0 };
/* Adapted from libvpx: vp8/common/arm/neon/shortidct4x4llm_neon.asm */
__asm__ volatile (
"vld1.16 {q1, q2}, [%[in]] \n"
@@ -304,26 +1168,472 @@ static void TransformOneNEON(const int16_t *in, uint8_t *dst) {
);
}
-static void TransformTwoNEON(const int16_t* in, uint8_t* dst, int do_two) {
- TransformOneNEON(in, dst);
+#endif // WEBP_USE_INTRINSICS
+
+static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
+ TransformOne(in, dst);
if (do_two) {
- TransformOneNEON(in + 16, dst + 4);
+ TransformOne(in + 16, dst + 4);
}
}
-extern void VP8DspInitNEON(void);
+static void TransformDC(const int16_t* in, uint8_t* dst) {
+ const int16x8_t DC = vdupq_n_s16(in[0]);
+ Add4x4(DC, DC, dst);
+}
+
+//------------------------------------------------------------------------------
+
+#define STORE_WHT(dst, col, rows) do { \
+ *dst = vgetq_lane_s32(rows.val[0], col); (dst) += 16; \
+ *dst = vgetq_lane_s32(rows.val[1], col); (dst) += 16; \
+ *dst = vgetq_lane_s32(rows.val[2], col); (dst) += 16; \
+ *dst = vgetq_lane_s32(rows.val[3], col); (dst) += 16; \
+} while (0)
+
+static void TransformWHT(const int16_t* in, int16_t* out) {
+ int32x4x4_t tmp;
-void VP8DspInitNEON(void) {
- VP8Transform = TransformTwoNEON;
+ {
+ // Load the source.
+ const int16x4_t in00_03 = vld1_s16(in + 0);
+ const int16x4_t in04_07 = vld1_s16(in + 4);
+ const int16x4_t in08_11 = vld1_s16(in + 8);
+ const int16x4_t in12_15 = vld1_s16(in + 12);
+ const int32x4_t a0 = vaddl_s16(in00_03, in12_15); // in[0..3] + in[12..15]
+ const int32x4_t a1 = vaddl_s16(in04_07, in08_11); // in[4..7] + in[8..11]
+ const int32x4_t a2 = vsubl_s16(in04_07, in08_11); // in[4..7] - in[8..11]
+ const int32x4_t a3 = vsubl_s16(in00_03, in12_15); // in[0..3] - in[12..15]
+ tmp.val[0] = vaddq_s32(a0, a1);
+ tmp.val[1] = vaddq_s32(a3, a2);
+ tmp.val[2] = vsubq_s32(a0, a1);
+ tmp.val[3] = vsubq_s32(a3, a2);
+ // Arrange the temporary results column-wise.
+ tmp = Transpose4x4(tmp);
+ }
+
+ {
+ const int32x4_t kCst3 = vdupq_n_s32(3);
+ const int32x4_t dc = vaddq_s32(tmp.val[0], kCst3); // add rounder
+ const int32x4_t a0 = vaddq_s32(dc, tmp.val[3]);
+ const int32x4_t a1 = vaddq_s32(tmp.val[1], tmp.val[2]);
+ const int32x4_t a2 = vsubq_s32(tmp.val[1], tmp.val[2]);
+ const int32x4_t a3 = vsubq_s32(dc, tmp.val[3]);
+
+ tmp.val[0] = vaddq_s32(a0, a1);
+ tmp.val[1] = vaddq_s32(a3, a2);
+ tmp.val[2] = vsubq_s32(a0, a1);
+ tmp.val[3] = vsubq_s32(a3, a2);
+
+ // right shift the results by 3.
+ tmp.val[0] = vshrq_n_s32(tmp.val[0], 3);
+ tmp.val[1] = vshrq_n_s32(tmp.val[1], 3);
+ tmp.val[2] = vshrq_n_s32(tmp.val[2], 3);
+ tmp.val[3] = vshrq_n_s32(tmp.val[3], 3);
- VP8SimpleVFilter16 = SimpleVFilter16NEON;
- VP8SimpleHFilter16 = SimpleHFilter16NEON;
- VP8SimpleVFilter16i = SimpleVFilter16iNEON;
- VP8SimpleHFilter16i = SimpleHFilter16iNEON;
+ STORE_WHT(out, 0, tmp);
+ STORE_WHT(out, 1, tmp);
+ STORE_WHT(out, 2, tmp);
+ STORE_WHT(out, 3, tmp);
+ }
}
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
+#undef STORE_WHT
+
+//------------------------------------------------------------------------------
+
+#define MUL(a, b) (((a) * (b)) >> 16)
+static void TransformAC3(const int16_t* in, uint8_t* dst) {
+ static const int kC1_full = 20091 + (1 << 16);
+ static const int kC2_full = 35468;
+ const int16x4_t A = vld1_dup_s16(in);
+ const int16x4_t c4 = vdup_n_s16(MUL(in[4], kC2_full));
+ const int16x4_t d4 = vdup_n_s16(MUL(in[4], kC1_full));
+ const int c1 = MUL(in[1], kC2_full);
+ const int d1 = MUL(in[1], kC1_full);
+ const uint64_t cd = (uint64_t)( d1 & 0xffff) << 0 |
+ (uint64_t)( c1 & 0xffff) << 16 |
+ (uint64_t)(-c1 & 0xffff) << 32 |
+ (uint64_t)(-d1 & 0xffff) << 48;
+ const int16x4_t CD = vcreate_s16(cd);
+ const int16x4_t B = vqadd_s16(A, CD);
+ const int16x8_t m0_m1 = vcombine_s16(vqadd_s16(B, d4), vqadd_s16(B, c4));
+ const int16x8_t m2_m3 = vcombine_s16(vqsub_s16(B, c4), vqsub_s16(B, d4));
+ Add4x4(m0_m1, m2_m3, dst);
+}
+#undef MUL
+
+//------------------------------------------------------------------------------
+// 4x4
+
+static void DC4(uint8_t* dst) { // DC
+ const uint8x8_t A = vld1_u8(dst - BPS); // top row
+ const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top
+ const uint16x4_t p1 = vpadd_u16(p0, p0);
+ const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + 0 * BPS - 1));
+ const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + 1 * BPS - 1));
+ const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + 2 * BPS - 1));
+ const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + 3 * BPS - 1));
+ const uint16x8_t s0 = vaddq_u16(L0, L1);
+ const uint16x8_t s1 = vaddq_u16(L2, L3);
+ const uint16x8_t s01 = vaddq_u16(s0, s1);
+ const uint16x8_t sum = vaddq_u16(s01, vcombine_u16(p1, p1));
+ const uint8x8_t dc0 = vrshrn_n_u16(sum, 3); // (sum + 4) >> 3
+ const uint8x8_t dc = vdup_lane_u8(dc0, 0);
+ int i;
+ for (i = 0; i < 4; ++i) {
+ vst1_lane_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(dc), 0);
+ }
+}
+
+// TrueMotion (4x4 + 8x8)
+static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) {
+ const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]'
+ const uint8x8_t T = vld1_u8(dst - BPS); // top row 'A[0..3]'
+ const int16x8_t d = vreinterpretq_s16_u16(vsubl_u8(T, TL)); // A[c] - A[-1]
+ int y;
+ for (y = 0; y < size; y += 4) {
+ // left edge
+ const int16x8_t L0 = ConvertU8ToS16(vld1_dup_u8(dst + 0 * BPS - 1));
+ const int16x8_t L1 = ConvertU8ToS16(vld1_dup_u8(dst + 1 * BPS - 1));
+ const int16x8_t L2 = ConvertU8ToS16(vld1_dup_u8(dst + 2 * BPS - 1));
+ const int16x8_t L3 = ConvertU8ToS16(vld1_dup_u8(dst + 3 * BPS - 1));
+ const int16x8_t r0 = vaddq_s16(L0, d); // L[r] + A[c] - A[-1]
+ const int16x8_t r1 = vaddq_s16(L1, d);
+ const int16x8_t r2 = vaddq_s16(L2, d);
+ const int16x8_t r3 = vaddq_s16(L3, d);
+ // Saturate and store the result.
+ const uint32x2_t r0_u32 = vreinterpret_u32_u8(vqmovun_s16(r0));
+ const uint32x2_t r1_u32 = vreinterpret_u32_u8(vqmovun_s16(r1));
+ const uint32x2_t r2_u32 = vreinterpret_u32_u8(vqmovun_s16(r2));
+ const uint32x2_t r3_u32 = vreinterpret_u32_u8(vqmovun_s16(r3));
+ if (size == 4) {
+ vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0_u32, 0);
+ vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1_u32, 0);
+ vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2_u32, 0);
+ vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3_u32, 0);
+ } else {
+ vst1_u32((uint32_t*)(dst + 0 * BPS), r0_u32);
+ vst1_u32((uint32_t*)(dst + 1 * BPS), r1_u32);
+ vst1_u32((uint32_t*)(dst + 2 * BPS), r2_u32);
+ vst1_u32((uint32_t*)(dst + 3 * BPS), r3_u32);
+ }
+ dst += 4 * BPS;
+ }
+}
+
+static void TM4(uint8_t* dst) { TrueMotion(dst, 4); }
+
+static void VE4(uint8_t* dst) { // vertical
+ // NB: avoid vld1_u64 here as an alignment hint may be added -> SIGBUS.
+ const uint64x1_t A0 = vreinterpret_u64_u8(vld1_u8(dst - BPS - 1)); // top row
+ const uint64x1_t A1 = vshr_n_u64(A0, 8);
+ const uint64x1_t A2 = vshr_n_u64(A0, 16);
+ const uint8x8_t ABCDEFGH = vreinterpret_u8_u64(A0);
+ const uint8x8_t BCDEFGH0 = vreinterpret_u8_u64(A1);
+ const uint8x8_t CDEFGH00 = vreinterpret_u8_u64(A2);
+ const uint8x8_t b = vhadd_u8(ABCDEFGH, CDEFGH00);
+ const uint8x8_t avg = vrhadd_u8(b, BCDEFGH0);
+ int i;
+ for (i = 0; i < 4; ++i) {
+ vst1_lane_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(avg), 0);
+ }
+}
+
+static void RD4(uint8_t* dst) { // Down-right
+ const uint8x8_t XABCD_u8 = vld1_u8(dst - BPS - 1);
+ const uint64x1_t XABCD = vreinterpret_u64_u8(XABCD_u8);
+ const uint64x1_t ____XABC = vshl_n_u64(XABCD, 32);
+ const uint32_t I = dst[-1 + 0 * BPS];
+ const uint32_t J = dst[-1 + 1 * BPS];
+ const uint32_t K = dst[-1 + 2 * BPS];
+ const uint32_t L = dst[-1 + 3 * BPS];
+ const uint64x1_t LKJI____ = vcreate_u64(L | (K << 8) | (J << 16) | (I << 24));
+ const uint64x1_t LKJIXABC = vorr_u64(LKJI____, ____XABC);
+ const uint8x8_t KJIXABC_ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 8));
+ const uint8x8_t JIXABC__ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 16));
+ const uint8_t D = vget_lane_u8(XABCD_u8, 4);
+ const uint8x8_t JIXABCD_ = vset_lane_u8(D, JIXABC__, 6);
+ const uint8x8_t LKJIXABC_u8 = vreinterpret_u8_u64(LKJIXABC);
+ const uint8x8_t avg1 = vhadd_u8(JIXABCD_, LKJIXABC_u8);
+ const uint8x8_t avg2 = vrhadd_u8(avg1, KJIXABC_);
+ const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2);
+ const uint32x2_t r3 = vreinterpret_u32_u8(avg2);
+ const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8));
+ const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16));
+ const uint32x2_t r0 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24));
+ vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0, 0);
+ vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1, 0);
+ vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2, 0);
+ vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3, 0);
+}
+
+static void LD4(uint8_t* dst) { // Down-left
+ // Note using the same shift trick as VE4() is slower here.
+ const uint8x8_t ABCDEFGH = vld1_u8(dst - BPS + 0);
+ const uint8x8_t BCDEFGH0 = vld1_u8(dst - BPS + 1);
+ const uint8x8_t CDEFGH00 = vld1_u8(dst - BPS + 2);
+ const uint8x8_t CDEFGHH0 = vset_lane_u8(dst[-BPS + 7], CDEFGH00, 6);
+ const uint8x8_t avg1 = vhadd_u8(ABCDEFGH, CDEFGHH0);
+ const uint8x8_t avg2 = vrhadd_u8(avg1, BCDEFGH0);
+ const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2);
+ const uint32x2_t r0 = vreinterpret_u32_u8(avg2);
+ const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8));
+ const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16));
+ const uint32x2_t r3 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24));
+ vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0, 0);
+ vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1, 0);
+ vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2, 0);
+ vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3, 0);
+}
+
+//------------------------------------------------------------------------------
+// Chroma
+
+static void VE8uv(uint8_t* dst) { // vertical
+ const uint8x8_t top = vld1_u8(dst - BPS);
+ int j;
+ for (j = 0; j < 8; ++j) {
+ vst1_u8(dst + j * BPS, top);
+ }
+}
+
+static void HE8uv(uint8_t* dst) { // horizontal
+ int j;
+ for (j = 0; j < 8; ++j) {
+ const uint8x8_t left = vld1_dup_u8(dst - 1);
+ vst1_u8(dst, left);
+ dst += BPS;
+ }
+}
+
+static WEBP_INLINE void DC8(uint8_t* dst, int do_top, int do_left) {
+ uint16x8_t sum_top;
+ uint16x8_t sum_left;
+ uint8x8_t dc0;
+
+ if (do_top) {
+ const uint8x8_t A = vld1_u8(dst - BPS); // top row
+ const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top
+ const uint16x4_t p1 = vpadd_u16(p0, p0);
+ const uint16x4_t p2 = vpadd_u16(p1, p1);
+ sum_top = vcombine_u16(p2, p2);
+ }
+
+ if (do_left) {
+ const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + 0 * BPS - 1));
+ const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + 1 * BPS - 1));
+ const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + 2 * BPS - 1));
+ const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + 3 * BPS - 1));
+ const uint16x8_t L4 = vmovl_u8(vld1_u8(dst + 4 * BPS - 1));
+ const uint16x8_t L5 = vmovl_u8(vld1_u8(dst + 5 * BPS - 1));
+ const uint16x8_t L6 = vmovl_u8(vld1_u8(dst + 6 * BPS - 1));
+ const uint16x8_t L7 = vmovl_u8(vld1_u8(dst + 7 * BPS - 1));
+ const uint16x8_t s0 = vaddq_u16(L0, L1);
+ const uint16x8_t s1 = vaddq_u16(L2, L3);
+ const uint16x8_t s2 = vaddq_u16(L4, L5);
+ const uint16x8_t s3 = vaddq_u16(L6, L7);
+ const uint16x8_t s01 = vaddq_u16(s0, s1);
+ const uint16x8_t s23 = vaddq_u16(s2, s3);
+ sum_left = vaddq_u16(s01, s23);
+ }
+
+ if (do_top && do_left) {
+ const uint16x8_t sum = vaddq_u16(sum_left, sum_top);
+ dc0 = vrshrn_n_u16(sum, 4);
+ } else if (do_top) {
+ dc0 = vrshrn_n_u16(sum_top, 3);
+ } else if (do_left) {
+ dc0 = vrshrn_n_u16(sum_left, 3);
+ } else {
+ dc0 = vdup_n_u8(0x80);
+ }
+
+ {
+ const uint8x8_t dc = vdup_lane_u8(dc0, 0);
+ int i;
+ for (i = 0; i < 8; ++i) {
+ vst1_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(dc));
+ }
+ }
+}
+
+static void DC8uv(uint8_t* dst) { DC8(dst, 1, 1); }
+static void DC8uvNoTop(uint8_t* dst) { DC8(dst, 0, 1); }
+static void DC8uvNoLeft(uint8_t* dst) { DC8(dst, 1, 0); }
+static void DC8uvNoTopLeft(uint8_t* dst) { DC8(dst, 0, 0); }
+
+static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); }
+
+//------------------------------------------------------------------------------
+// 16x16
+
+static void VE16(uint8_t* dst) { // vertical
+ const uint8x16_t top = vld1q_u8(dst - BPS);
+ int j;
+ for (j = 0; j < 16; ++j) {
+ vst1q_u8(dst + j * BPS, top);
+ }
+}
+
+static void HE16(uint8_t* dst) { // horizontal
+ int j;
+ for (j = 0; j < 16; ++j) {
+ const uint8x16_t left = vld1q_dup_u8(dst - 1);
+ vst1q_u8(dst, left);
+ dst += BPS;
+ }
+}
+
+static WEBP_INLINE void DC16(uint8_t* dst, int do_top, int do_left) {
+ uint16x8_t sum_top;
+ uint16x8_t sum_left;
+ uint8x8_t dc0;
+
+ if (do_top) {
+ const uint8x16_t A = vld1q_u8(dst - BPS); // top row
+ const uint16x8_t p0 = vpaddlq_u8(A); // cascading summation of the top
+ const uint16x4_t p1 = vadd_u16(vget_low_u16(p0), vget_high_u16(p0));
+ const uint16x4_t p2 = vpadd_u16(p1, p1);
+ const uint16x4_t p3 = vpadd_u16(p2, p2);
+ sum_top = vcombine_u16(p3, p3);
+ }
+
+ if (do_left) {
+ int i;
+ sum_left = vdupq_n_u16(0);
+ for (i = 0; i < 16; i += 8) {
+ const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + (i + 0) * BPS - 1));
+ const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + (i + 1) * BPS - 1));
+ const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + (i + 2) * BPS - 1));
+ const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + (i + 3) * BPS - 1));
+ const uint16x8_t L4 = vmovl_u8(vld1_u8(dst + (i + 4) * BPS - 1));
+ const uint16x8_t L5 = vmovl_u8(vld1_u8(dst + (i + 5) * BPS - 1));
+ const uint16x8_t L6 = vmovl_u8(vld1_u8(dst + (i + 6) * BPS - 1));
+ const uint16x8_t L7 = vmovl_u8(vld1_u8(dst + (i + 7) * BPS - 1));
+ const uint16x8_t s0 = vaddq_u16(L0, L1);
+ const uint16x8_t s1 = vaddq_u16(L2, L3);
+ const uint16x8_t s2 = vaddq_u16(L4, L5);
+ const uint16x8_t s3 = vaddq_u16(L6, L7);
+ const uint16x8_t s01 = vaddq_u16(s0, s1);
+ const uint16x8_t s23 = vaddq_u16(s2, s3);
+ const uint16x8_t sum = vaddq_u16(s01, s23);
+ sum_left = vaddq_u16(sum_left, sum);
+ }
+ }
+
+ if (do_top && do_left) {
+ const uint16x8_t sum = vaddq_u16(sum_left, sum_top);
+ dc0 = vrshrn_n_u16(sum, 5);
+ } else if (do_top) {
+ dc0 = vrshrn_n_u16(sum_top, 4);
+ } else if (do_left) {
+ dc0 = vrshrn_n_u16(sum_left, 4);
+ } else {
+ dc0 = vdup_n_u8(0x80);
+ }
+
+ {
+ const uint8x16_t dc = vdupq_lane_u8(dc0, 0);
+ int i;
+ for (i = 0; i < 16; ++i) {
+ vst1q_u8(dst + i * BPS, dc);
+ }
+ }
+}
+
+static void DC16TopLeft(uint8_t* dst) { DC16(dst, 1, 1); }
+static void DC16NoTop(uint8_t* dst) { DC16(dst, 0, 1); }
+static void DC16NoLeft(uint8_t* dst) { DC16(dst, 1, 0); }
+static void DC16NoTopLeft(uint8_t* dst) { DC16(dst, 0, 0); }
+
+static void TM16(uint8_t* dst) {
+ const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]'
+ const uint8x16_t T = vld1q_u8(dst - BPS); // top row 'A[0..15]'
+ // A[c] - A[-1]
+ const int16x8_t d_lo = vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(T), TL));
+ const int16x8_t d_hi = vreinterpretq_s16_u16(vsubl_u8(vget_high_u8(T), TL));
+ int y;
+ for (y = 0; y < 16; y += 4) {
+ // left edge
+ const int16x8_t L0 = ConvertU8ToS16(vld1_dup_u8(dst + 0 * BPS - 1));
+ const int16x8_t L1 = ConvertU8ToS16(vld1_dup_u8(dst + 1 * BPS - 1));
+ const int16x8_t L2 = ConvertU8ToS16(vld1_dup_u8(dst + 2 * BPS - 1));
+ const int16x8_t L3 = ConvertU8ToS16(vld1_dup_u8(dst + 3 * BPS - 1));
+ const int16x8_t r0_lo = vaddq_s16(L0, d_lo); // L[r] + A[c] - A[-1]
+ const int16x8_t r1_lo = vaddq_s16(L1, d_lo);
+ const int16x8_t r2_lo = vaddq_s16(L2, d_lo);
+ const int16x8_t r3_lo = vaddq_s16(L3, d_lo);
+ const int16x8_t r0_hi = vaddq_s16(L0, d_hi);
+ const int16x8_t r1_hi = vaddq_s16(L1, d_hi);
+ const int16x8_t r2_hi = vaddq_s16(L2, d_hi);
+ const int16x8_t r3_hi = vaddq_s16(L3, d_hi);
+ // Saturate and store the result.
+ const uint8x16_t row0 = vcombine_u8(vqmovun_s16(r0_lo), vqmovun_s16(r0_hi));
+ const uint8x16_t row1 = vcombine_u8(vqmovun_s16(r1_lo), vqmovun_s16(r1_hi));
+ const uint8x16_t row2 = vcombine_u8(vqmovun_s16(r2_lo), vqmovun_s16(r2_hi));
+ const uint8x16_t row3 = vcombine_u8(vqmovun_s16(r3_lo), vqmovun_s16(r3_hi));
+ vst1q_u8(dst + 0 * BPS, row0);
+ vst1q_u8(dst + 1 * BPS, row1);
+ vst1q_u8(dst + 2 * BPS, row2);
+ vst1q_u8(dst + 3 * BPS, row3);
+ dst += 4 * BPS;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8DspInitNEON(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitNEON(void) {
+ VP8Transform = TransformTwo;
+ VP8TransformAC3 = TransformAC3;
+ VP8TransformDC = TransformDC;
+ VP8TransformWHT = TransformWHT;
+
+ VP8VFilter16 = VFilter16;
+ VP8VFilter16i = VFilter16i;
+ VP8HFilter16 = HFilter16;
+#if !defined(WORK_AROUND_GCC)
+ VP8HFilter16i = HFilter16i;
#endif
+ VP8VFilter8 = VFilter8;
+ VP8VFilter8i = VFilter8i;
+#if !defined(WORK_AROUND_GCC)
+ VP8HFilter8 = HFilter8;
+ VP8HFilter8i = HFilter8i;
+#endif
+ VP8SimpleVFilter16 = SimpleVFilter16;
+ VP8SimpleHFilter16 = SimpleHFilter16;
+ VP8SimpleVFilter16i = SimpleVFilter16i;
+ VP8SimpleHFilter16i = SimpleHFilter16i;
+
+ VP8PredLuma4[0] = DC4;
+ VP8PredLuma4[1] = TM4;
+ VP8PredLuma4[2] = VE4;
+ VP8PredLuma4[4] = RD4;
+ VP8PredLuma4[6] = LD4;
+
+ VP8PredLuma16[0] = DC16TopLeft;
+ VP8PredLuma16[1] = TM16;
+ VP8PredLuma16[2] = VE16;
+ VP8PredLuma16[3] = HE16;
+ VP8PredLuma16[4] = DC16NoTop;
+ VP8PredLuma16[5] = DC16NoLeft;
+ VP8PredLuma16[6] = DC16NoTopLeft;
+
+ VP8PredChroma8[0] = DC8uv;
+ VP8PredChroma8[1] = TM8uv;
+ VP8PredChroma8[2] = VE8uv;
+ VP8PredChroma8[3] = HE8uv;
+ VP8PredChroma8[4] = DC8uvNoTop;
+ VP8PredChroma8[5] = DC8uvNoLeft;
+ VP8PredChroma8[6] = DC8uvNoTopLeft;
+}
+
+#else // !WEBP_USE_NEON
+
+WEBP_DSP_INIT_STUB(VP8DspInitNEON)
-#endif // WEBP_USE_NEON
+#endif // WEBP_USE_NEON
diff --git a/drivers/webp/dsp/dec_sse2.c b/drivers/webp/dsp/dec_sse2.c
index 472b68ecb8..d4838b9210 100644
--- a/drivers/webp/dsp/dec_sse2.c
+++ b/drivers/webp/dsp/dec_sse2.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// SSE2 version of some decoding functions (idct, loop filtering).
@@ -14,17 +16,17 @@
#if defined(WEBP_USE_SSE2)
+// The 3-coeff sparse transform in SSE2 is not really faster than the plain-C
+// one it seems => disable it by default. Uncomment the following to enable:
+// #define USE_TRANSFORM_AC3
+
#include <emmintrin.h>
#include "../dec/vp8i.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
//------------------------------------------------------------------------------
// Transforms (Paragraph 14.4)
-static void TransformSSE2(const int16_t* in, uint8_t* dst, int do_two) {
+static void Transform(const int16_t* in, uint8_t* dst, int do_two) {
// This implementation makes use of 16-bit fixed point versions of two
// multiply constants:
// K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16
@@ -50,19 +52,19 @@ static void TransformSSE2(const int16_t* in, uint8_t* dst, int do_two) {
// vectors will just contain random value we'll never use nor store.
__m128i in0, in1, in2, in3;
{
- in0 = _mm_loadl_epi64((__m128i*)&in[0]);
- in1 = _mm_loadl_epi64((__m128i*)&in[4]);
- in2 = _mm_loadl_epi64((__m128i*)&in[8]);
- in3 = _mm_loadl_epi64((__m128i*)&in[12]);
+ in0 = _mm_loadl_epi64((const __m128i*)&in[0]);
+ in1 = _mm_loadl_epi64((const __m128i*)&in[4]);
+ in2 = _mm_loadl_epi64((const __m128i*)&in[8]);
+ in3 = _mm_loadl_epi64((const __m128i*)&in[12]);
// a00 a10 a20 a30 x x x x
// a01 a11 a21 a31 x x x x
// a02 a12 a22 a32 x x x x
// a03 a13 a23 a33 x x x x
if (do_two) {
- const __m128i inB0 = _mm_loadl_epi64((__m128i*)&in[16]);
- const __m128i inB1 = _mm_loadl_epi64((__m128i*)&in[20]);
- const __m128i inB2 = _mm_loadl_epi64((__m128i*)&in[24]);
- const __m128i inB3 = _mm_loadl_epi64((__m128i*)&in[28]);
+ const __m128i inB0 = _mm_loadl_epi64((const __m128i*)&in[16]);
+ const __m128i inB1 = _mm_loadl_epi64((const __m128i*)&in[20]);
+ const __m128i inB2 = _mm_loadl_epi64((const __m128i*)&in[24]);
+ const __m128i inB3 = _mm_loadl_epi64((const __m128i*)&in[28]);
in0 = _mm_unpacklo_epi64(in0, inB0);
in1 = _mm_unpacklo_epi64(in1, inB1);
in2 = _mm_unpacklo_epi64(in2, inB2);
@@ -194,21 +196,21 @@ static void TransformSSE2(const int16_t* in, uint8_t* dst, int do_two) {
// Add inverse transform to 'dst' and store.
{
- const __m128i zero = _mm_set1_epi16(0);
+ const __m128i zero = _mm_setzero_si128();
// Load the reference(s).
__m128i dst0, dst1, dst2, dst3;
if (do_two) {
// Load eight bytes/pixels per line.
- dst0 = _mm_loadl_epi64((__m128i*)&dst[0 * BPS]);
- dst1 = _mm_loadl_epi64((__m128i*)&dst[1 * BPS]);
- dst2 = _mm_loadl_epi64((__m128i*)&dst[2 * BPS]);
- dst3 = _mm_loadl_epi64((__m128i*)&dst[3 * BPS]);
+ dst0 = _mm_loadl_epi64((__m128i*)(dst + 0 * BPS));
+ dst1 = _mm_loadl_epi64((__m128i*)(dst + 1 * BPS));
+ dst2 = _mm_loadl_epi64((__m128i*)(dst + 2 * BPS));
+ dst3 = _mm_loadl_epi64((__m128i*)(dst + 3 * BPS));
} else {
// Load four bytes/pixels per line.
- dst0 = _mm_cvtsi32_si128(*(int*)&dst[0 * BPS]);
- dst1 = _mm_cvtsi32_si128(*(int*)&dst[1 * BPS]);
- dst2 = _mm_cvtsi32_si128(*(int*)&dst[2 * BPS]);
- dst3 = _mm_cvtsi32_si128(*(int*)&dst[3 * BPS]);
+ dst0 = _mm_cvtsi32_si128(*(int*)(dst + 0 * BPS));
+ dst1 = _mm_cvtsi32_si128(*(int*)(dst + 1 * BPS));
+ dst2 = _mm_cvtsi32_si128(*(int*)(dst + 2 * BPS));
+ dst3 = _mm_cvtsi32_si128(*(int*)(dst + 3 * BPS));
}
// Convert to 16b.
dst0 = _mm_unpacklo_epi8(dst0, zero);
@@ -228,20 +230,66 @@ static void TransformSSE2(const int16_t* in, uint8_t* dst, int do_two) {
// Store the results.
if (do_two) {
// Store eight bytes/pixels per line.
- _mm_storel_epi64((__m128i*)&dst[0 * BPS], dst0);
- _mm_storel_epi64((__m128i*)&dst[1 * BPS], dst1);
- _mm_storel_epi64((__m128i*)&dst[2 * BPS], dst2);
- _mm_storel_epi64((__m128i*)&dst[3 * BPS], dst3);
+ _mm_storel_epi64((__m128i*)(dst + 0 * BPS), dst0);
+ _mm_storel_epi64((__m128i*)(dst + 1 * BPS), dst1);
+ _mm_storel_epi64((__m128i*)(dst + 2 * BPS), dst2);
+ _mm_storel_epi64((__m128i*)(dst + 3 * BPS), dst3);
} else {
// Store four bytes/pixels per line.
- *((int32_t *)&dst[0 * BPS]) = _mm_cvtsi128_si32(dst0);
- *((int32_t *)&dst[1 * BPS]) = _mm_cvtsi128_si32(dst1);
- *((int32_t *)&dst[2 * BPS]) = _mm_cvtsi128_si32(dst2);
- *((int32_t *)&dst[3 * BPS]) = _mm_cvtsi128_si32(dst3);
+ *(int*)(dst + 0 * BPS) = _mm_cvtsi128_si32(dst0);
+ *(int*)(dst + 1 * BPS) = _mm_cvtsi128_si32(dst1);
+ *(int*)(dst + 2 * BPS) = _mm_cvtsi128_si32(dst2);
+ *(int*)(dst + 3 * BPS) = _mm_cvtsi128_si32(dst3);
}
}
}
+#if defined(USE_TRANSFORM_AC3)
+#define MUL(a, b) (((a) * (b)) >> 16)
+static void TransformAC3(const int16_t* in, uint8_t* dst) {
+ static const int kC1 = 20091 + (1 << 16);
+ static const int kC2 = 35468;
+ const __m128i A = _mm_set1_epi16(in[0] + 4);
+ const __m128i c4 = _mm_set1_epi16(MUL(in[4], kC2));
+ const __m128i d4 = _mm_set1_epi16(MUL(in[4], kC1));
+ const int c1 = MUL(in[1], kC2);
+ const int d1 = MUL(in[1], kC1);
+ const __m128i CD = _mm_set_epi16(0, 0, 0, 0, -d1, -c1, c1, d1);
+ const __m128i B = _mm_adds_epi16(A, CD);
+ const __m128i m0 = _mm_adds_epi16(B, d4);
+ const __m128i m1 = _mm_adds_epi16(B, c4);
+ const __m128i m2 = _mm_subs_epi16(B, c4);
+ const __m128i m3 = _mm_subs_epi16(B, d4);
+ const __m128i zero = _mm_setzero_si128();
+ // Load the source pixels.
+ __m128i dst0 = _mm_cvtsi32_si128(*(int*)(dst + 0 * BPS));
+ __m128i dst1 = _mm_cvtsi32_si128(*(int*)(dst + 1 * BPS));
+ __m128i dst2 = _mm_cvtsi32_si128(*(int*)(dst + 2 * BPS));
+ __m128i dst3 = _mm_cvtsi32_si128(*(int*)(dst + 3 * BPS));
+ // Convert to 16b.
+ dst0 = _mm_unpacklo_epi8(dst0, zero);
+ dst1 = _mm_unpacklo_epi8(dst1, zero);
+ dst2 = _mm_unpacklo_epi8(dst2, zero);
+ dst3 = _mm_unpacklo_epi8(dst3, zero);
+ // Add the inverse transform.
+ dst0 = _mm_adds_epi16(dst0, _mm_srai_epi16(m0, 3));
+ dst1 = _mm_adds_epi16(dst1, _mm_srai_epi16(m1, 3));
+ dst2 = _mm_adds_epi16(dst2, _mm_srai_epi16(m2, 3));
+ dst3 = _mm_adds_epi16(dst3, _mm_srai_epi16(m3, 3));
+ // Unsigned saturate to 8b.
+ dst0 = _mm_packus_epi16(dst0, dst0);
+ dst1 = _mm_packus_epi16(dst1, dst1);
+ dst2 = _mm_packus_epi16(dst2, dst2);
+ dst3 = _mm_packus_epi16(dst3, dst3);
+ // Store the results.
+ *(int*)(dst + 0 * BPS) = _mm_cvtsi128_si32(dst0);
+ *(int*)(dst + 1 * BPS) = _mm_cvtsi128_si32(dst1);
+ *(int*)(dst + 2 * BPS) = _mm_cvtsi128_si32(dst2);
+ *(int*)(dst + 3 * BPS) = _mm_cvtsi128_si32(dst3);
+}
+#undef MUL
+#endif // USE_TRANSFORM_AC3
+
//------------------------------------------------------------------------------
// Loop Filter (Paragraph 15)
@@ -250,20 +298,14 @@ static void TransformSSE2(const int16_t* in, uint8_t* dst, int do_two) {
_mm_subs_epu8((q), (p)), \
_mm_subs_epu8((p), (q)))
-// Shift each byte of "a" by N bits while preserving by the sign bit.
-//
-// It first shifts the lower bytes of the words and then the upper bytes and
-// then merges the results together.
-#define SIGNED_SHIFT_N(a, N) { \
- __m128i t = a; \
- t = _mm_slli_epi16(t, 8); \
- t = _mm_srai_epi16(t, N); \
- t = _mm_srli_epi16(t, 8); \
- \
- a = _mm_srai_epi16(a, N + 8); \
- a = _mm_slli_epi16(a, 8); \
- \
- a = _mm_or_si128(t, a); \
+// Shift each byte of "x" by 3 bits while preserving by the sign bit.
+static WEBP_INLINE void SignedShift8b(__m128i* const x) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i lo_0 = _mm_unpacklo_epi8(zero, *x);
+ const __m128i hi_0 = _mm_unpackhi_epi8(zero, *x);
+ const __m128i lo_1 = _mm_srai_epi16(lo_0, 3 + 8);
+ const __m128i hi_1 = _mm_srai_epi16(hi_0, 3 + 8);
+ *x = _mm_packs_epi16(lo_1, hi_1);
}
#define FLIP_SIGN_BIT2(a, b) { \
@@ -276,103 +318,124 @@ static void TransformSSE2(const int16_t* in, uint8_t* dst, int do_two) {
FLIP_SIGN_BIT2(c, d); \
}
-#define GET_NOTHEV(p1, p0, q0, q1, hev_thresh, not_hev) { \
- const __m128i zero = _mm_setzero_si128(); \
- const __m128i t1 = MM_ABS(p1, p0); \
- const __m128i t2 = MM_ABS(q1, q0); \
- \
- const __m128i h = _mm_set1_epi8(hev_thresh); \
- const __m128i t3 = _mm_subs_epu8(t1, h); /* abs(p1 - p0) - hev_tresh */ \
- const __m128i t4 = _mm_subs_epu8(t2, h); /* abs(q1 - q0) - hev_tresh */ \
- \
- not_hev = _mm_or_si128(t3, t4); \
- not_hev = _mm_cmpeq_epi8(not_hev, zero); /* not_hev <= t1 && not_hev <= t2 */\
-}
-
-#define GET_BASE_DELTA(p1, p0, q0, q1, o) { \
- const __m128i qp0 = _mm_subs_epi8(q0, p0); /* q0 - p0 */ \
- o = _mm_subs_epi8(p1, q1); /* p1 - q1 */ \
- o = _mm_adds_epi8(o, qp0); /* p1 - q1 + 1 * (q0 - p0) */ \
- o = _mm_adds_epi8(o, qp0); /* p1 - q1 + 2 * (q0 - p0) */ \
- o = _mm_adds_epi8(o, qp0); /* p1 - q1 + 3 * (q0 - p0) */ \
-}
-
-#define DO_SIMPLE_FILTER(p0, q0, fl) { \
- const __m128i three = _mm_set1_epi8(3); \
- const __m128i four = _mm_set1_epi8(4); \
- __m128i v3 = _mm_adds_epi8(fl, three); \
- __m128i v4 = _mm_adds_epi8(fl, four); \
- \
- /* Do +4 side */ \
- SIGNED_SHIFT_N(v4, 3); /* v4 >> 3 */ \
- q0 = _mm_subs_epi8(q0, v4); /* q0 -= v4 */ \
- \
- /* Now do +3 side */ \
- SIGNED_SHIFT_N(v3, 3); /* v3 >> 3 */ \
- p0 = _mm_adds_epi8(p0, v3); /* p0 += v3 */ \
+// input/output is uint8_t
+static WEBP_INLINE void GetNotHEV(const __m128i* const p1,
+ const __m128i* const p0,
+ const __m128i* const q0,
+ const __m128i* const q1,
+ int hev_thresh, __m128i* const not_hev) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i t_1 = MM_ABS(*p1, *p0);
+ const __m128i t_2 = MM_ABS(*q1, *q0);
+
+ const __m128i h = _mm_set1_epi8(hev_thresh);
+ const __m128i t_max = _mm_max_epu8(t_1, t_2);
+
+ const __m128i t_max_h = _mm_subs_epu8(t_max, h);
+ *not_hev = _mm_cmpeq_epi8(t_max_h, zero); // not_hev <= t1 && not_hev <= t2
}
-// Updates values of 2 pixels at MB edge during complex filtering.
-// Update operations:
-// q = q - a and p = p + a; where a = [(a_hi >> 7), (a_lo >> 7)]
-#define UPDATE_2PIXELS(pi, qi, a_lo, a_hi) { \
- const __m128i a_lo7 = _mm_srai_epi16(a_lo, 7); \
- const __m128i a_hi7 = _mm_srai_epi16(a_hi, 7); \
- const __m128i a = _mm_packs_epi16(a_lo7, a_hi7); \
- pi = _mm_adds_epi8(pi, a); \
- qi = _mm_subs_epi8(qi, a); \
+// input pixels are int8_t
+static WEBP_INLINE void GetBaseDelta(const __m128i* const p1,
+ const __m128i* const p0,
+ const __m128i* const q0,
+ const __m128i* const q1,
+ __m128i* const delta) {
+ // beware of addition order, for saturation!
+ const __m128i p1_q1 = _mm_subs_epi8(*p1, *q1); // p1 - q1
+ const __m128i q0_p0 = _mm_subs_epi8(*q0, *p0); // q0 - p0
+ const __m128i s1 = _mm_adds_epi8(p1_q1, q0_p0); // p1 - q1 + 1 * (q0 - p0)
+ const __m128i s2 = _mm_adds_epi8(q0_p0, s1); // p1 - q1 + 2 * (q0 - p0)
+ const __m128i s3 = _mm_adds_epi8(q0_p0, s2); // p1 - q1 + 3 * (q0 - p0)
+ *delta = s3;
}
-static void NeedsFilter(const __m128i* p1, const __m128i* p0, const __m128i* q0,
- const __m128i* q1, int thresh, __m128i *mask) {
- __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1)
- *mask = _mm_set1_epi8(0xFE);
- t1 = _mm_and_si128(t1, *mask); // set lsb of each byte to zero
- t1 = _mm_srli_epi16(t1, 1); // abs(p1 - q1) / 2
+// input and output are int8_t
+static WEBP_INLINE void DoSimpleFilter(__m128i* const p0, __m128i* const q0,
+ const __m128i* const fl) {
+ const __m128i k3 = _mm_set1_epi8(3);
+ const __m128i k4 = _mm_set1_epi8(4);
+ __m128i v3 = _mm_adds_epi8(*fl, k3);
+ __m128i v4 = _mm_adds_epi8(*fl, k4);
+
+ SignedShift8b(&v4); // v4 >> 3
+ SignedShift8b(&v3); // v3 >> 3
+ *q0 = _mm_subs_epi8(*q0, v4); // q0 -= v4
+ *p0 = _mm_adds_epi8(*p0, v3); // p0 += v3
+}
- *mask = MM_ABS(*p0, *q0); // abs(p0 - q0)
- *mask = _mm_adds_epu8(*mask, *mask); // abs(p0 - q0) * 2
- *mask = _mm_adds_epu8(*mask, t1); // abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+// Updates values of 2 pixels at MB edge during complex filtering.
+// Update operations:
+// q = q - delta and p = p + delta; where delta = [(a_hi >> 7), (a_lo >> 7)]
+// Pixels 'pi' and 'qi' are int8_t on input, uint8_t on output (sign flip).
+static WEBP_INLINE void Update2Pixels(__m128i* const pi, __m128i* const qi,
+ const __m128i* const a0_lo,
+ const __m128i* const a0_hi) {
+ const __m128i a1_lo = _mm_srai_epi16(*a0_lo, 7);
+ const __m128i a1_hi = _mm_srai_epi16(*a0_hi, 7);
+ const __m128i delta = _mm_packs_epi16(a1_lo, a1_hi);
+ const __m128i sign_bit = _mm_set1_epi8(0x80);
+ *pi = _mm_adds_epi8(*pi, delta);
+ *qi = _mm_subs_epi8(*qi, delta);
+ FLIP_SIGN_BIT2(*pi, *qi);
+}
- t1 = _mm_set1_epi8(thresh);
- *mask = _mm_subs_epu8(*mask, t1); // mask <= thresh
- *mask = _mm_cmpeq_epi8(*mask, _mm_setzero_si128());
+// input pixels are uint8_t
+static WEBP_INLINE void NeedsFilter(const __m128i* const p1,
+ const __m128i* const p0,
+ const __m128i* const q0,
+ const __m128i* const q1,
+ int thresh, __m128i* const mask) {
+ const __m128i m_thresh = _mm_set1_epi8(thresh);
+ const __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1)
+ const __m128i kFE = _mm_set1_epi8(0xFE);
+ const __m128i t2 = _mm_and_si128(t1, kFE); // set lsb of each byte to zero
+ const __m128i t3 = _mm_srli_epi16(t2, 1); // abs(p1 - q1) / 2
+
+ const __m128i t4 = MM_ABS(*p0, *q0); // abs(p0 - q0)
+ const __m128i t5 = _mm_adds_epu8(t4, t4); // abs(p0 - q0) * 2
+ const __m128i t6 = _mm_adds_epu8(t5, t3); // abs(p0-q0)*2 + abs(p1-q1)/2
+
+ const __m128i t7 = _mm_subs_epu8(t6, m_thresh); // mask <= m_thresh
+ *mask = _mm_cmpeq_epi8(t7, _mm_setzero_si128());
}
//------------------------------------------------------------------------------
// Edge filtering functions
// Applies filter on 2 pixels (p0 and q0)
-static WEBP_INLINE void DoFilter2(const __m128i* p1, __m128i* p0, __m128i* q0,
- const __m128i* q1, int thresh) {
+static WEBP_INLINE void DoFilter2(__m128i* const p1, __m128i* const p0,
+ __m128i* const q0, __m128i* const q1,
+ int thresh) {
__m128i a, mask;
const __m128i sign_bit = _mm_set1_epi8(0x80);
+ // convert p1/q1 to int8_t (for GetBaseDelta)
const __m128i p1s = _mm_xor_si128(*p1, sign_bit);
const __m128i q1s = _mm_xor_si128(*q1, sign_bit);
NeedsFilter(p1, p0, q0, q1, thresh, &mask);
- // convert to signed values
FLIP_SIGN_BIT2(*p0, *q0);
-
- GET_BASE_DELTA(p1s, *p0, *q0, q1s, a);
+ GetBaseDelta(&p1s, p0, q0, &q1s, &a);
a = _mm_and_si128(a, mask); // mask filter values we don't care about
- DO_SIMPLE_FILTER(*p0, *q0, a);
-
- // unoffset
+ DoSimpleFilter(p0, q0, &a);
FLIP_SIGN_BIT2(*p0, *q0);
}
// Applies filter on 4 pixels (p1, p0, q0 and q1)
-static WEBP_INLINE void DoFilter4(__m128i* p1, __m128i *p0,
- __m128i* q0, __m128i* q1,
- const __m128i* mask, int hev_thresh) {
+static WEBP_INLINE void DoFilter4(__m128i* const p1, __m128i* const p0,
+ __m128i* const q0, __m128i* const q1,
+ const __m128i* const mask, int hev_thresh) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i sign_bit = _mm_set1_epi8(0x80);
+ const __m128i k64 = _mm_set1_epi8(64);
+ const __m128i k3 = _mm_set1_epi8(3);
+ const __m128i k4 = _mm_set1_epi8(4);
__m128i not_hev;
__m128i t1, t2, t3;
- const __m128i sign_bit = _mm_set1_epi8(0x80);
// compute hev mask
- GET_NOTHEV(*p1, *p0, *q0, *q1, hev_thresh, not_hev);
+ GetNotHEV(p1, p0, q0, q1, hev_thresh, &not_hev);
// convert to signed values
FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1);
@@ -385,135 +448,115 @@ static WEBP_INLINE void DoFilter4(__m128i* p1, __m128i *p0,
t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 3 * (q0 - p0)
t1 = _mm_and_si128(t1, *mask); // mask filter values we don't care about
- // Do +4 side
- t2 = _mm_set1_epi8(4);
- t2 = _mm_adds_epi8(t1, t2); // 3 * (q0 - p0) + (p1 - q1) + 4
- SIGNED_SHIFT_N(t2, 3); // (3 * (q0 - p0) + hev(p1 - q1) + 4) >> 3
- t3 = t2; // save t2
- *q0 = _mm_subs_epi8(*q0, t2); // q0 -= t2
-
- // Now do +3 side
- t2 = _mm_set1_epi8(3);
- t2 = _mm_adds_epi8(t1, t2); // +3 instead of +4
- SIGNED_SHIFT_N(t2, 3); // (3 * (q0 - p0) + hev(p1 - q1) + 3) >> 3
+ t2 = _mm_adds_epi8(t1, k3); // 3 * (q0 - p0) + hev(p1 - q1) + 3
+ t3 = _mm_adds_epi8(t1, k4); // 3 * (q0 - p0) + hev(p1 - q1) + 4
+ SignedShift8b(&t2); // (3 * (q0 - p0) + hev(p1 - q1) + 3) >> 3
+ SignedShift8b(&t3); // (3 * (q0 - p0) + hev(p1 - q1) + 4) >> 3
*p0 = _mm_adds_epi8(*p0, t2); // p0 += t2
+ *q0 = _mm_subs_epi8(*q0, t3); // q0 -= t3
+ FLIP_SIGN_BIT2(*p0, *q0);
- t2 = _mm_set1_epi8(1);
- t3 = _mm_adds_epi8(t3, t2);
- SIGNED_SHIFT_N(t3, 1); // (3 * (q0 - p0) + hev(p1 - q1) + 4) >> 4
+ // this is equivalent to signed (a + 1) >> 1 calculation
+ t2 = _mm_add_epi8(t3, sign_bit);
+ t3 = _mm_avg_epu8(t2, zero);
+ t3 = _mm_sub_epi8(t3, k64);
t3 = _mm_and_si128(not_hev, t3); // if !hev
*q1 = _mm_subs_epi8(*q1, t3); // q1 -= t3
*p1 = _mm_adds_epi8(*p1, t3); // p1 += t3
-
- // unoffset
- FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1);
+ FLIP_SIGN_BIT2(*p1, *q1);
}
// Applies filter on 6 pixels (p2, p1, p0, q0, q1 and q2)
-static WEBP_INLINE void DoFilter6(__m128i *p2, __m128i* p1, __m128i *p0,
- __m128i* q0, __m128i* q1, __m128i *q2,
- const __m128i* mask, int hev_thresh) {
- __m128i a, not_hev;
+static WEBP_INLINE void DoFilter6(__m128i* const p2, __m128i* const p1,
+ __m128i* const p0, __m128i* const q0,
+ __m128i* const q1, __m128i* const q2,
+ const __m128i* const mask, int hev_thresh) {
+ const __m128i zero = _mm_setzero_si128();
const __m128i sign_bit = _mm_set1_epi8(0x80);
+ __m128i a, not_hev;
// compute hev mask
- GET_NOTHEV(*p1, *p0, *q0, *q1, hev_thresh, not_hev);
+ GetNotHEV(p1, p0, q0, q1, hev_thresh, &not_hev);
- // convert to signed values
FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1);
FLIP_SIGN_BIT2(*p2, *q2);
-
- GET_BASE_DELTA(*p1, *p0, *q0, *q1, a);
+ GetBaseDelta(p1, p0, q0, q1, &a);
{ // do simple filter on pixels with hev
const __m128i m = _mm_andnot_si128(not_hev, *mask);
const __m128i f = _mm_and_si128(a, m);
- DO_SIMPLE_FILTER(*p0, *q0, f);
+ DoSimpleFilter(p0, q0, &f);
}
+
{ // do strong filter on pixels with not hev
- const __m128i zero = _mm_setzero_si128();
- const __m128i nine = _mm_set1_epi16(0x0900);
- const __m128i sixty_three = _mm_set1_epi16(63);
+ const __m128i k9 = _mm_set1_epi16(0x0900);
+ const __m128i k63 = _mm_set1_epi16(63);
const __m128i m = _mm_and_si128(not_hev, *mask);
const __m128i f = _mm_and_si128(a, m);
+
const __m128i f_lo = _mm_unpacklo_epi8(zero, f);
const __m128i f_hi = _mm_unpackhi_epi8(zero, f);
- const __m128i f9_lo = _mm_mulhi_epi16(f_lo, nine); // Filter (lo) * 9
- const __m128i f9_hi = _mm_mulhi_epi16(f_hi, nine); // Filter (hi) * 9
- const __m128i f18_lo = _mm_add_epi16(f9_lo, f9_lo); // Filter (lo) * 18
- const __m128i f18_hi = _mm_add_epi16(f9_hi, f9_hi); // Filter (hi) * 18
+ const __m128i f9_lo = _mm_mulhi_epi16(f_lo, k9); // Filter (lo) * 9
+ const __m128i f9_hi = _mm_mulhi_epi16(f_hi, k9); // Filter (hi) * 9
- const __m128i a2_lo = _mm_add_epi16(f9_lo, sixty_three); // Filter * 9 + 63
- const __m128i a2_hi = _mm_add_epi16(f9_hi, sixty_three); // Filter * 9 + 63
+ const __m128i a2_lo = _mm_add_epi16(f9_lo, k63); // Filter * 9 + 63
+ const __m128i a2_hi = _mm_add_epi16(f9_hi, k63); // Filter * 9 + 63
- const __m128i a1_lo = _mm_add_epi16(f18_lo, sixty_three); // F... * 18 + 63
- const __m128i a1_hi = _mm_add_epi16(f18_hi, sixty_three); // F... * 18 + 63
+ const __m128i a1_lo = _mm_add_epi16(a2_lo, f9_lo); // Filter * 18 + 63
+ const __m128i a1_hi = _mm_add_epi16(a2_hi, f9_hi); // Filter * 18 + 63
- const __m128i a0_lo = _mm_add_epi16(f18_lo, a2_lo); // Filter * 27 + 63
- const __m128i a0_hi = _mm_add_epi16(f18_hi, a2_hi); // Filter * 27 + 63
+ const __m128i a0_lo = _mm_add_epi16(a1_lo, f9_lo); // Filter * 27 + 63
+ const __m128i a0_hi = _mm_add_epi16(a1_hi, f9_hi); // Filter * 27 + 63
- UPDATE_2PIXELS(*p2, *q2, a2_lo, a2_hi);
- UPDATE_2PIXELS(*p1, *q1, a1_lo, a1_hi);
- UPDATE_2PIXELS(*p0, *q0, a0_lo, a0_hi);
+ Update2Pixels(p2, q2, &a2_lo, &a2_hi);
+ Update2Pixels(p1, q1, &a1_lo, &a1_hi);
+ Update2Pixels(p0, q0, &a0_lo, &a0_hi);
}
+}
- // unoffset
- FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1);
- FLIP_SIGN_BIT2(*p2, *q2);
+// memcpy() is the safe way of moving potentially unaligned 32b memory.
+static WEBP_INLINE uint32_t MemToUint32(const uint8_t* const ptr) {
+ uint32_t A;
+ memcpy(&A, (const int*)ptr, sizeof(A));
+ return A;
}
// reads 8 rows across a vertical edge.
-//
-// TODO(somnath): Investigate _mm_shuffle* also see if it can be broken into
-// two Load4x4() to avoid code duplication.
-static WEBP_INLINE void Load8x4(const uint8_t* b, int stride,
- __m128i* p, __m128i* q) {
- __m128i t1, t2;
-
- // Load 0th, 1st, 4th and 5th rows
- __m128i r0 = _mm_cvtsi32_si128(*((int*)&b[0 * stride])); // 03 02 01 00
- __m128i r1 = _mm_cvtsi32_si128(*((int*)&b[1 * stride])); // 13 12 11 10
- __m128i r4 = _mm_cvtsi32_si128(*((int*)&b[4 * stride])); // 43 42 41 40
- __m128i r5 = _mm_cvtsi32_si128(*((int*)&b[5 * stride])); // 53 52 51 50
-
- r0 = _mm_unpacklo_epi32(r0, r4); // 43 42 41 40 03 02 01 00
- r1 = _mm_unpacklo_epi32(r1, r5); // 53 52 51 50 13 12 11 10
-
- // t1 = 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00
- t1 = _mm_unpacklo_epi8(r0, r1);
-
- // Load 2nd, 3rd, 6th and 7th rows
- r0 = _mm_cvtsi32_si128(*((int*)&b[2 * stride])); // 23 22 21 22
- r1 = _mm_cvtsi32_si128(*((int*)&b[3 * stride])); // 33 32 31 30
- r4 = _mm_cvtsi32_si128(*((int*)&b[6 * stride])); // 63 62 61 60
- r5 = _mm_cvtsi32_si128(*((int*)&b[7 * stride])); // 73 72 71 70
-
- r0 = _mm_unpacklo_epi32(r0, r4); // 63 62 61 60 23 22 21 20
- r1 = _mm_unpacklo_epi32(r1, r5); // 73 72 71 70 33 32 31 30
-
- // t2 = 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20
- t2 = _mm_unpacklo_epi8(r0, r1);
-
- // t1 = 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00
- // t2 = 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40
- r0 = t1;
- t1 = _mm_unpacklo_epi16(t1, t2);
- t2 = _mm_unpackhi_epi16(r0, t2);
+static WEBP_INLINE void Load8x4(const uint8_t* const b, int stride,
+ __m128i* const p, __m128i* const q) {
+ // A0 = 63 62 61 60 23 22 21 20 43 42 41 40 03 02 01 00
+ // A1 = 73 72 71 70 33 32 31 30 53 52 51 50 13 12 11 10
+ const __m128i A0 = _mm_set_epi32(
+ MemToUint32(&b[6 * stride]), MemToUint32(&b[2 * stride]),
+ MemToUint32(&b[4 * stride]), MemToUint32(&b[0 * stride]));
+ const __m128i A1 = _mm_set_epi32(
+ MemToUint32(&b[7 * stride]), MemToUint32(&b[3 * stride]),
+ MemToUint32(&b[5 * stride]), MemToUint32(&b[1 * stride]));
+
+ // B0 = 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00
+ // B1 = 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20
+ const __m128i B0 = _mm_unpacklo_epi8(A0, A1);
+ const __m128i B1 = _mm_unpackhi_epi8(A0, A1);
+
+ // C0 = 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00
+ // C1 = 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40
+ const __m128i C0 = _mm_unpacklo_epi16(B0, B1);
+ const __m128i C1 = _mm_unpackhi_epi16(B0, B1);
// *p = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
// *q = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
- *p = _mm_unpacklo_epi32(t1, t2);
- *q = _mm_unpackhi_epi32(t1, t2);
+ *p = _mm_unpacklo_epi32(C0, C1);
+ *q = _mm_unpackhi_epi32(C0, C1);
}
-static WEBP_INLINE void Load16x4(const uint8_t* r0, const uint8_t* r8,
+static WEBP_INLINE void Load16x4(const uint8_t* const r0,
+ const uint8_t* const r8,
int stride,
- __m128i* p1, __m128i* p0,
- __m128i* q0, __m128i* q1) {
- __m128i t1, t2;
+ __m128i* const p1, __m128i* const p0,
+ __m128i* const q0, __m128i* const q1) {
// Assume the pixels around the edge (|) are numbered as follows
// 00 01 | 02 03
// 10 11 | 12 13
@@ -532,19 +575,21 @@ static WEBP_INLINE void Load16x4(const uint8_t* r0, const uint8_t* r8,
Load8x4(r0, stride, p1, q0);
Load8x4(r8, stride, p0, q1);
- t1 = *p1;
- t2 = *q0;
- // p1 = f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
- // p0 = f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01
- // q0 = f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
- // q1 = f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
- *p1 = _mm_unpacklo_epi64(t1, *p0);
- *p0 = _mm_unpackhi_epi64(t1, *p0);
- *q0 = _mm_unpacklo_epi64(t2, *q1);
- *q1 = _mm_unpackhi_epi64(t2, *q1);
+ {
+ // p1 = f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
+ // p0 = f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01
+ // q0 = f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+ // q1 = f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
+ const __m128i t1 = *p1;
+ const __m128i t2 = *q0;
+ *p1 = _mm_unpacklo_epi64(t1, *p0);
+ *p0 = _mm_unpackhi_epi64(t1, *p0);
+ *q0 = _mm_unpacklo_epi64(t2, *q1);
+ *q1 = _mm_unpackhi_epi64(t2, *q1);
+ }
}
-static WEBP_INLINE void Store4x4(__m128i* x, uint8_t* dst, int stride) {
+static WEBP_INLINE void Store4x4(__m128i* const x, uint8_t* dst, int stride) {
int i;
for (i = 0; i < 4; ++i, dst += stride) {
*((int32_t*)dst) = _mm_cvtsi128_si32(*x);
@@ -553,48 +598,51 @@ static WEBP_INLINE void Store4x4(__m128i* x, uint8_t* dst, int stride) {
}
// Transpose back and store
-static WEBP_INLINE void Store16x4(uint8_t* r0, uint8_t* r8, int stride,
- __m128i* p1, __m128i* p0,
- __m128i* q0, __m128i* q1) {
- __m128i t1;
+static WEBP_INLINE void Store16x4(const __m128i* const p1,
+ const __m128i* const p0,
+ const __m128i* const q0,
+ const __m128i* const q1,
+ uint8_t* r0, uint8_t* r8,
+ int stride) {
+ __m128i t1, p1_s, p0_s, q0_s, q1_s;
// p0 = 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00
// p1 = f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80
t1 = *p0;
- *p0 = _mm_unpacklo_epi8(*p1, t1);
- *p1 = _mm_unpackhi_epi8(*p1, t1);
+ p0_s = _mm_unpacklo_epi8(*p1, t1);
+ p1_s = _mm_unpackhi_epi8(*p1, t1);
// q0 = 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02
// q1 = f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82
t1 = *q0;
- *q0 = _mm_unpacklo_epi8(t1, *q1);
- *q1 = _mm_unpackhi_epi8(t1, *q1);
+ q0_s = _mm_unpacklo_epi8(t1, *q1);
+ q1_s = _mm_unpackhi_epi8(t1, *q1);
// p0 = 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00
// q0 = 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40
- t1 = *p0;
- *p0 = _mm_unpacklo_epi16(t1, *q0);
- *q0 = _mm_unpackhi_epi16(t1, *q0);
+ t1 = p0_s;
+ p0_s = _mm_unpacklo_epi16(t1, q0_s);
+ q0_s = _mm_unpackhi_epi16(t1, q0_s);
// p1 = b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80
// q1 = f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0
- t1 = *p1;
- *p1 = _mm_unpacklo_epi16(t1, *q1);
- *q1 = _mm_unpackhi_epi16(t1, *q1);
+ t1 = p1_s;
+ p1_s = _mm_unpacklo_epi16(t1, q1_s);
+ q1_s = _mm_unpackhi_epi16(t1, q1_s);
- Store4x4(p0, r0, stride);
+ Store4x4(&p0_s, r0, stride);
r0 += 4 * stride;
- Store4x4(q0, r0, stride);
+ Store4x4(&q0_s, r0, stride);
- Store4x4(p1, r8, stride);
+ Store4x4(&p1_s, r8, stride);
r8 += 4 * stride;
- Store4x4(q1, r8, stride);
+ Store4x4(&q1_s, r8, stride);
}
//------------------------------------------------------------------------------
// Simple In-loop filtering (Paragraph 15.2)
-static void SimpleVFilter16SSE2(uint8_t* p, int stride, int thresh) {
+static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
// Load
__m128i p1 = _mm_loadu_si128((__m128i*)&p[-2 * stride]);
__m128i p0 = _mm_loadu_si128((__m128i*)&p[-stride]);
@@ -605,49 +653,49 @@ static void SimpleVFilter16SSE2(uint8_t* p, int stride, int thresh) {
// Store
_mm_storeu_si128((__m128i*)&p[-stride], p0);
- _mm_storeu_si128((__m128i*)p, q0);
+ _mm_storeu_si128((__m128i*)&p[0], q0);
}
-static void SimpleHFilter16SSE2(uint8_t* p, int stride, int thresh) {
+static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
__m128i p1, p0, q0, q1;
p -= 2; // beginning of p1
- Load16x4(p, p + 8 * stride, stride, &p1, &p0, &q0, &q1);
+ Load16x4(p, p + 8 * stride, stride, &p1, &p0, &q0, &q1);
DoFilter2(&p1, &p0, &q0, &q1, thresh);
- Store16x4(p, p + 8 * stride, stride, &p1, &p0, &q0, &q1);
+ Store16x4(&p1, &p0, &q0, &q1, p, p + 8 * stride, stride);
}
-static void SimpleVFilter16iSSE2(uint8_t* p, int stride, int thresh) {
+static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) {
int k;
for (k = 3; k > 0; --k) {
p += 4 * stride;
- SimpleVFilter16SSE2(p, stride, thresh);
+ SimpleVFilter16(p, stride, thresh);
}
}
-static void SimpleHFilter16iSSE2(uint8_t* p, int stride, int thresh) {
+static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
int k;
for (k = 3; k > 0; --k) {
p += 4;
- SimpleHFilter16SSE2(p, stride, thresh);
+ SimpleHFilter16(p, stride, thresh);
}
}
//------------------------------------------------------------------------------
// Complex In-loop filtering (Paragraph 15.3)
-#define MAX_DIFF1(p3, p2, p1, p0, m) { \
- m = MM_ABS(p3, p2); \
+#define MAX_DIFF1(p3, p2, p1, p0, m) do { \
+ m = MM_ABS(p1, p0); \
+ m = _mm_max_epu8(m, MM_ABS(p3, p2)); \
m = _mm_max_epu8(m, MM_ABS(p2, p1)); \
- m = _mm_max_epu8(m, MM_ABS(p1, p0)); \
-}
+} while (0)
-#define MAX_DIFF2(p3, p2, p1, p0, m) { \
+#define MAX_DIFF2(p3, p2, p1, p0, m) do { \
+ m = _mm_max_epu8(m, MM_ABS(p1, p0)); \
m = _mm_max_epu8(m, MM_ABS(p3, p2)); \
m = _mm_max_epu8(m, MM_ABS(p2, p1)); \
- m = _mm_max_epu8(m, MM_ABS(p1, p0)); \
-}
+} while (0)
#define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) { \
e1 = _mm_loadu_si128((__m128i*)&(p)[0 * stride]); \
@@ -656,10 +704,11 @@ static void SimpleHFilter16iSSE2(uint8_t* p, int stride, int thresh) {
e4 = _mm_loadu_si128((__m128i*)&(p)[3 * stride]); \
}
-#define LOADUV_H_EDGE(p, u, v, stride) { \
- p = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \
- p = _mm_unpacklo_epi64(p, _mm_loadl_epi64((__m128i*)&(v)[(stride)])); \
-}
+#define LOADUV_H_EDGE(p, u, v, stride) do { \
+ const __m128i U = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \
+ const __m128i V = _mm_loadl_epi64((__m128i*)&(v)[(stride)]); \
+ p = _mm_unpacklo_epi64(U, V); \
+} while (0)
#define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) { \
LOADUV_H_EDGE(e1, u, v, 0 * stride); \
@@ -674,18 +723,23 @@ static void SimpleHFilter16iSSE2(uint8_t* p, int stride, int thresh) {
_mm_storel_epi64((__m128i*)&v[(stride)], p); \
}
-#define COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask) { \
- __m128i fl_yes; \
- const __m128i it = _mm_set1_epi8(ithresh); \
- mask = _mm_subs_epu8(mask, it); \
- mask = _mm_cmpeq_epi8(mask, _mm_setzero_si128()); \
- NeedsFilter(&p1, &p0, &q0, &q1, thresh, &fl_yes); \
- mask = _mm_and_si128(mask, fl_yes); \
+static WEBP_INLINE void ComplexMask(const __m128i* const p1,
+ const __m128i* const p0,
+ const __m128i* const q0,
+ const __m128i* const q1,
+ int thresh, int ithresh,
+ __m128i* const mask) {
+ const __m128i it = _mm_set1_epi8(ithresh);
+ const __m128i diff = _mm_subs_epu8(*mask, it);
+ const __m128i thresh_mask = _mm_cmpeq_epi8(diff, _mm_setzero_si128());
+ __m128i filter_mask;
+ NeedsFilter(p1, p0, q0, q1, thresh, &filter_mask);
+ *mask = _mm_and_si128(thresh_mask, filter_mask);
}
// on macroblock edges
-static void VFilter16SSE2(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
+static void VFilter16(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
__m128i t1;
__m128i mask;
__m128i p2, p1, p0, q0, q1, q2;
@@ -698,20 +752,20 @@ static void VFilter16SSE2(uint8_t* p, int stride,
LOAD_H_EDGES4(p, stride, q0, q1, q2, t1);
MAX_DIFF2(t1, q2, q1, q0, mask);
- COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
+ ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
// Store
_mm_storeu_si128((__m128i*)&p[-3 * stride], p2);
_mm_storeu_si128((__m128i*)&p[-2 * stride], p1);
_mm_storeu_si128((__m128i*)&p[-1 * stride], p0);
- _mm_storeu_si128((__m128i*)&p[0 * stride], q0);
- _mm_storeu_si128((__m128i*)&p[1 * stride], q1);
- _mm_storeu_si128((__m128i*)&p[2 * stride], q2);
+ _mm_storeu_si128((__m128i*)&p[+0 * stride], q0);
+ _mm_storeu_si128((__m128i*)&p[+1 * stride], q1);
+ _mm_storeu_si128((__m128i*)&p[+2 * stride], q2);
}
-static void HFilter16SSE2(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
+static void HFilter16(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
__m128i mask;
__m128i p3, p2, p1, p0, q0, q1, q2, q3;
@@ -722,71 +776,78 @@ static void HFilter16SSE2(uint8_t* p, int stride,
Load16x4(p, p + 8 * stride, stride, &q0, &q1, &q2, &q3); // q0, q1, q2, q3
MAX_DIFF2(q3, q2, q1, q0, mask);
- COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
+ ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
- Store16x4(b, b + 8 * stride, stride, &p3, &p2, &p1, &p0);
- Store16x4(p, p + 8 * stride, stride, &q0, &q1, &q2, &q3);
+ Store16x4(&p3, &p2, &p1, &p0, b, b + 8 * stride, stride);
+ Store16x4(&q0, &q1, &q2, &q3, p, p + 8 * stride, stride);
}
// on three inner edges
-static void VFilter16iSSE2(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
+static void VFilter16i(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
int k;
- __m128i mask;
- __m128i t1, t2, p1, p0, q0, q1;
+ __m128i p3, p2, p1, p0; // loop invariants
- for (k = 3; k > 0; --k) {
- // Load p3, p2, p1, p0
- LOAD_H_EDGES4(p, stride, t2, t1, p1, p0);
- MAX_DIFF1(t2, t1, p1, p0, mask);
+ LOAD_H_EDGES4(p, stride, p3, p2, p1, p0); // prologue
+ for (k = 3; k > 0; --k) {
+ __m128i mask, tmp1, tmp2;
+ uint8_t* const b = p + 2 * stride; // beginning of p1
p += 4 * stride;
- // Load q0, q1, q2, q3
- LOAD_H_EDGES4(p, stride, q0, q1, t1, t2);
- MAX_DIFF2(t2, t1, q1, q0, mask);
+ MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask
+ LOAD_H_EDGES4(p, stride, p3, p2, tmp1, tmp2);
+ MAX_DIFF2(p3, p2, tmp1, tmp2, mask);
- COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
- DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh);
+ // p3 and p2 are not just temporary variables here: they will be
+ // re-used for next span. And q2/q3 will become p1/p0 accordingly.
+ ComplexMask(&p1, &p0, &p3, &p2, thresh, ithresh, &mask);
+ DoFilter4(&p1, &p0, &p3, &p2, &mask, hev_thresh);
// Store
- _mm_storeu_si128((__m128i*)&p[-2 * stride], p1);
- _mm_storeu_si128((__m128i*)&p[-1 * stride], p0);
- _mm_storeu_si128((__m128i*)&p[0 * stride], q0);
- _mm_storeu_si128((__m128i*)&p[1 * stride], q1);
+ _mm_storeu_si128((__m128i*)&b[0 * stride], p1);
+ _mm_storeu_si128((__m128i*)&b[1 * stride], p0);
+ _mm_storeu_si128((__m128i*)&b[2 * stride], p3);
+ _mm_storeu_si128((__m128i*)&b[3 * stride], p2);
+
+ // rotate samples
+ p1 = tmp1;
+ p0 = tmp2;
}
}
-static void HFilter16iSSE2(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
+static void HFilter16i(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
int k;
- uint8_t* b;
- __m128i mask;
- __m128i t1, t2, p1, p0, q0, q1;
+ __m128i p3, p2, p1, p0; // loop invariants
+
+ Load16x4(p, p + 8 * stride, stride, &p3, &p2, &p1, &p0); // prologue
for (k = 3; k > 0; --k) {
- b = p;
- Load16x4(b, b + 8 * stride, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0
- MAX_DIFF1(t2, t1, p1, p0, mask);
+ __m128i mask, tmp1, tmp2;
+ uint8_t* const b = p + 2; // beginning of p1
- b += 4; // beginning of q0
- Load16x4(b, b + 8 * stride, stride, &q0, &q1, &t1, &t2); // q0, q1, q2, q3
- MAX_DIFF2(t2, t1, q1, q0, mask);
+ p += 4; // beginning of q0 (and next span)
- COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
- DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh);
+ MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask
+ Load16x4(p, p + 8 * stride, stride, &p3, &p2, &tmp1, &tmp2);
+ MAX_DIFF2(p3, p2, tmp1, tmp2, mask);
- b -= 2; // beginning of p1
- Store16x4(b, b + 8 * stride, stride, &p1, &p0, &q0, &q1);
+ ComplexMask(&p1, &p0, &p3, &p2, thresh, ithresh, &mask);
+ DoFilter4(&p1, &p0, &p3, &p2, &mask, hev_thresh);
- p += 4;
+ Store16x4(&p1, &p0, &p3, &p2, b, b + 8 * stride, stride);
+
+ // rotate samples
+ p1 = tmp1;
+ p0 = tmp2;
}
}
// 8-pixels wide variant, for chroma filtering
-static void VFilter8SSE2(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
+static void VFilter8(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
__m128i mask;
__m128i t1, p2, p1, p0, q0, q1, q2;
@@ -798,7 +859,7 @@ static void VFilter8SSE2(uint8_t* u, uint8_t* v, int stride,
LOADUV_H_EDGES4(u, v, stride, q0, q1, q2, t1);
MAX_DIFF2(t1, q2, q1, q0, mask);
- COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
+ ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
// Store
@@ -810,8 +871,8 @@ static void VFilter8SSE2(uint8_t* u, uint8_t* v, int stride,
STOREUV(q2, u, v, 2 * stride);
}
-static void HFilter8SSE2(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
+static void HFilter8(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
__m128i mask;
__m128i p3, p2, p1, p0, q0, q1, q2, q3;
@@ -823,15 +884,15 @@ static void HFilter8SSE2(uint8_t* u, uint8_t* v, int stride,
Load16x4(u, v, stride, &q0, &q1, &q2, &q3); // q0, q1, q2, q3
MAX_DIFF2(q3, q2, q1, q0, mask);
- COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
+ ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
- Store16x4(tu, tv, stride, &p3, &p2, &p1, &p0);
- Store16x4(u, v, stride, &q0, &q1, &q2, &q3);
+ Store16x4(&p3, &p2, &p1, &p0, tu, tv, stride);
+ Store16x4(&q0, &q1, &q2, &q3, u, v, stride);
}
-static void VFilter8iSSE2(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
+static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
__m128i mask;
__m128i t1, t2, p1, p0, q0, q1;
@@ -846,7 +907,7 @@ static void VFilter8iSSE2(uint8_t* u, uint8_t* v, int stride,
LOADUV_H_EDGES4(u, v, stride, q0, q1, t1, t2);
MAX_DIFF2(t2, t1, q1, q0, mask);
- COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
+ ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh);
// Store
@@ -856,8 +917,8 @@ static void VFilter8iSSE2(uint8_t* u, uint8_t* v, int stride,
STOREUV(q1, u, v, 1 * stride);
}
-static void HFilter8iSSE2(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
+static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
__m128i mask;
__m128i t1, t2, p1, p0, q0, q1;
Load16x4(u, v, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0
@@ -868,36 +929,361 @@ static void HFilter8iSSE2(uint8_t* u, uint8_t* v, int stride,
Load16x4(u, v, stride, &q0, &q1, &t1, &t2); // q0, q1, q2, q3
MAX_DIFF2(t2, t1, q1, q0, mask);
- COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
+ ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh);
u -= 2; // beginning of p1
v -= 2;
- Store16x4(u, v, stride, &p1, &p0, &q0, &q1);
+ Store16x4(&p1, &p0, &q0, &q1, u, v, stride);
}
-extern void VP8DspInitSSE2(void);
+//------------------------------------------------------------------------------
+// 4x4 predictions
+
+#define DST(x, y) dst[(x) + (y) * BPS]
+#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2)
+
+// We use the following 8b-arithmetic tricks:
+// (a + 2 * b + c + 2) >> 2 = (AC + b + 1) >> 1
+// where: AC = (a + c) >> 1 = [(a + c + 1) >> 1] - [(a^c) & 1]
+// and:
+// (a + 2 * b + c + 2) >> 2 = (AB + BC + 1) >> 1 - (ab|bc)&lsb
+// where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1
+// and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1
+
+static void VE4(uint8_t* dst) { // vertical
+ const __m128i one = _mm_set1_epi8(1);
+ const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS - 1));
+ const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1);
+ const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2);
+ const __m128i a = _mm_avg_epu8(ABCDEFGH, CDEFGH00);
+ const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one);
+ const __m128i b = _mm_subs_epu8(a, lsb);
+ const __m128i avg = _mm_avg_epu8(b, BCDEFGH0);
+ const uint32_t vals = _mm_cvtsi128_si32(avg);
+ int i;
+ for (i = 0; i < 4; ++i) {
+ *(uint32_t*)(dst + i * BPS) = vals;
+ }
+}
+
+static void LD4(uint8_t* dst) { // Down-Left
+ const __m128i one = _mm_set1_epi8(1);
+ const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS));
+ const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1);
+ const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2);
+ const __m128i CDEFGHH0 = _mm_insert_epi16(CDEFGH00, dst[-BPS + 7], 3);
+ const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, CDEFGHH0);
+ const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one);
+ const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
+ const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0);
+ *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( abcdefg );
+ *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1));
+ *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2));
+ *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3));
+}
+
+static void VR4(uint8_t* dst) { // Vertical-Right
+ const __m128i one = _mm_set1_epi8(1);
+ const int I = dst[-1 + 0 * BPS];
+ const int J = dst[-1 + 1 * BPS];
+ const int K = dst[-1 + 2 * BPS];
+ const int X = dst[-1 - BPS];
+ const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1));
+ const __m128i ABCD0 = _mm_srli_si128(XABCD, 1);
+ const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0);
+ const __m128i _XABCD = _mm_slli_si128(XABCD, 1);
+ const __m128i IXABCD = _mm_insert_epi16(_XABCD, I | (X << 8), 0);
+ const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0);
+ const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
+ const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
+ const __m128i efgh = _mm_avg_epu8(avg2, XABCD);
+ *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( abcd );
+ *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32( efgh );
+ *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1));
+ *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1));
+
+ // these two are hard to implement in SSE2, so we keep the C-version:
+ DST(0, 2) = AVG3(J, I, X);
+ DST(0, 3) = AVG3(K, J, I);
+}
-void VP8DspInitSSE2(void) {
- VP8Transform = TransformSSE2;
+static void VL4(uint8_t* dst) { // Vertical-Left
+ const __m128i one = _mm_set1_epi8(1);
+ const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS));
+ const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1);
+ const __m128i CDEFGH__ = _mm_srli_si128(ABCDEFGH, 2);
+ const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, BCDEFGH_);
+ const __m128i avg2 = _mm_avg_epu8(CDEFGH__, BCDEFGH_);
+ const __m128i avg3 = _mm_avg_epu8(avg1, avg2);
+ const __m128i lsb1 = _mm_and_si128(_mm_xor_si128(avg1, avg2), one);
+ const __m128i ab = _mm_xor_si128(ABCDEFGH, BCDEFGH_);
+ const __m128i bc = _mm_xor_si128(CDEFGH__, BCDEFGH_);
+ const __m128i abbc = _mm_or_si128(ab, bc);
+ const __m128i lsb2 = _mm_and_si128(abbc, lsb1);
+ const __m128i avg4 = _mm_subs_epu8(avg3, lsb2);
+ const uint32_t extra_out = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 4));
+ *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( avg1 );
+ *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32( avg4 );
+ *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1));
+ *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1));
+
+ // these two are hard to get and irregular
+ DST(3, 2) = (extra_out >> 0) & 0xff;
+ DST(3, 3) = (extra_out >> 8) & 0xff;
+}
+
+static void RD4(uint8_t* dst) { // Down-right
+ const __m128i one = _mm_set1_epi8(1);
+ const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1));
+ const __m128i ____XABCD = _mm_slli_si128(XABCD, 4);
+ const uint32_t I = dst[-1 + 0 * BPS];
+ const uint32_t J = dst[-1 + 1 * BPS];
+ const uint32_t K = dst[-1 + 2 * BPS];
+ const uint32_t L = dst[-1 + 3 * BPS];
+ const __m128i LKJI_____ =
+ _mm_cvtsi32_si128(L | (K << 8) | (J << 16) | (I << 24));
+ const __m128i LKJIXABCD = _mm_or_si128(LKJI_____, ____XABCD);
+ const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1);
+ const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2);
+ const __m128i avg1 = _mm_avg_epu8(JIXABCD__, LKJIXABCD);
+ const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one);
+ const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
+ const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_);
+ *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32( abcdefg );
+ *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1));
+ *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2));
+ *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3));
+}
+
+#undef DST
+#undef AVG3
+
+//------------------------------------------------------------------------------
+// Luma 16x16
+
+static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) {
+ const uint8_t* top = dst - BPS;
+ const __m128i zero = _mm_setzero_si128();
+ int y;
+ if (size == 4) {
+ const __m128i top_values = _mm_cvtsi32_si128(MemToUint32(top));
+ const __m128i top_base = _mm_unpacklo_epi8(top_values, zero);
+ for (y = 0; y < 4; ++y, dst += BPS) {
+ const int val = dst[-1] - top[-1];
+ const __m128i base = _mm_set1_epi16(val);
+ const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero);
+ *(int*)dst = _mm_cvtsi128_si32(out);
+ }
+ } else if (size == 8) {
+ const __m128i top_values = _mm_loadl_epi64((const __m128i*)top);
+ const __m128i top_base = _mm_unpacklo_epi8(top_values, zero);
+ for (y = 0; y < 8; ++y, dst += BPS) {
+ const int val = dst[-1] - top[-1];
+ const __m128i base = _mm_set1_epi16(val);
+ const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero);
+ _mm_storel_epi64((__m128i*)dst, out);
+ }
+ } else {
+ const __m128i top_values = _mm_loadu_si128((const __m128i*)top);
+ const __m128i top_base_0 = _mm_unpacklo_epi8(top_values, zero);
+ const __m128i top_base_1 = _mm_unpackhi_epi8(top_values, zero);
+ for (y = 0; y < 16; ++y, dst += BPS) {
+ const int val = dst[-1] - top[-1];
+ const __m128i base = _mm_set1_epi16(val);
+ const __m128i out_0 = _mm_add_epi16(base, top_base_0);
+ const __m128i out_1 = _mm_add_epi16(base, top_base_1);
+ const __m128i out = _mm_packus_epi16(out_0, out_1);
+ _mm_storeu_si128((__m128i*)dst, out);
+ }
+ }
+}
+
+static void TM4(uint8_t* dst) { TrueMotion(dst, 4); }
+static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); }
+static void TM16(uint8_t* dst) { TrueMotion(dst, 16); }
+
+static void VE16(uint8_t* dst) {
+ const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS));
+ int j;
+ for (j = 0; j < 16; ++j) {
+ _mm_storeu_si128((__m128i*)(dst + j * BPS), top);
+ }
+}
+
+static void HE16(uint8_t* dst) { // horizontal
+ int j;
+ for (j = 16; j > 0; --j) {
+ const __m128i values = _mm_set1_epi8(dst[-1]);
+ _mm_storeu_si128((__m128i*)dst, values);
+ dst += BPS;
+ }
+}
+
+static WEBP_INLINE void Put16(uint8_t v, uint8_t* dst) {
+ int j;
+ const __m128i values = _mm_set1_epi8(v);
+ for (j = 0; j < 16; ++j) {
+ _mm_storeu_si128((__m128i*)(dst + j * BPS), values);
+ }
+}
+
+static void DC16(uint8_t* dst) { // DC
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS));
+ const __m128i sad8x2 = _mm_sad_epu8(top, zero);
+ // sum the two sads: sad8x2[0:1] + sad8x2[8:9]
+ const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2));
+ int left = 0;
+ int j;
+ for (j = 0; j < 16; ++j) {
+ left += dst[-1 + j * BPS];
+ }
+ {
+ const int DC = _mm_cvtsi128_si32(sum) + left + 16;
+ Put16(DC >> 5, dst);
+ }
+}
+
+static void DC16NoTop(uint8_t* dst) { // DC with top samples not available
+ int DC = 8;
+ int j;
+ for (j = 0; j < 16; ++j) {
+ DC += dst[-1 + j * BPS];
+ }
+ Put16(DC >> 4, dst);
+}
+
+static void DC16NoLeft(uint8_t* dst) { // DC with left samples not available
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS));
+ const __m128i sad8x2 = _mm_sad_epu8(top, zero);
+ // sum the two sads: sad8x2[0:1] + sad8x2[8:9]
+ const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2));
+ const int DC = _mm_cvtsi128_si32(sum) + 8;
+ Put16(DC >> 4, dst);
+}
- VP8VFilter16 = VFilter16SSE2;
- VP8HFilter16 = HFilter16SSE2;
- VP8VFilter8 = VFilter8SSE2;
- VP8HFilter8 = HFilter8SSE2;
- VP8VFilter16i = VFilter16iSSE2;
- VP8HFilter16i = HFilter16iSSE2;
- VP8VFilter8i = VFilter8iSSE2;
- VP8HFilter8i = HFilter8iSSE2;
+static void DC16NoTopLeft(uint8_t* dst) { // DC with no top and left samples
+ Put16(0x80, dst);
+}
+
+//------------------------------------------------------------------------------
+// Chroma
+
+static void VE8uv(uint8_t* dst) { // vertical
+ int j;
+ const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS));
+ for (j = 0; j < 8; ++j) {
+ _mm_storel_epi64((__m128i*)(dst + j * BPS), top);
+ }
+}
+
+static void HE8uv(uint8_t* dst) { // horizontal
+ int j;
+ for (j = 0; j < 8; ++j) {
+ const __m128i values = _mm_set1_epi8(dst[-1]);
+ _mm_storel_epi64((__m128i*)dst, values);
+ dst += BPS;
+ }
+}
+
+// helper for chroma-DC predictions
+static WEBP_INLINE void Put8x8uv(uint8_t v, uint8_t* dst) {
+ int j;
+ const __m128i values = _mm_set1_epi8(v);
+ for (j = 0; j < 8; ++j) {
+ _mm_storel_epi64((__m128i*)(dst + j * BPS), values);
+ }
+}
- VP8SimpleVFilter16 = SimpleVFilter16SSE2;
- VP8SimpleHFilter16 = SimpleHFilter16SSE2;
- VP8SimpleVFilter16i = SimpleVFilter16iSSE2;
- VP8SimpleHFilter16i = SimpleHFilter16iSSE2;
+static void DC8uv(uint8_t* dst) { // DC
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS));
+ const __m128i sum = _mm_sad_epu8(top, zero);
+ int left = 0;
+ int j;
+ for (j = 0; j < 8; ++j) {
+ left += dst[-1 + j * BPS];
+ }
+ {
+ const int DC = _mm_cvtsi128_si32(sum) + left + 8;
+ Put8x8uv(DC >> 4, dst);
+ }
}
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
+static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS));
+ const __m128i sum = _mm_sad_epu8(top, zero);
+ const int DC = _mm_cvtsi128_si32(sum) + 4;
+ Put8x8uv(DC >> 3, dst);
+}
+
+static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples
+ int dc0 = 4;
+ int i;
+ for (i = 0; i < 8; ++i) {
+ dc0 += dst[-1 + i * BPS];
+ }
+ Put8x8uv(dc0 >> 3, dst);
+}
+
+static void DC8uvNoTopLeft(uint8_t* dst) { // DC with nothing
+ Put8x8uv(0x80, dst);
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8DspInitSSE2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE2(void) {
+ VP8Transform = Transform;
+#if defined(USE_TRANSFORM_AC3)
+ VP8TransformAC3 = TransformAC3;
#endif
-#endif // WEBP_USE_SSE2
+ VP8VFilter16 = VFilter16;
+ VP8HFilter16 = HFilter16;
+ VP8VFilter8 = VFilter8;
+ VP8HFilter8 = HFilter8;
+ VP8VFilter16i = VFilter16i;
+ VP8HFilter16i = HFilter16i;
+ VP8VFilter8i = VFilter8i;
+ VP8HFilter8i = HFilter8i;
+
+ VP8SimpleVFilter16 = SimpleVFilter16;
+ VP8SimpleHFilter16 = SimpleHFilter16;
+ VP8SimpleVFilter16i = SimpleVFilter16i;
+ VP8SimpleHFilter16i = SimpleHFilter16i;
+
+ VP8PredLuma4[1] = TM4;
+ VP8PredLuma4[2] = VE4;
+ VP8PredLuma4[4] = RD4;
+ VP8PredLuma4[5] = VR4;
+ VP8PredLuma4[6] = LD4;
+ VP8PredLuma4[7] = VL4;
+
+ VP8PredLuma16[0] = DC16;
+ VP8PredLuma16[1] = TM16;
+ VP8PredLuma16[2] = VE16;
+ VP8PredLuma16[3] = HE16;
+ VP8PredLuma16[4] = DC16NoTop;
+ VP8PredLuma16[5] = DC16NoLeft;
+ VP8PredLuma16[6] = DC16NoTopLeft;
+
+ VP8PredChroma8[0] = DC8uv;
+ VP8PredChroma8[1] = TM8uv;
+ VP8PredChroma8[2] = VE8uv;
+ VP8PredChroma8[3] = HE8uv;
+ VP8PredChroma8[4] = DC8uvNoTop;
+ VP8PredChroma8[5] = DC8uvNoLeft;
+ VP8PredChroma8[6] = DC8uvNoTopLeft;
+}
+
+#else // !WEBP_USE_SSE2
+
+WEBP_DSP_INIT_STUB(VP8DspInitSSE2)
+
+#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/dec_sse41.c b/drivers/webp/dsp/dec_sse41.c
new file mode 100644
index 0000000000..dc1e70428d
--- /dev/null
+++ b/drivers/webp/dsp/dec_sse41.c
@@ -0,0 +1,45 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// SSE4 version of some decoding functions.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_SSE41)
+
+#include <smmintrin.h>
+#include "../dec/vp8i.h"
+
+static void HE16(uint8_t* dst) { // horizontal
+ int j;
+ const __m128i kShuffle3 = _mm_set1_epi8(3);
+ for (j = 16; j > 0; --j) {
+ const __m128i in = _mm_cvtsi32_si128(*(int*)(dst - 4));
+ const __m128i values = _mm_shuffle_epi8(in, kShuffle3);
+ _mm_storeu_si128((__m128i*)dst, values);
+ dst += BPS;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8DspInitSSE41(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE41(void) {
+ VP8PredLuma16[3] = HE16;
+}
+
+#else // !WEBP_USE_SSE41
+
+WEBP_DSP_INIT_STUB(VP8DspInitSSE41)
+
+#endif // WEBP_USE_SSE41
diff --git a/drivers/webp/dsp/dsp.h b/drivers/webp/dsp/dsp.h
index fd686a8532..4613d9c3ff 100644
--- a/drivers/webp/dsp/dsp.h
+++ b/drivers/webp/dsp/dsp.h
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Speed-critical functions.
@@ -12,44 +14,121 @@
#ifndef WEBP_DSP_DSP_H_
#define WEBP_DSP_DSP_H_
-#include "../types.h"
+#ifdef HAVE_CONFIG_H
+#include "webp/config.h"
+#endif
+
+#include "webp/types.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
+#define BPS 32 // this is the common stride for enc/dec
+
//------------------------------------------------------------------------------
// CPU detection
-#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
+#if defined(__GNUC__)
+# define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__)
+# define LOCAL_GCC_PREREQ(maj, min) \
+ (LOCAL_GCC_VERSION >= (((maj) << 8) | (min)))
+#else
+# define LOCAL_GCC_VERSION 0
+# define LOCAL_GCC_PREREQ(maj, min) 0
+#endif
+
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER > 1310 && \
+ (defined(_M_X64) || defined(_M_IX86))
#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets
#endif
-#if defined(__SSE2__) || defined(WEBP_MSC_SSE2)
+#if defined(_MSC_VER) && _MSC_VER >= 1500 && \
+ (defined(_M_X64) || defined(_M_IX86))
+#define WEBP_MSC_SSE41 // Visual C++ SSE4.1 targets
+#endif
+
+// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp
+// files without intrinsics, allowing the corresponding Init() to be called.
+// Files containing intrinsics will need to be built targeting the instruction
+// set so should succeed on one of the earlier tests.
+#if defined(__SSE2__) || defined(WEBP_MSC_SSE2) || defined(WEBP_HAVE_SSE2)
#define WEBP_USE_SSE2
#endif
-#if defined(__ANDROID__) && defined(__ARM_ARCH_7A__) && defined(__ARM_NEON__)
+#if defined(__SSE4_1__) || defined(WEBP_MSC_SSE41) || defined(WEBP_HAVE_SSE41)
+#define WEBP_USE_SSE41
+#endif
+
+#if defined(__AVX2__) || defined(WEBP_HAVE_AVX2)
+#define WEBP_USE_AVX2
+#endif
+
+#if defined(__ANDROID__) && defined(__ARM_ARCH_7A__)
#define WEBP_ANDROID_NEON // Android targets that might support NEON
#endif
-#if ( (defined(__ARM_NEON__) && !defined(__aarch64__)) || defined(WEBP_ANDROID_NEON)) && !defined(PSP2_ENABLED)
+// The intrinsics currently cause compiler errors with arm-nacl-gcc and the
+// inline assembly would need to be modified for use with Native Client.
+#if (defined(__ARM_NEON__) || defined(WEBP_ANDROID_NEON) || \
+ defined(__aarch64__)) && !defined(__native_client__)
+#define WEBP_USE_NEON
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
#define WEBP_USE_NEON
+#define WEBP_USE_INTRINSICS
+#endif
+
+#if defined(__mips__) && !defined(__mips64) && \
+ defined(__mips_isa_rev) && (__mips_isa_rev >= 1) && (__mips_isa_rev < 6)
+#define WEBP_USE_MIPS32
+#if (__mips_isa_rev >= 2)
+#define WEBP_USE_MIPS32_R2
+#if defined(__mips_dspr2) || (__mips_dsp_rev >= 2)
+#define WEBP_USE_MIPS_DSP_R2
+#endif
+#endif
+#endif
+
+// This macro prevents thread_sanitizer from reporting known concurrent writes.
+#define WEBP_TSAN_IGNORE_FUNCTION
+#if defined(__has_feature)
+#if __has_feature(thread_sanitizer)
+#undef WEBP_TSAN_IGNORE_FUNCTION
+#define WEBP_TSAN_IGNORE_FUNCTION __attribute__((no_sanitize_thread))
+#endif
#endif
typedef enum {
kSSE2,
kSSE3,
- kNEON
+ kSSE4_1,
+ kAVX,
+ kAVX2,
+ kNEON,
+ kMIPS32,
+ kMIPSdspR2
} CPUFeature;
// returns true if the CPU supports the feature.
typedef int (*VP8CPUInfo)(CPUFeature feature);
-extern VP8CPUInfo VP8GetCPUInfo;
+WEBP_EXTERN(VP8CPUInfo) VP8GetCPUInfo;
//------------------------------------------------------------------------------
-// Encoding
+// Init stub generator
-int VP8GetAlpha(const int histo[]);
+// Defines an init function stub to ensure each module exposes a symbol,
+// avoiding a compiler warning.
+#define WEBP_DSP_INIT_STUB(func) \
+ extern void func(void); \
+ WEBP_TSAN_IGNORE_FUNCTION void func(void) {}
+
+//------------------------------------------------------------------------------
+// Encoding
// Transforms
// VP8Idct: Does one of two inverse transforms. If do_two is set, the transforms
@@ -60,7 +139,7 @@ typedef void (*VP8Fdct)(const uint8_t* src, const uint8_t* ref, int16_t* out);
typedef void (*VP8WHT)(const int16_t* in, int16_t* out);
extern VP8Idct VP8ITransform;
extern VP8Fdct VP8FTransform;
-extern VP8WHT VP8ITransformWHT;
+extern VP8Fdct VP8FTransform2; // performs two transforms at a time
extern VP8WHT VP8FTransformWHT;
// Predictions
// *dst is the destination block. *top and *left can be NULL.
@@ -79,20 +158,63 @@ extern VP8WMetric VP8TDisto4x4, VP8TDisto16x16;
typedef void (*VP8BlockCopy)(const uint8_t* src, uint8_t* dst);
extern VP8BlockCopy VP8Copy4x4;
+extern VP8BlockCopy VP8Copy16x8;
// Quantization
struct VP8Matrix; // forward declaration
typedef int (*VP8QuantizeBlock)(int16_t in[16], int16_t out[16],
- int n, const struct VP8Matrix* const mtx);
+ const struct VP8Matrix* const mtx);
+// Same as VP8QuantizeBlock, but quantizes two consecutive blocks.
+typedef int (*VP8Quantize2Blocks)(int16_t in[32], int16_t out[32],
+ const struct VP8Matrix* const mtx);
+
extern VP8QuantizeBlock VP8EncQuantizeBlock;
+extern VP8Quantize2Blocks VP8EncQuantize2Blocks;
+
+// specific to 2nd transform:
+typedef int (*VP8QuantizeBlockWHT)(int16_t in[16], int16_t out[16],
+ const struct VP8Matrix* const mtx);
+extern VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT;
-// Compute susceptibility based on DCT-coeff histograms:
-// the higher, the "easier" the macroblock is to compress.
-typedef int (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred,
- int start_block, int end_block);
extern const int VP8DspScan[16 + 4 + 4];
+
+// Collect histogram for susceptibility calculation.
+#define MAX_COEFF_THRESH 31 // size of histogram used by CollectHistogram.
+typedef struct {
+ // We only need to store max_value and last_non_zero, not the distribution.
+ int max_value;
+ int last_non_zero;
+} VP8Histogram;
+typedef void (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred,
+ int start_block, int end_block,
+ VP8Histogram* const histo);
extern VP8CHisto VP8CollectHistogram;
+// General-purpose util function to help VP8CollectHistogram().
+void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1],
+ VP8Histogram* const histo);
+
+// must be called before using any of the above
+void VP8EncDspInit(void);
+
+//------------------------------------------------------------------------------
+// cost functions (encoding)
+
+extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p)
+// approximate cost per level:
+extern const uint16_t VP8LevelFixedCosts[2047 /*MAX_LEVEL*/ + 1];
+extern const uint8_t VP8EncBands[16 + 1];
+
+struct VP8Residual;
+typedef void (*VP8SetResidualCoeffsFunc)(const int16_t* const coeffs,
+ struct VP8Residual* const res);
+extern VP8SetResidualCoeffsFunc VP8SetResidualCoeffs;
-void VP8EncDspInit(void); // must be called before using any of the above
+// Cost calculation function.
+typedef int (*VP8GetResidualCostFunc)(int ctx0,
+ const struct VP8Residual* const res);
+extern VP8GetResidualCostFunc VP8GetResidualCost;
+
+// must be called before anything using the above
+void VP8EncDspCostInit(void);
//------------------------------------------------------------------------------
// Decoding
@@ -101,17 +223,26 @@ typedef void (*VP8DecIdct)(const int16_t* coeffs, uint8_t* dst);
// when doing two transforms, coeffs is actually int16_t[2][16].
typedef void (*VP8DecIdct2)(const int16_t* coeffs, uint8_t* dst, int do_two);
extern VP8DecIdct2 VP8Transform;
+extern VP8DecIdct VP8TransformAC3;
extern VP8DecIdct VP8TransformUV;
extern VP8DecIdct VP8TransformDC;
extern VP8DecIdct VP8TransformDCUV;
-extern void (*VP8TransformWHT)(const int16_t* in, int16_t* out);
+extern VP8WHT VP8TransformWHT;
// *dst is the destination block, with stride BPS. Boundary samples are
// assumed accessible when needed.
typedef void (*VP8PredFunc)(uint8_t* dst);
-extern const VP8PredFunc VP8PredLuma16[/* NUM_B_DC_MODES */];
-extern const VP8PredFunc VP8PredChroma8[/* NUM_B_DC_MODES */];
-extern const VP8PredFunc VP8PredLuma4[/* NUM_BMODES */];
+extern VP8PredFunc VP8PredLuma16[/* NUM_B_DC_MODES */];
+extern VP8PredFunc VP8PredChroma8[/* NUM_B_DC_MODES */];
+extern VP8PredFunc VP8PredLuma4[/* NUM_BMODES */];
+
+// clipping tables (for filtering)
+extern const int8_t* const VP8ksclip1; // clips [-1020, 1020] to [-128, 127]
+extern const int8_t* const VP8ksclip2; // clips [-112, 112] to [-16, 15]
+extern const uint8_t* const VP8kclip1; // clips [-255,511] to [0,255]
+extern const uint8_t* const VP8kabs0; // abs(x) for x in [-255,255]
+// must be called first
+void VP8InitClipTables(void);
// simple filter (only for luma)
typedef void (*VP8SimpleFilterFunc)(uint8_t* p, int stride, int thresh);
@@ -145,6 +276,8 @@ void VP8DspInit(void);
#define FANCY_UPSAMPLING // undefined to remove fancy upsampling support
+// Convert a pair of y/u/v lines together to the output rgb/a colorspace.
+// bottom_y can be NULL if only one line of output is needed (at top/bottom).
typedef void (*WebPUpsampleLinePairFunc)(
const uint8_t* top_y, const uint8_t* bottom_y,
const uint8_t* top_u, const uint8_t* top_v,
@@ -156,18 +289,20 @@ typedef void (*WebPUpsampleLinePairFunc)(
// Fancy upsampling functions to convert YUV to RGB(A) modes
extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
-// Initializes SSE2 version of the fancy upsamplers.
-void WebPInitUpsamplersSSE2(void);
-
#endif // FANCY_UPSAMPLING
-// Point-sampling methods.
-typedef void (*WebPSampleLinePairFunc)(
- const uint8_t* top_y, const uint8_t* bottom_y,
- const uint8_t* u, const uint8_t* v,
- uint8_t* top_dst, uint8_t* bottom_dst, int len);
+// Per-row point-sampling methods.
+typedef void (*WebPSamplerRowFunc)(const uint8_t* y,
+ const uint8_t* u, const uint8_t* v,
+ uint8_t* dst, int len);
+// Generic function to apply 'WebPSamplerRowFunc' to the whole plane:
+void WebPSamplerProcessPlane(const uint8_t* y, int y_stride,
+ const uint8_t* u, const uint8_t* v, int uv_stride,
+ uint8_t* dst, int dst_stride,
+ int width, int height, WebPSamplerRowFunc func);
-extern const WebPSampleLinePairFunc WebPSamplers[/* MODE_LAST */];
+// Sampling functions to convert rows of YUV to RGB(A)
+extern WebPSamplerRowFunc WebPSamplers[/* MODE_LAST */];
// General function for converting two lines of ARGB or RGBA.
// 'alpha_is_last' should be true if 0xff000000 is stored in memory as
@@ -179,13 +314,84 @@ typedef void (*WebPYUV444Converter)(const uint8_t* y,
const uint8_t* u, const uint8_t* v,
uint8_t* dst, int len);
-extern const WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */];
+extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */];
-// Main function to be called
+// Must be called before using the WebPUpsamplers[] (and for premultiplied
+// colorspaces like rgbA, rgbA4444, etc)
void WebPInitUpsamplers(void);
+// Must be called before using WebPSamplers[]
+void WebPInitSamplers(void);
+// Must be called before using WebPYUV444Converters[]
+void WebPInitYUV444Converters(void);
//------------------------------------------------------------------------------
-// Pre-multiply planes with alpha values
+// ARGB -> YUV converters
+
+// Convert ARGB samples to luma Y.
+extern void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width);
+// Convert ARGB samples to U/V with downsampling. do_store should be '1' for
+// even lines and '0' for odd ones. 'src_width' is the original width, not
+// the U/V one.
+extern void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v,
+ int src_width, int do_store);
+
+// Convert a row of accumulated (four-values) of rgba32 toward U/V
+extern void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb,
+ uint8_t* u, uint8_t* v, int width);
+
+// Convert RGB or BGR to Y
+extern void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width);
+extern void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width);
+
+// used for plain-C fallback.
+extern void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v,
+ int src_width, int do_store);
+extern void WebPConvertRGBA32ToUV_C(const uint16_t* rgb,
+ uint8_t* u, uint8_t* v, int width);
+
+// Must be called before using the above.
+void WebPInitConvertARGBToYUV(void);
+
+//------------------------------------------------------------------------------
+// Rescaler
+
+struct WebPRescaler;
+
+// Import a row of data and save its contribution in the rescaler.
+// 'channel' denotes the channel number to be imported. 'Expand' corresponds to
+// the wrk->x_expand case. Otherwise, 'Shrink' is to be used.
+typedef void (*WebPRescalerImportRowFunc)(struct WebPRescaler* const wrk,
+ const uint8_t* src);
+
+extern WebPRescalerImportRowFunc WebPRescalerImportRowExpand;
+extern WebPRescalerImportRowFunc WebPRescalerImportRowShrink;
+
+// Export one row (starting at x_out position) from rescaler.
+// 'Expand' corresponds to the wrk->y_expand case.
+// Otherwise 'Shrink' is to be used
+typedef void (*WebPRescalerExportRowFunc)(struct WebPRescaler* const wrk);
+extern WebPRescalerExportRowFunc WebPRescalerExportRowExpand;
+extern WebPRescalerExportRowFunc WebPRescalerExportRowShrink;
+
+// Plain-C implementation, as fall-back.
+extern void WebPRescalerImportRowExpandC(struct WebPRescaler* const wrk,
+ const uint8_t* src);
+extern void WebPRescalerImportRowShrinkC(struct WebPRescaler* const wrk,
+ const uint8_t* src);
+extern void WebPRescalerExportRowExpandC(struct WebPRescaler* const wrk);
+extern void WebPRescalerExportRowShrinkC(struct WebPRescaler* const wrk);
+
+// Main entry calls:
+extern void WebPRescalerImportRow(struct WebPRescaler* const wrk,
+ const uint8_t* src);
+// Export one row (starting at x_out position) from rescaler.
+extern void WebPRescalerExportRow(struct WebPRescaler* const wrk);
+
+// Must be called first before using the above.
+void WebPRescalerDspInit(void);
+
+//------------------------------------------------------------------------------
+// Utilities for processing transparent channel.
// Apply alpha pre-multiply on an rgba, bgra or argb plane of size w * h.
// alpha_first should be 0 for argb, 1 for rgba or bgra (where alpha is last).
@@ -196,14 +402,98 @@ extern void (*WebPApplyAlphaMultiply)(
extern void (*WebPApplyAlphaMultiply4444)(
uint8_t* rgba4444, int w, int h, int stride);
+// Dispatch the values from alpha[] plane to the ARGB destination 'dst'.
+// Returns true if alpha[] plane has non-trivial values different from 0xff.
+extern int (*WebPDispatchAlpha)(const uint8_t* alpha, int alpha_stride,
+ int width, int height,
+ uint8_t* dst, int dst_stride);
+
+// Transfer packed 8b alpha[] values to green channel in dst[], zero'ing the
+// A/R/B values. 'dst_stride' is the stride for dst[] in uint32_t units.
+extern void (*WebPDispatchAlphaToGreen)(const uint8_t* alpha, int alpha_stride,
+ int width, int height,
+ uint32_t* dst, int dst_stride);
+
+// Extract the alpha values from 32b values in argb[] and pack them into alpha[]
+// (this is the opposite of WebPDispatchAlpha).
+// Returns true if there's only trivial 0xff alpha values.
+extern int (*WebPExtractAlpha)(const uint8_t* argb, int argb_stride,
+ int width, int height,
+ uint8_t* alpha, int alpha_stride);
+
+// Pre-Multiply operation transforms x into x * A / 255 (where x=Y,R,G or B).
+// Un-Multiply operation transforms x into x * 255 / A.
+
+// Pre-Multiply or Un-Multiply (if 'inverse' is true) argb values in a row.
+extern void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse);
+
+// Same a WebPMultARGBRow(), but for several rows.
+void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows,
+ int inverse);
+
+// Same for a row of single values, with side alpha values.
+extern void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha,
+ int width, int inverse);
+
+// Same a WebPMultRow(), but for several 'num_rows' rows.
+void WebPMultRows(uint8_t* ptr, int stride,
+ const uint8_t* alpha, int alpha_stride,
+ int width, int num_rows, int inverse);
+
+// Plain-C versions, used as fallback by some implementations.
+void WebPMultRowC(uint8_t* const ptr, const uint8_t* const alpha,
+ int width, int inverse);
+void WebPMultARGBRowC(uint32_t* const ptr, int width, int inverse);
+
// To be called first before using the above.
-void WebPInitPremultiply(void);
+void WebPInitAlphaProcessing(void);
+
+// ARGB packing function: a/r/g/b input is rgba or bgra order.
+extern void (*VP8PackARGB)(const uint8_t* a, const uint8_t* r,
+ const uint8_t* g, const uint8_t* b, int len,
+ uint32_t* out);
+
+// RGB packing function. 'step' can be 3 or 4. r/g/b input is rgb or bgr order.
+extern void (*VP8PackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b,
+ int len, int step, uint32_t* out);
-void WebPInitPremultiplySSE2(void); // should not be called directly.
+// To be called first before using the above.
+void VP8EncDspARGBInit(void);
//------------------------------------------------------------------------------
+// Filter functions
+
+typedef enum { // Filter types.
+ WEBP_FILTER_NONE = 0,
+ WEBP_FILTER_HORIZONTAL,
+ WEBP_FILTER_VERTICAL,
+ WEBP_FILTER_GRADIENT,
+ WEBP_FILTER_LAST = WEBP_FILTER_GRADIENT + 1, // end marker
+ WEBP_FILTER_BEST, // meta-types
+ WEBP_FILTER_FAST
+} WEBP_FILTER_TYPE;
+
+typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height,
+ int stride, uint8_t* out);
+typedef void (*WebPUnfilterFunc)(int width, int height, int stride,
+ int row, int num_rows, uint8_t* data);
+
+// Filter the given data using the given predictor.
+// 'in' corresponds to a 2-dimensional pixel array of size (stride * height)
+// in raster order.
+// 'stride' is number of bytes per scan line (with possible padding).
+// 'out' should be pre-allocated.
+extern WebPFilterFunc WebPFilters[WEBP_FILTER_LAST];
+
+// In-place reconstruct the original data from the given filtered data.
+// The reconstruction will be done for 'num_rows' rows starting from 'row'
+// (assuming rows upto 'row - 1' are already reconstructed).
+extern WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST];
+
+// To be called first before using the above.
+void VP8FiltersInit(void);
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/dsp/enc.c b/drivers/webp/dsp/enc.c
index 02234564be..95e63f89ab 100644
--- a/drivers/webp/dsp/enc.c
+++ b/drivers/webp/dsp/enc.c
@@ -1,47 +1,34 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Speed-critical encoding functions.
//
// Author: Skal (pascal.massimino@gmail.com)
+#include <assert.h>
#include <stdlib.h> // for abs()
+
#include "./dsp.h"
#include "../enc/vp8enci.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+static WEBP_INLINE uint8_t clip_8b(int v) {
+ return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255;
+}
+
+static WEBP_INLINE int clip_max(int v, int max) {
+ return (v > max) ? max : v;
+}
//------------------------------------------------------------------------------
// Compute susceptibility based on DCT-coeff histograms:
// the higher, the "easier" the macroblock is to compress.
-static int ClipAlpha(int alpha) {
- return alpha < 0 ? 0 : alpha > 255 ? 255 : alpha;
-}
-
-int VP8GetAlpha(const int histo[MAX_COEFF_THRESH + 1]) {
- int num = 0, den = 0, val = 0;
- int k;
- int alpha;
- // note: changing this loop to avoid the numerous "k + 1" slows things down.
- for (k = 0; k < MAX_COEFF_THRESH; ++k) {
- if (histo[k + 1]) {
- val += histo[k + 1];
- num += val * (k + 1);
- den += (k + 1) * (k + 1);
- }
- }
- // we scale the value to a usable [0..255] range
- alpha = den ? 10 * num / den - 5 : 0;
- return ClipAlpha(alpha);
-}
-
const int VP8DspScan[16 + 4 + 4] = {
// Luma
0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS,
@@ -53,27 +40,41 @@ const int VP8DspScan[16 + 4 + 4] = {
8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V
};
-static int CollectHistogram(const uint8_t* ref, const uint8_t* pred,
- int start_block, int end_block) {
- int histo[MAX_COEFF_THRESH + 1] = { 0 };
- int16_t out[16];
- int j, k;
+// general-purpose util function
+void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1],
+ VP8Histogram* const histo) {
+ int max_value = 0, last_non_zero = 1;
+ int k;
+ for (k = 0; k <= MAX_COEFF_THRESH; ++k) {
+ const int value = distribution[k];
+ if (value > 0) {
+ if (value > max_value) max_value = value;
+ last_non_zero = k;
+ }
+ }
+ histo->max_value = max_value;
+ histo->last_non_zero = last_non_zero;
+}
+
+static void CollectHistogram(const uint8_t* ref, const uint8_t* pred,
+ int start_block, int end_block,
+ VP8Histogram* const histo) {
+ int j;
+ int distribution[MAX_COEFF_THRESH + 1] = { 0 };
for (j = start_block; j < end_block; ++j) {
- VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
+ int k;
+ int16_t out[16];
- // Convert coefficients to bin (within out[]).
- for (k = 0; k < 16; ++k) {
- const int v = abs(out[k]) >> 2;
- out[k] = (v > MAX_COEFF_THRESH) ? MAX_COEFF_THRESH : v;
- }
+ VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
- // Use bin to update histogram.
+ // Convert coefficients to bin.
for (k = 0; k < 16; ++k) {
- histo[out[k]]++;
+ const int v = abs(out[k]) >> 3; // TODO(skal): add rounding?
+ const int clipped_value = clip_max(v, MAX_COEFF_THRESH);
+ ++distribution[clipped_value];
}
}
-
- return VP8GetAlpha(histo);
+ VP8SetHistogramData(distribution, histo);
}
//------------------------------------------------------------------------------
@@ -85,19 +86,16 @@ static uint8_t clip1[255 + 510 + 1]; // clips [-255,510] to [0,255]
// and make sure it's set to true _last_ (so as to be thread-safe)
static volatile int tables_ok = 0;
-static void InitTables(void) {
+static WEBP_TSAN_IGNORE_FUNCTION void InitTables(void) {
if (!tables_ok) {
int i;
for (i = -255; i <= 255 + 255; ++i) {
- clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i;
+ clip1[255 + i] = clip_8b(i);
}
tables_ok = 1;
}
}
-static WEBP_INLINE uint8_t clip_8b(int v) {
- return (!(v & ~0xff)) ? v : v < 0 ? 0 : 255;
-}
//------------------------------------------------------------------------------
// Transforms (Paragraph 14.4)
@@ -154,84 +152,63 @@ static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) {
int i;
int tmp[16];
for (i = 0; i < 4; ++i, src += BPS, ref += BPS) {
- const int d0 = src[0] - ref[0];
+ const int d0 = src[0] - ref[0]; // 9bit dynamic range ([-255,255])
const int d1 = src[1] - ref[1];
const int d2 = src[2] - ref[2];
const int d3 = src[3] - ref[3];
- const int a0 = (d0 + d3) << 3;
- const int a1 = (d1 + d2) << 3;
- const int a2 = (d1 - d2) << 3;
- const int a3 = (d0 - d3) << 3;
- tmp[0 + i * 4] = (a0 + a1);
- tmp[1 + i * 4] = (a2 * 2217 + a3 * 5352 + 14500) >> 12;
- tmp[2 + i * 4] = (a0 - a1);
- tmp[3 + i * 4] = (a3 * 2217 - a2 * 5352 + 7500) >> 12;
+ const int a0 = (d0 + d3); // 10b [-510,510]
+ const int a1 = (d1 + d2);
+ const int a2 = (d1 - d2);
+ const int a3 = (d0 - d3);
+ tmp[0 + i * 4] = (a0 + a1) * 8; // 14b [-8160,8160]
+ tmp[1 + i * 4] = (a2 * 2217 + a3 * 5352 + 1812) >> 9; // [-7536,7542]
+ tmp[2 + i * 4] = (a0 - a1) * 8;
+ tmp[3 + i * 4] = (a3 * 2217 - a2 * 5352 + 937) >> 9;
}
for (i = 0; i < 4; ++i) {
- const int a0 = (tmp[0 + i] + tmp[12 + i]);
+ const int a0 = (tmp[0 + i] + tmp[12 + i]); // 15b
const int a1 = (tmp[4 + i] + tmp[ 8 + i]);
const int a2 = (tmp[4 + i] - tmp[ 8 + i]);
const int a3 = (tmp[0 + i] - tmp[12 + i]);
- out[0 + i] = (a0 + a1 + 7) >> 4;
+ out[0 + i] = (a0 + a1 + 7) >> 4; // 12b
out[4 + i] = ((a2 * 2217 + a3 * 5352 + 12000) >> 16) + (a3 != 0);
out[8 + i] = (a0 - a1 + 7) >> 4;
out[12+ i] = ((a3 * 2217 - a2 * 5352 + 51000) >> 16);
}
}
-static void ITransformWHT(const int16_t* in, int16_t* out) {
- int tmp[16];
- int i;
- for (i = 0; i < 4; ++i) {
- const int a0 = in[0 + i] + in[12 + i];
- const int a1 = in[4 + i] + in[ 8 + i];
- const int a2 = in[4 + i] - in[ 8 + i];
- const int a3 = in[0 + i] - in[12 + i];
- tmp[0 + i] = a0 + a1;
- tmp[8 + i] = a0 - a1;
- tmp[4 + i] = a3 + a2;
- tmp[12 + i] = a3 - a2;
- }
- for (i = 0; i < 4; ++i) {
- const int dc = tmp[0 + i * 4] + 3; // w/ rounder
- const int a0 = dc + tmp[3 + i * 4];
- const int a1 = tmp[1 + i * 4] + tmp[2 + i * 4];
- const int a2 = tmp[1 + i * 4] - tmp[2 + i * 4];
- const int a3 = dc - tmp[3 + i * 4];
- out[ 0] = (a0 + a1) >> 3;
- out[16] = (a3 + a2) >> 3;
- out[32] = (a0 - a1) >> 3;
- out[48] = (a3 - a2) >> 3;
- out += 64;
- }
+static void FTransform2(const uint8_t* src, const uint8_t* ref, int16_t* out) {
+ VP8FTransform(src, ref, out);
+ VP8FTransform(src + 4, ref + 4, out + 16);
}
static void FTransformWHT(const int16_t* in, int16_t* out) {
- int tmp[16];
+ // input is 12b signed
+ int32_t tmp[16];
int i;
for (i = 0; i < 4; ++i, in += 64) {
- const int a0 = (in[0 * 16] + in[2 * 16]) << 2;
- const int a1 = (in[1 * 16] + in[3 * 16]) << 2;
- const int a2 = (in[1 * 16] - in[3 * 16]) << 2;
- const int a3 = (in[0 * 16] - in[2 * 16]) << 2;
- tmp[0 + i * 4] = (a0 + a1) + (a0 != 0);
+ const int a0 = (in[0 * 16] + in[2 * 16]); // 13b
+ const int a1 = (in[1 * 16] + in[3 * 16]);
+ const int a2 = (in[1 * 16] - in[3 * 16]);
+ const int a3 = (in[0 * 16] - in[2 * 16]);
+ tmp[0 + i * 4] = a0 + a1; // 14b
tmp[1 + i * 4] = a3 + a2;
tmp[2 + i * 4] = a3 - a2;
tmp[3 + i * 4] = a0 - a1;
}
for (i = 0; i < 4; ++i) {
- const int a0 = (tmp[0 + i] + tmp[8 + i]);
+ const int a0 = (tmp[0 + i] + tmp[8 + i]); // 15b
const int a1 = (tmp[4 + i] + tmp[12+ i]);
const int a2 = (tmp[4 + i] - tmp[12+ i]);
const int a3 = (tmp[0 + i] - tmp[8 + i]);
- const int b0 = a0 + a1;
+ const int b0 = a0 + a1; // 16b
const int b1 = a3 + a2;
const int b2 = a3 - a2;
const int b3 = a0 - a1;
- out[ 0 + i] = (b0 + (b0 > 0) + 3) >> 3;
- out[ 4 + i] = (b1 + (b1 > 0) + 3) >> 3;
- out[ 8 + i] = (b2 + (b2 > 0) + 3) >> 3;
- out[12 + i] = (b3 + (b3 > 0) + 3) >> 3;
+ out[ 0 + i] = b0 >> 1; // 15b
+ out[ 4 + i] = b1 >> 1;
+ out[ 8 + i] = b2 >> 1;
+ out[12 + i] = b3 >> 1;
}
}
@@ -241,8 +218,6 @@ static void FTransformWHT(const int16_t* in, int16_t* out) {
//------------------------------------------------------------------------------
// Intra predictions
-#define DST(x, y) dst[(x) + (y) * BPS]
-
static WEBP_INLINE void Fill(uint8_t* dst, int value, int size) {
int j;
for (j = 0; j < size; ++j) {
@@ -253,7 +228,7 @@ static WEBP_INLINE void Fill(uint8_t* dst, int value, int size) {
static WEBP_INLINE void VerticalPred(uint8_t* dst,
const uint8_t* top, int size) {
int j;
- if (top) {
+ if (top != NULL) {
for (j = 0; j < size; ++j) memcpy(dst + j * BPS, top, size);
} else {
Fill(dst, 127, size);
@@ -262,7 +237,7 @@ static WEBP_INLINE void VerticalPred(uint8_t* dst,
static WEBP_INLINE void HorizontalPred(uint8_t* dst,
const uint8_t* left, int size) {
- if (left) {
+ if (left != NULL) {
int j;
for (j = 0; j < size; ++j) {
memset(dst + j * BPS, left[j], size);
@@ -275,8 +250,8 @@ static WEBP_INLINE void HorizontalPred(uint8_t* dst,
static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left,
const uint8_t* top, int size) {
int y;
- if (left) {
- if (top) {
+ if (left != NULL) {
+ if (top != NULL) {
const uint8_t* const clip = clip1 + 255 - left[-1];
for (y = 0; y < size; ++y) {
const uint8_t* const clip_table = clip + left[y];
@@ -294,7 +269,7 @@ static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left,
// is equivalent to VE prediction where you just copy the top samples.
// Note that if top samples are not available, the default value is
// then 129, and not 127 as in the VerticalPred case.
- if (top) {
+ if (top != NULL) {
VerticalPred(dst, top, size);
} else {
Fill(dst, 129, size);
@@ -307,15 +282,15 @@ static WEBP_INLINE void DCMode(uint8_t* dst, const uint8_t* left,
int size, int round, int shift) {
int DC = 0;
int j;
- if (top) {
+ if (top != NULL) {
for (j = 0; j < size; ++j) DC += top[j];
- if (left) { // top and left present
+ if (left != NULL) { // top and left present
for (j = 0; j < size; ++j) DC += left[j];
} else { // top, but no left
DC += DC;
}
DC = (DC + round) >> shift;
- } else if (left) { // left but no top
+ } else if (left != NULL) { // left but no top
for (j = 0; j < size; ++j) DC += left[j];
DC += DC;
DC = (DC + round) >> shift;
@@ -337,8 +312,8 @@ static void IntraChromaPreds(uint8_t* dst, const uint8_t* left,
TrueMotion(C8TM8 + dst, left, top, 8);
// V block
dst += 8;
- if (top) top += 8;
- if (left) left += 16;
+ if (top != NULL) top += 8;
+ if (left != NULL) left += 16;
DCMode(C8DC8 + dst, left, top, 8, 8, 4);
VerticalPred(C8VE8 + dst, top, 8);
HorizontalPred(C8HE8 + dst, left, 8);
@@ -359,6 +334,7 @@ static void Intra16Preds(uint8_t* dst,
//------------------------------------------------------------------------------
// luma 4x4 prediction
+#define DST(x, y) dst[(x) + (y) * BPS]
#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2)
#define AVG2(a, b) (((a) + (b) + 1) >> 1)
@@ -589,30 +565,30 @@ static int TTransform(const uint8_t* in, const uint16_t* w) {
int i;
// horizontal pass
for (i = 0; i < 4; ++i, in += BPS) {
- const int a0 = (in[0] + in[2]) << 2;
- const int a1 = (in[1] + in[3]) << 2;
- const int a2 = (in[1] - in[3]) << 2;
- const int a3 = (in[0] - in[2]) << 2;
- tmp[0 + i * 4] = a0 + a1 + (a0 != 0);
+ const int a0 = in[0] + in[2];
+ const int a1 = in[1] + in[3];
+ const int a2 = in[1] - in[3];
+ const int a3 = in[0] - in[2];
+ tmp[0 + i * 4] = a0 + a1;
tmp[1 + i * 4] = a3 + a2;
tmp[2 + i * 4] = a3 - a2;
tmp[3 + i * 4] = a0 - a1;
}
// vertical pass
for (i = 0; i < 4; ++i, ++w) {
- const int a0 = (tmp[0 + i] + tmp[8 + i]);
- const int a1 = (tmp[4 + i] + tmp[12+ i]);
- const int a2 = (tmp[4 + i] - tmp[12+ i]);
- const int a3 = (tmp[0 + i] - tmp[8 + i]);
+ const int a0 = tmp[0 + i] + tmp[8 + i];
+ const int a1 = tmp[4 + i] + tmp[12+ i];
+ const int a2 = tmp[4 + i] - tmp[12+ i];
+ const int a3 = tmp[0 + i] - tmp[8 + i];
const int b0 = a0 + a1;
const int b1 = a3 + a2;
const int b2 = a3 - a2;
const int b3 = a0 - a1;
- // abs((b + (b<0) + 3) >> 3) = (abs(b) + 3) >> 3
- sum += w[ 0] * ((abs(b0) + 3) >> 3);
- sum += w[ 4] * ((abs(b1) + 3) >> 3);
- sum += w[ 8] * ((abs(b2) + 3) >> 3);
- sum += w[12] * ((abs(b3) + 3) >> 3);
+
+ sum += w[ 0] * abs(b0);
+ sum += w[ 4] * abs(b1);
+ sum += w[ 8] * abs(b2);
+ sum += w[12] * abs(b3);
}
return sum;
}
@@ -621,7 +597,7 @@ static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
const uint16_t* const w) {
const int sum1 = TTransform(a, w);
const int sum2 = TTransform(b, w);
- return (abs(sum2 - sum1) + 8) >> 4;
+ return abs(sum2 - sum1) >> 5;
}
static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
@@ -646,21 +622,57 @@ static const uint8_t kZigzag[16] = {
// Simple quantization
static int QuantizeBlock(int16_t in[16], int16_t out[16],
- int n, const VP8Matrix* const mtx) {
+ const VP8Matrix* const mtx) {
int last = -1;
- for (; n < 16; ++n) {
+ int n;
+ for (n = 0; n < 16; ++n) {
+ const int j = kZigzag[n];
+ const int sign = (in[j] < 0);
+ const uint32_t coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
+ if (coeff > mtx->zthresh_[j]) {
+ const uint32_t Q = mtx->q_[j];
+ const uint32_t iQ = mtx->iq_[j];
+ const uint32_t B = mtx->bias_[j];
+ int level = QUANTDIV(coeff, iQ, B);
+ if (level > MAX_LEVEL) level = MAX_LEVEL;
+ if (sign) level = -level;
+ in[j] = level * Q;
+ out[n] = level;
+ if (level) last = n;
+ } else {
+ out[n] = 0;
+ in[j] = 0;
+ }
+ }
+ return (last >= 0);
+}
+
+static int Quantize2Blocks(int16_t in[32], int16_t out[32],
+ const VP8Matrix* const mtx) {
+ int nz;
+ nz = VP8EncQuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0;
+ nz |= VP8EncQuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1;
+ return nz;
+}
+
+static int QuantizeBlockWHT(int16_t in[16], int16_t out[16],
+ const VP8Matrix* const mtx) {
+ int n, last = -1;
+ for (n = 0; n < 16; ++n) {
const int j = kZigzag[n];
const int sign = (in[j] < 0);
- int coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
- if (coeff > 2047) coeff = 2047;
+ const uint32_t coeff = sign ? -in[j] : in[j];
+ assert(mtx->sharpen_[j] == 0);
if (coeff > mtx->zthresh_[j]) {
- const int Q = mtx->q_[j];
- const int iQ = mtx->iq_[j];
- const int B = mtx->bias_[j];
- out[n] = QUANTDIV(coeff, iQ, B);
- if (sign) out[n] = -out[n];
- in[j] = out[n] * Q;
- if (out[n]) last = n;
+ const uint32_t Q = mtx->q_[j];
+ const uint32_t iQ = mtx->iq_[j];
+ const uint32_t B = mtx->bias_[j];
+ int level = QUANTDIV(coeff, iQ, B);
+ if (level > MAX_LEVEL) level = MAX_LEVEL;
+ if (sign) level = -level;
+ in[j] = level * Q;
+ out[n] = level;
+ if (level) last = n;
} else {
out[n] = 0;
in[j] = 0;
@@ -672,16 +684,22 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16],
//------------------------------------------------------------------------------
// Block copy
-static WEBP_INLINE void Copy(const uint8_t* src, uint8_t* dst, int size) {
+static WEBP_INLINE void Copy(const uint8_t* src, uint8_t* dst, int w, int h) {
int y;
- for (y = 0; y < size; ++y) {
- memcpy(dst, src, size);
+ for (y = 0; y < h; ++y) {
+ memcpy(dst, src, w);
src += BPS;
dst += BPS;
}
}
-static void Copy4x4(const uint8_t* src, uint8_t* dst) { Copy(src, dst, 4); }
+static void Copy4x4(const uint8_t* src, uint8_t* dst) {
+ Copy(src, dst, 4, 4);
+}
+
+static void Copy16x8(const uint8_t* src, uint8_t* dst) {
+ Copy(src, dst, 16, 8);
+}
//------------------------------------------------------------------------------
// Initialization
@@ -691,7 +709,7 @@ static void Copy4x4(const uint8_t* src, uint8_t* dst) { Copy(src, dst, 4); }
VP8CHisto VP8CollectHistogram;
VP8Idct VP8ITransform;
VP8Fdct VP8FTransform;
-VP8WHT VP8ITransformWHT;
+VP8Fdct VP8FTransform2;
VP8WHT VP8FTransformWHT;
VP8Intra4Preds VP8EncPredLuma4;
VP8IntraPreds VP8EncPredLuma16;
@@ -703,18 +721,32 @@ VP8Metric VP8SSE4x4;
VP8WMetric VP8TDisto4x4;
VP8WMetric VP8TDisto16x16;
VP8QuantizeBlock VP8EncQuantizeBlock;
+VP8Quantize2Blocks VP8EncQuantize2Blocks;
+VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT;
VP8BlockCopy VP8Copy4x4;
+VP8BlockCopy VP8Copy16x8;
extern void VP8EncDspInitSSE2(void);
+extern void VP8EncDspInitSSE41(void);
+extern void VP8EncDspInitAVX2(void);
+extern void VP8EncDspInitNEON(void);
+extern void VP8EncDspInitMIPS32(void);
+extern void VP8EncDspInitMIPSdspR2(void);
+
+static volatile VP8CPUInfo enc_last_cpuinfo_used =
+ (VP8CPUInfo)&enc_last_cpuinfo_used;
-void VP8EncDspInit(void) {
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) {
+ if (enc_last_cpuinfo_used == VP8GetCPUInfo) return;
+
+ VP8DspInit(); // common inverse transforms
InitTables();
// default C implementations
VP8CollectHistogram = CollectHistogram;
VP8ITransform = ITransform;
VP8FTransform = FTransform;
- VP8ITransformWHT = ITransformWHT;
+ VP8FTransform2 = FTransform2;
VP8FTransformWHT = FTransformWHT;
VP8EncPredLuma4 = Intra4Preds;
VP8EncPredLuma16 = Intra16Preds;
@@ -726,18 +758,43 @@ void VP8EncDspInit(void) {
VP8TDisto4x4 = Disto4x4;
VP8TDisto16x16 = Disto16x16;
VP8EncQuantizeBlock = QuantizeBlock;
+ VP8EncQuantize2Blocks = Quantize2Blocks;
+ VP8EncQuantizeBlockWHT = QuantizeBlockWHT;
VP8Copy4x4 = Copy4x4;
+ VP8Copy16x8 = Copy16x8;
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
- if (VP8GetCPUInfo) {
+ if (VP8GetCPUInfo != NULL) {
#if defined(WEBP_USE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
VP8EncDspInitSSE2();
+#if defined(WEBP_USE_SSE41)
+ if (VP8GetCPUInfo(kSSE4_1)) {
+ VP8EncDspInitSSE41();
+ }
+#endif
+ }
+#endif
+#if defined(WEBP_USE_AVX2)
+ if (VP8GetCPUInfo(kAVX2)) {
+ VP8EncDspInitAVX2();
+ }
+#endif
+#if defined(WEBP_USE_NEON)
+ if (VP8GetCPUInfo(kNEON)) {
+ VP8EncDspInitNEON();
+ }
+#endif
+#if defined(WEBP_USE_MIPS32)
+ if (VP8GetCPUInfo(kMIPS32)) {
+ VP8EncDspInitMIPS32();
+ }
+#endif
+#if defined(WEBP_USE_MIPS_DSP_R2)
+ if (VP8GetCPUInfo(kMIPSdspR2)) {
+ VP8EncDspInitMIPSdspR2();
}
#endif
}
+ enc_last_cpuinfo_used = VP8GetCPUInfo;
}
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/dsp/enc_avx2.c b/drivers/webp/dsp/enc_avx2.c
new file mode 100644
index 0000000000..93efb30b10
--- /dev/null
+++ b/drivers/webp/dsp/enc_avx2.c
@@ -0,0 +1,21 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// AVX2 version of speed-critical encoding functions.
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_AVX2)
+
+#endif // WEBP_USE_AVX2
+
+//------------------------------------------------------------------------------
+// Entry point
+
+WEBP_DSP_INIT_STUB(VP8EncDspInitAVX2)
diff --git a/drivers/webp/dsp/enc_mips32.c b/drivers/webp/dsp/enc_mips32.c
new file mode 100644
index 0000000000..fd10143de9
--- /dev/null
+++ b/drivers/webp/dsp/enc_mips32.c
@@ -0,0 +1,672 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// MIPS version of speed-critical encoding functions.
+//
+// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
+// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
+// Slobodan Prijic (slobodan.prijic@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS32)
+
+#include "./mips_macro.h"
+#include "../enc/vp8enci.h"
+#include "../enc/cost.h"
+
+static const int kC1 = 20091 + (1 << 16);
+static const int kC2 = 35468;
+
+// macro for one vertical pass in ITransformOne
+// MUL macro inlined
+// temp0..temp15 holds tmp[0]..tmp[15]
+// A..D - offsets in bytes to load from in buffer
+// TEMP0..TEMP3 - registers for corresponding tmp elements
+// TEMP4..TEMP5 - temporary registers
+#define VERTICAL_PASS(A, B, C, D, TEMP4, TEMP0, TEMP1, TEMP2, TEMP3) \
+ "lh %[temp16], " #A "(%[temp20]) \n\t" \
+ "lh %[temp18], " #B "(%[temp20]) \n\t" \
+ "lh %[temp17], " #C "(%[temp20]) \n\t" \
+ "lh %[temp19], " #D "(%[temp20]) \n\t" \
+ "addu %[" #TEMP4 "], %[temp16], %[temp18] \n\t" \
+ "subu %[temp16], %[temp16], %[temp18] \n\t" \
+ "mul %[" #TEMP0 "], %[temp17], %[kC2] \n\t" \
+ "mul %[temp18], %[temp19], %[kC1] \n\t" \
+ "mul %[temp17], %[temp17], %[kC1] \n\t" \
+ "mul %[temp19], %[temp19], %[kC2] \n\t" \
+ "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\n" \
+ "sra %[temp18], %[temp18], 16 \n\n" \
+ "sra %[temp17], %[temp17], 16 \n\n" \
+ "sra %[temp19], %[temp19], 16 \n\n" \
+ "subu %[" #TEMP2 "], %[" #TEMP0 "], %[temp18] \n\t" \
+ "addu %[" #TEMP3 "], %[temp17], %[temp19] \n\t" \
+ "addu %[" #TEMP0 "], %[" #TEMP4 "], %[" #TEMP3 "] \n\t" \
+ "addu %[" #TEMP1 "], %[temp16], %[" #TEMP2 "] \n\t" \
+ "subu %[" #TEMP2 "], %[temp16], %[" #TEMP2 "] \n\t" \
+ "subu %[" #TEMP3 "], %[" #TEMP4 "], %[" #TEMP3 "] \n\t"
+
+// macro for one horizontal pass in ITransformOne
+// MUL and STORE macros inlined
+// a = clip_8b(a) is replaced with: a = max(a, 0); a = min(a, 255)
+// temp0..temp15 holds tmp[0]..tmp[15]
+// A - offset in bytes to load from ref and store to dst buffer
+// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements
+#define HORIZONTAL_PASS(A, TEMP0, TEMP4, TEMP8, TEMP12) \
+ "addiu %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \
+ "addu %[temp16], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \
+ "subu %[temp17], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \
+ "mul %[" #TEMP0 "], %[" #TEMP4 "], %[kC2] \n\t" \
+ "mul %[" #TEMP8 "], %[" #TEMP12 "], %[kC1] \n\t" \
+ "mul %[" #TEMP4 "], %[" #TEMP4 "], %[kC1] \n\t" \
+ "mul %[" #TEMP12 "], %[" #TEMP12 "], %[kC2] \n\t" \
+ "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\t" \
+ "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \
+ "sra %[" #TEMP4 "], %[" #TEMP4 "], 16 \n\t" \
+ "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \
+ "subu %[temp18], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \
+ "addu %[temp19], %[" #TEMP4 "], %[" #TEMP12 "] \n\t" \
+ "addu %[" #TEMP0 "], %[temp16], %[temp19] \n\t" \
+ "addu %[" #TEMP4 "], %[temp17], %[temp18] \n\t" \
+ "subu %[" #TEMP8 "], %[temp17], %[temp18] \n\t" \
+ "subu %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \
+ "lw %[temp20], 0(%[args]) \n\t" \
+ "sra %[" #TEMP0 "], %[" #TEMP0 "], 3 \n\t" \
+ "sra %[" #TEMP4 "], %[" #TEMP4 "], 3 \n\t" \
+ "sra %[" #TEMP8 "], %[" #TEMP8 "], 3 \n\t" \
+ "sra %[" #TEMP12 "], %[" #TEMP12 "], 3 \n\t" \
+ "lbu %[temp16], 0+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \
+ "lbu %[temp17], 1+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \
+ "lbu %[temp18], 2+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \
+ "lbu %[temp19], 3+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \
+ "addu %[" #TEMP0 "], %[temp16], %[" #TEMP0 "] \n\t" \
+ "addu %[" #TEMP4 "], %[temp17], %[" #TEMP4 "] \n\t" \
+ "addu %[" #TEMP8 "], %[temp18], %[" #TEMP8 "] \n\t" \
+ "addu %[" #TEMP12 "], %[temp19], %[" #TEMP12 "] \n\t" \
+ "slt %[temp16], %[" #TEMP0 "], $zero \n\t" \
+ "slt %[temp17], %[" #TEMP4 "], $zero \n\t" \
+ "slt %[temp18], %[" #TEMP8 "], $zero \n\t" \
+ "slt %[temp19], %[" #TEMP12 "], $zero \n\t" \
+ "movn %[" #TEMP0 "], $zero, %[temp16] \n\t" \
+ "movn %[" #TEMP4 "], $zero, %[temp17] \n\t" \
+ "movn %[" #TEMP8 "], $zero, %[temp18] \n\t" \
+ "movn %[" #TEMP12 "], $zero, %[temp19] \n\t" \
+ "addiu %[temp20], $zero, 255 \n\t" \
+ "slt %[temp16], %[" #TEMP0 "], %[temp20] \n\t" \
+ "slt %[temp17], %[" #TEMP4 "], %[temp20] \n\t" \
+ "slt %[temp18], %[" #TEMP8 "], %[temp20] \n\t" \
+ "slt %[temp19], %[" #TEMP12 "], %[temp20] \n\t" \
+ "movz %[" #TEMP0 "], %[temp20], %[temp16] \n\t" \
+ "movz %[" #TEMP4 "], %[temp20], %[temp17] \n\t" \
+ "lw %[temp16], 8(%[args]) \n\t" \
+ "movz %[" #TEMP8 "], %[temp20], %[temp18] \n\t" \
+ "movz %[" #TEMP12 "], %[temp20], %[temp19] \n\t" \
+ "sb %[" #TEMP0 "], 0+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \
+ "sb %[" #TEMP4 "], 1+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \
+ "sb %[" #TEMP8 "], 2+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \
+ "sb %[" #TEMP12 "], 3+" XSTR(BPS) "*" #A "(%[temp16]) \n\t"
+
+// Does one or two inverse transforms.
+static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in,
+ uint8_t* dst) {
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6;
+ int temp7, temp8, temp9, temp10, temp11, temp12, temp13;
+ int temp14, temp15, temp16, temp17, temp18, temp19, temp20;
+ const int* args[3] = {(const int*)ref, (const int*)in, (const int*)dst};
+
+ __asm__ volatile(
+ "lw %[temp20], 4(%[args]) \n\t"
+ VERTICAL_PASS(0, 16, 8, 24, temp4, temp0, temp1, temp2, temp3)
+ VERTICAL_PASS(2, 18, 10, 26, temp8, temp4, temp5, temp6, temp7)
+ VERTICAL_PASS(4, 20, 12, 28, temp12, temp8, temp9, temp10, temp11)
+ VERTICAL_PASS(6, 22, 14, 30, temp20, temp12, temp13, temp14, temp15)
+
+ HORIZONTAL_PASS(0, temp0, temp4, temp8, temp12)
+ HORIZONTAL_PASS(1, temp1, temp5, temp9, temp13)
+ HORIZONTAL_PASS(2, temp2, temp6, temp10, temp14)
+ HORIZONTAL_PASS(3, temp3, temp7, temp11, temp15)
+
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
+ [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11),
+ [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14),
+ [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17),
+ [temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20)
+ : [args]"r"(args), [kC1]"r"(kC1), [kC2]"r"(kC2)
+ : "memory", "hi", "lo"
+ );
+}
+
+static void ITransform(const uint8_t* ref, const int16_t* in,
+ uint8_t* dst, int do_two) {
+ ITransformOne(ref, in, dst);
+ if (do_two) {
+ ITransformOne(ref + 4, in + 16, dst + 4);
+ }
+}
+
+#undef VERTICAL_PASS
+#undef HORIZONTAL_PASS
+
+// macro for one pass through for loop in QuantizeBlock
+// QUANTDIV macro inlined
+// J - offset in bytes (kZigzag[n] * 2)
+// K - offset in bytes (kZigzag[n] * 4)
+// N - offset in bytes (n * 2)
+#define QUANTIZE_ONE(J, K, N) \
+ "lh %[temp0], " #J "(%[ppin]) \n\t" \
+ "lhu %[temp1], " #J "(%[ppsharpen]) \n\t" \
+ "lw %[temp2], " #K "(%[ppzthresh]) \n\t" \
+ "sra %[sign], %[temp0], 15 \n\t" \
+ "xor %[coeff], %[temp0], %[sign] \n\t" \
+ "subu %[coeff], %[coeff], %[sign] \n\t" \
+ "addu %[coeff], %[coeff], %[temp1] \n\t" \
+ "slt %[temp4], %[temp2], %[coeff] \n\t" \
+ "addiu %[temp5], $zero, 0 \n\t" \
+ "addiu %[level], $zero, 0 \n\t" \
+ "beqz %[temp4], 2f \n\t" \
+ "lhu %[temp1], " #J "(%[ppiq]) \n\t" \
+ "lw %[temp2], " #K "(%[ppbias]) \n\t" \
+ "lhu %[temp3], " #J "(%[ppq]) \n\t" \
+ "mul %[level], %[coeff], %[temp1] \n\t" \
+ "addu %[level], %[level], %[temp2] \n\t" \
+ "sra %[level], %[level], 17 \n\t" \
+ "slt %[temp4], %[max_level], %[level] \n\t" \
+ "movn %[level], %[max_level], %[temp4] \n\t" \
+ "xor %[level], %[level], %[sign] \n\t" \
+ "subu %[level], %[level], %[sign] \n\t" \
+ "mul %[temp5], %[level], %[temp3] \n\t" \
+"2: \n\t" \
+ "sh %[temp5], " #J "(%[ppin]) \n\t" \
+ "sh %[level], " #N "(%[pout]) \n\t"
+
+static int QuantizeBlock(int16_t in[16], int16_t out[16],
+ const VP8Matrix* const mtx) {
+ int temp0, temp1, temp2, temp3, temp4, temp5;
+ int sign, coeff, level, i;
+ int max_level = MAX_LEVEL;
+
+ int16_t* ppin = &in[0];
+ int16_t* pout = &out[0];
+ const uint16_t* ppsharpen = &mtx->sharpen_[0];
+ const uint32_t* ppzthresh = &mtx->zthresh_[0];
+ const uint16_t* ppq = &mtx->q_[0];
+ const uint16_t* ppiq = &mtx->iq_[0];
+ const uint32_t* ppbias = &mtx->bias_[0];
+
+ __asm__ volatile(
+ QUANTIZE_ONE( 0, 0, 0)
+ QUANTIZE_ONE( 2, 4, 2)
+ QUANTIZE_ONE( 8, 16, 4)
+ QUANTIZE_ONE(16, 32, 6)
+ QUANTIZE_ONE(10, 20, 8)
+ QUANTIZE_ONE( 4, 8, 10)
+ QUANTIZE_ONE( 6, 12, 12)
+ QUANTIZE_ONE(12, 24, 14)
+ QUANTIZE_ONE(18, 36, 16)
+ QUANTIZE_ONE(24, 48, 18)
+ QUANTIZE_ONE(26, 52, 20)
+ QUANTIZE_ONE(20, 40, 22)
+ QUANTIZE_ONE(14, 28, 24)
+ QUANTIZE_ONE(22, 44, 26)
+ QUANTIZE_ONE(28, 56, 28)
+ QUANTIZE_ONE(30, 60, 30)
+
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
+ [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [sign]"=&r"(sign), [coeff]"=&r"(coeff),
+ [level]"=&r"(level)
+ : [pout]"r"(pout), [ppin]"r"(ppin),
+ [ppiq]"r"(ppiq), [max_level]"r"(max_level),
+ [ppbias]"r"(ppbias), [ppzthresh]"r"(ppzthresh),
+ [ppsharpen]"r"(ppsharpen), [ppq]"r"(ppq)
+ : "memory", "hi", "lo"
+ );
+
+ // moved out from macro to increase possibility for earlier breaking
+ for (i = 15; i >= 0; i--) {
+ if (out[i]) return 1;
+ }
+ return 0;
+}
+
+static int Quantize2Blocks(int16_t in[32], int16_t out[32],
+ const VP8Matrix* const mtx) {
+ int nz;
+ nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0;
+ nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1;
+ return nz;
+}
+
+#undef QUANTIZE_ONE
+
+// macro for one horizontal pass in Disto4x4 (TTransform)
+// two calls of function TTransform are merged into single one
+// A - offset in bytes to load from a and b buffers
+// E..H - offsets in bytes to store first results to tmp buffer
+// E1..H1 - offsets in bytes to store second results to tmp buffer
+#define HORIZONTAL_PASS(A, E, F, G, H, E1, F1, G1, H1) \
+ "lbu %[temp0], 0+" XSTR(BPS) "*" #A "(%[a]) \n\t" \
+ "lbu %[temp1], 1+" XSTR(BPS) "*" #A "(%[a]) \n\t" \
+ "lbu %[temp2], 2+" XSTR(BPS) "*" #A "(%[a]) \n\t" \
+ "lbu %[temp3], 3+" XSTR(BPS) "*" #A "(%[a]) \n\t" \
+ "lbu %[temp4], 0+" XSTR(BPS) "*" #A "(%[b]) \n\t" \
+ "lbu %[temp5], 1+" XSTR(BPS) "*" #A "(%[b]) \n\t" \
+ "lbu %[temp6], 2+" XSTR(BPS) "*" #A "(%[b]) \n\t" \
+ "lbu %[temp7], 3+" XSTR(BPS) "*" #A "(%[b]) \n\t" \
+ "addu %[temp8], %[temp0], %[temp2] \n\t" \
+ "subu %[temp0], %[temp0], %[temp2] \n\t" \
+ "addu %[temp2], %[temp1], %[temp3] \n\t" \
+ "subu %[temp1], %[temp1], %[temp3] \n\t" \
+ "addu %[temp3], %[temp4], %[temp6] \n\t" \
+ "subu %[temp4], %[temp4], %[temp6] \n\t" \
+ "addu %[temp6], %[temp5], %[temp7] \n\t" \
+ "subu %[temp5], %[temp5], %[temp7] \n\t" \
+ "addu %[temp7], %[temp8], %[temp2] \n\t" \
+ "subu %[temp2], %[temp8], %[temp2] \n\t" \
+ "addu %[temp8], %[temp0], %[temp1] \n\t" \
+ "subu %[temp0], %[temp0], %[temp1] \n\t" \
+ "addu %[temp1], %[temp3], %[temp6] \n\t" \
+ "subu %[temp3], %[temp3], %[temp6] \n\t" \
+ "addu %[temp6], %[temp4], %[temp5] \n\t" \
+ "subu %[temp4], %[temp4], %[temp5] \n\t" \
+ "sw %[temp7], " #E "(%[tmp]) \n\t" \
+ "sw %[temp2], " #H "(%[tmp]) \n\t" \
+ "sw %[temp8], " #F "(%[tmp]) \n\t" \
+ "sw %[temp0], " #G "(%[tmp]) \n\t" \
+ "sw %[temp1], " #E1 "(%[tmp]) \n\t" \
+ "sw %[temp3], " #H1 "(%[tmp]) \n\t" \
+ "sw %[temp6], " #F1 "(%[tmp]) \n\t" \
+ "sw %[temp4], " #G1 "(%[tmp]) \n\t"
+
+// macro for one vertical pass in Disto4x4 (TTransform)
+// two calls of function TTransform are merged into single one
+// since only one accu is available in mips32r1 instruction set
+// first is done second call of function TTransform and after
+// that first one.
+// const int sum1 = TTransform(a, w);
+// const int sum2 = TTransform(b, w);
+// return abs(sum2 - sum1) >> 5;
+// (sum2 - sum1) is calculated with madds (sub2) and msubs (sub1)
+// A..D - offsets in bytes to load first results from tmp buffer
+// A1..D1 - offsets in bytes to load second results from tmp buffer
+// E..H - offsets in bytes to load from w buffer
+#define VERTICAL_PASS(A, B, C, D, A1, B1, C1, D1, E, F, G, H) \
+ "lw %[temp0], " #A1 "(%[tmp]) \n\t" \
+ "lw %[temp1], " #C1 "(%[tmp]) \n\t" \
+ "lw %[temp2], " #B1 "(%[tmp]) \n\t" \
+ "lw %[temp3], " #D1 "(%[tmp]) \n\t" \
+ "addu %[temp8], %[temp0], %[temp1] \n\t" \
+ "subu %[temp0], %[temp0], %[temp1] \n\t" \
+ "addu %[temp1], %[temp2], %[temp3] \n\t" \
+ "subu %[temp2], %[temp2], %[temp3] \n\t" \
+ "addu %[temp3], %[temp8], %[temp1] \n\t" \
+ "subu %[temp8], %[temp8], %[temp1] \n\t" \
+ "addu %[temp1], %[temp0], %[temp2] \n\t" \
+ "subu %[temp0], %[temp0], %[temp2] \n\t" \
+ "sra %[temp4], %[temp3], 31 \n\t" \
+ "sra %[temp5], %[temp1], 31 \n\t" \
+ "sra %[temp6], %[temp0], 31 \n\t" \
+ "sra %[temp7], %[temp8], 31 \n\t" \
+ "xor %[temp3], %[temp3], %[temp4] \n\t" \
+ "xor %[temp1], %[temp1], %[temp5] \n\t" \
+ "xor %[temp0], %[temp0], %[temp6] \n\t" \
+ "xor %[temp8], %[temp8], %[temp7] \n\t" \
+ "subu %[temp3], %[temp3], %[temp4] \n\t" \
+ "subu %[temp1], %[temp1], %[temp5] \n\t" \
+ "subu %[temp0], %[temp0], %[temp6] \n\t" \
+ "subu %[temp8], %[temp8], %[temp7] \n\t" \
+ "lhu %[temp4], " #E "(%[w]) \n\t" \
+ "lhu %[temp5], " #F "(%[w]) \n\t" \
+ "lhu %[temp6], " #G "(%[w]) \n\t" \
+ "lhu %[temp7], " #H "(%[w]) \n\t" \
+ "madd %[temp4], %[temp3] \n\t" \
+ "madd %[temp5], %[temp1] \n\t" \
+ "madd %[temp6], %[temp0] \n\t" \
+ "madd %[temp7], %[temp8] \n\t" \
+ "lw %[temp0], " #A "(%[tmp]) \n\t" \
+ "lw %[temp1], " #C "(%[tmp]) \n\t" \
+ "lw %[temp2], " #B "(%[tmp]) \n\t" \
+ "lw %[temp3], " #D "(%[tmp]) \n\t" \
+ "addu %[temp8], %[temp0], %[temp1] \n\t" \
+ "subu %[temp0], %[temp0], %[temp1] \n\t" \
+ "addu %[temp1], %[temp2], %[temp3] \n\t" \
+ "subu %[temp2], %[temp2], %[temp3] \n\t" \
+ "addu %[temp3], %[temp8], %[temp1] \n\t" \
+ "subu %[temp1], %[temp8], %[temp1] \n\t" \
+ "addu %[temp8], %[temp0], %[temp2] \n\t" \
+ "subu %[temp0], %[temp0], %[temp2] \n\t" \
+ "sra %[temp2], %[temp3], 31 \n\t" \
+ "xor %[temp3], %[temp3], %[temp2] \n\t" \
+ "subu %[temp3], %[temp3], %[temp2] \n\t" \
+ "msub %[temp4], %[temp3] \n\t" \
+ "sra %[temp2], %[temp8], 31 \n\t" \
+ "sra %[temp3], %[temp0], 31 \n\t" \
+ "sra %[temp4], %[temp1], 31 \n\t" \
+ "xor %[temp8], %[temp8], %[temp2] \n\t" \
+ "xor %[temp0], %[temp0], %[temp3] \n\t" \
+ "xor %[temp1], %[temp1], %[temp4] \n\t" \
+ "subu %[temp8], %[temp8], %[temp2] \n\t" \
+ "subu %[temp0], %[temp0], %[temp3] \n\t" \
+ "subu %[temp1], %[temp1], %[temp4] \n\t" \
+ "msub %[temp5], %[temp8] \n\t" \
+ "msub %[temp6], %[temp0] \n\t" \
+ "msub %[temp7], %[temp1] \n\t"
+
+static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
+ const uint16_t* const w) {
+ int tmp[32];
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
+
+ __asm__ volatile(
+ HORIZONTAL_PASS(0, 0, 4, 8, 12, 64, 68, 72, 76)
+ HORIZONTAL_PASS(1, 16, 20, 24, 28, 80, 84, 88, 92)
+ HORIZONTAL_PASS(2, 32, 36, 40, 44, 96, 100, 104, 108)
+ HORIZONTAL_PASS(3, 48, 52, 56, 60, 112, 116, 120, 124)
+ "mthi $zero \n\t"
+ "mtlo $zero \n\t"
+ VERTICAL_PASS( 0, 16, 32, 48, 64, 80, 96, 112, 0, 8, 16, 24)
+ VERTICAL_PASS( 4, 20, 36, 52, 68, 84, 100, 116, 2, 10, 18, 26)
+ VERTICAL_PASS( 8, 24, 40, 56, 72, 88, 104, 120, 4, 12, 20, 28)
+ VERTICAL_PASS(12, 28, 44, 60, 76, 92, 108, 124, 6, 14, 22, 30)
+ "mflo %[temp0] \n\t"
+ "sra %[temp1], %[temp0], 31 \n\t"
+ "xor %[temp0], %[temp0], %[temp1] \n\t"
+ "subu %[temp0], %[temp0], %[temp1] \n\t"
+ "sra %[temp0], %[temp0], 5 \n\t"
+
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8)
+ : [a]"r"(a), [b]"r"(b), [w]"r"(w), [tmp]"r"(tmp)
+ : "memory", "hi", "lo"
+ );
+
+ return temp0;
+}
+
+#undef VERTICAL_PASS
+#undef HORIZONTAL_PASS
+
+static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
+ const uint16_t* const w) {
+ int D = 0;
+ int x, y;
+ for (y = 0; y < 16 * BPS; y += 4 * BPS) {
+ for (x = 0; x < 16; x += 4) {
+ D += Disto4x4(a + x + y, b + x + y, w);
+ }
+ }
+ return D;
+}
+
+// macro for one horizontal pass in FTransform
+// temp0..temp15 holds tmp[0]..tmp[15]
+// A - offset in bytes to load from src and ref buffers
+// TEMP0..TEMP3 - registers for corresponding tmp elements
+#define HORIZONTAL_PASS(A, TEMP0, TEMP1, TEMP2, TEMP3) \
+ "lw %[" #TEMP1 "], 0(%[args]) \n\t" \
+ "lw %[" #TEMP2 "], 4(%[args]) \n\t" \
+ "lbu %[temp16], 0+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \
+ "lbu %[temp17], 0+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \
+ "lbu %[temp18], 1+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \
+ "lbu %[temp19], 1+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \
+ "subu %[temp20], %[temp16], %[temp17] \n\t" \
+ "lbu %[temp16], 2+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \
+ "lbu %[temp17], 2+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \
+ "subu %[" #TEMP0 "], %[temp18], %[temp19] \n\t" \
+ "lbu %[temp18], 3+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \
+ "lbu %[temp19], 3+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \
+ "subu %[" #TEMP1 "], %[temp16], %[temp17] \n\t" \
+ "subu %[" #TEMP2 "], %[temp18], %[temp19] \n\t" \
+ "addu %[" #TEMP3 "], %[temp20], %[" #TEMP2 "] \n\t" \
+ "subu %[" #TEMP2 "], %[temp20], %[" #TEMP2 "] \n\t" \
+ "addu %[temp20], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \
+ "subu %[" #TEMP0 "], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \
+ "mul %[temp16], %[" #TEMP2 "], %[c5352] \n\t" \
+ "mul %[temp17], %[" #TEMP2 "], %[c2217] \n\t" \
+ "mul %[temp18], %[" #TEMP0 "], %[c5352] \n\t" \
+ "mul %[temp19], %[" #TEMP0 "], %[c2217] \n\t" \
+ "addu %[" #TEMP1 "], %[" #TEMP3 "], %[temp20] \n\t" \
+ "subu %[temp20], %[" #TEMP3 "], %[temp20] \n\t" \
+ "sll %[" #TEMP0 "], %[" #TEMP1 "], 3 \n\t" \
+ "sll %[" #TEMP2 "], %[temp20], 3 \n\t" \
+ "addiu %[temp16], %[temp16], 1812 \n\t" \
+ "addiu %[temp17], %[temp17], 937 \n\t" \
+ "addu %[temp16], %[temp16], %[temp19] \n\t" \
+ "subu %[temp17], %[temp17], %[temp18] \n\t" \
+ "sra %[" #TEMP1 "], %[temp16], 9 \n\t" \
+ "sra %[" #TEMP3 "], %[temp17], 9 \n\t"
+
+// macro for one vertical pass in FTransform
+// temp0..temp15 holds tmp[0]..tmp[15]
+// A..D - offsets in bytes to store to out buffer
+// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements
+#define VERTICAL_PASS(A, B, C, D, TEMP0, TEMP4, TEMP8, TEMP12) \
+ "addu %[temp16], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \
+ "subu %[temp19], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \
+ "addu %[temp17], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \
+ "subu %[temp18], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \
+ "mul %[" #TEMP8 "], %[temp19], %[c2217] \n\t" \
+ "mul %[" #TEMP12 "], %[temp18], %[c2217] \n\t" \
+ "mul %[" #TEMP4 "], %[temp19], %[c5352] \n\t" \
+ "mul %[temp18], %[temp18], %[c5352] \n\t" \
+ "addiu %[temp16], %[temp16], 7 \n\t" \
+ "addu %[" #TEMP0 "], %[temp16], %[temp17] \n\t" \
+ "sra %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \
+ "addu %[" #TEMP12 "], %[" #TEMP12 "], %[" #TEMP4 "] \n\t" \
+ "subu %[" #TEMP4 "], %[temp16], %[temp17] \n\t" \
+ "sra %[" #TEMP4 "], %[" #TEMP4 "], 4 \n\t" \
+ "addiu %[" #TEMP8 "], %[" #TEMP8 "], 30000 \n\t" \
+ "addiu %[" #TEMP12 "], %[" #TEMP12 "], 12000 \n\t" \
+ "addiu %[" #TEMP8 "], %[" #TEMP8 "], 21000 \n\t" \
+ "subu %[" #TEMP8 "], %[" #TEMP8 "], %[temp18] \n\t" \
+ "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \
+ "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \
+ "addiu %[temp16], %[" #TEMP12 "], 1 \n\t" \
+ "movn %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \
+ "sh %[" #TEMP0 "], " #A "(%[temp20]) \n\t" \
+ "sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \
+ "sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \
+ "sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t"
+
+static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) {
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
+ int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16;
+ int temp17, temp18, temp19, temp20;
+ const int c2217 = 2217;
+ const int c5352 = 5352;
+ const int* const args[3] =
+ { (const int*)src, (const int*)ref, (const int*)out };
+
+ __asm__ volatile(
+ HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3)
+ HORIZONTAL_PASS(1, temp4, temp5, temp6, temp7)
+ HORIZONTAL_PASS(2, temp8, temp9, temp10, temp11)
+ HORIZONTAL_PASS(3, temp12, temp13, temp14, temp15)
+ "lw %[temp20], 8(%[args]) \n\t"
+ VERTICAL_PASS(0, 8, 16, 24, temp0, temp4, temp8, temp12)
+ VERTICAL_PASS(2, 10, 18, 26, temp1, temp5, temp9, temp13)
+ VERTICAL_PASS(4, 12, 20, 28, temp2, temp6, temp10, temp14)
+ VERTICAL_PASS(6, 14, 22, 30, temp3, temp7, temp11, temp15)
+
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
+ [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11),
+ [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14),
+ [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17),
+ [temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20)
+ : [args]"r"(args), [c2217]"r"(c2217), [c5352]"r"(c5352)
+ : "memory", "hi", "lo"
+ );
+}
+
+#undef VERTICAL_PASS
+#undef HORIZONTAL_PASS
+
+#if !defined(WORK_AROUND_GCC)
+
+#define GET_SSE_INNER(A, B, C, D) \
+ "lbu %[temp0], " #A "(%[a]) \n\t" \
+ "lbu %[temp1], " #A "(%[b]) \n\t" \
+ "lbu %[temp2], " #B "(%[a]) \n\t" \
+ "lbu %[temp3], " #B "(%[b]) \n\t" \
+ "lbu %[temp4], " #C "(%[a]) \n\t" \
+ "lbu %[temp5], " #C "(%[b]) \n\t" \
+ "lbu %[temp6], " #D "(%[a]) \n\t" \
+ "lbu %[temp7], " #D "(%[b]) \n\t" \
+ "subu %[temp0], %[temp0], %[temp1] \n\t" \
+ "subu %[temp2], %[temp2], %[temp3] \n\t" \
+ "subu %[temp4], %[temp4], %[temp5] \n\t" \
+ "subu %[temp6], %[temp6], %[temp7] \n\t" \
+ "madd %[temp0], %[temp0] \n\t" \
+ "madd %[temp2], %[temp2] \n\t" \
+ "madd %[temp4], %[temp4] \n\t" \
+ "madd %[temp6], %[temp6] \n\t"
+
+#define GET_SSE(A, B, C, D) \
+ GET_SSE_INNER(A, A + 1, A + 2, A + 3) \
+ GET_SSE_INNER(B, B + 1, B + 2, B + 3) \
+ GET_SSE_INNER(C, C + 1, C + 2, C + 3) \
+ GET_SSE_INNER(D, D + 1, D + 2, D + 3)
+
+static int SSE16x16(const uint8_t* a, const uint8_t* b) {
+ int count;
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
+
+ __asm__ volatile(
+ "mult $zero, $zero \n\t"
+
+ GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS)
+ GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS)
+ GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS)
+ GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS)
+ GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS)
+ GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS)
+ GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS)
+ GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS)
+ GET_SSE( 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS)
+ GET_SSE( 9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS)
+ GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS)
+ GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS)
+ GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS)
+ GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS)
+ GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS)
+ GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS)
+
+ "mflo %[count] \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
+ : [a]"r"(a), [b]"r"(b)
+ : "memory", "hi", "lo"
+ );
+ return count;
+}
+
+static int SSE16x8(const uint8_t* a, const uint8_t* b) {
+ int count;
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
+
+ __asm__ volatile(
+ "mult $zero, $zero \n\t"
+
+ GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS)
+ GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS)
+ GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS)
+ GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS)
+ GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS)
+ GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS)
+ GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS)
+ GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS)
+
+ "mflo %[count] \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
+ : [a]"r"(a), [b]"r"(b)
+ : "memory", "hi", "lo"
+ );
+ return count;
+}
+
+static int SSE8x8(const uint8_t* a, const uint8_t* b) {
+ int count;
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
+
+ __asm__ volatile(
+ "mult $zero, $zero \n\t"
+
+ GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS)
+ GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS)
+ GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS)
+ GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS)
+
+ "mflo %[count] \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
+ : [a]"r"(a), [b]"r"(b)
+ : "memory", "hi", "lo"
+ );
+ return count;
+}
+
+static int SSE4x4(const uint8_t* a, const uint8_t* b) {
+ int count;
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
+
+ __asm__ volatile(
+ "mult $zero, $zero \n\t"
+
+ GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS)
+
+ "mflo %[count] \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
+ : [a]"r"(a), [b]"r"(b)
+ : "memory", "hi", "lo"
+ );
+ return count;
+}
+
+#undef GET_SSE
+#undef GET_SSE_INNER
+
+#endif // !WORK_AROUND_GCC
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8EncDspInitMIPS32(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMIPS32(void) {
+ VP8ITransform = ITransform;
+ VP8FTransform = FTransform;
+ VP8EncQuantizeBlock = QuantizeBlock;
+ VP8EncQuantize2Blocks = Quantize2Blocks;
+ VP8TDisto4x4 = Disto4x4;
+ VP8TDisto16x16 = Disto16x16;
+#if !defined(WORK_AROUND_GCC)
+ VP8SSE16x16 = SSE16x16;
+ VP8SSE8x8 = SSE8x8;
+ VP8SSE16x8 = SSE16x8;
+ VP8SSE4x4 = SSE4x4;
+#endif
+}
+
+#else // !WEBP_USE_MIPS32
+
+WEBP_DSP_INIT_STUB(VP8EncDspInitMIPS32)
+
+#endif // WEBP_USE_MIPS32
diff --git a/drivers/webp/dsp/enc_mips_dsp_r2.c b/drivers/webp/dsp/enc_mips_dsp_r2.c
new file mode 100644
index 0000000000..7c814fa04a
--- /dev/null
+++ b/drivers/webp/dsp/enc_mips_dsp_r2.c
@@ -0,0 +1,1512 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// MIPS version of speed-critical encoding functions.
+//
+// Author(s): Darko Laus (darko.laus@imgtec.com)
+// Mirko Raus (mirko.raus@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS_DSP_R2)
+
+#include "./mips_macro.h"
+#include "../enc/cost.h"
+#include "../enc/vp8enci.h"
+
+static const int kC1 = 20091 + (1 << 16);
+static const int kC2 = 35468;
+
+// O - output
+// I - input (macro doesn't change it)
+#define ADD_SUB_HALVES_X4(O0, O1, O2, O3, O4, O5, O6, O7, \
+ I0, I1, I2, I3, I4, I5, I6, I7) \
+ "addq.ph %[" #O0 "], %[" #I0 "], %[" #I1 "] \n\t" \
+ "subq.ph %[" #O1 "], %[" #I0 "], %[" #I1 "] \n\t" \
+ "addq.ph %[" #O2 "], %[" #I2 "], %[" #I3 "] \n\t" \
+ "subq.ph %[" #O3 "], %[" #I2 "], %[" #I3 "] \n\t" \
+ "addq.ph %[" #O4 "], %[" #I4 "], %[" #I5 "] \n\t" \
+ "subq.ph %[" #O5 "], %[" #I4 "], %[" #I5 "] \n\t" \
+ "addq.ph %[" #O6 "], %[" #I6 "], %[" #I7 "] \n\t" \
+ "subq.ph %[" #O7 "], %[" #I6 "], %[" #I7 "] \n\t"
+
+// IO - input/output
+#define ABS_X8(IO0, IO1, IO2, IO3, IO4, IO5, IO6, IO7) \
+ "absq_s.ph %[" #IO0 "], %[" #IO0 "] \n\t" \
+ "absq_s.ph %[" #IO1 "], %[" #IO1 "] \n\t" \
+ "absq_s.ph %[" #IO2 "], %[" #IO2 "] \n\t" \
+ "absq_s.ph %[" #IO3 "], %[" #IO3 "] \n\t" \
+ "absq_s.ph %[" #IO4 "], %[" #IO4 "] \n\t" \
+ "absq_s.ph %[" #IO5 "], %[" #IO5 "] \n\t" \
+ "absq_s.ph %[" #IO6 "], %[" #IO6 "] \n\t" \
+ "absq_s.ph %[" #IO7 "], %[" #IO7 "] \n\t"
+
+// dpa.w.ph $ac0 temp0 ,temp1
+// $ac += temp0[31..16] * temp1[31..16] + temp0[15..0] * temp1[15..0]
+// dpax.w.ph $ac0 temp0 ,temp1
+// $ac += temp0[31..16] * temp1[15..0] + temp0[15..0] * temp1[31..16]
+// O - output
+// I - input (macro doesn't change it)
+#define MUL_HALF(O0, I0, I1, I2, I3, I4, I5, I6, I7, \
+ I8, I9, I10, I11, I12, I13, I14, I15) \
+ "mult $ac0, $zero, $zero \n\t" \
+ "dpa.w.ph $ac0, %[" #I2 "], %[" #I0 "] \n\t" \
+ "dpax.w.ph $ac0, %[" #I5 "], %[" #I6 "] \n\t" \
+ "dpa.w.ph $ac0, %[" #I8 "], %[" #I9 "] \n\t" \
+ "dpax.w.ph $ac0, %[" #I11 "], %[" #I4 "] \n\t" \
+ "dpa.w.ph $ac0, %[" #I12 "], %[" #I7 "] \n\t" \
+ "dpax.w.ph $ac0, %[" #I13 "], %[" #I1 "] \n\t" \
+ "dpa.w.ph $ac0, %[" #I14 "], %[" #I3 "] \n\t" \
+ "dpax.w.ph $ac0, %[" #I15 "], %[" #I10 "] \n\t" \
+ "mflo %[" #O0 "], $ac0 \n\t"
+
+#define OUTPUT_EARLY_CLOBBER_REGS_17() \
+ OUTPUT_EARLY_CLOBBER_REGS_10(), \
+ [temp11]"=&r"(temp11), [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), \
+ [temp14]"=&r"(temp14), [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), \
+ [temp17]"=&r"(temp17)
+
+// macro for one horizontal pass in FTransform
+// temp0..temp15 holds tmp[0]..tmp[15]
+// A - offset in bytes to load from src and ref buffers
+// TEMP0..TEMP3 - registers for corresponding tmp elements
+#define HORIZONTAL_PASS(A, TEMP0, TEMP1, TEMP2, TEMP3) \
+ "lw %[" #TEMP0 "], 0(%[args]) \n\t" \
+ "lw %[" #TEMP1 "], 4(%[args]) \n\t" \
+ "lw %[" #TEMP2 "], " XSTR(BPS) "*" #A "(%[" #TEMP0 "]) \n\t" \
+ "lw %[" #TEMP3 "], " XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \
+ "preceu.ph.qbl %[" #TEMP0 "], %[" #TEMP2 "] \n\t" \
+ "preceu.ph.qbl %[" #TEMP1 "], %[" #TEMP3 "] \n\t" \
+ "preceu.ph.qbr %[" #TEMP2 "], %[" #TEMP2 "] \n\t" \
+ "preceu.ph.qbr %[" #TEMP3 "], %[" #TEMP3 "] \n\t" \
+ "subq.ph %[" #TEMP0 "], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \
+ "subq.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP3 "] \n\t" \
+ "rotr %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\t" \
+ "addq.ph %[" #TEMP1 "], %[" #TEMP2 "], %[" #TEMP0 "] \n\t" \
+ "subq.ph %[" #TEMP3 "], %[" #TEMP2 "], %[" #TEMP0 "] \n\t" \
+ "seh %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \
+ "sra %[temp16], %[" #TEMP1 "], 16 \n\t" \
+ "seh %[temp19], %[" #TEMP3 "] \n\t" \
+ "sra %[" #TEMP3 "], %[" #TEMP3 "], 16 \n\t" \
+ "subu %[" #TEMP2 "], %[" #TEMP0 "], %[temp16] \n\t" \
+ "addu %[" #TEMP0 "], %[" #TEMP0 "], %[temp16] \n\t" \
+ "mul %[temp17], %[temp19], %[c2217] \n\t" \
+ "mul %[temp18], %[" #TEMP3 "], %[c5352] \n\t" \
+ "mul %[" #TEMP1 "], %[temp19], %[c5352] \n\t" \
+ "mul %[temp16], %[" #TEMP3 "], %[c2217] \n\t" \
+ "sll %[" #TEMP2 "], %[" #TEMP2 "], 3 \n\t" \
+ "sll %[" #TEMP0 "], %[" #TEMP0 "], 3 \n\t" \
+ "subu %[" #TEMP3 "], %[temp17], %[temp18] \n\t" \
+ "addu %[" #TEMP1 "], %[temp16], %[" #TEMP1 "] \n\t" \
+ "addiu %[" #TEMP3 "], %[" #TEMP3 "], 937 \n\t" \
+ "addiu %[" #TEMP1 "], %[" #TEMP1 "], 1812 \n\t" \
+ "sra %[" #TEMP3 "], %[" #TEMP3 "], 9 \n\t" \
+ "sra %[" #TEMP1 "], %[" #TEMP1 "], 9 \n\t"
+
+// macro for one vertical pass in FTransform
+// temp0..temp15 holds tmp[0]..tmp[15]
+// A..D - offsets in bytes to store to out buffer
+// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements
+#define VERTICAL_PASS(A, B, C, D, TEMP0, TEMP4, TEMP8, TEMP12) \
+ "addu %[temp16], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \
+ "subu %[temp19], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \
+ "addu %[temp17], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \
+ "subu %[temp18], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \
+ "mul %[" #TEMP8 "], %[temp19], %[c2217] \n\t" \
+ "mul %[" #TEMP12 "], %[temp18], %[c2217] \n\t" \
+ "mul %[" #TEMP4 "], %[temp19], %[c5352] \n\t" \
+ "mul %[temp18], %[temp18], %[c5352] \n\t" \
+ "addiu %[temp16], %[temp16], 7 \n\t" \
+ "addu %[" #TEMP0 "], %[temp16], %[temp17] \n\t" \
+ "sra %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \
+ "addu %[" #TEMP12 "], %[" #TEMP12 "], %[" #TEMP4 "] \n\t" \
+ "subu %[" #TEMP4 "], %[temp16], %[temp17] \n\t" \
+ "sra %[" #TEMP4 "], %[" #TEMP4 "], 4 \n\t" \
+ "addiu %[" #TEMP8 "], %[" #TEMP8 "], 30000 \n\t" \
+ "addiu %[" #TEMP12 "], %[" #TEMP12 "], 12000 \n\t" \
+ "addiu %[" #TEMP8 "], %[" #TEMP8 "], 21000 \n\t" \
+ "subu %[" #TEMP8 "], %[" #TEMP8 "], %[temp18] \n\t" \
+ "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \
+ "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \
+ "addiu %[temp16], %[" #TEMP12 "], 1 \n\t" \
+ "movn %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \
+ "sh %[" #TEMP0 "], " #A "(%[temp20]) \n\t" \
+ "sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \
+ "sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \
+ "sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t"
+
+static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) {
+ const int c2217 = 2217;
+ const int c5352 = 5352;
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
+ int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16;
+ int temp17, temp18, temp19, temp20;
+ const int* const args[3] =
+ { (const int*)src, (const int*)ref, (const int*)out };
+
+ __asm__ volatile (
+ HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3)
+ HORIZONTAL_PASS(1, temp4, temp5, temp6, temp7)
+ HORIZONTAL_PASS(2, temp8, temp9, temp10, temp11)
+ HORIZONTAL_PASS(3, temp12, temp13, temp14, temp15)
+ "lw %[temp20], 8(%[args]) \n\t"
+ VERTICAL_PASS(0, 8, 16, 24, temp0, temp4, temp8, temp12)
+ VERTICAL_PASS(2, 10, 18, 26, temp1, temp5, temp9, temp13)
+ VERTICAL_PASS(4, 12, 20, 28, temp2, temp6, temp10, temp14)
+ VERTICAL_PASS(6, 14, 22, 30, temp3, temp7, temp11, temp15)
+ OUTPUT_EARLY_CLOBBER_REGS_18(),
+ [temp0]"=&r"(temp0), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20)
+ : [args]"r"(args), [c2217]"r"(c2217), [c5352]"r"(c5352)
+ : "memory", "hi", "lo"
+ );
+}
+
+#undef VERTICAL_PASS
+#undef HORIZONTAL_PASS
+
+static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in,
+ uint8_t* dst) {
+ int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
+ int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
+
+ __asm__ volatile (
+ "ulw %[temp1], 0(%[in]) \n\t"
+ "ulw %[temp2], 16(%[in]) \n\t"
+ LOAD_IN_X2(temp5, temp6, 24, 26)
+ ADD_SUB_HALVES(temp3, temp4, temp1, temp2)
+ LOAD_IN_X2(temp1, temp2, 8, 10)
+ MUL_SHIFT_SUM(temp7, temp8, temp9, temp10, temp11, temp12, temp13, temp14,
+ temp10, temp8, temp9, temp7, temp1, temp2, temp5, temp6,
+ temp13, temp11, temp14, temp12)
+ INSERT_HALF_X2(temp8, temp7, temp10, temp9)
+ "ulw %[temp17], 4(%[in]) \n\t"
+ "ulw %[temp18], 20(%[in]) \n\t"
+ ADD_SUB_HALVES(temp1, temp2, temp3, temp8)
+ ADD_SUB_HALVES(temp5, temp6, temp4, temp7)
+ ADD_SUB_HALVES(temp7, temp8, temp17, temp18)
+ LOAD_IN_X2(temp17, temp18, 12, 14)
+ LOAD_IN_X2(temp9, temp10, 28, 30)
+ MUL_SHIFT_SUM(temp11, temp12, temp13, temp14, temp15, temp16, temp4, temp17,
+ temp12, temp14, temp11, temp13, temp17, temp18, temp9, temp10,
+ temp15, temp4, temp16, temp17)
+ INSERT_HALF_X2(temp11, temp12, temp13, temp14)
+ ADD_SUB_HALVES(temp17, temp8, temp8, temp11)
+ ADD_SUB_HALVES(temp3, temp4, temp7, temp12)
+
+ // horizontal
+ SRA_16(temp9, temp10, temp11, temp12, temp1, temp2, temp5, temp6)
+ INSERT_HALF_X2(temp1, temp6, temp5, temp2)
+ SRA_16(temp13, temp14, temp15, temp16, temp3, temp4, temp17, temp8)
+ "repl.ph %[temp2], 0x4 \n\t"
+ INSERT_HALF_X2(temp3, temp8, temp17, temp4)
+ "addq.ph %[temp1], %[temp1], %[temp2] \n\t"
+ "addq.ph %[temp6], %[temp6], %[temp2] \n\t"
+ ADD_SUB_HALVES(temp2, temp4, temp1, temp3)
+ ADD_SUB_HALVES(temp5, temp7, temp6, temp8)
+ MUL_SHIFT_SUM(temp1, temp3, temp6, temp8, temp9, temp13, temp17, temp18,
+ temp3, temp13, temp1, temp9, temp9, temp13, temp11, temp15,
+ temp6, temp17, temp8, temp18)
+ MUL_SHIFT_SUM(temp6, temp8, temp18, temp17, temp11, temp15, temp12, temp16,
+ temp8, temp15, temp6, temp11, temp12, temp16, temp10, temp14,
+ temp18, temp12, temp17, temp16)
+ INSERT_HALF_X2(temp1, temp3, temp9, temp13)
+ INSERT_HALF_X2(temp6, temp8, temp11, temp15)
+ SHIFT_R_SUM_X2(temp9, temp10, temp11, temp12, temp13, temp14, temp15,
+ temp16, temp2, temp4, temp5, temp7, temp3, temp1, temp8,
+ temp6)
+ PACK_2_HALVES_TO_WORD(temp1, temp2, temp3, temp4, temp9, temp12, temp13,
+ temp16, temp11, temp10, temp15, temp14)
+ LOAD_WITH_OFFSET_X4(temp10, temp11, temp14, temp15, ref,
+ 0, 0, 0, 0,
+ 0, 1, 2, 3,
+ BPS)
+ CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp17, temp18, temp10,
+ temp11, temp10, temp11, temp14, temp15)
+ STORE_SAT_SUM_X2(temp5, temp6, temp7, temp8, temp17, temp18, temp10, temp11,
+ temp9, temp12, temp1, temp2, temp13, temp16, temp3, temp4,
+ dst, 0, 1, 2, 3, BPS)
+
+ OUTPUT_EARLY_CLOBBER_REGS_18()
+ : [dst]"r"(dst), [in]"r"(in), [kC1]"r"(kC1), [kC2]"r"(kC2), [ref]"r"(ref)
+ : "memory", "hi", "lo"
+ );
+}
+
+static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst,
+ int do_two) {
+ ITransformOne(ref, in, dst);
+ if (do_two) {
+ ITransformOne(ref + 4, in + 16, dst + 4);
+ }
+}
+
+static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
+ const uint16_t* const w) {
+ int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
+ int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17;
+
+ __asm__ volatile (
+ LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, a,
+ 0, 0, 0, 0,
+ 0, 1, 2, 3,
+ BPS)
+ CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp9,temp10, temp11,
+ temp12, temp1, temp2, temp3, temp4)
+ ADD_SUB_HALVES_X4(temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8,
+ temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12)
+ PACK_2_HALVES_TO_WORD(temp9, temp10, temp11, temp12, temp1, temp3, temp5,
+ temp7, temp2, temp4, temp6, temp8)
+ ADD_SUB_HALVES_X4(temp2, temp4, temp6, temp8, temp9, temp1, temp3, temp10,
+ temp1, temp9, temp3, temp10, temp5, temp11, temp7, temp12)
+ ADD_SUB_HALVES_X4(temp5, temp11, temp7, temp2, temp9, temp3, temp6, temp12,
+ temp2, temp9, temp6, temp3, temp4, temp1, temp8, temp10)
+ ADD_SUB_HALVES_X4(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2,
+ temp5, temp7, temp11, temp2, temp9, temp6, temp3, temp12)
+ ABS_X8(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2)
+ LOAD_WITH_OFFSET_X4(temp3, temp6, temp9, temp12, w,
+ 0, 4, 8, 12,
+ 0, 0, 0, 0,
+ 0)
+ LOAD_WITH_OFFSET_X4(temp13, temp14, temp15, temp16, w,
+ 0, 4, 8, 12,
+ 1, 1, 1, 1,
+ 16)
+ MUL_HALF(temp17, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8,
+ temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16)
+ LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, b,
+ 0, 0, 0, 0,
+ 0, 1, 2, 3,
+ BPS)
+ CONVERT_2_BYTES_TO_HALF(temp5,temp6, temp7, temp8, temp9,temp10, temp11,
+ temp12, temp1, temp2, temp3, temp4)
+ ADD_SUB_HALVES_X4(temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8,
+ temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12)
+ PACK_2_HALVES_TO_WORD(temp9, temp10, temp11, temp12, temp1, temp3, temp5,
+ temp7, temp2, temp4, temp6, temp8)
+ ADD_SUB_HALVES_X4(temp2, temp4, temp6, temp8, temp9, temp1, temp3, temp10,
+ temp1, temp9, temp3, temp10, temp5, temp11, temp7, temp12)
+ ADD_SUB_HALVES_X4(temp5, temp11, temp7, temp2, temp9, temp3, temp6, temp12,
+ temp2, temp9, temp6, temp3, temp4, temp1, temp8, temp10)
+ ADD_SUB_HALVES_X4(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2,
+ temp5, temp7, temp11, temp2, temp9, temp6, temp3, temp12)
+ ABS_X8(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2)
+ LOAD_WITH_OFFSET_X4(temp3, temp6, temp9, temp12, w,
+ 0, 4, 8, 12,
+ 0, 0, 0, 0,
+ 0)
+ LOAD_WITH_OFFSET_X4(temp13, temp14, temp15, temp16, w,
+ 0, 4, 8, 12,
+ 1, 1, 1, 1,
+ 16)
+ MUL_HALF(temp3, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8,
+ temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16)
+ OUTPUT_EARLY_CLOBBER_REGS_17()
+ : [a]"r"(a), [b]"r"(b), [w]"r"(w)
+ : "memory", "hi", "lo"
+ );
+ return abs(temp3 - temp17) >> 5;
+}
+
+static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
+ const uint16_t* const w) {
+ int D = 0;
+ int x, y;
+ for (y = 0; y < 16 * BPS; y += 4 * BPS) {
+ for (x = 0; x < 16; x += 4) {
+ D += Disto4x4(a + x + y, b + x + y, w);
+ }
+ }
+ return D;
+}
+
+//------------------------------------------------------------------------------
+// Intra predictions
+
+#define FILL_PART(J, SIZE) \
+ "usw %[value], 0+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \
+ "usw %[value], 4+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \
+ ".if " #SIZE " == 16 \n\t" \
+ "usw %[value], 8+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \
+ "usw %[value], 12+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \
+ ".endif \n\t"
+
+#define FILL_8_OR_16(DST, VALUE, SIZE) do { \
+ int value = (VALUE); \
+ __asm__ volatile ( \
+ "replv.qb %[value], %[value] \n\t" \
+ FILL_PART( 0, SIZE) \
+ FILL_PART( 1, SIZE) \
+ FILL_PART( 2, SIZE) \
+ FILL_PART( 3, SIZE) \
+ FILL_PART( 4, SIZE) \
+ FILL_PART( 5, SIZE) \
+ FILL_PART( 6, SIZE) \
+ FILL_PART( 7, SIZE) \
+ ".if " #SIZE " == 16 \n\t" \
+ FILL_PART( 8, 16) \
+ FILL_PART( 9, 16) \
+ FILL_PART(10, 16) \
+ FILL_PART(11, 16) \
+ FILL_PART(12, 16) \
+ FILL_PART(13, 16) \
+ FILL_PART(14, 16) \
+ FILL_PART(15, 16) \
+ ".endif \n\t" \
+ : [value]"+&r"(value) \
+ : [dst]"r"((DST)) \
+ : "memory" \
+ ); \
+} while (0)
+
+#define VERTICAL_PRED(DST, TOP, SIZE) \
+static WEBP_INLINE void VerticalPred##SIZE(uint8_t* (DST), \
+ const uint8_t* (TOP)) { \
+ int j; \
+ if ((TOP)) { \
+ for (j = 0; j < (SIZE); ++j) memcpy((DST) + j * BPS, (TOP), (SIZE)); \
+ } else { \
+ FILL_8_OR_16((DST), 127, (SIZE)); \
+ } \
+}
+
+VERTICAL_PRED(dst, top, 8)
+VERTICAL_PRED(dst, top, 16)
+
+#undef VERTICAL_PRED
+
+#define HORIZONTAL_PRED(DST, LEFT, SIZE) \
+static WEBP_INLINE void HorizontalPred##SIZE(uint8_t* (DST), \
+ const uint8_t* (LEFT)) { \
+ if (LEFT) { \
+ int j; \
+ for (j = 0; j < (SIZE); ++j) { \
+ memset((DST) + j * BPS, (LEFT)[j], (SIZE)); \
+ } \
+ } else { \
+ FILL_8_OR_16((DST), 129, (SIZE)); \
+ } \
+}
+
+HORIZONTAL_PRED(dst, left, 8)
+HORIZONTAL_PRED(dst, left, 16)
+
+#undef HORIZONTAL_PRED
+
+#define CLIPPING() \
+ "preceu.ph.qbl %[temp2], %[temp0] \n\t" \
+ "preceu.ph.qbr %[temp0], %[temp0] \n\t" \
+ "preceu.ph.qbl %[temp3], %[temp1] \n\t" \
+ "preceu.ph.qbr %[temp1], %[temp1] \n\t" \
+ "addu.ph %[temp2], %[temp2], %[leftY_1] \n\t" \
+ "addu.ph %[temp0], %[temp0], %[leftY_1] \n\t" \
+ "addu.ph %[temp3], %[temp3], %[leftY_1] \n\t" \
+ "addu.ph %[temp1], %[temp1], %[leftY_1] \n\t" \
+ "shll_s.ph %[temp2], %[temp2], 7 \n\t" \
+ "shll_s.ph %[temp0], %[temp0], 7 \n\t" \
+ "shll_s.ph %[temp3], %[temp3], 7 \n\t" \
+ "shll_s.ph %[temp1], %[temp1], 7 \n\t" \
+ "precrqu_s.qb.ph %[temp0], %[temp2], %[temp0] \n\t" \
+ "precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t"
+
+#define CLIP_8B_TO_DST(DST, LEFT, TOP, SIZE) do { \
+ int leftY_1 = ((int)(LEFT)[y] << 16) + (LEFT)[y]; \
+ int temp0, temp1, temp2, temp3; \
+ __asm__ volatile ( \
+ "replv.ph %[leftY_1], %[leftY_1] \n\t" \
+ "ulw %[temp0], 0(%[top]) \n\t" \
+ "ulw %[temp1], 4(%[top]) \n\t" \
+ "subu.ph %[leftY_1], %[leftY_1], %[left_1] \n\t" \
+ CLIPPING() \
+ "usw %[temp0], 0(%[dst]) \n\t" \
+ "usw %[temp1], 4(%[dst]) \n\t" \
+ ".if " #SIZE " == 16 \n\t" \
+ "ulw %[temp0], 8(%[top]) \n\t" \
+ "ulw %[temp1], 12(%[top]) \n\t" \
+ CLIPPING() \
+ "usw %[temp0], 8(%[dst]) \n\t" \
+ "usw %[temp1], 12(%[dst]) \n\t" \
+ ".endif \n\t" \
+ : [leftY_1]"+&r"(leftY_1), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \
+ [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \
+ : [left_1]"r"(left_1), [top]"r"((TOP)), [dst]"r"((DST)) \
+ : "memory" \
+ ); \
+} while (0)
+
+#define CLIP_TO_DST(DST, LEFT, TOP, SIZE) do { \
+ int y; \
+ const int left_1 = ((int)(LEFT)[-1] << 16) + (LEFT)[-1]; \
+ for (y = 0; y < (SIZE); ++y) { \
+ CLIP_8B_TO_DST((DST), (LEFT), (TOP), (SIZE)); \
+ (DST) += BPS; \
+ } \
+} while (0)
+
+#define TRUE_MOTION(DST, LEFT, TOP, SIZE) \
+static WEBP_INLINE void TrueMotion##SIZE(uint8_t* (DST), const uint8_t* (LEFT),\
+ const uint8_t* (TOP)) { \
+ if ((LEFT) != NULL) { \
+ if ((TOP) != NULL) { \
+ CLIP_TO_DST((DST), (LEFT), (TOP), (SIZE)); \
+ } else { \
+ HorizontalPred##SIZE((DST), (LEFT)); \
+ } \
+ } else { \
+ /* true motion without left samples (hence: with default 129 value) */ \
+ /* is equivalent to VE prediction where you just copy the top samples. */ \
+ /* Note that if top samples are not available, the default value is */ \
+ /* then 129, and not 127 as in the VerticalPred case. */ \
+ if ((TOP) != NULL) { \
+ VerticalPred##SIZE((DST), (TOP)); \
+ } else { \
+ FILL_8_OR_16((DST), 129, (SIZE)); \
+ } \
+ } \
+}
+
+TRUE_MOTION(dst, left, top, 8)
+TRUE_MOTION(dst, left, top, 16)
+
+#undef TRUE_MOTION
+#undef CLIP_TO_DST
+#undef CLIP_8B_TO_DST
+#undef CLIPPING
+
+static WEBP_INLINE void DCMode16(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top) {
+ int DC, DC1;
+ int temp0, temp1, temp2, temp3;
+
+ __asm__ volatile(
+ "beqz %[top], 2f \n\t"
+ LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, top,
+ 0, 4, 8, 12,
+ 0, 0, 0, 0,
+ 0)
+ "raddu.w.qb %[temp0], %[temp0] \n\t"
+ "raddu.w.qb %[temp1], %[temp1] \n\t"
+ "raddu.w.qb %[temp2], %[temp2] \n\t"
+ "raddu.w.qb %[temp3], %[temp3] \n\t"
+ "addu %[temp0], %[temp0], %[temp1] \n\t"
+ "addu %[temp2], %[temp2], %[temp3] \n\t"
+ "addu %[DC], %[temp0], %[temp2] \n\t"
+ "move %[DC1], %[DC] \n\t"
+ "beqz %[left], 1f \n\t"
+ LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, left,
+ 0, 4, 8, 12,
+ 0, 0, 0, 0,
+ 0)
+ "raddu.w.qb %[temp0], %[temp0] \n\t"
+ "raddu.w.qb %[temp1], %[temp1] \n\t"
+ "raddu.w.qb %[temp2], %[temp2] \n\t"
+ "raddu.w.qb %[temp3], %[temp3] \n\t"
+ "addu %[temp0], %[temp0], %[temp1] \n\t"
+ "addu %[temp2], %[temp2], %[temp3] \n\t"
+ "addu %[DC1], %[temp0], %[temp2] \n\t"
+ "1: \n\t"
+ "addu %[DC], %[DC], %[DC1] \n\t"
+ "j 3f \n\t"
+ "2: \n\t"
+ "beqz %[left], 4f \n\t"
+ LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, left,
+ 0, 4, 8, 12,
+ 0, 0, 0, 0,
+ 0)
+ "raddu.w.qb %[temp0], %[temp0] \n\t"
+ "raddu.w.qb %[temp1], %[temp1] \n\t"
+ "raddu.w.qb %[temp2], %[temp2] \n\t"
+ "raddu.w.qb %[temp3], %[temp3] \n\t"
+ "addu %[temp0], %[temp0], %[temp1] \n\t"
+ "addu %[temp2], %[temp2], %[temp3] \n\t"
+ "addu %[DC], %[temp0], %[temp2] \n\t"
+ "addu %[DC], %[DC], %[DC] \n\t"
+ "3: \n\t"
+ "shra_r.w %[DC], %[DC], 5 \n\t"
+ "j 5f \n\t"
+ "4: \n\t"
+ "li %[DC], 0x80 \n\t"
+ "5: \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [DC]"=&r"(DC),
+ [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [DC1]"=&r"(DC1)
+ : [left]"r"(left), [top]"r"(top)
+ : "memory"
+ );
+
+ FILL_8_OR_16(dst, DC, 16);
+}
+
+static WEBP_INLINE void DCMode8(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top) {
+ int DC, DC1;
+ int temp0, temp1, temp2, temp3;
+
+ __asm__ volatile(
+ "beqz %[top], 2f \n\t"
+ "ulw %[temp0], 0(%[top]) \n\t"
+ "ulw %[temp1], 4(%[top]) \n\t"
+ "raddu.w.qb %[temp0], %[temp0] \n\t"
+ "raddu.w.qb %[temp1], %[temp1] \n\t"
+ "addu %[DC], %[temp0], %[temp1] \n\t"
+ "move %[DC1], %[DC] \n\t"
+ "beqz %[left], 1f \n\t"
+ "ulw %[temp2], 0(%[left]) \n\t"
+ "ulw %[temp3], 4(%[left]) \n\t"
+ "raddu.w.qb %[temp2], %[temp2] \n\t"
+ "raddu.w.qb %[temp3], %[temp3] \n\t"
+ "addu %[DC1], %[temp2], %[temp3] \n\t"
+ "1: \n\t"
+ "addu %[DC], %[DC], %[DC1] \n\t"
+ "j 3f \n\t"
+ "2: \n\t"
+ "beqz %[left], 4f \n\t"
+ "ulw %[temp2], 0(%[left]) \n\t"
+ "ulw %[temp3], 4(%[left]) \n\t"
+ "raddu.w.qb %[temp2], %[temp2] \n\t"
+ "raddu.w.qb %[temp3], %[temp3] \n\t"
+ "addu %[DC], %[temp2], %[temp3] \n\t"
+ "addu %[DC], %[DC], %[DC] \n\t"
+ "3: \n\t"
+ "shra_r.w %[DC], %[DC], 4 \n\t"
+ "j 5f \n\t"
+ "4: \n\t"
+ "li %[DC], 0x80 \n\t"
+ "5: \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [DC]"=&r"(DC),
+ [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [DC1]"=&r"(DC1)
+ : [left]"r"(left), [top]"r"(top)
+ : "memory"
+ );
+
+ FILL_8_OR_16(dst, DC, 8);
+}
+
+static void DC4(uint8_t* dst, const uint8_t* top) {
+ int temp0, temp1;
+ __asm__ volatile(
+ "ulw %[temp0], 0(%[top]) \n\t"
+ "ulw %[temp1], -5(%[top]) \n\t"
+ "raddu.w.qb %[temp0], %[temp0] \n\t"
+ "raddu.w.qb %[temp1], %[temp1] \n\t"
+ "addu %[temp0], %[temp0], %[temp1] \n\t"
+ "addiu %[temp0], %[temp0], 4 \n\t"
+ "srl %[temp0], %[temp0], 3 \n\t"
+ "replv.qb %[temp0], %[temp0] \n\t"
+ "usw %[temp0], 0*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp0], 2*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp0], 3*" XSTR(BPS) "(%[dst]) \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1)
+ : [top]"r"(top), [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+static void TM4(uint8_t* dst, const uint8_t* top) {
+ int a10, a32, temp0, temp1, temp2, temp3, temp4, temp5;
+ const int c35 = 0xff00ff;
+ __asm__ volatile (
+ "lbu %[temp1], 0(%[top]) \n\t"
+ "lbu %[a10], 1(%[top]) \n\t"
+ "lbu %[temp2], 2(%[top]) \n\t"
+ "lbu %[a32], 3(%[top]) \n\t"
+ "ulw %[temp0], -5(%[top]) \n\t"
+ "lbu %[temp4], -1(%[top]) \n\t"
+ "append %[a10], %[temp1], 16 \n\t"
+ "append %[a32], %[temp2], 16 \n\t"
+ "replv.ph %[temp4], %[temp4] \n\t"
+ "shrl.ph %[temp1], %[temp0], 8 \n\t"
+ "and %[temp0], %[temp0], %[c35] \n\t"
+ "subu.ph %[temp1], %[temp1], %[temp4] \n\t"
+ "subu.ph %[temp0], %[temp0], %[temp4] \n\t"
+ "srl %[temp2], %[temp1], 16 \n\t"
+ "srl %[temp3], %[temp0], 16 \n\t"
+ "replv.ph %[temp2], %[temp2] \n\t"
+ "replv.ph %[temp3], %[temp3] \n\t"
+ "replv.ph %[temp4], %[temp1] \n\t"
+ "replv.ph %[temp5], %[temp0] \n\t"
+ "addu.ph %[temp0], %[temp3], %[a10] \n\t"
+ "addu.ph %[temp1], %[temp3], %[a32] \n\t"
+ "addu.ph %[temp3], %[temp2], %[a10] \n\t"
+ "addu.ph %[temp2], %[temp2], %[a32] \n\t"
+ "shll_s.ph %[temp0], %[temp0], 7 \n\t"
+ "shll_s.ph %[temp1], %[temp1], 7 \n\t"
+ "shll_s.ph %[temp3], %[temp3], 7 \n\t"
+ "shll_s.ph %[temp2], %[temp2], 7 \n\t"
+ "precrqu_s.qb.ph %[temp0], %[temp1], %[temp0] \n\t"
+ "precrqu_s.qb.ph %[temp1], %[temp2], %[temp3] \n\t"
+ "addu.ph %[temp2], %[temp5], %[a10] \n\t"
+ "addu.ph %[temp3], %[temp5], %[a32] \n\t"
+ "addu.ph %[temp5], %[temp4], %[a10] \n\t"
+ "addu.ph %[temp4], %[temp4], %[a32] \n\t"
+ "shll_s.ph %[temp2], %[temp2], 7 \n\t"
+ "shll_s.ph %[temp3], %[temp3], 7 \n\t"
+ "shll_s.ph %[temp4], %[temp4], 7 \n\t"
+ "shll_s.ph %[temp5], %[temp5], 7 \n\t"
+ "precrqu_s.qb.ph %[temp2], %[temp3], %[temp2] \n\t"
+ "precrqu_s.qb.ph %[temp3], %[temp4], %[temp5] \n\t"
+ "usw %[temp1], 0*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp3], 2*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp2], 3*" XSTR(BPS) "(%[dst]) \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [a10]"=&r"(a10), [a32]"=&r"(a32)
+ : [c35]"r"(c35), [top]"r"(top), [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+static void VE4(uint8_t* dst, const uint8_t* top) {
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6;
+ __asm__ volatile(
+ "ulw %[temp0], -1(%[top]) \n\t"
+ "ulh %[temp1], 3(%[top]) \n\t"
+ "preceu.ph.qbr %[temp2], %[temp0] \n\t"
+ "preceu.ph.qbl %[temp3], %[temp0] \n\t"
+ "preceu.ph.qbr %[temp4], %[temp1] \n\t"
+ "packrl.ph %[temp5], %[temp3], %[temp2] \n\t"
+ "packrl.ph %[temp6], %[temp4], %[temp3] \n\t"
+ "shll.ph %[temp5], %[temp5], 1 \n\t"
+ "shll.ph %[temp6], %[temp6], 1 \n\t"
+ "addq.ph %[temp2], %[temp5], %[temp2] \n\t"
+ "addq.ph %[temp6], %[temp6], %[temp4] \n\t"
+ "addq.ph %[temp2], %[temp2], %[temp3] \n\t"
+ "addq.ph %[temp6], %[temp6], %[temp3] \n\t"
+ "shra_r.ph %[temp2], %[temp2], 2 \n\t"
+ "shra_r.ph %[temp6], %[temp6], 2 \n\t"
+ "precr.qb.ph %[temp4], %[temp6], %[temp2] \n\t"
+ "usw %[temp4], 0*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp4], 1*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp4], 2*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp4], 3*" XSTR(BPS) "(%[dst]) \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6)
+ : [top]"r"(top), [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+static void HE4(uint8_t* dst, const uint8_t* top) {
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6;
+ __asm__ volatile(
+ "ulw %[temp0], -4(%[top]) \n\t"
+ "lbu %[temp1], -5(%[top]) \n\t"
+ "preceu.ph.qbr %[temp2], %[temp0] \n\t"
+ "preceu.ph.qbl %[temp3], %[temp0] \n\t"
+ "replv.ph %[temp4], %[temp1] \n\t"
+ "packrl.ph %[temp5], %[temp3], %[temp2] \n\t"
+ "packrl.ph %[temp6], %[temp2], %[temp4] \n\t"
+ "shll.ph %[temp5], %[temp5], 1 \n\t"
+ "shll.ph %[temp6], %[temp6], 1 \n\t"
+ "addq.ph %[temp3], %[temp3], %[temp5] \n\t"
+ "addq.ph %[temp3], %[temp3], %[temp2] \n\t"
+ "addq.ph %[temp2], %[temp2], %[temp6] \n\t"
+ "addq.ph %[temp2], %[temp2], %[temp4] \n\t"
+ "shra_r.ph %[temp3], %[temp3], 2 \n\t"
+ "shra_r.ph %[temp2], %[temp2], 2 \n\t"
+ "replv.qb %[temp0], %[temp3] \n\t"
+ "replv.qb %[temp1], %[temp2] \n\t"
+ "srl %[temp3], %[temp3], 16 \n\t"
+ "srl %[temp2], %[temp2], 16 \n\t"
+ "replv.qb %[temp3], %[temp3] \n\t"
+ "replv.qb %[temp2], %[temp2] \n\t"
+ "usw %[temp3], 0*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp2], 2*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp1], 3*" XSTR(BPS) "(%[dst]) \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6)
+ : [top]"r"(top), [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+static void RD4(uint8_t* dst, const uint8_t* top) {
+ int temp0, temp1, temp2, temp3, temp4, temp5;
+ int temp6, temp7, temp8, temp9, temp10, temp11;
+ __asm__ volatile(
+ "ulw %[temp0], -5(%[top]) \n\t"
+ "ulw %[temp1], -1(%[top]) \n\t"
+ "preceu.ph.qbl %[temp2], %[temp0] \n\t"
+ "preceu.ph.qbr %[temp3], %[temp0] \n\t"
+ "preceu.ph.qbr %[temp4], %[temp1] \n\t"
+ "preceu.ph.qbl %[temp5], %[temp1] \n\t"
+ "packrl.ph %[temp6], %[temp2], %[temp3] \n\t"
+ "packrl.ph %[temp7], %[temp4], %[temp2] \n\t"
+ "packrl.ph %[temp8], %[temp5], %[temp4] \n\t"
+ "shll.ph %[temp6], %[temp6], 1 \n\t"
+ "addq.ph %[temp9], %[temp2], %[temp6] \n\t"
+ "shll.ph %[temp7], %[temp7], 1 \n\t"
+ "addq.ph %[temp9], %[temp9], %[temp3] \n\t"
+ "shll.ph %[temp8], %[temp8], 1 \n\t"
+ "shra_r.ph %[temp9], %[temp9], 2 \n\t"
+ "addq.ph %[temp10], %[temp4], %[temp7] \n\t"
+ "addq.ph %[temp11], %[temp5], %[temp8] \n\t"
+ "addq.ph %[temp10], %[temp10], %[temp2] \n\t"
+ "addq.ph %[temp11], %[temp11], %[temp4] \n\t"
+ "shra_r.ph %[temp10], %[temp10], 2 \n\t"
+ "shra_r.ph %[temp11], %[temp11], 2 \n\t"
+ "lbu %[temp0], 3(%[top]) \n\t"
+ "lbu %[temp1], 2(%[top]) \n\t"
+ "lbu %[temp2], 1(%[top]) \n\t"
+ "sll %[temp1], %[temp1], 1 \n\t"
+ "addu %[temp0], %[temp0], %[temp1] \n\t"
+ "addu %[temp0], %[temp0], %[temp2] \n\t"
+ "precr.qb.ph %[temp9], %[temp10], %[temp9] \n\t"
+ "shra_r.w %[temp0], %[temp0], 2 \n\t"
+ "precr.qb.ph %[temp10], %[temp11], %[temp10] \n\t"
+ "usw %[temp9], 3*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp10], 1*" XSTR(BPS) "(%[dst]) \n\t"
+ "prepend %[temp9], %[temp11], 8 \n\t"
+ "prepend %[temp10], %[temp0], 8 \n\t"
+ "usw %[temp9], 2*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp10], 0*" XSTR(BPS) "(%[dst]) \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
+ [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11)
+ : [top]"r"(top), [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+static void VR4(uint8_t* dst, const uint8_t* top) {
+ int temp0, temp1, temp2, temp3, temp4;
+ int temp5, temp6, temp7, temp8, temp9;
+ __asm__ volatile (
+ "ulw %[temp0], -4(%[top]) \n\t"
+ "ulw %[temp1], 0(%[top]) \n\t"
+ "preceu.ph.qbl %[temp2], %[temp0] \n\t"
+ "preceu.ph.qbr %[temp0], %[temp0] \n\t"
+ "preceu.ph.qbla %[temp3], %[temp1] \n\t"
+ "preceu.ph.qbra %[temp1], %[temp1] \n\t"
+ "packrl.ph %[temp7], %[temp3], %[temp2] \n\t"
+ "addqh_r.ph %[temp4], %[temp1], %[temp3] \n\t"
+ "move %[temp6], %[temp1] \n\t"
+ "append %[temp1], %[temp2], 16 \n\t"
+ "shll.ph %[temp9], %[temp6], 1 \n\t"
+ "addqh_r.ph %[temp5], %[temp7], %[temp6] \n\t"
+ "shll.ph %[temp8], %[temp7], 1 \n\t"
+ "addu.ph %[temp3], %[temp7], %[temp3] \n\t"
+ "addu.ph %[temp1], %[temp1], %[temp6] \n\t"
+ "packrl.ph %[temp7], %[temp2], %[temp0] \n\t"
+ "addu.ph %[temp6], %[temp0], %[temp2] \n\t"
+ "addu.ph %[temp3], %[temp3], %[temp9] \n\t"
+ "addu.ph %[temp1], %[temp1], %[temp8] \n\t"
+ "shll.ph %[temp7], %[temp7], 1 \n\t"
+ "shra_r.ph %[temp3], %[temp3], 2 \n\t"
+ "shra_r.ph %[temp1], %[temp1], 2 \n\t"
+ "addu.ph %[temp6], %[temp6], %[temp7] \n\t"
+ "shra_r.ph %[temp6], %[temp6], 2 \n\t"
+ "precrq.ph.w %[temp8], %[temp4], %[temp5] \n\t"
+ "append %[temp4], %[temp5], 16 \n\t"
+ "precrq.ph.w %[temp2], %[temp3], %[temp1] \n\t"
+ "append %[temp3], %[temp1], 16 \n\t"
+ "precr.qb.ph %[temp8], %[temp8], %[temp4] \n\t"
+ "precr.qb.ph %[temp3], %[temp2], %[temp3] \n\t"
+ "usw %[temp8], 0*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp3], 1*" XSTR(BPS) "(%[dst]) \n\t"
+ "append %[temp3], %[temp6], 8 \n\t"
+ "srl %[temp6], %[temp6], 16 \n\t"
+ "append %[temp8], %[temp6], 8 \n\t"
+ "usw %[temp3], 3*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp8], 2*" XSTR(BPS) "(%[dst]) \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
+ [temp9]"=&r"(temp9)
+ : [top]"r"(top), [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+static void LD4(uint8_t* dst, const uint8_t* top) {
+ int temp0, temp1, temp2, temp3, temp4, temp5;
+ int temp6, temp7, temp8, temp9, temp10, temp11;
+ __asm__ volatile(
+ "ulw %[temp0], 0(%[top]) \n\t"
+ "ulw %[temp1], 4(%[top]) \n\t"
+ "preceu.ph.qbl %[temp2], %[temp0] \n\t"
+ "preceu.ph.qbr %[temp3], %[temp0] \n\t"
+ "preceu.ph.qbr %[temp4], %[temp1] \n\t"
+ "preceu.ph.qbl %[temp5], %[temp1] \n\t"
+ "packrl.ph %[temp6], %[temp2], %[temp3] \n\t"
+ "packrl.ph %[temp7], %[temp4], %[temp2] \n\t"
+ "packrl.ph %[temp8], %[temp5], %[temp4] \n\t"
+ "shll.ph %[temp6], %[temp6], 1 \n\t"
+ "addq.ph %[temp9], %[temp2], %[temp6] \n\t"
+ "shll.ph %[temp7], %[temp7], 1 \n\t"
+ "addq.ph %[temp9], %[temp9], %[temp3] \n\t"
+ "shll.ph %[temp8], %[temp8], 1 \n\t"
+ "shra_r.ph %[temp9], %[temp9], 2 \n\t"
+ "addq.ph %[temp10], %[temp4], %[temp7] \n\t"
+ "addq.ph %[temp11], %[temp5], %[temp8] \n\t"
+ "addq.ph %[temp10], %[temp10], %[temp2] \n\t"
+ "addq.ph %[temp11], %[temp11], %[temp4] \n\t"
+ "shra_r.ph %[temp10], %[temp10], 2 \n\t"
+ "shra_r.ph %[temp11], %[temp11], 2 \n\t"
+ "srl %[temp1], %[temp1], 24 \n\t"
+ "sll %[temp1], %[temp1], 1 \n\t"
+ "raddu.w.qb %[temp5], %[temp5] \n\t"
+ "precr.qb.ph %[temp9], %[temp10], %[temp9] \n\t"
+ "precr.qb.ph %[temp10], %[temp11], %[temp10] \n\t"
+ "addu %[temp1], %[temp1], %[temp5] \n\t"
+ "shra_r.w %[temp1], %[temp1], 2 \n\t"
+ "usw %[temp9], 0*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp10], 2*" XSTR(BPS) "(%[dst]) \n\t"
+ "prepend %[temp9], %[temp11], 8 \n\t"
+ "prepend %[temp10], %[temp1], 8 \n\t"
+ "usw %[temp9], 1*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp10], 3*" XSTR(BPS) "(%[dst]) \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
+ [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11)
+ : [top]"r"(top), [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+static void VL4(uint8_t* dst, const uint8_t* top) {
+ int temp0, temp1, temp2, temp3, temp4;
+ int temp5, temp6, temp7, temp8, temp9;
+ __asm__ volatile (
+ "ulw %[temp0], 0(%[top]) \n\t"
+ "ulw %[temp1], 4(%[top]) \n\t"
+ "preceu.ph.qbla %[temp2], %[temp0] \n\t"
+ "preceu.ph.qbra %[temp0], %[temp0] \n\t"
+ "preceu.ph.qbl %[temp3], %[temp1] \n\t"
+ "preceu.ph.qbr %[temp1], %[temp1] \n\t"
+ "addqh_r.ph %[temp4], %[temp0], %[temp2] \n\t"
+ "packrl.ph %[temp7], %[temp1], %[temp0] \n\t"
+ "precrq.ph.w %[temp6], %[temp1], %[temp2] \n\t"
+ "shll.ph %[temp9], %[temp2], 1 \n\t"
+ "addqh_r.ph %[temp5], %[temp7], %[temp2] \n\t"
+ "shll.ph %[temp8], %[temp7], 1 \n\t"
+ "addu.ph %[temp2], %[temp2], %[temp6] \n\t"
+ "addu.ph %[temp0], %[temp0], %[temp7] \n\t"
+ "packrl.ph %[temp7], %[temp3], %[temp1] \n\t"
+ "addu.ph %[temp6], %[temp1], %[temp3] \n\t"
+ "addu.ph %[temp2], %[temp2], %[temp8] \n\t"
+ "addu.ph %[temp0], %[temp0], %[temp9] \n\t"
+ "shll.ph %[temp7], %[temp7], 1 \n\t"
+ "shra_r.ph %[temp2], %[temp2], 2 \n\t"
+ "shra_r.ph %[temp0], %[temp0], 2 \n\t"
+ "addu.ph %[temp6], %[temp6], %[temp7] \n\t"
+ "shra_r.ph %[temp6], %[temp6], 2 \n\t"
+ "precrq.ph.w %[temp8], %[temp5], %[temp4] \n\t"
+ "append %[temp5], %[temp4], 16 \n\t"
+ "precrq.ph.w %[temp3], %[temp2], %[temp0] \n\t"
+ "append %[temp2], %[temp0], 16 \n\t"
+ "precr.qb.ph %[temp8], %[temp8], %[temp5] \n\t"
+ "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t"
+ "usw %[temp8], 0*" XSTR(BPS) "(%[dst]) \n\t"
+ "prepend %[temp8], %[temp6], 8 \n\t"
+ "usw %[temp3], 1*" XSTR(BPS) "(%[dst]) \n\t"
+ "srl %[temp6], %[temp6], 16 \n\t"
+ "prepend %[temp3], %[temp6], 8 \n\t"
+ "usw %[temp8], 2*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp3], 3*" XSTR(BPS) "(%[dst]) \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
+ [temp9]"=&r"(temp9)
+ : [top]"r"(top), [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+static void HD4(uint8_t* dst, const uint8_t* top) {
+ int temp0, temp1, temp2, temp3, temp4;
+ int temp5, temp6, temp7, temp8, temp9;
+ __asm__ volatile (
+ "ulw %[temp0], -5(%[top]) \n\t"
+ "ulw %[temp1], -1(%[top]) \n\t"
+ "preceu.ph.qbla %[temp2], %[temp0] \n\t"
+ "preceu.ph.qbra %[temp0], %[temp0] \n\t"
+ "preceu.ph.qbl %[temp3], %[temp1] \n\t"
+ "preceu.ph.qbr %[temp1], %[temp1] \n\t"
+ "addqh_r.ph %[temp4], %[temp0], %[temp2] \n\t"
+ "packrl.ph %[temp7], %[temp1], %[temp0] \n\t"
+ "precrq.ph.w %[temp6], %[temp1], %[temp2] \n\t"
+ "shll.ph %[temp9], %[temp2], 1 \n\t"
+ "addqh_r.ph %[temp5], %[temp7], %[temp2] \n\t"
+ "shll.ph %[temp8], %[temp7], 1 \n\t"
+ "addu.ph %[temp2], %[temp2], %[temp6] \n\t"
+ "addu.ph %[temp0], %[temp0], %[temp7] \n\t"
+ "packrl.ph %[temp7], %[temp3], %[temp1] \n\t"
+ "addu.ph %[temp6], %[temp1], %[temp3] \n\t"
+ "addu.ph %[temp2], %[temp2], %[temp8] \n\t"
+ "addu.ph %[temp0], %[temp0], %[temp9] \n\t"
+ "shll.ph %[temp7], %[temp7], 1 \n\t"
+ "shra_r.ph %[temp2], %[temp2], 2 \n\t"
+ "shra_r.ph %[temp0], %[temp0], 2 \n\t"
+ "addu.ph %[temp6], %[temp6], %[temp7] \n\t"
+ "shra_r.ph %[temp6], %[temp6], 2 \n\t"
+ "precrq.ph.w %[temp1], %[temp2], %[temp5] \n\t"
+ "precrq.ph.w %[temp3], %[temp0], %[temp4] \n\t"
+ "precr.qb.ph %[temp7], %[temp6], %[temp1] \n\t"
+ "precr.qb.ph %[temp6], %[temp1], %[temp3] \n\t"
+ "usw %[temp7], 0*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp6], 1*" XSTR(BPS) "(%[dst]) \n\t"
+ "append %[temp2], %[temp5], 16 \n\t"
+ "append %[temp0], %[temp4], 16 \n\t"
+ "precr.qb.ph %[temp5], %[temp3], %[temp2] \n\t"
+ "precr.qb.ph %[temp4], %[temp2], %[temp0] \n\t"
+ "usw %[temp5], 2*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp4], 3*" XSTR(BPS) "(%[dst]) \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
+ [temp9]"=&r"(temp9)
+ : [top]"r"(top), [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+static void HU4(uint8_t* dst, const uint8_t* top) {
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
+ __asm__ volatile (
+ "ulw %[temp0], -5(%[top]) \n\t"
+ "preceu.ph.qbl %[temp1], %[temp0] \n\t"
+ "preceu.ph.qbr %[temp2], %[temp0] \n\t"
+ "packrl.ph %[temp3], %[temp1], %[temp2] \n\t"
+ "replv.qb %[temp7], %[temp2] \n\t"
+ "addqh_r.ph %[temp4], %[temp1], %[temp3] \n\t"
+ "addqh_r.ph %[temp5], %[temp3], %[temp2] \n\t"
+ "shll.ph %[temp6], %[temp3], 1 \n\t"
+ "addu.ph %[temp3], %[temp2], %[temp3] \n\t"
+ "addu.ph %[temp6], %[temp1], %[temp6] \n\t"
+ "shll.ph %[temp0], %[temp2], 1 \n\t"
+ "addu.ph %[temp6], %[temp6], %[temp2] \n\t"
+ "addu.ph %[temp0], %[temp3], %[temp0] \n\t"
+ "shra_r.ph %[temp6], %[temp6], 2 \n\t"
+ "shra_r.ph %[temp0], %[temp0], 2 \n\t"
+ "packrl.ph %[temp3], %[temp6], %[temp5] \n\t"
+ "precrq.ph.w %[temp2], %[temp6], %[temp4] \n\t"
+ "append %[temp0], %[temp5], 16 \n\t"
+ "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t"
+ "usw %[temp3], 0*" XSTR(BPS) "(%[dst]) \n\t"
+ "precr.qb.ph %[temp1], %[temp7], %[temp0] \n\t"
+ "usw %[temp7], 3*" XSTR(BPS) "(%[dst]) \n\t"
+ "packrl.ph %[temp2], %[temp1], %[temp3] \n\t"
+ "usw %[temp1], 2*" XSTR(BPS) "(%[dst]) \n\t"
+ "usw %[temp2], 1*" XSTR(BPS) "(%[dst]) \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7)
+ : [top]"r"(top), [dst]"r"(dst)
+ : "memory"
+ );
+}
+
+//------------------------------------------------------------------------------
+// Chroma 8x8 prediction (paragraph 12.2)
+
+static void IntraChromaPreds(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top) {
+ // U block
+ DCMode8(C8DC8 + dst, left, top);
+ VerticalPred8(C8VE8 + dst, top);
+ HorizontalPred8(C8HE8 + dst, left);
+ TrueMotion8(C8TM8 + dst, left, top);
+ // V block
+ dst += 8;
+ if (top) top += 8;
+ if (left) left += 16;
+ DCMode8(C8DC8 + dst, left, top);
+ VerticalPred8(C8VE8 + dst, top);
+ HorizontalPred8(C8HE8 + dst, left);
+ TrueMotion8(C8TM8 + dst, left, top);
+}
+
+//------------------------------------------------------------------------------
+// luma 16x16 prediction (paragraph 12.3)
+
+static void Intra16Preds(uint8_t* dst,
+ const uint8_t* left, const uint8_t* top) {
+ DCMode16(I16DC16 + dst, left, top);
+ VerticalPred16(I16VE16 + dst, top);
+ HorizontalPred16(I16HE16 + dst, left);
+ TrueMotion16(I16TM16 + dst, left, top);
+}
+
+// Left samples are top[-5 .. -2], top_left is top[-1], top are
+// located at top[0..3], and top right is top[4..7]
+static void Intra4Preds(uint8_t* dst, const uint8_t* top) {
+ DC4(I4DC4 + dst, top);
+ TM4(I4TM4 + dst, top);
+ VE4(I4VE4 + dst, top);
+ HE4(I4HE4 + dst, top);
+ RD4(I4RD4 + dst, top);
+ VR4(I4VR4 + dst, top);
+ LD4(I4LD4 + dst, top);
+ VL4(I4VL4 + dst, top);
+ HD4(I4HD4 + dst, top);
+ HU4(I4HU4 + dst, top);
+}
+
+//------------------------------------------------------------------------------
+// Metric
+
+#if !defined(WORK_AROUND_GCC)
+
+#define GET_SSE_INNER(A) \
+ "lw %[temp0], " #A "(%[a]) \n\t" \
+ "lw %[temp1], " #A "(%[b]) \n\t" \
+ "preceu.ph.qbr %[temp2], %[temp0] \n\t" \
+ "preceu.ph.qbl %[temp0], %[temp0] \n\t" \
+ "preceu.ph.qbr %[temp3], %[temp1] \n\t" \
+ "preceu.ph.qbl %[temp1], %[temp1] \n\t" \
+ "subq.ph %[temp2], %[temp2], %[temp3] \n\t" \
+ "subq.ph %[temp0], %[temp0], %[temp1] \n\t" \
+ "dpa.w.ph $ac0, %[temp2], %[temp2] \n\t" \
+ "dpa.w.ph $ac0, %[temp0], %[temp0] \n\t"
+
+#define GET_SSE(A, B, C, D) \
+ GET_SSE_INNER(A) \
+ GET_SSE_INNER(B) \
+ GET_SSE_INNER(C) \
+ GET_SSE_INNER(D)
+
+static int SSE16x16(const uint8_t* a, const uint8_t* b) {
+ int count;
+ int temp0, temp1, temp2, temp3;
+ __asm__ volatile (
+ "mult $zero, $zero \n\t"
+ GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS)
+ GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS)
+ GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS)
+ GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS)
+ GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS)
+ GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS)
+ GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS)
+ GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS)
+ GET_SSE( 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS)
+ GET_SSE( 9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS)
+ GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS)
+ GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS)
+ GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS)
+ GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS)
+ GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS)
+ GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS)
+ "mflo %[count] \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [count]"=&r"(count)
+ : [a]"r"(a), [b]"r"(b)
+ : "memory", "hi", "lo"
+ );
+ return count;
+}
+
+static int SSE16x8(const uint8_t* a, const uint8_t* b) {
+ int count;
+ int temp0, temp1, temp2, temp3;
+ __asm__ volatile (
+ "mult $zero, $zero \n\t"
+ GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS)
+ GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS)
+ GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS)
+ GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS)
+ GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS)
+ GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS)
+ GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS)
+ GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS)
+ "mflo %[count] \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [count]"=&r"(count)
+ : [a]"r"(a), [b]"r"(b)
+ : "memory", "hi", "lo"
+ );
+ return count;
+}
+
+static int SSE8x8(const uint8_t* a, const uint8_t* b) {
+ int count;
+ int temp0, temp1, temp2, temp3;
+ __asm__ volatile (
+ "mult $zero, $zero \n\t"
+ GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS)
+ GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS)
+ GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS)
+ GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS)
+ "mflo %[count] \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [count]"=&r"(count)
+ : [a]"r"(a), [b]"r"(b)
+ : "memory", "hi", "lo"
+ );
+ return count;
+}
+
+static int SSE4x4(const uint8_t* a, const uint8_t* b) {
+ int count;
+ int temp0, temp1, temp2, temp3;
+ __asm__ volatile (
+ "mult $zero, $zero \n\t"
+ GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS)
+ "mflo %[count] \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [count]"=&r"(count)
+ : [a]"r"(a), [b]"r"(b)
+ : "memory", "hi", "lo"
+ );
+ return count;
+}
+
+#undef GET_SSE
+#undef GET_SSE_INNER
+
+#endif // !WORK_AROUND_GCC
+
+#undef FILL_8_OR_16
+#undef FILL_PART
+#undef OUTPUT_EARLY_CLOBBER_REGS_17
+#undef MUL_HALF
+#undef ABS_X8
+#undef ADD_SUB_HALVES_X4
+
+//------------------------------------------------------------------------------
+// Quantization
+//
+
+// macro for one pass through for loop in QuantizeBlock reading 2 values at time
+// QUANTDIV macro inlined
+// J - offset in bytes (kZigzag[n] * 2)
+// K - offset in bytes (kZigzag[n] * 4)
+// N - offset in bytes (n * 2)
+// N1 - offset in bytes ((n + 1) * 2)
+#define QUANTIZE_ONE(J, K, N, N1) \
+ "ulw %[temp1], " #J "(%[ppin]) \n\t" \
+ "ulw %[temp2], " #J "(%[ppsharpen]) \n\t" \
+ "lhu %[temp3], " #K "(%[ppzthresh]) \n\t" \
+ "lhu %[temp6], " #K "+4(%[ppzthresh]) \n\t" \
+ "absq_s.ph %[temp4], %[temp1] \n\t" \
+ "ins %[temp3], %[temp6], 16, 16 \n\t" \
+ "addu.ph %[coeff], %[temp4], %[temp2] \n\t" \
+ "shra.ph %[sign], %[temp1], 15 \n\t" \
+ "li %[level], 0x10001 \n\t" \
+ "cmp.lt.ph %[temp3], %[coeff] \n\t" \
+ "lhu %[temp1], " #J "(%[ppiq]) \n\t" \
+ "pick.ph %[temp5], %[level], $0 \n\t" \
+ "lw %[temp2], " #K "(%[ppbias]) \n\t" \
+ "beqz %[temp5], 0f \n\t" \
+ "lhu %[temp3], " #J "(%[ppq]) \n\t" \
+ "beq %[temp5], %[level], 1f \n\t" \
+ "andi %[temp5], %[temp5], 0x1 \n\t" \
+ "andi %[temp4], %[coeff], 0xffff \n\t" \
+ "beqz %[temp5], 2f \n\t" \
+ "mul %[level], %[temp4], %[temp1] \n\t" \
+ "sh $0, " #J "+2(%[ppin]) \n\t" \
+ "sh $0, " #N1 "(%[pout]) \n\t" \
+ "addu %[level], %[level], %[temp2] \n\t" \
+ "sra %[level], %[level], 17 \n\t" \
+ "slt %[temp4], %[max_level], %[level] \n\t" \
+ "movn %[level], %[max_level], %[temp4] \n\t" \
+ "andi %[temp6], %[sign], 0xffff \n\t" \
+ "xor %[level], %[level], %[temp6] \n\t" \
+ "subu %[level], %[level], %[temp6] \n\t" \
+ "mul %[temp5], %[level], %[temp3] \n\t" \
+ "or %[ret], %[ret], %[level] \n\t" \
+ "sh %[level], " #N "(%[pout]) \n\t" \
+ "sh %[temp5], " #J "(%[ppin]) \n\t" \
+ "j 3f \n\t" \
+"2: \n\t" \
+ "lhu %[temp1], " #J "+2(%[ppiq]) \n\t" \
+ "srl %[temp5], %[coeff], 16 \n\t" \
+ "mul %[level], %[temp5], %[temp1] \n\t" \
+ "lw %[temp2], " #K "+4(%[ppbias]) \n\t" \
+ "lhu %[temp3], " #J "+2(%[ppq]) \n\t" \
+ "addu %[level], %[level], %[temp2] \n\t" \
+ "sra %[level], %[level], 17 \n\t" \
+ "srl %[temp6], %[sign], 16 \n\t" \
+ "slt %[temp4], %[max_level], %[level] \n\t" \
+ "movn %[level], %[max_level], %[temp4] \n\t" \
+ "xor %[level], %[level], %[temp6] \n\t" \
+ "subu %[level], %[level], %[temp6] \n\t" \
+ "mul %[temp5], %[level], %[temp3] \n\t" \
+ "sh $0, " #J "(%[ppin]) \n\t" \
+ "sh $0, " #N "(%[pout]) \n\t" \
+ "or %[ret], %[ret], %[level] \n\t" \
+ "sh %[temp5], " #J "+2(%[ppin]) \n\t" \
+ "sh %[level], " #N1 "(%[pout]) \n\t" \
+ "j 3f \n\t" \
+"1: \n\t" \
+ "lhu %[temp1], " #J "(%[ppiq]) \n\t" \
+ "lw %[temp2], " #K "(%[ppbias]) \n\t" \
+ "ulw %[temp3], " #J "(%[ppq]) \n\t" \
+ "andi %[temp5], %[coeff], 0xffff \n\t" \
+ "srl %[temp0], %[coeff], 16 \n\t" \
+ "lhu %[temp6], " #J "+2(%[ppiq]) \n\t" \
+ "lw %[coeff], " #K "+4(%[ppbias]) \n\t" \
+ "mul %[level], %[temp5], %[temp1] \n\t" \
+ "mul %[temp4], %[temp0], %[temp6] \n\t" \
+ "addu %[level], %[level], %[temp2] \n\t" \
+ "addu %[temp4], %[temp4], %[coeff] \n\t" \
+ "precrq.ph.w %[level], %[temp4], %[level] \n\t" \
+ "shra.ph %[level], %[level], 1 \n\t" \
+ "cmp.lt.ph %[max_level1],%[level] \n\t" \
+ "pick.ph %[level], %[max_level], %[level] \n\t" \
+ "xor %[level], %[level], %[sign] \n\t" \
+ "subu.ph %[level], %[level], %[sign] \n\t" \
+ "mul.ph %[temp3], %[level], %[temp3] \n\t" \
+ "or %[ret], %[ret], %[level] \n\t" \
+ "sh %[level], " #N "(%[pout]) \n\t" \
+ "srl %[level], %[level], 16 \n\t" \
+ "sh %[level], " #N1 "(%[pout]) \n\t" \
+ "usw %[temp3], " #J "(%[ppin]) \n\t" \
+ "j 3f \n\t" \
+"0: \n\t" \
+ "sh $0, " #N "(%[pout]) \n\t" \
+ "sh $0, " #N1 "(%[pout]) \n\t" \
+ "usw $0, " #J "(%[ppin]) \n\t" \
+"3: \n\t"
+
+static int QuantizeBlock(int16_t in[16], int16_t out[16],
+ const VP8Matrix* const mtx) {
+ int temp0, temp1, temp2, temp3, temp4, temp5,temp6;
+ int sign, coeff, level;
+ int max_level = MAX_LEVEL;
+ int max_level1 = max_level << 16 | max_level;
+ int ret = 0;
+
+ int16_t* ppin = &in[0];
+ int16_t* pout = &out[0];
+ const uint16_t* ppsharpen = &mtx->sharpen_[0];
+ const uint32_t* ppzthresh = &mtx->zthresh_[0];
+ const uint16_t* ppq = &mtx->q_[0];
+ const uint16_t* ppiq = &mtx->iq_[0];
+ const uint32_t* ppbias = &mtx->bias_[0];
+
+ __asm__ volatile (
+ QUANTIZE_ONE( 0, 0, 0, 2)
+ QUANTIZE_ONE( 4, 8, 10, 12)
+ QUANTIZE_ONE( 8, 16, 4, 8)
+ QUANTIZE_ONE(12, 24, 14, 24)
+ QUANTIZE_ONE(16, 32, 6, 16)
+ QUANTIZE_ONE(20, 40, 22, 26)
+ QUANTIZE_ONE(24, 48, 18, 20)
+ QUANTIZE_ONE(28, 56, 28, 30)
+
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
+ [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [sign]"=&r"(sign), [coeff]"=&r"(coeff),
+ [level]"=&r"(level), [temp6]"=&r"(temp6), [ret]"+&r"(ret)
+ : [ppin]"r"(ppin), [pout]"r"(pout), [max_level1]"r"(max_level1),
+ [ppiq]"r"(ppiq), [max_level]"r"(max_level),
+ [ppbias]"r"(ppbias), [ppzthresh]"r"(ppzthresh),
+ [ppsharpen]"r"(ppsharpen), [ppq]"r"(ppq)
+ : "memory", "hi", "lo"
+ );
+
+ return (ret != 0);
+}
+
+static int Quantize2Blocks(int16_t in[32], int16_t out[32],
+ const VP8Matrix* const mtx) {
+ int nz;
+ nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0;
+ nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1;
+ return nz;
+}
+
+#undef QUANTIZE_ONE
+
+// macro for one horizontal pass in FTransformWHT
+// temp0..temp7 holds tmp[0]..tmp[15]
+// A, B, C, D - offset in bytes to load from in buffer
+// TEMP0, TEMP1 - registers for corresponding tmp elements
+#define HORIZONTAL_PASS_WHT(A, B, C, D, TEMP0, TEMP1) \
+ "lh %[" #TEMP0 "], " #A "(%[in]) \n\t" \
+ "lh %[" #TEMP1 "], " #B "(%[in]) \n\t" \
+ "lh %[temp8], " #C "(%[in]) \n\t" \
+ "lh %[temp9], " #D "(%[in]) \n\t" \
+ "ins %[" #TEMP1 "], %[" #TEMP0 "], 16, 16 \n\t" \
+ "ins %[temp9], %[temp8], 16, 16 \n\t" \
+ "subq.ph %[temp8], %[" #TEMP1 "], %[temp9] \n\t" \
+ "addq.ph %[temp9], %[" #TEMP1 "], %[temp9] \n\t" \
+ "precrq.ph.w %[" #TEMP0 "], %[temp8], %[temp9] \n\t" \
+ "append %[temp8], %[temp9], 16 \n\t" \
+ "subq.ph %[" #TEMP1 "], %[" #TEMP0 "], %[temp8] \n\t" \
+ "addq.ph %[" #TEMP0 "], %[" #TEMP0 "], %[temp8] \n\t" \
+ "rotr %[" #TEMP1 "], %[" #TEMP1 "], 16 \n\t"
+
+// macro for one vertical pass in FTransformWHT
+// temp0..temp7 holds tmp[0]..tmp[15]
+// A, B, C, D - offsets in bytes to store to out buffer
+// TEMP0, TEMP2, TEMP4 and TEMP6 - registers for corresponding tmp elements
+#define VERTICAL_PASS_WHT(A, B, C, D, TEMP0, TEMP2, TEMP4, TEMP6) \
+ "addq.ph %[temp8], %[" #TEMP0 "], %[" #TEMP4 "] \n\t" \
+ "addq.ph %[temp9], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \
+ "subq.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \
+ "subq.ph %[" #TEMP6 "], %[" #TEMP0 "], %[" #TEMP4 "] \n\t" \
+ "addqh.ph %[" #TEMP0 "], %[temp8], %[temp9] \n\t" \
+ "subqh.ph %[" #TEMP4 "], %[" #TEMP6 "], %[" #TEMP2 "] \n\t" \
+ "addqh.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \
+ "subqh.ph %[" #TEMP6 "], %[temp8], %[temp9] \n\t" \
+ "usw %[" #TEMP0 "], " #A "(%[out]) \n\t" \
+ "usw %[" #TEMP2 "], " #B "(%[out]) \n\t" \
+ "usw %[" #TEMP4 "], " #C "(%[out]) \n\t" \
+ "usw %[" #TEMP6 "], " #D "(%[out]) \n\t"
+
+static void FTransformWHT(const int16_t* in, int16_t* out) {
+ int temp0, temp1, temp2, temp3, temp4;
+ int temp5, temp6, temp7, temp8, temp9;
+
+ __asm__ volatile (
+ HORIZONTAL_PASS_WHT( 0, 32, 64, 96, temp0, temp1)
+ HORIZONTAL_PASS_WHT(128, 160, 192, 224, temp2, temp3)
+ HORIZONTAL_PASS_WHT(256, 288, 320, 352, temp4, temp5)
+ HORIZONTAL_PASS_WHT(384, 416, 448, 480, temp6, temp7)
+ VERTICAL_PASS_WHT(0, 8, 16, 24, temp0, temp2, temp4, temp6)
+ VERTICAL_PASS_WHT(4, 12, 20, 28, temp1, temp3, temp5, temp7)
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
+ [temp9]"=&r"(temp9)
+ : [in]"r"(in), [out]"r"(out)
+ : "memory"
+ );
+}
+
+#undef VERTICAL_PASS_WHT
+#undef HORIZONTAL_PASS_WHT
+
+// macro for converting coefficients to bin
+// convert 8 coeffs at time
+// A, B, C, D - offsets in bytes to load from out buffer
+#define CONVERT_COEFFS_TO_BIN(A, B, C, D) \
+ "ulw %[temp0], " #A "(%[out]) \n\t" \
+ "ulw %[temp1], " #B "(%[out]) \n\t" \
+ "ulw %[temp2], " #C "(%[out]) \n\t" \
+ "ulw %[temp3], " #D "(%[out]) \n\t" \
+ "absq_s.ph %[temp0], %[temp0] \n\t" \
+ "absq_s.ph %[temp1], %[temp1] \n\t" \
+ "absq_s.ph %[temp2], %[temp2] \n\t" \
+ "absq_s.ph %[temp3], %[temp3] \n\t" \
+ /* TODO(skal): add rounding ? shra_r.ph : shra.ph */ \
+ /* for following 4 instructions */ \
+ "shra.ph %[temp0], %[temp0], 3 \n\t" \
+ "shra.ph %[temp1], %[temp1], 3 \n\t" \
+ "shra.ph %[temp2], %[temp2], 3 \n\t" \
+ "shra.ph %[temp3], %[temp3], 3 \n\t" \
+ "shll_s.ph %[temp0], %[temp0], 10 \n\t" \
+ "shll_s.ph %[temp1], %[temp1], 10 \n\t" \
+ "shll_s.ph %[temp2], %[temp2], 10 \n\t" \
+ "shll_s.ph %[temp3], %[temp3], 10 \n\t" \
+ "shrl.ph %[temp0], %[temp0], 10 \n\t" \
+ "shrl.ph %[temp1], %[temp1], 10 \n\t" \
+ "shrl.ph %[temp2], %[temp2], 10 \n\t" \
+ "shrl.ph %[temp3], %[temp3], 10 \n\t" \
+ "shll.ph %[temp0], %[temp0], 2 \n\t" \
+ "shll.ph %[temp1], %[temp1], 2 \n\t" \
+ "shll.ph %[temp2], %[temp2], 2 \n\t" \
+ "shll.ph %[temp3], %[temp3], 2 \n\t" \
+ "ext %[temp4], %[temp0], 0, 16 \n\t" \
+ "ext %[temp0], %[temp0], 16, 16 \n\t" \
+ "addu %[temp4], %[temp4], %[dist] \n\t" \
+ "addu %[temp0], %[temp0], %[dist] \n\t" \
+ "ext %[temp5], %[temp1], 0, 16 \n\t" \
+ "lw %[temp8], 0(%[temp4]) \n\t" \
+ "ext %[temp1], %[temp1], 16, 16 \n\t" \
+ "addu %[temp5], %[temp5], %[dist] \n\t" \
+ "addiu %[temp8], %[temp8], 1 \n\t" \
+ "sw %[temp8], 0(%[temp4]) \n\t" \
+ "lw %[temp8], 0(%[temp0]) \n\t" \
+ "addu %[temp1], %[temp1], %[dist] \n\t" \
+ "ext %[temp6], %[temp2], 0, 16 \n\t" \
+ "addiu %[temp8], %[temp8], 1 \n\t" \
+ "sw %[temp8], 0(%[temp0]) \n\t" \
+ "lw %[temp8], 0(%[temp5]) \n\t" \
+ "ext %[temp2], %[temp2], 16, 16 \n\t" \
+ "addu %[temp6], %[temp6], %[dist] \n\t" \
+ "addiu %[temp8], %[temp8], 1 \n\t" \
+ "sw %[temp8], 0(%[temp5]) \n\t" \
+ "lw %[temp8], 0(%[temp1]) \n\t" \
+ "addu %[temp2], %[temp2], %[dist] \n\t" \
+ "ext %[temp7], %[temp3], 0, 16 \n\t" \
+ "addiu %[temp8], %[temp8], 1 \n\t" \
+ "sw %[temp8], 0(%[temp1]) \n\t" \
+ "lw %[temp8], 0(%[temp6]) \n\t" \
+ "ext %[temp3], %[temp3], 16, 16 \n\t" \
+ "addu %[temp7], %[temp7], %[dist] \n\t" \
+ "addiu %[temp8], %[temp8], 1 \n\t" \
+ "sw %[temp8], 0(%[temp6]) \n\t" \
+ "lw %[temp8], 0(%[temp2]) \n\t" \
+ "addu %[temp3], %[temp3], %[dist] \n\t" \
+ "addiu %[temp8], %[temp8], 1 \n\t" \
+ "sw %[temp8], 0(%[temp2]) \n\t" \
+ "lw %[temp8], 0(%[temp7]) \n\t" \
+ "addiu %[temp8], %[temp8], 1 \n\t" \
+ "sw %[temp8], 0(%[temp7]) \n\t" \
+ "lw %[temp8], 0(%[temp3]) \n\t" \
+ "addiu %[temp8], %[temp8], 1 \n\t" \
+ "sw %[temp8], 0(%[temp3]) \n\t"
+
+static void CollectHistogram(const uint8_t* ref, const uint8_t* pred,
+ int start_block, int end_block,
+ VP8Histogram* const histo) {
+ int j;
+ int distribution[MAX_COEFF_THRESH + 1] = { 0 };
+ const int max_coeff = (MAX_COEFF_THRESH << 16) + MAX_COEFF_THRESH;
+ for (j = start_block; j < end_block; ++j) {
+ int16_t out[16];
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
+
+ VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
+
+ // Convert coefficients to bin.
+ __asm__ volatile (
+ CONVERT_COEFFS_TO_BIN( 0, 4, 8, 12)
+ CONVERT_COEFFS_TO_BIN(16, 20, 24, 28)
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8)
+ : [dist]"r"(distribution), [out]"r"(out), [max_coeff]"r"(max_coeff)
+ : "memory"
+ );
+ }
+ VP8SetHistogramData(distribution, histo);
+}
+
+#undef CONVERT_COEFFS_TO_BIN
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8EncDspInitMIPSdspR2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMIPSdspR2(void) {
+ VP8FTransform = FTransform;
+ VP8ITransform = ITransform;
+ VP8TDisto4x4 = Disto4x4;
+ VP8TDisto16x16 = Disto16x16;
+ VP8EncPredLuma16 = Intra16Preds;
+ VP8EncPredChroma8 = IntraChromaPreds;
+ VP8EncPredLuma4 = Intra4Preds;
+#if !defined(WORK_AROUND_GCC)
+ VP8SSE16x16 = SSE16x16;
+ VP8SSE8x8 = SSE8x8;
+ VP8SSE16x8 = SSE16x8;
+ VP8SSE4x4 = SSE4x4;
+#endif
+ VP8EncQuantizeBlock = QuantizeBlock;
+ VP8EncQuantize2Blocks = Quantize2Blocks;
+ VP8FTransformWHT = FTransformWHT;
+ VP8CollectHistogram = CollectHistogram;
+}
+
+#else // !WEBP_USE_MIPS_DSP_R2
+
+WEBP_DSP_INIT_STUB(VP8EncDspInitMIPSdspR2)
+
+#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/enc_neon.c b/drivers/webp/dsp/enc_neon.c
new file mode 100644
index 0000000000..c2aef58e70
--- /dev/null
+++ b/drivers/webp/dsp/enc_neon.c
@@ -0,0 +1,934 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// ARM NEON version of speed-critical encoding functions.
+//
+// adapted from libvpx (http://www.webmproject.org/code/)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_NEON)
+
+#include <assert.h>
+
+#include "./neon.h"
+#include "../enc/vp8enci.h"
+
+//------------------------------------------------------------------------------
+// Transforms (Paragraph 14.4)
+
+// Inverse transform.
+// This code is pretty much the same as TransformOne in the dec_neon.c, except
+// for subtraction to *ref. See the comments there for algorithmic explanations.
+
+static const int16_t kC1 = 20091;
+static const int16_t kC2 = 17734; // half of kC2, actually. See comment above.
+
+// This code works but is *slower* than the inlined-asm version below
+// (with gcc-4.6). So we disable it for now. Later, it'll be conditional to
+// WEBP_USE_INTRINSICS define.
+// With gcc-4.8, it's a little faster speed than inlined-assembly.
+#if defined(WEBP_USE_INTRINSICS)
+
+// Treats 'v' as an uint8x8_t and zero extends to an int16x8_t.
+static WEBP_INLINE int16x8_t ConvertU8ToS16(uint32x2_t v) {
+ return vreinterpretq_s16_u16(vmovl_u8(vreinterpret_u8_u32(v)));
+}
+
+// Performs unsigned 8b saturation on 'dst01' and 'dst23' storing the result
+// to the corresponding rows of 'dst'.
+static WEBP_INLINE void SaturateAndStore4x4(uint8_t* const dst,
+ const int16x8_t dst01,
+ const int16x8_t dst23) {
+ // Unsigned saturate to 8b.
+ const uint8x8_t dst01_u8 = vqmovun_s16(dst01);
+ const uint8x8_t dst23_u8 = vqmovun_s16(dst23);
+
+ // Store the results.
+ vst1_lane_u32((uint32_t*)(dst + 0 * BPS), vreinterpret_u32_u8(dst01_u8), 0);
+ vst1_lane_u32((uint32_t*)(dst + 1 * BPS), vreinterpret_u32_u8(dst01_u8), 1);
+ vst1_lane_u32((uint32_t*)(dst + 2 * BPS), vreinterpret_u32_u8(dst23_u8), 0);
+ vst1_lane_u32((uint32_t*)(dst + 3 * BPS), vreinterpret_u32_u8(dst23_u8), 1);
+}
+
+static WEBP_INLINE void Add4x4(const int16x8_t row01, const int16x8_t row23,
+ const uint8_t* const ref, uint8_t* const dst) {
+ uint32x2_t dst01 = vdup_n_u32(0);
+ uint32x2_t dst23 = vdup_n_u32(0);
+
+ // Load the source pixels.
+ dst01 = vld1_lane_u32((uint32_t*)(ref + 0 * BPS), dst01, 0);
+ dst23 = vld1_lane_u32((uint32_t*)(ref + 2 * BPS), dst23, 0);
+ dst01 = vld1_lane_u32((uint32_t*)(ref + 1 * BPS), dst01, 1);
+ dst23 = vld1_lane_u32((uint32_t*)(ref + 3 * BPS), dst23, 1);
+
+ {
+ // Convert to 16b.
+ const int16x8_t dst01_s16 = ConvertU8ToS16(dst01);
+ const int16x8_t dst23_s16 = ConvertU8ToS16(dst23);
+
+ // Descale with rounding.
+ const int16x8_t out01 = vrsraq_n_s16(dst01_s16, row01, 3);
+ const int16x8_t out23 = vrsraq_n_s16(dst23_s16, row23, 3);
+ // Add the inverse transform.
+ SaturateAndStore4x4(dst, out01, out23);
+ }
+}
+
+static WEBP_INLINE void Transpose8x2(const int16x8_t in0, const int16x8_t in1,
+ int16x8x2_t* const out) {
+ // a0 a1 a2 a3 | b0 b1 b2 b3 => a0 b0 c0 d0 | a1 b1 c1 d1
+ // c0 c1 c2 c3 | d0 d1 d2 d3 a2 b2 c2 d2 | a3 b3 c3 d3
+ const int16x8x2_t tmp0 = vzipq_s16(in0, in1); // a0 c0 a1 c1 a2 c2 ...
+ // b0 d0 b1 d1 b2 d2 ...
+ *out = vzipq_s16(tmp0.val[0], tmp0.val[1]);
+}
+
+static WEBP_INLINE void TransformPass(int16x8x2_t* const rows) {
+ // {rows} = in0 | in4
+ // in8 | in12
+ // B1 = in4 | in12
+ const int16x8_t B1 =
+ vcombine_s16(vget_high_s16(rows->val[0]), vget_high_s16(rows->val[1]));
+ // C0 = kC1 * in4 | kC1 * in12
+ // C1 = kC2 * in4 | kC2 * in12
+ const int16x8_t C0 = vsraq_n_s16(B1, vqdmulhq_n_s16(B1, kC1), 1);
+ const int16x8_t C1 = vqdmulhq_n_s16(B1, kC2);
+ const int16x4_t a = vqadd_s16(vget_low_s16(rows->val[0]),
+ vget_low_s16(rows->val[1])); // in0 + in8
+ const int16x4_t b = vqsub_s16(vget_low_s16(rows->val[0]),
+ vget_low_s16(rows->val[1])); // in0 - in8
+ // c = kC2 * in4 - kC1 * in12
+ // d = kC1 * in4 + kC2 * in12
+ const int16x4_t c = vqsub_s16(vget_low_s16(C1), vget_high_s16(C0));
+ const int16x4_t d = vqadd_s16(vget_low_s16(C0), vget_high_s16(C1));
+ const int16x8_t D0 = vcombine_s16(a, b); // D0 = a | b
+ const int16x8_t D1 = vcombine_s16(d, c); // D1 = d | c
+ const int16x8_t E0 = vqaddq_s16(D0, D1); // a+d | b+c
+ const int16x8_t E_tmp = vqsubq_s16(D0, D1); // a-d | b-c
+ const int16x8_t E1 = vcombine_s16(vget_high_s16(E_tmp), vget_low_s16(E_tmp));
+ Transpose8x2(E0, E1, rows);
+}
+
+static void ITransformOne(const uint8_t* ref,
+ const int16_t* in, uint8_t* dst) {
+ int16x8x2_t rows;
+ INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8));
+ TransformPass(&rows);
+ TransformPass(&rows);
+ Add4x4(rows.val[0], rows.val[1], ref, dst);
+}
+
+#else
+
+static void ITransformOne(const uint8_t* ref,
+ const int16_t* in, uint8_t* dst) {
+ const int kBPS = BPS;
+ const int16_t kC1C2[] = { kC1, kC2, 0, 0 };
+
+ __asm__ volatile (
+ "vld1.16 {q1, q2}, [%[in]] \n"
+ "vld1.16 {d0}, [%[kC1C2]] \n"
+
+ // d2: in[0]
+ // d3: in[8]
+ // d4: in[4]
+ // d5: in[12]
+ "vswp d3, d4 \n"
+
+ // q8 = {in[4], in[12]} * kC1 * 2 >> 16
+ // q9 = {in[4], in[12]} * kC2 >> 16
+ "vqdmulh.s16 q8, q2, d0[0] \n"
+ "vqdmulh.s16 q9, q2, d0[1] \n"
+
+ // d22 = a = in[0] + in[8]
+ // d23 = b = in[0] - in[8]
+ "vqadd.s16 d22, d2, d3 \n"
+ "vqsub.s16 d23, d2, d3 \n"
+
+ // q8 = in[4]/[12] * kC1 >> 16
+ "vshr.s16 q8, q8, #1 \n"
+
+ // Add {in[4], in[12]} back after the multiplication.
+ "vqadd.s16 q8, q2, q8 \n"
+
+ // d20 = c = in[4]*kC2 - in[12]*kC1
+ // d21 = d = in[4]*kC1 + in[12]*kC2
+ "vqsub.s16 d20, d18, d17 \n"
+ "vqadd.s16 d21, d19, d16 \n"
+
+ // d2 = tmp[0] = a + d
+ // d3 = tmp[1] = b + c
+ // d4 = tmp[2] = b - c
+ // d5 = tmp[3] = a - d
+ "vqadd.s16 d2, d22, d21 \n"
+ "vqadd.s16 d3, d23, d20 \n"
+ "vqsub.s16 d4, d23, d20 \n"
+ "vqsub.s16 d5, d22, d21 \n"
+
+ "vzip.16 q1, q2 \n"
+ "vzip.16 q1, q2 \n"
+
+ "vswp d3, d4 \n"
+
+ // q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16
+ // q9 = {tmp[4], tmp[12]} * kC2 >> 16
+ "vqdmulh.s16 q8, q2, d0[0] \n"
+ "vqdmulh.s16 q9, q2, d0[1] \n"
+
+ // d22 = a = tmp[0] + tmp[8]
+ // d23 = b = tmp[0] - tmp[8]
+ "vqadd.s16 d22, d2, d3 \n"
+ "vqsub.s16 d23, d2, d3 \n"
+
+ "vshr.s16 q8, q8, #1 \n"
+ "vqadd.s16 q8, q2, q8 \n"
+
+ // d20 = c = in[4]*kC2 - in[12]*kC1
+ // d21 = d = in[4]*kC1 + in[12]*kC2
+ "vqsub.s16 d20, d18, d17 \n"
+ "vqadd.s16 d21, d19, d16 \n"
+
+ // d2 = tmp[0] = a + d
+ // d3 = tmp[1] = b + c
+ // d4 = tmp[2] = b - c
+ // d5 = tmp[3] = a - d
+ "vqadd.s16 d2, d22, d21 \n"
+ "vqadd.s16 d3, d23, d20 \n"
+ "vqsub.s16 d4, d23, d20 \n"
+ "vqsub.s16 d5, d22, d21 \n"
+
+ "vld1.32 d6[0], [%[ref]], %[kBPS] \n"
+ "vld1.32 d6[1], [%[ref]], %[kBPS] \n"
+ "vld1.32 d7[0], [%[ref]], %[kBPS] \n"
+ "vld1.32 d7[1], [%[ref]], %[kBPS] \n"
+
+ "sub %[ref], %[ref], %[kBPS], lsl #2 \n"
+
+ // (val) + 4 >> 3
+ "vrshr.s16 d2, d2, #3 \n"
+ "vrshr.s16 d3, d3, #3 \n"
+ "vrshr.s16 d4, d4, #3 \n"
+ "vrshr.s16 d5, d5, #3 \n"
+
+ "vzip.16 q1, q2 \n"
+ "vzip.16 q1, q2 \n"
+
+ // Must accumulate before saturating
+ "vmovl.u8 q8, d6 \n"
+ "vmovl.u8 q9, d7 \n"
+
+ "vqadd.s16 q1, q1, q8 \n"
+ "vqadd.s16 q2, q2, q9 \n"
+
+ "vqmovun.s16 d0, q1 \n"
+ "vqmovun.s16 d1, q2 \n"
+
+ "vst1.32 d0[0], [%[dst]], %[kBPS] \n"
+ "vst1.32 d0[1], [%[dst]], %[kBPS] \n"
+ "vst1.32 d1[0], [%[dst]], %[kBPS] \n"
+ "vst1.32 d1[1], [%[dst]] \n"
+
+ : [in] "+r"(in), [dst] "+r"(dst) // modified registers
+ : [kBPS] "r"(kBPS), [kC1C2] "r"(kC1C2), [ref] "r"(ref) // constants
+ : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11" // clobbered
+ );
+}
+
+#endif // WEBP_USE_INTRINSICS
+
+static void ITransform(const uint8_t* ref,
+ const int16_t* in, uint8_t* dst, int do_two) {
+ ITransformOne(ref, in, dst);
+ if (do_two) {
+ ITransformOne(ref + 4, in + 16, dst + 4);
+ }
+}
+
+// Load all 4x4 pixels into a single uint8x16_t variable.
+static uint8x16_t Load4x4(const uint8_t* src) {
+ uint32x4_t out = vdupq_n_u32(0);
+ out = vld1q_lane_u32((const uint32_t*)(src + 0 * BPS), out, 0);
+ out = vld1q_lane_u32((const uint32_t*)(src + 1 * BPS), out, 1);
+ out = vld1q_lane_u32((const uint32_t*)(src + 2 * BPS), out, 2);
+ out = vld1q_lane_u32((const uint32_t*)(src + 3 * BPS), out, 3);
+ return vreinterpretq_u8_u32(out);
+}
+
+// Forward transform.
+
+#if defined(WEBP_USE_INTRINSICS)
+
+static WEBP_INLINE void Transpose4x4_S16(const int16x4_t A, const int16x4_t B,
+ const int16x4_t C, const int16x4_t D,
+ int16x8_t* const out01,
+ int16x8_t* const out32) {
+ const int16x4x2_t AB = vtrn_s16(A, B);
+ const int16x4x2_t CD = vtrn_s16(C, D);
+ const int32x2x2_t tmp02 = vtrn_s32(vreinterpret_s32_s16(AB.val[0]),
+ vreinterpret_s32_s16(CD.val[0]));
+ const int32x2x2_t tmp13 = vtrn_s32(vreinterpret_s32_s16(AB.val[1]),
+ vreinterpret_s32_s16(CD.val[1]));
+ *out01 = vreinterpretq_s16_s64(
+ vcombine_s64(vreinterpret_s64_s32(tmp02.val[0]),
+ vreinterpret_s64_s32(tmp13.val[0])));
+ *out32 = vreinterpretq_s16_s64(
+ vcombine_s64(vreinterpret_s64_s32(tmp13.val[1]),
+ vreinterpret_s64_s32(tmp02.val[1])));
+}
+
+static WEBP_INLINE int16x8_t DiffU8ToS16(const uint8x8_t a,
+ const uint8x8_t b) {
+ return vreinterpretq_s16_u16(vsubl_u8(a, b));
+}
+
+static void FTransform(const uint8_t* src, const uint8_t* ref,
+ int16_t* out) {
+ int16x8_t d0d1, d3d2; // working 4x4 int16 variables
+ {
+ const uint8x16_t S0 = Load4x4(src);
+ const uint8x16_t R0 = Load4x4(ref);
+ const int16x8_t D0D1 = DiffU8ToS16(vget_low_u8(S0), vget_low_u8(R0));
+ const int16x8_t D2D3 = DiffU8ToS16(vget_high_u8(S0), vget_high_u8(R0));
+ const int16x4_t D0 = vget_low_s16(D0D1);
+ const int16x4_t D1 = vget_high_s16(D0D1);
+ const int16x4_t D2 = vget_low_s16(D2D3);
+ const int16x4_t D3 = vget_high_s16(D2D3);
+ Transpose4x4_S16(D0, D1, D2, D3, &d0d1, &d3d2);
+ }
+ { // 1rst pass
+ const int32x4_t kCst937 = vdupq_n_s32(937);
+ const int32x4_t kCst1812 = vdupq_n_s32(1812);
+ const int16x8_t a0a1 = vaddq_s16(d0d1, d3d2); // d0+d3 | d1+d2 (=a0|a1)
+ const int16x8_t a3a2 = vsubq_s16(d0d1, d3d2); // d0-d3 | d1-d2 (=a3|a2)
+ const int16x8_t a0a1_2 = vshlq_n_s16(a0a1, 3);
+ const int16x4_t tmp0 = vadd_s16(vget_low_s16(a0a1_2),
+ vget_high_s16(a0a1_2));
+ const int16x4_t tmp2 = vsub_s16(vget_low_s16(a0a1_2),
+ vget_high_s16(a0a1_2));
+ const int32x4_t a3_2217 = vmull_n_s16(vget_low_s16(a3a2), 2217);
+ const int32x4_t a2_2217 = vmull_n_s16(vget_high_s16(a3a2), 2217);
+ const int32x4_t a2_p_a3 = vmlal_n_s16(a2_2217, vget_low_s16(a3a2), 5352);
+ const int32x4_t a3_m_a2 = vmlsl_n_s16(a3_2217, vget_high_s16(a3a2), 5352);
+ const int16x4_t tmp1 = vshrn_n_s32(vaddq_s32(a2_p_a3, kCst1812), 9);
+ const int16x4_t tmp3 = vshrn_n_s32(vaddq_s32(a3_m_a2, kCst937), 9);
+ Transpose4x4_S16(tmp0, tmp1, tmp2, tmp3, &d0d1, &d3d2);
+ }
+ { // 2nd pass
+ // the (1<<16) addition is for the replacement: a3!=0 <-> 1-(a3==0)
+ const int32x4_t kCst12000 = vdupq_n_s32(12000 + (1 << 16));
+ const int32x4_t kCst51000 = vdupq_n_s32(51000);
+ const int16x8_t a0a1 = vaddq_s16(d0d1, d3d2); // d0+d3 | d1+d2 (=a0|a1)
+ const int16x8_t a3a2 = vsubq_s16(d0d1, d3d2); // d0-d3 | d1-d2 (=a3|a2)
+ const int16x4_t a0_k7 = vadd_s16(vget_low_s16(a0a1), vdup_n_s16(7));
+ const int16x4_t out0 = vshr_n_s16(vadd_s16(a0_k7, vget_high_s16(a0a1)), 4);
+ const int16x4_t out2 = vshr_n_s16(vsub_s16(a0_k7, vget_high_s16(a0a1)), 4);
+ const int32x4_t a3_2217 = vmull_n_s16(vget_low_s16(a3a2), 2217);
+ const int32x4_t a2_2217 = vmull_n_s16(vget_high_s16(a3a2), 2217);
+ const int32x4_t a2_p_a3 = vmlal_n_s16(a2_2217, vget_low_s16(a3a2), 5352);
+ const int32x4_t a3_m_a2 = vmlsl_n_s16(a3_2217, vget_high_s16(a3a2), 5352);
+ const int16x4_t tmp1 = vaddhn_s32(a2_p_a3, kCst12000);
+ const int16x4_t out3 = vaddhn_s32(a3_m_a2, kCst51000);
+ const int16x4_t a3_eq_0 =
+ vreinterpret_s16_u16(vceq_s16(vget_low_s16(a3a2), vdup_n_s16(0)));
+ const int16x4_t out1 = vadd_s16(tmp1, a3_eq_0);
+ vst1_s16(out + 0, out0);
+ vst1_s16(out + 4, out1);
+ vst1_s16(out + 8, out2);
+ vst1_s16(out + 12, out3);
+ }
+}
+
+#else
+
+// adapted from vp8/encoder/arm/neon/shortfdct_neon.asm
+static const int16_t kCoeff16[] = {
+ 5352, 5352, 5352, 5352, 2217, 2217, 2217, 2217
+};
+static const int32_t kCoeff32[] = {
+ 1812, 1812, 1812, 1812,
+ 937, 937, 937, 937,
+ 12000, 12000, 12000, 12000,
+ 51000, 51000, 51000, 51000
+};
+
+static void FTransform(const uint8_t* src, const uint8_t* ref,
+ int16_t* out) {
+ const int kBPS = BPS;
+ const uint8_t* src_ptr = src;
+ const uint8_t* ref_ptr = ref;
+ const int16_t* coeff16 = kCoeff16;
+ const int32_t* coeff32 = kCoeff32;
+
+ __asm__ volatile (
+ // load src into q4, q5 in high half
+ "vld1.8 {d8}, [%[src_ptr]], %[kBPS] \n"
+ "vld1.8 {d10}, [%[src_ptr]], %[kBPS] \n"
+ "vld1.8 {d9}, [%[src_ptr]], %[kBPS] \n"
+ "vld1.8 {d11}, [%[src_ptr]] \n"
+
+ // load ref into q6, q7 in high half
+ "vld1.8 {d12}, [%[ref_ptr]], %[kBPS] \n"
+ "vld1.8 {d14}, [%[ref_ptr]], %[kBPS] \n"
+ "vld1.8 {d13}, [%[ref_ptr]], %[kBPS] \n"
+ "vld1.8 {d15}, [%[ref_ptr]] \n"
+
+ // Pack the high values in to q4 and q6
+ "vtrn.32 q4, q5 \n"
+ "vtrn.32 q6, q7 \n"
+
+ // d[0-3] = src - ref
+ "vsubl.u8 q0, d8, d12 \n"
+ "vsubl.u8 q1, d9, d13 \n"
+
+ // load coeff16 into q8(d16=5352, d17=2217)
+ "vld1.16 {q8}, [%[coeff16]] \n"
+
+ // load coeff32 high half into q9 = 1812, q10 = 937
+ "vld1.32 {q9, q10}, [%[coeff32]]! \n"
+
+ // load coeff32 low half into q11=12000, q12=51000
+ "vld1.32 {q11,q12}, [%[coeff32]] \n"
+
+ // part 1
+ // Transpose. Register dN is the same as dN in C
+ "vtrn.32 d0, d2 \n"
+ "vtrn.32 d1, d3 \n"
+ "vtrn.16 d0, d1 \n"
+ "vtrn.16 d2, d3 \n"
+
+ "vadd.s16 d4, d0, d3 \n" // a0 = d0 + d3
+ "vadd.s16 d5, d1, d2 \n" // a1 = d1 + d2
+ "vsub.s16 d6, d1, d2 \n" // a2 = d1 - d2
+ "vsub.s16 d7, d0, d3 \n" // a3 = d0 - d3
+
+ "vadd.s16 d0, d4, d5 \n" // a0 + a1
+ "vshl.s16 d0, d0, #3 \n" // temp[0+i*4] = (a0+a1) << 3
+ "vsub.s16 d2, d4, d5 \n" // a0 - a1
+ "vshl.s16 d2, d2, #3 \n" // (temp[2+i*4] = (a0-a1) << 3
+
+ "vmlal.s16 q9, d7, d16 \n" // a3*5352 + 1812
+ "vmlal.s16 q10, d7, d17 \n" // a3*2217 + 937
+ "vmlal.s16 q9, d6, d17 \n" // a2*2217 + a3*5352 + 1812
+ "vmlsl.s16 q10, d6, d16 \n" // a3*2217 + 937 - a2*5352
+
+ // temp[1+i*4] = (d2*2217 + d3*5352 + 1812) >> 9
+ // temp[3+i*4] = (d3*2217 + 937 - d2*5352) >> 9
+ "vshrn.s32 d1, q9, #9 \n"
+ "vshrn.s32 d3, q10, #9 \n"
+
+ // part 2
+ // transpose d0=ip[0], d1=ip[4], d2=ip[8], d3=ip[12]
+ "vtrn.32 d0, d2 \n"
+ "vtrn.32 d1, d3 \n"
+ "vtrn.16 d0, d1 \n"
+ "vtrn.16 d2, d3 \n"
+
+ "vmov.s16 d26, #7 \n"
+
+ "vadd.s16 d4, d0, d3 \n" // a1 = ip[0] + ip[12]
+ "vadd.s16 d5, d1, d2 \n" // b1 = ip[4] + ip[8]
+ "vsub.s16 d6, d1, d2 \n" // c1 = ip[4] - ip[8]
+ "vadd.s16 d4, d4, d26 \n" // a1 + 7
+ "vsub.s16 d7, d0, d3 \n" // d1 = ip[0] - ip[12]
+
+ "vadd.s16 d0, d4, d5 \n" // op[0] = a1 + b1 + 7
+ "vsub.s16 d2, d4, d5 \n" // op[8] = a1 - b1 + 7
+
+ "vmlal.s16 q11, d7, d16 \n" // d1*5352 + 12000
+ "vmlal.s16 q12, d7, d17 \n" // d1*2217 + 51000
+
+ "vceq.s16 d4, d7, #0 \n"
+
+ "vshr.s16 d0, d0, #4 \n"
+ "vshr.s16 d2, d2, #4 \n"
+
+ "vmlal.s16 q11, d6, d17 \n" // c1*2217 + d1*5352 + 12000
+ "vmlsl.s16 q12, d6, d16 \n" // d1*2217 - c1*5352 + 51000
+
+ "vmvn d4, d4 \n" // !(d1 == 0)
+ // op[4] = (c1*2217 + d1*5352 + 12000)>>16
+ "vshrn.s32 d1, q11, #16 \n"
+ // op[4] += (d1!=0)
+ "vsub.s16 d1, d1, d4 \n"
+ // op[12]= (d1*2217 - c1*5352 + 51000)>>16
+ "vshrn.s32 d3, q12, #16 \n"
+
+ // set result to out array
+ "vst1.16 {q0, q1}, [%[out]] \n"
+ : [src_ptr] "+r"(src_ptr), [ref_ptr] "+r"(ref_ptr),
+ [coeff32] "+r"(coeff32) // modified registers
+ : [kBPS] "r"(kBPS), [coeff16] "r"(coeff16),
+ [out] "r"(out) // constants
+ : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9",
+ "q10", "q11", "q12", "q13" // clobbered
+ );
+}
+
+#endif
+
+#define LOAD_LANE_16b(VALUE, LANE) do { \
+ (VALUE) = vld1_lane_s16(src, (VALUE), (LANE)); \
+ src += stride; \
+} while (0)
+
+static void FTransformWHT(const int16_t* src, int16_t* out) {
+ const int stride = 16;
+ const int16x4_t zero = vdup_n_s16(0);
+ int32x4x4_t tmp0;
+ int16x4x4_t in;
+ INIT_VECTOR4(in, zero, zero, zero, zero);
+ LOAD_LANE_16b(in.val[0], 0);
+ LOAD_LANE_16b(in.val[1], 0);
+ LOAD_LANE_16b(in.val[2], 0);
+ LOAD_LANE_16b(in.val[3], 0);
+ LOAD_LANE_16b(in.val[0], 1);
+ LOAD_LANE_16b(in.val[1], 1);
+ LOAD_LANE_16b(in.val[2], 1);
+ LOAD_LANE_16b(in.val[3], 1);
+ LOAD_LANE_16b(in.val[0], 2);
+ LOAD_LANE_16b(in.val[1], 2);
+ LOAD_LANE_16b(in.val[2], 2);
+ LOAD_LANE_16b(in.val[3], 2);
+ LOAD_LANE_16b(in.val[0], 3);
+ LOAD_LANE_16b(in.val[1], 3);
+ LOAD_LANE_16b(in.val[2], 3);
+ LOAD_LANE_16b(in.val[3], 3);
+
+ {
+ // a0 = in[0 * 16] + in[2 * 16]
+ // a1 = in[1 * 16] + in[3 * 16]
+ // a2 = in[1 * 16] - in[3 * 16]
+ // a3 = in[0 * 16] - in[2 * 16]
+ const int32x4_t a0 = vaddl_s16(in.val[0], in.val[2]);
+ const int32x4_t a1 = vaddl_s16(in.val[1], in.val[3]);
+ const int32x4_t a2 = vsubl_s16(in.val[1], in.val[3]);
+ const int32x4_t a3 = vsubl_s16(in.val[0], in.val[2]);
+ tmp0.val[0] = vaddq_s32(a0, a1);
+ tmp0.val[1] = vaddq_s32(a3, a2);
+ tmp0.val[2] = vsubq_s32(a3, a2);
+ tmp0.val[3] = vsubq_s32(a0, a1);
+ }
+ {
+ const int32x4x4_t tmp1 = Transpose4x4(tmp0);
+ // a0 = tmp[0 + i] + tmp[ 8 + i]
+ // a1 = tmp[4 + i] + tmp[12 + i]
+ // a2 = tmp[4 + i] - tmp[12 + i]
+ // a3 = tmp[0 + i] - tmp[ 8 + i]
+ const int32x4_t a0 = vaddq_s32(tmp1.val[0], tmp1.val[2]);
+ const int32x4_t a1 = vaddq_s32(tmp1.val[1], tmp1.val[3]);
+ const int32x4_t a2 = vsubq_s32(tmp1.val[1], tmp1.val[3]);
+ const int32x4_t a3 = vsubq_s32(tmp1.val[0], tmp1.val[2]);
+ const int32x4_t b0 = vhaddq_s32(a0, a1); // (a0 + a1) >> 1
+ const int32x4_t b1 = vhaddq_s32(a3, a2); // (a3 + a2) >> 1
+ const int32x4_t b2 = vhsubq_s32(a3, a2); // (a3 - a2) >> 1
+ const int32x4_t b3 = vhsubq_s32(a0, a1); // (a0 - a1) >> 1
+ const int16x4_t out0 = vmovn_s32(b0);
+ const int16x4_t out1 = vmovn_s32(b1);
+ const int16x4_t out2 = vmovn_s32(b2);
+ const int16x4_t out3 = vmovn_s32(b3);
+
+ vst1_s16(out + 0, out0);
+ vst1_s16(out + 4, out1);
+ vst1_s16(out + 8, out2);
+ vst1_s16(out + 12, out3);
+ }
+}
+#undef LOAD_LANE_16b
+
+//------------------------------------------------------------------------------
+// Texture distortion
+//
+// We try to match the spectral content (weighted) between source and
+// reconstructed samples.
+
+// a 0123, b 0123
+// a 4567, b 4567
+// a 89ab, b 89ab
+// a cdef, b cdef
+//
+// transpose
+//
+// a 048c, b 048c
+// a 159d, b 159d
+// a 26ae, b 26ae
+// a 37bf, b 37bf
+//
+static WEBP_INLINE uint8x8x4_t DistoTranspose4x4U8(uint8x8x4_t d4_in) {
+ const uint8x8x2_t d2_tmp0 = vtrn_u8(d4_in.val[0], d4_in.val[1]);
+ const uint8x8x2_t d2_tmp1 = vtrn_u8(d4_in.val[2], d4_in.val[3]);
+ const uint16x4x2_t d2_tmp2 = vtrn_u16(vreinterpret_u16_u8(d2_tmp0.val[0]),
+ vreinterpret_u16_u8(d2_tmp1.val[0]));
+ const uint16x4x2_t d2_tmp3 = vtrn_u16(vreinterpret_u16_u8(d2_tmp0.val[1]),
+ vreinterpret_u16_u8(d2_tmp1.val[1]));
+
+ d4_in.val[0] = vreinterpret_u8_u16(d2_tmp2.val[0]);
+ d4_in.val[2] = vreinterpret_u8_u16(d2_tmp2.val[1]);
+ d4_in.val[1] = vreinterpret_u8_u16(d2_tmp3.val[0]);
+ d4_in.val[3] = vreinterpret_u8_u16(d2_tmp3.val[1]);
+ return d4_in;
+}
+
+static WEBP_INLINE int16x8x4_t DistoTranspose4x4S16(int16x8x4_t q4_in) {
+ const int16x8x2_t q2_tmp0 = vtrnq_s16(q4_in.val[0], q4_in.val[1]);
+ const int16x8x2_t q2_tmp1 = vtrnq_s16(q4_in.val[2], q4_in.val[3]);
+ const int32x4x2_t q2_tmp2 = vtrnq_s32(vreinterpretq_s32_s16(q2_tmp0.val[0]),
+ vreinterpretq_s32_s16(q2_tmp1.val[0]));
+ const int32x4x2_t q2_tmp3 = vtrnq_s32(vreinterpretq_s32_s16(q2_tmp0.val[1]),
+ vreinterpretq_s32_s16(q2_tmp1.val[1]));
+ q4_in.val[0] = vreinterpretq_s16_s32(q2_tmp2.val[0]);
+ q4_in.val[2] = vreinterpretq_s16_s32(q2_tmp2.val[1]);
+ q4_in.val[1] = vreinterpretq_s16_s32(q2_tmp3.val[0]);
+ q4_in.val[3] = vreinterpretq_s16_s32(q2_tmp3.val[1]);
+ return q4_in;
+}
+
+static WEBP_INLINE int16x8x4_t DistoHorizontalPass(const uint8x8x4_t d4_in) {
+ // {a0, a1} = {in[0] + in[2], in[1] + in[3]}
+ // {a3, a2} = {in[0] - in[2], in[1] - in[3]}
+ const int16x8_t q_a0 = vreinterpretq_s16_u16(vaddl_u8(d4_in.val[0],
+ d4_in.val[2]));
+ const int16x8_t q_a1 = vreinterpretq_s16_u16(vaddl_u8(d4_in.val[1],
+ d4_in.val[3]));
+ const int16x8_t q_a3 = vreinterpretq_s16_u16(vsubl_u8(d4_in.val[0],
+ d4_in.val[2]));
+ const int16x8_t q_a2 = vreinterpretq_s16_u16(vsubl_u8(d4_in.val[1],
+ d4_in.val[3]));
+ int16x8x4_t q4_out;
+ // tmp[0] = a0 + a1
+ // tmp[1] = a3 + a2
+ // tmp[2] = a3 - a2
+ // tmp[3] = a0 - a1
+ INIT_VECTOR4(q4_out,
+ vaddq_s16(q_a0, q_a1), vaddq_s16(q_a3, q_a2),
+ vsubq_s16(q_a3, q_a2), vsubq_s16(q_a0, q_a1));
+ return q4_out;
+}
+
+static WEBP_INLINE int16x8x4_t DistoVerticalPass(int16x8x4_t q4_in) {
+ const int16x8_t q_a0 = vaddq_s16(q4_in.val[0], q4_in.val[2]);
+ const int16x8_t q_a1 = vaddq_s16(q4_in.val[1], q4_in.val[3]);
+ const int16x8_t q_a2 = vsubq_s16(q4_in.val[1], q4_in.val[3]);
+ const int16x8_t q_a3 = vsubq_s16(q4_in.val[0], q4_in.val[2]);
+
+ q4_in.val[0] = vaddq_s16(q_a0, q_a1);
+ q4_in.val[1] = vaddq_s16(q_a3, q_a2);
+ q4_in.val[2] = vabdq_s16(q_a3, q_a2);
+ q4_in.val[3] = vabdq_s16(q_a0, q_a1);
+ q4_in.val[0] = vabsq_s16(q4_in.val[0]);
+ q4_in.val[1] = vabsq_s16(q4_in.val[1]);
+ return q4_in;
+}
+
+static WEBP_INLINE int16x4x4_t DistoLoadW(const uint16_t* w) {
+ const uint16x8_t q_w07 = vld1q_u16(&w[0]);
+ const uint16x8_t q_w8f = vld1q_u16(&w[8]);
+ int16x4x4_t d4_w;
+ INIT_VECTOR4(d4_w,
+ vget_low_s16(vreinterpretq_s16_u16(q_w07)),
+ vget_high_s16(vreinterpretq_s16_u16(q_w07)),
+ vget_low_s16(vreinterpretq_s16_u16(q_w8f)),
+ vget_high_s16(vreinterpretq_s16_u16(q_w8f)));
+ return d4_w;
+}
+
+static WEBP_INLINE int32x2_t DistoSum(const int16x8x4_t q4_in,
+ const int16x4x4_t d4_w) {
+ int32x2_t d_sum;
+ // sum += w[ 0] * abs(b0);
+ // sum += w[ 4] * abs(b1);
+ // sum += w[ 8] * abs(b2);
+ // sum += w[12] * abs(b3);
+ int32x4_t q_sum0 = vmull_s16(d4_w.val[0], vget_low_s16(q4_in.val[0]));
+ int32x4_t q_sum1 = vmull_s16(d4_w.val[1], vget_low_s16(q4_in.val[1]));
+ int32x4_t q_sum2 = vmull_s16(d4_w.val[2], vget_low_s16(q4_in.val[2]));
+ int32x4_t q_sum3 = vmull_s16(d4_w.val[3], vget_low_s16(q4_in.val[3]));
+ q_sum0 = vmlsl_s16(q_sum0, d4_w.val[0], vget_high_s16(q4_in.val[0]));
+ q_sum1 = vmlsl_s16(q_sum1, d4_w.val[1], vget_high_s16(q4_in.val[1]));
+ q_sum2 = vmlsl_s16(q_sum2, d4_w.val[2], vget_high_s16(q4_in.val[2]));
+ q_sum3 = vmlsl_s16(q_sum3, d4_w.val[3], vget_high_s16(q4_in.val[3]));
+
+ q_sum0 = vaddq_s32(q_sum0, q_sum1);
+ q_sum2 = vaddq_s32(q_sum2, q_sum3);
+ q_sum2 = vaddq_s32(q_sum0, q_sum2);
+ d_sum = vpadd_s32(vget_low_s32(q_sum2), vget_high_s32(q_sum2));
+ d_sum = vpadd_s32(d_sum, d_sum);
+ return d_sum;
+}
+
+#define LOAD_LANE_32b(src, VALUE, LANE) \
+ (VALUE) = vld1_lane_u32((const uint32_t*)(src), (VALUE), (LANE))
+
+// Hadamard transform
+// Returns the weighted sum of the absolute value of transformed coefficients.
+static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
+ const uint16_t* const w) {
+ uint32x2_t d_in_ab_0123 = vdup_n_u32(0);
+ uint32x2_t d_in_ab_4567 = vdup_n_u32(0);
+ uint32x2_t d_in_ab_89ab = vdup_n_u32(0);
+ uint32x2_t d_in_ab_cdef = vdup_n_u32(0);
+ uint8x8x4_t d4_in;
+
+ // load data a, b
+ LOAD_LANE_32b(a + 0 * BPS, d_in_ab_0123, 0);
+ LOAD_LANE_32b(a + 1 * BPS, d_in_ab_4567, 0);
+ LOAD_LANE_32b(a + 2 * BPS, d_in_ab_89ab, 0);
+ LOAD_LANE_32b(a + 3 * BPS, d_in_ab_cdef, 0);
+ LOAD_LANE_32b(b + 0 * BPS, d_in_ab_0123, 1);
+ LOAD_LANE_32b(b + 1 * BPS, d_in_ab_4567, 1);
+ LOAD_LANE_32b(b + 2 * BPS, d_in_ab_89ab, 1);
+ LOAD_LANE_32b(b + 3 * BPS, d_in_ab_cdef, 1);
+ INIT_VECTOR4(d4_in,
+ vreinterpret_u8_u32(d_in_ab_0123),
+ vreinterpret_u8_u32(d_in_ab_4567),
+ vreinterpret_u8_u32(d_in_ab_89ab),
+ vreinterpret_u8_u32(d_in_ab_cdef));
+
+ {
+ // horizontal pass
+ const uint8x8x4_t d4_t = DistoTranspose4x4U8(d4_in);
+ const int16x8x4_t q4_h = DistoHorizontalPass(d4_t);
+ const int16x4x4_t d4_w = DistoLoadW(w);
+ // vertical pass
+ const int16x8x4_t q4_t = DistoTranspose4x4S16(q4_h);
+ const int16x8x4_t q4_v = DistoVerticalPass(q4_t);
+ int32x2_t d_sum = DistoSum(q4_v, d4_w);
+
+ // abs(sum2 - sum1) >> 5
+ d_sum = vabs_s32(d_sum);
+ d_sum = vshr_n_s32(d_sum, 5);
+ return vget_lane_s32(d_sum, 0);
+ }
+}
+#undef LOAD_LANE_32b
+
+static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
+ const uint16_t* const w) {
+ int D = 0;
+ int x, y;
+ for (y = 0; y < 16 * BPS; y += 4 * BPS) {
+ for (x = 0; x < 16; x += 4) {
+ D += Disto4x4(a + x + y, b + x + y, w);
+ }
+ }
+ return D;
+}
+
+//------------------------------------------------------------------------------
+
+static void CollectHistogram(const uint8_t* ref, const uint8_t* pred,
+ int start_block, int end_block,
+ VP8Histogram* const histo) {
+ const uint16x8_t max_coeff_thresh = vdupq_n_u16(MAX_COEFF_THRESH);
+ int j;
+ int distribution[MAX_COEFF_THRESH + 1] = { 0 };
+ for (j = start_block; j < end_block; ++j) {
+ int16_t out[16];
+ FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
+ {
+ int k;
+ const int16x8_t a0 = vld1q_s16(out + 0);
+ const int16x8_t b0 = vld1q_s16(out + 8);
+ const uint16x8_t a1 = vreinterpretq_u16_s16(vabsq_s16(a0));
+ const uint16x8_t b1 = vreinterpretq_u16_s16(vabsq_s16(b0));
+ const uint16x8_t a2 = vshrq_n_u16(a1, 3);
+ const uint16x8_t b2 = vshrq_n_u16(b1, 3);
+ const uint16x8_t a3 = vminq_u16(a2, max_coeff_thresh);
+ const uint16x8_t b3 = vminq_u16(b2, max_coeff_thresh);
+ vst1q_s16(out + 0, vreinterpretq_s16_u16(a3));
+ vst1q_s16(out + 8, vreinterpretq_s16_u16(b3));
+ // Convert coefficients to bin.
+ for (k = 0; k < 16; ++k) {
+ ++distribution[out[k]];
+ }
+ }
+ }
+ VP8SetHistogramData(distribution, histo);
+}
+
+//------------------------------------------------------------------------------
+
+static WEBP_INLINE void AccumulateSSE16(const uint8_t* const a,
+ const uint8_t* const b,
+ uint32x4_t* const sum) {
+ const uint8x16_t a0 = vld1q_u8(a);
+ const uint8x16_t b0 = vld1q_u8(b);
+ const uint8x16_t abs_diff = vabdq_u8(a0, b0);
+ uint16x8_t prod = vmull_u8(vget_low_u8(abs_diff), vget_low_u8(abs_diff));
+ prod = vmlal_u8(prod, vget_high_u8(abs_diff), vget_high_u8(abs_diff));
+ *sum = vpadalq_u16(*sum, prod); // pair-wise add and accumulate
+}
+
+// Horizontal sum of all four uint32_t values in 'sum'.
+static int SumToInt(uint32x4_t sum) {
+ const uint64x2_t sum2 = vpaddlq_u32(sum);
+ const uint64_t sum3 = vgetq_lane_u64(sum2, 0) + vgetq_lane_u64(sum2, 1);
+ return (int)sum3;
+}
+
+static int SSE16x16(const uint8_t* a, const uint8_t* b) {
+ uint32x4_t sum = vdupq_n_u32(0);
+ int y;
+ for (y = 0; y < 16; ++y) {
+ AccumulateSSE16(a + y * BPS, b + y * BPS, &sum);
+ }
+ return SumToInt(sum);
+}
+
+static int SSE16x8(const uint8_t* a, const uint8_t* b) {
+ uint32x4_t sum = vdupq_n_u32(0);
+ int y;
+ for (y = 0; y < 8; ++y) {
+ AccumulateSSE16(a + y * BPS, b + y * BPS, &sum);
+ }
+ return SumToInt(sum);
+}
+
+static int SSE8x8(const uint8_t* a, const uint8_t* b) {
+ uint32x4_t sum = vdupq_n_u32(0);
+ int y;
+ for (y = 0; y < 8; ++y) {
+ const uint8x8_t a0 = vld1_u8(a + y * BPS);
+ const uint8x8_t b0 = vld1_u8(b + y * BPS);
+ const uint8x8_t abs_diff = vabd_u8(a0, b0);
+ const uint16x8_t prod = vmull_u8(abs_diff, abs_diff);
+ sum = vpadalq_u16(sum, prod);
+ }
+ return SumToInt(sum);
+}
+
+static int SSE4x4(const uint8_t* a, const uint8_t* b) {
+ const uint8x16_t a0 = Load4x4(a);
+ const uint8x16_t b0 = Load4x4(b);
+ const uint8x16_t abs_diff = vabdq_u8(a0, b0);
+ uint16x8_t prod = vmull_u8(vget_low_u8(abs_diff), vget_low_u8(abs_diff));
+ prod = vmlal_u8(prod, vget_high_u8(abs_diff), vget_high_u8(abs_diff));
+ return SumToInt(vpaddlq_u16(prod));
+}
+
+//------------------------------------------------------------------------------
+
+// Compilation with gcc-4.6.x is problematic for now.
+#if !defined(WORK_AROUND_GCC)
+
+static int16x8_t Quantize(int16_t* const in,
+ const VP8Matrix* const mtx, int offset) {
+ const uint16x8_t sharp = vld1q_u16(&mtx->sharpen_[offset]);
+ const uint16x8_t q = vld1q_u16(&mtx->q_[offset]);
+ const uint16x8_t iq = vld1q_u16(&mtx->iq_[offset]);
+ const uint32x4_t bias0 = vld1q_u32(&mtx->bias_[offset + 0]);
+ const uint32x4_t bias1 = vld1q_u32(&mtx->bias_[offset + 4]);
+
+ const int16x8_t a = vld1q_s16(in + offset); // in
+ const uint16x8_t b = vreinterpretq_u16_s16(vabsq_s16(a)); // coeff = abs(in)
+ const int16x8_t sign = vshrq_n_s16(a, 15); // sign
+ const uint16x8_t c = vaddq_u16(b, sharp); // + sharpen
+ const uint32x4_t m0 = vmull_u16(vget_low_u16(c), vget_low_u16(iq));
+ const uint32x4_t m1 = vmull_u16(vget_high_u16(c), vget_high_u16(iq));
+ const uint32x4_t m2 = vhaddq_u32(m0, bias0);
+ const uint32x4_t m3 = vhaddq_u32(m1, bias1); // (coeff * iQ + bias) >> 1
+ const uint16x8_t c0 = vcombine_u16(vshrn_n_u32(m2, 16),
+ vshrn_n_u32(m3, 16)); // QFIX=17 = 16+1
+ const uint16x8_t c1 = vminq_u16(c0, vdupq_n_u16(MAX_LEVEL));
+ const int16x8_t c2 = veorq_s16(vreinterpretq_s16_u16(c1), sign);
+ const int16x8_t c3 = vsubq_s16(c2, sign); // restore sign
+ const int16x8_t c4 = vmulq_s16(c3, vreinterpretq_s16_u16(q));
+ vst1q_s16(in + offset, c4);
+ assert(QFIX == 17); // this function can't work as is if QFIX != 16+1
+ return c3;
+}
+
+static const uint8_t kShuffles[4][8] = {
+ { 0, 1, 2, 3, 8, 9, 16, 17 },
+ { 10, 11, 4, 5, 6, 7, 12, 13 },
+ { 18, 19, 24, 25, 26, 27, 20, 21 },
+ { 14, 15, 22, 23, 28, 29, 30, 31 }
+};
+
+static int QuantizeBlock(int16_t in[16], int16_t out[16],
+ const VP8Matrix* const mtx) {
+ const int16x8_t out0 = Quantize(in, mtx, 0);
+ const int16x8_t out1 = Quantize(in, mtx, 8);
+ uint8x8x4_t shuffles;
+ // vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use
+ // non-standard versions there.
+#if defined(__APPLE__) && defined(__aarch64__) && \
+ defined(__apple_build_version__) && (__apple_build_version__< 6020037)
+ uint8x16x2_t all_out;
+ INIT_VECTOR2(all_out, vreinterpretq_u8_s16(out0), vreinterpretq_u8_s16(out1));
+ INIT_VECTOR4(shuffles,
+ vtbl2q_u8(all_out, vld1_u8(kShuffles[0])),
+ vtbl2q_u8(all_out, vld1_u8(kShuffles[1])),
+ vtbl2q_u8(all_out, vld1_u8(kShuffles[2])),
+ vtbl2q_u8(all_out, vld1_u8(kShuffles[3])));
+#else
+ uint8x8x4_t all_out;
+ INIT_VECTOR4(all_out,
+ vreinterpret_u8_s16(vget_low_s16(out0)),
+ vreinterpret_u8_s16(vget_high_s16(out0)),
+ vreinterpret_u8_s16(vget_low_s16(out1)),
+ vreinterpret_u8_s16(vget_high_s16(out1)));
+ INIT_VECTOR4(shuffles,
+ vtbl4_u8(all_out, vld1_u8(kShuffles[0])),
+ vtbl4_u8(all_out, vld1_u8(kShuffles[1])),
+ vtbl4_u8(all_out, vld1_u8(kShuffles[2])),
+ vtbl4_u8(all_out, vld1_u8(kShuffles[3])));
+#endif
+ // Zigzag reordering
+ vst1_u8((uint8_t*)(out + 0), shuffles.val[0]);
+ vst1_u8((uint8_t*)(out + 4), shuffles.val[1]);
+ vst1_u8((uint8_t*)(out + 8), shuffles.val[2]);
+ vst1_u8((uint8_t*)(out + 12), shuffles.val[3]);
+ // test zeros
+ if (*(uint64_t*)(out + 0) != 0) return 1;
+ if (*(uint64_t*)(out + 4) != 0) return 1;
+ if (*(uint64_t*)(out + 8) != 0) return 1;
+ if (*(uint64_t*)(out + 12) != 0) return 1;
+ return 0;
+}
+
+static int Quantize2Blocks(int16_t in[32], int16_t out[32],
+ const VP8Matrix* const mtx) {
+ int nz;
+ nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0;
+ nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1;
+ return nz;
+}
+
+#endif // !WORK_AROUND_GCC
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8EncDspInitNEON(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitNEON(void) {
+ VP8ITransform = ITransform;
+ VP8FTransform = FTransform;
+
+ VP8FTransformWHT = FTransformWHT;
+
+ VP8TDisto4x4 = Disto4x4;
+ VP8TDisto16x16 = Disto16x16;
+ VP8CollectHistogram = CollectHistogram;
+ VP8SSE16x16 = SSE16x16;
+ VP8SSE16x8 = SSE16x8;
+ VP8SSE8x8 = SSE8x8;
+ VP8SSE4x4 = SSE4x4;
+#if !defined(WORK_AROUND_GCC)
+ VP8EncQuantizeBlock = QuantizeBlock;
+ VP8EncQuantize2Blocks = Quantize2Blocks;
+#endif
+}
+
+#else // !WEBP_USE_NEON
+
+WEBP_DSP_INIT_STUB(VP8EncDspInitNEON)
+
+#endif // WEBP_USE_NEON
diff --git a/drivers/webp/dsp/enc_sse2.c b/drivers/webp/dsp/enc_sse2.c
index b046761dc1..63d9cecd85 100644
--- a/drivers/webp/dsp/enc_sse2.c
+++ b/drivers/webp/dsp/enc_sse2.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// SSE2 version of speed-critical encoding functions.
@@ -15,64 +17,55 @@
#include <stdlib.h> // for abs()
#include <emmintrin.h>
+#include "../enc/cost.h"
#include "../enc/vp8enci.h"
+#include "../utils/utils.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
+//------------------------------------------------------------------------------
+// Quite useful macro for debugging. Left here for convenience.
+
+#if 0
+#include <stdio.h>
+static void PrintReg(const __m128i r, const char* const name, int size) {
+ int n;
+ union {
+ __m128i r;
+ uint8_t i8[16];
+ uint16_t i16[8];
+ uint32_t i32[4];
+ uint64_t i64[2];
+ } tmp;
+ tmp.r = r;
+ fprintf(stderr, "%s\t: ", name);
+ if (size == 8) {
+ for (n = 0; n < 16; ++n) fprintf(stderr, "%.2x ", tmp.i8[n]);
+ } else if (size == 16) {
+ for (n = 0; n < 8; ++n) fprintf(stderr, "%.4x ", tmp.i16[n]);
+ } else if (size == 32) {
+ for (n = 0; n < 4; ++n) fprintf(stderr, "%.8x ", tmp.i32[n]);
+ } else {
+ for (n = 0; n < 2; ++n) fprintf(stderr, "%.16lx ", tmp.i64[n]);
+ }
+ fprintf(stderr, "\n");
+}
#endif
//------------------------------------------------------------------------------
-// Compute susceptibility based on DCT-coeff histograms:
-// the higher, the "easier" the macroblock is to compress.
-
-static int CollectHistogramSSE2(const uint8_t* ref, const uint8_t* pred,
- int start_block, int end_block) {
- int histo[MAX_COEFF_THRESH + 1] = { 0 };
- int16_t out[16];
- int j, k;
- const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH);
- for (j = start_block; j < end_block; ++j) {
- VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
-
- // Convert coefficients to bin (within out[]).
- {
- // Load.
- const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]);
- const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]);
- // sign(out) = out >> 15 (0x0000 if positive, 0xffff if negative)
- const __m128i sign0 = _mm_srai_epi16(out0, 15);
- const __m128i sign1 = _mm_srai_epi16(out1, 15);
- // abs(out) = (out ^ sign) - sign
- const __m128i xor0 = _mm_xor_si128(out0, sign0);
- const __m128i xor1 = _mm_xor_si128(out1, sign1);
- const __m128i abs0 = _mm_sub_epi16(xor0, sign0);
- const __m128i abs1 = _mm_sub_epi16(xor1, sign1);
- // v = abs(out) >> 2
- const __m128i v0 = _mm_srai_epi16(abs0, 2);
- const __m128i v1 = _mm_srai_epi16(abs1, 2);
- // bin = min(v, MAX_COEFF_THRESH)
- const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh);
- const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh);
- // Store.
- _mm_storeu_si128((__m128i*)&out[0], bin0);
- _mm_storeu_si128((__m128i*)&out[8], bin1);
- }
+// util for unaligned loads.
- // Use bin to update histogram.
- for (k = 0; k < 16; ++k) {
- histo[out[k]]++;
- }
- }
-
- return VP8GetAlpha(histo);
+// memcpy() is the safe way of moving potentially unaligned 32b memory.
+static WEBP_INLINE uint32_t MemToUint32(const uint8_t* const ptr) {
+ uint32_t A;
+ memcpy(&A, (const int*)ptr, sizeof(A));
+ return A;
}
//------------------------------------------------------------------------------
// Transforms (Paragraph 14.4)
// Does one or two inverse transforms.
-static void ITransformSSE2(const uint8_t* ref, const int16_t* in, uint8_t* dst,
- int do_two) {
+static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst,
+ int do_two) {
// This implementation makes use of 16-bit fixed point versions of two
// multiply constants:
// K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16
@@ -99,19 +92,19 @@ static void ITransformSSE2(const uint8_t* ref, const int16_t* in, uint8_t* dst,
// use nor store.
__m128i in0, in1, in2, in3;
{
- in0 = _mm_loadl_epi64((__m128i*)&in[0]);
- in1 = _mm_loadl_epi64((__m128i*)&in[4]);
- in2 = _mm_loadl_epi64((__m128i*)&in[8]);
- in3 = _mm_loadl_epi64((__m128i*)&in[12]);
+ in0 = _mm_loadl_epi64((const __m128i*)&in[0]);
+ in1 = _mm_loadl_epi64((const __m128i*)&in[4]);
+ in2 = _mm_loadl_epi64((const __m128i*)&in[8]);
+ in3 = _mm_loadl_epi64((const __m128i*)&in[12]);
// a00 a10 a20 a30 x x x x
// a01 a11 a21 a31 x x x x
// a02 a12 a22 a32 x x x x
// a03 a13 a23 a33 x x x x
if (do_two) {
- const __m128i inB0 = _mm_loadl_epi64((__m128i*)&in[16]);
- const __m128i inB1 = _mm_loadl_epi64((__m128i*)&in[20]);
- const __m128i inB2 = _mm_loadl_epi64((__m128i*)&in[24]);
- const __m128i inB3 = _mm_loadl_epi64((__m128i*)&in[28]);
+ const __m128i inB0 = _mm_loadl_epi64((const __m128i*)&in[16]);
+ const __m128i inB1 = _mm_loadl_epi64((const __m128i*)&in[20]);
+ const __m128i inB2 = _mm_loadl_epi64((const __m128i*)&in[24]);
+ const __m128i inB3 = _mm_loadl_epi64((const __m128i*)&in[28]);
in0 = _mm_unpacklo_epi64(in0, inB0);
in1 = _mm_unpacklo_epi64(in1, inB1);
in2 = _mm_unpacklo_epi64(in2, inB2);
@@ -243,21 +236,21 @@ static void ITransformSSE2(const uint8_t* ref, const int16_t* in, uint8_t* dst,
// Add inverse transform to 'ref' and store.
{
- const __m128i zero = _mm_set1_epi16(0);
+ const __m128i zero = _mm_setzero_si128();
// Load the reference(s).
__m128i ref0, ref1, ref2, ref3;
if (do_two) {
// Load eight bytes/pixels per line.
- ref0 = _mm_loadl_epi64((__m128i*)&ref[0 * BPS]);
- ref1 = _mm_loadl_epi64((__m128i*)&ref[1 * BPS]);
- ref2 = _mm_loadl_epi64((__m128i*)&ref[2 * BPS]);
- ref3 = _mm_loadl_epi64((__m128i*)&ref[3 * BPS]);
+ ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]);
+ ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]);
+ ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]);
+ ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]);
} else {
// Load four bytes/pixels per line.
- ref0 = _mm_cvtsi32_si128(*(int*)&ref[0 * BPS]);
- ref1 = _mm_cvtsi32_si128(*(int*)&ref[1 * BPS]);
- ref2 = _mm_cvtsi32_si128(*(int*)&ref[2 * BPS]);
- ref3 = _mm_cvtsi32_si128(*(int*)&ref[3 * BPS]);
+ ref0 = _mm_cvtsi32_si128(MemToUint32(&ref[0 * BPS]));
+ ref1 = _mm_cvtsi32_si128(MemToUint32(&ref[1 * BPS]));
+ ref2 = _mm_cvtsi32_si128(MemToUint32(&ref[2 * BPS]));
+ ref3 = _mm_cvtsi32_si128(MemToUint32(&ref[3 * BPS]));
}
// Convert to 16b.
ref0 = _mm_unpacklo_epi8(ref0, zero);
@@ -291,200 +284,865 @@ static void ITransformSSE2(const uint8_t* ref, const int16_t* in, uint8_t* dst,
}
}
-static void FTransformSSE2(const uint8_t* src, const uint8_t* ref,
- int16_t* out) {
+static void FTransformPass1(const __m128i* const in01,
+ const __m128i* const in23,
+ __m128i* const out01,
+ __m128i* const out32) {
+ const __m128i k937 = _mm_set1_epi32(937);
+ const __m128i k1812 = _mm_set1_epi32(1812);
+
+ const __m128i k88p = _mm_set_epi16(8, 8, 8, 8, 8, 8, 8, 8);
+ const __m128i k88m = _mm_set_epi16(-8, 8, -8, 8, -8, 8, -8, 8);
+ const __m128i k5352_2217p = _mm_set_epi16(2217, 5352, 2217, 5352,
+ 2217, 5352, 2217, 5352);
+ const __m128i k5352_2217m = _mm_set_epi16(-5352, 2217, -5352, 2217,
+ -5352, 2217, -5352, 2217);
+
+ // *in01 = 00 01 10 11 02 03 12 13
+ // *in23 = 20 21 30 31 22 23 32 33
+ const __m128i shuf01_p = _mm_shufflehi_epi16(*in01, _MM_SHUFFLE(2, 3, 0, 1));
+ const __m128i shuf23_p = _mm_shufflehi_epi16(*in23, _MM_SHUFFLE(2, 3, 0, 1));
+ // 00 01 10 11 03 02 13 12
+ // 20 21 30 31 23 22 33 32
+ const __m128i s01 = _mm_unpacklo_epi64(shuf01_p, shuf23_p);
+ const __m128i s32 = _mm_unpackhi_epi64(shuf01_p, shuf23_p);
+ // 00 01 10 11 20 21 30 31
+ // 03 02 13 12 23 22 33 32
+ const __m128i a01 = _mm_add_epi16(s01, s32);
+ const __m128i a32 = _mm_sub_epi16(s01, s32);
+ // [d0 + d3 | d1 + d2 | ...] = [a0 a1 | a0' a1' | ... ]
+ // [d0 - d3 | d1 - d2 | ...] = [a3 a2 | a3' a2' | ... ]
+
+ const __m128i tmp0 = _mm_madd_epi16(a01, k88p); // [ (a0 + a1) << 3, ... ]
+ const __m128i tmp2 = _mm_madd_epi16(a01, k88m); // [ (a0 - a1) << 3, ... ]
+ const __m128i tmp1_1 = _mm_madd_epi16(a32, k5352_2217p);
+ const __m128i tmp3_1 = _mm_madd_epi16(a32, k5352_2217m);
+ const __m128i tmp1_2 = _mm_add_epi32(tmp1_1, k1812);
+ const __m128i tmp3_2 = _mm_add_epi32(tmp3_1, k937);
+ const __m128i tmp1 = _mm_srai_epi32(tmp1_2, 9);
+ const __m128i tmp3 = _mm_srai_epi32(tmp3_2, 9);
+ const __m128i s03 = _mm_packs_epi32(tmp0, tmp2);
+ const __m128i s12 = _mm_packs_epi32(tmp1, tmp3);
+ const __m128i s_lo = _mm_unpacklo_epi16(s03, s12); // 0 1 0 1 0 1...
+ const __m128i s_hi = _mm_unpackhi_epi16(s03, s12); // 2 3 2 3 2 3
+ const __m128i v23 = _mm_unpackhi_epi32(s_lo, s_hi);
+ *out01 = _mm_unpacklo_epi32(s_lo, s_hi);
+ *out32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2)); // 3 2 3 2 3 2..
+}
+
+static void FTransformPass2(const __m128i* const v01, const __m128i* const v32,
+ int16_t* out) {
const __m128i zero = _mm_setzero_si128();
const __m128i seven = _mm_set1_epi16(7);
- const __m128i k7500 = _mm_set1_epi32(7500);
- const __m128i k14500 = _mm_set1_epi32(14500);
- const __m128i k51000 = _mm_set1_epi32(51000);
- const __m128i k12000_plus_one = _mm_set1_epi32(12000 + (1 << 16));
const __m128i k5352_2217 = _mm_set_epi16(5352, 2217, 5352, 2217,
5352, 2217, 5352, 2217);
const __m128i k2217_5352 = _mm_set_epi16(2217, -5352, 2217, -5352,
2217, -5352, 2217, -5352);
+ const __m128i k12000_plus_one = _mm_set1_epi32(12000 + (1 << 16));
+ const __m128i k51000 = _mm_set1_epi32(51000);
+
+ // Same operations are done on the (0,3) and (1,2) pairs.
+ // a0 = v0 + v3
+ // a1 = v1 + v2
+ // a3 = v0 - v3
+ // a2 = v1 - v2
+ const __m128i a01 = _mm_add_epi16(*v01, *v32);
+ const __m128i a32 = _mm_sub_epi16(*v01, *v32);
+ const __m128i a11 = _mm_unpackhi_epi64(a01, a01);
+ const __m128i a22 = _mm_unpackhi_epi64(a32, a32);
+ const __m128i a01_plus_7 = _mm_add_epi16(a01, seven);
+
+ // d0 = (a0 + a1 + 7) >> 4;
+ // d2 = (a0 - a1 + 7) >> 4;
+ const __m128i c0 = _mm_add_epi16(a01_plus_7, a11);
+ const __m128i c2 = _mm_sub_epi16(a01_plus_7, a11);
+ const __m128i d0 = _mm_srai_epi16(c0, 4);
+ const __m128i d2 = _mm_srai_epi16(c2, 4);
+
+ // f1 = ((b3 * 5352 + b2 * 2217 + 12000) >> 16)
+ // f3 = ((b3 * 2217 - b2 * 5352 + 51000) >> 16)
+ const __m128i b23 = _mm_unpacklo_epi16(a22, a32);
+ const __m128i c1 = _mm_madd_epi16(b23, k5352_2217);
+ const __m128i c3 = _mm_madd_epi16(b23, k2217_5352);
+ const __m128i d1 = _mm_add_epi32(c1, k12000_plus_one);
+ const __m128i d3 = _mm_add_epi32(c3, k51000);
+ const __m128i e1 = _mm_srai_epi32(d1, 16);
+ const __m128i e3 = _mm_srai_epi32(d3, 16);
+ const __m128i f1 = _mm_packs_epi32(e1, e1);
+ const __m128i f3 = _mm_packs_epi32(e3, e3);
+ // f1 = f1 + (a3 != 0);
+ // The compare will return (0xffff, 0) for (==0, !=0). To turn that into the
+ // desired (0, 1), we add one earlier through k12000_plus_one.
+ // -> f1 = f1 + 1 - (a3 == 0)
+ const __m128i g1 = _mm_add_epi16(f1, _mm_cmpeq_epi16(a32, zero));
+
+ const __m128i d0_g1 = _mm_unpacklo_epi64(d0, g1);
+ const __m128i d2_f3 = _mm_unpacklo_epi64(d2, f3);
+ _mm_storeu_si128((__m128i*)&out[0], d0_g1);
+ _mm_storeu_si128((__m128i*)&out[8], d2_f3);
+}
+
+static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) {
+ const __m128i zero = _mm_setzero_si128();
+ // Load src and convert to 16b.
+ const __m128i src0 = _mm_loadl_epi64((const __m128i*)&src[0 * BPS]);
+ const __m128i src1 = _mm_loadl_epi64((const __m128i*)&src[1 * BPS]);
+ const __m128i src2 = _mm_loadl_epi64((const __m128i*)&src[2 * BPS]);
+ const __m128i src3 = _mm_loadl_epi64((const __m128i*)&src[3 * BPS]);
+ const __m128i src_0 = _mm_unpacklo_epi8(src0, zero);
+ const __m128i src_1 = _mm_unpacklo_epi8(src1, zero);
+ const __m128i src_2 = _mm_unpacklo_epi8(src2, zero);
+ const __m128i src_3 = _mm_unpacklo_epi8(src3, zero);
+ // Load ref and convert to 16b.
+ const __m128i ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]);
+ const __m128i ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]);
+ const __m128i ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]);
+ const __m128i ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]);
+ const __m128i ref_0 = _mm_unpacklo_epi8(ref0, zero);
+ const __m128i ref_1 = _mm_unpacklo_epi8(ref1, zero);
+ const __m128i ref_2 = _mm_unpacklo_epi8(ref2, zero);
+ const __m128i ref_3 = _mm_unpacklo_epi8(ref3, zero);
+ // Compute difference. -> 00 01 02 03 00 00 00 00
+ const __m128i diff0 = _mm_sub_epi16(src_0, ref_0);
+ const __m128i diff1 = _mm_sub_epi16(src_1, ref_1);
+ const __m128i diff2 = _mm_sub_epi16(src_2, ref_2);
+ const __m128i diff3 = _mm_sub_epi16(src_3, ref_3);
+
+ // Unpack and shuffle
+ // 00 01 02 03 0 0 0 0
+ // 10 11 12 13 0 0 0 0
+ // 20 21 22 23 0 0 0 0
+ // 30 31 32 33 0 0 0 0
+ const __m128i shuf01 = _mm_unpacklo_epi32(diff0, diff1);
+ const __m128i shuf23 = _mm_unpacklo_epi32(diff2, diff3);
__m128i v01, v32;
- // Difference between src and ref and initial transpose.
- {
- // Load src and convert to 16b.
- const __m128i src0 = _mm_loadl_epi64((__m128i*)&src[0 * BPS]);
- const __m128i src1 = _mm_loadl_epi64((__m128i*)&src[1 * BPS]);
- const __m128i src2 = _mm_loadl_epi64((__m128i*)&src[2 * BPS]);
- const __m128i src3 = _mm_loadl_epi64((__m128i*)&src[3 * BPS]);
- const __m128i src_0 = _mm_unpacklo_epi8(src0, zero);
- const __m128i src_1 = _mm_unpacklo_epi8(src1, zero);
- const __m128i src_2 = _mm_unpacklo_epi8(src2, zero);
- const __m128i src_3 = _mm_unpacklo_epi8(src3, zero);
- // Load ref and convert to 16b.
- const __m128i ref0 = _mm_loadl_epi64((__m128i*)&ref[0 * BPS]);
- const __m128i ref1 = _mm_loadl_epi64((__m128i*)&ref[1 * BPS]);
- const __m128i ref2 = _mm_loadl_epi64((__m128i*)&ref[2 * BPS]);
- const __m128i ref3 = _mm_loadl_epi64((__m128i*)&ref[3 * BPS]);
- const __m128i ref_0 = _mm_unpacklo_epi8(ref0, zero);
- const __m128i ref_1 = _mm_unpacklo_epi8(ref1, zero);
- const __m128i ref_2 = _mm_unpacklo_epi8(ref2, zero);
- const __m128i ref_3 = _mm_unpacklo_epi8(ref3, zero);
- // Compute difference.
- const __m128i diff0 = _mm_sub_epi16(src_0, ref_0);
- const __m128i diff1 = _mm_sub_epi16(src_1, ref_1);
- const __m128i diff2 = _mm_sub_epi16(src_2, ref_2);
- const __m128i diff3 = _mm_sub_epi16(src_3, ref_3);
-
- // Transpose.
- // 00 01 02 03 0 0 0 0
- // 10 11 12 13 0 0 0 0
- // 20 21 22 23 0 0 0 0
- // 30 31 32 33 0 0 0 0
- const __m128i transpose0_0 = _mm_unpacklo_epi16(diff0, diff1);
- const __m128i transpose0_1 = _mm_unpacklo_epi16(diff2, diff3);
- // 00 10 01 11 02 12 03 13
- // 20 30 21 31 22 32 23 33
- const __m128i v23 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
- v01 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
- v32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2));
- // a02 a12 a22 a32 a03 a13 a23 a33
- // a00 a10 a20 a30 a01 a11 a21 a31
- // a03 a13 a23 a33 a02 a12 a22 a32
- }
-
- // First pass and subsequent transpose.
- {
- // Same operations are done on the (0,3) and (1,2) pairs.
- // b0 = (a0 + a3) << 3
- // b1 = (a1 + a2) << 3
- // b3 = (a0 - a3) << 3
- // b2 = (a1 - a2) << 3
- const __m128i a01 = _mm_add_epi16(v01, v32);
- const __m128i a32 = _mm_sub_epi16(v01, v32);
- const __m128i b01 = _mm_slli_epi16(a01, 3);
- const __m128i b32 = _mm_slli_epi16(a32, 3);
- const __m128i b11 = _mm_unpackhi_epi64(b01, b01);
- const __m128i b22 = _mm_unpackhi_epi64(b32, b32);
-
- // e0 = b0 + b1
- // e2 = b0 - b1
- const __m128i e0 = _mm_add_epi16(b01, b11);
- const __m128i e2 = _mm_sub_epi16(b01, b11);
- const __m128i e02 = _mm_unpacklo_epi64(e0, e2);
-
- // e1 = (b3 * 5352 + b2 * 2217 + 14500) >> 12
- // e3 = (b3 * 2217 - b2 * 5352 + 7500) >> 12
- const __m128i b23 = _mm_unpacklo_epi16(b22, b32);
- const __m128i c1 = _mm_madd_epi16(b23, k5352_2217);
- const __m128i c3 = _mm_madd_epi16(b23, k2217_5352);
- const __m128i d1 = _mm_add_epi32(c1, k14500);
- const __m128i d3 = _mm_add_epi32(c3, k7500);
- const __m128i e1 = _mm_srai_epi32(d1, 12);
- const __m128i e3 = _mm_srai_epi32(d3, 12);
- const __m128i e13 = _mm_packs_epi32(e1, e3);
-
- // Transpose.
- // 00 01 02 03 20 21 22 23
- // 10 11 12 13 30 31 32 33
- const __m128i transpose0_0 = _mm_unpacklo_epi16(e02, e13);
- const __m128i transpose0_1 = _mm_unpackhi_epi16(e02, e13);
- // 00 10 01 11 02 12 03 13
- // 20 30 21 31 22 32 23 33
- const __m128i v23 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
- v01 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
- v32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2));
- // 02 12 22 32 03 13 23 33
- // 00 10 20 30 01 11 21 31
- // 03 13 23 33 02 12 22 32
- }
+ // First pass
+ FTransformPass1(&shuf01, &shuf23, &v01, &v32);
// Second pass
+ FTransformPass2(&v01, &v32, out);
+}
+
+static void FTransform2(const uint8_t* src, const uint8_t* ref, int16_t* out) {
+ const __m128i zero = _mm_setzero_si128();
+
+ // Load src and convert to 16b.
+ const __m128i src0 = _mm_loadl_epi64((const __m128i*)&src[0 * BPS]);
+ const __m128i src1 = _mm_loadl_epi64((const __m128i*)&src[1 * BPS]);
+ const __m128i src2 = _mm_loadl_epi64((const __m128i*)&src[2 * BPS]);
+ const __m128i src3 = _mm_loadl_epi64((const __m128i*)&src[3 * BPS]);
+ const __m128i src_0 = _mm_unpacklo_epi8(src0, zero);
+ const __m128i src_1 = _mm_unpacklo_epi8(src1, zero);
+ const __m128i src_2 = _mm_unpacklo_epi8(src2, zero);
+ const __m128i src_3 = _mm_unpacklo_epi8(src3, zero);
+ // Load ref and convert to 16b.
+ const __m128i ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]);
+ const __m128i ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]);
+ const __m128i ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]);
+ const __m128i ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]);
+ const __m128i ref_0 = _mm_unpacklo_epi8(ref0, zero);
+ const __m128i ref_1 = _mm_unpacklo_epi8(ref1, zero);
+ const __m128i ref_2 = _mm_unpacklo_epi8(ref2, zero);
+ const __m128i ref_3 = _mm_unpacklo_epi8(ref3, zero);
+ // Compute difference. -> 00 01 02 03 00' 01' 02' 03'
+ const __m128i diff0 = _mm_sub_epi16(src_0, ref_0);
+ const __m128i diff1 = _mm_sub_epi16(src_1, ref_1);
+ const __m128i diff2 = _mm_sub_epi16(src_2, ref_2);
+ const __m128i diff3 = _mm_sub_epi16(src_3, ref_3);
+
+ // Unpack and shuffle
+ // 00 01 02 03 0 0 0 0
+ // 10 11 12 13 0 0 0 0
+ // 20 21 22 23 0 0 0 0
+ // 30 31 32 33 0 0 0 0
+ const __m128i shuf01l = _mm_unpacklo_epi32(diff0, diff1);
+ const __m128i shuf23l = _mm_unpacklo_epi32(diff2, diff3);
+ const __m128i shuf01h = _mm_unpackhi_epi32(diff0, diff1);
+ const __m128i shuf23h = _mm_unpackhi_epi32(diff2, diff3);
+ __m128i v01l, v32l;
+ __m128i v01h, v32h;
+
+ // First pass
+ FTransformPass1(&shuf01l, &shuf23l, &v01l, &v32l);
+ FTransformPass1(&shuf01h, &shuf23h, &v01h, &v32h);
+
+ // Second pass
+ FTransformPass2(&v01l, &v32l, out + 0);
+ FTransformPass2(&v01h, &v32h, out + 16);
+}
+
+static void FTransformWHTRow(const int16_t* const in, __m128i* const out) {
+ const __m128i kMult1 = _mm_set_epi16(0, 0, 0, 0, 1, 1, 1, 1);
+ const __m128i kMult2 = _mm_set_epi16(0, 0, 0, 0, -1, 1, -1, 1);
+ const __m128i src0 = _mm_loadl_epi64((__m128i*)&in[0 * 16]);
+ const __m128i src1 = _mm_loadl_epi64((__m128i*)&in[1 * 16]);
+ const __m128i src2 = _mm_loadl_epi64((__m128i*)&in[2 * 16]);
+ const __m128i src3 = _mm_loadl_epi64((__m128i*)&in[3 * 16]);
+ const __m128i A01 = _mm_unpacklo_epi16(src0, src1); // A0 A1 | ...
+ const __m128i A23 = _mm_unpacklo_epi16(src2, src3); // A2 A3 | ...
+ const __m128i B0 = _mm_adds_epi16(A01, A23); // a0 | a1 | ...
+ const __m128i B1 = _mm_subs_epi16(A01, A23); // a3 | a2 | ...
+ const __m128i C0 = _mm_unpacklo_epi32(B0, B1); // a0 | a1 | a3 | a2
+ const __m128i C1 = _mm_unpacklo_epi32(B1, B0); // a3 | a2 | a0 | a1
+ const __m128i D0 = _mm_madd_epi16(C0, kMult1); // out0, out1
+ const __m128i D1 = _mm_madd_epi16(C1, kMult2); // out2, out3
+ *out = _mm_unpacklo_epi64(D0, D1);
+}
+
+static void FTransformWHT(const int16_t* in, int16_t* out) {
+ __m128i row0, row1, row2, row3;
+ FTransformWHTRow(in + 0 * 64, &row0);
+ FTransformWHTRow(in + 1 * 64, &row1);
+ FTransformWHTRow(in + 2 * 64, &row2);
+ FTransformWHTRow(in + 3 * 64, &row3);
+
{
- // Same operations are done on the (0,3) and (1,2) pairs.
- // a0 = v0 + v3
- // a1 = v1 + v2
- // a3 = v0 - v3
- // a2 = v1 - v2
- const __m128i a01 = _mm_add_epi16(v01, v32);
- const __m128i a32 = _mm_sub_epi16(v01, v32);
- const __m128i a11 = _mm_unpackhi_epi64(a01, a01);
- const __m128i a22 = _mm_unpackhi_epi64(a32, a32);
-
- // d0 = (a0 + a1 + 7) >> 4;
- // d2 = (a0 - a1 + 7) >> 4;
- const __m128i b0 = _mm_add_epi16(a01, a11);
- const __m128i b2 = _mm_sub_epi16(a01, a11);
- const __m128i c0 = _mm_add_epi16(b0, seven);
- const __m128i c2 = _mm_add_epi16(b2, seven);
- const __m128i d0 = _mm_srai_epi16(c0, 4);
- const __m128i d2 = _mm_srai_epi16(c2, 4);
-
- // f1 = ((b3 * 5352 + b2 * 2217 + 12000) >> 16)
- // f3 = ((b3 * 2217 - b2 * 5352 + 51000) >> 16)
- const __m128i b23 = _mm_unpacklo_epi16(a22, a32);
- const __m128i c1 = _mm_madd_epi16(b23, k5352_2217);
- const __m128i c3 = _mm_madd_epi16(b23, k2217_5352);
- const __m128i d1 = _mm_add_epi32(c1, k12000_plus_one);
- const __m128i d3 = _mm_add_epi32(c3, k51000);
- const __m128i e1 = _mm_srai_epi32(d1, 16);
- const __m128i e3 = _mm_srai_epi32(d3, 16);
- const __m128i f1 = _mm_packs_epi32(e1, e1);
- const __m128i f3 = _mm_packs_epi32(e3, e3);
- // f1 = f1 + (a3 != 0);
- // The compare will return (0xffff, 0) for (==0, !=0). To turn that into the
- // desired (0, 1), we add one earlier through k12000_plus_one.
- const __m128i g1 = _mm_add_epi16(f1, _mm_cmpeq_epi16(a32, zero));
-
- _mm_storel_epi64((__m128i*)&out[ 0], d0);
- _mm_storel_epi64((__m128i*)&out[ 4], g1);
- _mm_storel_epi64((__m128i*)&out[ 8], d2);
- _mm_storel_epi64((__m128i*)&out[12], f3);
+ const __m128i a0 = _mm_add_epi32(row0, row2);
+ const __m128i a1 = _mm_add_epi32(row1, row3);
+ const __m128i a2 = _mm_sub_epi32(row1, row3);
+ const __m128i a3 = _mm_sub_epi32(row0, row2);
+ const __m128i b0 = _mm_srai_epi32(_mm_add_epi32(a0, a1), 1);
+ const __m128i b1 = _mm_srai_epi32(_mm_add_epi32(a3, a2), 1);
+ const __m128i b2 = _mm_srai_epi32(_mm_sub_epi32(a3, a2), 1);
+ const __m128i b3 = _mm_srai_epi32(_mm_sub_epi32(a0, a1), 1);
+ const __m128i out0 = _mm_packs_epi32(b0, b1);
+ const __m128i out1 = _mm_packs_epi32(b2, b3);
+ _mm_storeu_si128((__m128i*)&out[0], out0);
+ _mm_storeu_si128((__m128i*)&out[8], out1);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Compute susceptibility based on DCT-coeff histograms:
+// the higher, the "easier" the macroblock is to compress.
+
+static void CollectHistogram(const uint8_t* ref, const uint8_t* pred,
+ int start_block, int end_block,
+ VP8Histogram* const histo) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH);
+ int j;
+ int distribution[MAX_COEFF_THRESH + 1] = { 0 };
+ for (j = start_block; j < end_block; ++j) {
+ int16_t out[16];
+ int k;
+
+ FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
+
+ // Convert coefficients to bin (within out[]).
+ {
+ // Load.
+ const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]);
+ const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]);
+ const __m128i d0 = _mm_sub_epi16(zero, out0);
+ const __m128i d1 = _mm_sub_epi16(zero, out1);
+ const __m128i abs0 = _mm_max_epi16(out0, d0); // abs(v), 16b
+ const __m128i abs1 = _mm_max_epi16(out1, d1);
+ // v = abs(out) >> 3
+ const __m128i v0 = _mm_srai_epi16(abs0, 3);
+ const __m128i v1 = _mm_srai_epi16(abs1, 3);
+ // bin = min(v, MAX_COEFF_THRESH)
+ const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh);
+ const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh);
+ // Store.
+ _mm_storeu_si128((__m128i*)&out[0], bin0);
+ _mm_storeu_si128((__m128i*)&out[8], bin1);
+ }
+
+ // Convert coefficients to bin.
+ for (k = 0; k < 16; ++k) {
+ ++distribution[out[k]];
+ }
}
+ VP8SetHistogramData(distribution, histo);
+}
+
+//------------------------------------------------------------------------------
+// Intra predictions
+
+// helper for chroma-DC predictions
+static WEBP_INLINE void Put8x8uv(uint8_t v, uint8_t* dst) {
+ int j;
+ const __m128i values = _mm_set1_epi8(v);
+ for (j = 0; j < 8; ++j) {
+ _mm_storel_epi64((__m128i*)(dst + j * BPS), values);
+ }
+}
+
+static WEBP_INLINE void Put16(uint8_t v, uint8_t* dst) {
+ int j;
+ const __m128i values = _mm_set1_epi8(v);
+ for (j = 0; j < 16; ++j) {
+ _mm_store_si128((__m128i*)(dst + j * BPS), values);
+ }
+}
+
+static WEBP_INLINE void Fill(uint8_t* dst, int value, int size) {
+ if (size == 4) {
+ int j;
+ for (j = 0; j < 4; ++j) {
+ memset(dst + j * BPS, value, 4);
+ }
+ } else if (size == 8) {
+ Put8x8uv(value, dst);
+ } else {
+ Put16(value, dst);
+ }
+}
+
+static WEBP_INLINE void VE8uv(uint8_t* dst, const uint8_t* top) {
+ int j;
+ const __m128i top_values = _mm_loadl_epi64((const __m128i*)top);
+ for (j = 0; j < 8; ++j) {
+ _mm_storel_epi64((__m128i*)(dst + j * BPS), top_values);
+ }
+}
+
+static WEBP_INLINE void VE16(uint8_t* dst, const uint8_t* top) {
+ const __m128i top_values = _mm_load_si128((const __m128i*)top);
+ int j;
+ for (j = 0; j < 16; ++j) {
+ _mm_store_si128((__m128i*)(dst + j * BPS), top_values);
+ }
+}
+
+static WEBP_INLINE void VerticalPred(uint8_t* dst,
+ const uint8_t* top, int size) {
+ if (top != NULL) {
+ if (size == 8) {
+ VE8uv(dst, top);
+ } else {
+ VE16(dst, top);
+ }
+ } else {
+ Fill(dst, 127, size);
+ }
+}
+
+static WEBP_INLINE void HE8uv(uint8_t* dst, const uint8_t* left) {
+ int j;
+ for (j = 0; j < 8; ++j) {
+ const __m128i values = _mm_set1_epi8(left[j]);
+ _mm_storel_epi64((__m128i*)dst, values);
+ dst += BPS;
+ }
+}
+
+static WEBP_INLINE void HE16(uint8_t* dst, const uint8_t* left) {
+ int j;
+ for (j = 0; j < 16; ++j) {
+ const __m128i values = _mm_set1_epi8(left[j]);
+ _mm_store_si128((__m128i*)dst, values);
+ dst += BPS;
+ }
+}
+
+static WEBP_INLINE void HorizontalPred(uint8_t* dst,
+ const uint8_t* left, int size) {
+ if (left != NULL) {
+ if (size == 8) {
+ HE8uv(dst, left);
+ } else {
+ HE16(dst, left);
+ }
+ } else {
+ Fill(dst, 129, size);
+ }
+}
+
+static WEBP_INLINE void TM(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top, int size) {
+ const __m128i zero = _mm_setzero_si128();
+ int y;
+ if (size == 8) {
+ const __m128i top_values = _mm_loadl_epi64((const __m128i*)top);
+ const __m128i top_base = _mm_unpacklo_epi8(top_values, zero);
+ for (y = 0; y < 8; ++y, dst += BPS) {
+ const int val = left[y] - left[-1];
+ const __m128i base = _mm_set1_epi16(val);
+ const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero);
+ _mm_storel_epi64((__m128i*)dst, out);
+ }
+ } else {
+ const __m128i top_values = _mm_load_si128((const __m128i*)top);
+ const __m128i top_base_0 = _mm_unpacklo_epi8(top_values, zero);
+ const __m128i top_base_1 = _mm_unpackhi_epi8(top_values, zero);
+ for (y = 0; y < 16; ++y, dst += BPS) {
+ const int val = left[y] - left[-1];
+ const __m128i base = _mm_set1_epi16(val);
+ const __m128i out_0 = _mm_add_epi16(base, top_base_0);
+ const __m128i out_1 = _mm_add_epi16(base, top_base_1);
+ const __m128i out = _mm_packus_epi16(out_0, out_1);
+ _mm_store_si128((__m128i*)dst, out);
+ }
+ }
+}
+
+static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top, int size) {
+ if (left != NULL) {
+ if (top != NULL) {
+ TM(dst, left, top, size);
+ } else {
+ HorizontalPred(dst, left, size);
+ }
+ } else {
+ // true motion without left samples (hence: with default 129 value)
+ // is equivalent to VE prediction where you just copy the top samples.
+ // Note that if top samples are not available, the default value is
+ // then 129, and not 127 as in the VerticalPred case.
+ if (top != NULL) {
+ VerticalPred(dst, top, size);
+ } else {
+ Fill(dst, 129, size);
+ }
+ }
+}
+
+static WEBP_INLINE void DC8uv(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i top_values = _mm_loadl_epi64((const __m128i*)top);
+ const __m128i left_values = _mm_loadl_epi64((const __m128i*)left);
+ const __m128i sum_top = _mm_sad_epu8(top_values, zero);
+ const __m128i sum_left = _mm_sad_epu8(left_values, zero);
+ const int DC = _mm_cvtsi128_si32(sum_top) + _mm_cvtsi128_si32(sum_left) + 8;
+ Put8x8uv(DC >> 4, dst);
+}
+
+static WEBP_INLINE void DC8uvNoLeft(uint8_t* dst, const uint8_t* top) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i top_values = _mm_loadl_epi64((const __m128i*)top);
+ const __m128i sum = _mm_sad_epu8(top_values, zero);
+ const int DC = _mm_cvtsi128_si32(sum) + 4;
+ Put8x8uv(DC >> 3, dst);
+}
+
+static WEBP_INLINE void DC8uvNoTop(uint8_t* dst, const uint8_t* left) {
+ // 'left' is contiguous so we can reuse the top summation.
+ DC8uvNoLeft(dst, left);
+}
+
+static WEBP_INLINE void DC8uvNoTopLeft(uint8_t* dst) {
+ Put8x8uv(0x80, dst);
+}
+
+static WEBP_INLINE void DC8uvMode(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top) {
+ if (top != NULL) {
+ if (left != NULL) { // top and left present
+ DC8uv(dst, left, top);
+ } else { // top, but no left
+ DC8uvNoLeft(dst, top);
+ }
+ } else if (left != NULL) { // left but no top
+ DC8uvNoTop(dst, left);
+ } else { // no top, no left, nothing.
+ DC8uvNoTopLeft(dst);
+ }
+}
+
+static WEBP_INLINE void DC16(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i top_row = _mm_load_si128((const __m128i*)top);
+ const __m128i left_row = _mm_load_si128((const __m128i*)left);
+ const __m128i sad8x2 = _mm_sad_epu8(top_row, zero);
+ // sum the two sads: sad8x2[0:1] + sad8x2[8:9]
+ const __m128i sum_top = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2));
+ const __m128i sad8x2_left = _mm_sad_epu8(left_row, zero);
+ // sum the two sads: sad8x2[0:1] + sad8x2[8:9]
+ const __m128i sum_left =
+ _mm_add_epi16(sad8x2_left, _mm_shuffle_epi32(sad8x2_left, 2));
+ const int DC = _mm_cvtsi128_si32(sum_top) + _mm_cvtsi128_si32(sum_left) + 16;
+ Put16(DC >> 5, dst);
+}
+
+static WEBP_INLINE void DC16NoLeft(uint8_t* dst, const uint8_t* top) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i top_row = _mm_load_si128((const __m128i*)top);
+ const __m128i sad8x2 = _mm_sad_epu8(top_row, zero);
+ // sum the two sads: sad8x2[0:1] + sad8x2[8:9]
+ const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2));
+ const int DC = _mm_cvtsi128_si32(sum) + 8;
+ Put16(DC >> 4, dst);
+}
+
+static WEBP_INLINE void DC16NoTop(uint8_t* dst, const uint8_t* left) {
+ // 'left' is contiguous so we can reuse the top summation.
+ DC16NoLeft(dst, left);
+}
+
+static WEBP_INLINE void DC16NoTopLeft(uint8_t* dst) {
+ Put16(0x80, dst);
+}
+
+static WEBP_INLINE void DC16Mode(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top) {
+ if (top != NULL) {
+ if (left != NULL) { // top and left present
+ DC16(dst, left, top);
+ } else { // top, but no left
+ DC16NoLeft(dst, top);
+ }
+ } else if (left != NULL) { // left but no top
+ DC16NoTop(dst, left);
+ } else { // no top, no left, nothing.
+ DC16NoTopLeft(dst);
+ }
+}
+
+//------------------------------------------------------------------------------
+// 4x4 predictions
+
+#define DST(x, y) dst[(x) + (y) * BPS]
+#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2)
+#define AVG2(a, b) (((a) + (b) + 1) >> 1)
+
+// We use the following 8b-arithmetic tricks:
+// (a + 2 * b + c + 2) >> 2 = (AC + b + 1) >> 1
+// where: AC = (a + c) >> 1 = [(a + c + 1) >> 1] - [(a^c) & 1]
+// and:
+// (a + 2 * b + c + 2) >> 2 = (AB + BC + 1) >> 1 - (ab|bc)&lsb
+// where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1
+// and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1
+
+static WEBP_INLINE void VE4(uint8_t* dst, const uint8_t* top) { // vertical
+ const __m128i one = _mm_set1_epi8(1);
+ const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(top - 1));
+ const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1);
+ const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2);
+ const __m128i a = _mm_avg_epu8(ABCDEFGH, CDEFGH00);
+ const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one);
+ const __m128i b = _mm_subs_epu8(a, lsb);
+ const __m128i avg = _mm_avg_epu8(b, BCDEFGH0);
+ const uint32_t vals = _mm_cvtsi128_si32(avg);
+ int i;
+ for (i = 0; i < 4; ++i) {
+ *(uint32_t*)(dst + i * BPS) = vals;
+ }
+}
+
+static WEBP_INLINE void HE4(uint8_t* dst, const uint8_t* top) { // horizontal
+ const int X = top[-1];
+ const int I = top[-2];
+ const int J = top[-3];
+ const int K = top[-4];
+ const int L = top[-5];
+ *(uint32_t*)(dst + 0 * BPS) = 0x01010101U * AVG3(X, I, J);
+ *(uint32_t*)(dst + 1 * BPS) = 0x01010101U * AVG3(I, J, K);
+ *(uint32_t*)(dst + 2 * BPS) = 0x01010101U * AVG3(J, K, L);
+ *(uint32_t*)(dst + 3 * BPS) = 0x01010101U * AVG3(K, L, L);
+}
+
+static WEBP_INLINE void DC4(uint8_t* dst, const uint8_t* top) {
+ uint32_t dc = 4;
+ int i;
+ for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i];
+ Fill(dst, dc >> 3, 4);
+}
+
+static WEBP_INLINE void LD4(uint8_t* dst, const uint8_t* top) { // Down-Left
+ const __m128i one = _mm_set1_epi8(1);
+ const __m128i ABCDEFGH = _mm_loadl_epi64((const __m128i*)top);
+ const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1);
+ const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2);
+ const __m128i CDEFGHH0 = _mm_insert_epi16(CDEFGH00, top[7], 3);
+ const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, CDEFGHH0);
+ const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one);
+ const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
+ const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0);
+ *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( abcdefg );
+ *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1));
+ *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2));
+ *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3));
+}
+
+static WEBP_INLINE void VR4(uint8_t* dst,
+ const uint8_t* top) { // Vertical-Right
+ const __m128i one = _mm_set1_epi8(1);
+ const int I = top[-2];
+ const int J = top[-3];
+ const int K = top[-4];
+ const int X = top[-1];
+ const __m128i XABCD = _mm_loadl_epi64((const __m128i*)(top - 1));
+ const __m128i ABCD0 = _mm_srli_si128(XABCD, 1);
+ const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0);
+ const __m128i _XABCD = _mm_slli_si128(XABCD, 1);
+ const __m128i IXABCD = _mm_insert_epi16(_XABCD, I | (X << 8), 0);
+ const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0);
+ const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
+ const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
+ const __m128i efgh = _mm_avg_epu8(avg2, XABCD);
+ *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( abcd );
+ *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32( efgh );
+ *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1));
+ *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1));
+
+ // these two are hard to implement in SSE2, so we keep the C-version:
+ DST(0, 2) = AVG3(J, I, X);
+ DST(0, 3) = AVG3(K, J, I);
+}
+
+static WEBP_INLINE void VL4(uint8_t* dst,
+ const uint8_t* top) { // Vertical-Left
+ const __m128i one = _mm_set1_epi8(1);
+ const __m128i ABCDEFGH = _mm_loadl_epi64((const __m128i*)top);
+ const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1);
+ const __m128i CDEFGH__ = _mm_srli_si128(ABCDEFGH, 2);
+ const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, BCDEFGH_);
+ const __m128i avg2 = _mm_avg_epu8(CDEFGH__, BCDEFGH_);
+ const __m128i avg3 = _mm_avg_epu8(avg1, avg2);
+ const __m128i lsb1 = _mm_and_si128(_mm_xor_si128(avg1, avg2), one);
+ const __m128i ab = _mm_xor_si128(ABCDEFGH, BCDEFGH_);
+ const __m128i bc = _mm_xor_si128(CDEFGH__, BCDEFGH_);
+ const __m128i abbc = _mm_or_si128(ab, bc);
+ const __m128i lsb2 = _mm_and_si128(abbc, lsb1);
+ const __m128i avg4 = _mm_subs_epu8(avg3, lsb2);
+ const uint32_t extra_out = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 4));
+ *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( avg1 );
+ *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32( avg4 );
+ *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1));
+ *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1));
+
+ // these two are hard to get and irregular
+ DST(3, 2) = (extra_out >> 0) & 0xff;
+ DST(3, 3) = (extra_out >> 8) & 0xff;
+}
+
+static WEBP_INLINE void RD4(uint8_t* dst, const uint8_t* top) { // Down-right
+ const __m128i one = _mm_set1_epi8(1);
+ const __m128i LKJIXABC = _mm_loadl_epi64((const __m128i*)(top - 5));
+ const __m128i LKJIXABCD = _mm_insert_epi16(LKJIXABC, top[3], 4);
+ const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1);
+ const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2);
+ const __m128i avg1 = _mm_avg_epu8(JIXABCD__, LKJIXABCD);
+ const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one);
+ const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
+ const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_);
+ *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32( abcdefg );
+ *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1));
+ *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2));
+ *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3));
+}
+
+static WEBP_INLINE void HU4(uint8_t* dst, const uint8_t* top) {
+ const int I = top[-2];
+ const int J = top[-3];
+ const int K = top[-4];
+ const int L = top[-5];
+ DST(0, 0) = AVG2(I, J);
+ DST(2, 0) = DST(0, 1) = AVG2(J, K);
+ DST(2, 1) = DST(0, 2) = AVG2(K, L);
+ DST(1, 0) = AVG3(I, J, K);
+ DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
+ DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
+ DST(3, 2) = DST(2, 2) =
+ DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
+}
+
+static WEBP_INLINE void HD4(uint8_t* dst, const uint8_t* top) {
+ const int X = top[-1];
+ const int I = top[-2];
+ const int J = top[-3];
+ const int K = top[-4];
+ const int L = top[-5];
+ const int A = top[0];
+ const int B = top[1];
+ const int C = top[2];
+
+ DST(0, 0) = DST(2, 1) = AVG2(I, X);
+ DST(0, 1) = DST(2, 2) = AVG2(J, I);
+ DST(0, 2) = DST(2, 3) = AVG2(K, J);
+ DST(0, 3) = AVG2(L, K);
+
+ DST(3, 0) = AVG3(A, B, C);
+ DST(2, 0) = AVG3(X, A, B);
+ DST(1, 0) = DST(3, 1) = AVG3(I, X, A);
+ DST(1, 1) = DST(3, 2) = AVG3(J, I, X);
+ DST(1, 2) = DST(3, 3) = AVG3(K, J, I);
+ DST(1, 3) = AVG3(L, K, J);
+}
+
+static WEBP_INLINE void TM4(uint8_t* dst, const uint8_t* top) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i top_values = _mm_cvtsi32_si128(MemToUint32(top));
+ const __m128i top_base = _mm_unpacklo_epi8(top_values, zero);
+ int y;
+ for (y = 0; y < 4; ++y, dst += BPS) {
+ const int val = top[-2 - y] - top[-1];
+ const __m128i base = _mm_set1_epi16(val);
+ const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero);
+ *(int*)dst = _mm_cvtsi128_si32(out);
+ }
+}
+
+#undef DST
+#undef AVG3
+#undef AVG2
+
+//------------------------------------------------------------------------------
+// luma 4x4 prediction
+
+// Left samples are top[-5 .. -2], top_left is top[-1], top are
+// located at top[0..3], and top right is top[4..7]
+static void Intra4Preds(uint8_t* dst, const uint8_t* top) {
+ DC4(I4DC4 + dst, top);
+ TM4(I4TM4 + dst, top);
+ VE4(I4VE4 + dst, top);
+ HE4(I4HE4 + dst, top);
+ RD4(I4RD4 + dst, top);
+ VR4(I4VR4 + dst, top);
+ LD4(I4LD4 + dst, top);
+ VL4(I4VL4 + dst, top);
+ HD4(I4HD4 + dst, top);
+ HU4(I4HU4 + dst, top);
+}
+
+//------------------------------------------------------------------------------
+// Chroma 8x8 prediction (paragraph 12.2)
+
+static void IntraChromaPreds(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top) {
+ // U block
+ DC8uvMode(C8DC8 + dst, left, top);
+ VerticalPred(C8VE8 + dst, top, 8);
+ HorizontalPred(C8HE8 + dst, left, 8);
+ TrueMotion(C8TM8 + dst, left, top, 8);
+ // V block
+ dst += 8;
+ if (top != NULL) top += 8;
+ if (left != NULL) left += 16;
+ DC8uvMode(C8DC8 + dst, left, top);
+ VerticalPred(C8VE8 + dst, top, 8);
+ HorizontalPred(C8HE8 + dst, left, 8);
+ TrueMotion(C8TM8 + dst, left, top, 8);
+}
+
+//------------------------------------------------------------------------------
+// luma 16x16 prediction (paragraph 12.3)
+
+static void Intra16Preds(uint8_t* dst,
+ const uint8_t* left, const uint8_t* top) {
+ DC16Mode(I16DC16 + dst, left, top);
+ VerticalPred(I16VE16 + dst, top, 16);
+ HorizontalPred(I16HE16 + dst, left, 16);
+ TrueMotion(I16TM16 + dst, left, top, 16);
}
//------------------------------------------------------------------------------
// Metric
-static int SSE4x4SSE2(const uint8_t* a, const uint8_t* b) {
- const __m128i zero = _mm_set1_epi16(0);
+static WEBP_INLINE void SubtractAndAccumulate(const __m128i a, const __m128i b,
+ __m128i* const sum) {
+ // take abs(a-b) in 8b
+ const __m128i a_b = _mm_subs_epu8(a, b);
+ const __m128i b_a = _mm_subs_epu8(b, a);
+ const __m128i abs_a_b = _mm_or_si128(a_b, b_a);
+ // zero-extend to 16b
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i C0 = _mm_unpacklo_epi8(abs_a_b, zero);
+ const __m128i C1 = _mm_unpackhi_epi8(abs_a_b, zero);
+ // multiply with self
+ const __m128i sum1 = _mm_madd_epi16(C0, C0);
+ const __m128i sum2 = _mm_madd_epi16(C1, C1);
+ *sum = _mm_add_epi32(sum1, sum2);
+}
- // Load values.
- const __m128i a0 = _mm_loadl_epi64((__m128i*)&a[BPS * 0]);
- const __m128i a1 = _mm_loadl_epi64((__m128i*)&a[BPS * 1]);
- const __m128i a2 = _mm_loadl_epi64((__m128i*)&a[BPS * 2]);
- const __m128i a3 = _mm_loadl_epi64((__m128i*)&a[BPS * 3]);
- const __m128i b0 = _mm_loadl_epi64((__m128i*)&b[BPS * 0]);
- const __m128i b1 = _mm_loadl_epi64((__m128i*)&b[BPS * 1]);
- const __m128i b2 = _mm_loadl_epi64((__m128i*)&b[BPS * 2]);
- const __m128i b3 = _mm_loadl_epi64((__m128i*)&b[BPS * 3]);
+static WEBP_INLINE int SSE_16xN(const uint8_t* a, const uint8_t* b,
+ int num_pairs) {
+ __m128i sum = _mm_setzero_si128();
+ int32_t tmp[4];
+ int i;
+
+ for (i = 0; i < num_pairs; ++i) {
+ const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[BPS * 0]);
+ const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[BPS * 0]);
+ const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[BPS * 1]);
+ const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[BPS * 1]);
+ __m128i sum1, sum2;
+ SubtractAndAccumulate(a0, b0, &sum1);
+ SubtractAndAccumulate(a1, b1, &sum2);
+ sum = _mm_add_epi32(sum, _mm_add_epi32(sum1, sum2));
+ a += 2 * BPS;
+ b += 2 * BPS;
+ }
+ _mm_storeu_si128((__m128i*)tmp, sum);
+ return (tmp[3] + tmp[2] + tmp[1] + tmp[0]);
+}
+
+static int SSE16x16(const uint8_t* a, const uint8_t* b) {
+ return SSE_16xN(a, b, 8);
+}
- // Combine pair of lines and convert to 16b.
+static int SSE16x8(const uint8_t* a, const uint8_t* b) {
+ return SSE_16xN(a, b, 4);
+}
+
+#define LOAD_8x16b(ptr) \
+ _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)(ptr)), zero)
+
+static int SSE8x8(const uint8_t* a, const uint8_t* b) {
+ const __m128i zero = _mm_setzero_si128();
+ int num_pairs = 4;
+ __m128i sum = zero;
+ int32_t tmp[4];
+ while (num_pairs-- > 0) {
+ const __m128i a0 = LOAD_8x16b(&a[BPS * 0]);
+ const __m128i a1 = LOAD_8x16b(&a[BPS * 1]);
+ const __m128i b0 = LOAD_8x16b(&b[BPS * 0]);
+ const __m128i b1 = LOAD_8x16b(&b[BPS * 1]);
+ // subtract
+ const __m128i c0 = _mm_subs_epi16(a0, b0);
+ const __m128i c1 = _mm_subs_epi16(a1, b1);
+ // multiply/accumulate with self
+ const __m128i d0 = _mm_madd_epi16(c0, c0);
+ const __m128i d1 = _mm_madd_epi16(c1, c1);
+ // collect
+ const __m128i sum01 = _mm_add_epi32(d0, d1);
+ sum = _mm_add_epi32(sum, sum01);
+ a += 2 * BPS;
+ b += 2 * BPS;
+ }
+ _mm_storeu_si128((__m128i*)tmp, sum);
+ return (tmp[3] + tmp[2] + tmp[1] + tmp[0]);
+}
+#undef LOAD_8x16b
+
+static int SSE4x4(const uint8_t* a, const uint8_t* b) {
+ const __m128i zero = _mm_setzero_si128();
+
+ // Load values. Note that we read 8 pixels instead of 4,
+ // but the a/b buffers are over-allocated to that effect.
+ const __m128i a0 = _mm_loadl_epi64((const __m128i*)&a[BPS * 0]);
+ const __m128i a1 = _mm_loadl_epi64((const __m128i*)&a[BPS * 1]);
+ const __m128i a2 = _mm_loadl_epi64((const __m128i*)&a[BPS * 2]);
+ const __m128i a3 = _mm_loadl_epi64((const __m128i*)&a[BPS * 3]);
+ const __m128i b0 = _mm_loadl_epi64((const __m128i*)&b[BPS * 0]);
+ const __m128i b1 = _mm_loadl_epi64((const __m128i*)&b[BPS * 1]);
+ const __m128i b2 = _mm_loadl_epi64((const __m128i*)&b[BPS * 2]);
+ const __m128i b3 = _mm_loadl_epi64((const __m128i*)&b[BPS * 3]);
+ // Combine pair of lines.
const __m128i a01 = _mm_unpacklo_epi32(a0, a1);
const __m128i a23 = _mm_unpacklo_epi32(a2, a3);
const __m128i b01 = _mm_unpacklo_epi32(b0, b1);
const __m128i b23 = _mm_unpacklo_epi32(b2, b3);
+ // Convert to 16b.
const __m128i a01s = _mm_unpacklo_epi8(a01, zero);
const __m128i a23s = _mm_unpacklo_epi8(a23, zero);
const __m128i b01s = _mm_unpacklo_epi8(b01, zero);
const __m128i b23s = _mm_unpacklo_epi8(b23, zero);
+ // subtract, square and accumulate
+ const __m128i d0 = _mm_subs_epi16(a01s, b01s);
+ const __m128i d1 = _mm_subs_epi16(a23s, b23s);
+ const __m128i e0 = _mm_madd_epi16(d0, d0);
+ const __m128i e1 = _mm_madd_epi16(d1, d1);
+ const __m128i sum = _mm_add_epi32(e0, e1);
- // Compute differences; (a-b)^2 = (abs(a-b))^2 = (sat8(a-b) + sat8(b-a))^2
- // TODO(cduvivier): Dissassemble and figure out why this is fastest. We don't
- // need absolute values, there is no need to do calculation
- // in 8bit as we are already in 16bit, ... Yet this is what
- // benchmarks the fastest!
- const __m128i d0 = _mm_subs_epu8(a01s, b01s);
- const __m128i d1 = _mm_subs_epu8(b01s, a01s);
- const __m128i d2 = _mm_subs_epu8(a23s, b23s);
- const __m128i d3 = _mm_subs_epu8(b23s, a23s);
-
- // Square and add them all together.
- const __m128i madd0 = _mm_madd_epi16(d0, d0);
- const __m128i madd1 = _mm_madd_epi16(d1, d1);
- const __m128i madd2 = _mm_madd_epi16(d2, d2);
- const __m128i madd3 = _mm_madd_epi16(d3, d3);
- const __m128i sum0 = _mm_add_epi32(madd0, madd1);
- const __m128i sum1 = _mm_add_epi32(madd2, madd3);
- const __m128i sum2 = _mm_add_epi32(sum0, sum1);
int32_t tmp[4];
- _mm_storeu_si128((__m128i*)tmp, sum2);
+ _mm_storeu_si128((__m128i*)tmp, sum);
return (tmp[3] + tmp[2] + tmp[1] + tmp[0]);
}
@@ -497,24 +1155,22 @@ static int SSE4x4SSE2(const uint8_t* a, const uint8_t* b) {
// Hadamard transform
// Returns the difference between the weighted sum of the absolute value of
// transformed coefficients.
-static int TTransformSSE2(const uint8_t* inA, const uint8_t* inB,
- const uint16_t* const w) {
+static int TTransform(const uint8_t* inA, const uint8_t* inB,
+ const uint16_t* const w) {
int32_t sum[4];
__m128i tmp_0, tmp_1, tmp_2, tmp_3;
const __m128i zero = _mm_setzero_si128();
- const __m128i one = _mm_set1_epi16(1);
- const __m128i three = _mm_set1_epi16(3);
- // Load, combine and tranpose inputs.
+ // Load, combine and transpose inputs.
{
- const __m128i inA_0 = _mm_loadl_epi64((__m128i*)&inA[BPS * 0]);
- const __m128i inA_1 = _mm_loadl_epi64((__m128i*)&inA[BPS * 1]);
- const __m128i inA_2 = _mm_loadl_epi64((__m128i*)&inA[BPS * 2]);
- const __m128i inA_3 = _mm_loadl_epi64((__m128i*)&inA[BPS * 3]);
- const __m128i inB_0 = _mm_loadl_epi64((__m128i*)&inB[BPS * 0]);
- const __m128i inB_1 = _mm_loadl_epi64((__m128i*)&inB[BPS * 1]);
- const __m128i inB_2 = _mm_loadl_epi64((__m128i*)&inB[BPS * 2]);
- const __m128i inB_3 = _mm_loadl_epi64((__m128i*)&inB[BPS * 3]);
+ const __m128i inA_0 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 0]);
+ const __m128i inA_1 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 1]);
+ const __m128i inA_2 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 2]);
+ const __m128i inA_3 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 3]);
+ const __m128i inB_0 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 0]);
+ const __m128i inB_1 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 1]);
+ const __m128i inB_2 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 2]);
+ const __m128i inB_3 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 3]);
// Combine inA and inB (we'll do two transforms in parallel).
const __m128i inAB_0 = _mm_unpacklo_epi8(inA_0, inB_0);
@@ -550,17 +1206,14 @@ static int TTransformSSE2(const uint8_t* inA, const uint8_t* inB,
// Horizontal pass and subsequent transpose.
{
// Calculate a and b (two 4x4 at once).
- const __m128i a0 = _mm_slli_epi16(_mm_add_epi16(tmp_0, tmp_2), 2);
- const __m128i a1 = _mm_slli_epi16(_mm_add_epi16(tmp_1, tmp_3), 2);
- const __m128i a2 = _mm_slli_epi16(_mm_sub_epi16(tmp_1, tmp_3), 2);
- const __m128i a3 = _mm_slli_epi16(_mm_sub_epi16(tmp_0, tmp_2), 2);
- // b0_extra = (a0 != 0);
- const __m128i b0_extra = _mm_andnot_si128(_mm_cmpeq_epi16 (a0, zero), one);
- const __m128i b0_base = _mm_add_epi16(a0, a1);
+ const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2);
+ const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3);
+ const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3);
+ const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2);
+ const __m128i b0 = _mm_add_epi16(a0, a1);
const __m128i b1 = _mm_add_epi16(a3, a2);
const __m128i b2 = _mm_sub_epi16(a3, a2);
const __m128i b3 = _mm_sub_epi16(a0, a1);
- const __m128i b0 = _mm_add_epi16(b0_base, b0_extra);
// a00 a01 a02 a03 b00 b01 b02 b03
// a10 a11 a12 a13 b10 b11 b12 b13
// a20 a21 a22 a23 b20 b21 b22 b23
@@ -598,8 +1251,8 @@ static int TTransformSSE2(const uint8_t* inA, const uint8_t* inB,
// Load all inputs.
// TODO(cduvivier): Make variable declarations and allocations aligned so
// we can use _mm_load_si128 instead of _mm_loadu_si128.
- const __m128i w_0 = _mm_loadu_si128((__m128i*)&w[0]);
- const __m128i w_8 = _mm_loadu_si128((__m128i*)&w[8]);
+ const __m128i w_0 = _mm_loadu_si128((const __m128i*)&w[0]);
+ const __m128i w_8 = _mm_loadu_si128((const __m128i*)&w[8]);
// Calculate a and b (two 4x4 at once).
const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2);
@@ -618,36 +1271,16 @@ static int TTransformSSE2(const uint8_t* inA, const uint8_t* inB,
__m128i B_b2 = _mm_unpackhi_epi64(b2, b3);
{
- // sign(b) = b >> 15 (0x0000 if positive, 0xffff if negative)
- const __m128i sign_A_b0 = _mm_srai_epi16(A_b0, 15);
- const __m128i sign_A_b2 = _mm_srai_epi16(A_b2, 15);
- const __m128i sign_B_b0 = _mm_srai_epi16(B_b0, 15);
- const __m128i sign_B_b2 = _mm_srai_epi16(B_b2, 15);
-
- // b = abs(b) = (b ^ sign) - sign
- A_b0 = _mm_xor_si128(A_b0, sign_A_b0);
- A_b2 = _mm_xor_si128(A_b2, sign_A_b2);
- B_b0 = _mm_xor_si128(B_b0, sign_B_b0);
- B_b2 = _mm_xor_si128(B_b2, sign_B_b2);
- A_b0 = _mm_sub_epi16(A_b0, sign_A_b0);
- A_b2 = _mm_sub_epi16(A_b2, sign_A_b2);
- B_b0 = _mm_sub_epi16(B_b0, sign_B_b0);
- B_b2 = _mm_sub_epi16(B_b2, sign_B_b2);
+ const __m128i d0 = _mm_sub_epi16(zero, A_b0);
+ const __m128i d1 = _mm_sub_epi16(zero, A_b2);
+ const __m128i d2 = _mm_sub_epi16(zero, B_b0);
+ const __m128i d3 = _mm_sub_epi16(zero, B_b2);
+ A_b0 = _mm_max_epi16(A_b0, d0); // abs(v), 16b
+ A_b2 = _mm_max_epi16(A_b2, d1);
+ B_b0 = _mm_max_epi16(B_b0, d2);
+ B_b2 = _mm_max_epi16(B_b2, d3);
}
- // b = abs(b) + 3
- A_b0 = _mm_add_epi16(A_b0, three);
- A_b2 = _mm_add_epi16(A_b2, three);
- B_b0 = _mm_add_epi16(B_b0, three);
- B_b2 = _mm_add_epi16(B_b2, three);
-
- // abs((b + (b<0) + 3) >> 3) = (abs(b) + 3) >> 3
- // b = (abs(b) + 3) >> 3
- A_b0 = _mm_srai_epi16(A_b0, 3);
- A_b2 = _mm_srai_epi16(A_b2, 3);
- B_b0 = _mm_srai_epi16(B_b0, 3);
- B_b2 = _mm_srai_epi16(B_b2, 3);
-
// weighted sums
A_b0 = _mm_madd_epi16(A_b0, w_0);
A_b2 = _mm_madd_epi16(A_b2, w_8);
@@ -663,35 +1296,33 @@ static int TTransformSSE2(const uint8_t* inA, const uint8_t* inB,
return sum[0] + sum[1] + sum[2] + sum[3];
}
-static int Disto4x4SSE2(const uint8_t* const a, const uint8_t* const b,
- const uint16_t* const w) {
- const int diff_sum = TTransformSSE2(a, b, w);
- return (abs(diff_sum) + 8) >> 4;
+static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
+ const uint16_t* const w) {
+ const int diff_sum = TTransform(a, b, w);
+ return abs(diff_sum) >> 5;
}
-static int Disto16x16SSE2(const uint8_t* const a, const uint8_t* const b,
- const uint16_t* const w) {
+static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
+ const uint16_t* const w) {
int D = 0;
int x, y;
for (y = 0; y < 16 * BPS; y += 4 * BPS) {
for (x = 0; x < 16; x += 4) {
- D += Disto4x4SSE2(a + x + y, b + x + y, w);
+ D += Disto4x4(a + x + y, b + x + y, w);
}
}
return D;
}
-
//------------------------------------------------------------------------------
// Quantization
//
-// Simple quantization
-static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
- int n, const VP8Matrix* const mtx) {
- const __m128i max_coeff_2047 = _mm_set1_epi16(2047);
- const __m128i zero = _mm_set1_epi16(0);
- __m128i sign0, sign8;
+static WEBP_INLINE int DoQuantizeBlock(int16_t in[16], int16_t out[16],
+ const uint16_t* const sharpen,
+ const VP8Matrix* const mtx) {
+ const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL);
+ const __m128i zero = _mm_setzero_si128();
__m128i coeff0, coeff8;
__m128i out0, out8;
__m128i packed_out;
@@ -701,20 +1332,14 @@ static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
// we can use _mm_load_si128 instead of _mm_loadu_si128.
__m128i in0 = _mm_loadu_si128((__m128i*)&in[0]);
__m128i in8 = _mm_loadu_si128((__m128i*)&in[8]);
- const __m128i sharpen0 = _mm_loadu_si128((__m128i*)&mtx->sharpen_[0]);
- const __m128i sharpen8 = _mm_loadu_si128((__m128i*)&mtx->sharpen_[8]);
- const __m128i iq0 = _mm_loadu_si128((__m128i*)&mtx->iq_[0]);
- const __m128i iq8 = _mm_loadu_si128((__m128i*)&mtx->iq_[8]);
- const __m128i bias0 = _mm_loadu_si128((__m128i*)&mtx->bias_[0]);
- const __m128i bias8 = _mm_loadu_si128((__m128i*)&mtx->bias_[8]);
- const __m128i q0 = _mm_loadu_si128((__m128i*)&mtx->q_[0]);
- const __m128i q8 = _mm_loadu_si128((__m128i*)&mtx->q_[8]);
- const __m128i zthresh0 = _mm_loadu_si128((__m128i*)&mtx->zthresh_[0]);
- const __m128i zthresh8 = _mm_loadu_si128((__m128i*)&mtx->zthresh_[8]);
-
- // sign(in) = in >> 15 (0x0000 if positive, 0xffff if negative)
- sign0 = _mm_srai_epi16(in0, 15);
- sign8 = _mm_srai_epi16(in8, 15);
+ const __m128i iq0 = _mm_loadu_si128((const __m128i*)&mtx->iq_[0]);
+ const __m128i iq8 = _mm_loadu_si128((const __m128i*)&mtx->iq_[8]);
+ const __m128i q0 = _mm_loadu_si128((const __m128i*)&mtx->q_[0]);
+ const __m128i q8 = _mm_loadu_si128((const __m128i*)&mtx->q_[8]);
+
+ // extract sign(in) (0x0000 if positive, 0xffff if negative)
+ const __m128i sign0 = _mm_cmpgt_epi16(zero, in0);
+ const __m128i sign8 = _mm_cmpgt_epi16(zero, in8);
// coeff = abs(in) = (in ^ sign) - sign
coeff0 = _mm_xor_si128(in0, sign0);
@@ -723,43 +1348,47 @@ static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
coeff8 = _mm_sub_epi16(coeff8, sign8);
// coeff = abs(in) + sharpen
- coeff0 = _mm_add_epi16(coeff0, sharpen0);
- coeff8 = _mm_add_epi16(coeff8, sharpen8);
-
- // if (coeff > 2047) coeff = 2047
- coeff0 = _mm_min_epi16(coeff0, max_coeff_2047);
- coeff8 = _mm_min_epi16(coeff8, max_coeff_2047);
+ if (sharpen != NULL) {
+ const __m128i sharpen0 = _mm_loadu_si128((const __m128i*)&sharpen[0]);
+ const __m128i sharpen8 = _mm_loadu_si128((const __m128i*)&sharpen[8]);
+ coeff0 = _mm_add_epi16(coeff0, sharpen0);
+ coeff8 = _mm_add_epi16(coeff8, sharpen8);
+ }
- // out = (coeff * iQ + B) >> QFIX;
+ // out = (coeff * iQ + B) >> QFIX
{
// doing calculations with 32b precision (QFIX=17)
// out = (coeff * iQ)
- __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0);
- __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0);
- __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8);
- __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8);
+ const __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0);
+ const __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0);
+ const __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8);
+ const __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8);
__m128i out_00 = _mm_unpacklo_epi16(coeff_iQ0L, coeff_iQ0H);
__m128i out_04 = _mm_unpackhi_epi16(coeff_iQ0L, coeff_iQ0H);
__m128i out_08 = _mm_unpacklo_epi16(coeff_iQ8L, coeff_iQ8H);
__m128i out_12 = _mm_unpackhi_epi16(coeff_iQ8L, coeff_iQ8H);
- // expand bias from 16b to 32b
- __m128i bias_00 = _mm_unpacklo_epi16(bias0, zero);
- __m128i bias_04 = _mm_unpackhi_epi16(bias0, zero);
- __m128i bias_08 = _mm_unpacklo_epi16(bias8, zero);
- __m128i bias_12 = _mm_unpackhi_epi16(bias8, zero);
// out = (coeff * iQ + B)
+ const __m128i bias_00 = _mm_loadu_si128((const __m128i*)&mtx->bias_[0]);
+ const __m128i bias_04 = _mm_loadu_si128((const __m128i*)&mtx->bias_[4]);
+ const __m128i bias_08 = _mm_loadu_si128((const __m128i*)&mtx->bias_[8]);
+ const __m128i bias_12 = _mm_loadu_si128((const __m128i*)&mtx->bias_[12]);
out_00 = _mm_add_epi32(out_00, bias_00);
out_04 = _mm_add_epi32(out_04, bias_04);
out_08 = _mm_add_epi32(out_08, bias_08);
out_12 = _mm_add_epi32(out_12, bias_12);
- // out = (coeff * iQ + B) >> QFIX;
+ // out = QUANTDIV(coeff, iQ, B, QFIX)
out_00 = _mm_srai_epi32(out_00, QFIX);
out_04 = _mm_srai_epi32(out_04, QFIX);
out_08 = _mm_srai_epi32(out_08, QFIX);
out_12 = _mm_srai_epi32(out_12, QFIX);
+
// pack result as 16b
out0 = _mm_packs_epi32(out_00, out_04);
out8 = _mm_packs_epi32(out_08, out_12);
+
+ // if (coeff > 2047) coeff = 2047
+ out0 = _mm_min_epi16(out0, max_coeff_2047);
+ out8 = _mm_min_epi16(out8, max_coeff_2047);
}
// get sign back (if (sign[j]) out_n = -out_n)
@@ -772,17 +1401,8 @@ static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
in0 = _mm_mullo_epi16(out0, q0);
in8 = _mm_mullo_epi16(out8, q8);
- // if (coeff <= mtx->zthresh_) {in=0; out=0;}
- {
- __m128i cmp0 = _mm_cmpgt_epi16(coeff0, zthresh0);
- __m128i cmp8 = _mm_cmpgt_epi16(coeff8, zthresh8);
- in0 = _mm_and_si128(in0, cmp0);
- in8 = _mm_and_si128(in8, cmp8);
- _mm_storeu_si128((__m128i*)&in[0], in0);
- _mm_storeu_si128((__m128i*)&in[8], in8);
- out0 = _mm_and_si128(out0, cmp0);
- out8 = _mm_and_si128(out8, cmp8);
- }
+ _mm_storeu_si128((__m128i*)&in[0], in0);
+ _mm_storeu_si128((__m128i*)&in[8], in8);
// zigzag the output before storing it.
//
@@ -809,29 +1429,55 @@ static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
}
// detect if all 'out' values are zeroes or not
- {
- int32_t tmp[4];
- _mm_storeu_si128((__m128i*)tmp, packed_out);
- if (n) {
- tmp[0] &= ~0xff;
- }
- return (tmp[3] || tmp[2] || tmp[1] || tmp[0]);
- }
+ return (_mm_movemask_epi8(_mm_cmpeq_epi8(packed_out, zero)) != 0xffff);
+}
+
+static int QuantizeBlock(int16_t in[16], int16_t out[16],
+ const VP8Matrix* const mtx) {
+ return DoQuantizeBlock(in, out, &mtx->sharpen_[0], mtx);
+}
+
+static int QuantizeBlockWHT(int16_t in[16], int16_t out[16],
+ const VP8Matrix* const mtx) {
+ return DoQuantizeBlock(in, out, NULL, mtx);
+}
+
+static int Quantize2Blocks(int16_t in[32], int16_t out[32],
+ const VP8Matrix* const mtx) {
+ int nz;
+ const uint16_t* const sharpen = &mtx->sharpen_[0];
+ nz = DoQuantizeBlock(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0;
+ nz |= DoQuantizeBlock(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1;
+ return nz;
}
+//------------------------------------------------------------------------------
+// Entry point
+
extern void VP8EncDspInitSSE2(void);
-void VP8EncDspInitSSE2(void) {
- VP8CollectHistogram = CollectHistogramSSE2;
- VP8EncQuantizeBlock = QuantizeBlockSSE2;
- VP8ITransform = ITransformSSE2;
- VP8FTransform = FTransformSSE2;
- VP8SSE4x4 = SSE4x4SSE2;
- VP8TDisto4x4 = Disto4x4SSE2;
- VP8TDisto16x16 = Disto16x16SSE2;
-}
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
-#endif // WEBP_USE_SSE2
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE2(void) {
+ VP8CollectHistogram = CollectHistogram;
+ VP8EncPredLuma16 = Intra16Preds;
+ VP8EncPredChroma8 = IntraChromaPreds;
+ VP8EncPredLuma4 = Intra4Preds;
+ VP8EncQuantizeBlock = QuantizeBlock;
+ VP8EncQuantize2Blocks = Quantize2Blocks;
+ VP8EncQuantizeBlockWHT = QuantizeBlockWHT;
+ VP8ITransform = ITransform;
+ VP8FTransform = FTransform;
+ VP8FTransform2 = FTransform2;
+ VP8FTransformWHT = FTransformWHT;
+ VP8SSE16x16 = SSE16x16;
+ VP8SSE16x8 = SSE16x8;
+ VP8SSE8x8 = SSE8x8;
+ VP8SSE4x4 = SSE4x4;
+ VP8TDisto4x4 = Disto4x4;
+ VP8TDisto16x16 = Disto16x16;
+}
+
+#else // !WEBP_USE_SSE2
+
+WEBP_DSP_INIT_STUB(VP8EncDspInitSSE2)
+
+#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/enc_sse41.c b/drivers/webp/dsp/enc_sse41.c
new file mode 100644
index 0000000000..27f4189833
--- /dev/null
+++ b/drivers/webp/dsp/enc_sse41.c
@@ -0,0 +1,375 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// SSE4 version of some encoding functions.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_SSE41)
+#include <smmintrin.h>
+#include <stdlib.h> // for abs()
+
+#include "../enc/vp8enci.h"
+
+//------------------------------------------------------------------------------
+// Compute susceptibility based on DCT-coeff histograms.
+
+static void CollectHistogram(const uint8_t* ref, const uint8_t* pred,
+ int start_block, int end_block,
+ VP8Histogram* const histo) {
+ const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH);
+ int j;
+ int distribution[MAX_COEFF_THRESH + 1] = { 0 };
+ for (j = start_block; j < end_block; ++j) {
+ int16_t out[16];
+ int k;
+
+ VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
+
+ // Convert coefficients to bin (within out[]).
+ {
+ // Load.
+ const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]);
+ const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]);
+ // v = abs(out) >> 3
+ const __m128i abs0 = _mm_abs_epi16(out0);
+ const __m128i abs1 = _mm_abs_epi16(out1);
+ const __m128i v0 = _mm_srai_epi16(abs0, 3);
+ const __m128i v1 = _mm_srai_epi16(abs1, 3);
+ // bin = min(v, MAX_COEFF_THRESH)
+ const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh);
+ const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh);
+ // Store.
+ _mm_storeu_si128((__m128i*)&out[0], bin0);
+ _mm_storeu_si128((__m128i*)&out[8], bin1);
+ }
+
+ // Convert coefficients to bin.
+ for (k = 0; k < 16; ++k) {
+ ++distribution[out[k]];
+ }
+ }
+ VP8SetHistogramData(distribution, histo);
+}
+
+//------------------------------------------------------------------------------
+// Texture distortion
+//
+// We try to match the spectral content (weighted) between source and
+// reconstructed samples.
+
+// Hadamard transform
+// Returns the difference between the weighted sum of the absolute value of
+// transformed coefficients.
+static int TTransform(const uint8_t* inA, const uint8_t* inB,
+ const uint16_t* const w) {
+ __m128i tmp_0, tmp_1, tmp_2, tmp_3;
+
+ // Load, combine and transpose inputs.
+ {
+ const __m128i inA_0 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 0]);
+ const __m128i inA_1 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 1]);
+ const __m128i inA_2 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 2]);
+ const __m128i inA_3 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 3]);
+ const __m128i inB_0 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 0]);
+ const __m128i inB_1 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 1]);
+ const __m128i inB_2 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 2]);
+ const __m128i inB_3 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 3]);
+
+ // Combine inA and inB (we'll do two transforms in parallel).
+ const __m128i inAB_0 = _mm_unpacklo_epi8(inA_0, inB_0);
+ const __m128i inAB_1 = _mm_unpacklo_epi8(inA_1, inB_1);
+ const __m128i inAB_2 = _mm_unpacklo_epi8(inA_2, inB_2);
+ const __m128i inAB_3 = _mm_unpacklo_epi8(inA_3, inB_3);
+ // a00 b00 a01 b01 a02 b03 a03 b03 0 0 0 0 0 0 0 0
+ // a10 b10 a11 b11 a12 b12 a13 b13 0 0 0 0 0 0 0 0
+ // a20 b20 a21 b21 a22 b22 a23 b23 0 0 0 0 0 0 0 0
+ // a30 b30 a31 b31 a32 b32 a33 b33 0 0 0 0 0 0 0 0
+
+ // Transpose the two 4x4, discarding the filling zeroes.
+ const __m128i transpose0_0 = _mm_unpacklo_epi8(inAB_0, inAB_2);
+ const __m128i transpose0_1 = _mm_unpacklo_epi8(inAB_1, inAB_3);
+ // a00 a20 b00 b20 a01 a21 b01 b21 a02 a22 b02 b22 a03 a23 b03 b23
+ // a10 a30 b10 b30 a11 a31 b11 b31 a12 a32 b12 b32 a13 a33 b13 b33
+ const __m128i transpose1_0 = _mm_unpacklo_epi8(transpose0_0, transpose0_1);
+ const __m128i transpose1_1 = _mm_unpackhi_epi8(transpose0_0, transpose0_1);
+ // a00 a10 a20 a30 b00 b10 b20 b30 a01 a11 a21 a31 b01 b11 b21 b31
+ // a02 a12 a22 a32 b02 b12 b22 b32 a03 a13 a23 a33 b03 b13 b23 b33
+
+ // Convert to 16b.
+ tmp_0 = _mm_cvtepu8_epi16(transpose1_0);
+ tmp_1 = _mm_cvtepu8_epi16(_mm_srli_si128(transpose1_0, 8));
+ tmp_2 = _mm_cvtepu8_epi16(transpose1_1);
+ tmp_3 = _mm_cvtepu8_epi16(_mm_srli_si128(transpose1_1, 8));
+ // a00 a10 a20 a30 b00 b10 b20 b30
+ // a01 a11 a21 a31 b01 b11 b21 b31
+ // a02 a12 a22 a32 b02 b12 b22 b32
+ // a03 a13 a23 a33 b03 b13 b23 b33
+ }
+
+ // Horizontal pass and subsequent transpose.
+ {
+ // Calculate a and b (two 4x4 at once).
+ const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2);
+ const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3);
+ const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3);
+ const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2);
+ const __m128i b0 = _mm_add_epi16(a0, a1);
+ const __m128i b1 = _mm_add_epi16(a3, a2);
+ const __m128i b2 = _mm_sub_epi16(a3, a2);
+ const __m128i b3 = _mm_sub_epi16(a0, a1);
+ // a00 a01 a02 a03 b00 b01 b02 b03
+ // a10 a11 a12 a13 b10 b11 b12 b13
+ // a20 a21 a22 a23 b20 b21 b22 b23
+ // a30 a31 a32 a33 b30 b31 b32 b33
+
+ // Transpose the two 4x4.
+ const __m128i transpose0_0 = _mm_unpacklo_epi16(b0, b1);
+ const __m128i transpose0_1 = _mm_unpacklo_epi16(b2, b3);
+ const __m128i transpose0_2 = _mm_unpackhi_epi16(b0, b1);
+ const __m128i transpose0_3 = _mm_unpackhi_epi16(b2, b3);
+ // a00 a10 a01 a11 a02 a12 a03 a13
+ // a20 a30 a21 a31 a22 a32 a23 a33
+ // b00 b10 b01 b11 b02 b12 b03 b13
+ // b20 b30 b21 b31 b22 b32 b23 b33
+ const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
+ const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3);
+ const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
+ const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3);
+ // a00 a10 a20 a30 a01 a11 a21 a31
+ // b00 b10 b20 b30 b01 b11 b21 b31
+ // a02 a12 a22 a32 a03 a13 a23 a33
+ // b02 b12 a22 b32 b03 b13 b23 b33
+ tmp_0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1);
+ tmp_1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1);
+ tmp_2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3);
+ tmp_3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3);
+ // a00 a10 a20 a30 b00 b10 b20 b30
+ // a01 a11 a21 a31 b01 b11 b21 b31
+ // a02 a12 a22 a32 b02 b12 b22 b32
+ // a03 a13 a23 a33 b03 b13 b23 b33
+ }
+
+ // Vertical pass and difference of weighted sums.
+ {
+ // Load all inputs.
+ const __m128i w_0 = _mm_loadu_si128((const __m128i*)&w[0]);
+ const __m128i w_8 = _mm_loadu_si128((const __m128i*)&w[8]);
+
+ // Calculate a and b (two 4x4 at once).
+ const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2);
+ const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3);
+ const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3);
+ const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2);
+ const __m128i b0 = _mm_add_epi16(a0, a1);
+ const __m128i b1 = _mm_add_epi16(a3, a2);
+ const __m128i b2 = _mm_sub_epi16(a3, a2);
+ const __m128i b3 = _mm_sub_epi16(a0, a1);
+
+ // Separate the transforms of inA and inB.
+ __m128i A_b0 = _mm_unpacklo_epi64(b0, b1);
+ __m128i A_b2 = _mm_unpacklo_epi64(b2, b3);
+ __m128i B_b0 = _mm_unpackhi_epi64(b0, b1);
+ __m128i B_b2 = _mm_unpackhi_epi64(b2, b3);
+
+ A_b0 = _mm_abs_epi16(A_b0);
+ A_b2 = _mm_abs_epi16(A_b2);
+ B_b0 = _mm_abs_epi16(B_b0);
+ B_b2 = _mm_abs_epi16(B_b2);
+
+ // weighted sums
+ A_b0 = _mm_madd_epi16(A_b0, w_0);
+ A_b2 = _mm_madd_epi16(A_b2, w_8);
+ B_b0 = _mm_madd_epi16(B_b0, w_0);
+ B_b2 = _mm_madd_epi16(B_b2, w_8);
+ A_b0 = _mm_add_epi32(A_b0, A_b2);
+ B_b0 = _mm_add_epi32(B_b0, B_b2);
+
+ // difference of weighted sums
+ A_b2 = _mm_sub_epi32(A_b0, B_b0);
+ // cascading summation of the differences
+ B_b0 = _mm_hadd_epi32(A_b2, A_b2);
+ B_b2 = _mm_hadd_epi32(B_b0, B_b0);
+ return _mm_cvtsi128_si32(B_b2);
+ }
+}
+
+static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
+ const uint16_t* const w) {
+ const int diff_sum = TTransform(a, b, w);
+ return abs(diff_sum) >> 5;
+}
+
+static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
+ const uint16_t* const w) {
+ int D = 0;
+ int x, y;
+ for (y = 0; y < 16 * BPS; y += 4 * BPS) {
+ for (x = 0; x < 16; x += 4) {
+ D += Disto4x4(a + x + y, b + x + y, w);
+ }
+ }
+ return D;
+}
+
+//------------------------------------------------------------------------------
+// Quantization
+//
+
+// Generates a pshufb constant for shuffling 16b words.
+#define PSHUFB_CST(A,B,C,D,E,F,G,H) \
+ _mm_set_epi8(2 * (H) + 1, 2 * (H) + 0, 2 * (G) + 1, 2 * (G) + 0, \
+ 2 * (F) + 1, 2 * (F) + 0, 2 * (E) + 1, 2 * (E) + 0, \
+ 2 * (D) + 1, 2 * (D) + 0, 2 * (C) + 1, 2 * (C) + 0, \
+ 2 * (B) + 1, 2 * (B) + 0, 2 * (A) + 1, 2 * (A) + 0)
+
+static WEBP_INLINE int DoQuantizeBlock(int16_t in[16], int16_t out[16],
+ const uint16_t* const sharpen,
+ const VP8Matrix* const mtx) {
+ const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL);
+ const __m128i zero = _mm_setzero_si128();
+ __m128i out0, out8;
+ __m128i packed_out;
+
+ // Load all inputs.
+ // TODO(cduvivier): Make variable declarations and allocations aligned so that
+ // we can use _mm_load_si128 instead of _mm_loadu_si128.
+ __m128i in0 = _mm_loadu_si128((__m128i*)&in[0]);
+ __m128i in8 = _mm_loadu_si128((__m128i*)&in[8]);
+ const __m128i iq0 = _mm_loadu_si128((const __m128i*)&mtx->iq_[0]);
+ const __m128i iq8 = _mm_loadu_si128((const __m128i*)&mtx->iq_[8]);
+ const __m128i q0 = _mm_loadu_si128((const __m128i*)&mtx->q_[0]);
+ const __m128i q8 = _mm_loadu_si128((const __m128i*)&mtx->q_[8]);
+
+ // coeff = abs(in)
+ __m128i coeff0 = _mm_abs_epi16(in0);
+ __m128i coeff8 = _mm_abs_epi16(in8);
+
+ // coeff = abs(in) + sharpen
+ if (sharpen != NULL) {
+ const __m128i sharpen0 = _mm_loadu_si128((const __m128i*)&sharpen[0]);
+ const __m128i sharpen8 = _mm_loadu_si128((const __m128i*)&sharpen[8]);
+ coeff0 = _mm_add_epi16(coeff0, sharpen0);
+ coeff8 = _mm_add_epi16(coeff8, sharpen8);
+ }
+
+ // out = (coeff * iQ + B) >> QFIX
+ {
+ // doing calculations with 32b precision (QFIX=17)
+ // out = (coeff * iQ)
+ const __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0);
+ const __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0);
+ const __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8);
+ const __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8);
+ __m128i out_00 = _mm_unpacklo_epi16(coeff_iQ0L, coeff_iQ0H);
+ __m128i out_04 = _mm_unpackhi_epi16(coeff_iQ0L, coeff_iQ0H);
+ __m128i out_08 = _mm_unpacklo_epi16(coeff_iQ8L, coeff_iQ8H);
+ __m128i out_12 = _mm_unpackhi_epi16(coeff_iQ8L, coeff_iQ8H);
+ // out = (coeff * iQ + B)
+ const __m128i bias_00 = _mm_loadu_si128((const __m128i*)&mtx->bias_[0]);
+ const __m128i bias_04 = _mm_loadu_si128((const __m128i*)&mtx->bias_[4]);
+ const __m128i bias_08 = _mm_loadu_si128((const __m128i*)&mtx->bias_[8]);
+ const __m128i bias_12 = _mm_loadu_si128((const __m128i*)&mtx->bias_[12]);
+ out_00 = _mm_add_epi32(out_00, bias_00);
+ out_04 = _mm_add_epi32(out_04, bias_04);
+ out_08 = _mm_add_epi32(out_08, bias_08);
+ out_12 = _mm_add_epi32(out_12, bias_12);
+ // out = QUANTDIV(coeff, iQ, B, QFIX)
+ out_00 = _mm_srai_epi32(out_00, QFIX);
+ out_04 = _mm_srai_epi32(out_04, QFIX);
+ out_08 = _mm_srai_epi32(out_08, QFIX);
+ out_12 = _mm_srai_epi32(out_12, QFIX);
+
+ // pack result as 16b
+ out0 = _mm_packs_epi32(out_00, out_04);
+ out8 = _mm_packs_epi32(out_08, out_12);
+
+ // if (coeff > 2047) coeff = 2047
+ out0 = _mm_min_epi16(out0, max_coeff_2047);
+ out8 = _mm_min_epi16(out8, max_coeff_2047);
+ }
+
+ // put sign back
+ out0 = _mm_sign_epi16(out0, in0);
+ out8 = _mm_sign_epi16(out8, in8);
+
+ // in = out * Q
+ in0 = _mm_mullo_epi16(out0, q0);
+ in8 = _mm_mullo_epi16(out8, q8);
+
+ _mm_storeu_si128((__m128i*)&in[0], in0);
+ _mm_storeu_si128((__m128i*)&in[8], in8);
+
+ // zigzag the output before storing it. The re-ordering is:
+ // 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15
+ // -> 0 1 4[8]5 2 3 6 | 9 12 13 10 [7]11 14 15
+ // There's only two misplaced entries ([8] and [7]) that are crossing the
+ // reg's boundaries.
+ // We use pshufb instead of pshuflo/pshufhi.
+ {
+ const __m128i kCst_lo = PSHUFB_CST(0, 1, 4, -1, 5, 2, 3, 6);
+ const __m128i kCst_7 = PSHUFB_CST(-1, -1, -1, -1, 7, -1, -1, -1);
+ const __m128i tmp_lo = _mm_shuffle_epi8(out0, kCst_lo);
+ const __m128i tmp_7 = _mm_shuffle_epi8(out0, kCst_7); // extract #7
+ const __m128i kCst_hi = PSHUFB_CST(1, 4, 5, 2, -1, 3, 6, 7);
+ const __m128i kCst_8 = PSHUFB_CST(-1, -1, -1, 0, -1, -1, -1, -1);
+ const __m128i tmp_hi = _mm_shuffle_epi8(out8, kCst_hi);
+ const __m128i tmp_8 = _mm_shuffle_epi8(out8, kCst_8); // extract #8
+ const __m128i out_z0 = _mm_or_si128(tmp_lo, tmp_8);
+ const __m128i out_z8 = _mm_or_si128(tmp_hi, tmp_7);
+ _mm_storeu_si128((__m128i*)&out[0], out_z0);
+ _mm_storeu_si128((__m128i*)&out[8], out_z8);
+ packed_out = _mm_packs_epi16(out_z0, out_z8);
+ }
+
+ // detect if all 'out' values are zeroes or not
+ return (_mm_movemask_epi8(_mm_cmpeq_epi8(packed_out, zero)) != 0xffff);
+}
+
+#undef PSHUFB_CST
+
+static int QuantizeBlock(int16_t in[16], int16_t out[16],
+ const VP8Matrix* const mtx) {
+ return DoQuantizeBlock(in, out, &mtx->sharpen_[0], mtx);
+}
+
+static int QuantizeBlockWHT(int16_t in[16], int16_t out[16],
+ const VP8Matrix* const mtx) {
+ return DoQuantizeBlock(in, out, NULL, mtx);
+}
+
+static int Quantize2Blocks(int16_t in[32], int16_t out[32],
+ const VP8Matrix* const mtx) {
+ int nz;
+ const uint16_t* const sharpen = &mtx->sharpen_[0];
+ nz = DoQuantizeBlock(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0;
+ nz |= DoQuantizeBlock(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1;
+ return nz;
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8EncDspInitSSE41(void);
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE41(void) {
+ VP8CollectHistogram = CollectHistogram;
+ VP8EncQuantizeBlock = QuantizeBlock;
+ VP8EncQuantize2Blocks = Quantize2Blocks;
+ VP8EncQuantizeBlockWHT = QuantizeBlockWHT;
+ VP8TDisto4x4 = Disto4x4;
+ VP8TDisto16x16 = Disto16x16;
+}
+
+#else // !WEBP_USE_SSE41
+
+WEBP_DSP_INIT_STUB(VP8EncDspInitSSE41)
+
+#endif // WEBP_USE_SSE41
diff --git a/drivers/webp/dsp/filters.c b/drivers/webp/dsp/filters.c
new file mode 100644
index 0000000000..5c30f2e457
--- /dev/null
+++ b/drivers/webp/dsp/filters.c
@@ -0,0 +1,240 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Spatial prediction using various filters
+//
+// Author: Urvang (urvang@google.com)
+
+#include "./dsp.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+//------------------------------------------------------------------------------
+// Helpful macro.
+
+# define SANITY_CHECK(in, out) \
+ assert(in != NULL); \
+ assert(out != NULL); \
+ assert(width > 0); \
+ assert(height > 0); \
+ assert(stride >= width); \
+ assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \
+ (void)height; // Silence unused warning.
+
+static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred,
+ uint8_t* dst, int length, int inverse) {
+ int i;
+ if (inverse) {
+ for (i = 0; i < length; ++i) dst[i] = src[i] + pred[i];
+ } else {
+ for (i = 0; i < length; ++i) dst[i] = src[i] - pred[i];
+ }
+}
+
+//------------------------------------------------------------------------------
+// Horizontal filter.
+
+static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in,
+ int width, int height, int stride,
+ int row, int num_rows,
+ int inverse, uint8_t* out) {
+ const uint8_t* preds;
+ const size_t start_offset = row * stride;
+ const int last_row = row + num_rows;
+ SANITY_CHECK(in, out);
+ in += start_offset;
+ out += start_offset;
+ preds = inverse ? out : in;
+
+ if (row == 0) {
+ // Leftmost pixel is the same as input for topmost scanline.
+ out[0] = in[0];
+ PredictLine(in + 1, preds, out + 1, width - 1, inverse);
+ row = 1;
+ preds += stride;
+ in += stride;
+ out += stride;
+ }
+
+ // Filter line-by-line.
+ while (row < last_row) {
+ // Leftmost pixel is predicted from above.
+ PredictLine(in, preds - stride, out, 1, inverse);
+ PredictLine(in + 1, preds, out + 1, width - 1, inverse);
+ ++row;
+ preds += stride;
+ in += stride;
+ out += stride;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Vertical filter.
+
+static WEBP_INLINE void DoVerticalFilter(const uint8_t* in,
+ int width, int height, int stride,
+ int row, int num_rows,
+ int inverse, uint8_t* out) {
+ const uint8_t* preds;
+ const size_t start_offset = row * stride;
+ const int last_row = row + num_rows;
+ SANITY_CHECK(in, out);
+ in += start_offset;
+ out += start_offset;
+ preds = inverse ? out : in;
+
+ if (row == 0) {
+ // Very first top-left pixel is copied.
+ out[0] = in[0];
+ // Rest of top scan-line is left-predicted.
+ PredictLine(in + 1, preds, out + 1, width - 1, inverse);
+ row = 1;
+ in += stride;
+ out += stride;
+ } else {
+ // We are starting from in-between. Make sure 'preds' points to prev row.
+ preds -= stride;
+ }
+
+ // Filter line-by-line.
+ while (row < last_row) {
+ PredictLine(in, preds, out, width, inverse);
+ ++row;
+ preds += stride;
+ in += stride;
+ out += stride;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Gradient filter.
+
+static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) {
+ const int g = a + b - c;
+ return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit
+}
+
+static WEBP_INLINE void DoGradientFilter(const uint8_t* in,
+ int width, int height, int stride,
+ int row, int num_rows,
+ int inverse, uint8_t* out) {
+ const uint8_t* preds;
+ const size_t start_offset = row * stride;
+ const int last_row = row + num_rows;
+ SANITY_CHECK(in, out);
+ in += start_offset;
+ out += start_offset;
+ preds = inverse ? out : in;
+
+ // left prediction for top scan-line
+ if (row == 0) {
+ out[0] = in[0];
+ PredictLine(in + 1, preds, out + 1, width - 1, inverse);
+ row = 1;
+ preds += stride;
+ in += stride;
+ out += stride;
+ }
+
+ // Filter line-by-line.
+ while (row < last_row) {
+ int w;
+ // leftmost pixel: predict from above.
+ PredictLine(in, preds - stride, out, 1, inverse);
+ for (w = 1; w < width; ++w) {
+ const int pred = GradientPredictor(preds[w - 1],
+ preds[w - stride],
+ preds[w - stride - 1]);
+ out[w] = in[w] + (inverse ? pred : -pred);
+ }
+ ++row;
+ preds += stride;
+ in += stride;
+ out += stride;
+ }
+}
+
+#undef SANITY_CHECK
+
+//------------------------------------------------------------------------------
+
+static void HorizontalFilter(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data);
+}
+
+static void VerticalFilter(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data);
+}
+
+
+static void GradientFilter(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data);
+}
+
+
+//------------------------------------------------------------------------------
+
+static void VerticalUnfilter(int width, int height, int stride, int row,
+ int num_rows, uint8_t* data) {
+ DoVerticalFilter(data, width, height, stride, row, num_rows, 1, data);
+}
+
+static void HorizontalUnfilter(int width, int height, int stride, int row,
+ int num_rows, uint8_t* data) {
+ DoHorizontalFilter(data, width, height, stride, row, num_rows, 1, data);
+}
+
+static void GradientUnfilter(int width, int height, int stride, int row,
+ int num_rows, uint8_t* data) {
+ DoGradientFilter(data, width, height, stride, row, num_rows, 1, data);
+}
+
+//------------------------------------------------------------------------------
+// Init function
+
+WebPFilterFunc WebPFilters[WEBP_FILTER_LAST];
+WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST];
+
+extern void VP8FiltersInitMIPSdspR2(void);
+extern void VP8FiltersInitSSE2(void);
+
+static volatile VP8CPUInfo filters_last_cpuinfo_used =
+ (VP8CPUInfo)&filters_last_cpuinfo_used;
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) {
+ if (filters_last_cpuinfo_used == VP8GetCPUInfo) return;
+
+ WebPUnfilters[WEBP_FILTER_NONE] = NULL;
+ WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter;
+ WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter;
+ WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter;
+
+ WebPFilters[WEBP_FILTER_NONE] = NULL;
+ WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter;
+ WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter;
+ WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter;
+
+ if (VP8GetCPUInfo != NULL) {
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ VP8FiltersInitSSE2();
+ }
+#endif
+#if defined(WEBP_USE_MIPS_DSP_R2)
+ if (VP8GetCPUInfo(kMIPSdspR2)) {
+ VP8FiltersInitMIPSdspR2();
+ }
+#endif
+ }
+ filters_last_cpuinfo_used = VP8GetCPUInfo;
+}
diff --git a/drivers/webp/dsp/filters_mips_dsp_r2.c b/drivers/webp/dsp/filters_mips_dsp_r2.c
new file mode 100644
index 0000000000..8134af511b
--- /dev/null
+++ b/drivers/webp/dsp/filters_mips_dsp_r2.c
@@ -0,0 +1,405 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Spatial prediction using various filters
+//
+// Author(s): Branimir Vasic (branimir.vasic@imgtec.com)
+// Djordje Pesut (djordje.pesut@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS_DSP_R2)
+
+#include "../dsp/dsp.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+//------------------------------------------------------------------------------
+// Helpful macro.
+
+# define SANITY_CHECK(in, out) \
+ assert(in != NULL); \
+ assert(out != NULL); \
+ assert(width > 0); \
+ assert(height > 0); \
+ assert(stride >= width); \
+ assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \
+ (void)height; // Silence unused warning.
+
+// if INVERSE
+// preds == &dst[-1] == &src[-1]
+// else
+// preds == &src[-1] != &dst[-1]
+#define DO_PREDICT_LINE(SRC, DST, LENGTH, INVERSE) do { \
+ const uint8_t* psrc = (uint8_t*)(SRC); \
+ uint8_t* pdst = (uint8_t*)(DST); \
+ const int ilength = (int)(LENGTH); \
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6; \
+ __asm__ volatile ( \
+ ".set push \n\t" \
+ ".set noreorder \n\t" \
+ "srl %[temp0], %[length], 0x2 \n\t" \
+ "beqz %[temp0], 4f \n\t" \
+ " andi %[temp6], %[length], 0x3 \n\t" \
+ ".if " #INVERSE " \n\t" \
+ "lbu %[temp1], -1(%[src]) \n\t" \
+ "1: \n\t" \
+ "lbu %[temp2], 0(%[src]) \n\t" \
+ "lbu %[temp3], 1(%[src]) \n\t" \
+ "lbu %[temp4], 2(%[src]) \n\t" \
+ "lbu %[temp5], 3(%[src]) \n\t" \
+ "addiu %[src], %[src], 4 \n\t" \
+ "addiu %[temp0], %[temp0], -1 \n\t" \
+ "addu %[temp2], %[temp2], %[temp1] \n\t" \
+ "addu %[temp3], %[temp3], %[temp2] \n\t" \
+ "addu %[temp4], %[temp4], %[temp3] \n\t" \
+ "addu %[temp1], %[temp5], %[temp4] \n\t" \
+ "sb %[temp2], -4(%[src]) \n\t" \
+ "sb %[temp3], -3(%[src]) \n\t" \
+ "sb %[temp4], -2(%[src]) \n\t" \
+ "bnez %[temp0], 1b \n\t" \
+ " sb %[temp1], -1(%[src]) \n\t" \
+ ".else \n\t" \
+ "1: \n\t" \
+ "ulw %[temp1], -1(%[src]) \n\t" \
+ "ulw %[temp2], 0(%[src]) \n\t" \
+ "addiu %[src], %[src], 4 \n\t" \
+ "addiu %[temp0], %[temp0], -1 \n\t" \
+ "subu.qb %[temp3], %[temp2], %[temp1] \n\t" \
+ "usw %[temp3], 0(%[dst]) \n\t" \
+ "bnez %[temp0], 1b \n\t" \
+ " addiu %[dst], %[dst], 4 \n\t" \
+ ".endif \n\t" \
+ "4: \n\t" \
+ "beqz %[temp6], 3f \n\t" \
+ " nop \n\t" \
+ "2: \n\t" \
+ "lbu %[temp1], -1(%[src]) \n\t" \
+ "lbu %[temp2], 0(%[src]) \n\t" \
+ "addiu %[src], %[src], 1 \n\t" \
+ ".if " #INVERSE " \n\t" \
+ "addu %[temp3], %[temp1], %[temp2] \n\t" \
+ "sb %[temp3], -1(%[src]) \n\t" \
+ ".else \n\t" \
+ "subu %[temp3], %[temp1], %[temp2] \n\t" \
+ "sb %[temp3], 0(%[dst]) \n\t" \
+ ".endif \n\t" \
+ "addiu %[temp6], %[temp6], -1 \n\t" \
+ "bnez %[temp6], 2b \n\t" \
+ " addiu %[dst], %[dst], 1 \n\t" \
+ "3: \n\t" \
+ ".set pop \n\t" \
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \
+ [temp6]"=&r"(temp6), [dst]"+&r"(pdst), [src]"+&r"(psrc) \
+ : [length]"r"(ilength) \
+ : "memory" \
+ ); \
+ } while (0)
+
+static WEBP_INLINE void PredictLine(const uint8_t* src, uint8_t* dst,
+ int length, int inverse) {
+ if (inverse) {
+ DO_PREDICT_LINE(src, dst, length, 1);
+ } else {
+ DO_PREDICT_LINE(src, dst, length, 0);
+ }
+}
+
+#define DO_PREDICT_LINE_VERTICAL(SRC, PRED, DST, LENGTH, INVERSE) do { \
+ const uint8_t* psrc = (uint8_t*)(SRC); \
+ const uint8_t* ppred = (uint8_t*)(PRED); \
+ uint8_t* pdst = (uint8_t*)(DST); \
+ const int ilength = (int)(LENGTH); \
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; \
+ __asm__ volatile ( \
+ ".set push \n\t" \
+ ".set noreorder \n\t" \
+ "srl %[temp0], %[length], 0x3 \n\t" \
+ "beqz %[temp0], 4f \n\t" \
+ " andi %[temp7], %[length], 0x7 \n\t" \
+ "1: \n\t" \
+ "ulw %[temp1], 0(%[src]) \n\t" \
+ "ulw %[temp2], 0(%[pred]) \n\t" \
+ "ulw %[temp3], 4(%[src]) \n\t" \
+ "ulw %[temp4], 4(%[pred]) \n\t" \
+ "addiu %[src], %[src], 8 \n\t" \
+ ".if " #INVERSE " \n\t" \
+ "addu.qb %[temp5], %[temp1], %[temp2] \n\t" \
+ "addu.qb %[temp6], %[temp3], %[temp4] \n\t" \
+ ".else \n\t" \
+ "subu.qb %[temp5], %[temp1], %[temp2] \n\t" \
+ "subu.qb %[temp6], %[temp3], %[temp4] \n\t" \
+ ".endif \n\t" \
+ "addiu %[pred], %[pred], 8 \n\t" \
+ "usw %[temp5], 0(%[dst]) \n\t" \
+ "usw %[temp6], 4(%[dst]) \n\t" \
+ "addiu %[temp0], %[temp0], -1 \n\t" \
+ "bnez %[temp0], 1b \n\t" \
+ " addiu %[dst], %[dst], 8 \n\t" \
+ "4: \n\t" \
+ "beqz %[temp7], 3f \n\t" \
+ " nop \n\t" \
+ "2: \n\t" \
+ "lbu %[temp1], 0(%[src]) \n\t" \
+ "lbu %[temp2], 0(%[pred]) \n\t" \
+ "addiu %[src], %[src], 1 \n\t" \
+ "addiu %[pred], %[pred], 1 \n\t" \
+ ".if " #INVERSE " \n\t" \
+ "addu %[temp3], %[temp1], %[temp2] \n\t" \
+ ".else \n\t" \
+ "subu %[temp3], %[temp1], %[temp2] \n\t" \
+ ".endif \n\t" \
+ "sb %[temp3], 0(%[dst]) \n\t" \
+ "addiu %[temp7], %[temp7], -1 \n\t" \
+ "bnez %[temp7], 2b \n\t" \
+ " addiu %[dst], %[dst], 1 \n\t" \
+ "3: \n\t" \
+ ".set pop \n\t" \
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [pred]"+&r"(ppred), \
+ [dst]"+&r"(pdst), [src]"+&r"(psrc) \
+ : [length]"r"(ilength) \
+ : "memory" \
+ ); \
+ } while (0)
+
+#define PREDICT_LINE_ONE_PASS(SRC, PRED, DST, INVERSE) do { \
+ int temp1, temp2, temp3; \
+ __asm__ volatile ( \
+ "lbu %[temp1], 0(%[src]) \n\t" \
+ "lbu %[temp2], 0(%[pred]) \n\t" \
+ ".if " #INVERSE " \n\t" \
+ "addu %[temp3], %[temp1], %[temp2] \n\t" \
+ ".else \n\t" \
+ "subu %[temp3], %[temp1], %[temp2] \n\t" \
+ ".endif \n\t" \
+ "sb %[temp3], 0(%[dst]) \n\t" \
+ : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \
+ : [pred]"r"((PRED)), [dst]"r"((DST)), [src]"r"((SRC)) \
+ : "memory" \
+ ); \
+ } while (0)
+
+//------------------------------------------------------------------------------
+// Horizontal filter.
+
+#define FILTER_LINE_BY_LINE(INVERSE) do { \
+ while (row < last_row) { \
+ PREDICT_LINE_ONE_PASS(in, preds - stride, out, INVERSE); \
+ DO_PREDICT_LINE(in + 1, out + 1, width - 1, INVERSE); \
+ ++row; \
+ preds += stride; \
+ in += stride; \
+ out += stride; \
+ } \
+ } while (0)
+
+static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in,
+ int width, int height, int stride,
+ int row, int num_rows,
+ int inverse, uint8_t* out) {
+ const uint8_t* preds;
+ const size_t start_offset = row * stride;
+ const int last_row = row + num_rows;
+ SANITY_CHECK(in, out);
+ in += start_offset;
+ out += start_offset;
+ preds = inverse ? out : in;
+
+ if (row == 0) {
+ // Leftmost pixel is the same as input for topmost scanline.
+ out[0] = in[0];
+ PredictLine(in + 1, out + 1, width - 1, inverse);
+ row = 1;
+ preds += stride;
+ in += stride;
+ out += stride;
+ }
+
+ // Filter line-by-line.
+ if (inverse) {
+ FILTER_LINE_BY_LINE(1);
+ } else {
+ FILTER_LINE_BY_LINE(0);
+ }
+}
+
+#undef FILTER_LINE_BY_LINE
+
+static void HorizontalFilter(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data);
+}
+
+static void HorizontalUnfilter(int width, int height, int stride, int row,
+ int num_rows, uint8_t* data) {
+ DoHorizontalFilter(data, width, height, stride, row, num_rows, 1, data);
+}
+
+//------------------------------------------------------------------------------
+// Vertical filter.
+
+#define FILTER_LINE_BY_LINE(INVERSE) do { \
+ while (row < last_row) { \
+ DO_PREDICT_LINE_VERTICAL(in, preds, out, width, INVERSE); \
+ ++row; \
+ preds += stride; \
+ in += stride; \
+ out += stride; \
+ } \
+ } while (0)
+
+static WEBP_INLINE void DoVerticalFilter(const uint8_t* in,
+ int width, int height, int stride,
+ int row, int num_rows,
+ int inverse, uint8_t* out) {
+ const uint8_t* preds;
+ const size_t start_offset = row * stride;
+ const int last_row = row + num_rows;
+ SANITY_CHECK(in, out);
+ in += start_offset;
+ out += start_offset;
+ preds = inverse ? out : in;
+
+ if (row == 0) {
+ // Very first top-left pixel is copied.
+ out[0] = in[0];
+ // Rest of top scan-line is left-predicted.
+ PredictLine(in + 1, out + 1, width - 1, inverse);
+ row = 1;
+ in += stride;
+ out += stride;
+ } else {
+ // We are starting from in-between. Make sure 'preds' points to prev row.
+ preds -= stride;
+ }
+
+ // Filter line-by-line.
+ if (inverse) {
+ FILTER_LINE_BY_LINE(1);
+ } else {
+ FILTER_LINE_BY_LINE(0);
+ }
+}
+
+#undef FILTER_LINE_BY_LINE
+#undef DO_PREDICT_LINE_VERTICAL
+
+static void VerticalFilter(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data);
+}
+
+static void VerticalUnfilter(int width, int height, int stride, int row,
+ int num_rows, uint8_t* data) {
+ DoVerticalFilter(data, width, height, stride, row, num_rows, 1, data);
+}
+
+//------------------------------------------------------------------------------
+// Gradient filter.
+
+static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) {
+ int temp0;
+ __asm__ volatile (
+ "addu %[temp0], %[a], %[b] \n\t"
+ "subu %[temp0], %[temp0], %[c] \n\t"
+ "shll_s.w %[temp0], %[temp0], 23 \n\t"
+ "precrqu_s.qb.ph %[temp0], %[temp0], $zero \n\t"
+ "srl %[temp0], %[temp0], 24 \n\t"
+ : [temp0]"=&r"(temp0)
+ : [a]"r"(a),[b]"r"(b),[c]"r"(c)
+ );
+ return temp0;
+}
+
+#define FILTER_LINE_BY_LINE(INVERSE, PREDS, OPERATION) do { \
+ while (row < last_row) { \
+ int w; \
+ PREDICT_LINE_ONE_PASS(in, PREDS - stride, out, INVERSE); \
+ for (w = 1; w < width; ++w) { \
+ const int pred = GradientPredictor(PREDS[w - 1], \
+ PREDS[w - stride], \
+ PREDS[w - stride - 1]); \
+ out[w] = in[w] OPERATION pred; \
+ } \
+ ++row; \
+ in += stride; \
+ out += stride; \
+ } \
+ } while (0)
+
+static WEBP_INLINE void DoGradientFilter(const uint8_t* in,
+ int width, int height, int stride,
+ int row, int num_rows,
+ int inverse, uint8_t* out) {
+ const uint8_t* preds;
+ const size_t start_offset = row * stride;
+ const int last_row = row + num_rows;
+ SANITY_CHECK(in, out);
+ in += start_offset;
+ out += start_offset;
+ preds = inverse ? out : in;
+
+ // left prediction for top scan-line
+ if (row == 0) {
+ out[0] = in[0];
+ PredictLine(in + 1, out + 1, width - 1, inverse);
+ row = 1;
+ preds += stride;
+ in += stride;
+ out += stride;
+ }
+
+ // Filter line-by-line.
+ if (inverse) {
+ FILTER_LINE_BY_LINE(1, out, +);
+ } else {
+ FILTER_LINE_BY_LINE(0, in, -);
+ }
+}
+
+#undef FILTER_LINE_BY_LINE
+
+static void GradientFilter(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data);
+}
+
+static void GradientUnfilter(int width, int height, int stride, int row,
+ int num_rows, uint8_t* data) {
+ DoGradientFilter(data, width, height, stride, row, num_rows, 1, data);
+}
+
+#undef PREDICT_LINE_ONE_PASS
+#undef DO_PREDICT_LINE
+#undef SANITY_CHECK
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8FiltersInitMIPSdspR2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitMIPSdspR2(void) {
+ WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter;
+ WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter;
+ WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter;
+
+ WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter;
+ WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter;
+ WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter;
+}
+
+#else // !WEBP_USE_MIPS_DSP_R2
+
+WEBP_DSP_INIT_STUB(VP8FiltersInitMIPSdspR2)
+
+#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/filters_sse2.c b/drivers/webp/dsp/filters_sse2.c
new file mode 100644
index 0000000000..bf93342eb7
--- /dev/null
+++ b/drivers/webp/dsp/filters_sse2.c
@@ -0,0 +1,352 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// SSE2 variant of alpha filters
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_SSE2)
+
+#include <assert.h>
+#include <emmintrin.h>
+#include <stdlib.h>
+#include <string.h>
+
+//------------------------------------------------------------------------------
+// Helpful macro.
+
+# define SANITY_CHECK(in, out) \
+ assert(in != NULL); \
+ assert(out != NULL); \
+ assert(width > 0); \
+ assert(height > 0); \
+ assert(stride >= width); \
+ assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \
+ (void)height; // Silence unused warning.
+
+static void PredictLineTop(const uint8_t* src, const uint8_t* pred,
+ uint8_t* dst, int length, int inverse) {
+ int i;
+ const int max_pos = length & ~31;
+ assert(length >= 0);
+ if (inverse) {
+ for (i = 0; i < max_pos; i += 32) {
+ const __m128i A0 = _mm_loadu_si128((const __m128i*)&src[i + 0]);
+ const __m128i A1 = _mm_loadu_si128((const __m128i*)&src[i + 16]);
+ const __m128i B0 = _mm_loadu_si128((const __m128i*)&pred[i + 0]);
+ const __m128i B1 = _mm_loadu_si128((const __m128i*)&pred[i + 16]);
+ const __m128i C0 = _mm_add_epi8(A0, B0);
+ const __m128i C1 = _mm_add_epi8(A1, B1);
+ _mm_storeu_si128((__m128i*)&dst[i + 0], C0);
+ _mm_storeu_si128((__m128i*)&dst[i + 16], C1);
+ }
+ for (; i < length; ++i) dst[i] = src[i] + pred[i];
+ } else {
+ for (i = 0; i < max_pos; i += 32) {
+ const __m128i A0 = _mm_loadu_si128((const __m128i*)&src[i + 0]);
+ const __m128i A1 = _mm_loadu_si128((const __m128i*)&src[i + 16]);
+ const __m128i B0 = _mm_loadu_si128((const __m128i*)&pred[i + 0]);
+ const __m128i B1 = _mm_loadu_si128((const __m128i*)&pred[i + 16]);
+ const __m128i C0 = _mm_sub_epi8(A0, B0);
+ const __m128i C1 = _mm_sub_epi8(A1, B1);
+ _mm_storeu_si128((__m128i*)&dst[i + 0], C0);
+ _mm_storeu_si128((__m128i*)&dst[i + 16], C1);
+ }
+ for (; i < length; ++i) dst[i] = src[i] - pred[i];
+ }
+}
+
+// Special case for left-based prediction (when preds==dst-1 or preds==src-1).
+static void PredictLineLeft(const uint8_t* src, uint8_t* dst, int length,
+ int inverse) {
+ int i;
+ if (length <= 0) return;
+ if (inverse) {
+ const int max_pos = length & ~7;
+ __m128i last = _mm_set_epi32(0, 0, 0, dst[-1]);
+ for (i = 0; i < max_pos; i += 8) {
+ const __m128i A0 = _mm_loadl_epi64((const __m128i*)(src + i));
+ const __m128i A1 = _mm_add_epi8(A0, last);
+ const __m128i A2 = _mm_slli_si128(A1, 1);
+ const __m128i A3 = _mm_add_epi8(A1, A2);
+ const __m128i A4 = _mm_slli_si128(A3, 2);
+ const __m128i A5 = _mm_add_epi8(A3, A4);
+ const __m128i A6 = _mm_slli_si128(A5, 4);
+ const __m128i A7 = _mm_add_epi8(A5, A6);
+ _mm_storel_epi64((__m128i*)(dst + i), A7);
+ last = _mm_srli_epi64(A7, 56);
+ }
+ for (; i < length; ++i) dst[i] = src[i] + dst[i - 1];
+ } else {
+ const int max_pos = length & ~31;
+ for (i = 0; i < max_pos; i += 32) {
+ const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + i + 0 ));
+ const __m128i B0 = _mm_loadu_si128((const __m128i*)(src + i + 0 - 1));
+ const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + i + 16 ));
+ const __m128i B1 = _mm_loadu_si128((const __m128i*)(src + i + 16 - 1));
+ const __m128i C0 = _mm_sub_epi8(A0, B0);
+ const __m128i C1 = _mm_sub_epi8(A1, B1);
+ _mm_storeu_si128((__m128i*)(dst + i + 0), C0);
+ _mm_storeu_si128((__m128i*)(dst + i + 16), C1);
+ }
+ for (; i < length; ++i) dst[i] = src[i] - src[i - 1];
+ }
+}
+
+static void PredictLineC(const uint8_t* src, const uint8_t* pred,
+ uint8_t* dst, int length, int inverse) {
+ int i;
+ if (inverse) {
+ for (i = 0; i < length; ++i) dst[i] = src[i] + pred[i];
+ } else {
+ for (i = 0; i < length; ++i) dst[i] = src[i] - pred[i];
+ }
+}
+
+//------------------------------------------------------------------------------
+// Horizontal filter.
+
+static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in,
+ int width, int height, int stride,
+ int row, int num_rows,
+ int inverse, uint8_t* out) {
+ const uint8_t* preds;
+ const size_t start_offset = row * stride;
+ const int last_row = row + num_rows;
+ SANITY_CHECK(in, out);
+ in += start_offset;
+ out += start_offset;
+ preds = inverse ? out : in;
+
+ if (row == 0) {
+ // Leftmost pixel is the same as input for topmost scanline.
+ out[0] = in[0];
+ PredictLineLeft(in + 1, out + 1, width - 1, inverse);
+ row = 1;
+ preds += stride;
+ in += stride;
+ out += stride;
+ }
+
+ // Filter line-by-line.
+ while (row < last_row) {
+ // Leftmost pixel is predicted from above.
+ PredictLineC(in, preds - stride, out, 1, inverse);
+ PredictLineLeft(in + 1, out + 1, width - 1, inverse);
+ ++row;
+ preds += stride;
+ in += stride;
+ out += stride;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Vertical filter.
+
+static WEBP_INLINE void DoVerticalFilter(const uint8_t* in,
+ int width, int height, int stride,
+ int row, int num_rows,
+ int inverse, uint8_t* out) {
+ const uint8_t* preds;
+ const size_t start_offset = row * stride;
+ const int last_row = row + num_rows;
+ SANITY_CHECK(in, out);
+ in += start_offset;
+ out += start_offset;
+ preds = inverse ? out : in;
+
+ if (row == 0) {
+ // Very first top-left pixel is copied.
+ out[0] = in[0];
+ // Rest of top scan-line is left-predicted.
+ PredictLineLeft(in + 1, out + 1, width - 1, inverse);
+ row = 1;
+ in += stride;
+ out += stride;
+ } else {
+ // We are starting from in-between. Make sure 'preds' points to prev row.
+ preds -= stride;
+ }
+
+ // Filter line-by-line.
+ while (row < last_row) {
+ PredictLineTop(in, preds, out, width, inverse);
+ ++row;
+ preds += stride;
+ in += stride;
+ out += stride;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Gradient filter.
+
+static WEBP_INLINE int GradientPredictorC(uint8_t a, uint8_t b, uint8_t c) {
+ const int g = a + b - c;
+ return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit
+}
+
+static void GradientPredictDirect(const uint8_t* const row,
+ const uint8_t* const top,
+ uint8_t* const out, int length) {
+ const int max_pos = length & ~7;
+ int i;
+ const __m128i zero = _mm_setzero_si128();
+ for (i = 0; i < max_pos; i += 8) {
+ const __m128i A0 = _mm_loadl_epi64((const __m128i*)&row[i - 1]);
+ const __m128i B0 = _mm_loadl_epi64((const __m128i*)&top[i]);
+ const __m128i C0 = _mm_loadl_epi64((const __m128i*)&top[i - 1]);
+ const __m128i D = _mm_loadl_epi64((const __m128i*)&row[i]);
+ const __m128i A1 = _mm_unpacklo_epi8(A0, zero);
+ const __m128i B1 = _mm_unpacklo_epi8(B0, zero);
+ const __m128i C1 = _mm_unpacklo_epi8(C0, zero);
+ const __m128i E = _mm_add_epi16(A1, B1);
+ const __m128i F = _mm_sub_epi16(E, C1);
+ const __m128i G = _mm_packus_epi16(F, zero);
+ const __m128i H = _mm_sub_epi8(D, G);
+ _mm_storel_epi64((__m128i*)(out + i), H);
+ }
+ for (; i < length; ++i) {
+ out[i] = row[i] - GradientPredictorC(row[i - 1], top[i], top[i - 1]);
+ }
+}
+
+static void GradientPredictInverse(const uint8_t* const in,
+ const uint8_t* const top,
+ uint8_t* const row, int length) {
+ if (length > 0) {
+ int i;
+ const int max_pos = length & ~7;
+ const __m128i zero = _mm_setzero_si128();
+ __m128i A = _mm_set_epi32(0, 0, 0, row[-1]); // left sample
+ for (i = 0; i < max_pos; i += 8) {
+ const __m128i tmp0 = _mm_loadl_epi64((const __m128i*)&top[i]);
+ const __m128i tmp1 = _mm_loadl_epi64((const __m128i*)&top[i - 1]);
+ const __m128i B = _mm_unpacklo_epi8(tmp0, zero);
+ const __m128i C = _mm_unpacklo_epi8(tmp1, zero);
+ const __m128i tmp2 = _mm_loadl_epi64((const __m128i*)&in[i]);
+ const __m128i D = _mm_unpacklo_epi8(tmp2, zero); // base input
+ const __m128i E = _mm_sub_epi16(B, C); // unclipped gradient basis B - C
+ __m128i out = zero; // accumulator for output
+ __m128i mask_hi = _mm_set_epi32(0, 0, 0, 0xff);
+ int k = 8;
+ while (1) {
+ const __m128i tmp3 = _mm_add_epi16(A, E); // delta = A + B - C
+ const __m128i tmp4 = _mm_min_epi16(tmp3, mask_hi);
+ const __m128i tmp5 = _mm_max_epi16(tmp4, zero); // clipped delta
+ const __m128i tmp6 = _mm_add_epi16(tmp5, D); // add to in[] values
+ A = _mm_and_si128(tmp6, mask_hi); // 1-complement clip
+ out = _mm_or_si128(out, A); // accumulate output
+ if (--k == 0) break;
+ A = _mm_slli_si128(A, 2); // rotate left sample
+ mask_hi = _mm_slli_si128(mask_hi, 2); // rotate mask
+ }
+ A = _mm_srli_si128(A, 14); // prepare left sample for next iteration
+ _mm_storel_epi64((__m128i*)&row[i], _mm_packus_epi16(out, zero));
+ }
+ for (; i < length; ++i) {
+ row[i] = in[i] + GradientPredictorC(row[i - 1], top[i], top[i - 1]);
+ }
+ }
+}
+
+static WEBP_INLINE void DoGradientFilter(const uint8_t* in,
+ int width, int height, int stride,
+ int row, int num_rows,
+ int inverse, uint8_t* out) {
+ const size_t start_offset = row * stride;
+ const int last_row = row + num_rows;
+ SANITY_CHECK(in, out);
+ in += start_offset;
+ out += start_offset;
+
+ // left prediction for top scan-line
+ if (row == 0) {
+ out[0] = in[0];
+ PredictLineLeft(in + 1, out + 1, width - 1, inverse);
+ row = 1;
+ in += stride;
+ out += stride;
+ }
+
+ // Filter line-by-line.
+ while (row < last_row) {
+ if (inverse) {
+ PredictLineC(in, out - stride, out, 1, inverse); // predict from above
+ GradientPredictInverse(in + 1, out + 1 - stride, out + 1, width - 1);
+ } else {
+ PredictLineC(in, in - stride, out, 1, inverse);
+ GradientPredictDirect(in + 1, in + 1 - stride, out + 1, width - 1);
+ }
+ ++row;
+ in += stride;
+ out += stride;
+ }
+}
+
+#undef SANITY_CHECK
+
+//------------------------------------------------------------------------------
+
+static void HorizontalFilter(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data);
+}
+
+static void VerticalFilter(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data);
+}
+
+
+static void GradientFilter(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data);
+}
+
+
+//------------------------------------------------------------------------------
+
+static void VerticalUnfilter(int width, int height, int stride, int row,
+ int num_rows, uint8_t* data) {
+ DoVerticalFilter(data, width, height, stride, row, num_rows, 1, data);
+}
+
+static void HorizontalUnfilter(int width, int height, int stride, int row,
+ int num_rows, uint8_t* data) {
+ DoHorizontalFilter(data, width, height, stride, row, num_rows, 1, data);
+}
+
+static void GradientUnfilter(int width, int height, int stride, int row,
+ int num_rows, uint8_t* data) {
+ DoGradientFilter(data, width, height, stride, row, num_rows, 1, data);
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8FiltersInitSSE2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitSSE2(void) {
+ WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter;
+ WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter;
+ WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter;
+
+ WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter;
+ WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter;
+ WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter;
+}
+
+#else // !WEBP_USE_SSE2
+
+WEBP_DSP_INIT_STUB(VP8FiltersInitSSE2)
+
+#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/lossless.c b/drivers/webp/dsp/lossless.c
index 62a6b7b15a..5702eb3b17 100644
--- a/drivers/webp/dsp/lossless.c
+++ b/drivers/webp/dsp/lossless.c
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Image transforms and color space conversion methods for lossless decoder.
@@ -11,170 +13,16 @@
// Jyrki Alakuijala (jyrki@google.com)
// Urvang Joshi (urvang@google.com)
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+#include "./dsp.h"
#include <math.h>
#include <stdlib.h>
-#include "./lossless.h"
#include "../dec/vp8li.h"
-#include "../dsp/yuv.h"
-#include "../dsp/dsp.h"
-#include "../enc/histogram.h"
+#include "../utils/endian_inl.h"
+#include "./lossless.h"
#define MAX_DIFF_COST (1e30f)
-// lookup table for small values of log2(int)
-#define APPROX_LOG_MAX 4096
-#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086
-#define LOG_LOOKUP_IDX_MAX 256
-static const float kLog2Table[LOG_LOOKUP_IDX_MAX] = {
- 0.0000000000000000f, 0.0000000000000000f,
- 1.0000000000000000f, 1.5849625007211560f,
- 2.0000000000000000f, 2.3219280948873621f,
- 2.5849625007211560f, 2.8073549220576041f,
- 3.0000000000000000f, 3.1699250014423121f,
- 3.3219280948873621f, 3.4594316186372973f,
- 3.5849625007211560f, 3.7004397181410921f,
- 3.8073549220576041f, 3.9068905956085187f,
- 4.0000000000000000f, 4.0874628412503390f,
- 4.1699250014423121f, 4.2479275134435852f,
- 4.3219280948873626f, 4.3923174227787606f,
- 4.4594316186372973f, 4.5235619560570130f,
- 4.5849625007211560f, 4.6438561897747243f,
- 4.7004397181410917f, 4.7548875021634682f,
- 4.8073549220576037f, 4.8579809951275718f,
- 4.9068905956085187f, 4.9541963103868749f,
- 5.0000000000000000f, 5.0443941193584533f,
- 5.0874628412503390f, 5.1292830169449663f,
- 5.1699250014423121f, 5.2094533656289501f,
- 5.2479275134435852f, 5.2854022188622487f,
- 5.3219280948873626f, 5.3575520046180837f,
- 5.3923174227787606f, 5.4262647547020979f,
- 5.4594316186372973f, 5.4918530963296747f,
- 5.5235619560570130f, 5.5545888516776376f,
- 5.5849625007211560f, 5.6147098441152083f,
- 5.6438561897747243f, 5.6724253419714951f,
- 5.7004397181410917f, 5.7279204545631987f,
- 5.7548875021634682f, 5.7813597135246599f,
- 5.8073549220576037f, 5.8328900141647412f,
- 5.8579809951275718f, 5.8826430493618415f,
- 5.9068905956085187f, 5.9307373375628866f,
- 5.9541963103868749f, 5.9772799234999167f,
- 6.0000000000000000f, 6.0223678130284543f,
- 6.0443941193584533f, 6.0660891904577720f,
- 6.0874628412503390f, 6.1085244567781691f,
- 6.1292830169449663f, 6.1497471195046822f,
- 6.1699250014423121f, 6.1898245588800175f,
- 6.2094533656289501f, 6.2288186904958804f,
- 6.2479275134435852f, 6.2667865406949010f,
- 6.2854022188622487f, 6.3037807481771030f,
- 6.3219280948873626f, 6.3398500028846243f,
- 6.3575520046180837f, 6.3750394313469245f,
- 6.3923174227787606f, 6.4093909361377017f,
- 6.4262647547020979f, 6.4429434958487279f,
- 6.4594316186372973f, 6.4757334309663976f,
- 6.4918530963296747f, 6.5077946401986963f,
- 6.5235619560570130f, 6.5391588111080309f,
- 6.5545888516776376f, 6.5698556083309478f,
- 6.5849625007211560f, 6.5999128421871278f,
- 6.6147098441152083f, 6.6293566200796094f,
- 6.6438561897747243f, 6.6582114827517946f,
- 6.6724253419714951f, 6.6865005271832185f,
- 6.7004397181410917f, 6.7142455176661224f,
- 6.7279204545631987f, 6.7414669864011464f,
- 6.7548875021634682f, 6.7681843247769259f,
- 6.7813597135246599f, 6.7944158663501061f,
- 6.8073549220576037f, 6.8201789624151878f,
- 6.8328900141647412f, 6.8454900509443747f,
- 6.8579809951275718f, 6.8703647195834047f,
- 6.8826430493618415f, 6.8948177633079437f,
- 6.9068905956085187f, 6.9188632372745946f,
- 6.9307373375628866f, 6.9425145053392398f,
- 6.9541963103868749f, 6.9657842846620869f,
- 6.9772799234999167f, 6.9886846867721654f,
- 7.0000000000000000f, 7.0112272554232539f,
- 7.0223678130284543f, 7.0334230015374501f,
- 7.0443941193584533f, 7.0552824355011898f,
- 7.0660891904577720f, 7.0768155970508308f,
- 7.0874628412503390f, 7.0980320829605263f,
- 7.1085244567781691f, 7.1189410727235076f,
- 7.1292830169449663f, 7.1395513523987936f,
- 7.1497471195046822f, 7.1598713367783890f,
- 7.1699250014423121f, 7.1799090900149344f,
- 7.1898245588800175f, 7.1996723448363644f,
- 7.2094533656289501f, 7.2191685204621611f,
- 7.2288186904958804f, 7.2384047393250785f,
- 7.2479275134435852f, 7.2573878426926521f,
- 7.2667865406949010f, 7.2761244052742375f,
- 7.2854022188622487f, 7.2946207488916270f,
- 7.3037807481771030f, 7.3128829552843557f,
- 7.3219280948873626f, 7.3309168781146167f,
- 7.3398500028846243f, 7.3487281542310771f,
- 7.3575520046180837f, 7.3663222142458160f,
- 7.3750394313469245f, 7.3837042924740519f,
- 7.3923174227787606f, 7.4008794362821843f,
- 7.4093909361377017f, 7.4178525148858982f,
- 7.4262647547020979f, 7.4346282276367245f,
- 7.4429434958487279f, 7.4512111118323289f,
- 7.4594316186372973f, 7.4676055500829976f,
- 7.4757334309663976f, 7.4838157772642563f,
- 7.4918530963296747f, 7.4998458870832056f,
- 7.5077946401986963f, 7.5156998382840427f,
- 7.5235619560570130f, 7.5313814605163118f,
- 7.5391588111080309f, 7.5468944598876364f,
- 7.5545888516776376f, 7.5622424242210728f,
- 7.5698556083309478f, 7.5774288280357486f,
- 7.5849625007211560f, 7.5924570372680806f,
- 7.5999128421871278f, 7.6073303137496104f,
- 7.6147098441152083f, 7.6220518194563764f,
- 7.6293566200796094f, 7.6366246205436487f,
- 7.6438561897747243f, 7.6510516911789281f,
- 7.6582114827517946f, 7.6653359171851764f,
- 7.6724253419714951f, 7.6794800995054464f,
- 7.6865005271832185f, 7.6934869574993252f,
- 7.7004397181410917f, 7.7073591320808825f,
- 7.7142455176661224f, 7.7210991887071855f,
- 7.7279204545631987f, 7.7347096202258383f,
- 7.7414669864011464f, 7.7481928495894605f,
- 7.7548875021634682f, 7.7615512324444795f,
- 7.7681843247769259f, 7.7747870596011736f,
- 7.7813597135246599f, 7.7879025593914317f,
- 7.7944158663501061f, 7.8008998999203047f,
- 7.8073549220576037f, 7.8137811912170374f,
- 7.8201789624151878f, 7.8265484872909150f,
- 7.8328900141647412f, 7.8392037880969436f,
- 7.8454900509443747f, 7.8517490414160571f,
- 7.8579809951275718f, 7.8641861446542797f,
- 7.8703647195834047f, 7.8765169465649993f,
- 7.8826430493618415f, 7.8887432488982591f,
- 7.8948177633079437f, 7.9008668079807486f,
- 7.9068905956085187f, 7.9128893362299619f,
- 7.9188632372745946f, 7.9248125036057812f,
- 7.9307373375628866f, 7.9366379390025709f,
- 7.9425145053392398f, 7.9483672315846778f,
- 7.9541963103868749f, 7.9600019320680805f,
- 7.9657842846620869f, 7.9715435539507719f,
- 7.9772799234999167f, 7.9829935746943103f,
- 7.9886846867721654f, 7.9943534368588577f
-};
-
-float VP8LFastLog2(int v) {
- if (v < LOG_LOOKUP_IDX_MAX) {
- return kLog2Table[v];
- } else if (v < APPROX_LOG_MAX) {
- int log_cnt = 0;
- while (v >= LOG_LOOKUP_IDX_MAX) {
- ++log_cnt;
- v = v >> 1;
- }
- return kLog2Table[v] + (float)log_cnt;
- } else {
- return (float)(LOG_2_RECIPROCAL * log((double)v));
- }
-}
-
//------------------------------------------------------------------------------
// Image transforms.
@@ -186,7 +34,7 @@ static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) {
}
static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
- return (((a0 ^ a1) & 0xfefefefeL) >> 1) + (a0 & a1);
+ return (((a0 ^ a1) & 0xfefefefeu) >> 1) + (a0 & a1);
}
static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
@@ -221,7 +69,7 @@ static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
(c1 >> 8) & 0xff,
(c2 >> 8) & 0xff);
const int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff);
- return (a << 24) | (r << 16) | (g << 8) | b;
+ return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
}
static WEBP_INLINE int AddSubtractComponentHalf(int a, int b) {
@@ -235,22 +83,30 @@ static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
const int r = AddSubtractComponentHalf((ave >> 16) & 0xff, (c2 >> 16) & 0xff);
const int g = AddSubtractComponentHalf((ave >> 8) & 0xff, (c2 >> 8) & 0xff);
const int b = AddSubtractComponentHalf((ave >> 0) & 0xff, (c2 >> 0) & 0xff);
- return (a << 24) | (r << 16) | (g << 8) | b;
+ return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
}
-static WEBP_INLINE int Sub3(int a, int b, int c) {
- const int pa = b - c;
- const int pb = a - c;
- return abs(pa) - abs(pb);
+// gcc-4.9 on ARM generates incorrect code in Select() when Sub3() is inlined.
+#if defined(__arm__) && LOCAL_GCC_VERSION == 0x409
+# define LOCAL_INLINE __attribute__ ((noinline))
+#else
+# define LOCAL_INLINE WEBP_INLINE
+#endif
+
+static LOCAL_INLINE int Sub3(int a, int b, int c) {
+ const int pb = b - c;
+ const int pa = a - c;
+ return abs(pb) - abs(pa);
}
+#undef LOCAL_INLINE
+
static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
const int pa_minus_pb =
Sub3((a >> 24) , (b >> 24) , (c >> 24) ) +
Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) +
Sub3((a >> 8) & 0xff, (b >> 8) & 0xff, (c >> 8) & 0xff) +
Sub3((a ) & 0xff, (b ) & 0xff, (c ) & 0xff);
-
return (pa_minus_pb <= 0) ? a : b;
}
@@ -317,208 +173,7 @@ static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
return pred;
}
-typedef uint32_t (*PredictorFunc)(uint32_t left, const uint32_t* const top);
-static const PredictorFunc kPredictors[16] = {
- Predictor0, Predictor1, Predictor2, Predictor3,
- Predictor4, Predictor5, Predictor6, Predictor7,
- Predictor8, Predictor9, Predictor10, Predictor11,
- Predictor12, Predictor13,
- Predictor0, Predictor0 // <- padding security sentinels
-};
-
-// TODO(vikasa): Replace 256 etc with defines.
-static float PredictionCostSpatial(const int* counts,
- int weight_0, double exp_val) {
- const int significant_symbols = 16;
- const double exp_decay_factor = 0.6;
- double bits = weight_0 * counts[0];
- int i;
- for (i = 1; i < significant_symbols; ++i) {
- bits += exp_val * (counts[i] + counts[256 - i]);
- exp_val *= exp_decay_factor;
- }
- return (float)(-0.1 * bits);
-}
-
-// Compute the Shanon's entropy: Sum(p*log2(p))
-static float ShannonEntropy(const int* const array, int n) {
- int i;
- float retval = 0.f;
- int sum = 0;
- for (i = 0; i < n; ++i) {
- if (array[i] != 0) {
- sum += array[i];
- retval -= VP8LFastSLog2(array[i]);
- }
- }
- retval += VP8LFastSLog2(sum);
- return retval;
-}
-
-static float PredictionCostSpatialHistogram(int accumulated[4][256],
- int tile[4][256]) {
- int i;
- int k;
- int combo[256];
- double retval = 0;
- for (i = 0; i < 4; ++i) {
- const double exp_val = 0.94;
- retval += PredictionCostSpatial(&tile[i][0], 1, exp_val);
- retval += ShannonEntropy(&tile[i][0], 256);
- for (k = 0; k < 256; ++k) {
- combo[k] = accumulated[i][k] + tile[i][k];
- }
- retval += ShannonEntropy(&combo[0], 256);
- }
- return (float)retval;
-}
-
-static int GetBestPredictorForTile(int width, int height,
- int tile_x, int tile_y, int bits,
- int accumulated[4][256],
- const uint32_t* const argb_scratch) {
- const int kNumPredModes = 14;
- const int col_start = tile_x << bits;
- const int row_start = tile_y << bits;
- const int tile_size = 1 << bits;
- const int ymax = (tile_size <= height - row_start) ?
- tile_size : height - row_start;
- const int xmax = (tile_size <= width - col_start) ?
- tile_size : width - col_start;
- int histo[4][256];
- float best_diff = MAX_DIFF_COST;
- int best_mode = 0;
-
- int mode;
- for (mode = 0; mode < kNumPredModes; ++mode) {
- const uint32_t* current_row = argb_scratch;
- const PredictorFunc pred_func = kPredictors[mode];
- float cur_diff;
- int y;
- memset(&histo[0][0], 0, sizeof(histo));
- for (y = 0; y < ymax; ++y) {
- int x;
- const int row = row_start + y;
- const uint32_t* const upper_row = current_row;
- current_row = upper_row + width;
- for (x = 0; x < xmax; ++x) {
- const int col = col_start + x;
- uint32_t predict;
- uint32_t predict_diff;
- if (row == 0) {
- predict = (col == 0) ? ARGB_BLACK : current_row[col - 1]; // Left.
- } else if (col == 0) {
- predict = upper_row[col]; // Top.
- } else {
- predict = pred_func(current_row[col - 1], upper_row + col);
- }
- predict_diff = VP8LSubPixels(current_row[col], predict);
- ++histo[0][predict_diff >> 24];
- ++histo[1][((predict_diff >> 16) & 0xff)];
- ++histo[2][((predict_diff >> 8) & 0xff)];
- ++histo[3][(predict_diff & 0xff)];
- }
- }
- cur_diff = PredictionCostSpatialHistogram(accumulated, histo);
- if (cur_diff < best_diff) {
- best_diff = cur_diff;
- best_mode = mode;
- }
- }
-
- return best_mode;
-}
-
-static void CopyTileWithPrediction(int width, int height,
- int tile_x, int tile_y, int bits, int mode,
- const uint32_t* const argb_scratch,
- uint32_t* const argb) {
- const int col_start = tile_x << bits;
- const int row_start = tile_y << bits;
- const int tile_size = 1 << bits;
- const int ymax = (tile_size <= height - row_start) ?
- tile_size : height - row_start;
- const int xmax = (tile_size <= width - col_start) ?
- tile_size : width - col_start;
- const PredictorFunc pred_func = kPredictors[mode];
- const uint32_t* current_row = argb_scratch;
-
- int y;
- for (y = 0; y < ymax; ++y) {
- int x;
- const int row = row_start + y;
- const uint32_t* const upper_row = current_row;
- current_row = upper_row + width;
- for (x = 0; x < xmax; ++x) {
- const int col = col_start + x;
- const int pix = row * width + col;
- uint32_t predict;
- if (row == 0) {
- predict = (col == 0) ? ARGB_BLACK : current_row[col - 1]; // Left.
- } else if (col == 0) {
- predict = upper_row[col]; // Top.
- } else {
- predict = pred_func(current_row[col - 1], upper_row + col);
- }
- argb[pix] = VP8LSubPixels(current_row[col], predict);
- }
- }
-}
-
-void VP8LResidualImage(int width, int height, int bits,
- uint32_t* const argb, uint32_t* const argb_scratch,
- uint32_t* const image) {
- const int max_tile_size = 1 << bits;
- const int tiles_per_row = VP8LSubSampleSize(width, bits);
- const int tiles_per_col = VP8LSubSampleSize(height, bits);
- uint32_t* const upper_row = argb_scratch;
- uint32_t* const current_tile_rows = argb_scratch + width;
- int tile_y;
- int histo[4][256];
- memset(histo, 0, sizeof(histo));
- for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) {
- const int tile_y_offset = tile_y * max_tile_size;
- const int this_tile_height =
- (tile_y < tiles_per_col - 1) ? max_tile_size : height - tile_y_offset;
- int tile_x;
- if (tile_y > 0) {
- memcpy(upper_row, current_tile_rows + (max_tile_size - 1) * width,
- width * sizeof(*upper_row));
- }
- memcpy(current_tile_rows, &argb[tile_y_offset * width],
- this_tile_height * width * sizeof(*current_tile_rows));
- for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) {
- int pred;
- int y;
- const int tile_x_offset = tile_x * max_tile_size;
- int all_x_max = tile_x_offset + max_tile_size;
- if (all_x_max > width) {
- all_x_max = width;
- }
- pred = GetBestPredictorForTile(width, height, tile_x, tile_y, bits, histo,
- argb_scratch);
- image[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8);
- CopyTileWithPrediction(width, height, tile_x, tile_y, bits, pred,
- argb_scratch, argb);
- for (y = 0; y < max_tile_size; ++y) {
- int ix;
- int all_x;
- int all_y = tile_y_offset + y;
- if (all_y >= height) {
- break;
- }
- ix = all_y * width + tile_x_offset;
- for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
- const uint32_t a = argb[ix];
- ++histo[0][a >> 24];
- ++histo[1][((a >> 16) & 0xff)];
- ++histo[2][((a >> 8) & 0xff)];
- ++histo[3][(a & 0xff)];
- }
- }
- }
- }
-}
+//------------------------------------------------------------------------------
// Inverse prediction.
static void PredictorInverseTransform(const VP8LTransform* const transform,
@@ -538,29 +193,36 @@ static void PredictorInverseTransform(const VP8LTransform* const transform,
{
int y = y_start;
- const int mask = (1 << transform->bits_) - 1;
+ const int tile_width = 1 << transform->bits_;
+ const int mask = tile_width - 1;
+ const int safe_width = width & ~mask;
const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_);
const uint32_t* pred_mode_base =
transform->data_ + (y >> transform->bits_) * tiles_per_row;
while (y < y_end) {
- int x;
const uint32_t pred2 = Predictor2(data[-1], data - width);
const uint32_t* pred_mode_src = pred_mode_base;
- PredictorFunc pred_func;
-
+ VP8LPredictorFunc pred_func;
+ int x = 1;
+ int t = 1;
// First pixel follows the T (mode=2) mode.
AddPixelsEq(data, pred2);
-
// .. the rest:
- pred_func = kPredictors[((*pred_mode_src++) >> 8) & 0xf];
- for (x = 1; x < width; ++x) {
- uint32_t pred;
- if ((x & mask) == 0) { // start of tile. Read predictor function.
- pred_func = kPredictors[((*pred_mode_src++) >> 8) & 0xf];
+ while (x < safe_width) {
+ pred_func = VP8LPredictors[((*pred_mode_src++) >> 8) & 0xf];
+ for (; t < tile_width; ++t, ++x) {
+ const uint32_t pred = pred_func(data[x - 1], data + x - width);
+ AddPixelsEq(data + x, pred);
+ }
+ t = 0;
+ }
+ if (x < width) {
+ pred_func = VP8LPredictors[((*pred_mode_src++) >> 8) & 0xf];
+ for (; x < width; ++x) {
+ const uint32_t pred = pred_func(data[x - 1], data + x - width);
+ AddPixelsEq(data + x, pred);
}
- pred = pred_func(data[x - 1], data + x - width);
- AddPixelsEq(data + x, pred);
}
data += width;
++y;
@@ -571,326 +233,47 @@ static void PredictorInverseTransform(const VP8LTransform* const transform,
}
}
-void VP8LSubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixs) {
- int i;
- for (i = 0; i < num_pixs; ++i) {
- const uint32_t argb = argb_data[i];
- const uint32_t green = (argb >> 8) & 0xff;
- const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff;
- const uint32_t new_b = ((argb & 0xff) - green) & 0xff;
- argb_data[i] = (argb & 0xff00ff00) | (new_r << 16) | new_b;
- }
-}
-
// Add green to blue and red channels (i.e. perform the inverse transform of
// 'subtract green').
-static void AddGreenToBlueAndRed(const VP8LTransform* const transform,
- int y_start, int y_end, uint32_t* data) {
- const int width = transform->xsize_;
- const uint32_t* const data_end = data + (y_end - y_start) * width;
- while (data < data_end) {
- const uint32_t argb = *data;
- // "* 0001001u" is equivalent to "(green << 16) + green)"
+void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels) {
+ int i;
+ for (i = 0; i < num_pixels; ++i) {
+ const uint32_t argb = data[i];
const uint32_t green = ((argb >> 8) & 0xff);
uint32_t red_blue = (argb & 0x00ff00ffu);
red_blue += (green << 16) | green;
red_blue &= 0x00ff00ffu;
- *data++ = (argb & 0xff00ff00u) | red_blue;
+ data[i] = (argb & 0xff00ff00u) | red_blue;
}
}
-typedef struct {
- // Note: the members are uint8_t, so that any negative values are
- // automatically converted to "mod 256" values.
- uint8_t green_to_red_;
- uint8_t green_to_blue_;
- uint8_t red_to_blue_;
-} Multipliers;
-
-static WEBP_INLINE void MultipliersClear(Multipliers* m) {
- m->green_to_red_ = 0;
- m->green_to_blue_ = 0;
- m->red_to_blue_ = 0;
-}
-
static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred,
int8_t color) {
return (uint32_t)((int)(color_pred) * color) >> 5;
}
static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code,
- Multipliers* const m) {
+ VP8LMultipliers* const m) {
m->green_to_red_ = (color_code >> 0) & 0xff;
m->green_to_blue_ = (color_code >> 8) & 0xff;
m->red_to_blue_ = (color_code >> 16) & 0xff;
}
-static WEBP_INLINE uint32_t MultipliersToColorCode(Multipliers* const m) {
- return 0xff000000u |
- ((uint32_t)(m->red_to_blue_) << 16) |
- ((uint32_t)(m->green_to_blue_) << 8) |
- m->green_to_red_;
-}
-
-static WEBP_INLINE uint32_t TransformColor(const Multipliers* const m,
- uint32_t argb, int inverse) {
- const uint32_t green = argb >> 8;
- const uint32_t red = argb >> 16;
- uint32_t new_red = red;
- uint32_t new_blue = argb;
-
- if (inverse) {
+void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, uint32_t* data,
+ int num_pixels) {
+ int i;
+ for (i = 0; i < num_pixels; ++i) {
+ const uint32_t argb = data[i];
+ const uint32_t green = argb >> 8;
+ const uint32_t red = argb >> 16;
+ uint32_t new_red = red;
+ uint32_t new_blue = argb;
new_red += ColorTransformDelta(m->green_to_red_, green);
new_red &= 0xff;
new_blue += ColorTransformDelta(m->green_to_blue_, green);
new_blue += ColorTransformDelta(m->red_to_blue_, new_red);
new_blue &= 0xff;
- } else {
- new_red -= ColorTransformDelta(m->green_to_red_, green);
- new_red &= 0xff;
- new_blue -= ColorTransformDelta(m->green_to_blue_, green);
- new_blue -= ColorTransformDelta(m->red_to_blue_, red);
- new_blue &= 0xff;
- }
- return (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
-}
-
-static WEBP_INLINE int SkipRepeatedPixels(const uint32_t* const argb,
- int ix, int xsize) {
- const uint32_t v = argb[ix];
- if (ix >= xsize + 3) {
- if (v == argb[ix - xsize] &&
- argb[ix - 1] == argb[ix - xsize - 1] &&
- argb[ix - 2] == argb[ix - xsize - 2] &&
- argb[ix - 3] == argb[ix - xsize - 3]) {
- return 1;
- }
- return v == argb[ix - 3] && v == argb[ix - 2] && v == argb[ix - 1];
- } else if (ix >= 3) {
- return v == argb[ix - 3] && v == argb[ix - 2] && v == argb[ix - 1];
- }
- return 0;
-}
-
-static float PredictionCostCrossColor(const int accumulated[256],
- const int counts[256]) {
- // Favor low entropy, locally and globally.
- int i;
- int combo[256];
- for (i = 0; i < 256; ++i) {
- combo[i] = accumulated[i] + counts[i];
- }
- return ShannonEntropy(combo, 256) +
- ShannonEntropy(counts, 256) +
- PredictionCostSpatial(counts, 3, 2.4); // Favor small absolute values.
-}
-
-static Multipliers GetBestColorTransformForTile(
- int tile_x, int tile_y, int bits,
- Multipliers prevX,
- Multipliers prevY,
- int step, int xsize, int ysize,
- int* accumulated_red_histo,
- int* accumulated_blue_histo,
- const uint32_t* const argb) {
- float best_diff = MAX_DIFF_COST;
- float cur_diff;
- const int halfstep = step / 2;
- const int max_tile_size = 1 << bits;
- const int tile_y_offset = tile_y * max_tile_size;
- const int tile_x_offset = tile_x * max_tile_size;
- int green_to_red;
- int green_to_blue;
- int red_to_blue;
- int all_x_max = tile_x_offset + max_tile_size;
- int all_y_max = tile_y_offset + max_tile_size;
- Multipliers best_tx;
- MultipliersClear(&best_tx);
- if (all_x_max > xsize) {
- all_x_max = xsize;
- }
- if (all_y_max > ysize) {
- all_y_max = ysize;
- }
- for (green_to_red = -64; green_to_red <= 64; green_to_red += halfstep) {
- int histo[256] = { 0 };
- int all_y;
- Multipliers tx;
- MultipliersClear(&tx);
- tx.green_to_red_ = green_to_red & 0xff;
-
- for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) {
- uint32_t predict;
- int ix = all_y * xsize + tile_x_offset;
- int all_x;
- for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
- if (SkipRepeatedPixels(argb, ix, xsize)) {
- continue;
- }
- predict = TransformColor(&tx, argb[ix], 0);
- ++histo[(predict >> 16) & 0xff]; // red.
- }
- }
- cur_diff = PredictionCostCrossColor(&accumulated_red_histo[0], &histo[0]);
- if (tx.green_to_red_ == prevX.green_to_red_) {
- cur_diff -= 3; // favor keeping the areas locally similar
- }
- if (tx.green_to_red_ == prevY.green_to_red_) {
- cur_diff -= 3; // favor keeping the areas locally similar
- }
- if (tx.green_to_red_ == 0) {
- cur_diff -= 3;
- }
- if (cur_diff < best_diff) {
- best_diff = cur_diff;
- best_tx = tx;
- }
- }
- best_diff = MAX_DIFF_COST;
- green_to_red = best_tx.green_to_red_;
- for (green_to_blue = -32; green_to_blue <= 32; green_to_blue += step) {
- for (red_to_blue = -32; red_to_blue <= 32; red_to_blue += step) {
- int all_y;
- int histo[256] = { 0 };
- Multipliers tx;
- tx.green_to_red_ = green_to_red;
- tx.green_to_blue_ = green_to_blue;
- tx.red_to_blue_ = red_to_blue;
- for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) {
- uint32_t predict;
- int all_x;
- int ix = all_y * xsize + tile_x_offset;
- for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
- if (SkipRepeatedPixels(argb, ix, xsize)) {
- continue;
- }
- predict = TransformColor(&tx, argb[ix], 0);
- ++histo[predict & 0xff]; // blue.
- }
- }
- cur_diff =
- PredictionCostCrossColor(&accumulated_blue_histo[0], &histo[0]);
- if (tx.green_to_blue_ == prevX.green_to_blue_) {
- cur_diff -= 3; // favor keeping the areas locally similar
- }
- if (tx.green_to_blue_ == prevY.green_to_blue_) {
- cur_diff -= 3; // favor keeping the areas locally similar
- }
- if (tx.red_to_blue_ == prevX.red_to_blue_) {
- cur_diff -= 3; // favor keeping the areas locally similar
- }
- if (tx.red_to_blue_ == prevY.red_to_blue_) {
- cur_diff -= 3; // favor keeping the areas locally similar
- }
- if (tx.green_to_blue_ == 0) {
- cur_diff -= 3;
- }
- if (tx.red_to_blue_ == 0) {
- cur_diff -= 3;
- }
- if (cur_diff < best_diff) {
- best_diff = cur_diff;
- best_tx = tx;
- }
- }
- }
- return best_tx;
-}
-
-static void CopyTileWithColorTransform(int xsize, int ysize,
- int tile_x, int tile_y, int bits,
- Multipliers color_transform,
- uint32_t* const argb) {
- int y;
- int xscan = 1 << bits;
- int yscan = 1 << bits;
- tile_x <<= bits;
- tile_y <<= bits;
- if (xscan > xsize - tile_x) {
- xscan = xsize - tile_x;
- }
- if (yscan > ysize - tile_y) {
- yscan = ysize - tile_y;
- }
- yscan += tile_y;
- for (y = tile_y; y < yscan; ++y) {
- int ix = y * xsize + tile_x;
- const int end_ix = ix + xscan;
- for (; ix < end_ix; ++ix) {
- argb[ix] = TransformColor(&color_transform, argb[ix], 0);
- }
- }
-}
-
-void VP8LColorSpaceTransform(int width, int height, int bits, int step,
- uint32_t* const argb, uint32_t* image) {
- const int max_tile_size = 1 << bits;
- int tile_xsize = VP8LSubSampleSize(width, bits);
- int tile_ysize = VP8LSubSampleSize(height, bits);
- int accumulated_red_histo[256] = { 0 };
- int accumulated_blue_histo[256] = { 0 };
- int tile_y;
- int tile_x;
- Multipliers prevX;
- Multipliers prevY;
- MultipliersClear(&prevY);
- MultipliersClear(&prevX);
- for (tile_y = 0; tile_y < tile_ysize; ++tile_y) {
- for (tile_x = 0; tile_x < tile_xsize; ++tile_x) {
- Multipliers color_transform;
- int all_x_max;
- int y;
- const int tile_y_offset = tile_y * max_tile_size;
- const int tile_x_offset = tile_x * max_tile_size;
- if (tile_y != 0) {
- ColorCodeToMultipliers(image[tile_y * tile_xsize + tile_x - 1], &prevX);
- ColorCodeToMultipliers(image[(tile_y - 1) * tile_xsize + tile_x],
- &prevY);
- } else if (tile_x != 0) {
- ColorCodeToMultipliers(image[tile_y * tile_xsize + tile_x - 1], &prevX);
- }
- color_transform =
- GetBestColorTransformForTile(tile_x, tile_y, bits,
- prevX, prevY,
- step, width, height,
- &accumulated_red_histo[0],
- &accumulated_blue_histo[0],
- argb);
- image[tile_y * tile_xsize + tile_x] =
- MultipliersToColorCode(&color_transform);
- CopyTileWithColorTransform(width, height, tile_x, tile_y, bits,
- color_transform, argb);
-
- // Gather accumulated histogram data.
- all_x_max = tile_x_offset + max_tile_size;
- if (all_x_max > width) {
- all_x_max = width;
- }
- for (y = 0; y < max_tile_size; ++y) {
- int ix;
- int all_x;
- int all_y = tile_y_offset + y;
- if (all_y >= height) {
- break;
- }
- ix = all_y * width + tile_x_offset;
- for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
- if (ix >= 2 &&
- argb[ix] == argb[ix - 2] &&
- argb[ix] == argb[ix - 1]) {
- continue; // repeated pixels are handled by backward references
- }
- if (ix >= width + 2 &&
- argb[ix - 2] == argb[ix - width - 2] &&
- argb[ix - 1] == argb[ix - width - 1] &&
- argb[ix] == argb[ix - width]) {
- continue; // repeated pixels are handled by backward references
- }
- ++accumulated_red_histo[(argb[ix] >> 16) & 0xff];
- ++accumulated_blue_histo[argb[ix] & 0xff];
- }
- }
- }
+ data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
}
}
@@ -898,7 +281,10 @@ void VP8LColorSpaceTransform(int width, int height, int bits, int step,
static void ColorSpaceInverseTransform(const VP8LTransform* const transform,
int y_start, int y_end, uint32_t* data) {
const int width = transform->xsize_;
- const int mask = (1 << transform->bits_) - 1;
+ const int tile_width = 1 << transform->bits_;
+ const int mask = tile_width - 1;
+ const int safe_width = width & ~mask;
+ const int remaining_width = width - safe_width;
const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_);
int y = y_start;
const uint32_t* pred_row =
@@ -906,68 +292,89 @@ static void ColorSpaceInverseTransform(const VP8LTransform* const transform,
while (y < y_end) {
const uint32_t* pred = pred_row;
- Multipliers m = { 0, 0, 0 };
- int x;
-
- for (x = 0; x < width; ++x) {
- if ((x & mask) == 0) ColorCodeToMultipliers(*pred++, &m);
- data[x] = TransformColor(&m, data[x], 1);
+ VP8LMultipliers m = { 0, 0, 0 };
+ const uint32_t* const data_safe_end = data + safe_width;
+ const uint32_t* const data_end = data + width;
+ while (data < data_safe_end) {
+ ColorCodeToMultipliers(*pred++, &m);
+ VP8LTransformColorInverse(&m, data, tile_width);
+ data += tile_width;
+ }
+ if (data < data_end) { // Left-overs using C-version.
+ ColorCodeToMultipliers(*pred++, &m);
+ VP8LTransformColorInverse(&m, data, remaining_width);
+ data += remaining_width;
}
- data += width;
++y;
- if ((y & mask) == 0) pred_row += tiles_per_row;;
+ if ((y & mask) == 0) pred_row += tiles_per_row;
}
}
// Separate out pixels packed together using pixel-bundling.
-static void ColorIndexInverseTransform(
- const VP8LTransform* const transform,
- int y_start, int y_end, const uint32_t* src, uint32_t* dst) {
- int y;
- const int bits_per_pixel = 8 >> transform->bits_;
- const int width = transform->xsize_;
- const uint32_t* const color_map = transform->data_;
- if (bits_per_pixel < 8) {
- const int pixels_per_byte = 1 << transform->bits_;
- const int count_mask = pixels_per_byte - 1;
- const uint32_t bit_mask = (1 << bits_per_pixel) - 1;
- for (y = y_start; y < y_end; ++y) {
- uint32_t packed_pixels = 0;
- int x;
- for (x = 0; x < width; ++x) {
- // We need to load fresh 'packed_pixels' once every 'pixels_per_byte'
- // increments of x. Fortunately, pixels_per_byte is a power of 2, so
- // can just use a mask for that, instead of decrementing a counter.
- if ((x & count_mask) == 0) packed_pixels = ((*src++) >> 8) & 0xff;
- *dst++ = color_map[packed_pixels & bit_mask];
- packed_pixels >>= bits_per_pixel;
- }
- }
- } else {
- for (y = y_start; y < y_end; ++y) {
- int x;
- for (x = 0; x < width; ++x) {
- *dst++ = color_map[((*src++) >> 8) & 0xff];
- }
- }
- }
-}
+// We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t).
+#define COLOR_INDEX_INVERSE(FUNC_NAME, F_NAME, STATIC_DECL, TYPE, BIT_SUFFIX, \
+ GET_INDEX, GET_VALUE) \
+static void F_NAME(const TYPE* src, const uint32_t* const color_map, \
+ TYPE* dst, int y_start, int y_end, int width) { \
+ int y; \
+ for (y = y_start; y < y_end; ++y) { \
+ int x; \
+ for (x = 0; x < width; ++x) { \
+ *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \
+ } \
+ } \
+} \
+STATIC_DECL void FUNC_NAME(const VP8LTransform* const transform, \
+ int y_start, int y_end, const TYPE* src, \
+ TYPE* dst) { \
+ int y; \
+ const int bits_per_pixel = 8 >> transform->bits_; \
+ const int width = transform->xsize_; \
+ const uint32_t* const color_map = transform->data_; \
+ if (bits_per_pixel < 8) { \
+ const int pixels_per_byte = 1 << transform->bits_; \
+ const int count_mask = pixels_per_byte - 1; \
+ const uint32_t bit_mask = (1 << bits_per_pixel) - 1; \
+ for (y = y_start; y < y_end; ++y) { \
+ uint32_t packed_pixels = 0; \
+ int x; \
+ for (x = 0; x < width; ++x) { \
+ /* We need to load fresh 'packed_pixels' once every */ \
+ /* 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte */ \
+ /* is a power of 2, so can just use a mask for that, instead of */ \
+ /* decrementing a counter. */ \
+ if ((x & count_mask) == 0) packed_pixels = GET_INDEX(*src++); \
+ *dst++ = GET_VALUE(color_map[packed_pixels & bit_mask]); \
+ packed_pixels >>= bits_per_pixel; \
+ } \
+ } \
+ } else { \
+ VP8LMapColor##BIT_SUFFIX(src, color_map, dst, y_start, y_end, width); \
+ } \
+}
+
+COLOR_INDEX_INVERSE(ColorIndexInverseTransform, MapARGB, static, uint32_t, 32b,
+ VP8GetARGBIndex, VP8GetARGBValue)
+COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, MapAlpha, , uint8_t,
+ 8b, VP8GetAlphaIndex, VP8GetAlphaValue)
+
+#undef COLOR_INDEX_INVERSE
void VP8LInverseTransform(const VP8LTransform* const transform,
int row_start, int row_end,
const uint32_t* const in, uint32_t* const out) {
+ const int width = transform->xsize_;
assert(row_start < row_end);
assert(row_end <= transform->ysize_);
switch (transform->type_) {
case SUBTRACT_GREEN:
- AddGreenToBlueAndRed(transform, row_start, row_end, out);
+ VP8LAddGreenToBlueAndRed(out, (row_end - row_start) * width);
break;
case PREDICTOR_TRANSFORM:
PredictorInverseTransform(transform, row_start, row_end, out);
if (row_end != transform->ysize_) {
// The last predicted row in this iteration will be the top-pred row
// for the first row in next iteration.
- const int width = transform->xsize_;
memcpy(out - width, out + (row_end - row_start - 1) * width,
width * sizeof(*out));
}
@@ -982,7 +389,7 @@ void VP8LInverseTransform(const VP8LTransform* const transform,
// Also, note that this is the only transform that applies on
// the effective width of VP8LSubSampleSize(xsize_, bits_). All other
// transforms work on effective width of xsize_.
- const int out_stride = (row_end - row_start) * transform->xsize_;
+ const int out_stride = (row_end - row_start) * width;
const int in_stride = (row_end - row_start) *
VP8LSubSampleSize(transform->xsize_, transform->bits_);
uint32_t* const src = out + out_stride - in_stride;
@@ -1006,8 +413,8 @@ static int is_big_endian(void) {
return (tmp.b[0] != 1);
}
-static void ConvertBGRAToRGB(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
+void VP8LConvertBGRAToRGB_C(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
const uint32_t* const src_end = src + num_pixels;
while (src < src_end) {
const uint32_t argb = *src++;
@@ -1017,8 +424,8 @@ static void ConvertBGRAToRGB(const uint32_t* src,
}
}
-static void ConvertBGRAToRGBA(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
+void VP8LConvertBGRAToRGBA_C(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
const uint32_t* const src_end = src + num_pixels;
while (src < src_end) {
const uint32_t argb = *src++;
@@ -1029,28 +436,42 @@ static void ConvertBGRAToRGBA(const uint32_t* src,
}
}
-static void ConvertBGRAToRGBA4444(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
+void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
const uint32_t* const src_end = src + num_pixels;
while (src < src_end) {
const uint32_t argb = *src++;
- *dst++ = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf);
- *dst++ = ((argb >> 0) & 0xf0) | ((argb >> 28) & 0xf);
+ const uint8_t rg = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf);
+ const uint8_t ba = ((argb >> 0) & 0xf0) | ((argb >> 28) & 0xf);
+#ifdef WEBP_SWAP_16BIT_CSP
+ *dst++ = ba;
+ *dst++ = rg;
+#else
+ *dst++ = rg;
+ *dst++ = ba;
+#endif
}
}
-static void ConvertBGRAToRGB565(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
+void VP8LConvertBGRAToRGB565_C(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
const uint32_t* const src_end = src + num_pixels;
while (src < src_end) {
const uint32_t argb = *src++;
- *dst++ = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7);
- *dst++ = ((argb >> 5) & 0xe0) | ((argb >> 3) & 0x1f);
+ const uint8_t rg = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7);
+ const uint8_t gb = ((argb >> 5) & 0xe0) | ((argb >> 3) & 0x1f);
+#ifdef WEBP_SWAP_16BIT_CSP
+ *dst++ = gb;
+ *dst++ = rg;
+#else
+ *dst++ = rg;
+ *dst++ = gb;
+#endif
}
}
-static void ConvertBGRAToBGR(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
+void VP8LConvertBGRAToBGR_C(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
const uint32_t* const src_end = src + num_pixels;
while (src < src_end) {
const uint32_t argb = *src++;
@@ -1065,21 +486,24 @@ static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst,
if (is_big_endian() == swap_on_big_endian) {
const uint32_t* const src_end = src + num_pixels;
while (src < src_end) {
- uint32_t argb = *src++;
-#if !defined(__BIG_ENDIAN__) && (defined(__i386__) || defined(__x86_64__))
- __asm__ volatile("bswap %0" : "=r"(argb) : "0"(argb));
- *(uint32_t*)dst = argb;
- dst += sizeof(argb);
-#elif !defined(__BIG_ENDIAN__) && defined(_MSC_VER)
- argb = _byteswap_ulong(argb);
- *(uint32_t*)dst = argb;
- dst += sizeof(argb);
-#else
- *dst++ = (argb >> 24) & 0xff;
- *dst++ = (argb >> 16) & 0xff;
- *dst++ = (argb >> 8) & 0xff;
- *dst++ = (argb >> 0) & 0xff;
+ const uint32_t argb = *src++;
+
+#if !defined(WORDS_BIGENDIAN)
+#if !defined(WEBP_REFERENCE_IMPLEMENTATION)
+ *(uint32_t*)dst = BSwap32(argb);
+#else // WEBP_REFERENCE_IMPLEMENTATION
+ dst[0] = (argb >> 24) & 0xff;
+ dst[1] = (argb >> 16) & 0xff;
+ dst[2] = (argb >> 8) & 0xff;
+ dst[3] = (argb >> 0) & 0xff;
#endif
+#else // WORDS_BIGENDIAN
+ dst[0] = (argb >> 0) & 0xff;
+ dst[1] = (argb >> 8) & 0xff;
+ dst[2] = (argb >> 16) & 0xff;
+ dst[3] = (argb >> 24) & 0xff;
+#endif
+ dst += sizeof(argb);
}
} else {
memcpy(dst, src, num_pixels * sizeof(*src));
@@ -1090,17 +514,17 @@ void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels,
WEBP_CSP_MODE out_colorspace, uint8_t* const rgba) {
switch (out_colorspace) {
case MODE_RGB:
- ConvertBGRAToRGB(in_data, num_pixels, rgba);
+ VP8LConvertBGRAToRGB(in_data, num_pixels, rgba);
break;
case MODE_RGBA:
- ConvertBGRAToRGBA(in_data, num_pixels, rgba);
+ VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba);
break;
case MODE_rgbA:
- ConvertBGRAToRGBA(in_data, num_pixels, rgba);
+ VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba);
WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0);
break;
case MODE_BGR:
- ConvertBGRAToBGR(in_data, num_pixels, rgba);
+ VP8LConvertBGRAToBGR(in_data, num_pixels, rgba);
break;
case MODE_BGRA:
CopyOrSwap(in_data, num_pixels, rgba, 1);
@@ -1117,14 +541,14 @@ void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels,
WebPApplyAlphaMultiply(rgba, 1, num_pixels, 1, 0);
break;
case MODE_RGBA_4444:
- ConvertBGRAToRGBA4444(in_data, num_pixels, rgba);
+ VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba);
break;
case MODE_rgbA_4444:
- ConvertBGRAToRGBA4444(in_data, num_pixels, rgba);
+ VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba);
WebPApplyAlphaMultiply4444(rgba, num_pixels, 1, 0);
break;
case MODE_RGB_565:
- ConvertBGRAToRGB565(in_data, num_pixels, rgba);
+ VP8LConvertBGRAToRGB565(in_data, num_pixels, rgba);
break;
default:
assert(0); // Code flow should not reach here.
@@ -1133,6 +557,79 @@ void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels,
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
+VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed;
+VP8LPredictorFunc VP8LPredictors[16];
+
+VP8LTransformColorFunc VP8LTransformColorInverse;
+
+VP8LConvertFunc VP8LConvertBGRAToRGB;
+VP8LConvertFunc VP8LConvertBGRAToRGBA;
+VP8LConvertFunc VP8LConvertBGRAToRGBA4444;
+VP8LConvertFunc VP8LConvertBGRAToRGB565;
+VP8LConvertFunc VP8LConvertBGRAToBGR;
+
+VP8LMapARGBFunc VP8LMapColor32b;
+VP8LMapAlphaFunc VP8LMapColor8b;
+
+extern void VP8LDspInitSSE2(void);
+extern void VP8LDspInitNEON(void);
+extern void VP8LDspInitMIPSdspR2(void);
+
+static volatile VP8CPUInfo lossless_last_cpuinfo_used =
+ (VP8CPUInfo)&lossless_last_cpuinfo_used;
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) {
+ if (lossless_last_cpuinfo_used == VP8GetCPUInfo) return;
+
+ VP8LPredictors[0] = Predictor0;
+ VP8LPredictors[1] = Predictor1;
+ VP8LPredictors[2] = Predictor2;
+ VP8LPredictors[3] = Predictor3;
+ VP8LPredictors[4] = Predictor4;
+ VP8LPredictors[5] = Predictor5;
+ VP8LPredictors[6] = Predictor6;
+ VP8LPredictors[7] = Predictor7;
+ VP8LPredictors[8] = Predictor8;
+ VP8LPredictors[9] = Predictor9;
+ VP8LPredictors[10] = Predictor10;
+ VP8LPredictors[11] = Predictor11;
+ VP8LPredictors[12] = Predictor12;
+ VP8LPredictors[13] = Predictor13;
+ VP8LPredictors[14] = Predictor0; // <- padding security sentinels
+ VP8LPredictors[15] = Predictor0;
+
+ VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C;
+
+ VP8LTransformColorInverse = VP8LTransformColorInverse_C;
+
+ VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C;
+ VP8LConvertBGRAToRGBA = VP8LConvertBGRAToRGBA_C;
+ VP8LConvertBGRAToRGBA4444 = VP8LConvertBGRAToRGBA4444_C;
+ VP8LConvertBGRAToRGB565 = VP8LConvertBGRAToRGB565_C;
+ VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C;
+
+ VP8LMapColor32b = MapARGB;
+ VP8LMapColor8b = MapAlpha;
+
+ // If defined, use CPUInfo() to overwrite some pointers with faster versions.
+ if (VP8GetCPUInfo != NULL) {
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ VP8LDspInitSSE2();
+ }
+#endif
+#if defined(WEBP_USE_NEON)
+ if (VP8GetCPUInfo(kNEON)) {
+ VP8LDspInitNEON();
+ }
+#endif
+#if defined(WEBP_USE_MIPS_DSP_R2)
+ if (VP8GetCPUInfo(kMIPSdspR2)) {
+ VP8LDspInitMIPSdspR2();
+ }
#endif
+ }
+ lossless_last_cpuinfo_used = VP8GetCPUInfo;
+}
+
+//------------------------------------------------------------------------------
diff --git a/drivers/webp/dsp/lossless.h b/drivers/webp/dsp/lossless.h
index 7c7d5555ed..149c6a01d3 100644
--- a/drivers/webp/dsp/lossless.h
+++ b/drivers/webp/dsp/lossless.h
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Image transforms and color space conversion methods for lossless decoder.
@@ -13,15 +15,42 @@
#ifndef WEBP_DSP_LOSSLESS_H_
#define WEBP_DSP_LOSSLESS_H_
-#include "../types.h"
-#include "../decode.h"
+#include "webp/types.h"
+#include "webp/decode.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#include "../enc/histogram.h"
+#include "../utils/utils.h"
+
+#ifdef __cplusplus
extern "C" {
#endif
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+#include "../enc/delta_palettization.h"
+#endif // WEBP_EXPERIMENTAL_FEATURES
+
+// Not a trivial literal symbol.
+#define VP8L_NON_TRIVIAL_SYM (0xffffffff)
+
//------------------------------------------------------------------------------
-// Image transforms.
+// Decoding
+
+typedef uint32_t (*VP8LPredictorFunc)(uint32_t left, const uint32_t* const top);
+extern VP8LPredictorFunc VP8LPredictors[16];
+
+typedef void (*VP8LProcessBlueAndRedFunc)(uint32_t* argb_data, int num_pixels);
+extern VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed;
+
+typedef struct {
+ // Note: the members are uint8_t, so that any negative values are
+ // automatically converted to "mod 256" values.
+ uint8_t green_to_red_;
+ uint8_t green_to_blue_;
+ uint8_t red_to_blue_;
+} VP8LMultipliers;
+typedef void (*VP8LTransformColorFunc)(const VP8LMultipliers* const m,
+ uint32_t* argb_data, int num_pixels);
+extern VP8LTransformColorFunc VP8LTransformColorInverse;
struct VP8LTransform; // Defined in dec/vp8li.h.
@@ -33,23 +62,110 @@ void VP8LInverseTransform(const struct VP8LTransform* const transform,
int row_start, int row_end,
const uint32_t* const in, uint32_t* const out);
-// Subtracts green from blue and red channels.
-void VP8LSubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixs);
-
-void VP8LResidualImage(int width, int height, int bits,
- uint32_t* const argb, uint32_t* const argb_scratch,
- uint32_t* const image);
-
-void VP8LColorSpaceTransform(int width, int height, int bits, int step,
- uint32_t* const argb, uint32_t* image);
-
-//------------------------------------------------------------------------------
// Color space conversion.
+typedef void (*VP8LConvertFunc)(const uint32_t* src, int num_pixels,
+ uint8_t* dst);
+extern VP8LConvertFunc VP8LConvertBGRAToRGB;
+extern VP8LConvertFunc VP8LConvertBGRAToRGBA;
+extern VP8LConvertFunc VP8LConvertBGRAToRGBA4444;
+extern VP8LConvertFunc VP8LConvertBGRAToRGB565;
+extern VP8LConvertFunc VP8LConvertBGRAToBGR;
// Converts from BGRA to other color spaces.
void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels,
WEBP_CSP_MODE out_colorspace, uint8_t* const rgba);
+// color mapping related functions.
+static WEBP_INLINE uint32_t VP8GetARGBIndex(uint32_t idx) {
+ return (idx >> 8) & 0xff;
+}
+
+static WEBP_INLINE uint8_t VP8GetAlphaIndex(uint8_t idx) {
+ return idx;
+}
+
+static WEBP_INLINE uint32_t VP8GetARGBValue(uint32_t val) {
+ return val;
+}
+
+static WEBP_INLINE uint8_t VP8GetAlphaValue(uint32_t val) {
+ return (val >> 8) & 0xff;
+}
+
+typedef void (*VP8LMapARGBFunc)(const uint32_t* src,
+ const uint32_t* const color_map,
+ uint32_t* dst, int y_start,
+ int y_end, int width);
+typedef void (*VP8LMapAlphaFunc)(const uint8_t* src,
+ const uint32_t* const color_map,
+ uint8_t* dst, int y_start,
+ int y_end, int width);
+
+extern VP8LMapARGBFunc VP8LMapColor32b;
+extern VP8LMapAlphaFunc VP8LMapColor8b;
+
+// Similar to the static method ColorIndexInverseTransform() that is part of
+// lossless.c, but used only for alpha decoding. It takes uint8_t (rather than
+// uint32_t) arguments for 'src' and 'dst'.
+void VP8LColorIndexInverseTransformAlpha(
+ const struct VP8LTransform* const transform, int y_start, int y_end,
+ const uint8_t* src, uint8_t* dst);
+
+// Expose some C-only fallback functions
+void VP8LTransformColorInverse_C(const VP8LMultipliers* const m,
+ uint32_t* data, int num_pixels);
+
+void VP8LConvertBGRAToRGB_C(const uint32_t* src, int num_pixels, uint8_t* dst);
+void VP8LConvertBGRAToRGBA_C(const uint32_t* src, int num_pixels, uint8_t* dst);
+void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src,
+ int num_pixels, uint8_t* dst);
+void VP8LConvertBGRAToRGB565_C(const uint32_t* src,
+ int num_pixels, uint8_t* dst);
+void VP8LConvertBGRAToBGR_C(const uint32_t* src, int num_pixels, uint8_t* dst);
+void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels);
+
+// Must be called before calling any of the above methods.
+void VP8LDspInit(void);
+
+//------------------------------------------------------------------------------
+// Encoding
+
+extern VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;
+extern VP8LTransformColorFunc VP8LTransformColor;
+typedef void (*VP8LCollectColorBlueTransformsFunc)(
+ const uint32_t* argb, int stride,
+ int tile_width, int tile_height,
+ int green_to_blue, int red_to_blue, int histo[]);
+extern VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms;
+
+typedef void (*VP8LCollectColorRedTransformsFunc)(
+ const uint32_t* argb, int stride,
+ int tile_width, int tile_height,
+ int green_to_red, int histo[]);
+extern VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms;
+
+// Expose some C-only fallback functions
+void VP8LTransformColor_C(const VP8LMultipliers* const m,
+ uint32_t* data, int num_pixels);
+void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels);
+void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride,
+ int tile_width, int tile_height,
+ int green_to_red, int histo[]);
+void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride,
+ int tile_width, int tile_height,
+ int green_to_blue, int red_to_blue,
+ int histo[]);
+
+//------------------------------------------------------------------------------
+// Image transforms.
+
+void VP8LResidualImage(int width, int height, int bits, int low_effort,
+ uint32_t* const argb, uint32_t* const argb_scratch,
+ uint32_t* const image);
+
+void VP8LColorSpaceTransform(int width, int height, int bits, int quality,
+ uint32_t* const argb, uint32_t* image);
+
//------------------------------------------------------------------------------
// Misc methods.
@@ -59,10 +175,136 @@ static WEBP_INLINE uint32_t VP8LSubSampleSize(uint32_t size,
return (size + (1 << sampling_bits) - 1) >> sampling_bits;
}
-// Faster logarithm for integers, with the property of log2(0) == 0.
-float VP8LFastLog2(int v);
+// -----------------------------------------------------------------------------
+// Faster logarithm for integers. Small values use a look-up table.
+#define LOG_LOOKUP_IDX_MAX 256
+extern const float kLog2Table[LOG_LOOKUP_IDX_MAX];
+extern const float kSLog2Table[LOG_LOOKUP_IDX_MAX];
+typedef float (*VP8LFastLog2SlowFunc)(uint32_t v);
+
+extern VP8LFastLog2SlowFunc VP8LFastLog2Slow;
+extern VP8LFastLog2SlowFunc VP8LFastSLog2Slow;
+
+static WEBP_INLINE float VP8LFastLog2(uint32_t v) {
+ return (v < LOG_LOOKUP_IDX_MAX) ? kLog2Table[v] : VP8LFastLog2Slow(v);
+}
// Fast calculation of v * log2(v) for integer input.
-static WEBP_INLINE float VP8LFastSLog2(int v) { return VP8LFastLog2(v) * v; }
+static WEBP_INLINE float VP8LFastSLog2(uint32_t v) {
+ return (v < LOG_LOOKUP_IDX_MAX) ? kSLog2Table[v] : VP8LFastSLog2Slow(v);
+}
+
+// -----------------------------------------------------------------------------
+// Huffman-cost related functions.
+
+typedef double (*VP8LCostFunc)(const uint32_t* population, int length);
+typedef double (*VP8LCostCombinedFunc)(const uint32_t* X, const uint32_t* Y,
+ int length);
+
+extern VP8LCostFunc VP8LExtraCost;
+extern VP8LCostCombinedFunc VP8LExtraCostCombined;
+
+typedef struct { // small struct to hold counters
+ int counts[2]; // index: 0=zero steak, 1=non-zero streak
+ int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3]
+} VP8LStreaks;
+
+typedef VP8LStreaks (*VP8LCostCountFunc)(const uint32_t* population,
+ int length);
+typedef VP8LStreaks (*VP8LCostCombinedCountFunc)(const uint32_t* X,
+ const uint32_t* Y, int length);
+
+extern VP8LCostCountFunc VP8LHuffmanCostCount;
+extern VP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount;
+
+// Get the symbol entropy for the distribution 'population'.
+// Set 'trivial_sym', if there's only one symbol present in the distribution.
+double VP8LPopulationCost(const uint32_t* const population, int length,
+ uint32_t* const trivial_sym);
+
+// Get the combined symbol entropy for the distributions 'X' and 'Y'.
+double VP8LGetCombinedEntropy(const uint32_t* const X,
+ const uint32_t* const Y, int length);
+
+double VP8LBitsEntropy(const uint32_t* const array, int n,
+ uint32_t* const trivial_symbol);
+
+// Estimate how many bits the combined entropy of literals and distance
+// approximately maps to.
+double VP8LHistogramEstimateBits(const VP8LHistogram* const p);
+
+// This function estimates the cost in bits excluding the bits needed to
+// represent the entropy code itself.
+double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p);
+
+typedef void (*VP8LHistogramAddFunc)(const VP8LHistogram* const a,
+ const VP8LHistogram* const b,
+ VP8LHistogram* const out);
+extern VP8LHistogramAddFunc VP8LHistogramAdd;
+
+// -----------------------------------------------------------------------------
+// PrefixEncode()
+
+static WEBP_INLINE int VP8LBitsLog2Ceiling(uint32_t n) {
+ const int log_floor = BitsLog2Floor(n);
+ if (n == (n & ~(n - 1))) // zero or a power of two.
+ return log_floor;
+ else
+ return log_floor + 1;
+}
+
+// Splitting of distance and length codes into prefixes and
+// extra bits. The prefixes are encoded with an entropy code
+// while the extra bits are stored just as normal bits.
+static WEBP_INLINE void VP8LPrefixEncodeBitsNoLUT(int distance, int* const code,
+ int* const extra_bits) {
+ const int highest_bit = BitsLog2Floor(--distance);
+ const int second_highest_bit = (distance >> (highest_bit - 1)) & 1;
+ *extra_bits = highest_bit - 1;
+ *code = 2 * highest_bit + second_highest_bit;
+}
+
+static WEBP_INLINE void VP8LPrefixEncodeNoLUT(int distance, int* const code,
+ int* const extra_bits,
+ int* const extra_bits_value) {
+ const int highest_bit = BitsLog2Floor(--distance);
+ const int second_highest_bit = (distance >> (highest_bit - 1)) & 1;
+ *extra_bits = highest_bit - 1;
+ *extra_bits_value = distance & ((1 << *extra_bits) - 1);
+ *code = 2 * highest_bit + second_highest_bit;
+}
+
+#define PREFIX_LOOKUP_IDX_MAX 512
+typedef struct {
+ int8_t code_;
+ int8_t extra_bits_;
+} VP8LPrefixCode;
+
+// These tables are derived using VP8LPrefixEncodeNoLUT.
+extern const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX];
+extern const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX];
+static WEBP_INLINE void VP8LPrefixEncodeBits(int distance, int* const code,
+ int* const extra_bits) {
+ if (distance < PREFIX_LOOKUP_IDX_MAX) {
+ const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance];
+ *code = prefix_code.code_;
+ *extra_bits = prefix_code.extra_bits_;
+ } else {
+ VP8LPrefixEncodeBitsNoLUT(distance, code, extra_bits);
+ }
+}
+
+static WEBP_INLINE void VP8LPrefixEncode(int distance, int* const code,
+ int* const extra_bits,
+ int* const extra_bits_value) {
+ if (distance < PREFIX_LOOKUP_IDX_MAX) {
+ const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance];
+ *code = prefix_code.code_;
+ *extra_bits = prefix_code.extra_bits_;
+ *extra_bits_value = kPrefixEncodeExtraBitsValue[distance];
+ } else {
+ VP8LPrefixEncodeNoLUT(distance, code, extra_bits, extra_bits_value);
+ }
+}
// In-place difference of each component with mod 256.
static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
@@ -73,9 +315,15 @@ static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
}
+void VP8LBundleColorMap(const uint8_t* const row, int width,
+ int xbits, uint32_t* const dst);
+
+// Must be called before calling any of the above methods.
+void VP8LEncDspInit(void);
+
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/dsp/lossless_enc.c b/drivers/webp/dsp/lossless_enc.c
new file mode 100644
index 0000000000..b3036f5384
--- /dev/null
+++ b/drivers/webp/dsp/lossless_enc.c
@@ -0,0 +1,1305 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Image transform methods for lossless encoder.
+//
+// Authors: Vikas Arora (vikaas.arora@gmail.com)
+// Jyrki Alakuijala (jyrki@google.com)
+// Urvang Joshi (urvang@google.com)
+
+#include "./dsp.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include "../dec/vp8li.h"
+#include "../utils/endian_inl.h"
+#include "./lossless.h"
+#include "./yuv.h"
+
+#define MAX_DIFF_COST (1e30f)
+
+// lookup table for small values of log2(int)
+const float kLog2Table[LOG_LOOKUP_IDX_MAX] = {
+ 0.0000000000000000f, 0.0000000000000000f,
+ 1.0000000000000000f, 1.5849625007211560f,
+ 2.0000000000000000f, 2.3219280948873621f,
+ 2.5849625007211560f, 2.8073549220576041f,
+ 3.0000000000000000f, 3.1699250014423121f,
+ 3.3219280948873621f, 3.4594316186372973f,
+ 3.5849625007211560f, 3.7004397181410921f,
+ 3.8073549220576041f, 3.9068905956085187f,
+ 4.0000000000000000f, 4.0874628412503390f,
+ 4.1699250014423121f, 4.2479275134435852f,
+ 4.3219280948873626f, 4.3923174227787606f,
+ 4.4594316186372973f, 4.5235619560570130f,
+ 4.5849625007211560f, 4.6438561897747243f,
+ 4.7004397181410917f, 4.7548875021634682f,
+ 4.8073549220576037f, 4.8579809951275718f,
+ 4.9068905956085187f, 4.9541963103868749f,
+ 5.0000000000000000f, 5.0443941193584533f,
+ 5.0874628412503390f, 5.1292830169449663f,
+ 5.1699250014423121f, 5.2094533656289501f,
+ 5.2479275134435852f, 5.2854022188622487f,
+ 5.3219280948873626f, 5.3575520046180837f,
+ 5.3923174227787606f, 5.4262647547020979f,
+ 5.4594316186372973f, 5.4918530963296747f,
+ 5.5235619560570130f, 5.5545888516776376f,
+ 5.5849625007211560f, 5.6147098441152083f,
+ 5.6438561897747243f, 5.6724253419714951f,
+ 5.7004397181410917f, 5.7279204545631987f,
+ 5.7548875021634682f, 5.7813597135246599f,
+ 5.8073549220576037f, 5.8328900141647412f,
+ 5.8579809951275718f, 5.8826430493618415f,
+ 5.9068905956085187f, 5.9307373375628866f,
+ 5.9541963103868749f, 5.9772799234999167f,
+ 6.0000000000000000f, 6.0223678130284543f,
+ 6.0443941193584533f, 6.0660891904577720f,
+ 6.0874628412503390f, 6.1085244567781691f,
+ 6.1292830169449663f, 6.1497471195046822f,
+ 6.1699250014423121f, 6.1898245588800175f,
+ 6.2094533656289501f, 6.2288186904958804f,
+ 6.2479275134435852f, 6.2667865406949010f,
+ 6.2854022188622487f, 6.3037807481771030f,
+ 6.3219280948873626f, 6.3398500028846243f,
+ 6.3575520046180837f, 6.3750394313469245f,
+ 6.3923174227787606f, 6.4093909361377017f,
+ 6.4262647547020979f, 6.4429434958487279f,
+ 6.4594316186372973f, 6.4757334309663976f,
+ 6.4918530963296747f, 6.5077946401986963f,
+ 6.5235619560570130f, 6.5391588111080309f,
+ 6.5545888516776376f, 6.5698556083309478f,
+ 6.5849625007211560f, 6.5999128421871278f,
+ 6.6147098441152083f, 6.6293566200796094f,
+ 6.6438561897747243f, 6.6582114827517946f,
+ 6.6724253419714951f, 6.6865005271832185f,
+ 6.7004397181410917f, 6.7142455176661224f,
+ 6.7279204545631987f, 6.7414669864011464f,
+ 6.7548875021634682f, 6.7681843247769259f,
+ 6.7813597135246599f, 6.7944158663501061f,
+ 6.8073549220576037f, 6.8201789624151878f,
+ 6.8328900141647412f, 6.8454900509443747f,
+ 6.8579809951275718f, 6.8703647195834047f,
+ 6.8826430493618415f, 6.8948177633079437f,
+ 6.9068905956085187f, 6.9188632372745946f,
+ 6.9307373375628866f, 6.9425145053392398f,
+ 6.9541963103868749f, 6.9657842846620869f,
+ 6.9772799234999167f, 6.9886846867721654f,
+ 7.0000000000000000f, 7.0112272554232539f,
+ 7.0223678130284543f, 7.0334230015374501f,
+ 7.0443941193584533f, 7.0552824355011898f,
+ 7.0660891904577720f, 7.0768155970508308f,
+ 7.0874628412503390f, 7.0980320829605263f,
+ 7.1085244567781691f, 7.1189410727235076f,
+ 7.1292830169449663f, 7.1395513523987936f,
+ 7.1497471195046822f, 7.1598713367783890f,
+ 7.1699250014423121f, 7.1799090900149344f,
+ 7.1898245588800175f, 7.1996723448363644f,
+ 7.2094533656289501f, 7.2191685204621611f,
+ 7.2288186904958804f, 7.2384047393250785f,
+ 7.2479275134435852f, 7.2573878426926521f,
+ 7.2667865406949010f, 7.2761244052742375f,
+ 7.2854022188622487f, 7.2946207488916270f,
+ 7.3037807481771030f, 7.3128829552843557f,
+ 7.3219280948873626f, 7.3309168781146167f,
+ 7.3398500028846243f, 7.3487281542310771f,
+ 7.3575520046180837f, 7.3663222142458160f,
+ 7.3750394313469245f, 7.3837042924740519f,
+ 7.3923174227787606f, 7.4008794362821843f,
+ 7.4093909361377017f, 7.4178525148858982f,
+ 7.4262647547020979f, 7.4346282276367245f,
+ 7.4429434958487279f, 7.4512111118323289f,
+ 7.4594316186372973f, 7.4676055500829976f,
+ 7.4757334309663976f, 7.4838157772642563f,
+ 7.4918530963296747f, 7.4998458870832056f,
+ 7.5077946401986963f, 7.5156998382840427f,
+ 7.5235619560570130f, 7.5313814605163118f,
+ 7.5391588111080309f, 7.5468944598876364f,
+ 7.5545888516776376f, 7.5622424242210728f,
+ 7.5698556083309478f, 7.5774288280357486f,
+ 7.5849625007211560f, 7.5924570372680806f,
+ 7.5999128421871278f, 7.6073303137496104f,
+ 7.6147098441152083f, 7.6220518194563764f,
+ 7.6293566200796094f, 7.6366246205436487f,
+ 7.6438561897747243f, 7.6510516911789281f,
+ 7.6582114827517946f, 7.6653359171851764f,
+ 7.6724253419714951f, 7.6794800995054464f,
+ 7.6865005271832185f, 7.6934869574993252f,
+ 7.7004397181410917f, 7.7073591320808825f,
+ 7.7142455176661224f, 7.7210991887071855f,
+ 7.7279204545631987f, 7.7347096202258383f,
+ 7.7414669864011464f, 7.7481928495894605f,
+ 7.7548875021634682f, 7.7615512324444795f,
+ 7.7681843247769259f, 7.7747870596011736f,
+ 7.7813597135246599f, 7.7879025593914317f,
+ 7.7944158663501061f, 7.8008998999203047f,
+ 7.8073549220576037f, 7.8137811912170374f,
+ 7.8201789624151878f, 7.8265484872909150f,
+ 7.8328900141647412f, 7.8392037880969436f,
+ 7.8454900509443747f, 7.8517490414160571f,
+ 7.8579809951275718f, 7.8641861446542797f,
+ 7.8703647195834047f, 7.8765169465649993f,
+ 7.8826430493618415f, 7.8887432488982591f,
+ 7.8948177633079437f, 7.9008668079807486f,
+ 7.9068905956085187f, 7.9128893362299619f,
+ 7.9188632372745946f, 7.9248125036057812f,
+ 7.9307373375628866f, 7.9366379390025709f,
+ 7.9425145053392398f, 7.9483672315846778f,
+ 7.9541963103868749f, 7.9600019320680805f,
+ 7.9657842846620869f, 7.9715435539507719f,
+ 7.9772799234999167f, 7.9829935746943103f,
+ 7.9886846867721654f, 7.9943534368588577f
+};
+
+const float kSLog2Table[LOG_LOOKUP_IDX_MAX] = {
+ 0.00000000f, 0.00000000f, 2.00000000f, 4.75488750f,
+ 8.00000000f, 11.60964047f, 15.50977500f, 19.65148445f,
+ 24.00000000f, 28.52932501f, 33.21928095f, 38.05374781f,
+ 43.01955001f, 48.10571634f, 53.30296891f, 58.60335893f,
+ 64.00000000f, 69.48686830f, 75.05865003f, 80.71062276f,
+ 86.43856190f, 92.23866588f, 98.10749561f, 104.04192499f,
+ 110.03910002f, 116.09640474f, 122.21143267f, 128.38196256f,
+ 134.60593782f, 140.88144886f, 147.20671787f, 153.58008562f,
+ 160.00000000f, 166.46500594f, 172.97373660f, 179.52490559f,
+ 186.11730005f, 192.74977453f, 199.42124551f, 206.13068654f,
+ 212.87712380f, 219.65963219f, 226.47733176f, 233.32938445f,
+ 240.21499122f, 247.13338933f, 254.08384998f, 261.06567603f,
+ 268.07820003f, 275.12078236f, 282.19280949f, 289.29369244f,
+ 296.42286534f, 303.57978409f, 310.76392512f, 317.97478424f,
+ 325.21187564f, 332.47473081f, 339.76289772f, 347.07593991f,
+ 354.41343574f, 361.77497759f, 369.16017124f, 376.56863518f,
+ 384.00000000f, 391.45390785f, 398.93001188f, 406.42797576f,
+ 413.94747321f, 421.48818752f, 429.04981119f, 436.63204548f,
+ 444.23460010f, 451.85719280f, 459.49954906f, 467.16140179f,
+ 474.84249102f, 482.54256363f, 490.26137307f, 497.99867911f,
+ 505.75424759f, 513.52785023f, 521.31926438f, 529.12827280f,
+ 536.95466351f, 544.79822957f, 552.65876890f, 560.53608414f,
+ 568.42998244f, 576.34027536f, 584.26677867f, 592.20931226f,
+ 600.16769996f, 608.14176943f, 616.13135206f, 624.13628279f,
+ 632.15640007f, 640.19154569f, 648.24156472f, 656.30630539f,
+ 664.38561898f, 672.47935976f, 680.58738488f, 688.70955430f,
+ 696.84573069f, 704.99577935f, 713.15956818f, 721.33696754f,
+ 729.52785023f, 737.73209140f, 745.94956849f, 754.18016116f,
+ 762.42375127f, 770.68022275f, 778.94946161f, 787.23135586f,
+ 795.52579543f, 803.83267219f, 812.15187982f, 820.48331383f,
+ 828.82687147f, 837.18245171f, 845.54995518f, 853.92928416f,
+ 862.32034249f, 870.72303558f, 879.13727036f, 887.56295522f,
+ 896.00000000f, 904.44831595f, 912.90781569f, 921.37841320f,
+ 929.86002376f, 938.35256392f, 946.85595152f, 955.37010560f,
+ 963.89494641f, 972.43039537f, 980.97637504f, 989.53280911f,
+ 998.09962237f, 1006.67674069f, 1015.26409097f, 1023.86160116f,
+ 1032.46920021f, 1041.08681805f, 1049.71438560f, 1058.35183469f,
+ 1066.99909811f, 1075.65610955f, 1084.32280357f, 1092.99911564f,
+ 1101.68498204f, 1110.38033993f, 1119.08512727f, 1127.79928282f,
+ 1136.52274614f, 1145.25545758f, 1153.99735821f, 1162.74838989f,
+ 1171.50849518f, 1180.27761738f, 1189.05570047f, 1197.84268914f,
+ 1206.63852876f, 1215.44316535f, 1224.25654560f, 1233.07861684f,
+ 1241.90932703f, 1250.74862473f, 1259.59645914f, 1268.45278005f,
+ 1277.31753781f, 1286.19068338f, 1295.07216828f, 1303.96194457f,
+ 1312.85996488f, 1321.76618236f, 1330.68055071f, 1339.60302413f,
+ 1348.53355734f, 1357.47210556f, 1366.41862452f, 1375.37307041f,
+ 1384.33539991f, 1393.30557020f, 1402.28353887f, 1411.26926400f,
+ 1420.26270412f, 1429.26381818f, 1438.27256558f, 1447.28890615f,
+ 1456.31280014f, 1465.34420819f, 1474.38309138f, 1483.42941118f,
+ 1492.48312945f, 1501.54420843f, 1510.61261078f, 1519.68829949f,
+ 1528.77123795f, 1537.86138993f, 1546.95871952f, 1556.06319119f,
+ 1565.17476976f, 1574.29342040f, 1583.41910860f, 1592.55180020f,
+ 1601.69146137f, 1610.83805860f, 1619.99155871f, 1629.15192882f,
+ 1638.31913637f, 1647.49314911f, 1656.67393509f, 1665.86146266f,
+ 1675.05570047f, 1684.25661744f, 1693.46418280f, 1702.67836605f,
+ 1711.89913698f, 1721.12646563f, 1730.36032233f, 1739.60067768f,
+ 1748.84750254f, 1758.10076802f, 1767.36044551f, 1776.62650662f,
+ 1785.89892323f, 1795.17766747f, 1804.46271172f, 1813.75402857f,
+ 1823.05159087f, 1832.35537170f, 1841.66534438f, 1850.98148244f,
+ 1860.30375965f, 1869.63214999f, 1878.96662767f, 1888.30716711f,
+ 1897.65374295f, 1907.00633003f, 1916.36490342f, 1925.72943838f,
+ 1935.09991037f, 1944.47629506f, 1953.85856831f, 1963.24670620f,
+ 1972.64068498f, 1982.04048108f, 1991.44607117f, 2000.85743204f,
+ 2010.27454072f, 2019.69737440f, 2029.12591044f, 2038.56012640f
+};
+
+const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX] = {
+ { 0, 0}, { 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 1}, { 4, 1}, { 5, 1},
+ { 5, 1}, { 6, 2}, { 6, 2}, { 6, 2}, { 6, 2}, { 7, 2}, { 7, 2}, { 7, 2},
+ { 7, 2}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3},
+ { 8, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3},
+ { 9, 3}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4},
+ {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4},
+ {10, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
+ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
+ {11, 4}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
+ {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
+ {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
+ {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
+ {12, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},
+ {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},
+ {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},
+ {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},
+ {13, 5}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
+ {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
+ {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
+ {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
+ {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
+ {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
+ {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
+ {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
+ {14, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
+ {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
+ {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
+ {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
+ {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
+ {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
+ {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
+ {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
+ {15, 6}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
+ {16, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
+};
+
+const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX] = {
+ 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3,
+ 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126
+};
+
+// The threshold till approximate version of log_2 can be used.
+// Practically, we can get rid of the call to log() as the two values match to
+// very high degree (the ratio of these two is 0.99999x).
+// Keeping a high threshold for now.
+#define APPROX_LOG_WITH_CORRECTION_MAX 65536
+#define APPROX_LOG_MAX 4096
+#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086
+static float FastSLog2Slow(uint32_t v) {
+ assert(v >= LOG_LOOKUP_IDX_MAX);
+ if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
+ int log_cnt = 0;
+ uint32_t y = 1;
+ int correction = 0;
+ const float v_f = (float)v;
+ const uint32_t orig_v = v;
+ do {
+ ++log_cnt;
+ v = v >> 1;
+ y = y << 1;
+ } while (v >= LOG_LOOKUP_IDX_MAX);
+ // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256
+ // Xf = floor(Xf) * (1 + (v % y) / v)
+ // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v)
+ // The correction factor: log(1 + d) ~ d; for very small d values, so
+ // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v
+ // LOG_2_RECIPROCAL ~ 23/16
+ correction = (23 * (orig_v & (y - 1))) >> 4;
+ return v_f * (kLog2Table[v] + log_cnt) + correction;
+ } else {
+ return (float)(LOG_2_RECIPROCAL * v * log((double)v));
+ }
+}
+
+static float FastLog2Slow(uint32_t v) {
+ assert(v >= LOG_LOOKUP_IDX_MAX);
+ if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
+ int log_cnt = 0;
+ uint32_t y = 1;
+ const uint32_t orig_v = v;
+ double log_2;
+ do {
+ ++log_cnt;
+ v = v >> 1;
+ y = y << 1;
+ } while (v >= LOG_LOOKUP_IDX_MAX);
+ log_2 = kLog2Table[v] + log_cnt;
+ if (orig_v >= APPROX_LOG_MAX) {
+ // Since the division is still expensive, add this correction factor only
+ // for large values of 'v'.
+ const int correction = (23 * (orig_v & (y - 1))) >> 4;
+ log_2 += (double)correction / orig_v;
+ }
+ return (float)log_2;
+ } else {
+ return (float)(LOG_2_RECIPROCAL * log((double)v));
+ }
+}
+
+// Mostly used to reduce code size + readability
+static WEBP_INLINE int GetMin(int a, int b) { return (a > b) ? b : a; }
+
+//------------------------------------------------------------------------------
+// Methods to calculate Entropy (Shannon).
+
+static float PredictionCostSpatial(const int counts[256], int weight_0,
+ double exp_val) {
+ const int significant_symbols = 256 >> 4;
+ const double exp_decay_factor = 0.6;
+ double bits = weight_0 * counts[0];
+ int i;
+ for (i = 1; i < significant_symbols; ++i) {
+ bits += exp_val * (counts[i] + counts[256 - i]);
+ exp_val *= exp_decay_factor;
+ }
+ return (float)(-0.1 * bits);
+}
+
+// Compute the combined Shanon's entropy for distribution {X} and {X+Y}
+static float CombinedShannonEntropy(const int X[256], const int Y[256]) {
+ int i;
+ double retval = 0.;
+ int sumX = 0, sumXY = 0;
+ for (i = 0; i < 256; ++i) {
+ const int x = X[i];
+ const int xy = x + Y[i];
+ if (x != 0) {
+ sumX += x;
+ retval -= VP8LFastSLog2(x);
+ sumXY += xy;
+ retval -= VP8LFastSLog2(xy);
+ } else if (xy != 0) {
+ sumXY += xy;
+ retval -= VP8LFastSLog2(xy);
+ }
+ }
+ retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY);
+ return (float)retval;
+}
+
+static float PredictionCostSpatialHistogram(const int accumulated[4][256],
+ const int tile[4][256]) {
+ int i;
+ double retval = 0;
+ for (i = 0; i < 4; ++i) {
+ const double kExpValue = 0.94;
+ retval += PredictionCostSpatial(tile[i], 1, kExpValue);
+ retval += CombinedShannonEntropy(tile[i], accumulated[i]);
+ }
+ return (float)retval;
+}
+
+static WEBP_INLINE double BitsEntropyRefine(int nonzeros, int sum, int max_val,
+ double retval) {
+ double mix;
+ if (nonzeros < 5) {
+ if (nonzeros <= 1) {
+ return 0;
+ }
+ // Two symbols, they will be 0 and 1 in a Huffman code.
+ // Let's mix in a bit of entropy to favor good clustering when
+ // distributions of these are combined.
+ if (nonzeros == 2) {
+ return 0.99 * sum + 0.01 * retval;
+ }
+ // No matter what the entropy says, we cannot be better than min_limit
+ // with Huffman coding. I am mixing a bit of entropy into the
+ // min_limit since it produces much better (~0.5 %) compression results
+ // perhaps because of better entropy clustering.
+ if (nonzeros == 3) {
+ mix = 0.95;
+ } else {
+ mix = 0.7; // nonzeros == 4.
+ }
+ } else {
+ mix = 0.627;
+ }
+
+ {
+ double min_limit = 2 * sum - max_val;
+ min_limit = mix * min_limit + (1.0 - mix) * retval;
+ return (retval < min_limit) ? min_limit : retval;
+ }
+}
+
+// Returns the entropy for the symbols in the input array.
+// Also sets trivial_symbol to the code value, if the array has only one code
+// value. Otherwise, set it to VP8L_NON_TRIVIAL_SYM.
+double VP8LBitsEntropy(const uint32_t* const array, int n,
+ uint32_t* const trivial_symbol) {
+ double retval = 0.;
+ uint32_t sum = 0;
+ uint32_t nonzero_code = VP8L_NON_TRIVIAL_SYM;
+ int nonzeros = 0;
+ uint32_t max_val = 0;
+ int i;
+ for (i = 0; i < n; ++i) {
+ if (array[i] != 0) {
+ sum += array[i];
+ nonzero_code = i;
+ ++nonzeros;
+ retval -= VP8LFastSLog2(array[i]);
+ if (max_val < array[i]) {
+ max_val = array[i];
+ }
+ }
+ }
+ retval += VP8LFastSLog2(sum);
+ if (trivial_symbol != NULL) {
+ *trivial_symbol = (nonzeros == 1) ? nonzero_code : VP8L_NON_TRIVIAL_SYM;
+ }
+ return BitsEntropyRefine(nonzeros, sum, max_val, retval);
+}
+
+static double InitialHuffmanCost(void) {
+ // Small bias because Huffman code length is typically not stored in
+ // full length.
+ static const int kHuffmanCodeOfHuffmanCodeSize = CODE_LENGTH_CODES * 3;
+ static const double kSmallBias = 9.1;
+ return kHuffmanCodeOfHuffmanCodeSize - kSmallBias;
+}
+
+// Finalize the Huffman cost based on streak numbers and length type (<3 or >=3)
+static double FinalHuffmanCost(const VP8LStreaks* const stats) {
+ double retval = InitialHuffmanCost();
+ retval += stats->counts[0] * 1.5625 + 0.234375 * stats->streaks[0][1];
+ retval += stats->counts[1] * 2.578125 + 0.703125 * stats->streaks[1][1];
+ retval += 1.796875 * stats->streaks[0][0];
+ retval += 3.28125 * stats->streaks[1][0];
+ return retval;
+}
+
+// Trampolines
+static double HuffmanCost(const uint32_t* const population, int length) {
+ const VP8LStreaks stats = VP8LHuffmanCostCount(population, length);
+ return FinalHuffmanCost(&stats);
+}
+
+// Aggregated costs
+double VP8LPopulationCost(const uint32_t* const population, int length,
+ uint32_t* const trivial_sym) {
+ return
+ VP8LBitsEntropy(population, length, trivial_sym) +
+ HuffmanCost(population, length);
+}
+
+double VP8LGetCombinedEntropy(const uint32_t* const X,
+ const uint32_t* const Y, int length) {
+ double bits_entropy_combined;
+ double huffman_cost_combined;
+ int i;
+
+ // Bit entropy variables.
+ double retval = 0.;
+ int sum = 0;
+ int nonzeros = 0;
+ uint32_t max_val = 0;
+ int i_prev;
+ uint32_t xy;
+
+ // Huffman cost variables.
+ int streak = 0;
+ uint32_t xy_prev;
+ VP8LStreaks stats;
+ memset(&stats, 0, sizeof(stats));
+
+ // Treat the first value for the huffman cost: this is keeping the original
+ // behavior, even though there is no first streak.
+ // TODO(vrabaud): study proper behavior
+ xy = X[0] + Y[0];
+ ++stats.streaks[xy != 0][0];
+ xy_prev = xy;
+ i_prev = 0;
+
+ for (i = 1; i < length; ++i) {
+ xy = X[i] + Y[i];
+
+ // Process data by streaks for both bit entropy and huffman cost.
+ if (xy != xy_prev) {
+ streak = i - i_prev;
+
+ // Gather info for the bit entropy.
+ if (xy_prev != 0) {
+ sum += xy_prev * streak;
+ nonzeros += streak;
+ retval -= VP8LFastSLog2(xy_prev) * streak;
+ if (max_val < xy_prev) {
+ max_val = xy_prev;
+ }
+ }
+
+ // Gather info for the huffman cost.
+ stats.counts[xy != 0] += (streak > 3);
+ stats.streaks[xy != 0][(streak > 3)] += streak;
+
+ xy_prev = xy;
+ i_prev = i;
+ }
+ }
+
+ // Finish off the last streak for bit entropy.
+ if (xy != 0) {
+ streak = i - i_prev;
+ sum += xy * streak;
+ nonzeros += streak;
+ retval -= VP8LFastSLog2(xy) * streak;
+ if (max_val < xy) {
+ max_val = xy;
+ }
+ }
+ // Huffman cost is not updated with the last streak to keep original behavior.
+ // TODO(vrabaud): study proper behavior
+
+ retval += VP8LFastSLog2(sum);
+ bits_entropy_combined = BitsEntropyRefine(nonzeros, sum, max_val, retval);
+
+ huffman_cost_combined = FinalHuffmanCost(&stats);
+
+ return bits_entropy_combined + huffman_cost_combined;
+}
+
+// Estimates the Entropy + Huffman + other block overhead size cost.
+double VP8LHistogramEstimateBits(const VP8LHistogram* const p) {
+ return
+ VP8LPopulationCost(
+ p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_), NULL)
+ + VP8LPopulationCost(p->red_, NUM_LITERAL_CODES, NULL)
+ + VP8LPopulationCost(p->blue_, NUM_LITERAL_CODES, NULL)
+ + VP8LPopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL)
+ + VP8LPopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL)
+ + VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES)
+ + VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES);
+}
+
+double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p) {
+ return
+ VP8LBitsEntropy(p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_),
+ NULL)
+ + VP8LBitsEntropy(p->red_, NUM_LITERAL_CODES, NULL)
+ + VP8LBitsEntropy(p->blue_, NUM_LITERAL_CODES, NULL)
+ + VP8LBitsEntropy(p->alpha_, NUM_LITERAL_CODES, NULL)
+ + VP8LBitsEntropy(p->distance_, NUM_DISTANCE_CODES, NULL)
+ + VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES)
+ + VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES);
+}
+
+static WEBP_INLINE void UpdateHisto(int histo_argb[4][256], uint32_t argb) {
+ ++histo_argb[0][argb >> 24];
+ ++histo_argb[1][(argb >> 16) & 0xff];
+ ++histo_argb[2][(argb >> 8) & 0xff];
+ ++histo_argb[3][argb & 0xff];
+}
+
+//------------------------------------------------------------------------------
+
+// Returns best predictor and updates the accumulated histogram.
+static int GetBestPredictorForTile(int width, int height,
+ int tile_x, int tile_y, int bits,
+ int accumulated[4][256],
+ const uint32_t* const argb_scratch) {
+ const int kNumPredModes = 14;
+ const int col_start = tile_x << bits;
+ const int row_start = tile_y << bits;
+ const int tile_size = 1 << bits;
+ const int max_y = GetMin(tile_size, height - row_start);
+ const int max_x = GetMin(tile_size, width - col_start);
+ float best_diff = MAX_DIFF_COST;
+ int best_mode = 0;
+ int mode;
+ int histo_stack_1[4][256];
+ int histo_stack_2[4][256];
+ // Need pointers to be able to swap arrays.
+ int (*histo_argb)[256] = histo_stack_1;
+ int (*best_histo)[256] = histo_stack_2;
+
+ int i, j;
+ for (mode = 0; mode < kNumPredModes; ++mode) {
+ const uint32_t* current_row = argb_scratch;
+ const VP8LPredictorFunc pred_func = VP8LPredictors[mode];
+ float cur_diff;
+ int y;
+ memset(histo_argb, 0, sizeof(histo_stack_1));
+ for (y = 0; y < max_y; ++y) {
+ int x;
+ const int row = row_start + y;
+ const uint32_t* const upper_row = current_row;
+ current_row = upper_row + width;
+ for (x = 0; x < max_x; ++x) {
+ const int col = col_start + x;
+ uint32_t predict;
+ if (row == 0) {
+ predict = (col == 0) ? ARGB_BLACK : current_row[col - 1]; // Left.
+ } else if (col == 0) {
+ predict = upper_row[col]; // Top.
+ } else {
+ predict = pred_func(current_row[col - 1], upper_row + col);
+ }
+ UpdateHisto(histo_argb, VP8LSubPixels(current_row[col], predict));
+ }
+ }
+ cur_diff = PredictionCostSpatialHistogram(
+ (const int (*)[256])accumulated, (const int (*)[256])histo_argb);
+ if (cur_diff < best_diff) {
+ int (*tmp)[256] = histo_argb;
+ histo_argb = best_histo;
+ best_histo = tmp;
+ best_diff = cur_diff;
+ best_mode = mode;
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 256; j++) {
+ accumulated[i][j] += best_histo[i][j];
+ }
+ }
+
+ return best_mode;
+}
+
+static void CopyImageWithPrediction(int width, int height,
+ int bits, uint32_t* const modes,
+ uint32_t* const argb_scratch,
+ uint32_t* const argb) {
+ const int tiles_per_row = VP8LSubSampleSize(width, bits);
+ const int mask = (1 << bits) - 1;
+ // The row size is one pixel longer to allow the top right pixel to point to
+ // the leftmost pixel of the next row when at the right edge.
+ uint32_t* current_row = argb_scratch;
+ uint32_t* upper_row = argb_scratch + width + 1;
+ int y;
+ VP8LPredictorFunc pred_func = 0;
+
+ for (y = 0; y < height; ++y) {
+ int x;
+ uint32_t* tmp = upper_row;
+ upper_row = current_row;
+ current_row = tmp;
+ memcpy(current_row, argb + y * width, sizeof(*current_row) * width);
+ current_row[width] = (y + 1 < height) ? argb[(y + 1) * width] : ARGB_BLACK;
+ for (x = 0; x < width; ++x) {
+ uint32_t predict;
+ if ((x & mask) == 0) {
+ const int mode =
+ (modes[(y >> bits) * tiles_per_row + (x >> bits)] >> 8) & 0xff;
+ pred_func = VP8LPredictors[mode];
+ }
+ if (y == 0) {
+ predict = (x == 0) ? ARGB_BLACK : current_row[x - 1]; // Left.
+ } else if (x == 0) {
+ predict = upper_row[x]; // Top.
+ } else {
+ predict = pred_func(current_row[x - 1], upper_row + x);
+ }
+ argb[y * width + x] = VP8LSubPixels(current_row[x], predict);
+ }
+ }
+}
+
+void VP8LResidualImage(int width, int height, int bits, int low_effort,
+ uint32_t* const argb, uint32_t* const argb_scratch,
+ uint32_t* const image) {
+ const int max_tile_size = 1 << bits;
+ const int tiles_per_row = VP8LSubSampleSize(width, bits);
+ const int tiles_per_col = VP8LSubSampleSize(height, bits);
+ const int kPredLowEffort = 11;
+ uint32_t* const upper_row = argb_scratch;
+ uint32_t* const current_tile_rows = argb_scratch + width;
+ int tile_y;
+ int histo[4][256];
+ if (!low_effort) memset(histo, 0, sizeof(histo));
+ for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) {
+ const int tile_y_offset = tile_y * max_tile_size;
+ const int this_tile_height =
+ (tile_y < tiles_per_col - 1) ? max_tile_size : height - tile_y_offset;
+ int tile_x;
+ if (tile_y > 0) {
+ memcpy(upper_row, current_tile_rows + (max_tile_size - 1) * width,
+ width * sizeof(*upper_row));
+ }
+ memcpy(current_tile_rows, &argb[tile_y_offset * width],
+ this_tile_height * width * sizeof(*current_tile_rows));
+ for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) {
+ const int pred =
+ low_effort ? kPredLowEffort :
+ GetBestPredictorForTile(width, height,
+ tile_x, tile_y, bits,
+ (int (*)[256])histo,
+ argb_scratch);
+ image[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8);
+ }
+ }
+
+ CopyImageWithPrediction(width, height, bits, image, argb_scratch, argb);
+}
+
+void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels) {
+ int i;
+ for (i = 0; i < num_pixels; ++i) {
+ const uint32_t argb = argb_data[i];
+ const uint32_t green = (argb >> 8) & 0xff;
+ const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff;
+ const uint32_t new_b = ((argb & 0xff) - green) & 0xff;
+ argb_data[i] = (argb & 0xff00ff00) | (new_r << 16) | new_b;
+ }
+}
+
+static WEBP_INLINE void MultipliersClear(VP8LMultipliers* const m) {
+ m->green_to_red_ = 0;
+ m->green_to_blue_ = 0;
+ m->red_to_blue_ = 0;
+}
+
+static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred,
+ int8_t color) {
+ return (uint32_t)((int)(color_pred) * color) >> 5;
+}
+
+static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code,
+ VP8LMultipliers* const m) {
+ m->green_to_red_ = (color_code >> 0) & 0xff;
+ m->green_to_blue_ = (color_code >> 8) & 0xff;
+ m->red_to_blue_ = (color_code >> 16) & 0xff;
+}
+
+static WEBP_INLINE uint32_t MultipliersToColorCode(
+ const VP8LMultipliers* const m) {
+ return 0xff000000u |
+ ((uint32_t)(m->red_to_blue_) << 16) |
+ ((uint32_t)(m->green_to_blue_) << 8) |
+ m->green_to_red_;
+}
+
+void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data,
+ int num_pixels) {
+ int i;
+ for (i = 0; i < num_pixels; ++i) {
+ const uint32_t argb = data[i];
+ const uint32_t green = argb >> 8;
+ const uint32_t red = argb >> 16;
+ uint32_t new_red = red;
+ uint32_t new_blue = argb;
+ new_red -= ColorTransformDelta(m->green_to_red_, green);
+ new_red &= 0xff;
+ new_blue -= ColorTransformDelta(m->green_to_blue_, green);
+ new_blue -= ColorTransformDelta(m->red_to_blue_, red);
+ new_blue &= 0xff;
+ data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
+ }
+}
+
+static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red,
+ uint32_t argb) {
+ const uint32_t green = argb >> 8;
+ uint32_t new_red = argb >> 16;
+ new_red -= ColorTransformDelta(green_to_red, green);
+ return (new_red & 0xff);
+}
+
+static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue,
+ uint8_t red_to_blue,
+ uint32_t argb) {
+ const uint32_t green = argb >> 8;
+ const uint32_t red = argb >> 16;
+ uint8_t new_blue = argb;
+ new_blue -= ColorTransformDelta(green_to_blue, green);
+ new_blue -= ColorTransformDelta(red_to_blue, red);
+ return (new_blue & 0xff);
+}
+
+static float PredictionCostCrossColor(const int accumulated[256],
+ const int counts[256]) {
+ // Favor low entropy, locally and globally.
+ // Favor small absolute values for PredictionCostSpatial
+ static const double kExpValue = 2.4;
+ return CombinedShannonEntropy(counts, accumulated) +
+ PredictionCostSpatial(counts, 3, kExpValue);
+}
+
+void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride,
+ int tile_width, int tile_height,
+ int green_to_red, int histo[]) {
+ while (tile_height-- > 0) {
+ int x;
+ for (x = 0; x < tile_width; ++x) {
+ ++histo[TransformColorRed(green_to_red, argb[x])];
+ }
+ argb += stride;
+ }
+}
+
+static float GetPredictionCostCrossColorRed(
+ const uint32_t* argb, int stride, int tile_width, int tile_height,
+ VP8LMultipliers prev_x, VP8LMultipliers prev_y, int green_to_red,
+ const int accumulated_red_histo[256]) {
+ int histo[256] = { 0 };
+ float cur_diff;
+
+ VP8LCollectColorRedTransforms(argb, stride, tile_width, tile_height,
+ green_to_red, histo);
+
+ cur_diff = PredictionCostCrossColor(accumulated_red_histo, histo);
+ if ((uint8_t)green_to_red == prev_x.green_to_red_) {
+ cur_diff -= 3; // favor keeping the areas locally similar
+ }
+ if ((uint8_t)green_to_red == prev_y.green_to_red_) {
+ cur_diff -= 3; // favor keeping the areas locally similar
+ }
+ if (green_to_red == 0) {
+ cur_diff -= 3;
+ }
+ return cur_diff;
+}
+
+static void GetBestGreenToRed(
+ const uint32_t* argb, int stride, int tile_width, int tile_height,
+ VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality,
+ const int accumulated_red_histo[256], VP8LMultipliers* const best_tx) {
+ const int kMaxIters = 4 + ((7 * quality) >> 8); // in range [4..6]
+ int green_to_red_best = 0;
+ int iter, offset;
+ float best_diff = GetPredictionCostCrossColorRed(
+ argb, stride, tile_width, tile_height, prev_x, prev_y,
+ green_to_red_best, accumulated_red_histo);
+ for (iter = 0; iter < kMaxIters; ++iter) {
+ // ColorTransformDelta is a 3.5 bit fixed point, so 32 is equal to
+ // one in color computation. Having initial delta here as 1 is sufficient
+ // to explore the range of (-2, 2).
+ const int delta = 32 >> iter;
+ // Try a negative and a positive delta from the best known value.
+ for (offset = -delta; offset <= delta; offset += 2 * delta) {
+ const int green_to_red_cur = offset + green_to_red_best;
+ const float cur_diff = GetPredictionCostCrossColorRed(
+ argb, stride, tile_width, tile_height, prev_x, prev_y,
+ green_to_red_cur, accumulated_red_histo);
+ if (cur_diff < best_diff) {
+ best_diff = cur_diff;
+ green_to_red_best = green_to_red_cur;
+ }
+ }
+ }
+ best_tx->green_to_red_ = green_to_red_best;
+}
+
+void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride,
+ int tile_width, int tile_height,
+ int green_to_blue, int red_to_blue,
+ int histo[]) {
+ while (tile_height-- > 0) {
+ int x;
+ for (x = 0; x < tile_width; ++x) {
+ ++histo[TransformColorBlue(green_to_blue, red_to_blue, argb[x])];
+ }
+ argb += stride;
+ }
+}
+
+static float GetPredictionCostCrossColorBlue(
+ const uint32_t* argb, int stride, int tile_width, int tile_height,
+ VP8LMultipliers prev_x, VP8LMultipliers prev_y,
+ int green_to_blue, int red_to_blue, const int accumulated_blue_histo[256]) {
+ int histo[256] = { 0 };
+ float cur_diff;
+
+ VP8LCollectColorBlueTransforms(argb, stride, tile_width, tile_height,
+ green_to_blue, red_to_blue, histo);
+
+ cur_diff = PredictionCostCrossColor(accumulated_blue_histo, histo);
+ if ((uint8_t)green_to_blue == prev_x.green_to_blue_) {
+ cur_diff -= 3; // favor keeping the areas locally similar
+ }
+ if ((uint8_t)green_to_blue == prev_y.green_to_blue_) {
+ cur_diff -= 3; // favor keeping the areas locally similar
+ }
+ if ((uint8_t)red_to_blue == prev_x.red_to_blue_) {
+ cur_diff -= 3; // favor keeping the areas locally similar
+ }
+ if ((uint8_t)red_to_blue == prev_y.red_to_blue_) {
+ cur_diff -= 3; // favor keeping the areas locally similar
+ }
+ if (green_to_blue == 0) {
+ cur_diff -= 3;
+ }
+ if (red_to_blue == 0) {
+ cur_diff -= 3;
+ }
+ return cur_diff;
+}
+
+#define kGreenRedToBlueNumAxis 8
+#define kGreenRedToBlueMaxIters 7
+static void GetBestGreenRedToBlue(
+ const uint32_t* argb, int stride, int tile_width, int tile_height,
+ VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality,
+ const int accumulated_blue_histo[256],
+ VP8LMultipliers* const best_tx) {
+ const int8_t offset[kGreenRedToBlueNumAxis][2] =
+ {{0, -1}, {0, 1}, {-1, 0}, {1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
+ const int8_t delta_lut[kGreenRedToBlueMaxIters] = { 16, 16, 8, 4, 2, 2, 2 };
+ const int iters =
+ (quality < 25) ? 1 : (quality > 50) ? kGreenRedToBlueMaxIters : 4;
+ int green_to_blue_best = 0;
+ int red_to_blue_best = 0;
+ int iter;
+ // Initial value at origin:
+ float best_diff = GetPredictionCostCrossColorBlue(
+ argb, stride, tile_width, tile_height, prev_x, prev_y,
+ green_to_blue_best, red_to_blue_best, accumulated_blue_histo);
+ for (iter = 0; iter < iters; ++iter) {
+ const int delta = delta_lut[iter];
+ int axis;
+ for (axis = 0; axis < kGreenRedToBlueNumAxis; ++axis) {
+ const int green_to_blue_cur =
+ offset[axis][0] * delta + green_to_blue_best;
+ const int red_to_blue_cur = offset[axis][1] * delta + red_to_blue_best;
+ const float cur_diff = GetPredictionCostCrossColorBlue(
+ argb, stride, tile_width, tile_height, prev_x, prev_y,
+ green_to_blue_cur, red_to_blue_cur, accumulated_blue_histo);
+ if (cur_diff < best_diff) {
+ best_diff = cur_diff;
+ green_to_blue_best = green_to_blue_cur;
+ red_to_blue_best = red_to_blue_cur;
+ }
+ if (quality < 25 && iter == 4) {
+ // Only axis aligned diffs for lower quality.
+ break; // next iter.
+ }
+ }
+ if (delta == 2 && green_to_blue_best == 0 && red_to_blue_best == 0) {
+ // Further iterations would not help.
+ break; // out of iter-loop.
+ }
+ }
+ best_tx->green_to_blue_ = green_to_blue_best;
+ best_tx->red_to_blue_ = red_to_blue_best;
+}
+#undef kGreenRedToBlueMaxIters
+#undef kGreenRedToBlueNumAxis
+
+static VP8LMultipliers GetBestColorTransformForTile(
+ int tile_x, int tile_y, int bits,
+ VP8LMultipliers prev_x,
+ VP8LMultipliers prev_y,
+ int quality, int xsize, int ysize,
+ const int accumulated_red_histo[256],
+ const int accumulated_blue_histo[256],
+ const uint32_t* const argb) {
+ const int max_tile_size = 1 << bits;
+ const int tile_y_offset = tile_y * max_tile_size;
+ const int tile_x_offset = tile_x * max_tile_size;
+ const int all_x_max = GetMin(tile_x_offset + max_tile_size, xsize);
+ const int all_y_max = GetMin(tile_y_offset + max_tile_size, ysize);
+ const int tile_width = all_x_max - tile_x_offset;
+ const int tile_height = all_y_max - tile_y_offset;
+ const uint32_t* const tile_argb = argb + tile_y_offset * xsize
+ + tile_x_offset;
+ VP8LMultipliers best_tx;
+ MultipliersClear(&best_tx);
+
+ GetBestGreenToRed(tile_argb, xsize, tile_width, tile_height,
+ prev_x, prev_y, quality, accumulated_red_histo, &best_tx);
+ GetBestGreenRedToBlue(tile_argb, xsize, tile_width, tile_height,
+ prev_x, prev_y, quality, accumulated_blue_histo,
+ &best_tx);
+ return best_tx;
+}
+
+static void CopyTileWithColorTransform(int xsize, int ysize,
+ int tile_x, int tile_y,
+ int max_tile_size,
+ VP8LMultipliers color_transform,
+ uint32_t* argb) {
+ const int xscan = GetMin(max_tile_size, xsize - tile_x);
+ int yscan = GetMin(max_tile_size, ysize - tile_y);
+ argb += tile_y * xsize + tile_x;
+ while (yscan-- > 0) {
+ VP8LTransformColor(&color_transform, argb, xscan);
+ argb += xsize;
+ }
+}
+
+void VP8LColorSpaceTransform(int width, int height, int bits, int quality,
+ uint32_t* const argb, uint32_t* image) {
+ const int max_tile_size = 1 << bits;
+ const int tile_xsize = VP8LSubSampleSize(width, bits);
+ const int tile_ysize = VP8LSubSampleSize(height, bits);
+ int accumulated_red_histo[256] = { 0 };
+ int accumulated_blue_histo[256] = { 0 };
+ int tile_x, tile_y;
+ VP8LMultipliers prev_x, prev_y;
+ MultipliersClear(&prev_y);
+ MultipliersClear(&prev_x);
+ for (tile_y = 0; tile_y < tile_ysize; ++tile_y) {
+ for (tile_x = 0; tile_x < tile_xsize; ++tile_x) {
+ int y;
+ const int tile_x_offset = tile_x * max_tile_size;
+ const int tile_y_offset = tile_y * max_tile_size;
+ const int all_x_max = GetMin(tile_x_offset + max_tile_size, width);
+ const int all_y_max = GetMin(tile_y_offset + max_tile_size, height);
+ const int offset = tile_y * tile_xsize + tile_x;
+ if (tile_y != 0) {
+ ColorCodeToMultipliers(image[offset - tile_xsize], &prev_y);
+ }
+ prev_x = GetBestColorTransformForTile(tile_x, tile_y, bits,
+ prev_x, prev_y,
+ quality, width, height,
+ accumulated_red_histo,
+ accumulated_blue_histo,
+ argb);
+ image[offset] = MultipliersToColorCode(&prev_x);
+ CopyTileWithColorTransform(width, height, tile_x_offset, tile_y_offset,
+ max_tile_size, prev_x, argb);
+
+ // Gather accumulated histogram data.
+ for (y = tile_y_offset; y < all_y_max; ++y) {
+ int ix = y * width + tile_x_offset;
+ const int ix_end = ix + all_x_max - tile_x_offset;
+ for (; ix < ix_end; ++ix) {
+ const uint32_t pix = argb[ix];
+ if (ix >= 2 &&
+ pix == argb[ix - 2] &&
+ pix == argb[ix - 1]) {
+ continue; // repeated pixels are handled by backward references
+ }
+ if (ix >= width + 2 &&
+ argb[ix - 2] == argb[ix - width - 2] &&
+ argb[ix - 1] == argb[ix - width - 1] &&
+ pix == argb[ix - width]) {
+ continue; // repeated pixels are handled by backward references
+ }
+ ++accumulated_red_histo[(pix >> 16) & 0xff];
+ ++accumulated_blue_histo[(pix >> 0) & 0xff];
+ }
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel.
+void VP8LBundleColorMap(const uint8_t* const row, int width,
+ int xbits, uint32_t* const dst) {
+ int x;
+ if (xbits > 0) {
+ const int bit_depth = 1 << (3 - xbits);
+ const int mask = (1 << xbits) - 1;
+ uint32_t code = 0xff000000;
+ for (x = 0; x < width; ++x) {
+ const int xsub = x & mask;
+ if (xsub == 0) {
+ code = 0xff000000;
+ }
+ code |= row[x] << (8 + bit_depth * xsub);
+ dst[x >> xbits] = code;
+ }
+ } else {
+ for (x = 0; x < width; ++x) dst[x] = 0xff000000 | (row[x] << 8);
+ }
+}
+
+//------------------------------------------------------------------------------
+
+static double ExtraCost(const uint32_t* population, int length) {
+ int i;
+ double cost = 0.;
+ for (i = 2; i < length - 2; ++i) cost += (i >> 1) * population[i + 2];
+ return cost;
+}
+
+static double ExtraCostCombined(const uint32_t* X, const uint32_t* Y,
+ int length) {
+ int i;
+ double cost = 0.;
+ for (i = 2; i < length - 2; ++i) {
+ const int xy = X[i + 2] + Y[i + 2];
+ cost += (i >> 1) * xy;
+ }
+ return cost;
+}
+
+// Returns the various RLE counts
+static VP8LStreaks HuffmanCostCount(const uint32_t* population, int length) {
+ int i;
+ int streak = 0;
+ VP8LStreaks stats;
+ memset(&stats, 0, sizeof(stats));
+ for (i = 0; i < length - 1; ++i) {
+ ++streak;
+ if (population[i] == population[i + 1]) {
+ continue;
+ }
+ stats.counts[population[i] != 0] += (streak > 3);
+ stats.streaks[population[i] != 0][(streak > 3)] += streak;
+ streak = 0;
+ }
+ ++streak;
+ stats.counts[population[i] != 0] += (streak > 3);
+ stats.streaks[population[i] != 0][(streak > 3)] += streak;
+ return stats;
+}
+
+//------------------------------------------------------------------------------
+
+static void HistogramAdd(const VP8LHistogram* const a,
+ const VP8LHistogram* const b,
+ VP8LHistogram* const out) {
+ int i;
+ const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_);
+ assert(a->palette_code_bits_ == b->palette_code_bits_);
+ if (b != out) {
+ for (i = 0; i < literal_size; ++i) {
+ out->literal_[i] = a->literal_[i] + b->literal_[i];
+ }
+ for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
+ out->distance_[i] = a->distance_[i] + b->distance_[i];
+ }
+ for (i = 0; i < NUM_LITERAL_CODES; ++i) {
+ out->red_[i] = a->red_[i] + b->red_[i];
+ out->blue_[i] = a->blue_[i] + b->blue_[i];
+ out->alpha_[i] = a->alpha_[i] + b->alpha_[i];
+ }
+ } else {
+ for (i = 0; i < literal_size; ++i) {
+ out->literal_[i] += a->literal_[i];
+ }
+ for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
+ out->distance_[i] += a->distance_[i];
+ }
+ for (i = 0; i < NUM_LITERAL_CODES; ++i) {
+ out->red_[i] += a->red_[i];
+ out->blue_[i] += a->blue_[i];
+ out->alpha_[i] += a->alpha_[i];
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;
+
+VP8LTransformColorFunc VP8LTransformColor;
+
+VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms;
+VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms;
+
+VP8LFastLog2SlowFunc VP8LFastLog2Slow;
+VP8LFastLog2SlowFunc VP8LFastSLog2Slow;
+
+VP8LCostFunc VP8LExtraCost;
+VP8LCostCombinedFunc VP8LExtraCostCombined;
+
+VP8LCostCountFunc VP8LHuffmanCostCount;
+
+VP8LHistogramAddFunc VP8LHistogramAdd;
+
+extern void VP8LEncDspInitSSE2(void);
+extern void VP8LEncDspInitSSE41(void);
+extern void VP8LEncDspInitNEON(void);
+extern void VP8LEncDspInitMIPS32(void);
+extern void VP8LEncDspInitMIPSdspR2(void);
+
+static volatile VP8CPUInfo lossless_enc_last_cpuinfo_used =
+ (VP8CPUInfo)&lossless_enc_last_cpuinfo_used;
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) {
+ if (lossless_enc_last_cpuinfo_used == VP8GetCPUInfo) return;
+
+ VP8LDspInit();
+
+ VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C;
+
+ VP8LTransformColor = VP8LTransformColor_C;
+
+ VP8LCollectColorBlueTransforms = VP8LCollectColorBlueTransforms_C;
+ VP8LCollectColorRedTransforms = VP8LCollectColorRedTransforms_C;
+
+ VP8LFastLog2Slow = FastLog2Slow;
+ VP8LFastSLog2Slow = FastSLog2Slow;
+
+ VP8LExtraCost = ExtraCost;
+ VP8LExtraCostCombined = ExtraCostCombined;
+
+ VP8LHuffmanCostCount = HuffmanCostCount;
+
+ VP8LHistogramAdd = HistogramAdd;
+
+ // If defined, use CPUInfo() to overwrite some pointers with faster versions.
+ if (VP8GetCPUInfo != NULL) {
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ VP8LEncDspInitSSE2();
+#if defined(WEBP_USE_SSE41)
+ if (VP8GetCPUInfo(kSSE4_1)) {
+ VP8LEncDspInitSSE41();
+ }
+#endif
+ }
+#endif
+#if defined(WEBP_USE_NEON)
+ if (VP8GetCPUInfo(kNEON)) {
+ VP8LEncDspInitNEON();
+ }
+#endif
+#if defined(WEBP_USE_MIPS32)
+ if (VP8GetCPUInfo(kMIPS32)) {
+ VP8LEncDspInitMIPS32();
+ }
+#endif
+#if defined(WEBP_USE_MIPS_DSP_R2)
+ if (VP8GetCPUInfo(kMIPSdspR2)) {
+ VP8LEncDspInitMIPSdspR2();
+ }
+#endif
+ }
+ lossless_enc_last_cpuinfo_used = VP8GetCPUInfo;
+}
+
+//------------------------------------------------------------------------------
diff --git a/drivers/webp/dsp/lossless_enc_mips32.c b/drivers/webp/dsp/lossless_enc_mips32.c
new file mode 100644
index 0000000000..0468a5aac2
--- /dev/null
+++ b/drivers/webp/dsp/lossless_enc_mips32.c
@@ -0,0 +1,417 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// MIPS version of lossless functions
+//
+// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
+// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
+
+#include "./dsp.h"
+#include "./lossless.h"
+
+#if defined(WEBP_USE_MIPS32)
+
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define APPROX_LOG_WITH_CORRECTION_MAX 65536
+#define APPROX_LOG_MAX 4096
+#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086
+
+static float FastSLog2Slow(uint32_t v) {
+ assert(v >= LOG_LOOKUP_IDX_MAX);
+ if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
+ uint32_t log_cnt, y, correction;
+ const int c24 = 24;
+ const float v_f = (float)v;
+ uint32_t temp;
+
+ // Xf = 256 = 2^8
+ // log_cnt is index of leading one in upper 24 bits
+ __asm__ volatile(
+ "clz %[log_cnt], %[v] \n\t"
+ "addiu %[y], $zero, 1 \n\t"
+ "subu %[log_cnt], %[c24], %[log_cnt] \n\t"
+ "sllv %[y], %[y], %[log_cnt] \n\t"
+ "srlv %[temp], %[v], %[log_cnt] \n\t"
+ : [log_cnt]"=&r"(log_cnt), [y]"=&r"(y),
+ [temp]"=r"(temp)
+ : [c24]"r"(c24), [v]"r"(v)
+ );
+
+ // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256
+ // Xf = floor(Xf) * (1 + (v % y) / v)
+ // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v)
+ // The correction factor: log(1 + d) ~ d; for very small d values, so
+ // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v
+ // LOG_2_RECIPROCAL ~ 23/16
+
+ // (v % y) = (v % 2^log_cnt) = v & (2^log_cnt - 1)
+ correction = (23 * (v & (y - 1))) >> 4;
+ return v_f * (kLog2Table[temp] + log_cnt) + correction;
+ } else {
+ return (float)(LOG_2_RECIPROCAL * v * log((double)v));
+ }
+}
+
+static float FastLog2Slow(uint32_t v) {
+ assert(v >= LOG_LOOKUP_IDX_MAX);
+ if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
+ uint32_t log_cnt, y;
+ const int c24 = 24;
+ double log_2;
+ uint32_t temp;
+
+ __asm__ volatile(
+ "clz %[log_cnt], %[v] \n\t"
+ "addiu %[y], $zero, 1 \n\t"
+ "subu %[log_cnt], %[c24], %[log_cnt] \n\t"
+ "sllv %[y], %[y], %[log_cnt] \n\t"
+ "srlv %[temp], %[v], %[log_cnt] \n\t"
+ : [log_cnt]"=&r"(log_cnt), [y]"=&r"(y),
+ [temp]"=r"(temp)
+ : [c24]"r"(c24), [v]"r"(v)
+ );
+
+ log_2 = kLog2Table[temp] + log_cnt;
+ if (v >= APPROX_LOG_MAX) {
+ // Since the division is still expensive, add this correction factor only
+ // for large values of 'v'.
+
+ const uint32_t correction = (23 * (v & (y - 1))) >> 4;
+ log_2 += (double)correction / v;
+ }
+ return (float)log_2;
+ } else {
+ return (float)(LOG_2_RECIPROCAL * log((double)v));
+ }
+}
+
+// C version of this function:
+// int i = 0;
+// int64_t cost = 0;
+// const uint32_t* pop = &population[4];
+// const uint32_t* LoopEnd = &population[length];
+// while (pop != LoopEnd) {
+// ++i;
+// cost += i * *pop;
+// cost += i * *(pop + 1);
+// pop += 2;
+// }
+// return (double)cost;
+static double ExtraCost(const uint32_t* const population, int length) {
+ int i, temp0, temp1;
+ const uint32_t* pop = &population[4];
+ const uint32_t* const LoopEnd = &population[length];
+
+ __asm__ volatile(
+ "mult $zero, $zero \n\t"
+ "xor %[i], %[i], %[i] \n\t"
+ "beq %[pop], %[LoopEnd], 2f \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[pop]) \n\t"
+ "lw %[temp1], 4(%[pop]) \n\t"
+ "addiu %[i], %[i], 1 \n\t"
+ "addiu %[pop], %[pop], 8 \n\t"
+ "madd %[i], %[temp0] \n\t"
+ "madd %[i], %[temp1] \n\t"
+ "bne %[pop], %[LoopEnd], 1b \n\t"
+ "2: \n\t"
+ "mfhi %[temp0] \n\t"
+ "mflo %[temp1] \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
+ [i]"=&r"(i), [pop]"+r"(pop)
+ : [LoopEnd]"r"(LoopEnd)
+ : "memory", "hi", "lo"
+ );
+
+ return (double)((int64_t)temp0 << 32 | temp1);
+}
+
+// C version of this function:
+// int i = 0;
+// int64_t cost = 0;
+// const uint32_t* pX = &X[4];
+// const uint32_t* pY = &Y[4];
+// const uint32_t* LoopEnd = &X[length];
+// while (pX != LoopEnd) {
+// const uint32_t xy0 = *pX + *pY;
+// const uint32_t xy1 = *(pX + 1) + *(pY + 1);
+// ++i;
+// cost += i * xy0;
+// cost += i * xy1;
+// pX += 2;
+// pY += 2;
+// }
+// return (double)cost;
+static double ExtraCostCombined(const uint32_t* const X,
+ const uint32_t* const Y, int length) {
+ int i, temp0, temp1, temp2, temp3;
+ const uint32_t* pX = &X[4];
+ const uint32_t* pY = &Y[4];
+ const uint32_t* const LoopEnd = &X[length];
+
+ __asm__ volatile(
+ "mult $zero, $zero \n\t"
+ "xor %[i], %[i], %[i] \n\t"
+ "beq %[pX], %[LoopEnd], 2f \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[pX]) \n\t"
+ "lw %[temp1], 0(%[pY]) \n\t"
+ "lw %[temp2], 4(%[pX]) \n\t"
+ "lw %[temp3], 4(%[pY]) \n\t"
+ "addiu %[i], %[i], 1 \n\t"
+ "addu %[temp0], %[temp0], %[temp1] \n\t"
+ "addu %[temp2], %[temp2], %[temp3] \n\t"
+ "addiu %[pX], %[pX], 8 \n\t"
+ "addiu %[pY], %[pY], 8 \n\t"
+ "madd %[i], %[temp0] \n\t"
+ "madd %[i], %[temp2] \n\t"
+ "bne %[pX], %[LoopEnd], 1b \n\t"
+ "2: \n\t"
+ "mfhi %[temp0] \n\t"
+ "mflo %[temp1] \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
+ [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
+ [i]"=&r"(i), [pX]"+r"(pX), [pY]"+r"(pY)
+ : [LoopEnd]"r"(LoopEnd)
+ : "memory", "hi", "lo"
+ );
+
+ return (double)((int64_t)temp0 << 32 | temp1);
+}
+
+#define HUFFMAN_COST_PASS \
+ __asm__ volatile( \
+ "sll %[temp1], %[temp0], 3 \n\t" \
+ "addiu %[temp3], %[streak], -3 \n\t" \
+ "addu %[temp2], %[pstreaks], %[temp1] \n\t" \
+ "blez %[temp3], 1f \n\t" \
+ "srl %[temp1], %[temp1], 1 \n\t" \
+ "addu %[temp3], %[pcnts], %[temp1] \n\t" \
+ "lw %[temp0], 4(%[temp2]) \n\t" \
+ "lw %[temp1], 0(%[temp3]) \n\t" \
+ "addu %[temp0], %[temp0], %[streak] \n\t" \
+ "addiu %[temp1], %[temp1], 1 \n\t" \
+ "sw %[temp0], 4(%[temp2]) \n\t" \
+ "sw %[temp1], 0(%[temp3]) \n\t" \
+ "b 2f \n\t" \
+ "1: \n\t" \
+ "lw %[temp0], 0(%[temp2]) \n\t" \
+ "addu %[temp0], %[temp0], %[streak] \n\t" \
+ "sw %[temp0], 0(%[temp2]) \n\t" \
+ "2: \n\t" \
+ : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \
+ [temp3]"=&r"(temp3), [temp0]"+r"(temp0) \
+ : [pstreaks]"r"(pstreaks), [pcnts]"r"(pcnts), \
+ [streak]"r"(streak) \
+ : "memory" \
+ );
+
+// Returns the various RLE counts
+static VP8LStreaks HuffmanCostCount(const uint32_t* population, int length) {
+ int i;
+ int streak = 0;
+ VP8LStreaks stats;
+ int* const pstreaks = &stats.streaks[0][0];
+ int* const pcnts = &stats.counts[0];
+ int temp0, temp1, temp2, temp3;
+ memset(&stats, 0, sizeof(stats));
+ for (i = 0; i < length - 1; ++i) {
+ ++streak;
+ if (population[i] == population[i + 1]) {
+ continue;
+ }
+ temp0 = (population[i] != 0);
+ HUFFMAN_COST_PASS
+ streak = 0;
+ }
+ ++streak;
+ temp0 = (population[i] != 0);
+ HUFFMAN_COST_PASS
+
+ return stats;
+}
+
+static VP8LStreaks HuffmanCostCombinedCount(const uint32_t* X,
+ const uint32_t* Y, int length) {
+ int i;
+ int streak = 0;
+ uint32_t xy_prev = 0xffffffff;
+ VP8LStreaks stats;
+ int* const pstreaks = &stats.streaks[0][0];
+ int* const pcnts = &stats.counts[0];
+ int temp0, temp1, temp2, temp3;
+ memset(&stats, 0, sizeof(stats));
+ for (i = 0; i < length; ++i) {
+ const uint32_t xy = X[i] + Y[i];
+ ++streak;
+ if (xy != xy_prev) {
+ temp0 = (xy != 0);
+ HUFFMAN_COST_PASS
+ streak = 0;
+ xy_prev = xy;
+ }
+ }
+ return stats;
+}
+
+#define ASM_START \
+ __asm__ volatile( \
+ ".set push \n\t" \
+ ".set at \n\t" \
+ ".set macro \n\t" \
+ "1: \n\t"
+
+// P2 = P0 + P1
+// A..D - offsets
+// E - temp variable to tell macro
+// if pointer should be incremented
+// literal_ and successive histograms could be unaligned
+// so we must use ulw and usw
+#define ADD_TO_OUT(A, B, C, D, E, P0, P1, P2) \
+ "ulw %[temp0], " #A "(%[" #P0 "]) \n\t" \
+ "ulw %[temp1], " #B "(%[" #P0 "]) \n\t" \
+ "ulw %[temp2], " #C "(%[" #P0 "]) \n\t" \
+ "ulw %[temp3], " #D "(%[" #P0 "]) \n\t" \
+ "ulw %[temp4], " #A "(%[" #P1 "]) \n\t" \
+ "ulw %[temp5], " #B "(%[" #P1 "]) \n\t" \
+ "ulw %[temp6], " #C "(%[" #P1 "]) \n\t" \
+ "ulw %[temp7], " #D "(%[" #P1 "]) \n\t" \
+ "addu %[temp4], %[temp4], %[temp0] \n\t" \
+ "addu %[temp5], %[temp5], %[temp1] \n\t" \
+ "addu %[temp6], %[temp6], %[temp2] \n\t" \
+ "addu %[temp7], %[temp7], %[temp3] \n\t" \
+ "addiu %[" #P0 "], %[" #P0 "], 16 \n\t" \
+ ".if " #E " == 1 \n\t" \
+ "addiu %[" #P1 "], %[" #P1 "], 16 \n\t" \
+ ".endif \n\t" \
+ "usw %[temp4], " #A "(%[" #P2 "]) \n\t" \
+ "usw %[temp5], " #B "(%[" #P2 "]) \n\t" \
+ "usw %[temp6], " #C "(%[" #P2 "]) \n\t" \
+ "usw %[temp7], " #D "(%[" #P2 "]) \n\t" \
+ "addiu %[" #P2 "], %[" #P2 "], 16 \n\t" \
+ "bne %[" #P0 "], %[LoopEnd], 1b \n\t" \
+ ".set pop \n\t" \
+
+#define ASM_END_COMMON_0 \
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \
+ [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), \
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), \
+ [pa]"+r"(pa), [pout]"+r"(pout)
+
+#define ASM_END_COMMON_1 \
+ : [LoopEnd]"r"(LoopEnd) \
+ : "memory", "at" \
+ );
+
+#define ASM_END_0 \
+ ASM_END_COMMON_0 \
+ , [pb]"+r"(pb) \
+ ASM_END_COMMON_1
+
+#define ASM_END_1 \
+ ASM_END_COMMON_0 \
+ ASM_END_COMMON_1
+
+#define ADD_VECTOR(A, B, OUT, SIZE, EXTRA_SIZE) do { \
+ const uint32_t* pa = (const uint32_t*)(A); \
+ const uint32_t* pb = (const uint32_t*)(B); \
+ uint32_t* pout = (uint32_t*)(OUT); \
+ const uint32_t* const LoopEnd = pa + (SIZE); \
+ assert((SIZE) % 4 == 0); \
+ ASM_START \
+ ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout) \
+ ASM_END_0 \
+ if ((EXTRA_SIZE) > 0) { \
+ const int last = (EXTRA_SIZE); \
+ int i; \
+ for (i = 0; i < last; ++i) pout[i] = pa[i] + pb[i]; \
+ } \
+} while (0)
+
+#define ADD_VECTOR_EQ(A, OUT, SIZE, EXTRA_SIZE) do { \
+ const uint32_t* pa = (const uint32_t*)(A); \
+ uint32_t* pout = (uint32_t*)(OUT); \
+ const uint32_t* const LoopEnd = pa + (SIZE); \
+ assert((SIZE) % 4 == 0); \
+ ASM_START \
+ ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout) \
+ ASM_END_1 \
+ if ((EXTRA_SIZE) > 0) { \
+ const int last = (EXTRA_SIZE); \
+ int i; \
+ for (i = 0; i < last; ++i) pout[i] += pa[i]; \
+ } \
+} while (0)
+
+static void HistogramAdd(const VP8LHistogram* const a,
+ const VP8LHistogram* const b,
+ VP8LHistogram* const out) {
+ uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
+ const int extra_cache_size = VP8LHistogramNumCodes(a->palette_code_bits_)
+ - (NUM_LITERAL_CODES + NUM_LENGTH_CODES);
+ assert(a->palette_code_bits_ == b->palette_code_bits_);
+
+ if (b != out) {
+ ADD_VECTOR(a->literal_, b->literal_, out->literal_,
+ NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size);
+ ADD_VECTOR(a->distance_, b->distance_, out->distance_,
+ NUM_DISTANCE_CODES, 0);
+ ADD_VECTOR(a->red_, b->red_, out->red_, NUM_LITERAL_CODES, 0);
+ ADD_VECTOR(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES, 0);
+ ADD_VECTOR(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES, 0);
+ } else {
+ ADD_VECTOR_EQ(a->literal_, out->literal_,
+ NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size);
+ ADD_VECTOR_EQ(a->distance_, out->distance_, NUM_DISTANCE_CODES, 0);
+ ADD_VECTOR_EQ(a->red_, out->red_, NUM_LITERAL_CODES, 0);
+ ADD_VECTOR_EQ(a->blue_, out->blue_, NUM_LITERAL_CODES, 0);
+ ADD_VECTOR_EQ(a->alpha_, out->alpha_, NUM_LITERAL_CODES, 0);
+ }
+}
+
+#undef ADD_VECTOR_EQ
+#undef ADD_VECTOR
+#undef ASM_END_1
+#undef ASM_END_0
+#undef ASM_END_COMMON_1
+#undef ASM_END_COMMON_0
+#undef ADD_TO_OUT
+#undef ASM_START
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8LEncDspInitMIPS32(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPS32(void) {
+ VP8LFastSLog2Slow = FastSLog2Slow;
+ VP8LFastLog2Slow = FastLog2Slow;
+ VP8LExtraCost = ExtraCost;
+ VP8LExtraCostCombined = ExtraCostCombined;
+ VP8LHuffmanCostCount = HuffmanCostCount;
+// TODO(mips team): rewrite VP8LGetCombinedEntropy (which used to use
+// HuffmanCostCombinedCount) with MIPS optimizations
+#if 0
+ VP8LHuffmanCostCombinedCount = HuffmanCostCombinedCount;
+#else
+ (void)HuffmanCostCombinedCount;
+#endif
+ VP8LHistogramAdd = HistogramAdd;
+}
+
+#else // !WEBP_USE_MIPS32
+
+WEBP_DSP_INIT_STUB(VP8LEncDspInitMIPS32)
+
+#endif // WEBP_USE_MIPS32
diff --git a/drivers/webp/dsp/lossless_enc_mips_dsp_r2.c b/drivers/webp/dsp/lossless_enc_mips_dsp_r2.c
new file mode 100644
index 0000000000..0abf3c4f36
--- /dev/null
+++ b/drivers/webp/dsp/lossless_enc_mips_dsp_r2.c
@@ -0,0 +1,275 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Image transform methods for lossless encoder.
+//
+// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
+// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS_DSP_R2)
+
+#include "./lossless.h"
+
+static void SubtractGreenFromBlueAndRed(uint32_t* argb_data,
+ int num_pixels) {
+ uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
+ uint32_t* const p_loop1_end = argb_data + (num_pixels & ~3);
+ uint32_t* const p_loop2_end = p_loop1_end + (num_pixels & 3);
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "beq %[argb_data], %[p_loop1_end], 3f \n\t"
+ " nop \n\t"
+ "0: \n\t"
+ "lw %[temp0], 0(%[argb_data]) \n\t"
+ "lw %[temp1], 4(%[argb_data]) \n\t"
+ "lw %[temp2], 8(%[argb_data]) \n\t"
+ "lw %[temp3], 12(%[argb_data]) \n\t"
+ "ext %[temp4], %[temp0], 8, 8 \n\t"
+ "ext %[temp5], %[temp1], 8, 8 \n\t"
+ "ext %[temp6], %[temp2], 8, 8 \n\t"
+ "ext %[temp7], %[temp3], 8, 8 \n\t"
+ "addiu %[argb_data], %[argb_data], 16 \n\t"
+ "replv.ph %[temp4], %[temp4] \n\t"
+ "replv.ph %[temp5], %[temp5] \n\t"
+ "replv.ph %[temp6], %[temp6] \n\t"
+ "replv.ph %[temp7], %[temp7] \n\t"
+ "subu.qb %[temp0], %[temp0], %[temp4] \n\t"
+ "subu.qb %[temp1], %[temp1], %[temp5] \n\t"
+ "subu.qb %[temp2], %[temp2], %[temp6] \n\t"
+ "subu.qb %[temp3], %[temp3], %[temp7] \n\t"
+ "sw %[temp0], -16(%[argb_data]) \n\t"
+ "sw %[temp1], -12(%[argb_data]) \n\t"
+ "sw %[temp2], -8(%[argb_data]) \n\t"
+ "bne %[argb_data], %[p_loop1_end], 0b \n\t"
+ " sw %[temp3], -4(%[argb_data]) \n\t"
+ "3: \n\t"
+ "beq %[argb_data], %[p_loop2_end], 2f \n\t"
+ " nop \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[argb_data]) \n\t"
+ "addiu %[argb_data], %[argb_data], 4 \n\t"
+ "ext %[temp4], %[temp0], 8, 8 \n\t"
+ "replv.ph %[temp4], %[temp4] \n\t"
+ "subu.qb %[temp0], %[temp0], %[temp4] \n\t"
+ "bne %[argb_data], %[p_loop2_end], 1b \n\t"
+ " sw %[temp0], -4(%[argb_data]) \n\t"
+ "2: \n\t"
+ ".set pop \n\t"
+ : [argb_data]"+&r"(argb_data), [temp0]"=&r"(temp0),
+ [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6),
+ [temp7]"=&r"(temp7)
+ : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)
+ : "memory"
+ );
+}
+
+static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred,
+ int8_t color) {
+ return (uint32_t)((int)(color_pred) * color) >> 5;
+}
+
+static void TransformColor(const VP8LMultipliers* const m, uint32_t* data,
+ int num_pixels) {
+ int temp0, temp1, temp2, temp3, temp4, temp5;
+ uint32_t argb, argb1, new_red, new_red1;
+ const uint32_t G_to_R = m->green_to_red_;
+ const uint32_t G_to_B = m->green_to_blue_;
+ const uint32_t R_to_B = m->red_to_blue_;
+ uint32_t* const p_loop_end = data + (num_pixels & ~1);
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "beq %[data], %[p_loop_end], 1f \n\t"
+ " nop \n\t"
+ "replv.ph %[temp0], %[G_to_R] \n\t"
+ "replv.ph %[temp1], %[G_to_B] \n\t"
+ "replv.ph %[temp2], %[R_to_B] \n\t"
+ "shll.ph %[temp0], %[temp0], 8 \n\t"
+ "shll.ph %[temp1], %[temp1], 8 \n\t"
+ "shll.ph %[temp2], %[temp2], 8 \n\t"
+ "shra.ph %[temp0], %[temp0], 8 \n\t"
+ "shra.ph %[temp1], %[temp1], 8 \n\t"
+ "shra.ph %[temp2], %[temp2], 8 \n\t"
+ "0: \n\t"
+ "lw %[argb], 0(%[data]) \n\t"
+ "lw %[argb1], 4(%[data]) \n\t"
+ "lhu %[new_red], 2(%[data]) \n\t"
+ "lhu %[new_red1], 6(%[data]) \n\t"
+ "precrq.qb.ph %[temp3], %[argb], %[argb1] \n\t"
+ "precr.qb.ph %[temp4], %[argb], %[argb1] \n\t"
+ "preceu.ph.qbra %[temp3], %[temp3] \n\t"
+ "preceu.ph.qbla %[temp4], %[temp4] \n\t"
+ "shll.ph %[temp3], %[temp3], 8 \n\t"
+ "shll.ph %[temp4], %[temp4], 8 \n\t"
+ "shra.ph %[temp3], %[temp3], 8 \n\t"
+ "shra.ph %[temp4], %[temp4], 8 \n\t"
+ "mul.ph %[temp5], %[temp3], %[temp0] \n\t"
+ "mul.ph %[temp3], %[temp3], %[temp1] \n\t"
+ "mul.ph %[temp4], %[temp4], %[temp2] \n\t"
+ "addiu %[data], %[data], 8 \n\t"
+ "ins %[new_red1], %[new_red], 16, 16 \n\t"
+ "ins %[argb1], %[argb], 16, 16 \n\t"
+ "shra.ph %[temp5], %[temp5], 5 \n\t"
+ "shra.ph %[temp3], %[temp3], 5 \n\t"
+ "shra.ph %[temp4], %[temp4], 5 \n\t"
+ "subu.ph %[new_red1], %[new_red1], %[temp5] \n\t"
+ "subu.ph %[argb1], %[argb1], %[temp3] \n\t"
+ "preceu.ph.qbra %[temp5], %[new_red1] \n\t"
+ "subu.ph %[argb1], %[argb1], %[temp4] \n\t"
+ "preceu.ph.qbra %[temp3], %[argb1] \n\t"
+ "sb %[temp5], -2(%[data]) \n\t"
+ "sb %[temp3], -4(%[data]) \n\t"
+ "sra %[temp5], %[temp5], 16 \n\t"
+ "sra %[temp3], %[temp3], 16 \n\t"
+ "sb %[temp5], -6(%[data]) \n\t"
+ "bne %[data], %[p_loop_end], 0b \n\t"
+ " sb %[temp3], -8(%[data]) \n\t"
+ "1: \n\t"
+ ".set pop \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [new_red1]"=&r"(new_red1), [new_red]"=&r"(new_red),
+ [argb]"=&r"(argb), [argb1]"=&r"(argb1), [data]"+&r"(data)
+ : [G_to_R]"r"(G_to_R), [R_to_B]"r"(R_to_B),
+ [G_to_B]"r"(G_to_B), [p_loop_end]"r"(p_loop_end)
+ : "memory", "hi", "lo"
+ );
+
+ if (num_pixels & 1) {
+ const uint32_t argb_ = data[0];
+ const uint32_t green = argb_ >> 8;
+ const uint32_t red = argb_ >> 16;
+ uint32_t new_blue = argb_;
+ new_red = red;
+ new_red -= ColorTransformDelta(m->green_to_red_, green);
+ new_red &= 0xff;
+ new_blue -= ColorTransformDelta(m->green_to_blue_, green);
+ new_blue -= ColorTransformDelta(m->red_to_blue_, red);
+ new_blue &= 0xff;
+ data[0] = (argb_ & 0xff00ff00u) | (new_red << 16) | (new_blue);
+ }
+}
+
+static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue,
+ uint8_t red_to_blue,
+ uint32_t argb) {
+ const uint32_t green = argb >> 8;
+ const uint32_t red = argb >> 16;
+ uint8_t new_blue = argb;
+ new_blue -= ColorTransformDelta(green_to_blue, green);
+ new_blue -= ColorTransformDelta(red_to_blue, red);
+ return (new_blue & 0xff);
+}
+
+static void CollectColorBlueTransforms(const uint32_t* argb, int stride,
+ int tile_width, int tile_height,
+ int green_to_blue, int red_to_blue,
+ int histo[]) {
+ const int rtb = (red_to_blue << 16) | (red_to_blue & 0xffff);
+ const int gtb = (green_to_blue << 16) | (green_to_blue & 0xffff);
+ const uint32_t mask = 0xff00ffu;
+ while (tile_height-- > 0) {
+ int x;
+ const uint32_t* p_argb = argb;
+ argb += stride;
+ for (x = 0; x < (tile_width >> 1); ++x) {
+ int temp0, temp1, temp2, temp3, temp4, temp5, temp6;
+ __asm__ volatile (
+ "lw %[temp0], 0(%[p_argb]) \n\t"
+ "lw %[temp1], 4(%[p_argb]) \n\t"
+ "precr.qb.ph %[temp2], %[temp0], %[temp1] \n\t"
+ "ins %[temp1], %[temp0], 16, 16 \n\t"
+ "shra.ph %[temp2], %[temp2], 8 \n\t"
+ "shra.ph %[temp3], %[temp1], 8 \n\t"
+ "mul.ph %[temp5], %[temp2], %[rtb] \n\t"
+ "mul.ph %[temp6], %[temp3], %[gtb] \n\t"
+ "and %[temp4], %[temp1], %[mask] \n\t"
+ "addiu %[p_argb], %[p_argb], 8 \n\t"
+ "shra.ph %[temp5], %[temp5], 5 \n\t"
+ "shra.ph %[temp6], %[temp6], 5 \n\t"
+ "subu.qb %[temp2], %[temp4], %[temp5] \n\t"
+ "subu.qb %[temp2], %[temp2], %[temp6] \n\t"
+ : [p_argb]"+&r"(p_argb), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
+ [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4),
+ [temp5]"=&r"(temp5), [temp6]"=&r"(temp6)
+ : [rtb]"r"(rtb), [gtb]"r"(gtb), [mask]"r"(mask)
+ : "memory", "hi", "lo"
+ );
+ ++histo[(uint8_t)(temp2 >> 16)];
+ ++histo[(uint8_t)temp2];
+ }
+ if (tile_width & 1) {
+ ++histo[TransformColorBlue(green_to_blue, red_to_blue, *p_argb)];
+ }
+ }
+}
+
+static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red,
+ uint32_t argb) {
+ const uint32_t green = argb >> 8;
+ uint32_t new_red = argb >> 16;
+ new_red -= ColorTransformDelta(green_to_red, green);
+ return (new_red & 0xff);
+}
+
+static void CollectColorRedTransforms(const uint32_t* argb, int stride,
+ int tile_width, int tile_height,
+ int green_to_red, int histo[]) {
+ const int gtr = (green_to_red << 16) | (green_to_red & 0xffff);
+ while (tile_height-- > 0) {
+ int x;
+ const uint32_t* p_argb = argb;
+ argb += stride;
+ for (x = 0; x < (tile_width >> 1); ++x) {
+ int temp0, temp1, temp2, temp3, temp4;
+ __asm__ volatile (
+ "lw %[temp0], 0(%[p_argb]) \n\t"
+ "lw %[temp1], 4(%[p_argb]) \n\t"
+ "precrq.ph.w %[temp4], %[temp0], %[temp1] \n\t"
+ "ins %[temp1], %[temp0], 16, 16 \n\t"
+ "shra.ph %[temp3], %[temp1], 8 \n\t"
+ "mul.ph %[temp2], %[temp3], %[gtr] \n\t"
+ "addiu %[p_argb], %[p_argb], 8 \n\t"
+ "shra.ph %[temp2], %[temp2], 5 \n\t"
+ "subu.qb %[temp2], %[temp4], %[temp2] \n\t"
+ : [p_argb]"+&r"(p_argb), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
+ [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4)
+ : [gtr]"r"(gtr)
+ : "memory", "hi", "lo"
+ );
+ ++histo[(uint8_t)(temp2 >> 16)];
+ ++histo[(uint8_t)temp2];
+ }
+ if (tile_width & 1) {
+ ++histo[TransformColorRed(green_to_red, *p_argb)];
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8LEncDspInitMIPSdspR2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPSdspR2(void) {
+ VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed;
+ VP8LTransformColor = TransformColor;
+ VP8LCollectColorBlueTransforms = CollectColorBlueTransforms;
+ VP8LCollectColorRedTransforms = CollectColorRedTransforms;
+}
+
+#else // !WEBP_USE_MIPS_DSP_R2
+
+WEBP_DSP_INIT_STUB(VP8LEncDspInitMIPSdspR2)
+
+#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/lossless_enc_neon.c b/drivers/webp/dsp/lossless_enc_neon.c
new file mode 100644
index 0000000000..4c56f2594b
--- /dev/null
+++ b/drivers/webp/dsp/lossless_enc_neon.c
@@ -0,0 +1,143 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// NEON variant of methods for lossless encoder
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_NEON)
+
+#include <arm_neon.h>
+
+#include "./lossless.h"
+#include "./neon.h"
+
+//------------------------------------------------------------------------------
+// Subtract-Green Transform
+
+// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use
+// non-standard versions there.
+#if defined(__APPLE__) && defined(__aarch64__) && \
+ defined(__apple_build_version__) && (__apple_build_version__< 6020037)
+#define USE_VTBLQ
+#endif
+
+#ifdef USE_VTBLQ
+// 255 = byte will be zeroed
+static const uint8_t kGreenShuffle[16] = {
+ 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255
+};
+
+static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb,
+ const uint8x16_t shuffle) {
+ return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)),
+ vtbl1q_u8(argb, vget_high_u8(shuffle)));
+}
+#else // !USE_VTBLQ
+// 255 = byte will be zeroed
+static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 };
+
+static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb,
+ const uint8x8_t shuffle) {
+ return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle),
+ vtbl1_u8(vget_high_u8(argb), shuffle));
+}
+#endif // USE_VTBLQ
+
+static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) {
+ const uint32_t* const end = argb_data + (num_pixels & ~3);
+#ifdef USE_VTBLQ
+ const uint8x16_t shuffle = vld1q_u8(kGreenShuffle);
+#else
+ const uint8x8_t shuffle = vld1_u8(kGreenShuffle);
+#endif
+ for (; argb_data < end; argb_data += 4) {
+ const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data);
+ const uint8x16_t greens = DoGreenShuffle(argb, shuffle);
+ vst1q_u8((uint8_t*)argb_data, vsubq_u8(argb, greens));
+ }
+ // fallthrough and finish off with plain-C
+ VP8LSubtractGreenFromBlueAndRed_C(argb_data, num_pixels & 3);
+}
+
+//------------------------------------------------------------------------------
+// Color Transform
+
+static void TransformColor(const VP8LMultipliers* const m,
+ uint32_t* argb_data, int num_pixels) {
+ // sign-extended multiplying constants, pre-shifted by 6.
+#define CST(X) (((int16_t)(m->X << 8)) >> 6)
+ const int16_t rb[8] = {
+ CST(green_to_blue_), CST(green_to_red_),
+ CST(green_to_blue_), CST(green_to_red_),
+ CST(green_to_blue_), CST(green_to_red_),
+ CST(green_to_blue_), CST(green_to_red_)
+ };
+ const int16x8_t mults_rb = vld1q_s16(rb);
+ const int16_t b2[8] = {
+ 0, CST(red_to_blue_), 0, CST(red_to_blue_),
+ 0, CST(red_to_blue_), 0, CST(red_to_blue_),
+ };
+ const int16x8_t mults_b2 = vld1q_s16(b2);
+#undef CST
+#ifdef USE_VTBLQ
+ static const uint8_t kg0g0[16] = {
+ 255, 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13
+ };
+ const uint8x16_t shuffle = vld1q_u8(kg0g0);
+#else
+ static const uint8_t k0g0g[8] = { 255, 1, 255, 1, 255, 5, 255, 5 };
+ const uint8x8_t shuffle = vld1_u8(k0g0g);
+#endif
+ const uint32x4_t mask_rb = vdupq_n_u32(0x00ff00ffu); // red-blue masks
+ int i;
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const uint8x16_t in = vld1q_u8((uint8_t*)(argb_data + i));
+ // 0 g 0 g
+ const uint8x16_t greens = DoGreenShuffle(in, shuffle);
+ // x dr x db1
+ const int16x8_t A = vqdmulhq_s16(vreinterpretq_s16_u8(greens), mults_rb);
+ // r 0 b 0
+ const int16x8_t B = vshlq_n_s16(vreinterpretq_s16_u8(in), 8);
+ // x db2 0 0
+ const int16x8_t C = vqdmulhq_s16(B, mults_b2);
+ // 0 0 x db2
+ const uint32x4_t D = vshrq_n_u32(vreinterpretq_u32_s16(C), 16);
+ // x dr x db
+ const int8x16_t E = vaddq_s8(vreinterpretq_s8_u32(D),
+ vreinterpretq_s8_s16(A));
+ // 0 dr 0 db
+ const uint32x4_t F = vandq_u32(vreinterpretq_u32_s8(E), mask_rb);
+ const int8x16_t out = vsubq_s8(vreinterpretq_s8_u8(in),
+ vreinterpretq_s8_u32(F));
+ vst1q_s8((int8_t*)(argb_data + i), out);
+ }
+ // fallthrough and finish off with plain-C
+ VP8LTransformColor_C(m, argb_data + i, num_pixels - i);
+}
+
+#undef USE_VTBLQ
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8LEncDspInitNEON(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitNEON(void) {
+ VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed;
+ VP8LTransformColor = TransformColor;
+}
+
+#else // !WEBP_USE_NEON
+
+WEBP_DSP_INIT_STUB(VP8LEncDspInitNEON)
+
+#endif // WEBP_USE_NEON
diff --git a/drivers/webp/dsp/lossless_enc_sse2.c b/drivers/webp/dsp/lossless_enc_sse2.c
new file mode 100644
index 0000000000..1374b3ef64
--- /dev/null
+++ b/drivers/webp/dsp/lossless_enc_sse2.c
@@ -0,0 +1,270 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// SSE2 variant of methods for lossless encoder
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_SSE2)
+#include <assert.h>
+#include <emmintrin.h>
+#include "./lossless.h"
+
+// For sign-extended multiplying constants, pre-shifted by 5:
+#define CST_5b(X) (((int16_t)((uint16_t)X << 8)) >> 5)
+
+//------------------------------------------------------------------------------
+// Subtract-Green Transform
+
+static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) {
+ int i;
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb
+ const __m128i A = _mm_srli_epi16(in, 8); // 0 a 0 g
+ const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0));
+ const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // 0g0g
+ const __m128i out = _mm_sub_epi8(in, C);
+ _mm_storeu_si128((__m128i*)&argb_data[i], out);
+ }
+ // fallthrough and finish off with plain-C
+ VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i);
+}
+
+//------------------------------------------------------------------------------
+// Color Transform
+
+static void TransformColor(const VP8LMultipliers* const m,
+ uint32_t* argb_data, int num_pixels) {
+ const __m128i mults_rb = _mm_set_epi16(
+ CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_),
+ CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_),
+ CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_),
+ CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_));
+ const __m128i mults_b2 = _mm_set_epi16(
+ CST_5b(m->red_to_blue_), 0, CST_5b(m->red_to_blue_), 0,
+ CST_5b(m->red_to_blue_), 0, CST_5b(m->red_to_blue_), 0);
+ const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks
+ const __m128i mask_rb = _mm_set1_epi32(0x00ff00ff); // red-blue masks
+ int i;
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb
+ const __m128i A = _mm_and_si128(in, mask_ag); // a 0 g 0
+ const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0));
+ const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // g0g0
+ const __m128i D = _mm_mulhi_epi16(C, mults_rb); // x dr x db1
+ const __m128i E = _mm_slli_epi16(in, 8); // r 0 b 0
+ const __m128i F = _mm_mulhi_epi16(E, mults_b2); // x db2 0 0
+ const __m128i G = _mm_srli_epi32(F, 16); // 0 0 x db2
+ const __m128i H = _mm_add_epi8(G, D); // x dr x db
+ const __m128i I = _mm_and_si128(H, mask_rb); // 0 dr 0 db
+ const __m128i out = _mm_sub_epi8(in, I);
+ _mm_storeu_si128((__m128i*)&argb_data[i], out);
+ }
+ // fallthrough and finish off with plain-C
+ VP8LTransformColor_C(m, argb_data + i, num_pixels - i);
+}
+
+//------------------------------------------------------------------------------
+#define SPAN 8
+static void CollectColorBlueTransforms(const uint32_t* argb, int stride,
+ int tile_width, int tile_height,
+ int green_to_blue, int red_to_blue,
+ int histo[]) {
+ const __m128i mults_r = _mm_set_epi16(
+ CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0,
+ CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0);
+ const __m128i mults_g = _mm_set_epi16(
+ 0, CST_5b(green_to_blue), 0, CST_5b(green_to_blue),
+ 0, CST_5b(green_to_blue), 0, CST_5b(green_to_blue));
+ const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask
+ const __m128i mask_b = _mm_set1_epi32(0x0000ff); // blue mask
+ int y;
+ for (y = 0; y < tile_height; ++y) {
+ const uint32_t* const src = argb + y * stride;
+ int i, x;
+ for (x = 0; x + SPAN <= tile_width; x += SPAN) {
+ uint16_t values[SPAN];
+ const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]);
+ const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]);
+ const __m128i A0 = _mm_slli_epi16(in0, 8); // r 0 | b 0
+ const __m128i A1 = _mm_slli_epi16(in1, 8);
+ const __m128i B0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0
+ const __m128i B1 = _mm_and_si128(in1, mask_g);
+ const __m128i C0 = _mm_mulhi_epi16(A0, mults_r); // x db | 0 0
+ const __m128i C1 = _mm_mulhi_epi16(A1, mults_r);
+ const __m128i D0 = _mm_mulhi_epi16(B0, mults_g); // 0 0 | x db
+ const __m128i D1 = _mm_mulhi_epi16(B1, mults_g);
+ const __m128i E0 = _mm_sub_epi8(in0, D0); // x x | x b'
+ const __m128i E1 = _mm_sub_epi8(in1, D1);
+ const __m128i F0 = _mm_srli_epi32(C0, 16); // 0 0 | x db
+ const __m128i F1 = _mm_srli_epi32(C1, 16);
+ const __m128i G0 = _mm_sub_epi8(E0, F0); // 0 0 | x b'
+ const __m128i G1 = _mm_sub_epi8(E1, F1);
+ const __m128i H0 = _mm_and_si128(G0, mask_b); // 0 0 | 0 b
+ const __m128i H1 = _mm_and_si128(G1, mask_b);
+ const __m128i I = _mm_packs_epi32(H0, H1); // 0 b' | 0 b'
+ _mm_storeu_si128((__m128i*)values, I);
+ for (i = 0; i < SPAN; ++i) ++histo[values[i]];
+ }
+ }
+ {
+ const int left_over = tile_width & (SPAN - 1);
+ if (left_over > 0) {
+ VP8LCollectColorBlueTransforms_C(argb + tile_width - left_over, stride,
+ left_over, tile_height,
+ green_to_blue, red_to_blue, histo);
+ }
+ }
+}
+
+static void CollectColorRedTransforms(const uint32_t* argb, int stride,
+ int tile_width, int tile_height,
+ int green_to_red, int histo[]) {
+ const __m128i mults_g = _mm_set_epi16(
+ 0, CST_5b(green_to_red), 0, CST_5b(green_to_red),
+ 0, CST_5b(green_to_red), 0, CST_5b(green_to_red));
+ const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask
+ const __m128i mask = _mm_set1_epi32(0xff);
+
+ int y;
+ for (y = 0; y < tile_height; ++y) {
+ const uint32_t* const src = argb + y * stride;
+ int i, x;
+ for (x = 0; x + SPAN <= tile_width; x += SPAN) {
+ uint16_t values[SPAN];
+ const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]);
+ const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]);
+ const __m128i A0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0
+ const __m128i A1 = _mm_and_si128(in1, mask_g);
+ const __m128i B0 = _mm_srli_epi32(in0, 16); // 0 0 | x r
+ const __m128i B1 = _mm_srli_epi32(in1, 16);
+ const __m128i C0 = _mm_mulhi_epi16(A0, mults_g); // 0 0 | x dr
+ const __m128i C1 = _mm_mulhi_epi16(A1, mults_g);
+ const __m128i E0 = _mm_sub_epi8(B0, C0); // x x | x r'
+ const __m128i E1 = _mm_sub_epi8(B1, C1);
+ const __m128i F0 = _mm_and_si128(E0, mask); // 0 0 | 0 r'
+ const __m128i F1 = _mm_and_si128(E1, mask);
+ const __m128i I = _mm_packs_epi32(F0, F1);
+ _mm_storeu_si128((__m128i*)values, I);
+ for (i = 0; i < SPAN; ++i) ++histo[values[i]];
+ }
+ }
+ {
+ const int left_over = tile_width & (SPAN - 1);
+ if (left_over > 0) {
+ VP8LCollectColorRedTransforms_C(argb + tile_width - left_over, stride,
+ left_over, tile_height,
+ green_to_red, histo);
+ }
+ }
+}
+#undef SPAN
+
+//------------------------------------------------------------------------------
+
+#define LINE_SIZE 16 // 8 or 16
+static void AddVector(const uint32_t* a, const uint32_t* b, uint32_t* out,
+ int size) {
+ int i;
+ assert(size % LINE_SIZE == 0);
+ for (i = 0; i < size; i += LINE_SIZE) {
+ const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]);
+ const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]);
+#if (LINE_SIZE == 16)
+ const __m128i a2 = _mm_loadu_si128((const __m128i*)&a[i + 8]);
+ const __m128i a3 = _mm_loadu_si128((const __m128i*)&a[i + 12]);
+#endif
+ const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[i + 0]);
+ const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[i + 4]);
+#if (LINE_SIZE == 16)
+ const __m128i b2 = _mm_loadu_si128((const __m128i*)&b[i + 8]);
+ const __m128i b3 = _mm_loadu_si128((const __m128i*)&b[i + 12]);
+#endif
+ _mm_storeu_si128((__m128i*)&out[i + 0], _mm_add_epi32(a0, b0));
+ _mm_storeu_si128((__m128i*)&out[i + 4], _mm_add_epi32(a1, b1));
+#if (LINE_SIZE == 16)
+ _mm_storeu_si128((__m128i*)&out[i + 8], _mm_add_epi32(a2, b2));
+ _mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3));
+#endif
+ }
+}
+
+static void AddVectorEq(const uint32_t* a, uint32_t* out, int size) {
+ int i;
+ assert(size % LINE_SIZE == 0);
+ for (i = 0; i < size; i += LINE_SIZE) {
+ const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]);
+ const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]);
+#if (LINE_SIZE == 16)
+ const __m128i a2 = _mm_loadu_si128((const __m128i*)&a[i + 8]);
+ const __m128i a3 = _mm_loadu_si128((const __m128i*)&a[i + 12]);
+#endif
+ const __m128i b0 = _mm_loadu_si128((const __m128i*)&out[i + 0]);
+ const __m128i b1 = _mm_loadu_si128((const __m128i*)&out[i + 4]);
+#if (LINE_SIZE == 16)
+ const __m128i b2 = _mm_loadu_si128((const __m128i*)&out[i + 8]);
+ const __m128i b3 = _mm_loadu_si128((const __m128i*)&out[i + 12]);
+#endif
+ _mm_storeu_si128((__m128i*)&out[i + 0], _mm_add_epi32(a0, b0));
+ _mm_storeu_si128((__m128i*)&out[i + 4], _mm_add_epi32(a1, b1));
+#if (LINE_SIZE == 16)
+ _mm_storeu_si128((__m128i*)&out[i + 8], _mm_add_epi32(a2, b2));
+ _mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3));
+#endif
+ }
+}
+#undef LINE_SIZE
+
+// Note we are adding uint32_t's as *signed* int32's (using _mm_add_epi32). But
+// that's ok since the histogram values are less than 1<<28 (max picture size).
+static void HistogramAdd(const VP8LHistogram* const a,
+ const VP8LHistogram* const b,
+ VP8LHistogram* const out) {
+ int i;
+ const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_);
+ assert(a->palette_code_bits_ == b->palette_code_bits_);
+ if (b != out) {
+ AddVector(a->literal_, b->literal_, out->literal_, NUM_LITERAL_CODES);
+ AddVector(a->red_, b->red_, out->red_, NUM_LITERAL_CODES);
+ AddVector(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES);
+ AddVector(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES);
+ } else {
+ AddVectorEq(a->literal_, out->literal_, NUM_LITERAL_CODES);
+ AddVectorEq(a->red_, out->red_, NUM_LITERAL_CODES);
+ AddVectorEq(a->blue_, out->blue_, NUM_LITERAL_CODES);
+ AddVectorEq(a->alpha_, out->alpha_, NUM_LITERAL_CODES);
+ }
+ for (i = NUM_LITERAL_CODES; i < literal_size; ++i) {
+ out->literal_[i] = a->literal_[i] + b->literal_[i];
+ }
+ for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
+ out->distance_[i] = a->distance_[i] + b->distance_[i];
+ }
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8LEncDspInitSSE2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE2(void) {
+ VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed;
+ VP8LTransformColor = TransformColor;
+ VP8LCollectColorBlueTransforms = CollectColorBlueTransforms;
+ VP8LCollectColorRedTransforms = CollectColorRedTransforms;
+ VP8LHistogramAdd = HistogramAdd;
+}
+
+#else // !WEBP_USE_SSE2
+
+WEBP_DSP_INIT_STUB(VP8LEncDspInitSSE2)
+
+#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/lossless_enc_sse41.c b/drivers/webp/dsp/lossless_enc_sse41.c
new file mode 100644
index 0000000000..3e493198db
--- /dev/null
+++ b/drivers/webp/dsp/lossless_enc_sse41.c
@@ -0,0 +1,51 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// SSE4.1 variant of methods for lossless encoder
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_SSE41)
+#include <assert.h>
+#include <smmintrin.h>
+#include "./lossless.h"
+
+//------------------------------------------------------------------------------
+// Subtract-Green Transform
+
+static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) {
+ int i;
+ const __m128i kCstShuffle = _mm_set_epi8(-1, 13, -1, 13, -1, 9, -1, 9,
+ -1, 5, -1, 5, -1, 1, -1, 1);
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]);
+ const __m128i in_0g0g = _mm_shuffle_epi8(in, kCstShuffle);
+ const __m128i out = _mm_sub_epi8(in, in_0g0g);
+ _mm_storeu_si128((__m128i*)&argb_data[i], out);
+ }
+ // fallthrough and finish off with plain-C
+ VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i);
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8LEncDspInitSSE41(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE41(void) {
+ VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed;
+}
+
+#else // !WEBP_USE_SSE41
+
+WEBP_DSP_INIT_STUB(VP8LEncDspInitSSE41)
+
+#endif // WEBP_USE_SSE41
diff --git a/drivers/webp/dsp/lossless_mips_dsp_r2.c b/drivers/webp/dsp/lossless_mips_dsp_r2.c
new file mode 100644
index 0000000000..90aed7f151
--- /dev/null
+++ b/drivers/webp/dsp/lossless_mips_dsp_r2.c
@@ -0,0 +1,680 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Image transforms and color space conversion methods for lossless decoder.
+//
+// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
+// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS_DSP_R2)
+
+#include "./lossless.h"
+
+#define MAP_COLOR_FUNCS(FUNC_NAME, TYPE, GET_INDEX, GET_VALUE) \
+static void FUNC_NAME(const TYPE* src, \
+ const uint32_t* const color_map, \
+ TYPE* dst, int y_start, int y_end, \
+ int width) { \
+ int y; \
+ for (y = y_start; y < y_end; ++y) { \
+ int x; \
+ for (x = 0; x < (width >> 2); ++x) { \
+ int tmp1, tmp2, tmp3, tmp4; \
+ __asm__ volatile ( \
+ ".ifc " #TYPE ", uint8_t \n\t" \
+ "lbu %[tmp1], 0(%[src]) \n\t" \
+ "lbu %[tmp2], 1(%[src]) \n\t" \
+ "lbu %[tmp3], 2(%[src]) \n\t" \
+ "lbu %[tmp4], 3(%[src]) \n\t" \
+ "addiu %[src], %[src], 4 \n\t" \
+ ".endif \n\t" \
+ ".ifc " #TYPE ", uint32_t \n\t" \
+ "lw %[tmp1], 0(%[src]) \n\t" \
+ "lw %[tmp2], 4(%[src]) \n\t" \
+ "lw %[tmp3], 8(%[src]) \n\t" \
+ "lw %[tmp4], 12(%[src]) \n\t" \
+ "ext %[tmp1], %[tmp1], 8, 8 \n\t" \
+ "ext %[tmp2], %[tmp2], 8, 8 \n\t" \
+ "ext %[tmp3], %[tmp3], 8, 8 \n\t" \
+ "ext %[tmp4], %[tmp4], 8, 8 \n\t" \
+ "addiu %[src], %[src], 16 \n\t" \
+ ".endif \n\t" \
+ "sll %[tmp1], %[tmp1], 2 \n\t" \
+ "sll %[tmp2], %[tmp2], 2 \n\t" \
+ "sll %[tmp3], %[tmp3], 2 \n\t" \
+ "sll %[tmp4], %[tmp4], 2 \n\t" \
+ "lwx %[tmp1], %[tmp1](%[color_map]) \n\t" \
+ "lwx %[tmp2], %[tmp2](%[color_map]) \n\t" \
+ "lwx %[tmp3], %[tmp3](%[color_map]) \n\t" \
+ "lwx %[tmp4], %[tmp4](%[color_map]) \n\t" \
+ ".ifc " #TYPE ", uint8_t \n\t" \
+ "ext %[tmp1], %[tmp1], 8, 8 \n\t" \
+ "ext %[tmp2], %[tmp2], 8, 8 \n\t" \
+ "ext %[tmp3], %[tmp3], 8, 8 \n\t" \
+ "ext %[tmp4], %[tmp4], 8, 8 \n\t" \
+ "sb %[tmp1], 0(%[dst]) \n\t" \
+ "sb %[tmp2], 1(%[dst]) \n\t" \
+ "sb %[tmp3], 2(%[dst]) \n\t" \
+ "sb %[tmp4], 3(%[dst]) \n\t" \
+ "addiu %[dst], %[dst], 4 \n\t" \
+ ".endif \n\t" \
+ ".ifc " #TYPE ", uint32_t \n\t" \
+ "sw %[tmp1], 0(%[dst]) \n\t" \
+ "sw %[tmp2], 4(%[dst]) \n\t" \
+ "sw %[tmp3], 8(%[dst]) \n\t" \
+ "sw %[tmp4], 12(%[dst]) \n\t" \
+ "addiu %[dst], %[dst], 16 \n\t" \
+ ".endif \n\t" \
+ : [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), [tmp3]"=&r"(tmp3), \
+ [tmp4]"=&r"(tmp4), [src]"+&r"(src), [dst]"+r"(dst) \
+ : [color_map]"r"(color_map) \
+ : "memory" \
+ ); \
+ } \
+ for (x = 0; x < (width & 3); ++x) { \
+ *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \
+ } \
+ } \
+}
+
+MAP_COLOR_FUNCS(MapARGB, uint32_t, VP8GetARGBIndex, VP8GetARGBValue)
+MAP_COLOR_FUNCS(MapAlpha, uint8_t, VP8GetAlphaIndex, VP8GetAlphaValue)
+
+#undef MAP_COLOR_FUNCS
+
+static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
+ uint32_t c2) {
+ int temp0, temp1, temp2, temp3, temp4, temp5;
+ __asm__ volatile (
+ "preceu.ph.qbr %[temp1], %[c0] \n\t"
+ "preceu.ph.qbl %[temp2], %[c0] \n\t"
+ "preceu.ph.qbr %[temp3], %[c1] \n\t"
+ "preceu.ph.qbl %[temp4], %[c1] \n\t"
+ "preceu.ph.qbr %[temp5], %[c2] \n\t"
+ "preceu.ph.qbl %[temp0], %[c2] \n\t"
+ "subq.ph %[temp3], %[temp3], %[temp5] \n\t"
+ "subq.ph %[temp4], %[temp4], %[temp0] \n\t"
+ "addq.ph %[temp1], %[temp1], %[temp3] \n\t"
+ "addq.ph %[temp2], %[temp2], %[temp4] \n\t"
+ "shll_s.ph %[temp1], %[temp1], 7 \n\t"
+ "shll_s.ph %[temp2], %[temp2], 7 \n\t"
+ "precrqu_s.qb.ph %[temp2], %[temp2], %[temp1] \n\t"
+ : [temp0]"=r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5)
+ : [c0]"r"(c0), [c1]"r"(c1), [c2]"r"(c2)
+ : "memory"
+ );
+ return temp2;
+}
+
+static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
+ uint32_t c2) {
+ int temp0, temp1, temp2, temp3, temp4, temp5;
+ __asm__ volatile (
+ "adduh.qb %[temp5], %[c0], %[c1] \n\t"
+ "preceu.ph.qbr %[temp3], %[c2] \n\t"
+ "preceu.ph.qbr %[temp1], %[temp5] \n\t"
+ "preceu.ph.qbl %[temp2], %[temp5] \n\t"
+ "preceu.ph.qbl %[temp4], %[c2] \n\t"
+ "subq.ph %[temp3], %[temp1], %[temp3] \n\t"
+ "subq.ph %[temp4], %[temp2], %[temp4] \n\t"
+ "shrl.ph %[temp5], %[temp3], 15 \n\t"
+ "shrl.ph %[temp0], %[temp4], 15 \n\t"
+ "addq.ph %[temp3], %[temp3], %[temp5] \n\t"
+ "addq.ph %[temp4], %[temp0], %[temp4] \n\t"
+ "shra.ph %[temp3], %[temp3], 1 \n\t"
+ "shra.ph %[temp4], %[temp4], 1 \n\t"
+ "addq.ph %[temp1], %[temp1], %[temp3] \n\t"
+ "addq.ph %[temp2], %[temp2], %[temp4] \n\t"
+ "shll_s.ph %[temp1], %[temp1], 7 \n\t"
+ "shll_s.ph %[temp2], %[temp2], 7 \n\t"
+ "precrqu_s.qb.ph %[temp1], %[temp2], %[temp1] \n\t"
+ : [temp0]"=r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=r"(temp4), [temp5]"=&r"(temp5)
+ : [c0]"r"(c0), [c1]"r"(c1), [c2]"r"(c2)
+ : "memory"
+ );
+ return temp1;
+}
+
+static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
+ int temp0, temp1, temp2, temp3, temp4, temp5;
+ __asm__ volatile (
+ "cmpgdu.lt.qb %[temp1], %[c], %[b] \n\t"
+ "pick.qb %[temp1], %[b], %[c] \n\t"
+ "pick.qb %[temp2], %[c], %[b] \n\t"
+ "cmpgdu.lt.qb %[temp4], %[c], %[a] \n\t"
+ "pick.qb %[temp4], %[a], %[c] \n\t"
+ "pick.qb %[temp5], %[c], %[a] \n\t"
+ "subu.qb %[temp3], %[temp1], %[temp2] \n\t"
+ "subu.qb %[temp0], %[temp4], %[temp5] \n\t"
+ "raddu.w.qb %[temp3], %[temp3] \n\t"
+ "raddu.w.qb %[temp0], %[temp0] \n\t"
+ "subu %[temp3], %[temp3], %[temp0] \n\t"
+ "slti %[temp0], %[temp3], 0x1 \n\t"
+ "movz %[a], %[b], %[temp0] \n\t"
+ : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp0]"=&r"(temp0),
+ [a]"+&r"(a)
+ : [b]"r"(b), [c]"r"(c)
+ );
+ return a;
+}
+
+static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
+ __asm__ volatile (
+ "adduh.qb %[a0], %[a0], %[a1] \n\t"
+ : [a0]"+r"(a0)
+ : [a1]"r"(a1)
+ );
+ return a0;
+}
+
+static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
+ return Average2(Average2(a0, a2), a1);
+}
+
+static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
+ uint32_t a2, uint32_t a3) {
+ return Average2(Average2(a0, a1), Average2(a2, a3));
+}
+
+static uint32_t Predictor5(uint32_t left, const uint32_t* const top) {
+ return Average3(left, top[0], top[1]);
+}
+
+static uint32_t Predictor6(uint32_t left, const uint32_t* const top) {
+ return Average2(left, top[-1]);
+}
+
+static uint32_t Predictor7(uint32_t left, const uint32_t* const top) {
+ return Average2(left, top[0]);
+}
+
+static uint32_t Predictor8(uint32_t left, const uint32_t* const top) {
+ (void)left;
+ return Average2(top[-1], top[0]);
+}
+
+static uint32_t Predictor9(uint32_t left, const uint32_t* const top) {
+ (void)left;
+ return Average2(top[0], top[1]);
+}
+
+static uint32_t Predictor10(uint32_t left, const uint32_t* const top) {
+ return Average4(left, top[-1], top[0], top[1]);
+}
+
+static uint32_t Predictor11(uint32_t left, const uint32_t* const top) {
+ return Select(top[0], left, top[-1]);
+}
+
+static uint32_t Predictor12(uint32_t left, const uint32_t* const top) {
+ return ClampedAddSubtractFull(left, top[0], top[-1]);
+}
+
+static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
+ return ClampedAddSubtractHalf(left, top[0], top[-1]);
+}
+
+// Add green to blue and red channels (i.e. perform the inverse transform of
+// 'subtract green').
+static void AddGreenToBlueAndRed(uint32_t* data, int num_pixels) {
+ uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
+ uint32_t* const p_loop1_end = data + (num_pixels & ~3);
+ uint32_t* const p_loop2_end = data + num_pixels;
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "beq %[data], %[p_loop1_end], 3f \n\t"
+ " nop \n\t"
+ "0: \n\t"
+ "lw %[temp0], 0(%[data]) \n\t"
+ "lw %[temp1], 4(%[data]) \n\t"
+ "lw %[temp2], 8(%[data]) \n\t"
+ "lw %[temp3], 12(%[data]) \n\t"
+ "ext %[temp4], %[temp0], 8, 8 \n\t"
+ "ext %[temp5], %[temp1], 8, 8 \n\t"
+ "ext %[temp6], %[temp2], 8, 8 \n\t"
+ "ext %[temp7], %[temp3], 8, 8 \n\t"
+ "addiu %[data], %[data], 16 \n\t"
+ "replv.ph %[temp4], %[temp4] \n\t"
+ "replv.ph %[temp5], %[temp5] \n\t"
+ "replv.ph %[temp6], %[temp6] \n\t"
+ "replv.ph %[temp7], %[temp7] \n\t"
+ "addu.qb %[temp0], %[temp0], %[temp4] \n\t"
+ "addu.qb %[temp1], %[temp1], %[temp5] \n\t"
+ "addu.qb %[temp2], %[temp2], %[temp6] \n\t"
+ "addu.qb %[temp3], %[temp3], %[temp7] \n\t"
+ "sw %[temp0], -16(%[data]) \n\t"
+ "sw %[temp1], -12(%[data]) \n\t"
+ "sw %[temp2], -8(%[data]) \n\t"
+ "bne %[data], %[p_loop1_end], 0b \n\t"
+ " sw %[temp3], -4(%[data]) \n\t"
+ "3: \n\t"
+ "beq %[data], %[p_loop2_end], 2f \n\t"
+ " nop \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[data]) \n\t"
+ "addiu %[data], %[data], 4 \n\t"
+ "ext %[temp4], %[temp0], 8, 8 \n\t"
+ "replv.ph %[temp4], %[temp4] \n\t"
+ "addu.qb %[temp0], %[temp0], %[temp4] \n\t"
+ "bne %[data], %[p_loop2_end], 1b \n\t"
+ " sw %[temp0], -4(%[data]) \n\t"
+ "2: \n\t"
+ ".set pop \n\t"
+ : [data]"+&r"(data), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
+ [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4),
+ [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), [temp7]"=&r"(temp7)
+ : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)
+ : "memory"
+ );
+}
+
+static void TransformColorInverse(const VP8LMultipliers* const m,
+ uint32_t* data, int num_pixels) {
+ int temp0, temp1, temp2, temp3, temp4, temp5;
+ uint32_t argb, argb1, new_red;
+ const uint32_t G_to_R = m->green_to_red_;
+ const uint32_t G_to_B = m->green_to_blue_;
+ const uint32_t R_to_B = m->red_to_blue_;
+ uint32_t* const p_loop_end = data + (num_pixels & ~1);
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "beq %[data], %[p_loop_end], 1f \n\t"
+ " nop \n\t"
+ "replv.ph %[temp0], %[G_to_R] \n\t"
+ "replv.ph %[temp1], %[G_to_B] \n\t"
+ "replv.ph %[temp2], %[R_to_B] \n\t"
+ "shll.ph %[temp0], %[temp0], 8 \n\t"
+ "shll.ph %[temp1], %[temp1], 8 \n\t"
+ "shll.ph %[temp2], %[temp2], 8 \n\t"
+ "shra.ph %[temp0], %[temp0], 8 \n\t"
+ "shra.ph %[temp1], %[temp1], 8 \n\t"
+ "shra.ph %[temp2], %[temp2], 8 \n\t"
+ "0: \n\t"
+ "lw %[argb], 0(%[data]) \n\t"
+ "lw %[argb1], 4(%[data]) \n\t"
+ "addiu %[data], %[data], 8 \n\t"
+ "precrq.qb.ph %[temp3], %[argb], %[argb1] \n\t"
+ "preceu.ph.qbra %[temp3], %[temp3] \n\t"
+ "shll.ph %[temp3], %[temp3], 8 \n\t"
+ "shra.ph %[temp3], %[temp3], 8 \n\t"
+ "mul.ph %[temp5], %[temp3], %[temp0] \n\t"
+ "mul.ph %[temp3], %[temp3], %[temp1] \n\t"
+ "precrq.ph.w %[new_red], %[argb], %[argb1] \n\t"
+ "ins %[argb1], %[argb], 16, 16 \n\t"
+ "shra.ph %[temp5], %[temp5], 5 \n\t"
+ "shra.ph %[temp3], %[temp3], 5 \n\t"
+ "addu.ph %[new_red], %[new_red], %[temp5] \n\t"
+ "addu.ph %[argb1], %[argb1], %[temp3] \n\t"
+ "preceu.ph.qbra %[temp5], %[new_red] \n\t"
+ "shll.ph %[temp4], %[temp5], 8 \n\t"
+ "shra.ph %[temp4], %[temp4], 8 \n\t"
+ "mul.ph %[temp4], %[temp4], %[temp2] \n\t"
+ "sb %[temp5], -2(%[data]) \n\t"
+ "sra %[temp5], %[temp5], 16 \n\t"
+ "shra.ph %[temp4], %[temp4], 5 \n\t"
+ "addu.ph %[argb1], %[argb1], %[temp4] \n\t"
+ "preceu.ph.qbra %[temp3], %[argb1] \n\t"
+ "sb %[temp5], -6(%[data]) \n\t"
+ "sb %[temp3], -4(%[data]) \n\t"
+ "sra %[temp3], %[temp3], 16 \n\t"
+ "bne %[data], %[p_loop_end], 0b \n\t"
+ " sb %[temp3], -8(%[data]) \n\t"
+ "1: \n\t"
+ ".set pop \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [new_red]"=&r"(new_red), [argb]"=&r"(argb),
+ [argb1]"=&r"(argb1), [data]"+&r"(data)
+ : [G_to_R]"r"(G_to_R), [R_to_B]"r"(R_to_B),
+ [G_to_B]"r"(G_to_B), [p_loop_end]"r"(p_loop_end)
+ : "memory", "hi", "lo"
+ );
+
+ // Fall-back to C-version for left-overs.
+ if (num_pixels & 1) VP8LTransformColorInverse_C(m, data, 1);
+}
+
+static void ConvertBGRAToRGB(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ int temp0, temp1, temp2, temp3;
+ const uint32_t* const p_loop1_end = src + (num_pixels & ~3);
+ const uint32_t* const p_loop2_end = src + num_pixels;
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "beq %[src], %[p_loop1_end], 3f \n\t"
+ " nop \n\t"
+ "0: \n\t"
+ "lw %[temp3], 12(%[src]) \n\t"
+ "lw %[temp2], 8(%[src]) \n\t"
+ "lw %[temp1], 4(%[src]) \n\t"
+ "lw %[temp0], 0(%[src]) \n\t"
+ "ins %[temp3], %[temp2], 24, 8 \n\t"
+ "sll %[temp2], %[temp2], 8 \n\t"
+ "rotr %[temp3], %[temp3], 16 \n\t"
+ "ins %[temp2], %[temp1], 0, 16 \n\t"
+ "sll %[temp1], %[temp1], 8 \n\t"
+ "wsbh %[temp3], %[temp3] \n\t"
+ "balign %[temp0], %[temp1], 1 \n\t"
+ "wsbh %[temp2], %[temp2] \n\t"
+ "wsbh %[temp0], %[temp0] \n\t"
+ "usw %[temp3], 8(%[dst]) \n\t"
+ "rotr %[temp0], %[temp0], 16 \n\t"
+ "usw %[temp2], 4(%[dst]) \n\t"
+ "addiu %[src], %[src], 16 \n\t"
+ "usw %[temp0], 0(%[dst]) \n\t"
+ "bne %[src], %[p_loop1_end], 0b \n\t"
+ " addiu %[dst], %[dst], 12 \n\t"
+ "3: \n\t"
+ "beq %[src], %[p_loop2_end], 2f \n\t"
+ " nop \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[src]) \n\t"
+ "addiu %[src], %[src], 4 \n\t"
+ "wsbh %[temp1], %[temp0] \n\t"
+ "addiu %[dst], %[dst], 3 \n\t"
+ "ush %[temp1], -2(%[dst]) \n\t"
+ "sra %[temp0], %[temp0], 16 \n\t"
+ "bne %[src], %[p_loop2_end], 1b \n\t"
+ " sb %[temp0], -3(%[dst]) \n\t"
+ "2: \n\t"
+ ".set pop \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src)
+ : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)
+ : "memory"
+ );
+}
+
+static void ConvertBGRAToRGBA(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ int temp0, temp1, temp2, temp3;
+ const uint32_t* const p_loop1_end = src + (num_pixels & ~3);
+ const uint32_t* const p_loop2_end = src + num_pixels;
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "beq %[src], %[p_loop1_end], 3f \n\t"
+ " nop \n\t"
+ "0: \n\t"
+ "lw %[temp0], 0(%[src]) \n\t"
+ "lw %[temp1], 4(%[src]) \n\t"
+ "lw %[temp2], 8(%[src]) \n\t"
+ "lw %[temp3], 12(%[src]) \n\t"
+ "wsbh %[temp0], %[temp0] \n\t"
+ "wsbh %[temp1], %[temp1] \n\t"
+ "wsbh %[temp2], %[temp2] \n\t"
+ "wsbh %[temp3], %[temp3] \n\t"
+ "addiu %[src], %[src], 16 \n\t"
+ "balign %[temp0], %[temp0], 1 \n\t"
+ "balign %[temp1], %[temp1], 1 \n\t"
+ "balign %[temp2], %[temp2], 1 \n\t"
+ "balign %[temp3], %[temp3], 1 \n\t"
+ "usw %[temp0], 0(%[dst]) \n\t"
+ "usw %[temp1], 4(%[dst]) \n\t"
+ "usw %[temp2], 8(%[dst]) \n\t"
+ "usw %[temp3], 12(%[dst]) \n\t"
+ "bne %[src], %[p_loop1_end], 0b \n\t"
+ " addiu %[dst], %[dst], 16 \n\t"
+ "3: \n\t"
+ "beq %[src], %[p_loop2_end], 2f \n\t"
+ " nop \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[src]) \n\t"
+ "wsbh %[temp0], %[temp0] \n\t"
+ "addiu %[src], %[src], 4 \n\t"
+ "balign %[temp0], %[temp0], 1 \n\t"
+ "usw %[temp0], 0(%[dst]) \n\t"
+ "bne %[src], %[p_loop2_end], 1b \n\t"
+ " addiu %[dst], %[dst], 4 \n\t"
+ "2: \n\t"
+ ".set pop \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src)
+ : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)
+ : "memory"
+ );
+}
+
+static void ConvertBGRAToRGBA4444(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ int temp0, temp1, temp2, temp3, temp4, temp5;
+ const uint32_t* const p_loop1_end = src + (num_pixels & ~3);
+ const uint32_t* const p_loop2_end = src + num_pixels;
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "beq %[src], %[p_loop1_end], 3f \n\t"
+ " nop \n\t"
+ "0: \n\t"
+ "lw %[temp0], 0(%[src]) \n\t"
+ "lw %[temp1], 4(%[src]) \n\t"
+ "lw %[temp2], 8(%[src]) \n\t"
+ "lw %[temp3], 12(%[src]) \n\t"
+ "ext %[temp4], %[temp0], 28, 4 \n\t"
+ "ext %[temp5], %[temp0], 12, 4 \n\t"
+ "ins %[temp0], %[temp4], 0, 4 \n\t"
+ "ext %[temp4], %[temp1], 28, 4 \n\t"
+ "ins %[temp0], %[temp5], 16, 4 \n\t"
+ "ext %[temp5], %[temp1], 12, 4 \n\t"
+ "ins %[temp1], %[temp4], 0, 4 \n\t"
+ "ext %[temp4], %[temp2], 28, 4 \n\t"
+ "ins %[temp1], %[temp5], 16, 4 \n\t"
+ "ext %[temp5], %[temp2], 12, 4 \n\t"
+ "ins %[temp2], %[temp4], 0, 4 \n\t"
+ "ext %[temp4], %[temp3], 28, 4 \n\t"
+ "ins %[temp2], %[temp5], 16, 4 \n\t"
+ "ext %[temp5], %[temp3], 12, 4 \n\t"
+ "ins %[temp3], %[temp4], 0, 4 \n\t"
+ "precr.qb.ph %[temp1], %[temp1], %[temp0] \n\t"
+ "ins %[temp3], %[temp5], 16, 4 \n\t"
+ "addiu %[src], %[src], 16 \n\t"
+ "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t"
+#ifdef WEBP_SWAP_16BIT_CSP
+ "usw %[temp1], 0(%[dst]) \n\t"
+ "usw %[temp3], 4(%[dst]) \n\t"
+#else
+ "wsbh %[temp1], %[temp1] \n\t"
+ "wsbh %[temp3], %[temp3] \n\t"
+ "usw %[temp1], 0(%[dst]) \n\t"
+ "usw %[temp3], 4(%[dst]) \n\t"
+#endif
+ "bne %[src], %[p_loop1_end], 0b \n\t"
+ " addiu %[dst], %[dst], 8 \n\t"
+ "3: \n\t"
+ "beq %[src], %[p_loop2_end], 2f \n\t"
+ " nop \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[src]) \n\t"
+ "ext %[temp4], %[temp0], 28, 4 \n\t"
+ "ext %[temp5], %[temp0], 12, 4 \n\t"
+ "ins %[temp0], %[temp4], 0, 4 \n\t"
+ "ins %[temp0], %[temp5], 16, 4 \n\t"
+ "addiu %[src], %[src], 4 \n\t"
+ "precr.qb.ph %[temp0], %[temp0], %[temp0] \n\t"
+#ifdef WEBP_SWAP_16BIT_CSP
+ "ush %[temp0], 0(%[dst]) \n\t"
+#else
+ "wsbh %[temp0], %[temp0] \n\t"
+ "ush %[temp0], 0(%[dst]) \n\t"
+#endif
+ "bne %[src], %[p_loop2_end], 1b \n\t"
+ " addiu %[dst], %[dst], 2 \n\t"
+ "2: \n\t"
+ ".set pop \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [dst]"+&r"(dst), [src]"+&r"(src)
+ : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)
+ : "memory"
+ );
+}
+
+static void ConvertBGRAToRGB565(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ int temp0, temp1, temp2, temp3, temp4, temp5;
+ const uint32_t* const p_loop1_end = src + (num_pixels & ~3);
+ const uint32_t* const p_loop2_end = src + num_pixels;
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "beq %[src], %[p_loop1_end], 3f \n\t"
+ " nop \n\t"
+ "0: \n\t"
+ "lw %[temp0], 0(%[src]) \n\t"
+ "lw %[temp1], 4(%[src]) \n\t"
+ "lw %[temp2], 8(%[src]) \n\t"
+ "lw %[temp3], 12(%[src]) \n\t"
+ "ext %[temp4], %[temp0], 8, 16 \n\t"
+ "ext %[temp5], %[temp0], 5, 11 \n\t"
+ "ext %[temp0], %[temp0], 3, 5 \n\t"
+ "ins %[temp4], %[temp5], 0, 11 \n\t"
+ "ext %[temp5], %[temp1], 5, 11 \n\t"
+ "ins %[temp4], %[temp0], 0, 5 \n\t"
+ "ext %[temp0], %[temp1], 8, 16 \n\t"
+ "ext %[temp1], %[temp1], 3, 5 \n\t"
+ "ins %[temp0], %[temp5], 0, 11 \n\t"
+ "ext %[temp5], %[temp2], 5, 11 \n\t"
+ "ins %[temp0], %[temp1], 0, 5 \n\t"
+ "ext %[temp1], %[temp2], 8, 16 \n\t"
+ "ext %[temp2], %[temp2], 3, 5 \n\t"
+ "ins %[temp1], %[temp5], 0, 11 \n\t"
+ "ext %[temp5], %[temp3], 5, 11 \n\t"
+ "ins %[temp1], %[temp2], 0, 5 \n\t"
+ "ext %[temp2], %[temp3], 8, 16 \n\t"
+ "ext %[temp3], %[temp3], 3, 5 \n\t"
+ "ins %[temp2], %[temp5], 0, 11 \n\t"
+ "append %[temp0], %[temp4], 16 \n\t"
+ "ins %[temp2], %[temp3], 0, 5 \n\t"
+ "addiu %[src], %[src], 16 \n\t"
+ "append %[temp2], %[temp1], 16 \n\t"
+#ifdef WEBP_SWAP_16BIT_CSP
+ "usw %[temp0], 0(%[dst]) \n\t"
+ "usw %[temp2], 4(%[dst]) \n\t"
+#else
+ "wsbh %[temp0], %[temp0] \n\t"
+ "wsbh %[temp2], %[temp2] \n\t"
+ "usw %[temp0], 0(%[dst]) \n\t"
+ "usw %[temp2], 4(%[dst]) \n\t"
+#endif
+ "bne %[src], %[p_loop1_end], 0b \n\t"
+ " addiu %[dst], %[dst], 8 \n\t"
+ "3: \n\t"
+ "beq %[src], %[p_loop2_end], 2f \n\t"
+ " nop \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[src]) \n\t"
+ "ext %[temp4], %[temp0], 8, 16 \n\t"
+ "ext %[temp5], %[temp0], 5, 11 \n\t"
+ "ext %[temp0], %[temp0], 3, 5 \n\t"
+ "ins %[temp4], %[temp5], 0, 11 \n\t"
+ "addiu %[src], %[src], 4 \n\t"
+ "ins %[temp4], %[temp0], 0, 5 \n\t"
+#ifdef WEBP_SWAP_16BIT_CSP
+ "ush %[temp4], 0(%[dst]) \n\t"
+#else
+ "wsbh %[temp4], %[temp4] \n\t"
+ "ush %[temp4], 0(%[dst]) \n\t"
+#endif
+ "bne %[src], %[p_loop2_end], 1b \n\t"
+ " addiu %[dst], %[dst], 2 \n\t"
+ "2: \n\t"
+ ".set pop \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
+ [dst]"+&r"(dst), [src]"+&r"(src)
+ : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)
+ : "memory"
+ );
+}
+
+static void ConvertBGRAToBGR(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ int temp0, temp1, temp2, temp3;
+ const uint32_t* const p_loop1_end = src + (num_pixels & ~3);
+ const uint32_t* const p_loop2_end = src + num_pixels;
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "beq %[src], %[p_loop1_end], 3f \n\t"
+ " nop \n\t"
+ "0: \n\t"
+ "lw %[temp0], 0(%[src]) \n\t"
+ "lw %[temp1], 4(%[src]) \n\t"
+ "lw %[temp2], 8(%[src]) \n\t"
+ "lw %[temp3], 12(%[src]) \n\t"
+ "ins %[temp0], %[temp1], 24, 8 \n\t"
+ "sra %[temp1], %[temp1], 8 \n\t"
+ "ins %[temp1], %[temp2], 16, 16 \n\t"
+ "sll %[temp2], %[temp2], 8 \n\t"
+ "balign %[temp3], %[temp2], 1 \n\t"
+ "addiu %[src], %[src], 16 \n\t"
+ "usw %[temp0], 0(%[dst]) \n\t"
+ "usw %[temp1], 4(%[dst]) \n\t"
+ "usw %[temp3], 8(%[dst]) \n\t"
+ "bne %[src], %[p_loop1_end], 0b \n\t"
+ " addiu %[dst], %[dst], 12 \n\t"
+ "3: \n\t"
+ "beq %[src], %[p_loop2_end], 2f \n\t"
+ " nop \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[src]) \n\t"
+ "addiu %[src], %[src], 4 \n\t"
+ "addiu %[dst], %[dst], 3 \n\t"
+ "ush %[temp0], -3(%[dst]) \n\t"
+ "sra %[temp0], %[temp0], 16 \n\t"
+ "bne %[src], %[p_loop2_end], 1b \n\t"
+ " sb %[temp0], -1(%[dst]) \n\t"
+ "2: \n\t"
+ ".set pop \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src)
+ : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)
+ : "memory"
+ );
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8LDspInitMIPSdspR2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitMIPSdspR2(void) {
+ VP8LMapColor32b = MapARGB;
+ VP8LMapColor8b = MapAlpha;
+ VP8LPredictors[5] = Predictor5;
+ VP8LPredictors[6] = Predictor6;
+ VP8LPredictors[7] = Predictor7;
+ VP8LPredictors[8] = Predictor8;
+ VP8LPredictors[9] = Predictor9;
+ VP8LPredictors[10] = Predictor10;
+ VP8LPredictors[11] = Predictor11;
+ VP8LPredictors[12] = Predictor12;
+ VP8LPredictors[13] = Predictor13;
+ VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed;
+ VP8LTransformColorInverse = TransformColorInverse;
+ VP8LConvertBGRAToRGB = ConvertBGRAToRGB;
+ VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA;
+ VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444;
+ VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565;
+ VP8LConvertBGRAToBGR = ConvertBGRAToBGR;
+}
+
+#else // !WEBP_USE_MIPS_DSP_R2
+
+WEBP_DSP_INIT_STUB(VP8LDspInitMIPSdspR2)
+
+#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/lossless_neon.c b/drivers/webp/dsp/lossless_neon.c
new file mode 100644
index 0000000000..6faccb8f97
--- /dev/null
+++ b/drivers/webp/dsp/lossless_neon.c
@@ -0,0 +1,269 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// NEON variant of methods for lossless decoder
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_NEON)
+
+#include <arm_neon.h>
+
+#include "./lossless.h"
+#include "./neon.h"
+
+//------------------------------------------------------------------------------
+// Colorspace conversion functions
+
+#if !defined(WORK_AROUND_GCC)
+// gcc 4.6.0 had some trouble (NDK-r9) with this code. We only use it for
+// gcc-4.8.x at least.
+static void ConvertBGRAToRGBA(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const uint32_t* const end = src + (num_pixels & ~15);
+ for (; src < end; src += 16) {
+ uint8x16x4_t pixel = vld4q_u8((uint8_t*)src);
+ // swap B and R. (VSWP d0,d2 has no intrinsics equivalent!)
+ const uint8x16_t tmp = pixel.val[0];
+ pixel.val[0] = pixel.val[2];
+ pixel.val[2] = tmp;
+ vst4q_u8(dst, pixel);
+ dst += 64;
+ }
+ VP8LConvertBGRAToRGBA_C(src, num_pixels & 15, dst); // left-overs
+}
+
+static void ConvertBGRAToBGR(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const uint32_t* const end = src + (num_pixels & ~15);
+ for (; src < end; src += 16) {
+ const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src);
+ const uint8x16x3_t tmp = { { pixel.val[0], pixel.val[1], pixel.val[2] } };
+ vst3q_u8(dst, tmp);
+ dst += 48;
+ }
+ VP8LConvertBGRAToBGR_C(src, num_pixels & 15, dst); // left-overs
+}
+
+static void ConvertBGRAToRGB(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const uint32_t* const end = src + (num_pixels & ~15);
+ for (; src < end; src += 16) {
+ const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src);
+ const uint8x16x3_t tmp = { { pixel.val[2], pixel.val[1], pixel.val[0] } };
+ vst3q_u8(dst, tmp);
+ dst += 48;
+ }
+ VP8LConvertBGRAToRGB_C(src, num_pixels & 15, dst); // left-overs
+}
+
+#else // WORK_AROUND_GCC
+
+// gcc-4.6.0 fallback
+
+static const uint8_t kRGBAShuffle[8] = { 2, 1, 0, 3, 6, 5, 4, 7 };
+
+static void ConvertBGRAToRGBA(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const uint32_t* const end = src + (num_pixels & ~1);
+ const uint8x8_t shuffle = vld1_u8(kRGBAShuffle);
+ for (; src < end; src += 2) {
+ const uint8x8_t pixels = vld1_u8((uint8_t*)src);
+ vst1_u8(dst, vtbl1_u8(pixels, shuffle));
+ dst += 8;
+ }
+ VP8LConvertBGRAToRGBA_C(src, num_pixels & 1, dst); // left-overs
+}
+
+static const uint8_t kBGRShuffle[3][8] = {
+ { 0, 1, 2, 4, 5, 6, 8, 9 },
+ { 10, 12, 13, 14, 16, 17, 18, 20 },
+ { 21, 22, 24, 25, 26, 28, 29, 30 }
+};
+
+static void ConvertBGRAToBGR(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const uint32_t* const end = src + (num_pixels & ~7);
+ const uint8x8_t shuffle0 = vld1_u8(kBGRShuffle[0]);
+ const uint8x8_t shuffle1 = vld1_u8(kBGRShuffle[1]);
+ const uint8x8_t shuffle2 = vld1_u8(kBGRShuffle[2]);
+ for (; src < end; src += 8) {
+ uint8x8x4_t pixels;
+ INIT_VECTOR4(pixels,
+ vld1_u8((const uint8_t*)(src + 0)),
+ vld1_u8((const uint8_t*)(src + 2)),
+ vld1_u8((const uint8_t*)(src + 4)),
+ vld1_u8((const uint8_t*)(src + 6)));
+ vst1_u8(dst + 0, vtbl4_u8(pixels, shuffle0));
+ vst1_u8(dst + 8, vtbl4_u8(pixels, shuffle1));
+ vst1_u8(dst + 16, vtbl4_u8(pixels, shuffle2));
+ dst += 8 * 3;
+ }
+ VP8LConvertBGRAToBGR_C(src, num_pixels & 7, dst); // left-overs
+}
+
+static const uint8_t kRGBShuffle[3][8] = {
+ { 2, 1, 0, 6, 5, 4, 10, 9 },
+ { 8, 14, 13, 12, 18, 17, 16, 22 },
+ { 21, 20, 26, 25, 24, 30, 29, 28 }
+};
+
+static void ConvertBGRAToRGB(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const uint32_t* const end = src + (num_pixels & ~7);
+ const uint8x8_t shuffle0 = vld1_u8(kRGBShuffle[0]);
+ const uint8x8_t shuffle1 = vld1_u8(kRGBShuffle[1]);
+ const uint8x8_t shuffle2 = vld1_u8(kRGBShuffle[2]);
+ for (; src < end; src += 8) {
+ uint8x8x4_t pixels;
+ INIT_VECTOR4(pixels,
+ vld1_u8((const uint8_t*)(src + 0)),
+ vld1_u8((const uint8_t*)(src + 2)),
+ vld1_u8((const uint8_t*)(src + 4)),
+ vld1_u8((const uint8_t*)(src + 6)));
+ vst1_u8(dst + 0, vtbl4_u8(pixels, shuffle0));
+ vst1_u8(dst + 8, vtbl4_u8(pixels, shuffle1));
+ vst1_u8(dst + 16, vtbl4_u8(pixels, shuffle2));
+ dst += 8 * 3;
+ }
+ VP8LConvertBGRAToRGB_C(src, num_pixels & 7, dst); // left-overs
+}
+
+#endif // !WORK_AROUND_GCC
+
+//------------------------------------------------------------------------------
+// Subtract-Green Transform
+
+// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use
+// non-standard versions there.
+#if defined(__APPLE__) && defined(__aarch64__) && \
+ defined(__apple_build_version__) && (__apple_build_version__< 6020037)
+#define USE_VTBLQ
+#endif
+
+#ifdef USE_VTBLQ
+// 255 = byte will be zeroed
+static const uint8_t kGreenShuffle[16] = {
+ 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255
+};
+
+static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb,
+ const uint8x16_t shuffle) {
+ return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)),
+ vtbl1q_u8(argb, vget_high_u8(shuffle)));
+}
+#else // !USE_VTBLQ
+// 255 = byte will be zeroed
+static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 };
+
+static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb,
+ const uint8x8_t shuffle) {
+ return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle),
+ vtbl1_u8(vget_high_u8(argb), shuffle));
+}
+#endif // USE_VTBLQ
+
+static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) {
+ const uint32_t* const end = argb_data + (num_pixels & ~3);
+#ifdef USE_VTBLQ
+ const uint8x16_t shuffle = vld1q_u8(kGreenShuffle);
+#else
+ const uint8x8_t shuffle = vld1_u8(kGreenShuffle);
+#endif
+ for (; argb_data < end; argb_data += 4) {
+ const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data);
+ const uint8x16_t greens = DoGreenShuffle(argb, shuffle);
+ vst1q_u8((uint8_t*)argb_data, vaddq_u8(argb, greens));
+ }
+ // fallthrough and finish off with plain-C
+ VP8LAddGreenToBlueAndRed_C(argb_data, num_pixels & 3);
+}
+
+//------------------------------------------------------------------------------
+// Color Transform
+
+static void TransformColorInverse(const VP8LMultipliers* const m,
+ uint32_t* argb_data, int num_pixels) {
+ // sign-extended multiplying constants, pre-shifted by 6.
+#define CST(X) (((int16_t)(m->X << 8)) >> 6)
+ const int16_t rb[8] = {
+ CST(green_to_blue_), CST(green_to_red_),
+ CST(green_to_blue_), CST(green_to_red_),
+ CST(green_to_blue_), CST(green_to_red_),
+ CST(green_to_blue_), CST(green_to_red_)
+ };
+ const int16x8_t mults_rb = vld1q_s16(rb);
+ const int16_t b2[8] = {
+ 0, CST(red_to_blue_), 0, CST(red_to_blue_),
+ 0, CST(red_to_blue_), 0, CST(red_to_blue_),
+ };
+ const int16x8_t mults_b2 = vld1q_s16(b2);
+#undef CST
+#ifdef USE_VTBLQ
+ static const uint8_t kg0g0[16] = {
+ 255, 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13
+ };
+ const uint8x16_t shuffle = vld1q_u8(kg0g0);
+#else
+ static const uint8_t k0g0g[8] = { 255, 1, 255, 1, 255, 5, 255, 5 };
+ const uint8x8_t shuffle = vld1_u8(k0g0g);
+#endif
+ const uint32x4_t mask_ag = vdupq_n_u32(0xff00ff00u);
+ int i;
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const uint8x16_t in = vld1q_u8((uint8_t*)(argb_data + i));
+ const uint32x4_t a0g0 = vandq_u32(vreinterpretq_u32_u8(in), mask_ag);
+ // 0 g 0 g
+ const uint8x16_t greens = DoGreenShuffle(in, shuffle);
+ // x dr x db1
+ const int16x8_t A = vqdmulhq_s16(vreinterpretq_s16_u8(greens), mults_rb);
+ // x r' x b'
+ const int8x16_t B = vaddq_s8(vreinterpretq_s8_u8(in),
+ vreinterpretq_s8_s16(A));
+ // r' 0 b' 0
+ const int16x8_t C = vshlq_n_s16(vreinterpretq_s16_s8(B), 8);
+ // x db2 0 0
+ const int16x8_t D = vqdmulhq_s16(C, mults_b2);
+ // 0 x db2 0
+ const uint32x4_t E = vshrq_n_u32(vreinterpretq_u32_s16(D), 8);
+ // r' x b'' 0
+ const int8x16_t F = vaddq_s8(vreinterpretq_s8_u32(E),
+ vreinterpretq_s8_s16(C));
+ // 0 r' 0 b''
+ const uint16x8_t G = vshrq_n_u16(vreinterpretq_u16_s8(F), 8);
+ const uint32x4_t out = vorrq_u32(vreinterpretq_u32_u16(G), a0g0);
+ vst1q_u32(argb_data + i, out);
+ }
+ // Fall-back to C-version for left-overs.
+ VP8LTransformColorInverse_C(m, argb_data + i, num_pixels - i);
+}
+
+#undef USE_VTBLQ
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8LDspInitNEON(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitNEON(void) {
+ VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA;
+ VP8LConvertBGRAToBGR = ConvertBGRAToBGR;
+ VP8LConvertBGRAToRGB = ConvertBGRAToRGB;
+
+ VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed;
+ VP8LTransformColorInverse = TransformColorInverse;
+}
+
+#else // !WEBP_USE_NEON
+
+WEBP_DSP_INIT_STUB(VP8LDspInitNEON)
+
+#endif // WEBP_USE_NEON
diff --git a/drivers/webp/dsp/lossless_sse2.c b/drivers/webp/dsp/lossless_sse2.c
new file mode 100644
index 0000000000..2d016c2911
--- /dev/null
+++ b/drivers/webp/dsp/lossless_sse2.c
@@ -0,0 +1,372 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// SSE2 variant of methods for lossless decoder
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_SSE2)
+#include <assert.h>
+#include <emmintrin.h>
+#include "./lossless.h"
+
+//------------------------------------------------------------------------------
+// Predictor Transform
+
+static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
+ uint32_t c2) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero);
+ const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero);
+ const __m128i C2 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c2), zero);
+ const __m128i V1 = _mm_add_epi16(C0, C1);
+ const __m128i V2 = _mm_sub_epi16(V1, C2);
+ const __m128i b = _mm_packus_epi16(V2, V2);
+ const uint32_t output = _mm_cvtsi128_si32(b);
+ return output;
+}
+
+static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
+ uint32_t c2) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero);
+ const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero);
+ const __m128i B0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c2), zero);
+ const __m128i avg = _mm_add_epi16(C1, C0);
+ const __m128i A0 = _mm_srli_epi16(avg, 1);
+ const __m128i A1 = _mm_sub_epi16(A0, B0);
+ const __m128i BgtA = _mm_cmpgt_epi16(B0, A0);
+ const __m128i A2 = _mm_sub_epi16(A1, BgtA);
+ const __m128i A3 = _mm_srai_epi16(A2, 1);
+ const __m128i A4 = _mm_add_epi16(A0, A3);
+ const __m128i A5 = _mm_packus_epi16(A4, A4);
+ const uint32_t output = _mm_cvtsi128_si32(A5);
+ return output;
+}
+
+static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
+ int pa_minus_pb;
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i A0 = _mm_cvtsi32_si128(a);
+ const __m128i B0 = _mm_cvtsi32_si128(b);
+ const __m128i C0 = _mm_cvtsi32_si128(c);
+ const __m128i AC0 = _mm_subs_epu8(A0, C0);
+ const __m128i CA0 = _mm_subs_epu8(C0, A0);
+ const __m128i BC0 = _mm_subs_epu8(B0, C0);
+ const __m128i CB0 = _mm_subs_epu8(C0, B0);
+ const __m128i AC = _mm_or_si128(AC0, CA0);
+ const __m128i BC = _mm_or_si128(BC0, CB0);
+ const __m128i pa = _mm_unpacklo_epi8(AC, zero); // |a - c|
+ const __m128i pb = _mm_unpacklo_epi8(BC, zero); // |b - c|
+ const __m128i diff = _mm_sub_epi16(pb, pa);
+ {
+ int16_t out[8];
+ _mm_storeu_si128((__m128i*)out, diff);
+ pa_minus_pb = out[0] + out[1] + out[2] + out[3];
+ }
+ return (pa_minus_pb <= 0) ? a : b;
+}
+
+static WEBP_INLINE __m128i Average2_128i(uint32_t a0, uint32_t a1) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i A0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a0), zero);
+ const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a1), zero);
+ const __m128i sum = _mm_add_epi16(A1, A0);
+ const __m128i avg = _mm_srli_epi16(sum, 1);
+ return avg;
+}
+
+static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
+ const __m128i avg = Average2_128i(a0, a1);
+ const __m128i A2 = _mm_packus_epi16(avg, avg);
+ const uint32_t output = _mm_cvtsi128_si32(A2);
+ return output;
+}
+
+static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i avg1 = Average2_128i(a0, a2);
+ const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a1), zero);
+ const __m128i sum = _mm_add_epi16(avg1, A1);
+ const __m128i avg2 = _mm_srli_epi16(sum, 1);
+ const __m128i A2 = _mm_packus_epi16(avg2, avg2);
+ const uint32_t output = _mm_cvtsi128_si32(A2);
+ return output;
+}
+
+static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
+ uint32_t a2, uint32_t a3) {
+ const __m128i avg1 = Average2_128i(a0, a1);
+ const __m128i avg2 = Average2_128i(a2, a3);
+ const __m128i sum = _mm_add_epi16(avg2, avg1);
+ const __m128i avg3 = _mm_srli_epi16(sum, 1);
+ const __m128i A0 = _mm_packus_epi16(avg3, avg3);
+ const uint32_t output = _mm_cvtsi128_si32(A0);
+ return output;
+}
+
+static uint32_t Predictor5(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = Average3(left, top[0], top[1]);
+ return pred;
+}
+static uint32_t Predictor6(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = Average2(left, top[-1]);
+ return pred;
+}
+static uint32_t Predictor7(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = Average2(left, top[0]);
+ return pred;
+}
+static uint32_t Predictor8(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = Average2(top[-1], top[0]);
+ (void)left;
+ return pred;
+}
+static uint32_t Predictor9(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = Average2(top[0], top[1]);
+ (void)left;
+ return pred;
+}
+static uint32_t Predictor10(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = Average4(left, top[-1], top[0], top[1]);
+ return pred;
+}
+static uint32_t Predictor11(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = Select(top[0], left, top[-1]);
+ return pred;
+}
+static uint32_t Predictor12(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]);
+ return pred;
+}
+static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]);
+ return pred;
+}
+
+//------------------------------------------------------------------------------
+// Subtract-Green Transform
+
+static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) {
+ int i;
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb
+ const __m128i A = _mm_srli_epi16(in, 8); // 0 a 0 g
+ const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0));
+ const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // 0g0g
+ const __m128i out = _mm_add_epi8(in, C);
+ _mm_storeu_si128((__m128i*)&argb_data[i], out);
+ }
+ // fallthrough and finish off with plain-C
+ VP8LAddGreenToBlueAndRed_C(argb_data + i, num_pixels - i);
+}
+
+//------------------------------------------------------------------------------
+// Color Transform
+
+static void TransformColorInverse(const VP8LMultipliers* const m,
+ uint32_t* argb_data, int num_pixels) {
+ // sign-extended multiplying constants, pre-shifted by 5.
+#define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend
+ const __m128i mults_rb = _mm_set_epi16(
+ CST(green_to_red_), CST(green_to_blue_),
+ CST(green_to_red_), CST(green_to_blue_),
+ CST(green_to_red_), CST(green_to_blue_),
+ CST(green_to_red_), CST(green_to_blue_));
+ const __m128i mults_b2 = _mm_set_epi16(
+ CST(red_to_blue_), 0, CST(red_to_blue_), 0,
+ CST(red_to_blue_), 0, CST(red_to_blue_), 0);
+#undef CST
+ const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks
+ int i;
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb
+ const __m128i A = _mm_and_si128(in, mask_ag); // a 0 g 0
+ const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0));
+ const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // g0g0
+ const __m128i D = _mm_mulhi_epi16(C, mults_rb); // x dr x db1
+ const __m128i E = _mm_add_epi8(in, D); // x r' x b'
+ const __m128i F = _mm_slli_epi16(E, 8); // r' 0 b' 0
+ const __m128i G = _mm_mulhi_epi16(F, mults_b2); // x db2 0 0
+ const __m128i H = _mm_srli_epi32(G, 8); // 0 x db2 0
+ const __m128i I = _mm_add_epi8(H, F); // r' x b'' 0
+ const __m128i J = _mm_srli_epi16(I, 8); // 0 r' 0 b''
+ const __m128i out = _mm_or_si128(J, A);
+ _mm_storeu_si128((__m128i*)&argb_data[i], out);
+ }
+ // Fall-back to C-version for left-overs.
+ VP8LTransformColorInverse_C(m, argb_data + i, num_pixels - i);
+}
+
+//------------------------------------------------------------------------------
+// Color-space conversion functions
+
+static void ConvertBGRAToRGBA(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const __m128i* in = (const __m128i*)src;
+ __m128i* out = (__m128i*)dst;
+ while (num_pixels >= 8) {
+ const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3
+ const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7
+ const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4...
+ const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6...
+ const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6...
+ const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7...
+ const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7
+ const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7
+ const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7
+ const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7
+ const __m128i rg0 = _mm_unpacklo_epi8(rb0, ga0); // r0g0r1g1 ... r6g6r7g7
+ const __m128i ba0 = _mm_unpackhi_epi8(rb0, ga0); // b0a0b1a1 ... b6a6b7a7
+ const __m128i rgba0 = _mm_unpacklo_epi16(rg0, ba0); // rgba0|rgba1...
+ const __m128i rgba4 = _mm_unpackhi_epi16(rg0, ba0); // rgba4|rgba5...
+ _mm_storeu_si128(out++, rgba0);
+ _mm_storeu_si128(out++, rgba4);
+ num_pixels -= 8;
+ }
+ // left-overs
+ VP8LConvertBGRAToRGBA_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
+}
+
+static void ConvertBGRAToRGBA4444(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const __m128i mask_0x0f = _mm_set1_epi8(0x0f);
+ const __m128i mask_0xf0 = _mm_set1_epi8(0xf0);
+ const __m128i* in = (const __m128i*)src;
+ __m128i* out = (__m128i*)dst;
+ while (num_pixels >= 8) {
+ const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3
+ const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7
+ const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4...
+ const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6...
+ const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6...
+ const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7...
+ const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7
+ const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7
+ const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7
+ const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7
+ const __m128i ga1 = _mm_srli_epi16(ga0, 4); // g0-|g1-|...|a6-|a7-
+ const __m128i rb1 = _mm_and_si128(rb0, mask_0xf0); // -r0|-r1|...|-b6|-a7
+ const __m128i ga2 = _mm_and_si128(ga1, mask_0x0f); // g0-|g1-|...|a6-|a7-
+ const __m128i rgba0 = _mm_or_si128(ga2, rb1); // rg0..rg7 | ba0..ba7
+ const __m128i rgba1 = _mm_srli_si128(rgba0, 8); // ba0..ba7 | 0
+#ifdef WEBP_SWAP_16BIT_CSP
+ const __m128i rgba = _mm_unpacklo_epi8(rgba1, rgba0); // barg0...barg7
+#else
+ const __m128i rgba = _mm_unpacklo_epi8(rgba0, rgba1); // rgba0...rgba7
+#endif
+ _mm_storeu_si128(out++, rgba);
+ num_pixels -= 8;
+ }
+ // left-overs
+ VP8LConvertBGRAToRGBA4444_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
+}
+
+static void ConvertBGRAToRGB565(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const __m128i mask_0xe0 = _mm_set1_epi8(0xe0);
+ const __m128i mask_0xf8 = _mm_set1_epi8(0xf8);
+ const __m128i mask_0x07 = _mm_set1_epi8(0x07);
+ const __m128i* in = (const __m128i*)src;
+ __m128i* out = (__m128i*)dst;
+ while (num_pixels >= 8) {
+ const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3
+ const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7
+ const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4...
+ const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6...
+ const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6...
+ const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7...
+ const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7
+ const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7
+ const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7
+ const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7
+ const __m128i rb1 = _mm_and_si128(rb0, mask_0xf8); // -r0..-r7|-b0..-b7
+ const __m128i g_lo1 = _mm_srli_epi16(ga0, 5);
+ const __m128i g_lo2 = _mm_and_si128(g_lo1, mask_0x07); // g0-...g7-|xx (3b)
+ const __m128i g_hi1 = _mm_slli_epi16(ga0, 3);
+ const __m128i g_hi2 = _mm_and_si128(g_hi1, mask_0xe0); // -g0...-g7|xx (3b)
+ const __m128i b0 = _mm_srli_si128(rb1, 8); // -b0...-b7|0
+ const __m128i rg1 = _mm_or_si128(rb1, g_lo2); // gr0...gr7|xx
+ const __m128i b1 = _mm_srli_epi16(b0, 3);
+ const __m128i gb1 = _mm_or_si128(b1, g_hi2); // bg0...bg7|xx
+#ifdef WEBP_SWAP_16BIT_CSP
+ const __m128i rgba = _mm_unpacklo_epi8(gb1, rg1); // rggb0...rggb7
+#else
+ const __m128i rgba = _mm_unpacklo_epi8(rg1, gb1); // bgrb0...bgrb7
+#endif
+ _mm_storeu_si128(out++, rgba);
+ num_pixels -= 8;
+ }
+ // left-overs
+ VP8LConvertBGRAToRGB565_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
+}
+
+static void ConvertBGRAToBGR(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const __m128i mask_l = _mm_set_epi32(0, 0x00ffffff, 0, 0x00ffffff);
+ const __m128i mask_h = _mm_set_epi32(0x00ffffff, 0, 0x00ffffff, 0);
+ const __m128i* in = (const __m128i*)src;
+ const uint8_t* const end = dst + num_pixels * 3;
+ // the last storel_epi64 below writes 8 bytes starting at offset 18
+ while (dst + 26 <= end) {
+ const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3
+ const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7
+ const __m128i a0l = _mm_and_si128(bgra0, mask_l); // bgr0|0|bgr0|0
+ const __m128i a4l = _mm_and_si128(bgra4, mask_l); // bgr0|0|bgr0|0
+ const __m128i a0h = _mm_and_si128(bgra0, mask_h); // 0|bgr0|0|bgr0
+ const __m128i a4h = _mm_and_si128(bgra4, mask_h); // 0|bgr0|0|bgr0
+ const __m128i b0h = _mm_srli_epi64(a0h, 8); // 000b|gr00|000b|gr00
+ const __m128i b4h = _mm_srli_epi64(a4h, 8); // 000b|gr00|000b|gr00
+ const __m128i c0 = _mm_or_si128(a0l, b0h); // rgbrgb00|rgbrgb00
+ const __m128i c4 = _mm_or_si128(a4l, b4h); // rgbrgb00|rgbrgb00
+ const __m128i c2 = _mm_srli_si128(c0, 8);
+ const __m128i c6 = _mm_srli_si128(c4, 8);
+ _mm_storel_epi64((__m128i*)(dst + 0), c0);
+ _mm_storel_epi64((__m128i*)(dst + 6), c2);
+ _mm_storel_epi64((__m128i*)(dst + 12), c4);
+ _mm_storel_epi64((__m128i*)(dst + 18), c6);
+ dst += 24;
+ num_pixels -= 8;
+ }
+ // left-overs
+ VP8LConvertBGRAToBGR_C((const uint32_t*)in, num_pixels, dst);
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8LDspInitSSE2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitSSE2(void) {
+ VP8LPredictors[5] = Predictor5;
+ VP8LPredictors[6] = Predictor6;
+ VP8LPredictors[7] = Predictor7;
+ VP8LPredictors[8] = Predictor8;
+ VP8LPredictors[9] = Predictor9;
+ VP8LPredictors[10] = Predictor10;
+ VP8LPredictors[11] = Predictor11;
+ VP8LPredictors[12] = Predictor12;
+ VP8LPredictors[13] = Predictor13;
+
+ VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed;
+ VP8LTransformColorInverse = TransformColorInverse;
+
+ VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA;
+ VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444;
+ VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565;
+ VP8LConvertBGRAToBGR = ConvertBGRAToBGR;
+}
+
+#else // !WEBP_USE_SSE2
+
+WEBP_DSP_INIT_STUB(VP8LDspInitSSE2)
+
+#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/mips_macro.h b/drivers/webp/dsp/mips_macro.h
new file mode 100644
index 0000000000..44aba9b71d
--- /dev/null
+++ b/drivers/webp/dsp/mips_macro.h
@@ -0,0 +1,200 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// MIPS common macros
+
+#ifndef WEBP_DSP_MIPS_MACRO_H_
+#define WEBP_DSP_MIPS_MACRO_H_
+
+#if defined(__GNUC__) && defined(__ANDROID__) && LOCAL_GCC_VERSION == 0x409
+#define WORK_AROUND_GCC
+#endif
+
+#define STR(s) #s
+#define XSTR(s) STR(s)
+
+// O0[31..16 | 15..0] = I0[31..16 | 15..0] + I1[31..16 | 15..0]
+// O1[31..16 | 15..0] = I0[31..16 | 15..0] - I1[31..16 | 15..0]
+// O - output
+// I - input (macro doesn't change it)
+#define ADD_SUB_HALVES(O0, O1, \
+ I0, I1) \
+ "addq.ph %[" #O0 "], %[" #I0 "], %[" #I1 "] \n\t" \
+ "subq.ph %[" #O1 "], %[" #I0 "], %[" #I1 "] \n\t"
+
+// O - output
+// I - input (macro doesn't change it)
+// I[0/1] - offset in bytes
+#define LOAD_IN_X2(O0, O1, \
+ I0, I1) \
+ "lh %[" #O0 "], " #I0 "(%[in]) \n\t" \
+ "lh %[" #O1 "], " #I1 "(%[in]) \n\t"
+
+// I0 - location
+// I1..I9 - offsets in bytes
+#define LOAD_WITH_OFFSET_X4(O0, O1, O2, O3, \
+ I0, I1, I2, I3, I4, I5, I6, I7, I8, I9) \
+ "ulw %[" #O0 "], " #I1 "+" XSTR(I9) "*" #I5 "(%[" #I0 "]) \n\t" \
+ "ulw %[" #O1 "], " #I2 "+" XSTR(I9) "*" #I6 "(%[" #I0 "]) \n\t" \
+ "ulw %[" #O2 "], " #I3 "+" XSTR(I9) "*" #I7 "(%[" #I0 "]) \n\t" \
+ "ulw %[" #O3 "], " #I4 "+" XSTR(I9) "*" #I8 "(%[" #I0 "]) \n\t"
+
+// O - output
+// IO - input/output
+// I - input (macro doesn't change it)
+#define MUL_SHIFT_SUM(O0, O1, O2, O3, O4, O5, O6, O7, \
+ IO0, IO1, IO2, IO3, \
+ I0, I1, I2, I3, I4, I5, I6, I7) \
+ "mul %[" #O0 "], %[" #I0 "], %[kC2] \n\t" \
+ "mul %[" #O1 "], %[" #I0 "], %[kC1] \n\t" \
+ "mul %[" #O2 "], %[" #I1 "], %[kC2] \n\t" \
+ "mul %[" #O3 "], %[" #I1 "], %[kC1] \n\t" \
+ "mul %[" #O4 "], %[" #I2 "], %[kC2] \n\t" \
+ "mul %[" #O5 "], %[" #I2 "], %[kC1] \n\t" \
+ "mul %[" #O6 "], %[" #I3 "], %[kC2] \n\t" \
+ "mul %[" #O7 "], %[" #I3 "], %[kC1] \n\t" \
+ "sra %[" #O0 "], %[" #O0 "], 16 \n\t" \
+ "sra %[" #O1 "], %[" #O1 "], 16 \n\t" \
+ "sra %[" #O2 "], %[" #O2 "], 16 \n\t" \
+ "sra %[" #O3 "], %[" #O3 "], 16 \n\t" \
+ "sra %[" #O4 "], %[" #O4 "], 16 \n\t" \
+ "sra %[" #O5 "], %[" #O5 "], 16 \n\t" \
+ "sra %[" #O6 "], %[" #O6 "], 16 \n\t" \
+ "sra %[" #O7 "], %[" #O7 "], 16 \n\t" \
+ "addu %[" #IO0 "], %[" #IO0 "], %[" #I4 "] \n\t" \
+ "addu %[" #IO1 "], %[" #IO1 "], %[" #I5 "] \n\t" \
+ "subu %[" #IO2 "], %[" #IO2 "], %[" #I6 "] \n\t" \
+ "subu %[" #IO3 "], %[" #IO3 "], %[" #I7 "] \n\t"
+
+// O - output
+// I - input (macro doesn't change it)
+#define INSERT_HALF_X2(O0, O1, \
+ I0, I1) \
+ "ins %[" #O0 "], %[" #I0 "], 16, 16 \n\t" \
+ "ins %[" #O1 "], %[" #I1 "], 16, 16 \n\t"
+
+// O - output
+// I - input (macro doesn't change it)
+#define SRA_16(O0, O1, O2, O3, \
+ I0, I1, I2, I3) \
+ "sra %[" #O0 "], %[" #I0 "], 16 \n\t" \
+ "sra %[" #O1 "], %[" #I1 "], 16 \n\t" \
+ "sra %[" #O2 "], %[" #I2 "], 16 \n\t" \
+ "sra %[" #O3 "], %[" #I3 "], 16 \n\t"
+
+// temp0[31..16 | 15..0] = temp8[31..16 | 15..0] + temp12[31..16 | 15..0]
+// temp1[31..16 | 15..0] = temp8[31..16 | 15..0] - temp12[31..16 | 15..0]
+// temp0[31..16 | 15..0] = temp0[31..16 >> 3 | 15..0 >> 3]
+// temp1[31..16 | 15..0] = temp1[31..16 >> 3 | 15..0 >> 3]
+// O - output
+// I - input (macro doesn't change it)
+#define SHIFT_R_SUM_X2(O0, O1, O2, O3, O4, O5, O6, O7, \
+ I0, I1, I2, I3, I4, I5, I6, I7) \
+ "addq.ph %[" #O0 "], %[" #I0 "], %[" #I4 "] \n\t" \
+ "subq.ph %[" #O1 "], %[" #I0 "], %[" #I4 "] \n\t" \
+ "addq.ph %[" #O2 "], %[" #I1 "], %[" #I5 "] \n\t" \
+ "subq.ph %[" #O3 "], %[" #I1 "], %[" #I5 "] \n\t" \
+ "addq.ph %[" #O4 "], %[" #I2 "], %[" #I6 "] \n\t" \
+ "subq.ph %[" #O5 "], %[" #I2 "], %[" #I6 "] \n\t" \
+ "addq.ph %[" #O6 "], %[" #I3 "], %[" #I7 "] \n\t" \
+ "subq.ph %[" #O7 "], %[" #I3 "], %[" #I7 "] \n\t" \
+ "shra.ph %[" #O0 "], %[" #O0 "], 3 \n\t" \
+ "shra.ph %[" #O1 "], %[" #O1 "], 3 \n\t" \
+ "shra.ph %[" #O2 "], %[" #O2 "], 3 \n\t" \
+ "shra.ph %[" #O3 "], %[" #O3 "], 3 \n\t" \
+ "shra.ph %[" #O4 "], %[" #O4 "], 3 \n\t" \
+ "shra.ph %[" #O5 "], %[" #O5 "], 3 \n\t" \
+ "shra.ph %[" #O6 "], %[" #O6 "], 3 \n\t" \
+ "shra.ph %[" #O7 "], %[" #O7 "], 3 \n\t"
+
+// precrq.ph.w temp0, temp8, temp2
+// temp0 = temp8[31..16] | temp2[31..16]
+// ins temp2, temp8, 16, 16
+// temp2 = temp8[31..16] | temp2[15..0]
+// O - output
+// IO - input/output
+// I - input (macro doesn't change it)
+#define PACK_2_HALVES_TO_WORD(O0, O1, O2, O3, \
+ IO0, IO1, IO2, IO3, \
+ I0, I1, I2, I3) \
+ "precrq.ph.w %[" #O0 "], %[" #I0 "], %[" #IO0 "] \n\t" \
+ "precrq.ph.w %[" #O1 "], %[" #I1 "], %[" #IO1 "] \n\t" \
+ "ins %[" #IO0 "], %[" #I0 "], 16, 16 \n\t" \
+ "ins %[" #IO1 "], %[" #I1 "], 16, 16 \n\t" \
+ "precrq.ph.w %[" #O2 "], %[" #I2 "], %[" #IO2 "] \n\t" \
+ "precrq.ph.w %[" #O3 "], %[" #I3 "], %[" #IO3 "] \n\t" \
+ "ins %[" #IO2 "], %[" #I2 "], 16, 16 \n\t" \
+ "ins %[" #IO3 "], %[" #I3 "], 16, 16 \n\t"
+
+// preceu.ph.qbr temp0, temp8
+// temp0 = 0 | 0 | temp8[23..16] | temp8[7..0]
+// preceu.ph.qbl temp1, temp8
+// temp1 = temp8[23..16] | temp8[7..0] | 0 | 0
+// O - output
+// I - input (macro doesn't change it)
+#define CONVERT_2_BYTES_TO_HALF(O0, O1, O2, O3, O4, O5, O6, O7, \
+ I0, I1, I2, I3) \
+ "preceu.ph.qbr %[" #O0 "], %[" #I0 "] \n\t" \
+ "preceu.ph.qbl %[" #O1 "], %[" #I0 "] \n\t" \
+ "preceu.ph.qbr %[" #O2 "], %[" #I1 "] \n\t" \
+ "preceu.ph.qbl %[" #O3 "], %[" #I1 "] \n\t" \
+ "preceu.ph.qbr %[" #O4 "], %[" #I2 "] \n\t" \
+ "preceu.ph.qbl %[" #O5 "], %[" #I2 "] \n\t" \
+ "preceu.ph.qbr %[" #O6 "], %[" #I3 "] \n\t" \
+ "preceu.ph.qbl %[" #O7 "], %[" #I3 "] \n\t"
+
+// temp0[31..16 | 15..0] = temp0[31..16 | 15..0] + temp8[31..16 | 15..0]
+// temp0[31..16 | 15..0] = temp0[31..16 <<(s) 7 | 15..0 <<(s) 7]
+// temp1..temp7 same as temp0
+// precrqu_s.qb.ph temp0, temp1, temp0:
+// temp0 = temp1[31..24] | temp1[15..8] | temp0[31..24] | temp0[15..8]
+// store temp0 to dst
+// IO - input/output
+// I - input (macro doesn't change it)
+#define STORE_SAT_SUM_X2(IO0, IO1, IO2, IO3, IO4, IO5, IO6, IO7, \
+ I0, I1, I2, I3, I4, I5, I6, I7, \
+ I8, I9, I10, I11, I12, I13) \
+ "addq.ph %[" #IO0 "], %[" #IO0 "], %[" #I0 "] \n\t" \
+ "addq.ph %[" #IO1 "], %[" #IO1 "], %[" #I1 "] \n\t" \
+ "addq.ph %[" #IO2 "], %[" #IO2 "], %[" #I2 "] \n\t" \
+ "addq.ph %[" #IO3 "], %[" #IO3 "], %[" #I3 "] \n\t" \
+ "addq.ph %[" #IO4 "], %[" #IO4 "], %[" #I4 "] \n\t" \
+ "addq.ph %[" #IO5 "], %[" #IO5 "], %[" #I5 "] \n\t" \
+ "addq.ph %[" #IO6 "], %[" #IO6 "], %[" #I6 "] \n\t" \
+ "addq.ph %[" #IO7 "], %[" #IO7 "], %[" #I7 "] \n\t" \
+ "shll_s.ph %[" #IO0 "], %[" #IO0 "], 7 \n\t" \
+ "shll_s.ph %[" #IO1 "], %[" #IO1 "], 7 \n\t" \
+ "shll_s.ph %[" #IO2 "], %[" #IO2 "], 7 \n\t" \
+ "shll_s.ph %[" #IO3 "], %[" #IO3 "], 7 \n\t" \
+ "shll_s.ph %[" #IO4 "], %[" #IO4 "], 7 \n\t" \
+ "shll_s.ph %[" #IO5 "], %[" #IO5 "], 7 \n\t" \
+ "shll_s.ph %[" #IO6 "], %[" #IO6 "], 7 \n\t" \
+ "shll_s.ph %[" #IO7 "], %[" #IO7 "], 7 \n\t" \
+ "precrqu_s.qb.ph %[" #IO0 "], %[" #IO1 "], %[" #IO0 "] \n\t" \
+ "precrqu_s.qb.ph %[" #IO2 "], %[" #IO3 "], %[" #IO2 "] \n\t" \
+ "precrqu_s.qb.ph %[" #IO4 "], %[" #IO5 "], %[" #IO4 "] \n\t" \
+ "precrqu_s.qb.ph %[" #IO6 "], %[" #IO7 "], %[" #IO6 "] \n\t" \
+ "usw %[" #IO0 "], " XSTR(I13) "*" #I9 "(%[" #I8 "]) \n\t" \
+ "usw %[" #IO2 "], " XSTR(I13) "*" #I10 "(%[" #I8 "]) \n\t" \
+ "usw %[" #IO4 "], " XSTR(I13) "*" #I11 "(%[" #I8 "]) \n\t" \
+ "usw %[" #IO6 "], " XSTR(I13) "*" #I12 "(%[" #I8 "]) \n\t"
+
+#define OUTPUT_EARLY_CLOBBER_REGS_10() \
+ : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), \
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), \
+ [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), \
+ [temp10]"=&r"(temp10)
+
+#define OUTPUT_EARLY_CLOBBER_REGS_18() \
+ OUTPUT_EARLY_CLOBBER_REGS_10(), \
+ [temp11]"=&r"(temp11), [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), \
+ [temp14]"=&r"(temp14), [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), \
+ [temp17]"=&r"(temp17), [temp18]"=&r"(temp18)
+
+#endif // WEBP_DSP_MIPS_MACRO_H_
diff --git a/drivers/webp/dsp/neon.h b/drivers/webp/dsp/neon.h
new file mode 100644
index 0000000000..0a06266848
--- /dev/null
+++ b/drivers/webp/dsp/neon.h
@@ -0,0 +1,82 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// NEON common code.
+
+#ifndef WEBP_DSP_NEON_H_
+#define WEBP_DSP_NEON_H_
+
+#include <arm_neon.h>
+
+#include "./dsp.h"
+
+// Right now, some intrinsics functions seem slower, so we disable them
+// everywhere except aarch64 where the inline assembly is incompatible.
+#if defined(__aarch64__)
+#define WEBP_USE_INTRINSICS // use intrinsics when possible
+#endif
+
+#define INIT_VECTOR2(v, a, b) do { \
+ v.val[0] = a; \
+ v.val[1] = b; \
+} while (0)
+
+#define INIT_VECTOR3(v, a, b, c) do { \
+ v.val[0] = a; \
+ v.val[1] = b; \
+ v.val[2] = c; \
+} while (0)
+
+#define INIT_VECTOR4(v, a, b, c, d) do { \
+ v.val[0] = a; \
+ v.val[1] = b; \
+ v.val[2] = c; \
+ v.val[3] = d; \
+} while (0)
+
+// if using intrinsics, this flag avoids some functions that make gcc-4.6.3
+// crash ("internal compiler error: in immed_double_const, at emit-rtl.").
+// (probably similar to gcc.gnu.org/bugzilla/show_bug.cgi?id=48183)
+#if !(LOCAL_GCC_PREREQ(4,8) || defined(__aarch64__))
+#define WORK_AROUND_GCC
+#endif
+
+static WEBP_INLINE int32x4x4_t Transpose4x4(const int32x4x4_t rows) {
+ uint64x2x2_t row01, row23;
+
+ row01.val[0] = vreinterpretq_u64_s32(rows.val[0]);
+ row01.val[1] = vreinterpretq_u64_s32(rows.val[1]);
+ row23.val[0] = vreinterpretq_u64_s32(rows.val[2]);
+ row23.val[1] = vreinterpretq_u64_s32(rows.val[3]);
+ // Transpose 64-bit values (there's no vswp equivalent)
+ {
+ const uint64x1_t row0h = vget_high_u64(row01.val[0]);
+ const uint64x1_t row2l = vget_low_u64(row23.val[0]);
+ const uint64x1_t row1h = vget_high_u64(row01.val[1]);
+ const uint64x1_t row3l = vget_low_u64(row23.val[1]);
+ row01.val[0] = vcombine_u64(vget_low_u64(row01.val[0]), row2l);
+ row23.val[0] = vcombine_u64(row0h, vget_high_u64(row23.val[0]));
+ row01.val[1] = vcombine_u64(vget_low_u64(row01.val[1]), row3l);
+ row23.val[1] = vcombine_u64(row1h, vget_high_u64(row23.val[1]));
+ }
+ {
+ const int32x4x2_t out01 = vtrnq_s32(vreinterpretq_s32_u64(row01.val[0]),
+ vreinterpretq_s32_u64(row01.val[1]));
+ const int32x4x2_t out23 = vtrnq_s32(vreinterpretq_s32_u64(row23.val[0]),
+ vreinterpretq_s32_u64(row23.val[1]));
+ int32x4x4_t out;
+ out.val[0] = out01.val[0];
+ out.val[1] = out01.val[1];
+ out.val[2] = out23.val[0];
+ out.val[3] = out23.val[1];
+ return out;
+ }
+}
+
+#endif // WEBP_DSP_NEON_H_
diff --git a/drivers/webp/dsp/rescaler.c b/drivers/webp/dsp/rescaler.c
new file mode 100644
index 0000000000..bc743d5dc5
--- /dev/null
+++ b/drivers/webp/dsp/rescaler.c
@@ -0,0 +1,238 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Rescaling functions
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+
+#include "./dsp.h"
+#include "../utils/rescaler.h"
+
+//------------------------------------------------------------------------------
+// Implementations of critical functions ImportRow / ExportRow
+
+#define ROUNDER (WEBP_RESCALER_ONE >> 1)
+#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+
+//------------------------------------------------------------------------------
+// Row import
+
+void WebPRescalerImportRowExpandC(WebPRescaler* const wrk, const uint8_t* src) {
+ const int x_stride = wrk->num_channels;
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ int channel;
+ assert(!WebPRescalerInputDone(wrk));
+ assert(wrk->x_expand);
+ for (channel = 0; channel < x_stride; ++channel) {
+ int x_in = channel;
+ int x_out = channel;
+ // simple bilinear interpolation
+ int accum = wrk->x_add;
+ int left = src[x_in];
+ int right = (wrk->src_width > 1) ? src[x_in + x_stride] : left;
+ x_in += x_stride;
+ while (1) {
+ wrk->frow[x_out] = right * wrk->x_add + (left - right) * accum;
+ x_out += x_stride;
+ if (x_out >= x_out_max) break;
+ accum -= wrk->x_sub;
+ if (accum < 0) {
+ left = right;
+ x_in += x_stride;
+ assert(x_in < wrk->src_width * x_stride);
+ right = src[x_in];
+ accum += wrk->x_add;
+ }
+ }
+ assert(wrk->x_sub == 0 /* <- special case for src_width=1 */ || accum == 0);
+ }
+}
+
+void WebPRescalerImportRowShrinkC(WebPRescaler* const wrk, const uint8_t* src) {
+ const int x_stride = wrk->num_channels;
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ int channel;
+ assert(!WebPRescalerInputDone(wrk));
+ assert(!wrk->x_expand);
+ for (channel = 0; channel < x_stride; ++channel) {
+ int x_in = channel;
+ int x_out = channel;
+ uint32_t sum = 0;
+ int accum = 0;
+ while (x_out < x_out_max) {
+ uint32_t base = 0;
+ accum += wrk->x_add;
+ while (accum > 0) {
+ accum -= wrk->x_sub;
+ assert(x_in < wrk->src_width * x_stride);
+ base = src[x_in];
+ sum += base;
+ x_in += x_stride;
+ }
+ { // Emit next horizontal pixel.
+ const rescaler_t frac = base * (-accum);
+ wrk->frow[x_out] = sum * wrk->x_sub - frac;
+ // fresh fractional start for next pixel
+ sum = (int)MULT_FIX(frac, wrk->fx_scale);
+ }
+ x_out += x_stride;
+ }
+ assert(accum == 0);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Row export
+
+void WebPRescalerExportRowExpandC(WebPRescaler* const wrk) {
+ int x_out;
+ uint8_t* const dst = wrk->dst;
+ rescaler_t* const irow = wrk->irow;
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ const rescaler_t* const frow = wrk->frow;
+ assert(!WebPRescalerOutputDone(wrk));
+ assert(wrk->y_accum <= 0);
+ assert(wrk->y_expand);
+ assert(wrk->y_sub != 0);
+ if (wrk->y_accum == 0) {
+ for (x_out = 0; x_out < x_out_max; ++x_out) {
+ const uint32_t J = frow[x_out];
+ const int v = (int)MULT_FIX(J, wrk->fy_scale);
+ assert(v >= 0 && v <= 255);
+ dst[x_out] = v;
+ }
+ } else {
+ const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
+ const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B);
+ for (x_out = 0; x_out < x_out_max; ++x_out) {
+ const uint64_t I = (uint64_t)A * frow[x_out]
+ + (uint64_t)B * irow[x_out];
+ const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
+ const int v = (int)MULT_FIX(J, wrk->fy_scale);
+ assert(v >= 0 && v <= 255);
+ dst[x_out] = v;
+ }
+ }
+}
+
+void WebPRescalerExportRowShrinkC(WebPRescaler* const wrk) {
+ int x_out;
+ uint8_t* const dst = wrk->dst;
+ rescaler_t* const irow = wrk->irow;
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ const rescaler_t* const frow = wrk->frow;
+ const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum);
+ assert(!WebPRescalerOutputDone(wrk));
+ assert(wrk->y_accum <= 0);
+ assert(!wrk->y_expand);
+ if (yscale) {
+ for (x_out = 0; x_out < x_out_max; ++x_out) {
+ const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
+ const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
+ assert(v >= 0 && v <= 255);
+ dst[x_out] = v;
+ irow[x_out] = frac; // new fractional start
+ }
+ } else {
+ for (x_out = 0; x_out < x_out_max; ++x_out) {
+ const int v = (int)MULT_FIX(irow[x_out], wrk->fxy_scale);
+ assert(v >= 0 && v <= 255);
+ dst[x_out] = v;
+ irow[x_out] = 0;
+ }
+ }
+}
+
+#undef MULT_FIX
+#undef ROUNDER
+
+//------------------------------------------------------------------------------
+// Main entry calls
+
+void WebPRescalerImportRow(WebPRescaler* const wrk, const uint8_t* src) {
+ assert(!WebPRescalerInputDone(wrk));
+ if (!wrk->x_expand) {
+ WebPRescalerImportRowShrink(wrk, src);
+ } else {
+ WebPRescalerImportRowExpand(wrk, src);
+ }
+}
+
+void WebPRescalerExportRow(WebPRescaler* const wrk) {
+ if (wrk->y_accum <= 0) {
+ assert(!WebPRescalerOutputDone(wrk));
+ if (wrk->y_expand) {
+ WebPRescalerExportRowExpand(wrk);
+ } else if (wrk->fxy_scale) {
+ WebPRescalerExportRowShrink(wrk);
+ } else { // very special case for src = dst = 1x1
+ int i;
+ assert(wrk->src_width == 1 && wrk->dst_width <= 2);
+ assert(wrk->src_height == 1 && wrk->dst_height == 1);
+ for (i = 0; i < wrk->num_channels * wrk->dst_width; ++i) {
+ wrk->dst[i] = wrk->irow[i];
+ wrk->irow[i] = 0;
+ }
+ }
+ wrk->y_accum += wrk->y_add;
+ wrk->dst += wrk->dst_stride;
+ ++wrk->dst_y;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+WebPRescalerImportRowFunc WebPRescalerImportRowExpand;
+WebPRescalerImportRowFunc WebPRescalerImportRowShrink;
+
+WebPRescalerExportRowFunc WebPRescalerExportRowExpand;
+WebPRescalerExportRowFunc WebPRescalerExportRowShrink;
+
+extern void WebPRescalerDspInitSSE2(void);
+extern void WebPRescalerDspInitMIPS32(void);
+extern void WebPRescalerDspInitMIPSdspR2(void);
+extern void WebPRescalerDspInitNEON(void);
+
+static volatile VP8CPUInfo rescaler_last_cpuinfo_used =
+ (VP8CPUInfo)&rescaler_last_cpuinfo_used;
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInit(void) {
+ if (rescaler_last_cpuinfo_used == VP8GetCPUInfo) return;
+
+ WebPRescalerImportRowExpand = WebPRescalerImportRowExpandC;
+ WebPRescalerImportRowShrink = WebPRescalerImportRowShrinkC;
+ WebPRescalerExportRowExpand = WebPRescalerExportRowExpandC;
+ WebPRescalerExportRowShrink = WebPRescalerExportRowShrinkC;
+
+ if (VP8GetCPUInfo != NULL) {
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ WebPRescalerDspInitSSE2();
+ }
+#endif
+#if defined(WEBP_USE_NEON)
+ if (VP8GetCPUInfo(kNEON)) {
+ WebPRescalerDspInitNEON();
+ }
+#endif
+#if defined(WEBP_USE_MIPS32)
+ if (VP8GetCPUInfo(kMIPS32)) {
+ WebPRescalerDspInitMIPS32();
+ }
+#endif
+#if defined(WEBP_USE_MIPS_DSP_R2)
+ if (VP8GetCPUInfo(kMIPSdspR2)) {
+ WebPRescalerDspInitMIPSdspR2();
+ }
+#endif
+ }
+ rescaler_last_cpuinfo_used = VP8GetCPUInfo;
+}
diff --git a/drivers/webp/dsp/rescaler_mips32.c b/drivers/webp/dsp/rescaler_mips32.c
new file mode 100644
index 0000000000..ddaa391336
--- /dev/null
+++ b/drivers/webp/dsp/rescaler_mips32.c
@@ -0,0 +1,291 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// MIPS version of rescaling functions
+//
+// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS32)
+
+#include <assert.h>
+#include "../utils/rescaler.h"
+
+//------------------------------------------------------------------------------
+// Row import
+
+static void ImportRowShrink(WebPRescaler* const wrk, const uint8_t* src) {
+ const int x_stride = wrk->num_channels;
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ const int fx_scale = wrk->fx_scale;
+ const int x_add = wrk->x_add;
+ const int x_sub = wrk->x_sub;
+ const int x_stride1 = x_stride << 2;
+ int channel;
+ assert(!wrk->x_expand);
+ assert(!WebPRescalerInputDone(wrk));
+
+ for (channel = 0; channel < x_stride; ++channel) {
+ const uint8_t* src1 = src + channel;
+ rescaler_t* frow = wrk->frow + channel;
+ int temp1, temp2, temp3;
+ int base, frac, sum;
+ int accum, accum1;
+ int loop_c = x_out_max - channel;
+
+ __asm__ volatile (
+ "li %[temp1], 0x8000 \n\t"
+ "li %[temp2], 0x10000 \n\t"
+ "li %[sum], 0 \n\t"
+ "li %[accum], 0 \n\t"
+ "1: \n\t"
+ "addu %[accum], %[accum], %[x_add] \n\t"
+ "li %[base], 0 \n\t"
+ "blez %[accum], 3f \n\t"
+ "2: \n\t"
+ "lbu %[base], 0(%[src1]) \n\t"
+ "subu %[accum], %[accum], %[x_sub] \n\t"
+ "addu %[src1], %[src1], %[x_stride] \n\t"
+ "addu %[sum], %[sum], %[base] \n\t"
+ "bgtz %[accum], 2b \n\t"
+ "3: \n\t"
+ "negu %[accum1], %[accum] \n\t"
+ "mul %[frac], %[base], %[accum1] \n\t"
+ "mul %[temp3], %[sum], %[x_sub] \n\t"
+ "subu %[loop_c], %[loop_c], %[x_stride] \n\t"
+ "mult %[temp1], %[temp2] \n\t"
+ "maddu %[frac], %[fx_scale] \n\t"
+ "mfhi %[sum] \n\t"
+ "subu %[temp3], %[temp3], %[frac] \n\t"
+ "sw %[temp3], 0(%[frow]) \n\t"
+ "addu %[frow], %[frow], %[x_stride1] \n\t"
+ "bgtz %[loop_c], 1b \n\t"
+ : [accum]"=&r"(accum), [src1]"+r"(src1), [temp3]"=&r"(temp3),
+ [sum]"=&r"(sum), [base]"=&r"(base), [frac]"=&r"(frac),
+ [frow]"+r"(frow), [accum1]"=&r"(accum1),
+ [temp2]"=&r"(temp2), [temp1]"=&r"(temp1)
+ : [x_stride]"r"(x_stride), [fx_scale]"r"(fx_scale),
+ [x_sub]"r"(x_sub), [x_add]"r"(x_add),
+ [loop_c]"r"(loop_c), [x_stride1]"r"(x_stride1)
+ : "memory", "hi", "lo"
+ );
+ assert(accum == 0);
+ }
+}
+
+static void ImportRowExpand(WebPRescaler* const wrk, const uint8_t* src) {
+ const int x_stride = wrk->num_channels;
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ const int x_add = wrk->x_add;
+ const int x_sub = wrk->x_sub;
+ const int src_width = wrk->src_width;
+ const int x_stride1 = x_stride << 2;
+ int channel;
+ assert(wrk->x_expand);
+ assert(!WebPRescalerInputDone(wrk));
+
+ for (channel = 0; channel < x_stride; ++channel) {
+ const uint8_t* src1 = src + channel;
+ rescaler_t* frow = wrk->frow + channel;
+ int temp1, temp2, temp3, temp4;
+ int frac;
+ int accum;
+ int x_out = channel;
+
+ __asm__ volatile (
+ "addiu %[temp3], %[src_width], -1 \n\t"
+ "lbu %[temp2], 0(%[src1]) \n\t"
+ "addu %[src1], %[src1], %[x_stride] \n\t"
+ "bgtz %[temp3], 0f \n\t"
+ "addiu %[temp1], %[temp2], 0 \n\t"
+ "b 3f \n\t"
+ "0: \n\t"
+ "lbu %[temp1], 0(%[src1]) \n\t"
+ "3: \n\t"
+ "addiu %[accum], %[x_add], 0 \n\t"
+ "1: \n\t"
+ "subu %[temp3], %[temp2], %[temp1] \n\t"
+ "mul %[temp3], %[temp3], %[accum] \n\t"
+ "mul %[temp4], %[temp1], %[x_add] \n\t"
+ "addu %[temp3], %[temp4], %[temp3] \n\t"
+ "sw %[temp3], 0(%[frow]) \n\t"
+ "addu %[frow], %[frow], %[x_stride1] \n\t"
+ "addu %[x_out], %[x_out], %[x_stride] \n\t"
+ "subu %[temp3], %[x_out], %[x_out_max] \n\t"
+ "bgez %[temp3], 2f \n\t"
+ "subu %[accum], %[accum], %[x_sub] \n\t"
+ "bgez %[accum], 4f \n\t"
+ "addiu %[temp2], %[temp1], 0 \n\t"
+ "addu %[src1], %[src1], %[x_stride] \n\t"
+ "lbu %[temp1], 0(%[src1]) \n\t"
+ "addu %[accum], %[accum], %[x_add] \n\t"
+ "4: \n\t"
+ "b 1b \n\t"
+ "2: \n\t"
+ : [src1]"+r"(src1), [accum]"=&r"(accum), [temp1]"=&r"(temp1),
+ [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4),
+ [x_out]"+r"(x_out), [frac]"=&r"(frac), [frow]"+r"(frow)
+ : [x_stride]"r"(x_stride), [x_add]"r"(x_add), [x_sub]"r"(x_sub),
+ [x_stride1]"r"(x_stride1), [src_width]"r"(src_width),
+ [x_out_max]"r"(x_out_max)
+ : "memory", "hi", "lo"
+ );
+ assert(wrk->x_sub == 0 /* <- special case for src_width=1 */ || accum == 0);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Row export
+
+static void ExportRowExpand(WebPRescaler* const wrk) {
+ uint8_t* dst = wrk->dst;
+ rescaler_t* irow = wrk->irow;
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ const rescaler_t* frow = wrk->frow;
+ int temp0, temp1, temp3, temp4, temp5, loop_end;
+ const int temp2 = (int)wrk->fy_scale;
+ const int temp6 = x_out_max << 2;
+ assert(!WebPRescalerOutputDone(wrk));
+ assert(wrk->y_accum <= 0);
+ assert(wrk->y_expand);
+ assert(wrk->y_sub != 0);
+ if (wrk->y_accum == 0) {
+ __asm__ volatile (
+ "li %[temp3], 0x10000 \n\t"
+ "li %[temp4], 0x8000 \n\t"
+ "addu %[loop_end], %[frow], %[temp6] \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[frow]) \n\t"
+ "addiu %[dst], %[dst], 1 \n\t"
+ "addiu %[frow], %[frow], 4 \n\t"
+ "mult %[temp3], %[temp4] \n\t"
+ "maddu %[temp0], %[temp2] \n\t"
+ "mfhi %[temp5] \n\t"
+ "sb %[temp5], -1(%[dst]) \n\t"
+ "bne %[frow], %[loop_end], 1b \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow),
+ [dst]"+r"(dst), [loop_end]"=&r"(loop_end)
+ : [temp2]"r"(temp2), [temp6]"r"(temp6)
+ : "memory", "hi", "lo"
+ );
+ } else {
+ const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
+ const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B);
+ __asm__ volatile (
+ "li %[temp3], 0x10000 \n\t"
+ "li %[temp4], 0x8000 \n\t"
+ "addu %[loop_end], %[frow], %[temp6] \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[frow]) \n\t"
+ "lw %[temp1], 0(%[irow]) \n\t"
+ "addiu %[dst], %[dst], 1 \n\t"
+ "mult %[temp3], %[temp4] \n\t"
+ "maddu %[A], %[temp0] \n\t"
+ "maddu %[B], %[temp1] \n\t"
+ "addiu %[frow], %[frow], 4 \n\t"
+ "addiu %[irow], %[irow], 4 \n\t"
+ "mfhi %[temp5] \n\t"
+ "mult %[temp3], %[temp4] \n\t"
+ "maddu %[temp5], %[temp2] \n\t"
+ "mfhi %[temp5] \n\t"
+ "sb %[temp5], -1(%[dst]) \n\t"
+ "bne %[frow], %[loop_end], 1b \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow),
+ [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end)
+ : [temp2]"r"(temp2), [temp6]"r"(temp6), [A]"r"(A), [B]"r"(B)
+ : "memory", "hi", "lo"
+ );
+ }
+}
+
+static void ExportRowShrink(WebPRescaler* const wrk) {
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ uint8_t* dst = wrk->dst;
+ rescaler_t* irow = wrk->irow;
+ const rescaler_t* frow = wrk->frow;
+ const int yscale = wrk->fy_scale * (-wrk->y_accum);
+ int temp0, temp1, temp3, temp4, temp5, loop_end;
+ const int temp2 = (int)wrk->fxy_scale;
+ const int temp6 = x_out_max << 2;
+
+ assert(!WebPRescalerOutputDone(wrk));
+ assert(wrk->y_accum <= 0);
+ assert(!wrk->y_expand);
+ assert(wrk->fxy_scale != 0);
+ if (yscale) {
+ __asm__ volatile (
+ "li %[temp3], 0x10000 \n\t"
+ "li %[temp4], 0x8000 \n\t"
+ "addu %[loop_end], %[frow], %[temp6] \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[frow]) \n\t"
+ "mult %[temp3], %[temp4] \n\t"
+ "addiu %[frow], %[frow], 4 \n\t"
+ "maddu %[temp0], %[yscale] \n\t"
+ "mfhi %[temp1] \n\t"
+ "lw %[temp0], 0(%[irow]) \n\t"
+ "addiu %[dst], %[dst], 1 \n\t"
+ "addiu %[irow], %[irow], 4 \n\t"
+ "subu %[temp0], %[temp0], %[temp1] \n\t"
+ "mult %[temp3], %[temp4] \n\t"
+ "maddu %[temp0], %[temp2] \n\t"
+ "mfhi %[temp5] \n\t"
+ "sw %[temp1], -4(%[irow]) \n\t"
+ "sb %[temp5], -1(%[dst]) \n\t"
+ "bne %[frow], %[loop_end], 1b \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow),
+ [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end)
+ : [temp2]"r"(temp2), [yscale]"r"(yscale), [temp6]"r"(temp6)
+ : "memory", "hi", "lo"
+ );
+ } else {
+ __asm__ volatile (
+ "li %[temp3], 0x10000 \n\t"
+ "li %[temp4], 0x8000 \n\t"
+ "addu %[loop_end], %[irow], %[temp6] \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[irow]) \n\t"
+ "addiu %[dst], %[dst], 1 \n\t"
+ "addiu %[irow], %[irow], 4 \n\t"
+ "mult %[temp3], %[temp4] \n\t"
+ "maddu %[temp0], %[temp2] \n\t"
+ "mfhi %[temp5] \n\t"
+ "sw $zero, -4(%[irow]) \n\t"
+ "sb %[temp5], -1(%[dst]) \n\t"
+ "bne %[irow], %[loop_end], 1b \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [irow]"+r"(irow),
+ [dst]"+r"(dst), [loop_end]"=&r"(loop_end)
+ : [temp2]"r"(temp2), [temp6]"r"(temp6)
+ : "memory", "hi", "lo"
+ );
+ }
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void WebPRescalerDspInitMIPS32(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPS32(void) {
+ WebPRescalerImportRowExpand = ImportRowExpand;
+ WebPRescalerImportRowShrink = ImportRowShrink;
+ WebPRescalerExportRowExpand = ExportRowExpand;
+ WebPRescalerExportRowShrink = ExportRowShrink;
+}
+
+#else // !WEBP_USE_MIPS32
+
+WEBP_DSP_INIT_STUB(WebPRescalerDspInitMIPS32)
+
+#endif // WEBP_USE_MIPS32
diff --git a/drivers/webp/dsp/rescaler_mips_dsp_r2.c b/drivers/webp/dsp/rescaler_mips_dsp_r2.c
new file mode 100644
index 0000000000..b457d0a30a
--- /dev/null
+++ b/drivers/webp/dsp/rescaler_mips_dsp_r2.c
@@ -0,0 +1,314 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// MIPS version of rescaling functions
+//
+// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS_DSP_R2)
+
+#include <assert.h>
+#include "../utils/rescaler.h"
+
+#define ROUNDER (WEBP_RESCALER_ONE >> 1)
+#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+
+//------------------------------------------------------------------------------
+// Row export
+
+static void ExportRowShrink(WebPRescaler* const wrk) {
+ int i;
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ uint8_t* dst = wrk->dst;
+ rescaler_t* irow = wrk->irow;
+ const rescaler_t* frow = wrk->frow;
+ const int yscale = wrk->fy_scale * (-wrk->y_accum);
+ int temp0, temp1, temp2, temp3, temp4, temp5, loop_end;
+ const int temp7 = (int)wrk->fxy_scale;
+ const int temp6 = (x_out_max & ~0x3) << 2;
+ assert(!WebPRescalerOutputDone(wrk));
+ assert(wrk->y_accum <= 0);
+ assert(!wrk->y_expand);
+ assert(wrk->fxy_scale != 0);
+ if (yscale) {
+ if (x_out_max >= 4) {
+ int temp8, temp9, temp10, temp11;
+ __asm__ volatile (
+ "li %[temp3], 0x10000 \n\t"
+ "li %[temp4], 0x8000 \n\t"
+ "addu %[loop_end], %[frow], %[temp6] \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[frow]) \n\t"
+ "lw %[temp1], 4(%[frow]) \n\t"
+ "lw %[temp2], 8(%[frow]) \n\t"
+ "lw %[temp5], 12(%[frow]) \n\t"
+ "mult $ac0, %[temp3], %[temp4] \n\t"
+ "maddu $ac0, %[temp0], %[yscale] \n\t"
+ "mult $ac1, %[temp3], %[temp4] \n\t"
+ "maddu $ac1, %[temp1], %[yscale] \n\t"
+ "mult $ac2, %[temp3], %[temp4] \n\t"
+ "maddu $ac2, %[temp2], %[yscale] \n\t"
+ "mult $ac3, %[temp3], %[temp4] \n\t"
+ "maddu $ac3, %[temp5], %[yscale] \n\t"
+ "addiu %[frow], %[frow], 16 \n\t"
+ "mfhi %[temp0], $ac0 \n\t"
+ "mfhi %[temp1], $ac1 \n\t"
+ "mfhi %[temp2], $ac2 \n\t"
+ "mfhi %[temp5], $ac3 \n\t"
+ "lw %[temp8], 0(%[irow]) \n\t"
+ "lw %[temp9], 4(%[irow]) \n\t"
+ "lw %[temp10], 8(%[irow]) \n\t"
+ "lw %[temp11], 12(%[irow]) \n\t"
+ "addiu %[dst], %[dst], 4 \n\t"
+ "addiu %[irow], %[irow], 16 \n\t"
+ "subu %[temp8], %[temp8], %[temp0] \n\t"
+ "subu %[temp9], %[temp9], %[temp1] \n\t"
+ "subu %[temp10], %[temp10], %[temp2] \n\t"
+ "subu %[temp11], %[temp11], %[temp5] \n\t"
+ "mult $ac0, %[temp3], %[temp4] \n\t"
+ "maddu $ac0, %[temp8], %[temp7] \n\t"
+ "mult $ac1, %[temp3], %[temp4] \n\t"
+ "maddu $ac1, %[temp9], %[temp7] \n\t"
+ "mult $ac2, %[temp3], %[temp4] \n\t"
+ "maddu $ac2, %[temp10], %[temp7] \n\t"
+ "mult $ac3, %[temp3], %[temp4] \n\t"
+ "maddu $ac3, %[temp11], %[temp7] \n\t"
+ "mfhi %[temp8], $ac0 \n\t"
+ "mfhi %[temp9], $ac1 \n\t"
+ "mfhi %[temp10], $ac2 \n\t"
+ "mfhi %[temp11], $ac3 \n\t"
+ "sw %[temp0], -16(%[irow]) \n\t"
+ "sw %[temp1], -12(%[irow]) \n\t"
+ "sw %[temp2], -8(%[irow]) \n\t"
+ "sw %[temp5], -4(%[irow]) \n\t"
+ "sb %[temp8], -4(%[dst]) \n\t"
+ "sb %[temp9], -3(%[dst]) \n\t"
+ "sb %[temp10], -2(%[dst]) \n\t"
+ "sb %[temp11], -1(%[dst]) \n\t"
+ "bne %[frow], %[loop_end], 1b \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow),
+ [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end),
+ [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), [temp10]"=&r"(temp10),
+ [temp11]"=&r"(temp11), [temp2]"=&r"(temp2)
+ : [temp7]"r"(temp7), [yscale]"r"(yscale), [temp6]"r"(temp6)
+ : "memory", "hi", "lo", "$ac1hi", "$ac1lo",
+ "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo"
+ );
+ }
+ for (i = 0; i < (x_out_max & 0x3); ++i) {
+ const uint32_t frac = (uint32_t)MULT_FIX(*frow++, yscale);
+ const int v = (int)MULT_FIX(*irow - frac, wrk->fxy_scale);
+ assert(v >= 0 && v <= 255);
+ *dst++ = v;
+ *irow++ = frac; // new fractional start
+ }
+ } else {
+ if (x_out_max >= 4) {
+ __asm__ volatile (
+ "li %[temp3], 0x10000 \n\t"
+ "li %[temp4], 0x8000 \n\t"
+ "addu %[loop_end], %[irow], %[temp6] \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[irow]) \n\t"
+ "lw %[temp1], 4(%[irow]) \n\t"
+ "lw %[temp2], 8(%[irow]) \n\t"
+ "lw %[temp5], 12(%[irow]) \n\t"
+ "addiu %[dst], %[dst], 4 \n\t"
+ "addiu %[irow], %[irow], 16 \n\t"
+ "mult $ac0, %[temp3], %[temp4] \n\t"
+ "maddu $ac0, %[temp0], %[temp7] \n\t"
+ "mult $ac1, %[temp3], %[temp4] \n\t"
+ "maddu $ac1, %[temp1], %[temp7] \n\t"
+ "mult $ac2, %[temp3], %[temp4] \n\t"
+ "maddu $ac2, %[temp2], %[temp7] \n\t"
+ "mult $ac3, %[temp3], %[temp4] \n\t"
+ "maddu $ac3, %[temp5], %[temp7] \n\t"
+ "mfhi %[temp0], $ac0 \n\t"
+ "mfhi %[temp1], $ac1 \n\t"
+ "mfhi %[temp2], $ac2 \n\t"
+ "mfhi %[temp5], $ac3 \n\t"
+ "sw $zero, -16(%[irow]) \n\t"
+ "sw $zero, -12(%[irow]) \n\t"
+ "sw $zero, -8(%[irow]) \n\t"
+ "sw $zero, -4(%[irow]) \n\t"
+ "sb %[temp0], -4(%[dst]) \n\t"
+ "sb %[temp1], -3(%[dst]) \n\t"
+ "sb %[temp2], -2(%[dst]) \n\t"
+ "sb %[temp5], -1(%[dst]) \n\t"
+ "bne %[irow], %[loop_end], 1b \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [irow]"+r"(irow),
+ [dst]"+r"(dst), [loop_end]"=&r"(loop_end), [temp2]"=&r"(temp2)
+ : [temp7]"r"(temp7), [temp6]"r"(temp6)
+ : "memory", "hi", "lo", "$ac1hi", "$ac1lo",
+ "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo"
+ );
+ }
+ for (i = 0; i < (x_out_max & 0x3); ++i) {
+ const int v = (int)MULT_FIX(*irow, wrk->fxy_scale);
+ assert(v >= 0 && v <= 255);
+ *dst++ = v;
+ *irow++ = 0;
+ }
+ }
+}
+
+static void ExportRowExpand(WebPRescaler* const wrk) {
+ int i;
+ uint8_t* dst = wrk->dst;
+ rescaler_t* irow = wrk->irow;
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ const rescaler_t* frow = wrk->frow;
+ int temp0, temp1, temp2, temp3, temp4, temp5, loop_end;
+ const int temp6 = (x_out_max & ~0x3) << 2;
+ const int temp7 = (int)wrk->fy_scale;
+ assert(!WebPRescalerOutputDone(wrk));
+ assert(wrk->y_accum <= 0);
+ assert(wrk->y_expand);
+ assert(wrk->y_sub != 0);
+ if (wrk->y_accum == 0) {
+ if (x_out_max >= 4) {
+ __asm__ volatile (
+ "li %[temp4], 0x10000 \n\t"
+ "li %[temp5], 0x8000 \n\t"
+ "addu %[loop_end], %[frow], %[temp6] \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[frow]) \n\t"
+ "lw %[temp1], 4(%[frow]) \n\t"
+ "lw %[temp2], 8(%[frow]) \n\t"
+ "lw %[temp3], 12(%[frow]) \n\t"
+ "addiu %[dst], %[dst], 4 \n\t"
+ "addiu %[frow], %[frow], 16 \n\t"
+ "mult $ac0, %[temp4], %[temp5] \n\t"
+ "maddu $ac0, %[temp0], %[temp7] \n\t"
+ "mult $ac1, %[temp4], %[temp5] \n\t"
+ "maddu $ac1, %[temp1], %[temp7] \n\t"
+ "mult $ac2, %[temp4], %[temp5] \n\t"
+ "maddu $ac2, %[temp2], %[temp7] \n\t"
+ "mult $ac3, %[temp4], %[temp5] \n\t"
+ "maddu $ac3, %[temp3], %[temp7] \n\t"
+ "mfhi %[temp0], $ac0 \n\t"
+ "mfhi %[temp1], $ac1 \n\t"
+ "mfhi %[temp2], $ac2 \n\t"
+ "mfhi %[temp3], $ac3 \n\t"
+ "sb %[temp0], -4(%[dst]) \n\t"
+ "sb %[temp1], -3(%[dst]) \n\t"
+ "sb %[temp2], -2(%[dst]) \n\t"
+ "sb %[temp3], -1(%[dst]) \n\t"
+ "bne %[frow], %[loop_end], 1b \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow),
+ [dst]"+r"(dst), [loop_end]"=&r"(loop_end), [temp2]"=&r"(temp2)
+ : [temp7]"r"(temp7), [temp6]"r"(temp6)
+ : "memory", "hi", "lo", "$ac1hi", "$ac1lo",
+ "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo"
+ );
+ }
+ for (i = 0; i < (x_out_max & 0x3); ++i) {
+ const uint32_t J = *frow++;
+ const int v = (int)MULT_FIX(J, wrk->fy_scale);
+ assert(v >= 0 && v <= 255);
+ *dst++ = v;
+ }
+ } else {
+ const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
+ const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B);
+ if (x_out_max >= 4) {
+ int temp8, temp9, temp10, temp11;
+ __asm__ volatile (
+ "li %[temp8], 0x10000 \n\t"
+ "li %[temp9], 0x8000 \n\t"
+ "addu %[loop_end], %[frow], %[temp6] \n\t"
+ "1: \n\t"
+ "lw %[temp0], 0(%[frow]) \n\t"
+ "lw %[temp1], 4(%[frow]) \n\t"
+ "lw %[temp2], 8(%[frow]) \n\t"
+ "lw %[temp3], 12(%[frow]) \n\t"
+ "lw %[temp4], 0(%[irow]) \n\t"
+ "lw %[temp5], 4(%[irow]) \n\t"
+ "lw %[temp10], 8(%[irow]) \n\t"
+ "lw %[temp11], 12(%[irow]) \n\t"
+ "addiu %[dst], %[dst], 4 \n\t"
+ "mult $ac0, %[temp8], %[temp9] \n\t"
+ "maddu $ac0, %[A], %[temp0] \n\t"
+ "maddu $ac0, %[B], %[temp4] \n\t"
+ "mult $ac1, %[temp8], %[temp9] \n\t"
+ "maddu $ac1, %[A], %[temp1] \n\t"
+ "maddu $ac1, %[B], %[temp5] \n\t"
+ "mult $ac2, %[temp8], %[temp9] \n\t"
+ "maddu $ac2, %[A], %[temp2] \n\t"
+ "maddu $ac2, %[B], %[temp10] \n\t"
+ "mult $ac3, %[temp8], %[temp9] \n\t"
+ "maddu $ac3, %[A], %[temp3] \n\t"
+ "maddu $ac3, %[B], %[temp11] \n\t"
+ "addiu %[frow], %[frow], 16 \n\t"
+ "addiu %[irow], %[irow], 16 \n\t"
+ "mfhi %[temp0], $ac0 \n\t"
+ "mfhi %[temp1], $ac1 \n\t"
+ "mfhi %[temp2], $ac2 \n\t"
+ "mfhi %[temp3], $ac3 \n\t"
+ "mult $ac0, %[temp8], %[temp9] \n\t"
+ "maddu $ac0, %[temp0], %[temp7] \n\t"
+ "mult $ac1, %[temp8], %[temp9] \n\t"
+ "maddu $ac1, %[temp1], %[temp7] \n\t"
+ "mult $ac2, %[temp8], %[temp9] \n\t"
+ "maddu $ac2, %[temp2], %[temp7] \n\t"
+ "mult $ac3, %[temp8], %[temp9] \n\t"
+ "maddu $ac3, %[temp3], %[temp7] \n\t"
+ "mfhi %[temp0], $ac0 \n\t"
+ "mfhi %[temp1], $ac1 \n\t"
+ "mfhi %[temp2], $ac2 \n\t"
+ "mfhi %[temp3], $ac3 \n\t"
+ "sb %[temp0], -4(%[dst]) \n\t"
+ "sb %[temp1], -3(%[dst]) \n\t"
+ "sb %[temp2], -2(%[dst]) \n\t"
+ "sb %[temp3], -1(%[dst]) \n\t"
+ "bne %[frow], %[loop_end], 1b \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
+ [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow),
+ [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end),
+ [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), [temp10]"=&r"(temp10),
+ [temp11]"=&r"(temp11), [temp2]"=&r"(temp2)
+ : [temp7]"r"(temp7), [temp6]"r"(temp6), [A]"r"(A), [B]"r"(B)
+ : "memory", "hi", "lo", "$ac1hi", "$ac1lo",
+ "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo"
+ );
+ }
+ for (i = 0; i < (x_out_max & 0x3); ++i) {
+ const uint64_t I = (uint64_t)A * *frow++
+ + (uint64_t)B * *irow++;
+ const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
+ const int v = (int)MULT_FIX(J, wrk->fy_scale);
+ assert(v >= 0 && v <= 255);
+ *dst++ = v;
+ }
+ }
+}
+
+#undef MULT_FIX
+#undef ROUNDER
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void WebPRescalerDspInitMIPSdspR2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPSdspR2(void) {
+ WebPRescalerExportRowExpand = ExportRowExpand;
+ WebPRescalerExportRowShrink = ExportRowShrink;
+}
+
+#else // !WEBP_USE_MIPS_DSP_R2
+
+WEBP_DSP_INIT_STUB(WebPRescalerDspInitMIPSdspR2)
+
+#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/rescaler_neon.c b/drivers/webp/dsp/rescaler_neon.c
new file mode 100644
index 0000000000..16fd450ea3
--- /dev/null
+++ b/drivers/webp/dsp/rescaler_neon.c
@@ -0,0 +1,186 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// NEON version of rescaling functions
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_NEON)
+
+#include <arm_neon.h>
+#include <assert.h>
+#include "./neon.h"
+#include "../utils/rescaler.h"
+
+#define ROUNDER (WEBP_RESCALER_ONE >> 1)
+#define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+
+#define LOAD_32x4(SRC, DST) const uint32x4_t DST = vld1q_u32((SRC))
+#define LOAD_32x8(SRC, DST0, DST1) \
+ LOAD_32x4(SRC + 0, DST0); \
+ LOAD_32x4(SRC + 4, DST1)
+
+#define STORE_32x8(SRC0, SRC1, DST) do { \
+ vst1q_u32((DST) + 0, SRC0); \
+ vst1q_u32((DST) + 4, SRC1); \
+} while (0);
+
+#if (WEBP_RESCALER_RFIX == 32)
+#define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1))
+#define MULT_FIX(A, B) /* note: B is actualy scale>>1. See MAKE_HALF_CST */ \
+ vreinterpretq_u32_s32(vqrdmulhq_s32(vreinterpretq_s32_u32((A)), (B)))
+#else
+#error "MULT_FIX/WEBP_RESCALER_RFIX need some more work"
+#endif
+
+static uint32x4_t Interpolate(const rescaler_t* const frow,
+ const rescaler_t* const irow,
+ uint32_t A, uint32_t B) {
+ LOAD_32x4(frow, A0);
+ LOAD_32x4(irow, B0);
+ const uint64x2_t C0 = vmull_n_u32(vget_low_u32(A0), A);
+ const uint64x2_t C1 = vmull_n_u32(vget_high_u32(A0), A);
+ const uint64x2_t D0 = vmlal_n_u32(C0, vget_low_u32(B0), B);
+ const uint64x2_t D1 = vmlal_n_u32(C1, vget_high_u32(B0), B);
+ const uint32x4_t E = vcombine_u32(
+ vrshrn_n_u64(D0, WEBP_RESCALER_RFIX),
+ vrshrn_n_u64(D1, WEBP_RESCALER_RFIX));
+ return E;
+}
+
+static void RescalerExportRowExpand(WebPRescaler* const wrk) {
+ int x_out;
+ uint8_t* const dst = wrk->dst;
+ rescaler_t* const irow = wrk->irow;
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ const int max_span = x_out_max & ~7;
+ const rescaler_t* const frow = wrk->frow;
+ const uint32_t fy_scale = wrk->fy_scale;
+ const int32x4_t fy_scale_half = MAKE_HALF_CST(fy_scale);
+ assert(!WebPRescalerOutputDone(wrk));
+ assert(wrk->y_accum <= 0);
+ assert(wrk->y_expand);
+ assert(wrk->y_sub != 0);
+ if (wrk->y_accum == 0) {
+ for (x_out = 0; x_out < max_span; x_out += 8) {
+ LOAD_32x4(frow + x_out + 0, A0);
+ LOAD_32x4(frow + x_out + 4, A1);
+ const uint32x4_t B0 = MULT_FIX(A0, fy_scale_half);
+ const uint32x4_t B1 = MULT_FIX(A1, fy_scale_half);
+ const uint16x4_t C0 = vmovn_u32(B0);
+ const uint16x4_t C1 = vmovn_u32(B1);
+ const uint8x8_t D = vmovn_u16(vcombine_u16(C0, C1));
+ vst1_u8(dst + x_out, D);
+ }
+ for (; x_out < x_out_max; ++x_out) {
+ const uint32_t J = frow[x_out];
+ const int v = (int)MULT_FIX_C(J, fy_scale);
+ assert(v >= 0 && v <= 255);
+ dst[x_out] = v;
+ }
+ } else {
+ const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
+ const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B);
+ for (x_out = 0; x_out < max_span; x_out += 8) {
+ const uint32x4_t C0 =
+ Interpolate(frow + x_out + 0, irow + x_out + 0, A, B);
+ const uint32x4_t C1 =
+ Interpolate(frow + x_out + 4, irow + x_out + 4, A, B);
+ const uint32x4_t D0 = MULT_FIX(C0, fy_scale_half);
+ const uint32x4_t D1 = MULT_FIX(C1, fy_scale_half);
+ const uint16x4_t E0 = vmovn_u32(D0);
+ const uint16x4_t E1 = vmovn_u32(D1);
+ const uint8x8_t F = vmovn_u16(vcombine_u16(E0, E1));
+ vst1_u8(dst + x_out, F);
+ }
+ for (; x_out < x_out_max; ++x_out) {
+ const uint64_t I = (uint64_t)A * frow[x_out]
+ + (uint64_t)B * irow[x_out];
+ const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
+ const int v = (int)MULT_FIX_C(J, fy_scale);
+ assert(v >= 0 && v <= 255);
+ dst[x_out] = v;
+ }
+ }
+}
+
+static void RescalerExportRowShrink(WebPRescaler* const wrk) {
+ int x_out;
+ uint8_t* const dst = wrk->dst;
+ rescaler_t* const irow = wrk->irow;
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ const int max_span = x_out_max & ~7;
+ const rescaler_t* const frow = wrk->frow;
+ const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum);
+ const uint32_t fxy_scale = wrk->fxy_scale;
+ const uint32x4_t zero = vdupq_n_u32(0);
+ const int32x4_t yscale_half = MAKE_HALF_CST(yscale);
+ const int32x4_t fxy_scale_half = MAKE_HALF_CST(fxy_scale);
+ assert(!WebPRescalerOutputDone(wrk));
+ assert(wrk->y_accum <= 0);
+ assert(!wrk->y_expand);
+ if (yscale) {
+ for (x_out = 0; x_out < max_span; x_out += 8) {
+ LOAD_32x8(frow + x_out, in0, in1);
+ LOAD_32x8(irow + x_out, in2, in3);
+ const uint32x4_t A0 = MULT_FIX(in0, yscale_half);
+ const uint32x4_t A1 = MULT_FIX(in1, yscale_half);
+ const uint32x4_t B0 = vqsubq_u32(in2, A0);
+ const uint32x4_t B1 = vqsubq_u32(in3, A1);
+ const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half);
+ const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half);
+ const uint16x4_t D0 = vmovn_u32(C0);
+ const uint16x4_t D1 = vmovn_u32(C1);
+ const uint8x8_t E = vmovn_u16(vcombine_u16(D0, D1));
+ vst1_u8(dst + x_out, E);
+ STORE_32x8(A0, A1, irow + x_out);
+ }
+ for (; x_out < x_out_max; ++x_out) {
+ const uint32_t frac = (uint32_t)MULT_FIX_C(frow[x_out], yscale);
+ const int v = (int)MULT_FIX_C(irow[x_out] - frac, wrk->fxy_scale);
+ assert(v >= 0 && v <= 255);
+ dst[x_out] = v;
+ irow[x_out] = frac; // new fractional start
+ }
+ } else {
+ for (x_out = 0; x_out < max_span; x_out += 8) {
+ LOAD_32x8(irow + x_out, in0, in1);
+ const uint32x4_t A0 = MULT_FIX(in0, fxy_scale_half);
+ const uint32x4_t A1 = MULT_FIX(in1, fxy_scale_half);
+ const uint16x4_t B0 = vmovn_u32(A0);
+ const uint16x4_t B1 = vmovn_u32(A1);
+ const uint8x8_t C = vmovn_u16(vcombine_u16(B0, B1));
+ vst1_u8(dst + x_out, C);
+ STORE_32x8(zero, zero, irow + x_out);
+ }
+ for (; x_out < x_out_max; ++x_out) {
+ const int v = (int)MULT_FIX_C(irow[x_out], fxy_scale);
+ assert(v >= 0 && v <= 255);
+ dst[x_out] = v;
+ irow[x_out] = 0;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+extern void WebPRescalerDspInitNEON(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitNEON(void) {
+ WebPRescalerExportRowExpand = RescalerExportRowExpand;
+ WebPRescalerExportRowShrink = RescalerExportRowShrink;
+}
+
+#else // !WEBP_USE_NEON
+
+WEBP_DSP_INIT_STUB(WebPRescalerDspInitNEON)
+
+#endif // WEBP_USE_NEON
diff --git a/drivers/webp/dsp/rescaler_sse2.c b/drivers/webp/dsp/rescaler_sse2.c
new file mode 100644
index 0000000000..186edb653e
--- /dev/null
+++ b/drivers/webp/dsp/rescaler_sse2.c
@@ -0,0 +1,373 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// SSE2 Rescaling functions
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_SSE2)
+#include <emmintrin.h>
+
+#include <assert.h>
+#include "../utils/rescaler.h"
+
+//------------------------------------------------------------------------------
+// Implementations of critical functions ImportRow / ExportRow
+
+#define ROUNDER (WEBP_RESCALER_ONE >> 1)
+#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+
+// input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0
+static void LoadTwoPixels(const uint8_t* const src, __m128i* out) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH
+ const __m128i B = _mm_unpacklo_epi8(A, zero); // A0B0C0D0E0F0G0H0
+ const __m128i C = _mm_srli_si128(B, 8); // E0F0G0H0
+ *out = _mm_unpacklo_epi16(B, C);
+}
+
+// input: 8 bytes ABCDEFGH -> output: A0B0C0D0E0F0G0H0
+static void LoadHeightPixels(const uint8_t* const src, __m128i* out) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH
+ *out = _mm_unpacklo_epi8(A, zero);
+}
+
+static void RescalerImportRowExpandSSE2(WebPRescaler* const wrk,
+ const uint8_t* src) {
+ rescaler_t* frow = wrk->frow;
+ const rescaler_t* const frow_end = frow + wrk->dst_width * wrk->num_channels;
+ const int x_add = wrk->x_add;
+ int accum = x_add;
+ __m128i cur_pixels;
+
+ assert(!WebPRescalerInputDone(wrk));
+ assert(wrk->x_expand);
+ if (wrk->num_channels == 4) {
+ if (wrk->src_width < 2) {
+ WebPRescalerImportRowExpandC(wrk, src);
+ return;
+ }
+ LoadTwoPixels(src, &cur_pixels);
+ src += 4;
+ while (1) {
+ const __m128i mult = _mm_set1_epi32(((x_add - accum) << 16) | accum);
+ const __m128i out = _mm_madd_epi16(cur_pixels, mult);
+ _mm_storeu_si128((__m128i*)frow, out);
+ frow += 4;
+ if (frow >= frow_end) break;
+ accum -= wrk->x_sub;
+ if (accum < 0) {
+ LoadTwoPixels(src, &cur_pixels);
+ src += 4;
+ accum += x_add;
+ }
+ }
+ } else {
+ int left;
+ const uint8_t* const src_limit = src + wrk->src_width - 8;
+ if (wrk->src_width < 8) {
+ WebPRescalerImportRowExpandC(wrk, src);
+ return;
+ }
+ LoadHeightPixels(src, &cur_pixels);
+ src += 7;
+ left = 7;
+ while (1) {
+ const __m128i mult = _mm_cvtsi32_si128(((x_add - accum) << 16) | accum);
+ const __m128i out = _mm_madd_epi16(cur_pixels, mult);
+ *(uint32_t*)frow = _mm_cvtsi128_si32(out);
+ frow += 1;
+ if (frow >= frow_end) break;
+ accum -= wrk->x_sub;
+ if (accum < 0) {
+ if (--left) {
+ cur_pixels = _mm_srli_si128(cur_pixels, 2);
+ } else if (src <= src_limit) {
+ LoadHeightPixels(src, &cur_pixels);
+ src += 7;
+ left = 7;
+ } else { // tail
+ cur_pixels = _mm_srli_si128(cur_pixels, 2);
+ cur_pixels = _mm_insert_epi16(cur_pixels, src[1], 1);
+ src += 1;
+ left = 1;
+ }
+ accum += x_add;
+ }
+ }
+ }
+ assert(accum == 0);
+}
+
+static void RescalerImportRowShrinkSSE2(WebPRescaler* const wrk,
+ const uint8_t* src) {
+ const int x_sub = wrk->x_sub;
+ int accum = 0;
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i mult0 = _mm_set1_epi16(x_sub);
+ const __m128i mult1 = _mm_set1_epi32(wrk->fx_scale);
+ const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER);
+ __m128i sum = zero;
+ rescaler_t* frow = wrk->frow;
+ const rescaler_t* const frow_end = wrk->frow + 4 * wrk->dst_width;
+
+ if (wrk->num_channels != 4 || wrk->x_add > (x_sub << 7)) {
+ WebPRescalerImportRowShrinkC(wrk, src);
+ return;
+ }
+ assert(!WebPRescalerInputDone(wrk));
+ assert(!wrk->x_expand);
+
+ for (; frow < frow_end; frow += 4) {
+ __m128i base = zero;
+ accum += wrk->x_add;
+ while (accum > 0) {
+ const __m128i A = _mm_cvtsi32_si128(*(int*)src);
+ src += 4;
+ base = _mm_unpacklo_epi8(A, zero);
+ // To avoid overflow, we need: base * x_add / x_sub < 32768
+ // => x_add < x_sub << 7. That's a 1/128 reduction ratio limit.
+ sum = _mm_add_epi16(sum, base);
+ accum -= x_sub;
+ }
+ { // Emit next horizontal pixel.
+ const __m128i mult = _mm_set1_epi16(-accum);
+ const __m128i frac0 = _mm_mullo_epi16(base, mult); // 16b x 16b -> 32b
+ const __m128i frac1 = _mm_mulhi_epu16(base, mult);
+ const __m128i frac = _mm_unpacklo_epi16(frac0, frac1); // frac is 32b
+ const __m128i A0 = _mm_mullo_epi16(sum, mult0);
+ const __m128i A1 = _mm_mulhi_epu16(sum, mult0);
+ const __m128i B0 = _mm_unpacklo_epi16(A0, A1); // sum * x_sub
+ const __m128i frow_out = _mm_sub_epi32(B0, frac); // sum * x_sub - frac
+ const __m128i D0 = _mm_srli_epi64(frac, 32);
+ const __m128i D1 = _mm_mul_epu32(frac, mult1); // 32b x 16b -> 64b
+ const __m128i D2 = _mm_mul_epu32(D0, mult1);
+ const __m128i E1 = _mm_add_epi64(D1, rounder);
+ const __m128i E2 = _mm_add_epi64(D2, rounder);
+ const __m128i F1 = _mm_shuffle_epi32(E1, 1 | (3 << 2));
+ const __m128i F2 = _mm_shuffle_epi32(E2, 1 | (3 << 2));
+ const __m128i G = _mm_unpacklo_epi32(F1, F2);
+ sum = _mm_packs_epi32(G, zero);
+ _mm_storeu_si128((__m128i*)frow, frow_out);
+ }
+ }
+ assert(accum == 0);
+}
+
+//------------------------------------------------------------------------------
+// Row export
+
+// load *src as epi64, multiply by mult and store result in [out0 ... out3]
+static WEBP_INLINE void LoadDispatchAndMult(const rescaler_t* const src,
+ const __m128i* const mult,
+ __m128i* const out0,
+ __m128i* const out1,
+ __m128i* const out2,
+ __m128i* const out3) {
+ const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + 0));
+ const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + 4));
+ const __m128i A2 = _mm_srli_epi64(A0, 32);
+ const __m128i A3 = _mm_srli_epi64(A1, 32);
+ if (mult != NULL) {
+ *out0 = _mm_mul_epu32(A0, *mult);
+ *out1 = _mm_mul_epu32(A1, *mult);
+ *out2 = _mm_mul_epu32(A2, *mult);
+ *out3 = _mm_mul_epu32(A3, *mult);
+ } else {
+ *out0 = A0;
+ *out1 = A1;
+ *out2 = A2;
+ *out3 = A3;
+ }
+}
+
+static WEBP_INLINE void ProcessRow(const __m128i* const A0,
+ const __m128i* const A1,
+ const __m128i* const A2,
+ const __m128i* const A3,
+ const __m128i* const mult,
+ uint8_t* const dst) {
+ const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER);
+ const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0);
+ const __m128i B0 = _mm_mul_epu32(*A0, *mult);
+ const __m128i B1 = _mm_mul_epu32(*A1, *mult);
+ const __m128i B2 = _mm_mul_epu32(*A2, *mult);
+ const __m128i B3 = _mm_mul_epu32(*A3, *mult);
+ const __m128i C0 = _mm_add_epi64(B0, rounder);
+ const __m128i C1 = _mm_add_epi64(B1, rounder);
+ const __m128i C2 = _mm_add_epi64(B2, rounder);
+ const __m128i C3 = _mm_add_epi64(B3, rounder);
+ const __m128i D0 = _mm_srli_epi64(C0, WEBP_RESCALER_RFIX);
+ const __m128i D1 = _mm_srli_epi64(C1, WEBP_RESCALER_RFIX);
+#if (WEBP_RESCALER_FIX < 32)
+ const __m128i D2 =
+ _mm_and_si128(_mm_slli_epi64(C2, 32 - WEBP_RESCALER_RFIX), mask);
+ const __m128i D3 =
+ _mm_and_si128(_mm_slli_epi64(C3, 32 - WEBP_RESCALER_RFIX), mask);
+#else
+ const __m128i D2 = _mm_and_si128(C2, mask);
+ const __m128i D3 = _mm_and_si128(C3, mask);
+#endif
+ const __m128i E0 = _mm_or_si128(D0, D2);
+ const __m128i E1 = _mm_or_si128(D1, D3);
+ const __m128i F = _mm_packs_epi32(E0, E1);
+ const __m128i G = _mm_packus_epi16(F, F);
+ _mm_storel_epi64((__m128i*)dst, G);
+}
+
+static void RescalerExportRowExpandSSE2(WebPRescaler* const wrk) {
+ int x_out;
+ uint8_t* const dst = wrk->dst;
+ rescaler_t* const irow = wrk->irow;
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ const rescaler_t* const frow = wrk->frow;
+ const __m128i mult = _mm_set_epi32(0, wrk->fy_scale, 0, wrk->fy_scale);
+
+ assert(!WebPRescalerOutputDone(wrk));
+ assert(wrk->y_accum <= 0 && wrk->y_sub + wrk->y_accum >= 0);
+ assert(wrk->y_expand);
+ if (wrk->y_accum == 0) {
+ for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) {
+ __m128i A0, A1, A2, A3;
+ LoadDispatchAndMult(frow + x_out, NULL, &A0, &A1, &A2, &A3);
+ ProcessRow(&A0, &A1, &A2, &A3, &mult, dst + x_out);
+ }
+ for (; x_out < x_out_max; ++x_out) {
+ const uint32_t J = frow[x_out];
+ const int v = (int)MULT_FIX(J, wrk->fy_scale);
+ assert(v >= 0 && v <= 255);
+ dst[x_out] = v;
+ }
+ } else {
+ const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
+ const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B);
+ const __m128i mA = _mm_set_epi32(0, A, 0, A);
+ const __m128i mB = _mm_set_epi32(0, B, 0, B);
+ const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER);
+ for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) {
+ __m128i A0, A1, A2, A3, B0, B1, B2, B3;
+ LoadDispatchAndMult(frow + x_out, &mA, &A0, &A1, &A2, &A3);
+ LoadDispatchAndMult(irow + x_out, &mB, &B0, &B1, &B2, &B3);
+ {
+ const __m128i C0 = _mm_add_epi64(A0, B0);
+ const __m128i C1 = _mm_add_epi64(A1, B1);
+ const __m128i C2 = _mm_add_epi64(A2, B2);
+ const __m128i C3 = _mm_add_epi64(A3, B3);
+ const __m128i D0 = _mm_add_epi64(C0, rounder);
+ const __m128i D1 = _mm_add_epi64(C1, rounder);
+ const __m128i D2 = _mm_add_epi64(C2, rounder);
+ const __m128i D3 = _mm_add_epi64(C3, rounder);
+ const __m128i E0 = _mm_srli_epi64(D0, WEBP_RESCALER_RFIX);
+ const __m128i E1 = _mm_srli_epi64(D1, WEBP_RESCALER_RFIX);
+ const __m128i E2 = _mm_srli_epi64(D2, WEBP_RESCALER_RFIX);
+ const __m128i E3 = _mm_srli_epi64(D3, WEBP_RESCALER_RFIX);
+ ProcessRow(&E0, &E1, &E2, &E3, &mult, dst + x_out);
+ }
+ }
+ for (; x_out < x_out_max; ++x_out) {
+ const uint64_t I = (uint64_t)A * frow[x_out]
+ + (uint64_t)B * irow[x_out];
+ const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
+ const int v = (int)MULT_FIX(J, wrk->fy_scale);
+ assert(v >= 0 && v <= 255);
+ dst[x_out] = v;
+ }
+ }
+}
+
+static void RescalerExportRowShrinkSSE2(WebPRescaler* const wrk) {
+ int x_out;
+ uint8_t* const dst = wrk->dst;
+ rescaler_t* const irow = wrk->irow;
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ const rescaler_t* const frow = wrk->frow;
+ const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum);
+ assert(!WebPRescalerOutputDone(wrk));
+ assert(wrk->y_accum <= 0);
+ assert(!wrk->y_expand);
+ if (yscale) {
+ const int scale_xy = wrk->fxy_scale;
+ const __m128i mult_xy = _mm_set_epi32(0, scale_xy, 0, scale_xy);
+ const __m128i mult_y = _mm_set_epi32(0, yscale, 0, yscale);
+ const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER);
+ for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) {
+ __m128i A0, A1, A2, A3, B0, B1, B2, B3;
+ LoadDispatchAndMult(irow + x_out, NULL, &A0, &A1, &A2, &A3);
+ LoadDispatchAndMult(frow + x_out, &mult_y, &B0, &B1, &B2, &B3);
+ {
+ const __m128i C0 = _mm_add_epi64(B0, rounder);
+ const __m128i C1 = _mm_add_epi64(B1, rounder);
+ const __m128i C2 = _mm_add_epi64(B2, rounder);
+ const __m128i C3 = _mm_add_epi64(B3, rounder);
+ const __m128i D0 = _mm_srli_epi64(C0, WEBP_RESCALER_RFIX); // = frac
+ const __m128i D1 = _mm_srli_epi64(C1, WEBP_RESCALER_RFIX);
+ const __m128i D2 = _mm_srli_epi64(C2, WEBP_RESCALER_RFIX);
+ const __m128i D3 = _mm_srli_epi64(C3, WEBP_RESCALER_RFIX);
+ const __m128i E0 = _mm_sub_epi64(A0, D0); // irow[x] - frac
+ const __m128i E1 = _mm_sub_epi64(A1, D1);
+ const __m128i E2 = _mm_sub_epi64(A2, D2);
+ const __m128i E3 = _mm_sub_epi64(A3, D3);
+ const __m128i F2 = _mm_slli_epi64(D2, 32);
+ const __m128i F3 = _mm_slli_epi64(D3, 32);
+ const __m128i G0 = _mm_or_si128(D0, F2);
+ const __m128i G1 = _mm_or_si128(D1, F3);
+ _mm_storeu_si128((__m128i*)(irow + x_out + 0), G0);
+ _mm_storeu_si128((__m128i*)(irow + x_out + 4), G1);
+ ProcessRow(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
+ }
+ }
+ for (; x_out < x_out_max; ++x_out) {
+ const uint32_t frac = (int)MULT_FIX(frow[x_out], yscale);
+ const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
+ assert(v >= 0 && v <= 255);
+ dst[x_out] = v;
+ irow[x_out] = frac; // new fractional start
+ }
+ } else {
+ const uint32_t scale = wrk->fxy_scale;
+ const __m128i mult = _mm_set_epi32(0, scale, 0, scale);
+ const __m128i zero = _mm_setzero_si128();
+ for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) {
+ __m128i A0, A1, A2, A3;
+ LoadDispatchAndMult(irow + x_out, NULL, &A0, &A1, &A2, &A3);
+ _mm_storeu_si128((__m128i*)(irow + x_out + 0), zero);
+ _mm_storeu_si128((__m128i*)(irow + x_out + 4), zero);
+ ProcessRow(&A0, &A1, &A2, &A3, &mult, dst + x_out);
+ }
+ for (; x_out < x_out_max; ++x_out) {
+ const int v = (int)MULT_FIX(irow[x_out], scale);
+ assert(v >= 0 && v <= 255);
+ dst[x_out] = v;
+ irow[x_out] = 0;
+ }
+ }
+}
+
+#undef MULT_FIX
+#undef ROUNDER
+
+//------------------------------------------------------------------------------
+
+extern void WebPRescalerDspInitSSE2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitSSE2(void) {
+ WebPRescalerImportRowExpand = RescalerImportRowExpandSSE2;
+ WebPRescalerImportRowShrink = RescalerImportRowShrinkSSE2;
+ WebPRescalerExportRowExpand = RescalerExportRowExpandSSE2;
+ WebPRescalerExportRowShrink = RescalerExportRowShrinkSSE2;
+}
+
+#else // !WEBP_USE_SSE2
+
+WEBP_DSP_INIT_STUB(WebPRescalerDspInitSSE2)
+
+#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/upsampling.c b/drivers/webp/dsp/upsampling.c
index 4855eb1432..651274fcee 100644
--- a/drivers/webp/dsp/upsampling.c
+++ b/drivers/webp/dsp/upsampling.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// YUV to RGB upsampling functions.
@@ -12,9 +14,7 @@
#include "./dsp.h"
#include "./yuv.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+#include <assert.h>
//------------------------------------------------------------------------------
// Fancy upsampler
@@ -32,7 +32,7 @@ WebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST];
// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16
// We process u and v together stashed into 32bit (16bit each).
-#define LOAD_UV(u,v) ((u) | ((v) << 16))
+#define LOAD_UV(u, v) ((u) | ((v) << 16))
#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \
static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
@@ -43,11 +43,12 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
const int last_pixel_pair = (len - 1) >> 1; \
uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \
uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \
- if (top_y) { \
+ assert(top_y != NULL); \
+ { \
const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \
} \
- if (bottom_y) { \
+ if (bottom_y != NULL) { \
const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \
} \
@@ -58,7 +59,7 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \
const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \
const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \
- if (top_y) { \
+ { \
const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \
const uint32_t uv1 = (diag_03 + t_uv) >> 1; \
FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \
@@ -66,7 +67,7 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \
top_dst + (2 * x - 0) * XSTEP); \
} \
- if (bottom_y) { \
+ if (bottom_y != NULL) { \
const uint32_t uv0 = (diag_03 + l_uv) >> 1; \
const uint32_t uv1 = (diag_12 + uv) >> 1; \
FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \
@@ -78,12 +79,12 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
l_uv = uv; \
} \
if (!(len & 1)) { \
- if (top_y) { \
+ { \
const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \
top_dst + (len - 1) * XSTEP); \
} \
- if (bottom_y) { \
+ if (bottom_y != NULL) { \
const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \
bottom_dst + (len - 1) * XSTEP); \
@@ -106,57 +107,6 @@ UPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2)
#endif // FANCY_UPSAMPLING
//------------------------------------------------------------------------------
-// simple point-sampling
-
-#define SAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \
-static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
- const uint8_t* u, const uint8_t* v, \
- uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
- int i; \
- for (i = 0; i < len - 1; i += 2) { \
- FUNC(top_y[0], u[0], v[0], top_dst); \
- FUNC(top_y[1], u[0], v[0], top_dst + XSTEP); \
- FUNC(bottom_y[0], u[0], v[0], bottom_dst); \
- FUNC(bottom_y[1], u[0], v[0], bottom_dst + XSTEP); \
- top_y += 2; \
- bottom_y += 2; \
- u++; \
- v++; \
- top_dst += 2 * XSTEP; \
- bottom_dst += 2 * XSTEP; \
- } \
- if (i == len - 1) { /* last one */ \
- FUNC(top_y[0], u[0], v[0], top_dst); \
- FUNC(bottom_y[0], u[0], v[0], bottom_dst); \
- } \
-}
-
-// All variants implemented.
-SAMPLE_FUNC(SampleRgbLinePair, VP8YuvToRgb, 3)
-SAMPLE_FUNC(SampleBgrLinePair, VP8YuvToBgr, 3)
-SAMPLE_FUNC(SampleRgbaLinePair, VP8YuvToRgba, 4)
-SAMPLE_FUNC(SampleBgraLinePair, VP8YuvToBgra, 4)
-SAMPLE_FUNC(SampleArgbLinePair, VP8YuvToArgb, 4)
-SAMPLE_FUNC(SampleRgba4444LinePair, VP8YuvToRgba4444, 2)
-SAMPLE_FUNC(SampleRgb565LinePair, VP8YuvToRgb565, 2)
-
-#undef SAMPLE_FUNC
-
-const WebPSampleLinePairFunc WebPSamplers[MODE_LAST] = {
- SampleRgbLinePair, // MODE_RGB
- SampleRgbaLinePair, // MODE_RGBA
- SampleBgrLinePair, // MODE_BGR
- SampleBgraLinePair, // MODE_BGRA
- SampleArgbLinePair, // MODE_ARGB
- SampleRgba4444LinePair, // MODE_RGBA_4444
- SampleRgb565LinePair, // MODE_RGB_565
- SampleRgbaLinePair, // MODE_rgbA
- SampleBgraLinePair, // MODE_bgrA
- SampleArgbLinePair, // MODE_Argb
- SampleRgba4444LinePair // MODE_rgbA_4444
-};
-
-//------------------------------------------------------------------------------
#if !defined(FANCY_UPSAMPLING)
#define DUAL_SAMPLE_FUNC(FUNC_NAME, FUNC) \
@@ -166,7 +116,8 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \
uint8_t* top_dst, uint8_t* bot_dst, int len) { \
const int half_len = len >> 1; \
int x; \
- if (top_dst != NULL) { \
+ assert(top_dst != NULL); \
+ { \
for (x = 0; x < half_len; ++x) { \
FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \
FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \
@@ -202,116 +153,75 @@ WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last) {
// YUV444 converter
#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \
-static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
- uint8_t* dst, int len) { \
+extern void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
+ uint8_t* dst, int len); \
+void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
+ uint8_t* dst, int len) { \
int i; \
for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \
}
-YUV444_FUNC(Yuv444ToRgb, VP8YuvToRgb, 3)
-YUV444_FUNC(Yuv444ToBgr, VP8YuvToBgr, 3)
-YUV444_FUNC(Yuv444ToRgba, VP8YuvToRgba, 4)
-YUV444_FUNC(Yuv444ToBgra, VP8YuvToBgra, 4)
-YUV444_FUNC(Yuv444ToArgb, VP8YuvToArgb, 4)
-YUV444_FUNC(Yuv444ToRgba4444, VP8YuvToRgba4444, 2)
-YUV444_FUNC(Yuv444ToRgb565, VP8YuvToRgb565, 2)
+YUV444_FUNC(WebPYuv444ToRgbC, VP8YuvToRgb, 3)
+YUV444_FUNC(WebPYuv444ToBgrC, VP8YuvToBgr, 3)
+YUV444_FUNC(WebPYuv444ToRgbaC, VP8YuvToRgba, 4)
+YUV444_FUNC(WebPYuv444ToBgraC, VP8YuvToBgra, 4)
+YUV444_FUNC(WebPYuv444ToArgbC, VP8YuvToArgb, 4)
+YUV444_FUNC(WebPYuv444ToRgba4444C, VP8YuvToRgba4444, 2)
+YUV444_FUNC(WebPYuv444ToRgb565C, VP8YuvToRgb565, 2)
#undef YUV444_FUNC
-const WebPYUV444Converter WebPYUV444Converters[MODE_LAST] = {
- Yuv444ToRgb, // MODE_RGB
- Yuv444ToRgba, // MODE_RGBA
- Yuv444ToBgr, // MODE_BGR
- Yuv444ToBgra, // MODE_BGRA
- Yuv444ToArgb, // MODE_ARGB
- Yuv444ToRgba4444, // MODE_RGBA_4444
- Yuv444ToRgb565, // MODE_RGB_565
- Yuv444ToRgba, // MODE_rgbA
- Yuv444ToBgra, // MODE_bgrA
- Yuv444ToArgb, // MODE_Argb
- Yuv444ToRgba4444 // MODE_rgbA_4444
-};
-
-//------------------------------------------------------------------------------
-// Premultiplied modes
-
-// non dithered-modes
-
-// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.)
-// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5),
-// one can use instead: (x * a * 65793 + (1 << 23)) >> 24
-#if 1 // (int)(x * a / 255.)
-#define MULTIPLIER(a) ((a) * 32897UL)
-#define PREMULTIPLY(x, m) (((x) * (m)) >> 23)
-#else // (int)(x * a / 255. + .5)
-#define MULTIPLIER(a) ((a) * 65793UL)
-#define PREMULTIPLY(x, m) (((x) * (m) + (1UL << 23)) >> 24)
-#endif
-
-static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first,
- int w, int h, int stride) {
- while (h-- > 0) {
- uint8_t* const rgb = rgba + (alpha_first ? 1 : 0);
- const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3);
- int i;
- for (i = 0; i < w; ++i) {
- const uint32_t a = alpha[4 * i];
- if (a != 0xff) {
- const uint32_t mult = MULTIPLIER(a);
- rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult);
- rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult);
- rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult);
- }
- }
- rgba += stride;
- }
-}
-#undef MULTIPLIER
-#undef PREMULTIPLY
-
-// rgbA4444
+WebPYUV444Converter WebPYUV444Converters[MODE_LAST];
-#define MULTIPLIER(a) ((a) * 0x1111) // 0x1111 ~= (1 << 16) / 15
+extern void WebPInitYUV444ConvertersMIPSdspR2(void);
+extern void WebPInitYUV444ConvertersSSE2(void);
-static WEBP_INLINE uint8_t dither_hi(uint8_t x) {
- return (x & 0xf0) | (x >> 4);
-}
+static volatile VP8CPUInfo upsampling_last_cpuinfo_used1 =
+ (VP8CPUInfo)&upsampling_last_cpuinfo_used1;
-static WEBP_INLINE uint8_t dither_lo(uint8_t x) {
- return (x & 0x0f) | (x << 4);
-}
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444Converters(void) {
+ if (upsampling_last_cpuinfo_used1 == VP8GetCPUInfo) return;
-static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) {
- return (x * m) >> 16;
-}
+ WebPYUV444Converters[MODE_RGB] = WebPYuv444ToRgbC;
+ WebPYUV444Converters[MODE_RGBA] = WebPYuv444ToRgbaC;
+ WebPYUV444Converters[MODE_BGR] = WebPYuv444ToBgrC;
+ WebPYUV444Converters[MODE_BGRA] = WebPYuv444ToBgraC;
+ WebPYUV444Converters[MODE_ARGB] = WebPYuv444ToArgbC;
+ WebPYUV444Converters[MODE_RGBA_4444] = WebPYuv444ToRgba4444C;
+ WebPYUV444Converters[MODE_RGB_565] = WebPYuv444ToRgb565C;
+ WebPYUV444Converters[MODE_rgbA] = WebPYuv444ToRgbaC;
+ WebPYUV444Converters[MODE_bgrA] = WebPYuv444ToBgraC;
+ WebPYUV444Converters[MODE_Argb] = WebPYuv444ToArgbC;
+ WebPYUV444Converters[MODE_rgbA_4444] = WebPYuv444ToRgba4444C;
-static void ApplyAlphaMultiply4444(uint8_t* rgba4444,
- int w, int h, int stride) {
- while (h-- > 0) {
- int i;
- for (i = 0; i < w; ++i) {
- const uint8_t a = (rgba4444[2 * i + 1] & 0x0f);
- const uint32_t mult = MULTIPLIER(a);
- const uint8_t r = multiply(dither_hi(rgba4444[2 * i + 0]), mult);
- const uint8_t g = multiply(dither_lo(rgba4444[2 * i + 0]), mult);
- const uint8_t b = multiply(dither_hi(rgba4444[2 * i + 1]), mult);
- rgba4444[2 * i + 0] = (r & 0xf0) | ((g >> 4) & 0x0f);
- rgba4444[2 * i + 1] = (b & 0xf0) | a;
+ if (VP8GetCPUInfo != NULL) {
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ WebPInitYUV444ConvertersSSE2();
+ }
+#endif
+#if defined(WEBP_USE_MIPS_DSP_R2)
+ if (VP8GetCPUInfo(kMIPSdspR2)) {
+ WebPInitYUV444ConvertersMIPSdspR2();
}
- rgba4444 += stride;
+#endif
}
+ upsampling_last_cpuinfo_used1 = VP8GetCPUInfo;
}
-#undef MULTIPLIER
-
-void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int)
- = ApplyAlphaMultiply;
-void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int)
- = ApplyAlphaMultiply4444;
//------------------------------------------------------------------------------
-// Main call
+// Main calls
+
+extern void WebPInitUpsamplersSSE2(void);
+extern void WebPInitUpsamplersNEON(void);
+extern void WebPInitUpsamplersMIPSdspR2(void);
+
+static volatile VP8CPUInfo upsampling_last_cpuinfo_used2 =
+ (VP8CPUInfo)&upsampling_last_cpuinfo_used2;
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) {
+ if (upsampling_last_cpuinfo_used2 == VP8GetCPUInfo) return;
-void WebPInitUpsamplers(void) {
#ifdef FANCY_UPSAMPLING
WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
@@ -320,38 +230,31 @@ void WebPInitUpsamplers(void) {
WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair;
WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair;
WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair;
-
- // If defined, use CPUInfo() to overwrite some pointers with faster versions.
- if (VP8GetCPUInfo != NULL) {
-#if defined(WEBP_USE_SSE2)
- if (VP8GetCPUInfo(kSSE2)) {
- WebPInitUpsamplersSSE2();
- }
-#endif
- }
-#endif // FANCY_UPSAMPLING
-}
-
-void WebPInitPremultiply(void) {
- WebPApplyAlphaMultiply = ApplyAlphaMultiply;
- WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply4444;
-
-#ifdef FANCY_UPSAMPLING
WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair;
WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair;
WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair;
WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair;
+ // If defined, use CPUInfo() to overwrite some pointers with faster versions.
if (VP8GetCPUInfo != NULL) {
#if defined(WEBP_USE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
- WebPInitPremultiplySSE2();
+ WebPInitUpsamplersSSE2();
+ }
+#endif
+#if defined(WEBP_USE_NEON)
+ if (VP8GetCPUInfo(kNEON)) {
+ WebPInitUpsamplersNEON();
+ }
+#endif
+#if defined(WEBP_USE_MIPS_DSP_R2)
+ if (VP8GetCPUInfo(kMIPSdspR2)) {
+ WebPInitUpsamplersMIPSdspR2();
}
#endif
}
#endif // FANCY_UPSAMPLING
+ upsampling_last_cpuinfo_used2 = VP8GetCPUInfo;
}
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
+//------------------------------------------------------------------------------
diff --git a/drivers/webp/dsp/upsampling_mips_dsp_r2.c b/drivers/webp/dsp/upsampling_mips_dsp_r2.c
new file mode 100644
index 0000000000..46f207b43e
--- /dev/null
+++ b/drivers/webp/dsp/upsampling_mips_dsp_r2.c
@@ -0,0 +1,282 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// YUV to RGB upsampling functions.
+//
+// Author(s): Branimir Vasic (branimir.vasic@imgtec.com)
+// Djordje Pesut (djordje.pesut@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS_DSP_R2)
+
+#include <assert.h>
+#include "./yuv.h"
+
+#if !defined(WEBP_YUV_USE_TABLE)
+
+#define YUV_TO_RGB(Y, U, V, R, G, B) do { \
+ const int t1 = kYScale * Y; \
+ const int t2 = kVToG * V; \
+ R = kVToR * V; \
+ G = kUToG * U; \
+ B = kUToB * U; \
+ R = t1 + R; \
+ G = t1 - G; \
+ B = t1 + B; \
+ R = R + kRCst; \
+ G = G - t2 + kGCst; \
+ B = B + kBCst; \
+ __asm__ volatile ( \
+ "shll_s.w %[" #R "], %[" #R "], 9 \n\t" \
+ "shll_s.w %[" #G "], %[" #G "], 9 \n\t" \
+ "shll_s.w %[" #B "], %[" #B "], 9 \n\t" \
+ "precrqu_s.qb.ph %[" #R "], %[" #R "], $zero \n\t" \
+ "precrqu_s.qb.ph %[" #G "], %[" #G "], $zero \n\t" \
+ "precrqu_s.qb.ph %[" #B "], %[" #B "], $zero \n\t" \
+ "srl %[" #R "], %[" #R "], 24 \n\t" \
+ "srl %[" #G "], %[" #G "], 24 \n\t" \
+ "srl %[" #B "], %[" #B "], 24 \n\t" \
+ : [R]"+r"(R), [G]"+r"(G), [B]"+r"(B) \
+ : \
+ ); \
+ } while (0)
+
+static WEBP_INLINE void YuvToRgb(int y, int u, int v, uint8_t* const rgb) {
+ int r, g, b;
+ YUV_TO_RGB(y, u, v, r, g, b);
+ rgb[0] = r;
+ rgb[1] = g;
+ rgb[2] = b;
+}
+static WEBP_INLINE void YuvToBgr(int y, int u, int v, uint8_t* const bgr) {
+ int r, g, b;
+ YUV_TO_RGB(y, u, v, r, g, b);
+ bgr[0] = b;
+ bgr[1] = g;
+ bgr[2] = r;
+}
+static WEBP_INLINE void YuvToRgb565(int y, int u, int v, uint8_t* const rgb) {
+ int r, g, b;
+ YUV_TO_RGB(y, u, v, r, g, b);
+ {
+ const int rg = (r & 0xf8) | (g >> 5);
+ const int gb = ((g << 3) & 0xe0) | (b >> 3);
+#ifdef WEBP_SWAP_16BIT_CSP
+ rgb[0] = gb;
+ rgb[1] = rg;
+#else
+ rgb[0] = rg;
+ rgb[1] = gb;
+#endif
+ }
+}
+static WEBP_INLINE void YuvToRgba4444(int y, int u, int v,
+ uint8_t* const argb) {
+ int r, g, b;
+ YUV_TO_RGB(y, u, v, r, g, b);
+ {
+ const int rg = (r & 0xf0) | (g >> 4);
+ const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits
+#ifdef WEBP_SWAP_16BIT_CSP
+ argb[0] = ba;
+ argb[1] = rg;
+#else
+ argb[0] = rg;
+ argb[1] = ba;
+#endif
+ }
+}
+#endif // WEBP_YUV_USE_TABLE
+
+//-----------------------------------------------------------------------------
+// Alpha handling variants
+
+static WEBP_INLINE void YuvToArgb(uint8_t y, uint8_t u, uint8_t v,
+ uint8_t* const argb) {
+ int r, g, b;
+ YUV_TO_RGB(y, u, v, r, g, b);
+ argb[0] = 0xff;
+ argb[1] = r;
+ argb[2] = g;
+ argb[3] = b;
+}
+static WEBP_INLINE void YuvToBgra(uint8_t y, uint8_t u, uint8_t v,
+ uint8_t* const bgra) {
+ int r, g, b;
+ YUV_TO_RGB(y, u, v, r, g, b);
+ bgra[0] = b;
+ bgra[1] = g;
+ bgra[2] = r;
+ bgra[3] = 0xff;
+}
+static WEBP_INLINE void YuvToRgba(uint8_t y, uint8_t u, uint8_t v,
+ uint8_t* const rgba) {
+ int r, g, b;
+ YUV_TO_RGB(y, u, v, r, g, b);
+ rgba[0] = r;
+ rgba[1] = g;
+ rgba[2] = b;
+ rgba[3] = 0xff;
+}
+
+//------------------------------------------------------------------------------
+// Fancy upsampler
+
+#ifdef FANCY_UPSAMPLING
+
+// Given samples laid out in a square as:
+// [a b]
+// [c d]
+// we interpolate u/v as:
+// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16
+// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16
+
+// We process u and v together stashed into 32bit (16bit each).
+#define LOAD_UV(u, v) ((u) | ((v) << 16))
+
+#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \
+static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
+ const uint8_t* top_u, const uint8_t* top_v, \
+ const uint8_t* cur_u, const uint8_t* cur_v, \
+ uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
+ int x; \
+ const int last_pixel_pair = (len - 1) >> 1; \
+ uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \
+ uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \
+ assert(top_y != NULL); \
+ { \
+ const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
+ FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \
+ } \
+ if (bottom_y != NULL) { \
+ const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
+ FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \
+ } \
+ for (x = 1; x <= last_pixel_pair; ++x) { \
+ const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \
+ const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \
+ /* precompute invariant values associated with first and second diagonals*/\
+ const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \
+ const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \
+ const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \
+ { \
+ const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \
+ const uint32_t uv1 = (diag_03 + t_uv) >> 1; \
+ FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \
+ top_dst + (2 * x - 1) * XSTEP); \
+ FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \
+ top_dst + (2 * x - 0) * XSTEP); \
+ } \
+ if (bottom_y != NULL) { \
+ const uint32_t uv0 = (diag_03 + l_uv) >> 1; \
+ const uint32_t uv1 = (diag_12 + uv) >> 1; \
+ FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \
+ bottom_dst + (2 * x - 1) * XSTEP); \
+ FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \
+ bottom_dst + (2 * x + 0) * XSTEP); \
+ } \
+ tl_uv = t_uv; \
+ l_uv = uv; \
+ } \
+ if (!(len & 1)) { \
+ { \
+ const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
+ FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \
+ top_dst + (len - 1) * XSTEP); \
+ } \
+ if (bottom_y != NULL) { \
+ const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
+ FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \
+ bottom_dst + (len - 1) * XSTEP); \
+ } \
+ } \
+}
+
+// All variants implemented.
+UPSAMPLE_FUNC(UpsampleRgbLinePair, YuvToRgb, 3)
+UPSAMPLE_FUNC(UpsampleBgrLinePair, YuvToBgr, 3)
+UPSAMPLE_FUNC(UpsampleRgbaLinePair, YuvToRgba, 4)
+UPSAMPLE_FUNC(UpsampleBgraLinePair, YuvToBgra, 4)
+UPSAMPLE_FUNC(UpsampleArgbLinePair, YuvToArgb, 4)
+UPSAMPLE_FUNC(UpsampleRgba4444LinePair, YuvToRgba4444, 2)
+UPSAMPLE_FUNC(UpsampleRgb565LinePair, YuvToRgb565, 2)
+
+#undef LOAD_UV
+#undef UPSAMPLE_FUNC
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void WebPInitUpsamplersMIPSdspR2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersMIPSdspR2(void) {
+ WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
+ WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
+ WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair;
+ WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair;
+ WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair;
+ WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair;
+ WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair;
+ WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair;
+ WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair;
+ WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair;
+ WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair;
+}
+
+#endif // FANCY_UPSAMPLING
+
+//------------------------------------------------------------------------------
+// YUV444 converter
+
+#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \
+static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
+ uint8_t* dst, int len) { \
+ int i; \
+ for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \
+}
+
+YUV444_FUNC(Yuv444ToRgb, YuvToRgb, 3)
+YUV444_FUNC(Yuv444ToBgr, YuvToBgr, 3)
+YUV444_FUNC(Yuv444ToRgba, YuvToRgba, 4)
+YUV444_FUNC(Yuv444ToBgra, YuvToBgra, 4)
+YUV444_FUNC(Yuv444ToArgb, YuvToArgb, 4)
+YUV444_FUNC(Yuv444ToRgba4444, YuvToRgba4444, 2)
+YUV444_FUNC(Yuv444ToRgb565, YuvToRgb565, 2)
+
+#undef YUV444_FUNC
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void WebPInitYUV444ConvertersMIPSdspR2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersMIPSdspR2(void) {
+ WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb;
+ WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba;
+ WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr;
+ WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra;
+ WebPYUV444Converters[MODE_ARGB] = Yuv444ToArgb;
+ WebPYUV444Converters[MODE_RGBA_4444] = Yuv444ToRgba4444;
+ WebPYUV444Converters[MODE_RGB_565] = Yuv444ToRgb565;
+ WebPYUV444Converters[MODE_rgbA] = Yuv444ToRgba;
+ WebPYUV444Converters[MODE_bgrA] = Yuv444ToBgra;
+ WebPYUV444Converters[MODE_Argb] = Yuv444ToArgb;
+ WebPYUV444Converters[MODE_rgbA_4444] = Yuv444ToRgba4444;
+}
+
+#else // !WEBP_USE_MIPS_DSP_R2
+
+WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersMIPSdspR2)
+
+#endif // WEBP_USE_MIPS_DSP_R2
+
+#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_MIPS_DSP_R2))
+WEBP_DSP_INIT_STUB(WebPInitUpsamplersMIPSdspR2)
+#endif
diff --git a/drivers/webp/dsp/upsampling_neon.c b/drivers/webp/dsp/upsampling_neon.c
new file mode 100644
index 0000000000..a8384c2149
--- /dev/null
+++ b/drivers/webp/dsp/upsampling_neon.c
@@ -0,0 +1,261 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// NEON version of YUV to RGB upsampling functions.
+//
+// Author: mans@mansr.com (Mans Rullgard)
+// Based on SSE code by: somnath@google.com (Somnath Banerjee)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_NEON)
+
+#include <assert.h>
+#include <arm_neon.h>
+#include <string.h>
+#include "./neon.h"
+#include "./yuv.h"
+
+#ifdef FANCY_UPSAMPLING
+
+//-----------------------------------------------------------------------------
+// U/V upsampling
+
+// Loads 9 pixels each from rows r1 and r2 and generates 16 pixels.
+#define UPSAMPLE_16PIXELS(r1, r2, out) { \
+ uint8x8_t a = vld1_u8(r1); \
+ uint8x8_t b = vld1_u8(r1 + 1); \
+ uint8x8_t c = vld1_u8(r2); \
+ uint8x8_t d = vld1_u8(r2 + 1); \
+ \
+ uint16x8_t al = vshll_n_u8(a, 1); \
+ uint16x8_t bl = vshll_n_u8(b, 1); \
+ uint16x8_t cl = vshll_n_u8(c, 1); \
+ uint16x8_t dl = vshll_n_u8(d, 1); \
+ \
+ uint8x8_t diag1, diag2; \
+ uint16x8_t sl; \
+ \
+ /* a + b + c + d */ \
+ sl = vaddl_u8(a, b); \
+ sl = vaddw_u8(sl, c); \
+ sl = vaddw_u8(sl, d); \
+ \
+ al = vaddq_u16(sl, al); /* 3a + b + c + d */ \
+ bl = vaddq_u16(sl, bl); /* a + 3b + c + d */ \
+ \
+ al = vaddq_u16(al, dl); /* 3a + b + c + 3d */ \
+ bl = vaddq_u16(bl, cl); /* a + 3b + 3c + d */ \
+ \
+ diag2 = vshrn_n_u16(al, 3); \
+ diag1 = vshrn_n_u16(bl, 3); \
+ \
+ a = vrhadd_u8(a, diag1); \
+ b = vrhadd_u8(b, diag2); \
+ c = vrhadd_u8(c, diag2); \
+ d = vrhadd_u8(d, diag1); \
+ \
+ { \
+ uint8x8x2_t a_b, c_d; \
+ INIT_VECTOR2(a_b, a, b); \
+ INIT_VECTOR2(c_d, c, d); \
+ vst2_u8(out, a_b); \
+ vst2_u8(out + 32, c_d); \
+ } \
+}
+
+// Turn the macro into a function for reducing code-size when non-critical
+static void Upsample16Pixels(const uint8_t *r1, const uint8_t *r2,
+ uint8_t *out) {
+ UPSAMPLE_16PIXELS(r1, r2, out);
+}
+
+#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \
+ uint8_t r1[9], r2[9]; \
+ memcpy(r1, (tb), (num_pixels)); \
+ memcpy(r2, (bb), (num_pixels)); \
+ /* replicate last byte */ \
+ memset(r1 + (num_pixels), r1[(num_pixels) - 1], 9 - (num_pixels)); \
+ memset(r2 + (num_pixels), r2[(num_pixels) - 1], 9 - (num_pixels)); \
+ Upsample16Pixels(r1, r2, out); \
+}
+
+//-----------------------------------------------------------------------------
+// YUV->RGB conversion
+
+static const int16_t kCoeffs[4] = { kYScale, kVToR, kUToG, kVToG };
+
+#define v255 vdup_n_u8(255)
+
+#define STORE_Rgb(out, r, g, b) do { \
+ uint8x8x3_t r_g_b; \
+ INIT_VECTOR3(r_g_b, r, g, b); \
+ vst3_u8(out, r_g_b); \
+} while (0)
+
+#define STORE_Bgr(out, r, g, b) do { \
+ uint8x8x3_t b_g_r; \
+ INIT_VECTOR3(b_g_r, b, g, r); \
+ vst3_u8(out, b_g_r); \
+} while (0)
+
+#define STORE_Rgba(out, r, g, b) do { \
+ uint8x8x4_t r_g_b_v255; \
+ INIT_VECTOR4(r_g_b_v255, r, g, b, v255); \
+ vst4_u8(out, r_g_b_v255); \
+} while (0)
+
+#define STORE_Bgra(out, r, g, b) do { \
+ uint8x8x4_t b_g_r_v255; \
+ INIT_VECTOR4(b_g_r_v255, b, g, r, v255); \
+ vst4_u8(out, b_g_r_v255); \
+} while (0)
+
+#define CONVERT8(FMT, XSTEP, N, src_y, src_uv, out, cur_x) { \
+ int i; \
+ for (i = 0; i < N; i += 8) { \
+ const int off = ((cur_x) + i) * XSTEP; \
+ uint8x8_t y = vld1_u8((src_y) + (cur_x) + i); \
+ uint8x8_t u = vld1_u8((src_uv) + i); \
+ uint8x8_t v = vld1_u8((src_uv) + i + 16); \
+ const int16x8_t yy = vreinterpretq_s16_u16(vsubl_u8(y, u16)); \
+ const int16x8_t uu = vreinterpretq_s16_u16(vsubl_u8(u, u128)); \
+ const int16x8_t vv = vreinterpretq_s16_u16(vsubl_u8(v, u128)); \
+ int32x4_t yl = vmull_lane_s16(vget_low_s16(yy), cf16, 0); \
+ int32x4_t yh = vmull_lane_s16(vget_high_s16(yy), cf16, 0); \
+ const int32x4_t rl = vmlal_lane_s16(yl, vget_low_s16(vv), cf16, 1);\
+ const int32x4_t rh = vmlal_lane_s16(yh, vget_high_s16(vv), cf16, 1);\
+ int32x4_t gl = vmlsl_lane_s16(yl, vget_low_s16(uu), cf16, 2); \
+ int32x4_t gh = vmlsl_lane_s16(yh, vget_high_s16(uu), cf16, 2); \
+ const int32x4_t bl = vmovl_s16(vget_low_s16(uu)); \
+ const int32x4_t bh = vmovl_s16(vget_high_s16(uu)); \
+ gl = vmlsl_lane_s16(gl, vget_low_s16(vv), cf16, 3); \
+ gh = vmlsl_lane_s16(gh, vget_high_s16(vv), cf16, 3); \
+ yl = vmlaq_lane_s32(yl, bl, cf32, 0); \
+ yh = vmlaq_lane_s32(yh, bh, cf32, 0); \
+ /* vrshrn_n_s32() already incorporates the rounding constant */ \
+ y = vqmovun_s16(vcombine_s16(vrshrn_n_s32(rl, YUV_FIX2), \
+ vrshrn_n_s32(rh, YUV_FIX2))); \
+ u = vqmovun_s16(vcombine_s16(vrshrn_n_s32(gl, YUV_FIX2), \
+ vrshrn_n_s32(gh, YUV_FIX2))); \
+ v = vqmovun_s16(vcombine_s16(vrshrn_n_s32(yl, YUV_FIX2), \
+ vrshrn_n_s32(yh, YUV_FIX2))); \
+ STORE_ ## FMT(out + off, y, u, v); \
+ } \
+}
+
+#define CONVERT1(FUNC, XSTEP, N, src_y, src_uv, rgb, cur_x) { \
+ int i; \
+ for (i = 0; i < N; i++) { \
+ const int off = ((cur_x) + i) * XSTEP; \
+ const int y = src_y[(cur_x) + i]; \
+ const int u = (src_uv)[i]; \
+ const int v = (src_uv)[i + 16]; \
+ FUNC(y, u, v, rgb + off); \
+ } \
+}
+
+#define CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, uv, \
+ top_dst, bottom_dst, cur_x, len) { \
+ CONVERT8(FMT, XSTEP, len, top_y, uv, top_dst, cur_x) \
+ if (bottom_y != NULL) { \
+ CONVERT8(FMT, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x) \
+ } \
+}
+
+#define CONVERT2RGB_1(FUNC, XSTEP, top_y, bottom_y, uv, \
+ top_dst, bottom_dst, cur_x, len) { \
+ CONVERT1(FUNC, XSTEP, len, top_y, uv, top_dst, cur_x); \
+ if (bottom_y != NULL) { \
+ CONVERT1(FUNC, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \
+ } \
+}
+
+#define NEON_UPSAMPLE_FUNC(FUNC_NAME, FMT, XSTEP) \
+static void FUNC_NAME(const uint8_t *top_y, const uint8_t *bottom_y, \
+ const uint8_t *top_u, const uint8_t *top_v, \
+ const uint8_t *cur_u, const uint8_t *cur_v, \
+ uint8_t *top_dst, uint8_t *bottom_dst, int len) { \
+ int block; \
+ /* 16 byte aligned array to cache reconstructed u and v */ \
+ uint8_t uv_buf[2 * 32 + 15]; \
+ uint8_t *const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
+ const int uv_len = (len + 1) >> 1; \
+ /* 9 pixels must be read-able for each block */ \
+ const int num_blocks = (uv_len - 1) >> 3; \
+ const int leftover = uv_len - num_blocks * 8; \
+ const int last_pos = 1 + 16 * num_blocks; \
+ \
+ const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \
+ const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \
+ \
+ const int16x4_t cf16 = vld1_s16(kCoeffs); \
+ const int32x2_t cf32 = vdup_n_s32(kUToB); \
+ const uint8x8_t u16 = vdup_n_u8(16); \
+ const uint8x8_t u128 = vdup_n_u8(128); \
+ \
+ /* Treat the first pixel in regular way */ \
+ assert(top_y != NULL); \
+ { \
+ const int u0 = (top_u[0] + u_diag) >> 1; \
+ const int v0 = (top_v[0] + v_diag) >> 1; \
+ VP8YuvTo ## FMT(top_y[0], u0, v0, top_dst); \
+ } \
+ if (bottom_y != NULL) { \
+ const int u0 = (cur_u[0] + u_diag) >> 1; \
+ const int v0 = (cur_v[0] + v_diag) >> 1; \
+ VP8YuvTo ## FMT(bottom_y[0], u0, v0, bottom_dst); \
+ } \
+ \
+ for (block = 0; block < num_blocks; ++block) { \
+ UPSAMPLE_16PIXELS(top_u, cur_u, r_uv); \
+ UPSAMPLE_16PIXELS(top_v, cur_v, r_uv + 16); \
+ CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, r_uv, \
+ top_dst, bottom_dst, 16 * block + 1, 16); \
+ top_u += 8; \
+ cur_u += 8; \
+ top_v += 8; \
+ cur_v += 8; \
+ } \
+ \
+ UPSAMPLE_LAST_BLOCK(top_u, cur_u, leftover, r_uv); \
+ UPSAMPLE_LAST_BLOCK(top_v, cur_v, leftover, r_uv + 16); \
+ CONVERT2RGB_1(VP8YuvTo ## FMT, XSTEP, top_y, bottom_y, r_uv, \
+ top_dst, bottom_dst, last_pos, len - last_pos); \
+}
+
+// NEON variants of the fancy upsampler.
+NEON_UPSAMPLE_FUNC(UpsampleRgbLinePair, Rgb, 3)
+NEON_UPSAMPLE_FUNC(UpsampleBgrLinePair, Bgr, 3)
+NEON_UPSAMPLE_FUNC(UpsampleRgbaLinePair, Rgba, 4)
+NEON_UPSAMPLE_FUNC(UpsampleBgraLinePair, Bgra, 4)
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
+
+extern void WebPInitUpsamplersNEON(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersNEON(void) {
+ WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
+ WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
+ WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair;
+ WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair;
+ WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair;
+ WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair;
+}
+
+#endif // FANCY_UPSAMPLING
+
+#endif // WEBP_USE_NEON
+
+#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_NEON))
+WEBP_DSP_INIT_STUB(WebPInitUpsamplersNEON)
+#endif
diff --git a/drivers/webp/dsp/upsampling_sse2.c b/drivers/webp/dsp/upsampling_sse2.c
index 8cb275a02b..b85808e271 100644
--- a/drivers/webp/dsp/upsampling_sse2.c
+++ b/drivers/webp/dsp/upsampling_sse2.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// SSE2 version of YUV to RGB upsampling functions.
@@ -18,10 +20,6 @@
#include <string.h>
#include "./yuv.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
#ifdef FANCY_UPSAMPLING
// We compute (9*a + 3*b + 3*c + d + 8) / 16 as follows
@@ -49,23 +47,23 @@ extern "C" {
(out) = _mm_sub_epi8(tmp0, tmp4); /* (k + in + 1) / 2 - lsb_correction */ \
} while (0)
-// pack and store two alterning pixel rows
+// pack and store two alternating pixel rows
#define PACK_AND_STORE(a, b, da, db, out) do { \
- const __m128i ta = _mm_avg_epu8(a, da); /* (9a + 3b + 3c + d + 8) / 16 */ \
- const __m128i tb = _mm_avg_epu8(b, db); /* (3a + 9b + c + 3d + 8) / 16 */ \
- const __m128i t1 = _mm_unpacklo_epi8(ta, tb); \
- const __m128i t2 = _mm_unpackhi_epi8(ta, tb); \
- _mm_store_si128(((__m128i*)(out)) + 0, t1); \
- _mm_store_si128(((__m128i*)(out)) + 1, t2); \
+ const __m128i t_a = _mm_avg_epu8(a, da); /* (9a + 3b + 3c + d + 8) / 16 */ \
+ const __m128i t_b = _mm_avg_epu8(b, db); /* (3a + 9b + c + 3d + 8) / 16 */ \
+ const __m128i t_1 = _mm_unpacklo_epi8(t_a, t_b); \
+ const __m128i t_2 = _mm_unpackhi_epi8(t_a, t_b); \
+ _mm_store_si128(((__m128i*)(out)) + 0, t_1); \
+ _mm_store_si128(((__m128i*)(out)) + 1, t_2); \
} while (0)
// Loads 17 pixels each from rows r1 and r2 and generates 32 pixels.
#define UPSAMPLE_32PIXELS(r1, r2, out) { \
const __m128i one = _mm_set1_epi8(1); \
- const __m128i a = _mm_loadu_si128((__m128i*)&(r1)[0]); \
- const __m128i b = _mm_loadu_si128((__m128i*)&(r1)[1]); \
- const __m128i c = _mm_loadu_si128((__m128i*)&(r2)[0]); \
- const __m128i d = _mm_loadu_si128((__m128i*)&(r2)[1]); \
+ const __m128i a = _mm_loadu_si128((const __m128i*)&(r1)[0]); \
+ const __m128i b = _mm_loadu_si128((const __m128i*)&(r1)[1]); \
+ const __m128i c = _mm_loadu_si128((const __m128i*)&(r2)[0]); \
+ const __m128i d = _mm_loadu_si128((const __m128i*)&(r2)[1]); \
\
const __m128i s = _mm_avg_epu8(a, d); /* s = (a + d + 1) / 2 */ \
const __m128i t = _mm_avg_epu8(b, c); /* t = (b + c + 1) / 2 */ \
@@ -85,8 +83,8 @@ extern "C" {
GET_M(ad, s, diag2); /* diag2 = (3a + b + c + 3d) / 8 */ \
\
/* pack the alternate pixels */ \
- PACK_AND_STORE(a, b, diag1, diag2, &(out)[0 * 32]); \
- PACK_AND_STORE(c, d, diag2, diag1, &(out)[2 * 32]); \
+ PACK_AND_STORE(a, b, diag1, diag2, out + 0); /* store top */ \
+ PACK_AND_STORE(c, d, diag2, diag1, out + 2 * 32); /* store bottom */ \
}
// Turn the macro into a function for reducing code-size when non-critical
@@ -106,104 +104,140 @@ static void Upsample32Pixels(const uint8_t r1[], const uint8_t r2[],
Upsample32Pixels(r1, r2, out); \
}
-#define CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, uv, \
+#define CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, \
top_dst, bottom_dst, cur_x, num_pixels) { \
int n; \
- if (top_y) { \
- for (n = 0; n < (num_pixels); ++n) { \
- FUNC(top_y[(cur_x) + n], (uv)[n], (uv)[32 + n], \
- top_dst + ((cur_x) + n) * XSTEP); \
- } \
+ for (n = 0; n < (num_pixels); ++n) { \
+ FUNC(top_y[(cur_x) + n], r_u[n], r_v[n], \
+ top_dst + ((cur_x) + n) * XSTEP); \
} \
- if (bottom_y) { \
+ if (bottom_y != NULL) { \
for (n = 0; n < (num_pixels); ++n) { \
- FUNC(bottom_y[(cur_x) + n], (uv)[64 + n], (uv)[64 + 32 + n], \
+ FUNC(bottom_y[(cur_x) + n], r_u[64 + n], r_v[64 + n], \
bottom_dst + ((cur_x) + n) * XSTEP); \
} \
} \
}
+#define CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, \
+ top_dst, bottom_dst, cur_x) do { \
+ FUNC##32(top_y + (cur_x), r_u, r_v, top_dst + (cur_x) * XSTEP); \
+ if (bottom_y != NULL) { \
+ FUNC##32(bottom_y + (cur_x), r_u + 64, r_v + 64, \
+ bottom_dst + (cur_x) * XSTEP); \
+ } \
+} while (0)
+
#define SSE2_UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \
static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
const uint8_t* top_u, const uint8_t* top_v, \
const uint8_t* cur_u, const uint8_t* cur_v, \
uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
- int b; \
- /* 16 byte aligned array to cache reconstructed u and v */ \
+ int uv_pos, pos; \
+ /* 16byte-aligned array to cache reconstructed u and v */ \
uint8_t uv_buf[4 * 32 + 15]; \
- uint8_t* const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
- const int uv_len = (len + 1) >> 1; \
- /* 17 pixels must be read-able for each block */ \
- const int num_blocks = (uv_len - 1) >> 4; \
- const int leftover = uv_len - num_blocks * 16; \
- const int last_pos = 1 + 32 * num_blocks; \
- \
- const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \
- const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \
+ uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
+ uint8_t* const r_v = r_u + 32; \
\
- assert(len > 0); \
- /* Treat the first pixel in regular way */ \
- if (top_y) { \
- const int u0 = (top_u[0] + u_diag) >> 1; \
- const int v0 = (top_v[0] + v_diag) >> 1; \
- FUNC(top_y[0], u0, v0, top_dst); \
+ assert(top_y != NULL); \
+ { /* Treat the first pixel in regular way */ \
+ const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \
+ const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \
+ const int u0_t = (top_u[0] + u_diag) >> 1; \
+ const int v0_t = (top_v[0] + v_diag) >> 1; \
+ FUNC(top_y[0], u0_t, v0_t, top_dst); \
+ if (bottom_y != NULL) { \
+ const int u0_b = (cur_u[0] + u_diag) >> 1; \
+ const int v0_b = (cur_v[0] + v_diag) >> 1; \
+ FUNC(bottom_y[0], u0_b, v0_b, bottom_dst); \
+ } \
} \
- if (bottom_y) { \
- const int u0 = (cur_u[0] + u_diag) >> 1; \
- const int v0 = (cur_v[0] + v_diag) >> 1; \
- FUNC(bottom_y[0], u0, v0, bottom_dst); \
+ /* For UPSAMPLE_32PIXELS, 17 u/v values must be read-able for each block */ \
+ for (pos = 1, uv_pos = 0; pos + 32 + 1 <= len; pos += 32, uv_pos += 16) { \
+ UPSAMPLE_32PIXELS(top_u + uv_pos, cur_u + uv_pos, r_u); \
+ UPSAMPLE_32PIXELS(top_v + uv_pos, cur_v + uv_pos, r_v); \
+ CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, pos); \
} \
- \
- for (b = 0; b < num_blocks; ++b) { \
- UPSAMPLE_32PIXELS(top_u, cur_u, r_uv + 0 * 32); \
- UPSAMPLE_32PIXELS(top_v, cur_v, r_uv + 1 * 32); \
- CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, r_uv, top_dst, bottom_dst, \
- 32 * b + 1, 32) \
- top_u += 16; \
- cur_u += 16; \
- top_v += 16; \
- cur_v += 16; \
+ if (len > 1) { \
+ const int left_over = ((len + 1) >> 1) - (pos >> 1); \
+ assert(left_over > 0); \
+ UPSAMPLE_LAST_BLOCK(top_u + uv_pos, cur_u + uv_pos, left_over, r_u); \
+ UPSAMPLE_LAST_BLOCK(top_v + uv_pos, cur_v + uv_pos, left_over, r_v); \
+ CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, \
+ pos, len - pos); \
} \
- \
- UPSAMPLE_LAST_BLOCK(top_u, cur_u, leftover, r_uv + 0 * 32); \
- UPSAMPLE_LAST_BLOCK(top_v, cur_v, leftover, r_uv + 1 * 32); \
- CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, r_uv, top_dst, bottom_dst, \
- last_pos, len - last_pos); \
}
// SSE2 variants of the fancy upsampler.
-SSE2_UPSAMPLE_FUNC(UpsampleRgbLinePairSSE2, VP8YuvToRgb, 3)
-SSE2_UPSAMPLE_FUNC(UpsampleBgrLinePairSSE2, VP8YuvToBgr, 3)
-SSE2_UPSAMPLE_FUNC(UpsampleRgbaLinePairSSE2, VP8YuvToRgba, 4)
-SSE2_UPSAMPLE_FUNC(UpsampleBgraLinePairSSE2, VP8YuvToBgra, 4)
+SSE2_UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3)
+SSE2_UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3)
+SSE2_UPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4)
+SSE2_UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4)
#undef GET_M
#undef PACK_AND_STORE
#undef UPSAMPLE_32PIXELS
#undef UPSAMPLE_LAST_BLOCK
#undef CONVERT2RGB
+#undef CONVERT2RGB_32
#undef SSE2_UPSAMPLE_FUNC
//------------------------------------------------------------------------------
+// Entry point
extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
-void WebPInitUpsamplersSSE2(void) {
- WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePairSSE2;
- WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePairSSE2;
- WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePairSSE2;
- WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePairSSE2;
-}
+extern void WebPInitUpsamplersSSE2(void);
-void WebPInitPremultiplySSE2(void) {
- WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePairSSE2;
- WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePairSSE2;
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersSSE2(void) {
+ VP8YUVInitSSE2();
+ WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
+ WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
+ WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair;
+ WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair;
+ WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair;
+ WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair;
}
#endif // FANCY_UPSAMPLING
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
+//------------------------------------------------------------------------------
+
+extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */];
+extern void WebPInitYUV444ConvertersSSE2(void);
+
+#define YUV444_FUNC(FUNC_NAME, CALL, XSTEP) \
+extern void WebP##FUNC_NAME##C(const uint8_t* y, const uint8_t* u, \
+ const uint8_t* v, uint8_t* dst, int len); \
+static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
+ uint8_t* dst, int len) { \
+ int i; \
+ const int max_len = len & ~31; \
+ for (i = 0; i < max_len; i += 32) CALL(y + i, u + i, v + i, dst + i * XSTEP);\
+ if (i < len) { /* C-fallback */ \
+ WebP##FUNC_NAME##C(y + i, u + i, v + i, dst + i * XSTEP, len - i); \
+ } \
+}
-#endif // WEBP_USE_SSE2
+YUV444_FUNC(Yuv444ToRgba, VP8YuvToRgba32, 4);
+YUV444_FUNC(Yuv444ToBgra, VP8YuvToBgra32, 4);
+YUV444_FUNC(Yuv444ToRgb, VP8YuvToRgb32, 3);
+YUV444_FUNC(Yuv444ToBgr, VP8YuvToBgr32, 3);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersSSE2(void) {
+ VP8YUVInitSSE2();
+ WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba;
+ WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra;
+ WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb;
+ WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr;
+}
+
+#else
+
+WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersSSE2)
+
+#endif // WEBP_USE_SSE2
+
+#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_SSE2))
+WEBP_DSP_INIT_STUB(WebPInitUpsamplersSSE2)
+#endif
diff --git a/drivers/webp/dsp/yuv.c b/drivers/webp/dsp/yuv.c
index 7f05f9a3aa..f50a253168 100644
--- a/drivers/webp/dsp/yuv.c
+++ b/drivers/webp/dsp/yuv.c
@@ -1,26 +1,19 @@
// Copyright 2010 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
-// YUV->RGB conversion function
+// YUV->RGB conversion functions
//
// Author: Skal (pascal.massimino@gmail.com)
#include "./yuv.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-enum { YUV_HALF = 1 << (YUV_FIX - 1) };
-
-int16_t VP8kVToR[256], VP8kUToB[256];
-int32_t VP8kVToG[256], VP8kUToG[256];
-uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN];
-uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN];
+#if defined(WEBP_YUV_USE_TABLE)
static int done = 0;
@@ -28,11 +21,17 @@ static WEBP_INLINE uint8_t clip(int v, int max_value) {
return v < 0 ? 0 : v > max_value ? max_value : v;
}
-void VP8YUVInit(void) {
+int16_t VP8kVToR[256], VP8kUToB[256];
+int32_t VP8kVToG[256], VP8kUToG[256];
+uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN];
+uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN];
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInit(void) {
int i;
if (done) {
return;
}
+#ifndef USE_YUVj
for (i = 0; i < 256; ++i) {
VP8kVToR[i] = (89858 * (i - 128) + YUV_HALF) >> YUV_FIX;
VP8kUToG[i] = -22014 * (i - 128) + YUV_HALF;
@@ -44,9 +43,238 @@ void VP8YUVInit(void) {
VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255);
VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15);
}
+#else
+ for (i = 0; i < 256; ++i) {
+ VP8kVToR[i] = (91881 * (i - 128) + YUV_HALF) >> YUV_FIX;
+ VP8kUToG[i] = -22554 * (i - 128) + YUV_HALF;
+ VP8kVToG[i] = -46802 * (i - 128);
+ VP8kUToB[i] = (116130 * (i - 128) + YUV_HALF) >> YUV_FIX;
+ }
+ for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) {
+ const int k = i;
+ VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255);
+ VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15);
+ }
+#endif
+
done = 1;
}
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
+#else
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInit(void) {}
+
+#endif // WEBP_YUV_USE_TABLE
+
+//-----------------------------------------------------------------------------
+// Plain-C version
+
+#define ROW_FUNC(FUNC_NAME, FUNC, XSTEP) \
+static void FUNC_NAME(const uint8_t* y, \
+ const uint8_t* u, const uint8_t* v, \
+ uint8_t* dst, int len) { \
+ const uint8_t* const end = dst + (len & ~1) * XSTEP; \
+ while (dst != end) { \
+ FUNC(y[0], u[0], v[0], dst); \
+ FUNC(y[1], u[0], v[0], dst + XSTEP); \
+ y += 2; \
+ ++u; \
+ ++v; \
+ dst += 2 * XSTEP; \
+ } \
+ if (len & 1) { \
+ FUNC(y[0], u[0], v[0], dst); \
+ } \
+} \
+
+// All variants implemented.
+ROW_FUNC(YuvToRgbRow, VP8YuvToRgb, 3)
+ROW_FUNC(YuvToBgrRow, VP8YuvToBgr, 3)
+ROW_FUNC(YuvToRgbaRow, VP8YuvToRgba, 4)
+ROW_FUNC(YuvToBgraRow, VP8YuvToBgra, 4)
+ROW_FUNC(YuvToArgbRow, VP8YuvToArgb, 4)
+ROW_FUNC(YuvToRgba4444Row, VP8YuvToRgba4444, 2)
+ROW_FUNC(YuvToRgb565Row, VP8YuvToRgb565, 2)
+
+#undef ROW_FUNC
+
+// Main call for processing a plane with a WebPSamplerRowFunc function:
+void WebPSamplerProcessPlane(const uint8_t* y, int y_stride,
+ const uint8_t* u, const uint8_t* v, int uv_stride,
+ uint8_t* dst, int dst_stride,
+ int width, int height, WebPSamplerRowFunc func) {
+ int j;
+ for (j = 0; j < height; ++j) {
+ func(y, u, v, dst, width);
+ y += y_stride;
+ if (j & 1) {
+ u += uv_stride;
+ v += uv_stride;
+ }
+ dst += dst_stride;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Main call
+
+WebPSamplerRowFunc WebPSamplers[MODE_LAST];
+
+extern void WebPInitSamplersSSE2(void);
+extern void WebPInitSamplersMIPS32(void);
+extern void WebPInitSamplersMIPSdspR2(void);
+
+static volatile VP8CPUInfo yuv_last_cpuinfo_used =
+ (VP8CPUInfo)&yuv_last_cpuinfo_used;
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplers(void) {
+ if (yuv_last_cpuinfo_used == VP8GetCPUInfo) return;
+
+ WebPSamplers[MODE_RGB] = YuvToRgbRow;
+ WebPSamplers[MODE_RGBA] = YuvToRgbaRow;
+ WebPSamplers[MODE_BGR] = YuvToBgrRow;
+ WebPSamplers[MODE_BGRA] = YuvToBgraRow;
+ WebPSamplers[MODE_ARGB] = YuvToArgbRow;
+ WebPSamplers[MODE_RGBA_4444] = YuvToRgba4444Row;
+ WebPSamplers[MODE_RGB_565] = YuvToRgb565Row;
+ WebPSamplers[MODE_rgbA] = YuvToRgbaRow;
+ WebPSamplers[MODE_bgrA] = YuvToBgraRow;
+ WebPSamplers[MODE_Argb] = YuvToArgbRow;
+ WebPSamplers[MODE_rgbA_4444] = YuvToRgba4444Row;
+
+ // If defined, use CPUInfo() to overwrite some pointers with faster versions.
+ if (VP8GetCPUInfo != NULL) {
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ WebPInitSamplersSSE2();
+ }
+#endif // WEBP_USE_SSE2
+#if defined(WEBP_USE_MIPS32)
+ if (VP8GetCPUInfo(kMIPS32)) {
+ WebPInitSamplersMIPS32();
+ }
+#endif // WEBP_USE_MIPS32
+#if defined(WEBP_USE_MIPS_DSP_R2)
+ if (VP8GetCPUInfo(kMIPSdspR2)) {
+ WebPInitSamplersMIPSdspR2();
+ }
+#endif // WEBP_USE_MIPS_DSP_R2
+ }
+ yuv_last_cpuinfo_used = VP8GetCPUInfo;
+}
+
+//-----------------------------------------------------------------------------
+// ARGB -> YUV converters
+
+static void ConvertARGBToY(const uint32_t* argb, uint8_t* y, int width) {
+ int i;
+ for (i = 0; i < width; ++i) {
+ const uint32_t p = argb[i];
+ y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff,
+ YUV_HALF);
+ }
+}
+
+void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v,
+ int src_width, int do_store) {
+ // No rounding. Last pixel is dealt with separately.
+ const int uv_width = src_width >> 1;
+ int i;
+ for (i = 0; i < uv_width; ++i) {
+ const uint32_t v0 = argb[2 * i + 0];
+ const uint32_t v1 = argb[2 * i + 1];
+ // VP8RGBToU/V expects four accumulated pixels. Hence we need to
+ // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less.
+ const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe);
+ const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe);
+ const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe);
+ const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2);
+ const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2);
+ if (do_store) {
+ u[i] = tmp_u;
+ v[i] = tmp_v;
+ } else {
+ // Approximated average-of-four. But it's an acceptable diff.
+ u[i] = (u[i] + tmp_u + 1) >> 1;
+ v[i] = (v[i] + tmp_v + 1) >> 1;
+ }
+ }
+ if (src_width & 1) { // last pixel
+ const uint32_t v0 = argb[2 * i + 0];
+ const int r = (v0 >> 14) & 0x3fc;
+ const int g = (v0 >> 6) & 0x3fc;
+ const int b = (v0 << 2) & 0x3fc;
+ const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2);
+ const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2);
+ if (do_store) {
+ u[i] = tmp_u;
+ v[i] = tmp_v;
+ } else {
+ u[i] = (u[i] + tmp_u + 1) >> 1;
+ v[i] = (v[i] + tmp_v + 1) >> 1;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) {
+ int i;
+ for (i = 0; i < width; ++i, rgb += 3) {
+ y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF);
+ }
+}
+
+static void ConvertBGR24ToY(const uint8_t* bgr, uint8_t* y, int width) {
+ int i;
+ for (i = 0; i < width; ++i, bgr += 3) {
+ y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF);
+ }
+}
+
+void WebPConvertRGBA32ToUV_C(const uint16_t* rgb,
+ uint8_t* u, uint8_t* v, int width) {
+ int i;
+ for (i = 0; i < width; i += 1, rgb += 4) {
+ const int r = rgb[0], g = rgb[1], b = rgb[2];
+ u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2);
+ v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2);
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width);
+void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width);
+void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb,
+ uint8_t* u, uint8_t* v, int width);
+
+void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width);
+void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v,
+ int src_width, int do_store);
+
+static volatile VP8CPUInfo rgba_to_yuv_last_cpuinfo_used =
+ (VP8CPUInfo)&rgba_to_yuv_last_cpuinfo_used;
+
+extern void WebPInitConvertARGBToYUVSSE2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) {
+ if (rgba_to_yuv_last_cpuinfo_used == VP8GetCPUInfo) return;
+
+ WebPConvertARGBToY = ConvertARGBToY;
+ WebPConvertARGBToUV = WebPConvertARGBToUV_C;
+
+ WebPConvertRGB24ToY = ConvertRGB24ToY;
+ WebPConvertBGR24ToY = ConvertBGR24ToY;
+
+ WebPConvertRGBA32ToUV = WebPConvertRGBA32ToUV_C;
+
+ if (VP8GetCPUInfo != NULL) {
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ WebPInitConvertARGBToYUVSSE2();
+ }
+#endif // WEBP_USE_SSE2
+ }
+ rgba_to_yuv_last_cpuinfo_used = VP8GetCPUInfo;
+}
diff --git a/drivers/webp/dsp/yuv.h b/drivers/webp/dsp/yuv.h
index a569109c54..af435a5b3e 100644
--- a/drivers/webp/dsp/yuv.h
+++ b/drivers/webp/dsp/yuv.h
@@ -1,36 +1,165 @@
// Copyright 2010 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// inline YUV<->RGB conversion function
//
+// The exact naming is Y'CbCr, following the ITU-R BT.601 standard.
+// More information at: http://en.wikipedia.org/wiki/YCbCr
+// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16
+// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128
+// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128
+// We use 16bit fixed point operations for RGB->YUV conversion (YUV_FIX).
+//
+// For the Y'CbCr to RGB conversion, the BT.601 specification reads:
+// R = 1.164 * (Y-16) + 1.596 * (V-128)
+// G = 1.164 * (Y-16) - 0.813 * (V-128) - 0.391 * (U-128)
+// B = 1.164 * (Y-16) + 2.018 * (U-128)
+// where Y is in the [16,235] range, and U/V in the [16,240] range.
+// In the table-lookup version (WEBP_YUV_USE_TABLE), the common factor
+// "1.164 * (Y-16)" can be handled as an offset in the VP8kClip[] table.
+// So in this case the formulae should read:
+// R = 1.164 * [Y + 1.371 * (V-128) ] - 18.624
+// G = 1.164 * [Y - 0.698 * (V-128) - 0.336 * (U-128)] - 18.624
+// B = 1.164 * [Y + 1.733 * (U-128)] - 18.624
+// once factorized.
+// For YUV->RGB conversion, only 14bit fixed precision is used (YUV_FIX2).
+// That's the maximum possible for a convenient ARM implementation.
+//
// Author: Skal (pascal.massimino@gmail.com)
#ifndef WEBP_DSP_YUV_H_
#define WEBP_DSP_YUV_H_
+#include "./dsp.h"
#include "../dec/decode_vp8.h"
+// Define the following to use the LUT-based code:
+// #define WEBP_YUV_USE_TABLE
+
+#if defined(WEBP_EXPERIMENTAL_FEATURES)
+// Do NOT activate this feature for real compression. This is only experimental!
+// This flag is for comparison purpose against JPEG's "YUVj" natural colorspace.
+// This colorspace is close to Rec.601's Y'CbCr model with the notable
+// difference of allowing larger range for luma/chroma.
+// See http://en.wikipedia.org/wiki/YCbCr#JPEG_conversion paragraph, and its
+// difference with http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
+// #define USE_YUVj
+#endif
+
//------------------------------------------------------------------------------
// YUV -> RGB conversion
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
-enum { YUV_FIX = 16, // fixed-point precision
- YUV_RANGE_MIN = -227, // min value of r/g/b output
- YUV_RANGE_MAX = 256 + 226 // max value of r/g/b output
+enum {
+ YUV_FIX = 16, // fixed-point precision for RGB->YUV
+ YUV_HALF = 1 << (YUV_FIX - 1),
+ YUV_MASK = (256 << YUV_FIX) - 1,
+ YUV_RANGE_MIN = -227, // min value of r/g/b output
+ YUV_RANGE_MAX = 256 + 226, // max value of r/g/b output
+
+ YUV_FIX2 = 14, // fixed-point precision for YUV->RGB
+ YUV_HALF2 = 1 << (YUV_FIX2 - 1),
+ YUV_MASK2 = (256 << YUV_FIX2) - 1
};
+
+// These constants are 14b fixed-point version of ITU-R BT.601 constants.
+#define kYScale 19077 // 1.164 = 255 / 219
+#define kVToR 26149 // 1.596 = 255 / 112 * 0.701
+#define kUToG 6419 // 0.391 = 255 / 112 * 0.886 * 0.114 / 0.587
+#define kVToG 13320 // 0.813 = 255 / 112 * 0.701 * 0.299 / 0.587
+#define kUToB 33050 // 2.018 = 255 / 112 * 0.886
+#define kRCst (-kYScale * 16 - kVToR * 128 + YUV_HALF2)
+#define kGCst (-kYScale * 16 + kUToG * 128 + kVToG * 128 + YUV_HALF2)
+#define kBCst (-kYScale * 16 - kUToB * 128 + YUV_HALF2)
+
+//------------------------------------------------------------------------------
+
+#if !defined(WEBP_YUV_USE_TABLE)
+
+// slower on x86 by ~7-8%, but bit-exact with the SSE2 version
+
+static WEBP_INLINE int VP8Clip8(int v) {
+ return ((v & ~YUV_MASK2) == 0) ? (v >> YUV_FIX2) : (v < 0) ? 0 : 255;
+}
+
+static WEBP_INLINE int VP8YUVToR(int y, int v) {
+ return VP8Clip8(kYScale * y + kVToR * v + kRCst);
+}
+
+static WEBP_INLINE int VP8YUVToG(int y, int u, int v) {
+ return VP8Clip8(kYScale * y - kUToG * u - kVToG * v + kGCst);
+}
+
+static WEBP_INLINE int VP8YUVToB(int y, int u) {
+ return VP8Clip8(kYScale * y + kUToB * u + kBCst);
+}
+
+static WEBP_INLINE void VP8YuvToRgb(int y, int u, int v,
+ uint8_t* const rgb) {
+ rgb[0] = VP8YUVToR(y, v);
+ rgb[1] = VP8YUVToG(y, u, v);
+ rgb[2] = VP8YUVToB(y, u);
+}
+
+static WEBP_INLINE void VP8YuvToBgr(int y, int u, int v,
+ uint8_t* const bgr) {
+ bgr[0] = VP8YUVToB(y, u);
+ bgr[1] = VP8YUVToG(y, u, v);
+ bgr[2] = VP8YUVToR(y, v);
+}
+
+static WEBP_INLINE void VP8YuvToRgb565(int y, int u, int v,
+ uint8_t* const rgb) {
+ const int r = VP8YUVToR(y, v); // 5 usable bits
+ const int g = VP8YUVToG(y, u, v); // 6 usable bits
+ const int b = VP8YUVToB(y, u); // 5 usable bits
+ const int rg = (r & 0xf8) | (g >> 5);
+ const int gb = ((g << 3) & 0xe0) | (b >> 3);
+#ifdef WEBP_SWAP_16BIT_CSP
+ rgb[0] = gb;
+ rgb[1] = rg;
+#else
+ rgb[0] = rg;
+ rgb[1] = gb;
+#endif
+}
+
+static WEBP_INLINE void VP8YuvToRgba4444(int y, int u, int v,
+ uint8_t* const argb) {
+ const int r = VP8YUVToR(y, v); // 4 usable bits
+ const int g = VP8YUVToG(y, u, v); // 4 usable bits
+ const int b = VP8YUVToB(y, u); // 4 usable bits
+ const int rg = (r & 0xf0) | (g >> 4);
+ const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits
+#ifdef WEBP_SWAP_16BIT_CSP
+ argb[0] = ba;
+ argb[1] = rg;
+#else
+ argb[0] = rg;
+ argb[1] = ba;
+#endif
+}
+
+#else
+
+// Table-based version, not totally equivalent to the SSE2 version.
+// Rounding diff is only +/-1 though.
+
extern int16_t VP8kVToR[256], VP8kUToB[256];
extern int32_t VP8kVToG[256], VP8kUToG[256];
extern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN];
extern uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN];
-static WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v,
+static WEBP_INLINE void VP8YuvToRgb(int y, int u, int v,
uint8_t* const rgb) {
const int r_off = VP8kVToR[v];
const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
@@ -40,42 +169,60 @@ static WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v,
rgb[2] = VP8kClip[y + b_off - YUV_RANGE_MIN];
}
-static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v,
- uint8_t* const rgb) {
+static WEBP_INLINE void VP8YuvToBgr(int y, int u, int v,
+ uint8_t* const bgr) {
const int r_off = VP8kVToR[v];
const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
const int b_off = VP8kUToB[u];
- rgb[0] = ((VP8kClip[y + r_off - YUV_RANGE_MIN] & 0xf8) |
- (VP8kClip[y + g_off - YUV_RANGE_MIN] >> 5));
- rgb[1] = (((VP8kClip[y + g_off - YUV_RANGE_MIN] << 3) & 0xe0) |
- (VP8kClip[y + b_off - YUV_RANGE_MIN] >> 3));
-}
-
-static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v,
- uint8_t* const argb) {
- argb[0] = 0xff;
- VP8YuvToRgb(y, u, v, argb + 1);
+ bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN];
+ bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN];
+ bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN];
}
-static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v,
- uint8_t* const argb) {
+static WEBP_INLINE void VP8YuvToRgb565(int y, int u, int v,
+ uint8_t* const rgb) {
const int r_off = VP8kVToR[v];
const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
const int b_off = VP8kUToB[u];
- // Don't update alpha (last 4 bits of argb[1])
- argb[0] = ((VP8kClip4Bits[y + r_off - YUV_RANGE_MIN] << 4) |
- VP8kClip4Bits[y + g_off - YUV_RANGE_MIN]);
- argb[1] = 0x0f | (VP8kClip4Bits[y + b_off - YUV_RANGE_MIN] << 4);
+ const int rg = ((VP8kClip[y + r_off - YUV_RANGE_MIN] & 0xf8) |
+ (VP8kClip[y + g_off - YUV_RANGE_MIN] >> 5));
+ const int gb = (((VP8kClip[y + g_off - YUV_RANGE_MIN] << 3) & 0xe0) |
+ (VP8kClip[y + b_off - YUV_RANGE_MIN] >> 3));
+#ifdef WEBP_SWAP_16BIT_CSP
+ rgb[0] = gb;
+ rgb[1] = rg;
+#else
+ rgb[0] = rg;
+ rgb[1] = gb;
+#endif
}
-static WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v,
- uint8_t* const bgr) {
+static WEBP_INLINE void VP8YuvToRgba4444(int y, int u, int v,
+ uint8_t* const argb) {
const int r_off = VP8kVToR[v];
const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
const int b_off = VP8kUToB[u];
- bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN];
- bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN];
- bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN];
+ const int rg = ((VP8kClip4Bits[y + r_off - YUV_RANGE_MIN] << 4) |
+ VP8kClip4Bits[y + g_off - YUV_RANGE_MIN]);
+ const int ba = (VP8kClip4Bits[y + b_off - YUV_RANGE_MIN] << 4) | 0x0f;
+#ifdef WEBP_SWAP_16BIT_CSP
+ argb[0] = ba;
+ argb[1] = rg;
+#else
+ argb[0] = rg;
+ argb[1] = ba;
+#endif
+}
+
+#endif // WEBP_YUV_USE_TABLE
+
+//-----------------------------------------------------------------------------
+// Alpha handling variants
+
+static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v,
+ uint8_t* const argb) {
+ argb[0] = 0xff;
+ VP8YuvToRgb(y, u, v, argb + 1);
}
static WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v,
@@ -93,35 +240,79 @@ static WEBP_INLINE void VP8YuvToRgba(uint8_t y, uint8_t u, uint8_t v,
// Must be called before everything, to initialize the tables.
void VP8YUVInit(void);
+//-----------------------------------------------------------------------------
+// SSE2 extra functions (mostly for upsampling_sse2.c)
+
+#if defined(WEBP_USE_SSE2)
+
+// When the following is defined, tables are initialized statically, adding ~12k
+// to the binary size. Otherwise, they are initialized at run-time (small cost).
+#define WEBP_YUV_USE_SSE2_TABLES
+
+// Process 32 pixels and store the result (24b or 32b per pixel) in *dst.
+void VP8YuvToRgba32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst);
+void VP8YuvToRgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst);
+void VP8YuvToBgra32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst);
+void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst);
+
+// Must be called to initialize tables before using the functions.
+void VP8YUVInitSSE2(void);
+
+#endif // WEBP_USE_SSE2
+
//------------------------------------------------------------------------------
// RGB -> YUV conversion
-// The exact naming is Y'CbCr, following the ITU-R BT.601 standard.
-// More information at: http://en.wikipedia.org/wiki/YCbCr
-// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16
-// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128
-// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128
-// We use 16bit fixed point operations.
-static WEBP_INLINE int VP8ClipUV(int v) {
- v = (v + (257 << (YUV_FIX + 2 - 1))) >> (YUV_FIX + 2);
- return ((v & ~0xff) == 0) ? v : (v < 0) ? 0 : 255;
+// Stub functions that can be called with various rounding values:
+static WEBP_INLINE int VP8ClipUV(int uv, int rounding) {
+ uv = (uv + rounding + (128 << (YUV_FIX + 2))) >> (YUV_FIX + 2);
+ return ((uv & ~0xff) == 0) ? uv : (uv < 0) ? 0 : 255;
}
-static WEBP_INLINE int VP8RGBToY(int r, int g, int b) {
- const int kRound = (1 << (YUV_FIX - 1)) + (16 << YUV_FIX);
+#ifndef USE_YUVj
+
+static WEBP_INLINE int VP8RGBToY(int r, int g, int b, int rounding) {
const int luma = 16839 * r + 33059 * g + 6420 * b;
- return (luma + kRound) >> YUV_FIX; // no need to clip
+ return (luma + rounding + (16 << YUV_FIX)) >> YUV_FIX; // no need to clip
}
-static WEBP_INLINE int VP8RGBToU(int r, int g, int b) {
- return VP8ClipUV(-9719 * r - 19081 * g + 28800 * b);
+static WEBP_INLINE int VP8RGBToU(int r, int g, int b, int rounding) {
+ const int u = -9719 * r - 19081 * g + 28800 * b;
+ return VP8ClipUV(u, rounding);
}
-static WEBP_INLINE int VP8RGBToV(int r, int g, int b) {
- return VP8ClipUV(+28800 * r - 24116 * g - 4684 * b);
+static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) {
+ const int v = +28800 * r - 24116 * g - 4684 * b;
+ return VP8ClipUV(v, rounding);
+}
+
+#else
+
+// This JPEG-YUV colorspace, only for comparison!
+// These are also 16bit precision coefficients from Rec.601, but with full
+// [0..255] output range.
+static WEBP_INLINE int VP8RGBToY(int r, int g, int b, int rounding) {
+ const int luma = 19595 * r + 38470 * g + 7471 * b;
+ return (luma + rounding) >> YUV_FIX; // no need to clip
}
-#if defined(__cplusplus) || defined(c_plusplus)
+static WEBP_INLINE int VP8RGBToU(int r, int g, int b, int rounding) {
+ const int u = -11058 * r - 21710 * g + 32768 * b;
+ return VP8ClipUV(u, rounding);
+}
+
+static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) {
+ const int v = 32768 * r - 27439 * g - 5329 * b;
+ return VP8ClipUV(v, rounding);
+}
+
+#endif // USE_YUVj
+
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/dsp/yuv_mips32.c b/drivers/webp/dsp/yuv_mips32.c
new file mode 100644
index 0000000000..018f8ab774
--- /dev/null
+++ b/drivers/webp/dsp/yuv_mips32.c
@@ -0,0 +1,103 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// MIPS version of YUV to RGB upsampling functions.
+//
+// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
+// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS32)
+
+#include "./yuv.h"
+
+//------------------------------------------------------------------------------
+// simple point-sampling
+
+#define ROW_FUNC(FUNC_NAME, XSTEP, R, G, B, A) \
+static void FUNC_NAME(const uint8_t* y, \
+ const uint8_t* u, const uint8_t* v, \
+ uint8_t* dst, int len) { \
+ int i, r, g, b; \
+ int temp0, temp1, temp2, temp3, temp4; \
+ for (i = 0; i < (len >> 1); i++) { \
+ temp1 = kVToR * v[0]; \
+ temp3 = kVToG * v[0]; \
+ temp2 = kUToG * u[0]; \
+ temp4 = kUToB * u[0]; \
+ temp0 = kYScale * y[0]; \
+ temp1 += kRCst; \
+ temp3 -= kGCst; \
+ temp2 += temp3; \
+ temp4 += kBCst; \
+ r = VP8Clip8(temp0 + temp1); \
+ g = VP8Clip8(temp0 - temp2); \
+ b = VP8Clip8(temp0 + temp4); \
+ temp0 = kYScale * y[1]; \
+ dst[R] = r; \
+ dst[G] = g; \
+ dst[B] = b; \
+ if (A) dst[A] = 0xff; \
+ r = VP8Clip8(temp0 + temp1); \
+ g = VP8Clip8(temp0 - temp2); \
+ b = VP8Clip8(temp0 + temp4); \
+ dst[R + XSTEP] = r; \
+ dst[G + XSTEP] = g; \
+ dst[B + XSTEP] = b; \
+ if (A) dst[A + XSTEP] = 0xff; \
+ y += 2; \
+ ++u; \
+ ++v; \
+ dst += 2 * XSTEP; \
+ } \
+ if (len & 1) { \
+ temp1 = kVToR * v[0]; \
+ temp3 = kVToG * v[0]; \
+ temp2 = kUToG * u[0]; \
+ temp4 = kUToB * u[0]; \
+ temp0 = kYScale * y[0]; \
+ temp1 += kRCst; \
+ temp3 -= kGCst; \
+ temp2 += temp3; \
+ temp4 += kBCst; \
+ r = VP8Clip8(temp0 + temp1); \
+ g = VP8Clip8(temp0 - temp2); \
+ b = VP8Clip8(temp0 + temp4); \
+ dst[R] = r; \
+ dst[G] = g; \
+ dst[B] = b; \
+ if (A) dst[A] = 0xff; \
+ } \
+}
+
+ROW_FUNC(YuvToRgbRow, 3, 0, 1, 2, 0)
+ROW_FUNC(YuvToRgbaRow, 4, 0, 1, 2, 3)
+ROW_FUNC(YuvToBgrRow, 3, 2, 1, 0, 0)
+ROW_FUNC(YuvToBgraRow, 4, 2, 1, 0, 3)
+
+#undef ROW_FUNC
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void WebPInitSamplersMIPS32(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersMIPS32(void) {
+ WebPSamplers[MODE_RGB] = YuvToRgbRow;
+ WebPSamplers[MODE_RGBA] = YuvToRgbaRow;
+ WebPSamplers[MODE_BGR] = YuvToBgrRow;
+ WebPSamplers[MODE_BGRA] = YuvToBgraRow;
+}
+
+#else // !WEBP_USE_MIPS32
+
+WEBP_DSP_INIT_STUB(WebPInitSamplersMIPS32)
+
+#endif // WEBP_USE_MIPS32
diff --git a/drivers/webp/dsp/yuv_mips_dsp_r2.c b/drivers/webp/dsp/yuv_mips_dsp_r2.c
new file mode 100644
index 0000000000..45a2200352
--- /dev/null
+++ b/drivers/webp/dsp/yuv_mips_dsp_r2.c
@@ -0,0 +1,134 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// MIPS DSPr2 version of YUV to RGB upsampling functions.
+//
+// Author(s): Branimir Vasic (branimir.vasic@imgtec.com)
+// Djordje Pesut (djordje.pesut@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MIPS_DSP_R2)
+
+#include "./yuv.h"
+
+//------------------------------------------------------------------------------
+// simple point-sampling
+
+#define ROW_FUNC_PART_1() \
+ "lbu %[temp3], 0(%[v]) \n\t" \
+ "lbu %[temp4], 0(%[u]) \n\t" \
+ "lbu %[temp0], 0(%[y]) \n\t" \
+ "mul %[temp1], %[t_con_1], %[temp3] \n\t" \
+ "mul %[temp3], %[t_con_2], %[temp3] \n\t" \
+ "mul %[temp2], %[t_con_3], %[temp4] \n\t" \
+ "mul %[temp4], %[t_con_4], %[temp4] \n\t" \
+ "mul %[temp0], %[t_con_5], %[temp0] \n\t" \
+ "addu %[temp1], %[temp1], %[t_con_6] \n\t" \
+ "subu %[temp3], %[temp3], %[t_con_7] \n\t" \
+ "addu %[temp2], %[temp2], %[temp3] \n\t" \
+ "addu %[temp4], %[temp4], %[t_con_8] \n\t" \
+
+#define ROW_FUNC_PART_2(R, G, B, K) \
+ "addu %[temp5], %[temp0], %[temp1] \n\t" \
+ "subu %[temp6], %[temp0], %[temp2] \n\t" \
+ "addu %[temp7], %[temp0], %[temp4] \n\t" \
+".if " #K " \n\t" \
+ "lbu %[temp0], 1(%[y]) \n\t" \
+".endif \n\t" \
+ "shll_s.w %[temp5], %[temp5], 9 \n\t" \
+ "shll_s.w %[temp6], %[temp6], 9 \n\t" \
+".if " #K " \n\t" \
+ "mul %[temp0], %[t_con_5], %[temp0] \n\t" \
+".endif \n\t" \
+ "shll_s.w %[temp7], %[temp7], 9 \n\t" \
+ "precrqu_s.qb.ph %[temp5], %[temp5], $zero \n\t" \
+ "precrqu_s.qb.ph %[temp6], %[temp6], $zero \n\t" \
+ "precrqu_s.qb.ph %[temp7], %[temp7], $zero \n\t" \
+ "srl %[temp5], %[temp5], 24 \n\t" \
+ "srl %[temp6], %[temp6], 24 \n\t" \
+ "srl %[temp7], %[temp7], 24 \n\t" \
+ "sb %[temp5], " #R "(%[dst]) \n\t" \
+ "sb %[temp6], " #G "(%[dst]) \n\t" \
+ "sb %[temp7], " #B "(%[dst]) \n\t" \
+
+#define ASM_CLOBBER_LIST() \
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \
+ [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \
+ [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) \
+ : [t_con_1]"r"(t_con_1), [t_con_2]"r"(t_con_2), [t_con_3]"r"(t_con_3), \
+ [t_con_4]"r"(t_con_4), [t_con_5]"r"(t_con_5), [t_con_6]"r"(t_con_6), \
+ [u]"r"(u), [v]"r"(v), [y]"r"(y), [dst]"r"(dst), \
+ [t_con_7]"r"(t_con_7), [t_con_8]"r"(t_con_8) \
+ : "memory", "hi", "lo" \
+
+#define ROW_FUNC(FUNC_NAME, XSTEP, R, G, B, A) \
+static void FUNC_NAME(const uint8_t* y, \
+ const uint8_t* u, const uint8_t* v, \
+ uint8_t* dst, int len) { \
+ int i; \
+ uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; \
+ const int t_con_1 = kVToR; \
+ const int t_con_2 = kVToG; \
+ const int t_con_3 = kUToG; \
+ const int t_con_4 = kUToB; \
+ const int t_con_5 = kYScale; \
+ const int t_con_6 = kRCst; \
+ const int t_con_7 = kGCst; \
+ const int t_con_8 = kBCst; \
+ for (i = 0; i < (len >> 1); i++) { \
+ __asm__ volatile ( \
+ ROW_FUNC_PART_1() \
+ ROW_FUNC_PART_2(R, G, B, 1) \
+ ROW_FUNC_PART_2(R + XSTEP, G + XSTEP, B + XSTEP, 0) \
+ ASM_CLOBBER_LIST() \
+ ); \
+ if (A) dst[A] = dst[A + XSTEP] = 0xff; \
+ y += 2; \
+ ++u; \
+ ++v; \
+ dst += 2 * XSTEP; \
+ } \
+ if (len & 1) { \
+ __asm__ volatile ( \
+ ROW_FUNC_PART_1() \
+ ROW_FUNC_PART_2(R, G, B, 0) \
+ ASM_CLOBBER_LIST() \
+ ); \
+ if (A) dst[A] = 0xff; \
+ } \
+}
+
+ROW_FUNC(YuvToRgbRow, 3, 0, 1, 2, 0)
+ROW_FUNC(YuvToRgbaRow, 4, 0, 1, 2, 3)
+ROW_FUNC(YuvToBgrRow, 3, 2, 1, 0, 0)
+ROW_FUNC(YuvToBgraRow, 4, 2, 1, 0, 3)
+
+#undef ROW_FUNC
+#undef ASM_CLOBBER_LIST
+#undef ROW_FUNC_PART_2
+#undef ROW_FUNC_PART_1
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void WebPInitSamplersMIPSdspR2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersMIPSdspR2(void) {
+ WebPSamplers[MODE_RGB] = YuvToRgbRow;
+ WebPSamplers[MODE_RGBA] = YuvToRgbaRow;
+ WebPSamplers[MODE_BGR] = YuvToBgrRow;
+ WebPSamplers[MODE_BGRA] = YuvToBgraRow;
+}
+
+#else // !WEBP_USE_MIPS_DSP_R2
+
+WEBP_DSP_INIT_STUB(WebPInitSamplersMIPSdspR2)
+
+#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/yuv_sse2.c b/drivers/webp/dsp/yuv_sse2.c
new file mode 100644
index 0000000000..283b3af228
--- /dev/null
+++ b/drivers/webp/dsp/yuv_sse2.c
@@ -0,0 +1,606 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// YUV->RGB conversion functions
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./yuv.h"
+
+#if defined(WEBP_USE_SSE2)
+
+#include <emmintrin.h>
+#include <string.h> // for memcpy
+
+typedef union { // handy struct for converting SSE2 registers
+ int32_t i32[4];
+ uint8_t u8[16];
+ __m128i m;
+} VP8kCstSSE2;
+
+#if defined(WEBP_YUV_USE_SSE2_TABLES)
+
+#include "./yuv_tables_sse2.h"
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInitSSE2(void) {}
+
+#else
+
+static int done_sse2 = 0;
+static VP8kCstSSE2 VP8kUtoRGBA[256], VP8kVtoRGBA[256], VP8kYtoRGBA[256];
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInitSSE2(void) {
+ if (!done_sse2) {
+ int i;
+ for (i = 0; i < 256; ++i) {
+ VP8kYtoRGBA[i].i32[0] =
+ VP8kYtoRGBA[i].i32[1] =
+ VP8kYtoRGBA[i].i32[2] = (i - 16) * kYScale + YUV_HALF2;
+ VP8kYtoRGBA[i].i32[3] = 0xff << YUV_FIX2;
+
+ VP8kUtoRGBA[i].i32[0] = 0;
+ VP8kUtoRGBA[i].i32[1] = -kUToG * (i - 128);
+ VP8kUtoRGBA[i].i32[2] = kUToB * (i - 128);
+ VP8kUtoRGBA[i].i32[3] = 0;
+
+ VP8kVtoRGBA[i].i32[0] = kVToR * (i - 128);
+ VP8kVtoRGBA[i].i32[1] = -kVToG * (i - 128);
+ VP8kVtoRGBA[i].i32[2] = 0;
+ VP8kVtoRGBA[i].i32[3] = 0;
+ }
+ done_sse2 = 1;
+
+#if 0 // code used to generate 'yuv_tables_sse2.h'
+ printf("static const VP8kCstSSE2 VP8kYtoRGBA[256] = {\n");
+ for (i = 0; i < 256; ++i) {
+ printf(" {{0x%.8x, 0x%.8x, 0x%.8x, 0x%.8x}},\n",
+ VP8kYtoRGBA[i].i32[0], VP8kYtoRGBA[i].i32[1],
+ VP8kYtoRGBA[i].i32[2], VP8kYtoRGBA[i].i32[3]);
+ }
+ printf("};\n\n");
+ printf("static const VP8kCstSSE2 VP8kUtoRGBA[256] = {\n");
+ for (i = 0; i < 256; ++i) {
+ printf(" {{0, 0x%.8x, 0x%.8x, 0}},\n",
+ VP8kUtoRGBA[i].i32[1], VP8kUtoRGBA[i].i32[2]);
+ }
+ printf("};\n\n");
+ printf("static VP8kCstSSE2 VP8kVtoRGBA[256] = {\n");
+ for (i = 0; i < 256; ++i) {
+ printf(" {{0x%.8x, 0x%.8x, 0, 0}},\n",
+ VP8kVtoRGBA[i].i32[0], VP8kVtoRGBA[i].i32[1]);
+ }
+ printf("};\n\n");
+#endif
+ }
+}
+
+#endif // WEBP_YUV_USE_SSE2_TABLES
+
+//-----------------------------------------------------------------------------
+
+static WEBP_INLINE __m128i LoadUVPart(int u, int v) {
+ const __m128i u_part = _mm_loadu_si128(&VP8kUtoRGBA[u].m);
+ const __m128i v_part = _mm_loadu_si128(&VP8kVtoRGBA[v].m);
+ const __m128i uv_part = _mm_add_epi32(u_part, v_part);
+ return uv_part;
+}
+
+static WEBP_INLINE __m128i GetRGBA32bWithUV(int y, const __m128i uv_part) {
+ const __m128i y_part = _mm_loadu_si128(&VP8kYtoRGBA[y].m);
+ const __m128i rgba1 = _mm_add_epi32(y_part, uv_part);
+ const __m128i rgba2 = _mm_srai_epi32(rgba1, YUV_FIX2);
+ return rgba2;
+}
+
+static WEBP_INLINE __m128i GetRGBA32b(int y, int u, int v) {
+ const __m128i uv_part = LoadUVPart(u, v);
+ return GetRGBA32bWithUV(y, uv_part);
+}
+
+static WEBP_INLINE void YuvToRgbSSE2(uint8_t y, uint8_t u, uint8_t v,
+ uint8_t* const rgb) {
+ const __m128i tmp0 = GetRGBA32b(y, u, v);
+ const __m128i tmp1 = _mm_packs_epi32(tmp0, tmp0);
+ const __m128i tmp2 = _mm_packus_epi16(tmp1, tmp1);
+ // Note: we store 8 bytes at a time, not 3 bytes! -> memory stomp
+ _mm_storel_epi64((__m128i*)rgb, tmp2);
+}
+
+static WEBP_INLINE void YuvToBgrSSE2(uint8_t y, uint8_t u, uint8_t v,
+ uint8_t* const bgr) {
+ const __m128i tmp0 = GetRGBA32b(y, u, v);
+ const __m128i tmp1 = _mm_shuffle_epi32(tmp0, _MM_SHUFFLE(3, 0, 1, 2));
+ const __m128i tmp2 = _mm_packs_epi32(tmp1, tmp1);
+ const __m128i tmp3 = _mm_packus_epi16(tmp2, tmp2);
+ // Note: we store 8 bytes at a time, not 3 bytes! -> memory stomp
+ _mm_storel_epi64((__m128i*)bgr, tmp3);
+}
+
+//-----------------------------------------------------------------------------
+// Convert spans of 32 pixels to various RGB formats for the fancy upsampler.
+
+void VP8YuvToRgba32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst) {
+ int n;
+ for (n = 0; n < 32; n += 4) {
+ const __m128i tmp0_1 = GetRGBA32b(y[n + 0], u[n + 0], v[n + 0]);
+ const __m128i tmp0_2 = GetRGBA32b(y[n + 1], u[n + 1], v[n + 1]);
+ const __m128i tmp0_3 = GetRGBA32b(y[n + 2], u[n + 2], v[n + 2]);
+ const __m128i tmp0_4 = GetRGBA32b(y[n + 3], u[n + 3], v[n + 3]);
+ const __m128i tmp1_1 = _mm_packs_epi32(tmp0_1, tmp0_2);
+ const __m128i tmp1_2 = _mm_packs_epi32(tmp0_3, tmp0_4);
+ const __m128i tmp2 = _mm_packus_epi16(tmp1_1, tmp1_2);
+ _mm_storeu_si128((__m128i*)dst, tmp2);
+ dst += 4 * 4;
+ }
+}
+
+void VP8YuvToBgra32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst) {
+ int n;
+ for (n = 0; n < 32; n += 2) {
+ const __m128i tmp0_1 = GetRGBA32b(y[n + 0], u[n + 0], v[n + 0]);
+ const __m128i tmp0_2 = GetRGBA32b(y[n + 1], u[n + 1], v[n + 1]);
+ const __m128i tmp1_1 = _mm_shuffle_epi32(tmp0_1, _MM_SHUFFLE(3, 0, 1, 2));
+ const __m128i tmp1_2 = _mm_shuffle_epi32(tmp0_2, _MM_SHUFFLE(3, 0, 1, 2));
+ const __m128i tmp2_1 = _mm_packs_epi32(tmp1_1, tmp1_2);
+ const __m128i tmp3 = _mm_packus_epi16(tmp2_1, tmp2_1);
+ _mm_storel_epi64((__m128i*)dst, tmp3);
+ dst += 4 * 2;
+ }
+}
+
+void VP8YuvToRgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst) {
+ int n;
+ uint8_t tmp0[2 * 3 + 5 + 15];
+ uint8_t* const tmp = (uint8_t*)((uintptr_t)(tmp0 + 15) & ~15); // align
+ for (n = 0; n < 30; ++n) { // we directly stomp the *dst memory
+ YuvToRgbSSE2(y[n], u[n], v[n], dst + n * 3);
+ }
+ // Last two pixels are special: we write in a tmp buffer before sending
+ // to dst.
+ YuvToRgbSSE2(y[n + 0], u[n + 0], v[n + 0], tmp + 0);
+ YuvToRgbSSE2(y[n + 1], u[n + 1], v[n + 1], tmp + 3);
+ memcpy(dst + n * 3, tmp, 2 * 3);
+}
+
+void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst) {
+ int n;
+ uint8_t tmp0[2 * 3 + 5 + 15];
+ uint8_t* const tmp = (uint8_t*)((uintptr_t)(tmp0 + 15) & ~15); // align
+ for (n = 0; n < 30; ++n) {
+ YuvToBgrSSE2(y[n], u[n], v[n], dst + n * 3);
+ }
+ YuvToBgrSSE2(y[n + 0], u[n + 0], v[n + 0], tmp + 0);
+ YuvToBgrSSE2(y[n + 1], u[n + 1], v[n + 1], tmp + 3);
+ memcpy(dst + n * 3, tmp, 2 * 3);
+}
+
+//-----------------------------------------------------------------------------
+// Arbitrary-length row conversion functions
+
+static void YuvToRgbaRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst, int len) {
+ int n;
+ for (n = 0; n + 4 <= len; n += 4) {
+ const __m128i uv_0 = LoadUVPart(u[0], v[0]);
+ const __m128i uv_1 = LoadUVPart(u[1], v[1]);
+ const __m128i tmp0_1 = GetRGBA32bWithUV(y[0], uv_0);
+ const __m128i tmp0_2 = GetRGBA32bWithUV(y[1], uv_0);
+ const __m128i tmp0_3 = GetRGBA32bWithUV(y[2], uv_1);
+ const __m128i tmp0_4 = GetRGBA32bWithUV(y[3], uv_1);
+ const __m128i tmp1_1 = _mm_packs_epi32(tmp0_1, tmp0_2);
+ const __m128i tmp1_2 = _mm_packs_epi32(tmp0_3, tmp0_4);
+ const __m128i tmp2 = _mm_packus_epi16(tmp1_1, tmp1_2);
+ _mm_storeu_si128((__m128i*)dst, tmp2);
+ dst += 4 * 4;
+ y += 4;
+ u += 2;
+ v += 2;
+ }
+ // Finish off
+ while (n < len) {
+ VP8YuvToRgba(y[0], u[0], v[0], dst);
+ dst += 4;
+ ++y;
+ u += (n & 1);
+ v += (n & 1);
+ ++n;
+ }
+}
+
+static void YuvToBgraRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst, int len) {
+ int n;
+ for (n = 0; n + 2 <= len; n += 2) {
+ const __m128i uv_0 = LoadUVPart(u[0], v[0]);
+ const __m128i tmp0_1 = GetRGBA32bWithUV(y[0], uv_0);
+ const __m128i tmp0_2 = GetRGBA32bWithUV(y[1], uv_0);
+ const __m128i tmp1_1 = _mm_shuffle_epi32(tmp0_1, _MM_SHUFFLE(3, 0, 1, 2));
+ const __m128i tmp1_2 = _mm_shuffle_epi32(tmp0_2, _MM_SHUFFLE(3, 0, 1, 2));
+ const __m128i tmp2_1 = _mm_packs_epi32(tmp1_1, tmp1_2);
+ const __m128i tmp3 = _mm_packus_epi16(tmp2_1, tmp2_1);
+ _mm_storel_epi64((__m128i*)dst, tmp3);
+ dst += 4 * 2;
+ y += 2;
+ ++u;
+ ++v;
+ }
+ // Finish off
+ if (len & 1) {
+ VP8YuvToBgra(y[0], u[0], v[0], dst);
+ }
+}
+
+static void YuvToArgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst, int len) {
+ int n;
+ for (n = 0; n + 2 <= len; n += 2) {
+ const __m128i uv_0 = LoadUVPart(u[0], v[0]);
+ const __m128i tmp0_1 = GetRGBA32bWithUV(y[0], uv_0);
+ const __m128i tmp0_2 = GetRGBA32bWithUV(y[1], uv_0);
+ const __m128i tmp1_1 = _mm_shuffle_epi32(tmp0_1, _MM_SHUFFLE(2, 1, 0, 3));
+ const __m128i tmp1_2 = _mm_shuffle_epi32(tmp0_2, _MM_SHUFFLE(2, 1, 0, 3));
+ const __m128i tmp2_1 = _mm_packs_epi32(tmp1_1, tmp1_2);
+ const __m128i tmp3 = _mm_packus_epi16(tmp2_1, tmp2_1);
+ _mm_storel_epi64((__m128i*)dst, tmp3);
+ dst += 4 * 2;
+ y += 2;
+ ++u;
+ ++v;
+ }
+ // Finish off
+ if (len & 1) {
+ VP8YuvToArgb(y[0], u[0], v[0], dst);
+ }
+}
+
+static void YuvToRgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst, int len) {
+ int n;
+ for (n = 0; n + 2 < len; ++n) { // we directly stomp the *dst memory
+ YuvToRgbSSE2(y[0], u[0], v[0], dst); // stomps 8 bytes
+ dst += 3;
+ ++y;
+ u += (n & 1);
+ v += (n & 1);
+ }
+ VP8YuvToRgb(y[0], u[0], v[0], dst);
+ if (len > 1) {
+ VP8YuvToRgb(y[1], u[n & 1], v[n & 1], dst + 3);
+ }
+}
+
+static void YuvToBgrRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst, int len) {
+ int n;
+ for (n = 0; n + 2 < len; ++n) { // we directly stomp the *dst memory
+ YuvToBgrSSE2(y[0], u[0], v[0], dst); // stomps 8 bytes
+ dst += 3;
+ ++y;
+ u += (n & 1);
+ v += (n & 1);
+ }
+ VP8YuvToBgr(y[0], u[0], v[0], dst + 0);
+ if (len > 1) {
+ VP8YuvToBgr(y[1], u[n & 1], v[n & 1], dst + 3);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void WebPInitSamplersSSE2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersSSE2(void) {
+ WebPSamplers[MODE_RGB] = YuvToRgbRow;
+ WebPSamplers[MODE_RGBA] = YuvToRgbaRow;
+ WebPSamplers[MODE_BGR] = YuvToBgrRow;
+ WebPSamplers[MODE_BGRA] = YuvToBgraRow;
+ WebPSamplers[MODE_ARGB] = YuvToArgbRow;
+}
+
+//------------------------------------------------------------------------------
+// RGB24/32 -> YUV converters
+
+// Load eight 16b-words from *src.
+#define LOAD_16(src) _mm_loadu_si128((const __m128i*)(src))
+// Store either 16b-words into *dst
+#define STORE_16(V, dst) _mm_storeu_si128((__m128i*)(dst), (V))
+
+// Convert 8 packed RGB or BGR samples to r[], g[], b[]
+static WEBP_INLINE void RGB24PackedToPlanar(const uint8_t* const rgb,
+ __m128i* const r,
+ __m128i* const g,
+ __m128i* const b,
+ int input_is_bgr) {
+ const __m128i zero = _mm_setzero_si128();
+ // in0: r0 g0 b0 r1 | g1 b1 r2 g2 | b2 r3 g3 b3 | r4 g4 b4 r5
+ // in1: b2 r3 g3 b3 | r4 g4 b4 r5 | g5 b5 r6 g6 | b6 r7 g7 b7
+ const __m128i in0 = LOAD_16(rgb + 0);
+ const __m128i in1 = LOAD_16(rgb + 8);
+ // A0: | r2 g2 b2 r3 | g3 b3 r4 g4 | b4 r5 ...
+ // A1: ... b2 r3 | g3 b3 r4 g4 | b4 r5 g5 b5 |
+ const __m128i A0 = _mm_srli_si128(in0, 6);
+ const __m128i A1 = _mm_slli_si128(in1, 6);
+ // B0: r0 r2 g0 g2 | b0 b2 r1 r3 | g1 g3 b1 b3 | r2 r4 b2 b4
+ // B1: g3 g5 b3 b5 | r4 r6 g4 g6 | b4 b6 r5 r7 | g5 g7 b5 b7
+ const __m128i B0 = _mm_unpacklo_epi8(in0, A0);
+ const __m128i B1 = _mm_unpackhi_epi8(A1, in1);
+ // C0: r1 r3 g1 g3 | b1 b3 r2 r4 | b2 b4 ...
+ // C1: ... g3 g5 | b3 b5 r4 r6 | g4 g6 b4 b6
+ const __m128i C0 = _mm_srli_si128(B0, 6);
+ const __m128i C1 = _mm_slli_si128(B1, 6);
+ // D0: r0 r1 r2 r3 | g0 g1 g2 g3 | b0 b1 b2 b3 | r1 r2 r3 r4
+ // D1: b3 b4 b5 b6 | r4 r5 r6 r7 | g4 g5 g6 g7 | b4 b5 b6 b7 |
+ const __m128i D0 = _mm_unpacklo_epi8(B0, C0);
+ const __m128i D1 = _mm_unpackhi_epi8(C1, B1);
+ // r4 r5 r6 r7 | g4 g5 g6 g7 | b4 b5 b6 b7 | 0
+ const __m128i D2 = _mm_srli_si128(D1, 4);
+ // r0 r1 r2 r3 | r4 r5 r6 r7 | g0 g1 g2 g3 | g4 g5 g6 g7
+ const __m128i E0 = _mm_unpacklo_epi32(D0, D2);
+ // b0 b1 b2 b3 | b4 b5 b6 b7 | r1 r2 r3 r4 | 0
+ const __m128i E1 = _mm_unpackhi_epi32(D0, D2);
+ // g0 g1 g2 g3 | g4 g5 g6 g7 | 0
+ const __m128i E2 = _mm_srli_si128(E0, 8);
+ const __m128i F0 = _mm_unpacklo_epi8(E0, zero); // -> R
+ const __m128i F1 = _mm_unpacklo_epi8(E1, zero); // -> B
+ const __m128i F2 = _mm_unpacklo_epi8(E2, zero); // -> G
+ *g = F2;
+ if (input_is_bgr) {
+ *r = F1;
+ *b = F0;
+ } else {
+ *r = F0;
+ *b = F1;
+ }
+}
+
+// Convert 8 packed ARGB to r[], g[], b[]
+static WEBP_INLINE void RGB32PackedToPlanar(const uint32_t* const argb,
+ __m128i* const r,
+ __m128i* const g,
+ __m128i* const b) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i in0 = LOAD_16(argb + 0); // argb3 | argb2 | argb1 | argb0
+ const __m128i in1 = LOAD_16(argb + 4); // argb7 | argb6 | argb5 | argb4
+ // column-wise transpose
+ const __m128i A0 = _mm_unpacklo_epi8(in0, in1);
+ const __m128i A1 = _mm_unpackhi_epi8(in0, in1);
+ const __m128i B0 = _mm_unpacklo_epi8(A0, A1);
+ const __m128i B1 = _mm_unpackhi_epi8(A0, A1);
+ // C0 = g7 g6 ... g1 g0 | b7 b6 ... b1 b0
+ // C1 = a7 a6 ... a1 a0 | r7 r6 ... r1 r0
+ const __m128i C0 = _mm_unpacklo_epi8(B0, B1);
+ const __m128i C1 = _mm_unpackhi_epi8(B0, B1);
+ // store 16b
+ *r = _mm_unpacklo_epi8(C1, zero);
+ *g = _mm_unpackhi_epi8(C0, zero);
+ *b = _mm_unpacklo_epi8(C0, zero);
+}
+
+// This macro computes (RG * MULT_RG + GB * MULT_GB + ROUNDER) >> DESCALE_FIX
+// It's a macro and not a function because we need to use immediate values with
+// srai_epi32, e.g.
+#define TRANSFORM(RG_LO, RG_HI, GB_LO, GB_HI, MULT_RG, MULT_GB, \
+ ROUNDER, DESCALE_FIX, OUT) do { \
+ const __m128i V0_lo = _mm_madd_epi16(RG_LO, MULT_RG); \
+ const __m128i V0_hi = _mm_madd_epi16(RG_HI, MULT_RG); \
+ const __m128i V1_lo = _mm_madd_epi16(GB_LO, MULT_GB); \
+ const __m128i V1_hi = _mm_madd_epi16(GB_HI, MULT_GB); \
+ const __m128i V2_lo = _mm_add_epi32(V0_lo, V1_lo); \
+ const __m128i V2_hi = _mm_add_epi32(V0_hi, V1_hi); \
+ const __m128i V3_lo = _mm_add_epi32(V2_lo, ROUNDER); \
+ const __m128i V3_hi = _mm_add_epi32(V2_hi, ROUNDER); \
+ const __m128i V5_lo = _mm_srai_epi32(V3_lo, DESCALE_FIX); \
+ const __m128i V5_hi = _mm_srai_epi32(V3_hi, DESCALE_FIX); \
+ (OUT) = _mm_packs_epi32(V5_lo, V5_hi); \
+} while (0)
+
+#define MK_CST_16(A, B) _mm_set_epi16((B), (A), (B), (A), (B), (A), (B), (A))
+static WEBP_INLINE void ConvertRGBToY(const __m128i* const R,
+ const __m128i* const G,
+ const __m128i* const B,
+ __m128i* const Y) {
+ const __m128i kRG_y = MK_CST_16(16839, 33059 - 16384);
+ const __m128i kGB_y = MK_CST_16(16384, 6420);
+ const __m128i kHALF_Y = _mm_set1_epi32((16 << YUV_FIX) + YUV_HALF);
+
+ const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G);
+ const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G);
+ const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B);
+ const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B);
+ TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_y, kGB_y, kHALF_Y, YUV_FIX, *Y);
+}
+
+static WEBP_INLINE void ConvertRGBToUV(const __m128i* const R,
+ const __m128i* const G,
+ const __m128i* const B,
+ __m128i* const U, __m128i* const V) {
+ const __m128i kRG_u = MK_CST_16(-9719, -19081);
+ const __m128i kGB_u = MK_CST_16(0, 28800);
+ const __m128i kRG_v = MK_CST_16(28800, 0);
+ const __m128i kGB_v = MK_CST_16(-24116, -4684);
+ const __m128i kHALF_UV = _mm_set1_epi32(((128 << YUV_FIX) + YUV_HALF) << 2);
+
+ const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G);
+ const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G);
+ const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B);
+ const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B);
+ TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_u, kGB_u,
+ kHALF_UV, YUV_FIX + 2, *U);
+ TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_v, kGB_v,
+ kHALF_UV, YUV_FIX + 2, *V);
+}
+
+#undef MK_CST_16
+#undef TRANSFORM
+
+static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) {
+ const int max_width = width & ~15;
+ int i;
+ for (i = 0; i < max_width; i += 16, rgb += 3 * 16) {
+ __m128i r, g, b, Y0, Y1;
+ RGB24PackedToPlanar(rgb + 0 * 8, &r, &g, &b, 0);
+ ConvertRGBToY(&r, &g, &b, &Y0);
+ RGB24PackedToPlanar(rgb + 3 * 8, &r, &g, &b, 0);
+ ConvertRGBToY(&r, &g, &b, &Y1);
+ STORE_16(_mm_packus_epi16(Y0, Y1), y + i);
+ }
+ for (; i < width; ++i, rgb += 3) { // left-over
+ y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF);
+ }
+}
+
+static void ConvertBGR24ToY(const uint8_t* bgr, uint8_t* y, int width) {
+ int i;
+ const int max_width = width & ~15;
+ for (i = 0; i < max_width; i += 16, bgr += 3 * 16) {
+ __m128i r, g, b, Y0, Y1;
+ RGB24PackedToPlanar(bgr + 0 * 8, &r, &g, &b, 1);
+ ConvertRGBToY(&r, &g, &b, &Y0);
+ RGB24PackedToPlanar(bgr + 3 * 8, &r, &g, &b, 1);
+ ConvertRGBToY(&r, &g, &b, &Y1);
+ STORE_16(_mm_packus_epi16(Y0, Y1), y + i);
+ }
+ for (; i < width; ++i, bgr += 3) { // left-over
+ y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF);
+ }
+}
+
+static void ConvertARGBToY(const uint32_t* argb, uint8_t* y, int width) {
+ const int max_width = width & ~15;
+ int i;
+ for (i = 0; i < max_width; i += 16) {
+ __m128i r, g, b, Y0, Y1;
+ RGB32PackedToPlanar(&argb[i + 0], &r, &g, &b);
+ ConvertRGBToY(&r, &g, &b, &Y0);
+ RGB32PackedToPlanar(&argb[i + 8], &r, &g, &b);
+ ConvertRGBToY(&r, &g, &b, &Y1);
+ STORE_16(_mm_packus_epi16(Y0, Y1), y + i);
+ }
+ for (; i < width; ++i) { // left-over
+ const uint32_t p = argb[i];
+ y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff,
+ YUV_HALF);
+ }
+}
+
+// Horizontal add (doubled) of two 16b values, result is 16b.
+// in: A | B | C | D | ... -> out: 2*(A+B) | 2*(C+D) | ...
+static void HorizontalAddPack(const __m128i* const A, const __m128i* const B,
+ __m128i* const out) {
+ const __m128i k2 = _mm_set1_epi16(2);
+ const __m128i C = _mm_madd_epi16(*A, k2);
+ const __m128i D = _mm_madd_epi16(*B, k2);
+ *out = _mm_packs_epi32(C, D);
+}
+
+static void ConvertARGBToUV(const uint32_t* argb, uint8_t* u, uint8_t* v,
+ int src_width, int do_store) {
+ const int max_width = src_width & ~31;
+ int i;
+ for (i = 0; i < max_width; i += 32, u += 16, v += 16) {
+ __m128i r0, g0, b0, r1, g1, b1, U0, V0, U1, V1;
+ RGB32PackedToPlanar(&argb[i + 0], &r0, &g0, &b0);
+ RGB32PackedToPlanar(&argb[i + 8], &r1, &g1, &b1);
+ HorizontalAddPack(&r0, &r1, &r0);
+ HorizontalAddPack(&g0, &g1, &g0);
+ HorizontalAddPack(&b0, &b1, &b0);
+ ConvertRGBToUV(&r0, &g0, &b0, &U0, &V0);
+
+ RGB32PackedToPlanar(&argb[i + 16], &r0, &g0, &b0);
+ RGB32PackedToPlanar(&argb[i + 24], &r1, &g1, &b1);
+ HorizontalAddPack(&r0, &r1, &r0);
+ HorizontalAddPack(&g0, &g1, &g0);
+ HorizontalAddPack(&b0, &b1, &b0);
+ ConvertRGBToUV(&r0, &g0, &b0, &U1, &V1);
+
+ U0 = _mm_packus_epi16(U0, U1);
+ V0 = _mm_packus_epi16(V0, V1);
+ if (!do_store) {
+ const __m128i prev_u = LOAD_16(u);
+ const __m128i prev_v = LOAD_16(v);
+ U0 = _mm_avg_epu8(U0, prev_u);
+ V0 = _mm_avg_epu8(V0, prev_v);
+ }
+ STORE_16(U0, u);
+ STORE_16(V0, v);
+ }
+ if (i < src_width) { // left-over
+ WebPConvertARGBToUV_C(argb + i, u, v, src_width - i, do_store);
+ }
+}
+
+// Convert 16 packed ARGB 16b-values to r[], g[], b[]
+static WEBP_INLINE void RGBA32PackedToPlanar_16b(const uint16_t* const rgbx,
+ __m128i* const r,
+ __m128i* const g,
+ __m128i* const b) {
+ const __m128i in0 = LOAD_16(rgbx + 0); // r0 | g0 | b0 |x| r1 | g1 | b1 |x
+ const __m128i in1 = LOAD_16(rgbx + 8); // r2 | g2 | b2 |x| r3 | g3 | b3 |x
+ const __m128i in2 = LOAD_16(rgbx + 16); // r4 | ...
+ const __m128i in3 = LOAD_16(rgbx + 24); // r6 | ...
+ // column-wise transpose
+ const __m128i A0 = _mm_unpacklo_epi16(in0, in1);
+ const __m128i A1 = _mm_unpackhi_epi16(in0, in1);
+ const __m128i A2 = _mm_unpacklo_epi16(in2, in3);
+ const __m128i A3 = _mm_unpackhi_epi16(in2, in3);
+ const __m128i B0 = _mm_unpacklo_epi16(A0, A1); // r0 r1 r2 r3 | g0 g1 ..
+ const __m128i B1 = _mm_unpackhi_epi16(A0, A1); // b0 b1 b2 b3 | x x x x
+ const __m128i B2 = _mm_unpacklo_epi16(A2, A3); // r4 r5 r6 r7 | g4 g5 ..
+ const __m128i B3 = _mm_unpackhi_epi16(A2, A3); // b4 b5 b6 b7 | x x x x
+ *r = _mm_unpacklo_epi64(B0, B2);
+ *g = _mm_unpackhi_epi64(B0, B2);
+ *b = _mm_unpacklo_epi64(B1, B3);
+}
+
+static void ConvertRGBA32ToUV(const uint16_t* rgb,
+ uint8_t* u, uint8_t* v, int width) {
+ const int max_width = width & ~15;
+ const uint16_t* const last_rgb = rgb + 4 * max_width;
+ while (rgb < last_rgb) {
+ __m128i r, g, b, U0, V0, U1, V1;
+ RGBA32PackedToPlanar_16b(rgb + 0, &r, &g, &b);
+ ConvertRGBToUV(&r, &g, &b, &U0, &V0);
+ RGBA32PackedToPlanar_16b(rgb + 32, &r, &g, &b);
+ ConvertRGBToUV(&r, &g, &b, &U1, &V1);
+ STORE_16(_mm_packus_epi16(U0, U1), u);
+ STORE_16(_mm_packus_epi16(V0, V1), v);
+ u += 16;
+ v += 16;
+ rgb += 2 * 32;
+ }
+ if (max_width < width) { // left-over
+ WebPConvertRGBA32ToUV_C(rgb, u, v, width - max_width);
+ }
+}
+
+//------------------------------------------------------------------------------
+
+extern void WebPInitConvertARGBToYUVSSE2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUVSSE2(void) {
+ WebPConvertARGBToY = ConvertARGBToY;
+ WebPConvertARGBToUV = ConvertARGBToUV;
+
+ WebPConvertRGB24ToY = ConvertRGB24ToY;
+ WebPConvertBGR24ToY = ConvertBGR24ToY;
+
+ WebPConvertRGBA32ToUV = ConvertRGBA32ToUV;
+}
+
+#else // !WEBP_USE_SSE2
+
+WEBP_DSP_INIT_STUB(WebPInitSamplersSSE2)
+WEBP_DSP_INIT_STUB(WebPInitConvertARGBToYUVSSE2)
+
+#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/yuv_tables_sse2.h b/drivers/webp/dsp/yuv_tables_sse2.h
new file mode 100644
index 0000000000..2b0f057518
--- /dev/null
+++ b/drivers/webp/dsp/yuv_tables_sse2.h
@@ -0,0 +1,536 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// SSE2 tables for YUV->RGB conversion (12kB overall)
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+// This file is not compiled, but #include'd directly from yuv.c
+// Only used if WEBP_YUV_USE_SSE2_TABLES is defined.
+
+static const VP8kCstSSE2 VP8kYtoRGBA[256] = {
+ {{0xfffb77b0, 0xfffb77b0, 0xfffb77b0, 0x003fc000}},
+ {{0xfffbc235, 0xfffbc235, 0xfffbc235, 0x003fc000}},
+ {{0xfffc0cba, 0xfffc0cba, 0xfffc0cba, 0x003fc000}},
+ {{0xfffc573f, 0xfffc573f, 0xfffc573f, 0x003fc000}},
+ {{0xfffca1c4, 0xfffca1c4, 0xfffca1c4, 0x003fc000}},
+ {{0xfffcec49, 0xfffcec49, 0xfffcec49, 0x003fc000}},
+ {{0xfffd36ce, 0xfffd36ce, 0xfffd36ce, 0x003fc000}},
+ {{0xfffd8153, 0xfffd8153, 0xfffd8153, 0x003fc000}},
+ {{0xfffdcbd8, 0xfffdcbd8, 0xfffdcbd8, 0x003fc000}},
+ {{0xfffe165d, 0xfffe165d, 0xfffe165d, 0x003fc000}},
+ {{0xfffe60e2, 0xfffe60e2, 0xfffe60e2, 0x003fc000}},
+ {{0xfffeab67, 0xfffeab67, 0xfffeab67, 0x003fc000}},
+ {{0xfffef5ec, 0xfffef5ec, 0xfffef5ec, 0x003fc000}},
+ {{0xffff4071, 0xffff4071, 0xffff4071, 0x003fc000}},
+ {{0xffff8af6, 0xffff8af6, 0xffff8af6, 0x003fc000}},
+ {{0xffffd57b, 0xffffd57b, 0xffffd57b, 0x003fc000}},
+ {{0x00002000, 0x00002000, 0x00002000, 0x003fc000}},
+ {{0x00006a85, 0x00006a85, 0x00006a85, 0x003fc000}},
+ {{0x0000b50a, 0x0000b50a, 0x0000b50a, 0x003fc000}},
+ {{0x0000ff8f, 0x0000ff8f, 0x0000ff8f, 0x003fc000}},
+ {{0x00014a14, 0x00014a14, 0x00014a14, 0x003fc000}},
+ {{0x00019499, 0x00019499, 0x00019499, 0x003fc000}},
+ {{0x0001df1e, 0x0001df1e, 0x0001df1e, 0x003fc000}},
+ {{0x000229a3, 0x000229a3, 0x000229a3, 0x003fc000}},
+ {{0x00027428, 0x00027428, 0x00027428, 0x003fc000}},
+ {{0x0002bead, 0x0002bead, 0x0002bead, 0x003fc000}},
+ {{0x00030932, 0x00030932, 0x00030932, 0x003fc000}},
+ {{0x000353b7, 0x000353b7, 0x000353b7, 0x003fc000}},
+ {{0x00039e3c, 0x00039e3c, 0x00039e3c, 0x003fc000}},
+ {{0x0003e8c1, 0x0003e8c1, 0x0003e8c1, 0x003fc000}},
+ {{0x00043346, 0x00043346, 0x00043346, 0x003fc000}},
+ {{0x00047dcb, 0x00047dcb, 0x00047dcb, 0x003fc000}},
+ {{0x0004c850, 0x0004c850, 0x0004c850, 0x003fc000}},
+ {{0x000512d5, 0x000512d5, 0x000512d5, 0x003fc000}},
+ {{0x00055d5a, 0x00055d5a, 0x00055d5a, 0x003fc000}},
+ {{0x0005a7df, 0x0005a7df, 0x0005a7df, 0x003fc000}},
+ {{0x0005f264, 0x0005f264, 0x0005f264, 0x003fc000}},
+ {{0x00063ce9, 0x00063ce9, 0x00063ce9, 0x003fc000}},
+ {{0x0006876e, 0x0006876e, 0x0006876e, 0x003fc000}},
+ {{0x0006d1f3, 0x0006d1f3, 0x0006d1f3, 0x003fc000}},
+ {{0x00071c78, 0x00071c78, 0x00071c78, 0x003fc000}},
+ {{0x000766fd, 0x000766fd, 0x000766fd, 0x003fc000}},
+ {{0x0007b182, 0x0007b182, 0x0007b182, 0x003fc000}},
+ {{0x0007fc07, 0x0007fc07, 0x0007fc07, 0x003fc000}},
+ {{0x0008468c, 0x0008468c, 0x0008468c, 0x003fc000}},
+ {{0x00089111, 0x00089111, 0x00089111, 0x003fc000}},
+ {{0x0008db96, 0x0008db96, 0x0008db96, 0x003fc000}},
+ {{0x0009261b, 0x0009261b, 0x0009261b, 0x003fc000}},
+ {{0x000970a0, 0x000970a0, 0x000970a0, 0x003fc000}},
+ {{0x0009bb25, 0x0009bb25, 0x0009bb25, 0x003fc000}},
+ {{0x000a05aa, 0x000a05aa, 0x000a05aa, 0x003fc000}},
+ {{0x000a502f, 0x000a502f, 0x000a502f, 0x003fc000}},
+ {{0x000a9ab4, 0x000a9ab4, 0x000a9ab4, 0x003fc000}},
+ {{0x000ae539, 0x000ae539, 0x000ae539, 0x003fc000}},
+ {{0x000b2fbe, 0x000b2fbe, 0x000b2fbe, 0x003fc000}},
+ {{0x000b7a43, 0x000b7a43, 0x000b7a43, 0x003fc000}},
+ {{0x000bc4c8, 0x000bc4c8, 0x000bc4c8, 0x003fc000}},
+ {{0x000c0f4d, 0x000c0f4d, 0x000c0f4d, 0x003fc000}},
+ {{0x000c59d2, 0x000c59d2, 0x000c59d2, 0x003fc000}},
+ {{0x000ca457, 0x000ca457, 0x000ca457, 0x003fc000}},
+ {{0x000ceedc, 0x000ceedc, 0x000ceedc, 0x003fc000}},
+ {{0x000d3961, 0x000d3961, 0x000d3961, 0x003fc000}},
+ {{0x000d83e6, 0x000d83e6, 0x000d83e6, 0x003fc000}},
+ {{0x000dce6b, 0x000dce6b, 0x000dce6b, 0x003fc000}},
+ {{0x000e18f0, 0x000e18f0, 0x000e18f0, 0x003fc000}},
+ {{0x000e6375, 0x000e6375, 0x000e6375, 0x003fc000}},
+ {{0x000eadfa, 0x000eadfa, 0x000eadfa, 0x003fc000}},
+ {{0x000ef87f, 0x000ef87f, 0x000ef87f, 0x003fc000}},
+ {{0x000f4304, 0x000f4304, 0x000f4304, 0x003fc000}},
+ {{0x000f8d89, 0x000f8d89, 0x000f8d89, 0x003fc000}},
+ {{0x000fd80e, 0x000fd80e, 0x000fd80e, 0x003fc000}},
+ {{0x00102293, 0x00102293, 0x00102293, 0x003fc000}},
+ {{0x00106d18, 0x00106d18, 0x00106d18, 0x003fc000}},
+ {{0x0010b79d, 0x0010b79d, 0x0010b79d, 0x003fc000}},
+ {{0x00110222, 0x00110222, 0x00110222, 0x003fc000}},
+ {{0x00114ca7, 0x00114ca7, 0x00114ca7, 0x003fc000}},
+ {{0x0011972c, 0x0011972c, 0x0011972c, 0x003fc000}},
+ {{0x0011e1b1, 0x0011e1b1, 0x0011e1b1, 0x003fc000}},
+ {{0x00122c36, 0x00122c36, 0x00122c36, 0x003fc000}},
+ {{0x001276bb, 0x001276bb, 0x001276bb, 0x003fc000}},
+ {{0x0012c140, 0x0012c140, 0x0012c140, 0x003fc000}},
+ {{0x00130bc5, 0x00130bc5, 0x00130bc5, 0x003fc000}},
+ {{0x0013564a, 0x0013564a, 0x0013564a, 0x003fc000}},
+ {{0x0013a0cf, 0x0013a0cf, 0x0013a0cf, 0x003fc000}},
+ {{0x0013eb54, 0x0013eb54, 0x0013eb54, 0x003fc000}},
+ {{0x001435d9, 0x001435d9, 0x001435d9, 0x003fc000}},
+ {{0x0014805e, 0x0014805e, 0x0014805e, 0x003fc000}},
+ {{0x0014cae3, 0x0014cae3, 0x0014cae3, 0x003fc000}},
+ {{0x00151568, 0x00151568, 0x00151568, 0x003fc000}},
+ {{0x00155fed, 0x00155fed, 0x00155fed, 0x003fc000}},
+ {{0x0015aa72, 0x0015aa72, 0x0015aa72, 0x003fc000}},
+ {{0x0015f4f7, 0x0015f4f7, 0x0015f4f7, 0x003fc000}},
+ {{0x00163f7c, 0x00163f7c, 0x00163f7c, 0x003fc000}},
+ {{0x00168a01, 0x00168a01, 0x00168a01, 0x003fc000}},
+ {{0x0016d486, 0x0016d486, 0x0016d486, 0x003fc000}},
+ {{0x00171f0b, 0x00171f0b, 0x00171f0b, 0x003fc000}},
+ {{0x00176990, 0x00176990, 0x00176990, 0x003fc000}},
+ {{0x0017b415, 0x0017b415, 0x0017b415, 0x003fc000}},
+ {{0x0017fe9a, 0x0017fe9a, 0x0017fe9a, 0x003fc000}},
+ {{0x0018491f, 0x0018491f, 0x0018491f, 0x003fc000}},
+ {{0x001893a4, 0x001893a4, 0x001893a4, 0x003fc000}},
+ {{0x0018de29, 0x0018de29, 0x0018de29, 0x003fc000}},
+ {{0x001928ae, 0x001928ae, 0x001928ae, 0x003fc000}},
+ {{0x00197333, 0x00197333, 0x00197333, 0x003fc000}},
+ {{0x0019bdb8, 0x0019bdb8, 0x0019bdb8, 0x003fc000}},
+ {{0x001a083d, 0x001a083d, 0x001a083d, 0x003fc000}},
+ {{0x001a52c2, 0x001a52c2, 0x001a52c2, 0x003fc000}},
+ {{0x001a9d47, 0x001a9d47, 0x001a9d47, 0x003fc000}},
+ {{0x001ae7cc, 0x001ae7cc, 0x001ae7cc, 0x003fc000}},
+ {{0x001b3251, 0x001b3251, 0x001b3251, 0x003fc000}},
+ {{0x001b7cd6, 0x001b7cd6, 0x001b7cd6, 0x003fc000}},
+ {{0x001bc75b, 0x001bc75b, 0x001bc75b, 0x003fc000}},
+ {{0x001c11e0, 0x001c11e0, 0x001c11e0, 0x003fc000}},
+ {{0x001c5c65, 0x001c5c65, 0x001c5c65, 0x003fc000}},
+ {{0x001ca6ea, 0x001ca6ea, 0x001ca6ea, 0x003fc000}},
+ {{0x001cf16f, 0x001cf16f, 0x001cf16f, 0x003fc000}},
+ {{0x001d3bf4, 0x001d3bf4, 0x001d3bf4, 0x003fc000}},
+ {{0x001d8679, 0x001d8679, 0x001d8679, 0x003fc000}},
+ {{0x001dd0fe, 0x001dd0fe, 0x001dd0fe, 0x003fc000}},
+ {{0x001e1b83, 0x001e1b83, 0x001e1b83, 0x003fc000}},
+ {{0x001e6608, 0x001e6608, 0x001e6608, 0x003fc000}},
+ {{0x001eb08d, 0x001eb08d, 0x001eb08d, 0x003fc000}},
+ {{0x001efb12, 0x001efb12, 0x001efb12, 0x003fc000}},
+ {{0x001f4597, 0x001f4597, 0x001f4597, 0x003fc000}},
+ {{0x001f901c, 0x001f901c, 0x001f901c, 0x003fc000}},
+ {{0x001fdaa1, 0x001fdaa1, 0x001fdaa1, 0x003fc000}},
+ {{0x00202526, 0x00202526, 0x00202526, 0x003fc000}},
+ {{0x00206fab, 0x00206fab, 0x00206fab, 0x003fc000}},
+ {{0x0020ba30, 0x0020ba30, 0x0020ba30, 0x003fc000}},
+ {{0x002104b5, 0x002104b5, 0x002104b5, 0x003fc000}},
+ {{0x00214f3a, 0x00214f3a, 0x00214f3a, 0x003fc000}},
+ {{0x002199bf, 0x002199bf, 0x002199bf, 0x003fc000}},
+ {{0x0021e444, 0x0021e444, 0x0021e444, 0x003fc000}},
+ {{0x00222ec9, 0x00222ec9, 0x00222ec9, 0x003fc000}},
+ {{0x0022794e, 0x0022794e, 0x0022794e, 0x003fc000}},
+ {{0x0022c3d3, 0x0022c3d3, 0x0022c3d3, 0x003fc000}},
+ {{0x00230e58, 0x00230e58, 0x00230e58, 0x003fc000}},
+ {{0x002358dd, 0x002358dd, 0x002358dd, 0x003fc000}},
+ {{0x0023a362, 0x0023a362, 0x0023a362, 0x003fc000}},
+ {{0x0023ede7, 0x0023ede7, 0x0023ede7, 0x003fc000}},
+ {{0x0024386c, 0x0024386c, 0x0024386c, 0x003fc000}},
+ {{0x002482f1, 0x002482f1, 0x002482f1, 0x003fc000}},
+ {{0x0024cd76, 0x0024cd76, 0x0024cd76, 0x003fc000}},
+ {{0x002517fb, 0x002517fb, 0x002517fb, 0x003fc000}},
+ {{0x00256280, 0x00256280, 0x00256280, 0x003fc000}},
+ {{0x0025ad05, 0x0025ad05, 0x0025ad05, 0x003fc000}},
+ {{0x0025f78a, 0x0025f78a, 0x0025f78a, 0x003fc000}},
+ {{0x0026420f, 0x0026420f, 0x0026420f, 0x003fc000}},
+ {{0x00268c94, 0x00268c94, 0x00268c94, 0x003fc000}},
+ {{0x0026d719, 0x0026d719, 0x0026d719, 0x003fc000}},
+ {{0x0027219e, 0x0027219e, 0x0027219e, 0x003fc000}},
+ {{0x00276c23, 0x00276c23, 0x00276c23, 0x003fc000}},
+ {{0x0027b6a8, 0x0027b6a8, 0x0027b6a8, 0x003fc000}},
+ {{0x0028012d, 0x0028012d, 0x0028012d, 0x003fc000}},
+ {{0x00284bb2, 0x00284bb2, 0x00284bb2, 0x003fc000}},
+ {{0x00289637, 0x00289637, 0x00289637, 0x003fc000}},
+ {{0x0028e0bc, 0x0028e0bc, 0x0028e0bc, 0x003fc000}},
+ {{0x00292b41, 0x00292b41, 0x00292b41, 0x003fc000}},
+ {{0x002975c6, 0x002975c6, 0x002975c6, 0x003fc000}},
+ {{0x0029c04b, 0x0029c04b, 0x0029c04b, 0x003fc000}},
+ {{0x002a0ad0, 0x002a0ad0, 0x002a0ad0, 0x003fc000}},
+ {{0x002a5555, 0x002a5555, 0x002a5555, 0x003fc000}},
+ {{0x002a9fda, 0x002a9fda, 0x002a9fda, 0x003fc000}},
+ {{0x002aea5f, 0x002aea5f, 0x002aea5f, 0x003fc000}},
+ {{0x002b34e4, 0x002b34e4, 0x002b34e4, 0x003fc000}},
+ {{0x002b7f69, 0x002b7f69, 0x002b7f69, 0x003fc000}},
+ {{0x002bc9ee, 0x002bc9ee, 0x002bc9ee, 0x003fc000}},
+ {{0x002c1473, 0x002c1473, 0x002c1473, 0x003fc000}},
+ {{0x002c5ef8, 0x002c5ef8, 0x002c5ef8, 0x003fc000}},
+ {{0x002ca97d, 0x002ca97d, 0x002ca97d, 0x003fc000}},
+ {{0x002cf402, 0x002cf402, 0x002cf402, 0x003fc000}},
+ {{0x002d3e87, 0x002d3e87, 0x002d3e87, 0x003fc000}},
+ {{0x002d890c, 0x002d890c, 0x002d890c, 0x003fc000}},
+ {{0x002dd391, 0x002dd391, 0x002dd391, 0x003fc000}},
+ {{0x002e1e16, 0x002e1e16, 0x002e1e16, 0x003fc000}},
+ {{0x002e689b, 0x002e689b, 0x002e689b, 0x003fc000}},
+ {{0x002eb320, 0x002eb320, 0x002eb320, 0x003fc000}},
+ {{0x002efda5, 0x002efda5, 0x002efda5, 0x003fc000}},
+ {{0x002f482a, 0x002f482a, 0x002f482a, 0x003fc000}},
+ {{0x002f92af, 0x002f92af, 0x002f92af, 0x003fc000}},
+ {{0x002fdd34, 0x002fdd34, 0x002fdd34, 0x003fc000}},
+ {{0x003027b9, 0x003027b9, 0x003027b9, 0x003fc000}},
+ {{0x0030723e, 0x0030723e, 0x0030723e, 0x003fc000}},
+ {{0x0030bcc3, 0x0030bcc3, 0x0030bcc3, 0x003fc000}},
+ {{0x00310748, 0x00310748, 0x00310748, 0x003fc000}},
+ {{0x003151cd, 0x003151cd, 0x003151cd, 0x003fc000}},
+ {{0x00319c52, 0x00319c52, 0x00319c52, 0x003fc000}},
+ {{0x0031e6d7, 0x0031e6d7, 0x0031e6d7, 0x003fc000}},
+ {{0x0032315c, 0x0032315c, 0x0032315c, 0x003fc000}},
+ {{0x00327be1, 0x00327be1, 0x00327be1, 0x003fc000}},
+ {{0x0032c666, 0x0032c666, 0x0032c666, 0x003fc000}},
+ {{0x003310eb, 0x003310eb, 0x003310eb, 0x003fc000}},
+ {{0x00335b70, 0x00335b70, 0x00335b70, 0x003fc000}},
+ {{0x0033a5f5, 0x0033a5f5, 0x0033a5f5, 0x003fc000}},
+ {{0x0033f07a, 0x0033f07a, 0x0033f07a, 0x003fc000}},
+ {{0x00343aff, 0x00343aff, 0x00343aff, 0x003fc000}},
+ {{0x00348584, 0x00348584, 0x00348584, 0x003fc000}},
+ {{0x0034d009, 0x0034d009, 0x0034d009, 0x003fc000}},
+ {{0x00351a8e, 0x00351a8e, 0x00351a8e, 0x003fc000}},
+ {{0x00356513, 0x00356513, 0x00356513, 0x003fc000}},
+ {{0x0035af98, 0x0035af98, 0x0035af98, 0x003fc000}},
+ {{0x0035fa1d, 0x0035fa1d, 0x0035fa1d, 0x003fc000}},
+ {{0x003644a2, 0x003644a2, 0x003644a2, 0x003fc000}},
+ {{0x00368f27, 0x00368f27, 0x00368f27, 0x003fc000}},
+ {{0x0036d9ac, 0x0036d9ac, 0x0036d9ac, 0x003fc000}},
+ {{0x00372431, 0x00372431, 0x00372431, 0x003fc000}},
+ {{0x00376eb6, 0x00376eb6, 0x00376eb6, 0x003fc000}},
+ {{0x0037b93b, 0x0037b93b, 0x0037b93b, 0x003fc000}},
+ {{0x003803c0, 0x003803c0, 0x003803c0, 0x003fc000}},
+ {{0x00384e45, 0x00384e45, 0x00384e45, 0x003fc000}},
+ {{0x003898ca, 0x003898ca, 0x003898ca, 0x003fc000}},
+ {{0x0038e34f, 0x0038e34f, 0x0038e34f, 0x003fc000}},
+ {{0x00392dd4, 0x00392dd4, 0x00392dd4, 0x003fc000}},
+ {{0x00397859, 0x00397859, 0x00397859, 0x003fc000}},
+ {{0x0039c2de, 0x0039c2de, 0x0039c2de, 0x003fc000}},
+ {{0x003a0d63, 0x003a0d63, 0x003a0d63, 0x003fc000}},
+ {{0x003a57e8, 0x003a57e8, 0x003a57e8, 0x003fc000}},
+ {{0x003aa26d, 0x003aa26d, 0x003aa26d, 0x003fc000}},
+ {{0x003aecf2, 0x003aecf2, 0x003aecf2, 0x003fc000}},
+ {{0x003b3777, 0x003b3777, 0x003b3777, 0x003fc000}},
+ {{0x003b81fc, 0x003b81fc, 0x003b81fc, 0x003fc000}},
+ {{0x003bcc81, 0x003bcc81, 0x003bcc81, 0x003fc000}},
+ {{0x003c1706, 0x003c1706, 0x003c1706, 0x003fc000}},
+ {{0x003c618b, 0x003c618b, 0x003c618b, 0x003fc000}},
+ {{0x003cac10, 0x003cac10, 0x003cac10, 0x003fc000}},
+ {{0x003cf695, 0x003cf695, 0x003cf695, 0x003fc000}},
+ {{0x003d411a, 0x003d411a, 0x003d411a, 0x003fc000}},
+ {{0x003d8b9f, 0x003d8b9f, 0x003d8b9f, 0x003fc000}},
+ {{0x003dd624, 0x003dd624, 0x003dd624, 0x003fc000}},
+ {{0x003e20a9, 0x003e20a9, 0x003e20a9, 0x003fc000}},
+ {{0x003e6b2e, 0x003e6b2e, 0x003e6b2e, 0x003fc000}},
+ {{0x003eb5b3, 0x003eb5b3, 0x003eb5b3, 0x003fc000}},
+ {{0x003f0038, 0x003f0038, 0x003f0038, 0x003fc000}},
+ {{0x003f4abd, 0x003f4abd, 0x003f4abd, 0x003fc000}},
+ {{0x003f9542, 0x003f9542, 0x003f9542, 0x003fc000}},
+ {{0x003fdfc7, 0x003fdfc7, 0x003fdfc7, 0x003fc000}},
+ {{0x00402a4c, 0x00402a4c, 0x00402a4c, 0x003fc000}},
+ {{0x004074d1, 0x004074d1, 0x004074d1, 0x003fc000}},
+ {{0x0040bf56, 0x0040bf56, 0x0040bf56, 0x003fc000}},
+ {{0x004109db, 0x004109db, 0x004109db, 0x003fc000}},
+ {{0x00415460, 0x00415460, 0x00415460, 0x003fc000}},
+ {{0x00419ee5, 0x00419ee5, 0x00419ee5, 0x003fc000}},
+ {{0x0041e96a, 0x0041e96a, 0x0041e96a, 0x003fc000}},
+ {{0x004233ef, 0x004233ef, 0x004233ef, 0x003fc000}},
+ {{0x00427e74, 0x00427e74, 0x00427e74, 0x003fc000}},
+ {{0x0042c8f9, 0x0042c8f9, 0x0042c8f9, 0x003fc000}},
+ {{0x0043137e, 0x0043137e, 0x0043137e, 0x003fc000}},
+ {{0x00435e03, 0x00435e03, 0x00435e03, 0x003fc000}},
+ {{0x0043a888, 0x0043a888, 0x0043a888, 0x003fc000}},
+ {{0x0043f30d, 0x0043f30d, 0x0043f30d, 0x003fc000}},
+ {{0x00443d92, 0x00443d92, 0x00443d92, 0x003fc000}},
+ {{0x00448817, 0x00448817, 0x00448817, 0x003fc000}},
+ {{0x0044d29c, 0x0044d29c, 0x0044d29c, 0x003fc000}},
+ {{0x00451d21, 0x00451d21, 0x00451d21, 0x003fc000}},
+ {{0x004567a6, 0x004567a6, 0x004567a6, 0x003fc000}},
+ {{0x0045b22b, 0x0045b22b, 0x0045b22b, 0x003fc000}}
+};
+
+static const VP8kCstSSE2 VP8kUtoRGBA[256] = {
+ {{0, 0x000c8980, 0xffbf7300, 0}}, {{0, 0x000c706d, 0xffbff41a, 0}},
+ {{0, 0x000c575a, 0xffc07534, 0}}, {{0, 0x000c3e47, 0xffc0f64e, 0}},
+ {{0, 0x000c2534, 0xffc17768, 0}}, {{0, 0x000c0c21, 0xffc1f882, 0}},
+ {{0, 0x000bf30e, 0xffc2799c, 0}}, {{0, 0x000bd9fb, 0xffc2fab6, 0}},
+ {{0, 0x000bc0e8, 0xffc37bd0, 0}}, {{0, 0x000ba7d5, 0xffc3fcea, 0}},
+ {{0, 0x000b8ec2, 0xffc47e04, 0}}, {{0, 0x000b75af, 0xffc4ff1e, 0}},
+ {{0, 0x000b5c9c, 0xffc58038, 0}}, {{0, 0x000b4389, 0xffc60152, 0}},
+ {{0, 0x000b2a76, 0xffc6826c, 0}}, {{0, 0x000b1163, 0xffc70386, 0}},
+ {{0, 0x000af850, 0xffc784a0, 0}}, {{0, 0x000adf3d, 0xffc805ba, 0}},
+ {{0, 0x000ac62a, 0xffc886d4, 0}}, {{0, 0x000aad17, 0xffc907ee, 0}},
+ {{0, 0x000a9404, 0xffc98908, 0}}, {{0, 0x000a7af1, 0xffca0a22, 0}},
+ {{0, 0x000a61de, 0xffca8b3c, 0}}, {{0, 0x000a48cb, 0xffcb0c56, 0}},
+ {{0, 0x000a2fb8, 0xffcb8d70, 0}}, {{0, 0x000a16a5, 0xffcc0e8a, 0}},
+ {{0, 0x0009fd92, 0xffcc8fa4, 0}}, {{0, 0x0009e47f, 0xffcd10be, 0}},
+ {{0, 0x0009cb6c, 0xffcd91d8, 0}}, {{0, 0x0009b259, 0xffce12f2, 0}},
+ {{0, 0x00099946, 0xffce940c, 0}}, {{0, 0x00098033, 0xffcf1526, 0}},
+ {{0, 0x00096720, 0xffcf9640, 0}}, {{0, 0x00094e0d, 0xffd0175a, 0}},
+ {{0, 0x000934fa, 0xffd09874, 0}}, {{0, 0x00091be7, 0xffd1198e, 0}},
+ {{0, 0x000902d4, 0xffd19aa8, 0}}, {{0, 0x0008e9c1, 0xffd21bc2, 0}},
+ {{0, 0x0008d0ae, 0xffd29cdc, 0}}, {{0, 0x0008b79b, 0xffd31df6, 0}},
+ {{0, 0x00089e88, 0xffd39f10, 0}}, {{0, 0x00088575, 0xffd4202a, 0}},
+ {{0, 0x00086c62, 0xffd4a144, 0}}, {{0, 0x0008534f, 0xffd5225e, 0}},
+ {{0, 0x00083a3c, 0xffd5a378, 0}}, {{0, 0x00082129, 0xffd62492, 0}},
+ {{0, 0x00080816, 0xffd6a5ac, 0}}, {{0, 0x0007ef03, 0xffd726c6, 0}},
+ {{0, 0x0007d5f0, 0xffd7a7e0, 0}}, {{0, 0x0007bcdd, 0xffd828fa, 0}},
+ {{0, 0x0007a3ca, 0xffd8aa14, 0}}, {{0, 0x00078ab7, 0xffd92b2e, 0}},
+ {{0, 0x000771a4, 0xffd9ac48, 0}}, {{0, 0x00075891, 0xffda2d62, 0}},
+ {{0, 0x00073f7e, 0xffdaae7c, 0}}, {{0, 0x0007266b, 0xffdb2f96, 0}},
+ {{0, 0x00070d58, 0xffdbb0b0, 0}}, {{0, 0x0006f445, 0xffdc31ca, 0}},
+ {{0, 0x0006db32, 0xffdcb2e4, 0}}, {{0, 0x0006c21f, 0xffdd33fe, 0}},
+ {{0, 0x0006a90c, 0xffddb518, 0}}, {{0, 0x00068ff9, 0xffde3632, 0}},
+ {{0, 0x000676e6, 0xffdeb74c, 0}}, {{0, 0x00065dd3, 0xffdf3866, 0}},
+ {{0, 0x000644c0, 0xffdfb980, 0}}, {{0, 0x00062bad, 0xffe03a9a, 0}},
+ {{0, 0x0006129a, 0xffe0bbb4, 0}}, {{0, 0x0005f987, 0xffe13cce, 0}},
+ {{0, 0x0005e074, 0xffe1bde8, 0}}, {{0, 0x0005c761, 0xffe23f02, 0}},
+ {{0, 0x0005ae4e, 0xffe2c01c, 0}}, {{0, 0x0005953b, 0xffe34136, 0}},
+ {{0, 0x00057c28, 0xffe3c250, 0}}, {{0, 0x00056315, 0xffe4436a, 0}},
+ {{0, 0x00054a02, 0xffe4c484, 0}}, {{0, 0x000530ef, 0xffe5459e, 0}},
+ {{0, 0x000517dc, 0xffe5c6b8, 0}}, {{0, 0x0004fec9, 0xffe647d2, 0}},
+ {{0, 0x0004e5b6, 0xffe6c8ec, 0}}, {{0, 0x0004cca3, 0xffe74a06, 0}},
+ {{0, 0x0004b390, 0xffe7cb20, 0}}, {{0, 0x00049a7d, 0xffe84c3a, 0}},
+ {{0, 0x0004816a, 0xffe8cd54, 0}}, {{0, 0x00046857, 0xffe94e6e, 0}},
+ {{0, 0x00044f44, 0xffe9cf88, 0}}, {{0, 0x00043631, 0xffea50a2, 0}},
+ {{0, 0x00041d1e, 0xffead1bc, 0}}, {{0, 0x0004040b, 0xffeb52d6, 0}},
+ {{0, 0x0003eaf8, 0xffebd3f0, 0}}, {{0, 0x0003d1e5, 0xffec550a, 0}},
+ {{0, 0x0003b8d2, 0xffecd624, 0}}, {{0, 0x00039fbf, 0xffed573e, 0}},
+ {{0, 0x000386ac, 0xffedd858, 0}}, {{0, 0x00036d99, 0xffee5972, 0}},
+ {{0, 0x00035486, 0xffeeda8c, 0}}, {{0, 0x00033b73, 0xffef5ba6, 0}},
+ {{0, 0x00032260, 0xffefdcc0, 0}}, {{0, 0x0003094d, 0xfff05dda, 0}},
+ {{0, 0x0002f03a, 0xfff0def4, 0}}, {{0, 0x0002d727, 0xfff1600e, 0}},
+ {{0, 0x0002be14, 0xfff1e128, 0}}, {{0, 0x0002a501, 0xfff26242, 0}},
+ {{0, 0x00028bee, 0xfff2e35c, 0}}, {{0, 0x000272db, 0xfff36476, 0}},
+ {{0, 0x000259c8, 0xfff3e590, 0}}, {{0, 0x000240b5, 0xfff466aa, 0}},
+ {{0, 0x000227a2, 0xfff4e7c4, 0}}, {{0, 0x00020e8f, 0xfff568de, 0}},
+ {{0, 0x0001f57c, 0xfff5e9f8, 0}}, {{0, 0x0001dc69, 0xfff66b12, 0}},
+ {{0, 0x0001c356, 0xfff6ec2c, 0}}, {{0, 0x0001aa43, 0xfff76d46, 0}},
+ {{0, 0x00019130, 0xfff7ee60, 0}}, {{0, 0x0001781d, 0xfff86f7a, 0}},
+ {{0, 0x00015f0a, 0xfff8f094, 0}}, {{0, 0x000145f7, 0xfff971ae, 0}},
+ {{0, 0x00012ce4, 0xfff9f2c8, 0}}, {{0, 0x000113d1, 0xfffa73e2, 0}},
+ {{0, 0x0000fabe, 0xfffaf4fc, 0}}, {{0, 0x0000e1ab, 0xfffb7616, 0}},
+ {{0, 0x0000c898, 0xfffbf730, 0}}, {{0, 0x0000af85, 0xfffc784a, 0}},
+ {{0, 0x00009672, 0xfffcf964, 0}}, {{0, 0x00007d5f, 0xfffd7a7e, 0}},
+ {{0, 0x0000644c, 0xfffdfb98, 0}}, {{0, 0x00004b39, 0xfffe7cb2, 0}},
+ {{0, 0x00003226, 0xfffefdcc, 0}}, {{0, 0x00001913, 0xffff7ee6, 0}},
+ {{0, 0x00000000, 0x00000000, 0}}, {{0, 0xffffe6ed, 0x0000811a, 0}},
+ {{0, 0xffffcdda, 0x00010234, 0}}, {{0, 0xffffb4c7, 0x0001834e, 0}},
+ {{0, 0xffff9bb4, 0x00020468, 0}}, {{0, 0xffff82a1, 0x00028582, 0}},
+ {{0, 0xffff698e, 0x0003069c, 0}}, {{0, 0xffff507b, 0x000387b6, 0}},
+ {{0, 0xffff3768, 0x000408d0, 0}}, {{0, 0xffff1e55, 0x000489ea, 0}},
+ {{0, 0xffff0542, 0x00050b04, 0}}, {{0, 0xfffeec2f, 0x00058c1e, 0}},
+ {{0, 0xfffed31c, 0x00060d38, 0}}, {{0, 0xfffeba09, 0x00068e52, 0}},
+ {{0, 0xfffea0f6, 0x00070f6c, 0}}, {{0, 0xfffe87e3, 0x00079086, 0}},
+ {{0, 0xfffe6ed0, 0x000811a0, 0}}, {{0, 0xfffe55bd, 0x000892ba, 0}},
+ {{0, 0xfffe3caa, 0x000913d4, 0}}, {{0, 0xfffe2397, 0x000994ee, 0}},
+ {{0, 0xfffe0a84, 0x000a1608, 0}}, {{0, 0xfffdf171, 0x000a9722, 0}},
+ {{0, 0xfffdd85e, 0x000b183c, 0}}, {{0, 0xfffdbf4b, 0x000b9956, 0}},
+ {{0, 0xfffda638, 0x000c1a70, 0}}, {{0, 0xfffd8d25, 0x000c9b8a, 0}},
+ {{0, 0xfffd7412, 0x000d1ca4, 0}}, {{0, 0xfffd5aff, 0x000d9dbe, 0}},
+ {{0, 0xfffd41ec, 0x000e1ed8, 0}}, {{0, 0xfffd28d9, 0x000e9ff2, 0}},
+ {{0, 0xfffd0fc6, 0x000f210c, 0}}, {{0, 0xfffcf6b3, 0x000fa226, 0}},
+ {{0, 0xfffcdda0, 0x00102340, 0}}, {{0, 0xfffcc48d, 0x0010a45a, 0}},
+ {{0, 0xfffcab7a, 0x00112574, 0}}, {{0, 0xfffc9267, 0x0011a68e, 0}},
+ {{0, 0xfffc7954, 0x001227a8, 0}}, {{0, 0xfffc6041, 0x0012a8c2, 0}},
+ {{0, 0xfffc472e, 0x001329dc, 0}}, {{0, 0xfffc2e1b, 0x0013aaf6, 0}},
+ {{0, 0xfffc1508, 0x00142c10, 0}}, {{0, 0xfffbfbf5, 0x0014ad2a, 0}},
+ {{0, 0xfffbe2e2, 0x00152e44, 0}}, {{0, 0xfffbc9cf, 0x0015af5e, 0}},
+ {{0, 0xfffbb0bc, 0x00163078, 0}}, {{0, 0xfffb97a9, 0x0016b192, 0}},
+ {{0, 0xfffb7e96, 0x001732ac, 0}}, {{0, 0xfffb6583, 0x0017b3c6, 0}},
+ {{0, 0xfffb4c70, 0x001834e0, 0}}, {{0, 0xfffb335d, 0x0018b5fa, 0}},
+ {{0, 0xfffb1a4a, 0x00193714, 0}}, {{0, 0xfffb0137, 0x0019b82e, 0}},
+ {{0, 0xfffae824, 0x001a3948, 0}}, {{0, 0xfffacf11, 0x001aba62, 0}},
+ {{0, 0xfffab5fe, 0x001b3b7c, 0}}, {{0, 0xfffa9ceb, 0x001bbc96, 0}},
+ {{0, 0xfffa83d8, 0x001c3db0, 0}}, {{0, 0xfffa6ac5, 0x001cbeca, 0}},
+ {{0, 0xfffa51b2, 0x001d3fe4, 0}}, {{0, 0xfffa389f, 0x001dc0fe, 0}},
+ {{0, 0xfffa1f8c, 0x001e4218, 0}}, {{0, 0xfffa0679, 0x001ec332, 0}},
+ {{0, 0xfff9ed66, 0x001f444c, 0}}, {{0, 0xfff9d453, 0x001fc566, 0}},
+ {{0, 0xfff9bb40, 0x00204680, 0}}, {{0, 0xfff9a22d, 0x0020c79a, 0}},
+ {{0, 0xfff9891a, 0x002148b4, 0}}, {{0, 0xfff97007, 0x0021c9ce, 0}},
+ {{0, 0xfff956f4, 0x00224ae8, 0}}, {{0, 0xfff93de1, 0x0022cc02, 0}},
+ {{0, 0xfff924ce, 0x00234d1c, 0}}, {{0, 0xfff90bbb, 0x0023ce36, 0}},
+ {{0, 0xfff8f2a8, 0x00244f50, 0}}, {{0, 0xfff8d995, 0x0024d06a, 0}},
+ {{0, 0xfff8c082, 0x00255184, 0}}, {{0, 0xfff8a76f, 0x0025d29e, 0}},
+ {{0, 0xfff88e5c, 0x002653b8, 0}}, {{0, 0xfff87549, 0x0026d4d2, 0}},
+ {{0, 0xfff85c36, 0x002755ec, 0}}, {{0, 0xfff84323, 0x0027d706, 0}},
+ {{0, 0xfff82a10, 0x00285820, 0}}, {{0, 0xfff810fd, 0x0028d93a, 0}},
+ {{0, 0xfff7f7ea, 0x00295a54, 0}}, {{0, 0xfff7ded7, 0x0029db6e, 0}},
+ {{0, 0xfff7c5c4, 0x002a5c88, 0}}, {{0, 0xfff7acb1, 0x002adda2, 0}},
+ {{0, 0xfff7939e, 0x002b5ebc, 0}}, {{0, 0xfff77a8b, 0x002bdfd6, 0}},
+ {{0, 0xfff76178, 0x002c60f0, 0}}, {{0, 0xfff74865, 0x002ce20a, 0}},
+ {{0, 0xfff72f52, 0x002d6324, 0}}, {{0, 0xfff7163f, 0x002de43e, 0}},
+ {{0, 0xfff6fd2c, 0x002e6558, 0}}, {{0, 0xfff6e419, 0x002ee672, 0}},
+ {{0, 0xfff6cb06, 0x002f678c, 0}}, {{0, 0xfff6b1f3, 0x002fe8a6, 0}},
+ {{0, 0xfff698e0, 0x003069c0, 0}}, {{0, 0xfff67fcd, 0x0030eada, 0}},
+ {{0, 0xfff666ba, 0x00316bf4, 0}}, {{0, 0xfff64da7, 0x0031ed0e, 0}},
+ {{0, 0xfff63494, 0x00326e28, 0}}, {{0, 0xfff61b81, 0x0032ef42, 0}},
+ {{0, 0xfff6026e, 0x0033705c, 0}}, {{0, 0xfff5e95b, 0x0033f176, 0}},
+ {{0, 0xfff5d048, 0x00347290, 0}}, {{0, 0xfff5b735, 0x0034f3aa, 0}},
+ {{0, 0xfff59e22, 0x003574c4, 0}}, {{0, 0xfff5850f, 0x0035f5de, 0}},
+ {{0, 0xfff56bfc, 0x003676f8, 0}}, {{0, 0xfff552e9, 0x0036f812, 0}},
+ {{0, 0xfff539d6, 0x0037792c, 0}}, {{0, 0xfff520c3, 0x0037fa46, 0}},
+ {{0, 0xfff507b0, 0x00387b60, 0}}, {{0, 0xfff4ee9d, 0x0038fc7a, 0}},
+ {{0, 0xfff4d58a, 0x00397d94, 0}}, {{0, 0xfff4bc77, 0x0039feae, 0}},
+ {{0, 0xfff4a364, 0x003a7fc8, 0}}, {{0, 0xfff48a51, 0x003b00e2, 0}},
+ {{0, 0xfff4713e, 0x003b81fc, 0}}, {{0, 0xfff4582b, 0x003c0316, 0}},
+ {{0, 0xfff43f18, 0x003c8430, 0}}, {{0, 0xfff42605, 0x003d054a, 0}},
+ {{0, 0xfff40cf2, 0x003d8664, 0}}, {{0, 0xfff3f3df, 0x003e077e, 0}},
+ {{0, 0xfff3dacc, 0x003e8898, 0}}, {{0, 0xfff3c1b9, 0x003f09b2, 0}},
+ {{0, 0xfff3a8a6, 0x003f8acc, 0}}, {{0, 0xfff38f93, 0x00400be6, 0}}
+};
+
+static VP8kCstSSE2 VP8kVtoRGBA[256] = {
+ {{0xffcced80, 0x001a0400, 0, 0}}, {{0xffcd53a5, 0x0019cff8, 0, 0}},
+ {{0xffcdb9ca, 0x00199bf0, 0, 0}}, {{0xffce1fef, 0x001967e8, 0, 0}},
+ {{0xffce8614, 0x001933e0, 0, 0}}, {{0xffceec39, 0x0018ffd8, 0, 0}},
+ {{0xffcf525e, 0x0018cbd0, 0, 0}}, {{0xffcfb883, 0x001897c8, 0, 0}},
+ {{0xffd01ea8, 0x001863c0, 0, 0}}, {{0xffd084cd, 0x00182fb8, 0, 0}},
+ {{0xffd0eaf2, 0x0017fbb0, 0, 0}}, {{0xffd15117, 0x0017c7a8, 0, 0}},
+ {{0xffd1b73c, 0x001793a0, 0, 0}}, {{0xffd21d61, 0x00175f98, 0, 0}},
+ {{0xffd28386, 0x00172b90, 0, 0}}, {{0xffd2e9ab, 0x0016f788, 0, 0}},
+ {{0xffd34fd0, 0x0016c380, 0, 0}}, {{0xffd3b5f5, 0x00168f78, 0, 0}},
+ {{0xffd41c1a, 0x00165b70, 0, 0}}, {{0xffd4823f, 0x00162768, 0, 0}},
+ {{0xffd4e864, 0x0015f360, 0, 0}}, {{0xffd54e89, 0x0015bf58, 0, 0}},
+ {{0xffd5b4ae, 0x00158b50, 0, 0}}, {{0xffd61ad3, 0x00155748, 0, 0}},
+ {{0xffd680f8, 0x00152340, 0, 0}}, {{0xffd6e71d, 0x0014ef38, 0, 0}},
+ {{0xffd74d42, 0x0014bb30, 0, 0}}, {{0xffd7b367, 0x00148728, 0, 0}},
+ {{0xffd8198c, 0x00145320, 0, 0}}, {{0xffd87fb1, 0x00141f18, 0, 0}},
+ {{0xffd8e5d6, 0x0013eb10, 0, 0}}, {{0xffd94bfb, 0x0013b708, 0, 0}},
+ {{0xffd9b220, 0x00138300, 0, 0}}, {{0xffda1845, 0x00134ef8, 0, 0}},
+ {{0xffda7e6a, 0x00131af0, 0, 0}}, {{0xffdae48f, 0x0012e6e8, 0, 0}},
+ {{0xffdb4ab4, 0x0012b2e0, 0, 0}}, {{0xffdbb0d9, 0x00127ed8, 0, 0}},
+ {{0xffdc16fe, 0x00124ad0, 0, 0}}, {{0xffdc7d23, 0x001216c8, 0, 0}},
+ {{0xffdce348, 0x0011e2c0, 0, 0}}, {{0xffdd496d, 0x0011aeb8, 0, 0}},
+ {{0xffddaf92, 0x00117ab0, 0, 0}}, {{0xffde15b7, 0x001146a8, 0, 0}},
+ {{0xffde7bdc, 0x001112a0, 0, 0}}, {{0xffdee201, 0x0010de98, 0, 0}},
+ {{0xffdf4826, 0x0010aa90, 0, 0}}, {{0xffdfae4b, 0x00107688, 0, 0}},
+ {{0xffe01470, 0x00104280, 0, 0}}, {{0xffe07a95, 0x00100e78, 0, 0}},
+ {{0xffe0e0ba, 0x000fda70, 0, 0}}, {{0xffe146df, 0x000fa668, 0, 0}},
+ {{0xffe1ad04, 0x000f7260, 0, 0}}, {{0xffe21329, 0x000f3e58, 0, 0}},
+ {{0xffe2794e, 0x000f0a50, 0, 0}}, {{0xffe2df73, 0x000ed648, 0, 0}},
+ {{0xffe34598, 0x000ea240, 0, 0}}, {{0xffe3abbd, 0x000e6e38, 0, 0}},
+ {{0xffe411e2, 0x000e3a30, 0, 0}}, {{0xffe47807, 0x000e0628, 0, 0}},
+ {{0xffe4de2c, 0x000dd220, 0, 0}}, {{0xffe54451, 0x000d9e18, 0, 0}},
+ {{0xffe5aa76, 0x000d6a10, 0, 0}}, {{0xffe6109b, 0x000d3608, 0, 0}},
+ {{0xffe676c0, 0x000d0200, 0, 0}}, {{0xffe6dce5, 0x000ccdf8, 0, 0}},
+ {{0xffe7430a, 0x000c99f0, 0, 0}}, {{0xffe7a92f, 0x000c65e8, 0, 0}},
+ {{0xffe80f54, 0x000c31e0, 0, 0}}, {{0xffe87579, 0x000bfdd8, 0, 0}},
+ {{0xffe8db9e, 0x000bc9d0, 0, 0}}, {{0xffe941c3, 0x000b95c8, 0, 0}},
+ {{0xffe9a7e8, 0x000b61c0, 0, 0}}, {{0xffea0e0d, 0x000b2db8, 0, 0}},
+ {{0xffea7432, 0x000af9b0, 0, 0}}, {{0xffeada57, 0x000ac5a8, 0, 0}},
+ {{0xffeb407c, 0x000a91a0, 0, 0}}, {{0xffeba6a1, 0x000a5d98, 0, 0}},
+ {{0xffec0cc6, 0x000a2990, 0, 0}}, {{0xffec72eb, 0x0009f588, 0, 0}},
+ {{0xffecd910, 0x0009c180, 0, 0}}, {{0xffed3f35, 0x00098d78, 0, 0}},
+ {{0xffeda55a, 0x00095970, 0, 0}}, {{0xffee0b7f, 0x00092568, 0, 0}},
+ {{0xffee71a4, 0x0008f160, 0, 0}}, {{0xffeed7c9, 0x0008bd58, 0, 0}},
+ {{0xffef3dee, 0x00088950, 0, 0}}, {{0xffefa413, 0x00085548, 0, 0}},
+ {{0xfff00a38, 0x00082140, 0, 0}}, {{0xfff0705d, 0x0007ed38, 0, 0}},
+ {{0xfff0d682, 0x0007b930, 0, 0}}, {{0xfff13ca7, 0x00078528, 0, 0}},
+ {{0xfff1a2cc, 0x00075120, 0, 0}}, {{0xfff208f1, 0x00071d18, 0, 0}},
+ {{0xfff26f16, 0x0006e910, 0, 0}}, {{0xfff2d53b, 0x0006b508, 0, 0}},
+ {{0xfff33b60, 0x00068100, 0, 0}}, {{0xfff3a185, 0x00064cf8, 0, 0}},
+ {{0xfff407aa, 0x000618f0, 0, 0}}, {{0xfff46dcf, 0x0005e4e8, 0, 0}},
+ {{0xfff4d3f4, 0x0005b0e0, 0, 0}}, {{0xfff53a19, 0x00057cd8, 0, 0}},
+ {{0xfff5a03e, 0x000548d0, 0, 0}}, {{0xfff60663, 0x000514c8, 0, 0}},
+ {{0xfff66c88, 0x0004e0c0, 0, 0}}, {{0xfff6d2ad, 0x0004acb8, 0, 0}},
+ {{0xfff738d2, 0x000478b0, 0, 0}}, {{0xfff79ef7, 0x000444a8, 0, 0}},
+ {{0xfff8051c, 0x000410a0, 0, 0}}, {{0xfff86b41, 0x0003dc98, 0, 0}},
+ {{0xfff8d166, 0x0003a890, 0, 0}}, {{0xfff9378b, 0x00037488, 0, 0}},
+ {{0xfff99db0, 0x00034080, 0, 0}}, {{0xfffa03d5, 0x00030c78, 0, 0}},
+ {{0xfffa69fa, 0x0002d870, 0, 0}}, {{0xfffad01f, 0x0002a468, 0, 0}},
+ {{0xfffb3644, 0x00027060, 0, 0}}, {{0xfffb9c69, 0x00023c58, 0, 0}},
+ {{0xfffc028e, 0x00020850, 0, 0}}, {{0xfffc68b3, 0x0001d448, 0, 0}},
+ {{0xfffcced8, 0x0001a040, 0, 0}}, {{0xfffd34fd, 0x00016c38, 0, 0}},
+ {{0xfffd9b22, 0x00013830, 0, 0}}, {{0xfffe0147, 0x00010428, 0, 0}},
+ {{0xfffe676c, 0x0000d020, 0, 0}}, {{0xfffecd91, 0x00009c18, 0, 0}},
+ {{0xffff33b6, 0x00006810, 0, 0}}, {{0xffff99db, 0x00003408, 0, 0}},
+ {{0x00000000, 0x00000000, 0, 0}}, {{0x00006625, 0xffffcbf8, 0, 0}},
+ {{0x0000cc4a, 0xffff97f0, 0, 0}}, {{0x0001326f, 0xffff63e8, 0, 0}},
+ {{0x00019894, 0xffff2fe0, 0, 0}}, {{0x0001feb9, 0xfffefbd8, 0, 0}},
+ {{0x000264de, 0xfffec7d0, 0, 0}}, {{0x0002cb03, 0xfffe93c8, 0, 0}},
+ {{0x00033128, 0xfffe5fc0, 0, 0}}, {{0x0003974d, 0xfffe2bb8, 0, 0}},
+ {{0x0003fd72, 0xfffdf7b0, 0, 0}}, {{0x00046397, 0xfffdc3a8, 0, 0}},
+ {{0x0004c9bc, 0xfffd8fa0, 0, 0}}, {{0x00052fe1, 0xfffd5b98, 0, 0}},
+ {{0x00059606, 0xfffd2790, 0, 0}}, {{0x0005fc2b, 0xfffcf388, 0, 0}},
+ {{0x00066250, 0xfffcbf80, 0, 0}}, {{0x0006c875, 0xfffc8b78, 0, 0}},
+ {{0x00072e9a, 0xfffc5770, 0, 0}}, {{0x000794bf, 0xfffc2368, 0, 0}},
+ {{0x0007fae4, 0xfffbef60, 0, 0}}, {{0x00086109, 0xfffbbb58, 0, 0}},
+ {{0x0008c72e, 0xfffb8750, 0, 0}}, {{0x00092d53, 0xfffb5348, 0, 0}},
+ {{0x00099378, 0xfffb1f40, 0, 0}}, {{0x0009f99d, 0xfffaeb38, 0, 0}},
+ {{0x000a5fc2, 0xfffab730, 0, 0}}, {{0x000ac5e7, 0xfffa8328, 0, 0}},
+ {{0x000b2c0c, 0xfffa4f20, 0, 0}}, {{0x000b9231, 0xfffa1b18, 0, 0}},
+ {{0x000bf856, 0xfff9e710, 0, 0}}, {{0x000c5e7b, 0xfff9b308, 0, 0}},
+ {{0x000cc4a0, 0xfff97f00, 0, 0}}, {{0x000d2ac5, 0xfff94af8, 0, 0}},
+ {{0x000d90ea, 0xfff916f0, 0, 0}}, {{0x000df70f, 0xfff8e2e8, 0, 0}},
+ {{0x000e5d34, 0xfff8aee0, 0, 0}}, {{0x000ec359, 0xfff87ad8, 0, 0}},
+ {{0x000f297e, 0xfff846d0, 0, 0}}, {{0x000f8fa3, 0xfff812c8, 0, 0}},
+ {{0x000ff5c8, 0xfff7dec0, 0, 0}}, {{0x00105bed, 0xfff7aab8, 0, 0}},
+ {{0x0010c212, 0xfff776b0, 0, 0}}, {{0x00112837, 0xfff742a8, 0, 0}},
+ {{0x00118e5c, 0xfff70ea0, 0, 0}}, {{0x0011f481, 0xfff6da98, 0, 0}},
+ {{0x00125aa6, 0xfff6a690, 0, 0}}, {{0x0012c0cb, 0xfff67288, 0, 0}},
+ {{0x001326f0, 0xfff63e80, 0, 0}}, {{0x00138d15, 0xfff60a78, 0, 0}},
+ {{0x0013f33a, 0xfff5d670, 0, 0}}, {{0x0014595f, 0xfff5a268, 0, 0}},
+ {{0x0014bf84, 0xfff56e60, 0, 0}}, {{0x001525a9, 0xfff53a58, 0, 0}},
+ {{0x00158bce, 0xfff50650, 0, 0}}, {{0x0015f1f3, 0xfff4d248, 0, 0}},
+ {{0x00165818, 0xfff49e40, 0, 0}}, {{0x0016be3d, 0xfff46a38, 0, 0}},
+ {{0x00172462, 0xfff43630, 0, 0}}, {{0x00178a87, 0xfff40228, 0, 0}},
+ {{0x0017f0ac, 0xfff3ce20, 0, 0}}, {{0x001856d1, 0xfff39a18, 0, 0}},
+ {{0x0018bcf6, 0xfff36610, 0, 0}}, {{0x0019231b, 0xfff33208, 0, 0}},
+ {{0x00198940, 0xfff2fe00, 0, 0}}, {{0x0019ef65, 0xfff2c9f8, 0, 0}},
+ {{0x001a558a, 0xfff295f0, 0, 0}}, {{0x001abbaf, 0xfff261e8, 0, 0}},
+ {{0x001b21d4, 0xfff22de0, 0, 0}}, {{0x001b87f9, 0xfff1f9d8, 0, 0}},
+ {{0x001bee1e, 0xfff1c5d0, 0, 0}}, {{0x001c5443, 0xfff191c8, 0, 0}},
+ {{0x001cba68, 0xfff15dc0, 0, 0}}, {{0x001d208d, 0xfff129b8, 0, 0}},
+ {{0x001d86b2, 0xfff0f5b0, 0, 0}}, {{0x001decd7, 0xfff0c1a8, 0, 0}},
+ {{0x001e52fc, 0xfff08da0, 0, 0}}, {{0x001eb921, 0xfff05998, 0, 0}},
+ {{0x001f1f46, 0xfff02590, 0, 0}}, {{0x001f856b, 0xffeff188, 0, 0}},
+ {{0x001feb90, 0xffefbd80, 0, 0}}, {{0x002051b5, 0xffef8978, 0, 0}},
+ {{0x0020b7da, 0xffef5570, 0, 0}}, {{0x00211dff, 0xffef2168, 0, 0}},
+ {{0x00218424, 0xffeeed60, 0, 0}}, {{0x0021ea49, 0xffeeb958, 0, 0}},
+ {{0x0022506e, 0xffee8550, 0, 0}}, {{0x0022b693, 0xffee5148, 0, 0}},
+ {{0x00231cb8, 0xffee1d40, 0, 0}}, {{0x002382dd, 0xffede938, 0, 0}},
+ {{0x0023e902, 0xffedb530, 0, 0}}, {{0x00244f27, 0xffed8128, 0, 0}},
+ {{0x0024b54c, 0xffed4d20, 0, 0}}, {{0x00251b71, 0xffed1918, 0, 0}},
+ {{0x00258196, 0xffece510, 0, 0}}, {{0x0025e7bb, 0xffecb108, 0, 0}},
+ {{0x00264de0, 0xffec7d00, 0, 0}}, {{0x0026b405, 0xffec48f8, 0, 0}},
+ {{0x00271a2a, 0xffec14f0, 0, 0}}, {{0x0027804f, 0xffebe0e8, 0, 0}},
+ {{0x0027e674, 0xffebace0, 0, 0}}, {{0x00284c99, 0xffeb78d8, 0, 0}},
+ {{0x0028b2be, 0xffeb44d0, 0, 0}}, {{0x002918e3, 0xffeb10c8, 0, 0}},
+ {{0x00297f08, 0xffeadcc0, 0, 0}}, {{0x0029e52d, 0xffeaa8b8, 0, 0}},
+ {{0x002a4b52, 0xffea74b0, 0, 0}}, {{0x002ab177, 0xffea40a8, 0, 0}},
+ {{0x002b179c, 0xffea0ca0, 0, 0}}, {{0x002b7dc1, 0xffe9d898, 0, 0}},
+ {{0x002be3e6, 0xffe9a490, 0, 0}}, {{0x002c4a0b, 0xffe97088, 0, 0}},
+ {{0x002cb030, 0xffe93c80, 0, 0}}, {{0x002d1655, 0xffe90878, 0, 0}},
+ {{0x002d7c7a, 0xffe8d470, 0, 0}}, {{0x002de29f, 0xffe8a068, 0, 0}},
+ {{0x002e48c4, 0xffe86c60, 0, 0}}, {{0x002eaee9, 0xffe83858, 0, 0}},
+ {{0x002f150e, 0xffe80450, 0, 0}}, {{0x002f7b33, 0xffe7d048, 0, 0}},
+ {{0x002fe158, 0xffe79c40, 0, 0}}, {{0x0030477d, 0xffe76838, 0, 0}},
+ {{0x0030ada2, 0xffe73430, 0, 0}}, {{0x003113c7, 0xffe70028, 0, 0}},
+ {{0x003179ec, 0xffe6cc20, 0, 0}}, {{0x0031e011, 0xffe69818, 0, 0}},
+ {{0x00324636, 0xffe66410, 0, 0}}, {{0x0032ac5b, 0xffe63008, 0, 0}}
+};
diff --git a/drivers/webp/enc/alpha.c b/drivers/webp/enc/alpha.c
index e554eb7f30..1842b36401 100644
--- a/drivers/webp/enc/alpha.c
+++ b/drivers/webp/enc/alpha.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Alpha-plane compression.
@@ -13,13 +15,11 @@
#include <stdlib.h>
#include "./vp8enci.h"
+#include "../dsp/dsp.h"
#include "../utils/filters.h"
#include "../utils/quant_levels.h"
-#include "../format_constants.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+#include "../utils/utils.h"
+#include "webp/format_constants.h"
// -----------------------------------------------------------------------------
// Encodes the given alpha data via specified compression method 'method'.
@@ -36,7 +36,7 @@ extern "C" {
//
// 'output' corresponds to the buffer containing compressed alpha data.
// This buffer is allocated by this method and caller should call
-// free(*output) when done.
+// WebPSafeFree(*output) when done.
// 'output_size' corresponds to size of this compressed alpha buffer.
//
// Returns 1 on successfully encoding the alpha and
@@ -48,12 +48,11 @@ extern "C" {
static int EncodeLossless(const uint8_t* const data, int width, int height,
int effort_level, // in [0..6] range
- VP8BitWriter* const bw,
+ VP8LBitWriter* const bw,
WebPAuxStats* const stats) {
int ok = 0;
WebPConfig config;
WebPPicture picture;
- VP8LBitWriter tmp_bw;
WebPPictureInit(&picture);
picture.width = width;
@@ -63,53 +62,51 @@ static int EncodeLossless(const uint8_t* const data, int width, int height,
if (!WebPPictureAlloc(&picture)) return 0;
// Transfer the alpha values to the green channel.
- {
- int i, j;
- uint32_t* dst = picture.argb;
- const uint8_t* src = data;
- for (j = 0; j < picture.height; ++j) {
- for (i = 0; i < picture.width; ++i) {
- dst[i] = (src[i] << 8) | 0xff000000u;
- }
- src += width;
- dst += picture.argb_stride;
- }
- }
+ WebPDispatchAlphaToGreen(data, width, picture.width, picture.height,
+ picture.argb, picture.argb_stride);
WebPConfigInit(&config);
config.lossless = 1;
config.method = effort_level; // impact is very small
- // Set moderate default quality setting for alpha. Higher qualities (80 and
- // above) could be very slow.
- config.quality = 10.f + 15.f * effort_level;
- if (config.quality > 100.f) config.quality = 100.f;
+ // Set a low default quality for encoding alpha. Ensure that Alpha quality at
+ // lower methods (3 and below) is less than the threshold for triggering
+ // costly 'BackwardReferencesTraceBackwards'.
+ config.quality = 8.f * effort_level;
+ assert(config.quality >= 0 && config.quality <= 100.f);
- ok = VP8LBitWriterInit(&tmp_bw, (width * height) >> 3);
- ok = ok && (VP8LEncodeStream(&config, &picture, &tmp_bw) == VP8_ENC_OK);
+ ok = (VP8LEncodeStream(&config, &picture, bw) == VP8_ENC_OK);
WebPPictureFree(&picture);
- if (ok) {
- const uint8_t* const data = VP8LBitWriterFinish(&tmp_bw);
- const size_t data_size = VP8LBitWriterNumBytes(&tmp_bw);
- VP8BitWriterAppend(bw, data, data_size);
+ ok = ok && !bw->error_;
+ if (!ok) {
+ VP8LBitWriterWipeOut(bw);
+ return 0;
}
- VP8LBitWriterDestroy(&tmp_bw);
- return ok && !bw->error_;
+ return 1;
}
// -----------------------------------------------------------------------------
+// Small struct to hold the result of a filter mode compression attempt.
+typedef struct {
+ size_t score;
+ VP8BitWriter bw;
+ WebPAuxStats stats;
+} FilterTrial;
+
+// This function always returns an initialized 'bw' object, even upon error.
static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
int method, int filter, int reduce_levels,
int effort_level, // in [0..6] range
uint8_t* const tmp_alpha,
- VP8BitWriter* const bw,
- WebPAuxStats* const stats) {
+ FilterTrial* result) {
int ok = 0;
const uint8_t* alpha_src;
WebPFilterFunc filter_func;
uint8_t header;
- size_t expected_size;
const size_t data_size = width * height;
+ const uint8_t* output = NULL;
+ size_t output_size = 0;
+ VP8LBitWriter tmp_bw;
assert((uint64_t)data_size == (uint64_t)width * height); // as per spec
assert(filter >= 0 && filter < WEBP_FILTER_LAST);
@@ -118,43 +115,163 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
assert(sizeof(header) == ALPHA_HEADER_LEN);
// TODO(skal): have a common function and #define's to validate alpha params.
- expected_size =
- (method == ALPHA_NO_COMPRESSION) ? (ALPHA_HEADER_LEN + data_size)
- : (data_size >> 5);
- header = method | (filter << 2);
- if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4;
-
- VP8BitWriterInit(bw, expected_size);
- VP8BitWriterAppend(bw, &header, ALPHA_HEADER_LEN);
-
filter_func = WebPFilters[filter];
- if (filter_func) {
- filter_func(data, width, height, 1, width, tmp_alpha);
+ if (filter_func != NULL) {
+ filter_func(data, width, height, width, tmp_alpha);
alpha_src = tmp_alpha;
} else {
alpha_src = data;
}
+ if (method != ALPHA_NO_COMPRESSION) {
+ ok = VP8LBitWriterInit(&tmp_bw, data_size >> 3);
+ ok = ok && EncodeLossless(alpha_src, width, height, effort_level,
+ &tmp_bw, &result->stats);
+ if (ok) {
+ output = VP8LBitWriterFinish(&tmp_bw);
+ output_size = VP8LBitWriterNumBytes(&tmp_bw);
+ if (output_size > data_size) {
+ // compressed size is larger than source! Revert to uncompressed mode.
+ method = ALPHA_NO_COMPRESSION;
+ VP8LBitWriterWipeOut(&tmp_bw);
+ }
+ } else {
+ VP8LBitWriterWipeOut(&tmp_bw);
+ return 0;
+ }
+ }
+
if (method == ALPHA_NO_COMPRESSION) {
- ok = VP8BitWriterAppend(bw, alpha_src, width * height);
- ok = ok && !bw->error_;
- } else {
- ok = EncodeLossless(alpha_src, width, height, effort_level, bw, stats);
- VP8BitWriterFinish(bw);
+ output = alpha_src;
+ output_size = data_size;
+ ok = 1;
+ }
+
+ // Emit final result.
+ header = method | (filter << 2);
+ if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4;
+
+ VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size);
+ ok = ok && VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN);
+ ok = ok && VP8BitWriterAppend(&result->bw, output, output_size);
+
+ if (method != ALPHA_NO_COMPRESSION) {
+ VP8LBitWriterWipeOut(&tmp_bw);
}
+ ok = ok && !result->bw.error_;
+ result->score = VP8BitWriterSize(&result->bw);
return ok;
}
// -----------------------------------------------------------------------------
-// TODO(skal): move to dsp/ ?
-static void CopyPlane(const uint8_t* src, int src_stride,
- uint8_t* dst, int dst_stride, int width, int height) {
- while (height-- > 0) {
- memcpy(dst, src, width);
- src += src_stride;
- dst += dst_stride;
+static int GetNumColors(const uint8_t* data, int width, int height,
+ int stride) {
+ int j;
+ int colors = 0;
+ uint8_t color[256] = { 0 };
+
+ for (j = 0; j < height; ++j) {
+ int i;
+ const uint8_t* const p = data + j * stride;
+ for (i = 0; i < width; ++i) {
+ color[p[i]] = 1;
+ }
+ }
+ for (j = 0; j < 256; ++j) {
+ if (color[j] > 0) ++colors;
}
+ return colors;
+}
+
+#define FILTER_TRY_NONE (1 << WEBP_FILTER_NONE)
+#define FILTER_TRY_ALL ((1 << WEBP_FILTER_LAST) - 1)
+
+// Given the input 'filter' option, return an OR'd bit-set of filters to try.
+static uint32_t GetFilterMap(const uint8_t* alpha, int width, int height,
+ int filter, int effort_level) {
+ uint32_t bit_map = 0U;
+ if (filter == WEBP_FILTER_FAST) {
+ // Quick estimate of the best candidate.
+ int try_filter_none = (effort_level > 3);
+ const int kMinColorsForFilterNone = 16;
+ const int kMaxColorsForFilterNone = 192;
+ const int num_colors = GetNumColors(alpha, width, height, width);
+ // For low number of colors, NONE yields better compression.
+ filter = (num_colors <= kMinColorsForFilterNone)
+ ? WEBP_FILTER_NONE
+ : WebPEstimateBestFilter(alpha, width, height, width);
+ bit_map |= 1 << filter;
+ // For large number of colors, try FILTER_NONE in addition to the best
+ // filter as well.
+ if (try_filter_none || num_colors > kMaxColorsForFilterNone) {
+ bit_map |= FILTER_TRY_NONE;
+ }
+ } else if (filter == WEBP_FILTER_NONE) {
+ bit_map = FILTER_TRY_NONE;
+ } else { // WEBP_FILTER_BEST -> try all
+ bit_map = FILTER_TRY_ALL;
+ }
+ return bit_map;
+}
+
+static void InitFilterTrial(FilterTrial* const score) {
+ score->score = (size_t)~0U;
+ VP8BitWriterInit(&score->bw, 0);
+}
+
+static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height,
+ size_t data_size, int method, int filter,
+ int reduce_levels, int effort_level,
+ uint8_t** const output,
+ size_t* const output_size,
+ WebPAuxStats* const stats) {
+ int ok = 1;
+ FilterTrial best;
+ uint32_t try_map =
+ GetFilterMap(alpha, width, height, filter, effort_level);
+ InitFilterTrial(&best);
+
+ if (try_map != FILTER_TRY_NONE) {
+ uint8_t* filtered_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size);
+ if (filtered_alpha == NULL) return 0;
+
+ for (filter = WEBP_FILTER_NONE; ok && try_map; ++filter, try_map >>= 1) {
+ if (try_map & 1) {
+ FilterTrial trial;
+ ok = EncodeAlphaInternal(alpha, width, height, method, filter,
+ reduce_levels, effort_level, filtered_alpha,
+ &trial);
+ if (ok && trial.score < best.score) {
+ VP8BitWriterWipeOut(&best.bw);
+ best = trial;
+ } else {
+ VP8BitWriterWipeOut(&trial.bw);
+ }
+ }
+ }
+ WebPSafeFree(filtered_alpha);
+ } else {
+ ok = EncodeAlphaInternal(alpha, width, height, method, WEBP_FILTER_NONE,
+ reduce_levels, effort_level, NULL, &best);
+ }
+ if (ok) {
+ if (stats != NULL) {
+ stats->lossless_features = best.stats.lossless_features;
+ stats->histogram_bits = best.stats.histogram_bits;
+ stats->transform_bits = best.stats.transform_bits;
+ stats->cache_bits = best.stats.cache_bits;
+ stats->palette_size = best.stats.palette_size;
+ stats->lossless_size = best.stats.lossless_size;
+ stats->lossless_hdr_size = best.stats.lossless_hdr_size;
+ stats->lossless_data_size = best.stats.lossless_data_size;
+ }
+ *output_size = VP8BitWriterSize(&best.bw);
+ *output = VP8BitWriterBuf(&best.bw);
+ } else {
+ VP8BitWriterWipeOut(&best.bw);
+ }
+ return ok;
}
static int EncodeAlpha(VP8Encoder* const enc,
@@ -187,13 +304,18 @@ static int EncodeAlpha(VP8Encoder* const enc,
return 0;
}
- quant_alpha = (uint8_t*)malloc(data_size);
+ if (method == ALPHA_NO_COMPRESSION) {
+ // Don't filter, as filtering will make no impact on compressed size.
+ filter = WEBP_FILTER_NONE;
+ }
+
+ quant_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size);
if (quant_alpha == NULL) {
return 0;
}
// Extract alpha data (width x height) from raw_data (stride x height).
- CopyPlane(pic->a, pic->a_stride, quant_alpha, width, width, height);
+ WebPCopyPlane(pic->a, pic->a_stride, quant_alpha, width, width, height);
if (reduce_levels) { // No Quantization required for 'quality = 100'.
// 16 alpha levels gives quite a low MSE w.r.t original alpha plane hence
@@ -205,126 +327,99 @@ static int EncodeAlpha(VP8Encoder* const enc,
}
if (ok) {
- VP8BitWriter bw;
- int test_filter;
- uint8_t* filtered_alpha = NULL;
-
- // We always test WEBP_FILTER_NONE first.
- ok = EncodeAlphaInternal(quant_alpha, width, height,
- method, WEBP_FILTER_NONE, reduce_levels,
- effort_level, NULL, &bw, pic->stats);
- if (!ok) {
- VP8BitWriterWipeOut(&bw);
- goto End;
- }
-
- if (filter == WEBP_FILTER_FAST) { // Quick estimate of a second candidate?
- filter = EstimateBestFilter(quant_alpha, width, height, width);
- }
- // Stop?
- if (filter == WEBP_FILTER_NONE) {
- goto Ok;
- }
-
- filtered_alpha = (uint8_t*)malloc(data_size);
- ok = (filtered_alpha != NULL);
- if (!ok) {
- goto End;
+ VP8FiltersInit();
+ ok = ApplyFiltersAndEncode(quant_alpha, width, height, data_size, method,
+ filter, reduce_levels, effort_level, output,
+ output_size, pic->stats);
+ if (pic->stats != NULL) { // need stats?
+ pic->stats->coded_size += (int)(*output_size);
+ enc->sse_[3] = sse;
}
-
- // Try the other mode(s).
- {
- WebPAuxStats best_stats;
- size_t best_score = VP8BitWriterSize(&bw);
-
- memset(&best_stats, 0, sizeof(best_stats)); // prevent spurious warning
- if (pic->stats != NULL) best_stats = *pic->stats;
- for (test_filter = WEBP_FILTER_HORIZONTAL;
- ok && (test_filter <= WEBP_FILTER_GRADIENT);
- ++test_filter) {
- VP8BitWriter tmp_bw;
- if (filter != WEBP_FILTER_BEST && test_filter != filter) {
- continue;
- }
- ok = EncodeAlphaInternal(quant_alpha, width, height,
- method, test_filter, reduce_levels,
- effort_level, filtered_alpha, &tmp_bw,
- pic->stats);
- if (ok) {
- const size_t score = VP8BitWriterSize(&tmp_bw);
- if (score < best_score) {
- // swap bitwriter objects.
- VP8BitWriter tmp = tmp_bw;
- tmp_bw = bw;
- bw = tmp;
- best_score = score;
- if (pic->stats != NULL) best_stats = *pic->stats;
- }
- } else {
- VP8BitWriterWipeOut(&bw);
- }
- VP8BitWriterWipeOut(&tmp_bw);
- }
- if (pic->stats != NULL) *pic->stats = best_stats;
- }
- Ok:
- if (ok) {
- *output_size = VP8BitWriterSize(&bw);
- *output = VP8BitWriterBuf(&bw);
- if (pic->stats != NULL) { // need stats?
- pic->stats->coded_size += (int)(*output_size);
- enc->sse_[3] = sse;
- }
- }
- free(filtered_alpha);
}
- End:
- free(quant_alpha);
+
+ WebPSafeFree(quant_alpha);
return ok;
}
-
//------------------------------------------------------------------------------
// Main calls
+static int CompressAlphaJob(VP8Encoder* const enc, void* dummy) {
+ const WebPConfig* config = enc->config_;
+ uint8_t* alpha_data = NULL;
+ size_t alpha_size = 0;
+ const int effort_level = config->method; // maps to [0..6]
+ const WEBP_FILTER_TYPE filter =
+ (config->alpha_filtering == 0) ? WEBP_FILTER_NONE :
+ (config->alpha_filtering == 1) ? WEBP_FILTER_FAST :
+ WEBP_FILTER_BEST;
+ if (!EncodeAlpha(enc, config->alpha_quality, config->alpha_compression,
+ filter, effort_level, &alpha_data, &alpha_size)) {
+ return 0;
+ }
+ if (alpha_size != (uint32_t)alpha_size) { // Sanity check.
+ WebPSafeFree(alpha_data);
+ return 0;
+ }
+ enc->alpha_data_size_ = (uint32_t)alpha_size;
+ enc->alpha_data_ = alpha_data;
+ (void)dummy;
+ return 1;
+}
+
void VP8EncInitAlpha(VP8Encoder* const enc) {
+ WebPInitAlphaProcessing();
enc->has_alpha_ = WebPPictureHasTransparency(enc->pic_);
enc->alpha_data_ = NULL;
enc->alpha_data_size_ = 0;
+ if (enc->thread_level_ > 0) {
+ WebPWorker* const worker = &enc->alpha_worker_;
+ WebPGetWorkerInterface()->Init(worker);
+ worker->data1 = enc;
+ worker->data2 = NULL;
+ worker->hook = (WebPWorkerHook)CompressAlphaJob;
+ }
}
-int VP8EncFinishAlpha(VP8Encoder* const enc) {
+int VP8EncStartAlpha(VP8Encoder* const enc) {
if (enc->has_alpha_) {
- const WebPConfig* config = enc->config_;
- uint8_t* tmp_data = NULL;
- size_t tmp_size = 0;
- const int effort_level = config->method; // maps to [0..6]
- const WEBP_FILTER_TYPE filter =
- (config->alpha_filtering == 0) ? WEBP_FILTER_NONE :
- (config->alpha_filtering == 1) ? WEBP_FILTER_FAST :
- WEBP_FILTER_BEST;
-
- if (!EncodeAlpha(enc, config->alpha_quality, config->alpha_compression,
- filter, effort_level, &tmp_data, &tmp_size)) {
- return 0;
+ if (enc->thread_level_ > 0) {
+ WebPWorker* const worker = &enc->alpha_worker_;
+ // Makes sure worker is good to go.
+ if (!WebPGetWorkerInterface()->Reset(worker)) {
+ return 0;
+ }
+ WebPGetWorkerInterface()->Launch(worker);
+ return 1;
+ } else {
+ return CompressAlphaJob(enc, NULL); // just do the job right away
}
- if (tmp_size != (uint32_t)tmp_size) { // Sanity check.
- free(tmp_data);
- return 0;
+ }
+ return 1;
+}
+
+int VP8EncFinishAlpha(VP8Encoder* const enc) {
+ if (enc->has_alpha_) {
+ if (enc->thread_level_ > 0) {
+ WebPWorker* const worker = &enc->alpha_worker_;
+ if (!WebPGetWorkerInterface()->Sync(worker)) return 0; // error
}
- enc->alpha_data_size_ = (uint32_t)tmp_size;
- enc->alpha_data_ = tmp_data;
}
return WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_);
}
-void VP8EncDeleteAlpha(VP8Encoder* const enc) {
- free(enc->alpha_data_);
+int VP8EncDeleteAlpha(VP8Encoder* const enc) {
+ int ok = 1;
+ if (enc->thread_level_ > 0) {
+ WebPWorker* const worker = &enc->alpha_worker_;
+ // finish anything left in flight
+ ok = WebPGetWorkerInterface()->Sync(worker);
+ // still need to end the worker, even if !ok
+ WebPGetWorkerInterface()->End(worker);
+ }
+ WebPSafeFree(enc->alpha_data_);
enc->alpha_data_ = NULL;
enc->alpha_data_size_ = 0;
enc->has_alpha_ = 0;
+ return ok;
}
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/enc/analysis.c b/drivers/webp/enc/analysis.c
index 22cfb492e7..b55128fd48 100644
--- a/drivers/webp/enc/analysis.c
+++ b/drivers/webp/enc/analysis.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Macroblock analysis
@@ -17,16 +19,8 @@
#include "./cost.h"
#include "../utils/utils.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
#define MAX_ITERS_K_MEANS 6
-static int ClipAlpha(int alpha) {
- return alpha < 0 ? 0 : alpha > 255 ? 255 : alpha;
-}
-
//------------------------------------------------------------------------------
// Smooth the segment map by replacing isolated block by the majority of its
// neighbours.
@@ -36,7 +30,7 @@ static void SmoothSegmentMap(VP8Encoder* const enc) {
const int w = enc->mb_w_;
const int h = enc->mb_h_;
const int majority_cnt_3_x_3_grid = 5;
- uint8_t* const tmp = (uint8_t*)WebPSafeMalloc((uint64_t)w * h, sizeof(*tmp));
+ uint8_t* const tmp = (uint8_t*)WebPSafeMalloc(w * h, sizeof(*tmp));
assert((uint64_t)(w * h) == (uint64_t)w * h); // no overflow, as per spec
if (tmp == NULL) return;
@@ -57,6 +51,7 @@ static void SmoothSegmentMap(VP8Encoder* const enc) {
for (n = 0; n < NUM_MB_SEGMENTS; ++n) {
if (cnt[n] >= majority_cnt_3_x_3_grid) {
majority_seg = n;
+ break;
}
}
tmp[x + y * w] = majority_seg;
@@ -68,54 +63,14 @@ static void SmoothSegmentMap(VP8Encoder* const enc) {
mb->segment_ = tmp[x + y * w];
}
}
- free(tmp);
+ WebPSafeFree(tmp);
}
//------------------------------------------------------------------------------
-// Finalize Segment probability based on the coding tree
-
-static int GetProba(int a, int b) {
- int proba;
- const int total = a + b;
- if (total == 0) return 255; // that's the default probability.
- proba = (255 * a + total / 2) / total;
- return proba;
-}
-
-static void SetSegmentProbas(VP8Encoder* const enc) {
- int p[NUM_MB_SEGMENTS] = { 0 };
- int n;
-
- for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) {
- const VP8MBInfo* const mb = &enc->mb_info_[n];
- p[mb->segment_]++;
- }
- if (enc->pic_->stats) {
- for (n = 0; n < NUM_MB_SEGMENTS; ++n) {
- enc->pic_->stats->segment_size[n] = p[n];
- }
- }
- if (enc->segment_hdr_.num_segments_ > 1) {
- uint8_t* const probas = enc->proba_.segments_;
- probas[0] = GetProba(p[0] + p[1], p[2] + p[3]);
- probas[1] = GetProba(p[0], p[1]);
- probas[2] = GetProba(p[2], p[3]);
-
- enc->segment_hdr_.update_map_ =
- (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255);
- enc->segment_hdr_.size_ =
- p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) +
- p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) +
- p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) +
- p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2]));
- } else {
- enc->segment_hdr_.update_map_ = 0;
- enc->segment_hdr_.size_ = 0;
- }
-}
+// set segment susceptibility alpha_ / beta_
static WEBP_INLINE int clip(int v, int m, int M) {
- return v < m ? m : v > M ? M : v;
+ return (v < m) ? m : (v > M) ? M : v;
}
static void SetSegmentAlphas(VP8Encoder* const enc,
@@ -142,28 +97,77 @@ static void SetSegmentAlphas(VP8Encoder* const enc,
}
//------------------------------------------------------------------------------
+// Compute susceptibility based on DCT-coeff histograms:
+// the higher, the "easier" the macroblock is to compress.
+
+#define MAX_ALPHA 255 // 8b of precision for susceptibilities.
+#define ALPHA_SCALE (2 * MAX_ALPHA) // scaling factor for alpha.
+#define DEFAULT_ALPHA (-1)
+#define IS_BETTER_ALPHA(alpha, best_alpha) ((alpha) > (best_alpha))
+
+static int FinalAlphaValue(int alpha) {
+ alpha = MAX_ALPHA - alpha;
+ return clip(alpha, 0, MAX_ALPHA);
+}
+
+static int GetAlpha(const VP8Histogram* const histo) {
+ // 'alpha' will later be clipped to [0..MAX_ALPHA] range, clamping outer
+ // values which happen to be mostly noise. This leaves the maximum precision
+ // for handling the useful small values which contribute most.
+ const int max_value = histo->max_value;
+ const int last_non_zero = histo->last_non_zero;
+ const int alpha =
+ (max_value > 1) ? ALPHA_SCALE * last_non_zero / max_value : 0;
+ return alpha;
+}
+
+static void InitHistogram(VP8Histogram* const histo) {
+ histo->max_value = 0;
+ histo->last_non_zero = 1;
+}
+
+static void MergeHistograms(const VP8Histogram* const in,
+ VP8Histogram* const out) {
+ if (in->max_value > out->max_value) {
+ out->max_value = in->max_value;
+ }
+ if (in->last_non_zero > out->last_non_zero) {
+ out->last_non_zero = in->last_non_zero;
+ }
+}
+
+//------------------------------------------------------------------------------
// Simplified k-Means, to assign Nb segments based on alpha-histogram
-static void AssignSegments(VP8Encoder* const enc, const int alphas[256]) {
- const int nb = enc->segment_hdr_.num_segments_;
+static void AssignSegments(VP8Encoder* const enc,
+ const int alphas[MAX_ALPHA + 1]) {
+ // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an
+ // explicit check is needed to avoid spurious warning about 'n + 1' exceeding
+ // array bounds of 'centers' with some compilers (noticed with gcc-4.9).
+ const int nb = (enc->segment_hdr_.num_segments_ < NUM_MB_SEGMENTS) ?
+ enc->segment_hdr_.num_segments_ : NUM_MB_SEGMENTS;
int centers[NUM_MB_SEGMENTS];
int weighted_average = 0;
- int map[256];
+ int map[MAX_ALPHA + 1];
int a, n, k;
- int min_a = 0, max_a = 255, range_a;
+ int min_a = 0, max_a = MAX_ALPHA, range_a;
// 'int' type is ok for histo, and won't overflow
int accum[NUM_MB_SEGMENTS], dist_accum[NUM_MB_SEGMENTS];
+ assert(nb >= 1);
+ assert(nb <= NUM_MB_SEGMENTS);
+
// bracket the input
- for (n = 0; n < 256 && alphas[n] == 0; ++n) {}
+ for (n = 0; n <= MAX_ALPHA && alphas[n] == 0; ++n) {}
min_a = n;
- for (n = 255; n > min_a && alphas[n] == 0; --n) {}
+ for (n = MAX_ALPHA; n > min_a && alphas[n] == 0; --n) {}
max_a = n;
range_a = max_a - min_a;
// Spread initial centers evenly
- for (n = 1, k = 0; n < 2 * nb; n += 2) {
- centers[k++] = min_a + (n * range_a) / (2 * nb);
+ for (k = 0, n = 1; k < nb; ++k, n += 2) {
+ assert(n < 2 * nb);
+ centers[k] = min_a + (n * range_a) / (2 * nb);
}
for (k = 0; k < MAX_ITERS_K_MEANS; ++k) { // few iters are enough
@@ -178,7 +182,7 @@ static void AssignSegments(VP8Encoder* const enc, const int alphas[256]) {
n = 0; // track the nearest center for current 'a'
for (a = min_a; a <= max_a; ++a) {
if (alphas[a]) {
- while (n < nb - 1 && abs(a - centers[n + 1]) < abs(a - centers[n])) {
+ while (n + 1 < nb && abs(a - centers[n + 1]) < abs(a - centers[n])) {
n++;
}
map[a] = n;
@@ -210,7 +214,7 @@ static void AssignSegments(VP8Encoder* const enc, const int alphas[256]) {
VP8MBInfo* const mb = &enc->mb_info_[n];
const int alpha = mb->alpha_;
mb->segment_ = map[alpha];
- mb->alpha_ = centers[map[alpha]]; // just for the record.
+ mb->alpha_ = centers[map[alpha]]; // for the record.
}
if (nb > 1) {
@@ -218,7 +222,6 @@ static void AssignSegments(VP8Encoder* const enc, const int alphas[256]) {
if (smooth) SmoothSegmentMap(enc);
}
- SetSegmentProbas(enc); // Assign final proba
SetSegmentAlphas(enc, centers, weighted_average); // pick some alphas.
}
@@ -227,24 +230,30 @@ static void AssignSegments(VP8Encoder* const enc, const int alphas[256]) {
// susceptibility and set best modes for this macroblock.
// Segment assignment is done later.
-// Number of modes to inspect for alpha_ evaluation. For high-quality settings,
-// we don't need to test all the possible modes during the analysis phase.
+// Number of modes to inspect for alpha_ evaluation. We don't need to test all
+// the possible modes during the analysis phase: we risk falling into a local
+// optimum, or be subject to boundary effect
#define MAX_INTRA16_MODE 2
#define MAX_INTRA4_MODE 2
#define MAX_UV_MODE 2
static int MBAnalyzeBestIntra16Mode(VP8EncIterator* const it) {
- const int max_mode = (it->enc_->method_ >= 3) ? MAX_INTRA16_MODE : 4;
+ const int max_mode = MAX_INTRA16_MODE;
int mode;
- int best_alpha = -1;
+ int best_alpha = DEFAULT_ALPHA;
int best_mode = 0;
VP8MakeLuma16Preds(it);
for (mode = 0; mode < max_mode; ++mode) {
- const int alpha = VP8CollectHistogram(it->yuv_in_ + Y_OFF,
- it->yuv_p_ + VP8I16ModeOffsets[mode],
- 0, 16);
- if (alpha > best_alpha) {
+ VP8Histogram histo;
+ int alpha;
+
+ InitHistogram(&histo);
+ VP8CollectHistogram(it->yuv_in_ + Y_OFF_ENC,
+ it->yuv_p_ + VP8I16ModeOffsets[mode],
+ 0, 16, &histo);
+ alpha = GetAlpha(&histo);
+ if (IS_BETTER_ALPHA(alpha, best_alpha)) {
best_alpha = alpha;
best_mode = mode;
}
@@ -256,46 +265,62 @@ static int MBAnalyzeBestIntra16Mode(VP8EncIterator* const it) {
static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it,
int best_alpha) {
uint8_t modes[16];
- const int max_mode = (it->enc_->method_ >= 3) ? MAX_INTRA4_MODE : NUM_BMODES;
- int i4_alpha = 0;
+ const int max_mode = MAX_INTRA4_MODE;
+ int i4_alpha;
+ VP8Histogram total_histo;
+ int cur_histo = 0;
+ InitHistogram(&total_histo);
+
VP8IteratorStartI4(it);
do {
int mode;
- int best_mode_alpha = -1;
- const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_];
+ int best_mode_alpha = DEFAULT_ALPHA;
+ VP8Histogram histos[2];
+ const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_];
VP8MakeIntra4Preds(it);
for (mode = 0; mode < max_mode; ++mode) {
- const int alpha = VP8CollectHistogram(src,
- it->yuv_p_ + VP8I4ModeOffsets[mode],
- 0, 1);
- if (alpha > best_mode_alpha) {
+ int alpha;
+
+ InitHistogram(&histos[cur_histo]);
+ VP8CollectHistogram(src, it->yuv_p_ + VP8I4ModeOffsets[mode],
+ 0, 1, &histos[cur_histo]);
+ alpha = GetAlpha(&histos[cur_histo]);
+ if (IS_BETTER_ALPHA(alpha, best_mode_alpha)) {
best_mode_alpha = alpha;
modes[it->i4_] = mode;
+ cur_histo ^= 1; // keep track of best histo so far.
}
}
- i4_alpha += best_mode_alpha;
+ // accumulate best histogram
+ MergeHistograms(&histos[cur_histo ^ 1], &total_histo);
// Note: we reuse the original samples for predictors
- } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF));
+ } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF_ENC));
- if (i4_alpha > best_alpha) {
+ i4_alpha = GetAlpha(&total_histo);
+ if (IS_BETTER_ALPHA(i4_alpha, best_alpha)) {
VP8SetIntra4Mode(it, modes);
- best_alpha = ClipAlpha(i4_alpha);
+ best_alpha = i4_alpha;
}
return best_alpha;
}
static int MBAnalyzeBestUVMode(VP8EncIterator* const it) {
- int best_alpha = -1;
+ int best_alpha = DEFAULT_ALPHA;
int best_mode = 0;
- const int max_mode = (it->enc_->method_ >= 3) ? MAX_UV_MODE : 4;
+ const int max_mode = MAX_UV_MODE;
int mode;
+
VP8MakeChroma8Preds(it);
for (mode = 0; mode < max_mode; ++mode) {
- const int alpha = VP8CollectHistogram(it->yuv_in_ + U_OFF,
- it->yuv_p_ + VP8UVModeOffsets[mode],
- 16, 16 + 4 + 4);
- if (alpha > best_alpha) {
+ VP8Histogram histo;
+ int alpha;
+ InitHistogram(&histo);
+ VP8CollectHistogram(it->yuv_in_ + U_OFF_ENC,
+ it->yuv_p_ + VP8UVModeOffsets[mode],
+ 16, 16 + 4 + 4, &histo);
+ alpha = GetAlpha(&histo);
+ if (IS_BETTER_ALPHA(alpha, best_alpha)) {
best_alpha = alpha;
best_mode = mode;
}
@@ -305,7 +330,8 @@ static int MBAnalyzeBestUVMode(VP8EncIterator* const it) {
}
static void MBAnalyze(VP8EncIterator* const it,
- int alphas[256], int* const uv_alpha) {
+ int alphas[MAX_ALPHA + 1],
+ int* const alpha, int* const uv_alpha) {
const VP8Encoder* const enc = it->enc_;
int best_alpha, best_uv_alpha;
@@ -314,7 +340,7 @@ static void MBAnalyze(VP8EncIterator* const it,
VP8SetSegment(it, 0); // default segment, spec-wise.
best_alpha = MBAnalyzeBestIntra16Mode(it);
- if (enc->method_ != 3) {
+ if (enc->method_ >= 5) {
// We go and make a fast decision for intra4/intra16.
// It's usually not a good and definitive pick, but helps seeding the stats
// about level bit-cost.
@@ -324,10 +350,22 @@ static void MBAnalyze(VP8EncIterator* const it,
best_uv_alpha = MBAnalyzeBestUVMode(it);
// Final susceptibility mix
- best_alpha = (best_alpha + best_uv_alpha + 1) / 2;
+ best_alpha = (3 * best_alpha + best_uv_alpha + 2) >> 2;
+ best_alpha = FinalAlphaValue(best_alpha);
alphas[best_alpha]++;
+ it->mb_->alpha_ = best_alpha; // for later remapping.
+
+ // Accumulate for later complexity analysis.
+ *alpha += best_alpha; // mixed susceptibility (not just luma)
*uv_alpha += best_uv_alpha;
- it->mb_->alpha_ = best_alpha; // Informative only.
+}
+
+static void DefaultMBInfo(VP8MBInfo* const mb) {
+ mb->type_ = 1; // I16x16
+ mb->uv_mode_ = 0;
+ mb->skip_ = 0; // not skipped
+ mb->segment_ = 0; // default segment
+ mb->alpha_ = 0;
}
//------------------------------------------------------------------------------
@@ -340,25 +378,124 @@ static void MBAnalyze(VP8EncIterator* const it,
// and decide intra4/intra16, but that's usually almost always a bad choice at
// this stage.
-int VP8EncAnalyze(VP8Encoder* const enc) {
- int ok = 1;
- int alphas[256] = { 0 };
- VP8EncIterator it;
-
- VP8IteratorInit(enc, &it);
+static void ResetAllMBInfo(VP8Encoder* const enc) {
+ int n;
+ for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) {
+ DefaultMBInfo(&enc->mb_info_[n]);
+ }
+ // Default susceptibilities.
+ enc->dqm_[0].alpha_ = 0;
+ enc->dqm_[0].beta_ = 0;
+ // Note: we can't compute this alpha_ / uv_alpha_ -> set to default value.
+ enc->alpha_ = 0;
enc->uv_alpha_ = 0;
- do {
- VP8IteratorImport(&it);
- MBAnalyze(&it, alphas, &enc->uv_alpha_);
- ok = VP8IteratorProgress(&it, 20);
- // Let's pretend we have perfect lossless reconstruction.
- } while (ok && VP8IteratorNext(&it, it.yuv_in_));
- enc->uv_alpha_ /= enc->mb_w_ * enc->mb_h_;
- if (ok) AssignSegments(enc, alphas);
+ WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_);
+}
+
+// struct used to collect job result
+typedef struct {
+ WebPWorker worker;
+ int alphas[MAX_ALPHA + 1];
+ int alpha, uv_alpha;
+ VP8EncIterator it;
+ int delta_progress;
+} SegmentJob;
+// main work call
+static int DoSegmentsJob(SegmentJob* const job, VP8EncIterator* const it) {
+ int ok = 1;
+ if (!VP8IteratorIsDone(it)) {
+ uint8_t tmp[32 + WEBP_ALIGN_CST];
+ uint8_t* const scratch = (uint8_t*)WEBP_ALIGN(tmp);
+ do {
+ // Let's pretend we have perfect lossless reconstruction.
+ VP8IteratorImport(it, scratch);
+ MBAnalyze(it, job->alphas, &job->alpha, &job->uv_alpha);
+ ok = VP8IteratorProgress(it, job->delta_progress);
+ } while (ok && VP8IteratorNext(it));
+ }
return ok;
}
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
+static void MergeJobs(const SegmentJob* const src, SegmentJob* const dst) {
+ int i;
+ for (i = 0; i <= MAX_ALPHA; ++i) dst->alphas[i] += src->alphas[i];
+ dst->alpha += src->alpha;
+ dst->uv_alpha += src->uv_alpha;
+}
+
+// initialize the job struct with some TODOs
+static void InitSegmentJob(VP8Encoder* const enc, SegmentJob* const job,
+ int start_row, int end_row) {
+ WebPGetWorkerInterface()->Init(&job->worker);
+ job->worker.data1 = job;
+ job->worker.data2 = &job->it;
+ job->worker.hook = (WebPWorkerHook)DoSegmentsJob;
+ VP8IteratorInit(enc, &job->it);
+ VP8IteratorSetRow(&job->it, start_row);
+ VP8IteratorSetCountDown(&job->it, (end_row - start_row) * enc->mb_w_);
+ memset(job->alphas, 0, sizeof(job->alphas));
+ job->alpha = 0;
+ job->uv_alpha = 0;
+ // only one of both jobs can record the progress, since we don't
+ // expect the user's hook to be multi-thread safe
+ job->delta_progress = (start_row == 0) ? 20 : 0;
+}
+
+// main entry point
+int VP8EncAnalyze(VP8Encoder* const enc) {
+ int ok = 1;
+ const int do_segments =
+ enc->config_->emulate_jpeg_size || // We need the complexity evaluation.
+ (enc->segment_hdr_.num_segments_ > 1) ||
+ (enc->method_ == 0); // for method 0, we need preds_[] to be filled.
+ if (do_segments) {
+ const int last_row = enc->mb_h_;
+ // We give a little more than a half work to the main thread.
+ const int split_row = (9 * last_row + 15) >> 4;
+ const int total_mb = last_row * enc->mb_w_;
+#ifdef WEBP_USE_THREAD
+ const int kMinSplitRow = 2; // minimal rows needed for mt to be worth it
+ const int do_mt = (enc->thread_level_ > 0) && (split_row >= kMinSplitRow);
+#else
+ const int do_mt = 0;
#endif
+ const WebPWorkerInterface* const worker_interface =
+ WebPGetWorkerInterface();
+ SegmentJob main_job;
+ if (do_mt) {
+ SegmentJob side_job;
+ // Note the use of '&' instead of '&&' because we must call the functions
+ // no matter what.
+ InitSegmentJob(enc, &main_job, 0, split_row);
+ InitSegmentJob(enc, &side_job, split_row, last_row);
+ // we don't need to call Reset() on main_job.worker, since we're calling
+ // WebPWorkerExecute() on it
+ ok &= worker_interface->Reset(&side_job.worker);
+ // launch the two jobs in parallel
+ if (ok) {
+ worker_interface->Launch(&side_job.worker);
+ worker_interface->Execute(&main_job.worker);
+ ok &= worker_interface->Sync(&side_job.worker);
+ ok &= worker_interface->Sync(&main_job.worker);
+ }
+ worker_interface->End(&side_job.worker);
+ if (ok) MergeJobs(&side_job, &main_job); // merge results together
+ } else {
+ // Even for single-thread case, we use the generic Worker tools.
+ InitSegmentJob(enc, &main_job, 0, last_row);
+ worker_interface->Execute(&main_job.worker);
+ ok &= worker_interface->Sync(&main_job.worker);
+ }
+ worker_interface->End(&main_job.worker);
+ if (ok) {
+ enc->alpha_ = main_job.alpha / total_mb;
+ enc->uv_alpha_ = main_job.uv_alpha / total_mb;
+ AssignSegments(enc, main_job.alphas);
+ }
+ } else { // Use only one default segment.
+ ResetAllMBInfo(enc);
+ }
+ return ok;
+}
+
diff --git a/drivers/webp/enc/backward_references.c b/drivers/webp/enc/backward_references.c
index b8c8ece806..049125e521 100644
--- a/drivers/webp/enc/backward_references.c
+++ b/drivers/webp/enc/backward_references.c
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Author: Jyrki Alakuijala (jyrki@google.com)
@@ -10,7 +12,6 @@
#include <assert.h>
#include <math.h>
-#include <stdio.h>
#include "./backward_references.h"
#include "./histogram.h"
@@ -20,9 +21,9 @@
#define VALUES_IN_BYTE 256
-#define HASH_BITS 18
-#define HASH_SIZE (1 << HASH_BITS)
-#define HASH_MULTIPLIER (0xc6a4a7935bd1e995ULL)
+#define MIN_BLOCK_SIZE 256 // minimum block size for backward references
+
+#define MAX_ENTROPY (1e30f)
// 1M window (4M bytes) minus 120 special codes for short distances.
#define WINDOW_SIZE ((1 << 20) - 120)
@@ -31,14 +32,6 @@
#define MIN_LENGTH 2
#define MAX_LENGTH 4096
-typedef struct {
- // Stores the most recently added position with the given hash value.
- int32_t hash_to_first_index_[HASH_SIZE];
- // chain_[pos] stores the previous position with the same hash value
- // for every pixel in the image.
- int32_t* chain_;
-} HashChain;
-
// -----------------------------------------------------------------------------
static const uint8_t plane_to_code_lut[128] = {
@@ -65,145 +58,275 @@ static int DistanceToPlaneCode(int xsize, int dist) {
static WEBP_INLINE int FindMatchLength(const uint32_t* const array1,
const uint32_t* const array2,
- const int max_limit) {
+ int best_len_match,
+ int max_limit) {
+#if !defined(__x86_64__)
+ // TODO(vrabaud): Compare on other architectures.
int match_len = 0;
+ // Before 'expensive' linear match, check if the two arrays match at the
+ // current best length index.
+ if (array1[best_len_match] != array2[best_len_match]) return 0;
while (match_len < max_limit && array1[match_len] == array2[match_len]) {
++match_len;
}
return match_len;
+#else
+ const uint32_t* array1_32 = array1;
+ const uint32_t* array2_32 = array2;
+ // max value is aligned to (uint64_t*) array1
+ const uint32_t* const array1_32_max = array1 + (max_limit & ~1);
+
+ // Before 'expensive' linear match, check if the two arrays match at the
+ // current best length index.
+ if (array1[best_len_match] != array2[best_len_match]) return 0;
+
+ // TODO(vrabaud): add __predict_true on bound checking?
+ while (array1_32 < array1_32_max) {
+ if (*(uint64_t*)array1_32 == *(uint64_t*)array2_32) {
+ array1_32 += 2;
+ array2_32 += 2;
+ } else {
+ // if the uint32_t pointed to are the same, then the following ones have
+ // to be different
+ return (array1_32 - array1) + (*array1_32 == *array2_32);
+ }
+ }
+
+ // Deal with the potential last uint32_t.
+ if ((max_limit & 1) && (*array1_32 != *array2_32)) return max_limit - 1;
+ return max_limit;
+#endif
}
// -----------------------------------------------------------------------------
// VP8LBackwardRefs
-void VP8LInitBackwardRefs(VP8LBackwardRefs* const refs) {
- if (refs != NULL) {
- refs->refs = NULL;
- refs->size = 0;
- refs->max_size = 0;
+struct PixOrCopyBlock {
+ PixOrCopyBlock* next_; // next block (or NULL)
+ PixOrCopy* start_; // data start
+ int size_; // currently used size
+};
+
+static void ClearBackwardRefs(VP8LBackwardRefs* const refs) {
+ assert(refs != NULL);
+ if (refs->tail_ != NULL) {
+ *refs->tail_ = refs->free_blocks_; // recycle all blocks at once
}
+ refs->free_blocks_ = refs->refs_;
+ refs->tail_ = &refs->refs_;
+ refs->last_block_ = NULL;
+ refs->refs_ = NULL;
}
-void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs) {
- if (refs != NULL) {
- free(refs->refs);
- VP8LInitBackwardRefs(refs);
+void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs) {
+ assert(refs != NULL);
+ ClearBackwardRefs(refs);
+ while (refs->free_blocks_ != NULL) {
+ PixOrCopyBlock* const next = refs->free_blocks_->next_;
+ WebPSafeFree(refs->free_blocks_);
+ refs->free_blocks_ = next;
}
}
-int VP8LBackwardRefsAlloc(VP8LBackwardRefs* const refs, int max_size) {
+void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size) {
assert(refs != NULL);
- refs->size = 0;
- refs->max_size = 0;
- refs->refs = (PixOrCopy*)WebPSafeMalloc((uint64_t)max_size,
- sizeof(*refs->refs));
- if (refs->refs == NULL) return 0;
- refs->max_size = max_size;
+ memset(refs, 0, sizeof(*refs));
+ refs->tail_ = &refs->refs_;
+ refs->block_size_ =
+ (block_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : block_size;
+}
+
+VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs) {
+ VP8LRefsCursor c;
+ c.cur_block_ = refs->refs_;
+ if (refs->refs_ != NULL) {
+ c.cur_pos = c.cur_block_->start_;
+ c.last_pos_ = c.cur_pos + c.cur_block_->size_;
+ } else {
+ c.cur_pos = NULL;
+ c.last_pos_ = NULL;
+ }
+ return c;
+}
+
+void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c) {
+ PixOrCopyBlock* const b = c->cur_block_->next_;
+ c->cur_pos = (b == NULL) ? NULL : b->start_;
+ c->last_pos_ = (b == NULL) ? NULL : b->start_ + b->size_;
+ c->cur_block_ = b;
+}
+
+// Create a new block, either from the free list or allocated
+static PixOrCopyBlock* BackwardRefsNewBlock(VP8LBackwardRefs* const refs) {
+ PixOrCopyBlock* b = refs->free_blocks_;
+ if (b == NULL) { // allocate new memory chunk
+ const size_t total_size =
+ sizeof(*b) + refs->block_size_ * sizeof(*b->start_);
+ b = (PixOrCopyBlock*)WebPSafeMalloc(1ULL, total_size);
+ if (b == NULL) {
+ refs->error_ |= 1;
+ return NULL;
+ }
+ b->start_ = (PixOrCopy*)((uint8_t*)b + sizeof(*b)); // not always aligned
+ } else { // recycle from free-list
+ refs->free_blocks_ = b->next_;
+ }
+ *refs->tail_ = b;
+ refs->tail_ = &b->next_;
+ refs->last_block_ = b;
+ b->next_ = NULL;
+ b->size_ = 0;
+ return b;
+}
+
+static WEBP_INLINE void BackwardRefsCursorAdd(VP8LBackwardRefs* const refs,
+ const PixOrCopy v) {
+ PixOrCopyBlock* b = refs->last_block_;
+ if (b == NULL || b->size_ == refs->block_size_) {
+ b = BackwardRefsNewBlock(refs);
+ if (b == NULL) return; // refs->error_ is set
+ }
+ b->start_[b->size_++] = v;
+}
+
+int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src,
+ VP8LBackwardRefs* const dst) {
+ const PixOrCopyBlock* b = src->refs_;
+ ClearBackwardRefs(dst);
+ assert(src->block_size_ == dst->block_size_);
+ while (b != NULL) {
+ PixOrCopyBlock* const new_b = BackwardRefsNewBlock(dst);
+ if (new_b == NULL) return 0; // dst->error_ is set
+ memcpy(new_b->start_, b->start_, b->size_ * sizeof(*b->start_));
+ new_b->size_ = b->size_;
+ b = b->next_;
+ }
return 1;
}
// -----------------------------------------------------------------------------
// Hash chains
-static WEBP_INLINE uint64_t GetPixPairHash64(const uint32_t* const argb) {
- uint64_t key = ((uint64_t)(argb[1]) << 32) | argb[0];
- key = (key * HASH_MULTIPLIER) >> (64 - HASH_BITS);
- return key;
-}
-
-static int HashChainInit(HashChain* const p, int size) {
+// initialize as empty
+static void HashChainReset(VP8LHashChain* const p) {
int i;
- p->chain_ = (int*)WebPSafeMalloc((uint64_t)size, sizeof(*p->chain_));
- if (p->chain_ == NULL) {
- return 0;
- }
- for (i = 0; i < size; ++i) {
+ assert(p != NULL);
+ for (i = 0; i < p->size_; ++i) {
p->chain_[i] = -1;
}
for (i = 0; i < HASH_SIZE; ++i) {
p->hash_to_first_index_[i] = -1;
}
+}
+
+int VP8LHashChainInit(VP8LHashChain* const p, int size) {
+ assert(p->size_ == 0);
+ assert(p->chain_ == NULL);
+ assert(size > 0);
+ p->chain_ = (int*)WebPSafeMalloc(size, sizeof(*p->chain_));
+ if (p->chain_ == NULL) return 0;
+ p->size_ = size;
+ HashChainReset(p);
return 1;
}
-static void HashChainDelete(HashChain* const p) {
- if (p != NULL) {
- free(p->chain_);
- free(p);
- }
+void VP8LHashChainClear(VP8LHashChain* const p) {
+ assert(p != NULL);
+ WebPSafeFree(p->chain_);
+ p->size_ = 0;
+ p->chain_ = NULL;
+}
+
+// -----------------------------------------------------------------------------
+
+#define HASH_MULTIPLIER_HI (0xc6a4a793U)
+#define HASH_MULTIPLIER_LO (0x5bd1e996U)
+
+static WEBP_INLINE uint32_t GetPixPairHash64(const uint32_t* const argb) {
+ uint32_t key;
+ key = argb[1] * HASH_MULTIPLIER_HI;
+ key += argb[0] * HASH_MULTIPLIER_LO;
+ key = key >> (32 - HASH_BITS);
+ return key;
}
// Insertion of two pixels at a time.
-static void HashChainInsert(HashChain* const p,
+static void HashChainInsert(VP8LHashChain* const p,
const uint32_t* const argb, int pos) {
- const uint64_t hash_code = GetPixPairHash64(argb);
+ const uint32_t hash_code = GetPixPairHash64(argb);
p->chain_[pos] = p->hash_to_first_index_[hash_code];
p->hash_to_first_index_[hash_code] = pos;
}
-static int HashChainFindCopy(const HashChain* const p,
- int quality, int index, int xsize,
- const uint32_t* const argb, int maxlen,
+// Returns the maximum number of hash chain lookups to do for a
+// given compression quality. Return value in range [6, 86].
+static int GetMaxItersForQuality(int quality, int low_effort) {
+ return (low_effort ? 6 : 8) + (quality * quality) / 128;
+}
+
+static int GetWindowSizeForHashChain(int quality, int xsize) {
+ const int max_window_size = (quality > 75) ? WINDOW_SIZE
+ : (quality > 50) ? (xsize << 8)
+ : (quality > 25) ? (xsize << 6)
+ : (xsize << 4);
+ assert(xsize > 0);
+ return (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE : max_window_size;
+}
+
+static WEBP_INLINE int MaxFindCopyLength(int len) {
+ return (len < MAX_LENGTH) ? len : MAX_LENGTH;
+}
+
+static void HashChainFindOffset(const VP8LHashChain* const p, int base_position,
+ const uint32_t* const argb, int len,
+ int window_size, int* const distance_ptr) {
+ const uint32_t* const argb_start = argb + base_position;
+ const int min_pos =
+ (base_position > window_size) ? base_position - window_size : 0;
+ int pos;
+ assert(len <= MAX_LENGTH);
+ for (pos = p->hash_to_first_index_[GetPixPairHash64(argb_start)];
+ pos >= min_pos;
+ pos = p->chain_[pos]) {
+ const int curr_length =
+ FindMatchLength(argb + pos, argb_start, len - 1, len);
+ if (curr_length == len) break;
+ }
+ *distance_ptr = base_position - pos;
+}
+
+static int HashChainFindCopy(const VP8LHashChain* const p,
+ int base_position,
+ const uint32_t* const argb, int max_len,
+ int window_size, int iter_max,
int* const distance_ptr,
int* const length_ptr) {
- const uint64_t hash_code = GetPixPairHash64(&argb[index]);
- int prev_length = 0;
- int64_t best_val = 0;
+ const uint32_t* const argb_start = argb + base_position;
+ int iter = iter_max;
int best_length = 0;
int best_distance = 0;
- const uint32_t* const argb_start = argb + index;
- const int iter_min_mult = (quality < 50) ? 2 : (quality < 75) ? 4 : 8;
- const int iter_min = -quality * iter_min_mult;
- int iter_cnt = 10 + (quality >> 1);
- const int min_pos = (index > WINDOW_SIZE) ? index - WINDOW_SIZE : 0;
+ const int min_pos =
+ (base_position > window_size) ? base_position - window_size : 0;
int pos;
-
- assert(xsize > 0);
- for (pos = p->hash_to_first_index_[hash_code];
+ int length_max = 256;
+ if (max_len < length_max) {
+ length_max = max_len;
+ }
+ for (pos = p->hash_to_first_index_[GetPixPairHash64(argb_start)];
pos >= min_pos;
pos = p->chain_[pos]) {
- int64_t val;
int curr_length;
- if (iter_cnt < 0) {
- if (iter_cnt < iter_min || best_val >= 0xff0000) {
- break;
- }
- }
- --iter_cnt;
- if (best_length != 0 &&
- argb[pos + best_length - 1] != argb_start[best_length - 1]) {
- continue;
- }
- curr_length = FindMatchLength(argb + pos, argb_start, maxlen);
- if (curr_length < prev_length) {
- continue;
+ int distance;
+ if (--iter < 0) {
+ break;
}
- val = 65536 * curr_length;
- // Favoring 2d locality here gives savings for certain images.
- if (index - pos < 9 * xsize) {
- const int y = (index - pos) / xsize;
- int x = (index - pos) % xsize;
- if (x > xsize / 2) {
- x = xsize - x;
- }
- if (x <= 7 && x >= -8) {
- val -= y * y + x * x;
- } else {
- val -= 9 * 9 + 9 * 9;
- }
- } else {
- val -= 9 * 9 + 9 * 9;
- }
- if (best_val < val) {
- prev_length = curr_length;
- best_val = val;
+
+ curr_length = FindMatchLength(argb + pos, argb_start, best_length, max_len);
+ if (best_length < curr_length) {
+ distance = base_position - pos;
best_length = curr_length;
- best_distance = index - pos;
- if (curr_length >= MAX_LENGTH) {
- break;
- }
- if ((best_distance == 1 || best_distance == xsize) &&
- best_length >= 128) {
+ best_distance = distance;
+ if (curr_length >= length_max) {
break;
}
}
@@ -213,140 +336,153 @@ static int HashChainFindCopy(const HashChain* const p,
return (best_length >= MIN_LENGTH);
}
-static WEBP_INLINE void PushBackCopy(VP8LBackwardRefs* const refs, int length) {
- int size = refs->size;
- while (length >= MAX_LENGTH) {
- refs->refs[size++] = PixOrCopyCreateCopy(1, MAX_LENGTH);
- length -= MAX_LENGTH;
- }
- if (length > 0) {
- refs->refs[size++] = PixOrCopyCreateCopy(1, length);
+static WEBP_INLINE void AddSingleLiteral(uint32_t pixel, int use_color_cache,
+ VP8LColorCache* const hashers,
+ VP8LBackwardRefs* const refs) {
+ PixOrCopy v;
+ if (use_color_cache) {
+ const uint32_t key = VP8LColorCacheGetIndex(hashers, pixel);
+ if (VP8LColorCacheLookup(hashers, key) == pixel) {
+ v = PixOrCopyCreateCacheIdx(key);
+ } else {
+ v = PixOrCopyCreateLiteral(pixel);
+ VP8LColorCacheSet(hashers, key, pixel);
+ }
+ } else {
+ v = PixOrCopyCreateLiteral(pixel);
}
- refs->size = size;
+ BackwardRefsCursorAdd(refs, v);
}
-static void BackwardReferencesRle(int xsize, int ysize,
- const uint32_t* const argb,
- VP8LBackwardRefs* const refs) {
+static int BackwardReferencesRle(int xsize, int ysize,
+ const uint32_t* const argb,
+ int cache_bits, VP8LBackwardRefs* const refs) {
const int pix_count = xsize * ysize;
- int match_len = 0;
- int i;
- refs->size = 0;
- PushBackCopy(refs, match_len); // i=0 case
- refs->refs[refs->size++] = PixOrCopyCreateLiteral(argb[0]);
- for (i = 1; i < pix_count; ++i) {
- if (argb[i] == argb[i - 1]) {
- ++match_len;
+ int i, k;
+ const int use_color_cache = (cache_bits > 0);
+ VP8LColorCache hashers;
+
+ if (use_color_cache && !VP8LColorCacheInit(&hashers, cache_bits)) {
+ return 0;
+ }
+ ClearBackwardRefs(refs);
+ // Add first pixel as literal.
+ AddSingleLiteral(argb[0], use_color_cache, &hashers, refs);
+ i = 1;
+ while (i < pix_count) {
+ const int max_len = MaxFindCopyLength(pix_count - i);
+ const int kMinLength = 4;
+ const int rle_len = FindMatchLength(argb + i, argb + i - 1, 0, max_len);
+ const int prev_row_len = (i < xsize) ? 0 :
+ FindMatchLength(argb + i, argb + i - xsize, 0, max_len);
+ if (rle_len >= prev_row_len && rle_len >= kMinLength) {
+ BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, rle_len));
+ // We don't need to update the color cache here since it is always the
+ // same pixel being copied, and that does not change the color cache
+ // state.
+ i += rle_len;
+ } else if (prev_row_len >= kMinLength) {
+ BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(xsize, prev_row_len));
+ if (use_color_cache) {
+ for (k = 0; k < prev_row_len; ++k) {
+ VP8LColorCacheInsert(&hashers, argb[i + k]);
+ }
+ }
+ i += prev_row_len;
} else {
- PushBackCopy(refs, match_len);
- match_len = 0;
- refs->refs[refs->size++] = PixOrCopyCreateLiteral(argb[i]);
+ AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
+ i++;
}
}
- PushBackCopy(refs, match_len);
+ if (use_color_cache) VP8LColorCacheClear(&hashers);
+ return !refs->error_;
}
-static int BackwardReferencesHashChain(int xsize, int ysize,
- const uint32_t* const argb,
- int cache_bits, int quality,
- VP8LBackwardRefs* const refs) {
+static int BackwardReferencesLz77(int xsize, int ysize,
+ const uint32_t* const argb, int cache_bits,
+ int quality, int low_effort,
+ VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs* const refs) {
int i;
int ok = 0;
int cc_init = 0;
const int use_color_cache = (cache_bits > 0);
const int pix_count = xsize * ysize;
- HashChain* const hash_chain = (HashChain*)malloc(sizeof(*hash_chain));
VP8LColorCache hashers;
+ int iter_max = GetMaxItersForQuality(quality, low_effort);
+ const int window_size = GetWindowSizeForHashChain(quality, xsize);
+ int min_matches = 32;
- if (hash_chain == NULL) return 0;
if (use_color_cache) {
cc_init = VP8LColorCacheInit(&hashers, cache_bits);
if (!cc_init) goto Error;
}
-
- if (!HashChainInit(hash_chain, pix_count)) goto Error;
-
- refs->size = 0;
- for (i = 0; i < pix_count; ) {
+ ClearBackwardRefs(refs);
+ HashChainReset(hash_chain);
+ for (i = 0; i < pix_count - 2; ) {
// Alternative#1: Code the pixels starting at 'i' using backward reference.
int offset = 0;
int len = 0;
- if (i < pix_count - 1) { // FindCopy(i,..) reads pixels at [i] and [i + 1].
- int maxlen = pix_count - i;
- if (maxlen > MAX_LENGTH) {
- maxlen = MAX_LENGTH;
- }
- HashChainFindCopy(hash_chain, quality, i, xsize, argb, maxlen,
- &offset, &len);
- }
- if (len >= MIN_LENGTH) {
- // Alternative#2: Insert the pixel at 'i' as literal, and code the
- // pixels starting at 'i + 1' using backward reference.
+ const int max_len = MaxFindCopyLength(pix_count - i);
+ HashChainFindCopy(hash_chain, i, argb, max_len, window_size,
+ iter_max, &offset, &len);
+ if (len > MIN_LENGTH || (len == MIN_LENGTH && offset <= 512)) {
int offset2 = 0;
int len2 = 0;
int k;
+ min_matches = 8;
HashChainInsert(hash_chain, &argb[i], i);
- if (i < pix_count - 2) { // FindCopy(i+1,..) reads [i + 1] and [i + 2].
- int maxlen = pix_count - (i + 1);
- if (maxlen > MAX_LENGTH) {
- maxlen = MAX_LENGTH;
- }
- HashChainFindCopy(hash_chain, quality,
- i + 1, xsize, argb, maxlen, &offset2, &len2);
+ if ((len < (max_len >> 2)) && !low_effort) {
+ // Evaluate Alternative#2: Insert the pixel at 'i' as literal, and code
+ // the pixels starting at 'i + 1' using backward reference.
+ HashChainFindCopy(hash_chain, i + 1, argb, max_len - 1,
+ window_size, iter_max, &offset2,
+ &len2);
if (len2 > len + 1) {
- const uint32_t pixel = argb[i];
- // Alternative#2 is a better match. So push pixel at 'i' as literal.
- if (use_color_cache && VP8LColorCacheContains(&hashers, pixel)) {
- const int ix = VP8LColorCacheGetIndex(&hashers, pixel);
- refs->refs[refs->size] = PixOrCopyCreateCacheIdx(ix);
- } else {
- refs->refs[refs->size] = PixOrCopyCreateLiteral(pixel);
- }
- ++refs->size;
- if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel);
+ AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
i++; // Backward reference to be done for next pixel.
len = len2;
offset = offset2;
}
}
- if (len >= MAX_LENGTH) {
- len = MAX_LENGTH - 1;
- }
- refs->refs[refs->size++] = PixOrCopyCreateCopy(offset, len);
+ BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len));
if (use_color_cache) {
for (k = 0; k < len; ++k) {
VP8LColorCacheInsert(&hashers, argb[i + k]);
}
}
// Add to the hash_chain (but cannot add the last pixel).
- {
+ if (offset >= 3 && offset != xsize) {
const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i;
- for (k = 1; k < last; ++k) {
+ for (k = 2; k < last - 8; k += 2) {
+ HashChainInsert(hash_chain, &argb[i + k], i + k);
+ }
+ for (; k < last; ++k) {
HashChainInsert(hash_chain, &argb[i + k], i + k);
}
}
i += len;
} else {
- const uint32_t pixel = argb[i];
- if (use_color_cache && VP8LColorCacheContains(&hashers, pixel)) {
- // push pixel as a PixOrCopyCreateCacheIdx pixel
- const int ix = VP8LColorCacheGetIndex(&hashers, pixel);
- refs->refs[refs->size] = PixOrCopyCreateCacheIdx(ix);
- } else {
- refs->refs[refs->size] = PixOrCopyCreateLiteral(pixel);
- }
- ++refs->size;
- if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel);
- if (i + 1 < pix_count) {
+ AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
+ HashChainInsert(hash_chain, &argb[i], i);
+ ++i;
+ --min_matches;
+ if (min_matches <= 0) {
+ AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
HashChainInsert(hash_chain, &argb[i], i);
+ ++i;
}
- ++i;
}
}
- ok = 1;
-Error:
+ while (i < pix_count) {
+ // Handle the last pixel(s).
+ AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
+ ++i;
+ }
+
+ ok = !refs->error_;
+ Error:
if (cc_init) VP8LColorCacheClear(&hashers);
- HashChainDelete(hash_chain);
return ok;
}
@@ -355,18 +491,19 @@ Error:
typedef struct {
double alpha_[VALUES_IN_BYTE];
double red_[VALUES_IN_BYTE];
- double literal_[PIX_OR_COPY_CODES_MAX];
double blue_[VALUES_IN_BYTE];
double distance_[NUM_DISTANCE_CODES];
+ double* literal_;
} CostModel;
static int BackwardReferencesTraceBackwards(
- int xsize, int ysize, int recursive_cost_model,
- const uint32_t* const argb, int cache_bits, VP8LBackwardRefs* const refs);
+ int xsize, int ysize, const uint32_t* const argb, int quality,
+ int cache_bits, VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs* const refs);
static void ConvertPopulationCountTableToBitEstimates(
- int num_symbols, const int population_counts[], double output[]) {
- int sum = 0;
+ int num_symbols, const uint32_t population_counts[], double output[]) {
+ uint32_t sum = 0;
int nonzeros = 0;
int i;
for (i = 0; i < num_symbols; ++i) {
@@ -385,42 +522,29 @@ static void ConvertPopulationCountTableToBitEstimates(
}
}
-static int CostModelBuild(CostModel* const m, int xsize, int ysize,
- int recursion_level, const uint32_t* const argb,
- int cache_bits) {
+static int CostModelBuild(CostModel* const m, int cache_bits,
+ VP8LBackwardRefs* const refs) {
int ok = 0;
- VP8LHistogram histo;
- VP8LBackwardRefs refs;
- const int quality = 100;
+ VP8LHistogram* const histo = VP8LAllocateHistogram(cache_bits);
+ if (histo == NULL) goto Error;
- if (!VP8LBackwardRefsAlloc(&refs, xsize * ysize)) goto Error;
+ VP8LHistogramCreate(histo, refs, cache_bits);
- if (recursion_level > 0) {
- if (!BackwardReferencesTraceBackwards(xsize, ysize, recursion_level - 1,
- argb, cache_bits, &refs)) {
- goto Error;
- }
- } else {
- if (!BackwardReferencesHashChain(xsize, ysize, argb, cache_bits, quality,
- &refs)) {
- goto Error;
- }
- }
- VP8LHistogramCreate(&histo, &refs, cache_bits);
ConvertPopulationCountTableToBitEstimates(
- VP8LHistogramNumCodes(&histo), histo.literal_, m->literal_);
+ VP8LHistogramNumCodes(histo->palette_code_bits_),
+ histo->literal_, m->literal_);
ConvertPopulationCountTableToBitEstimates(
- VALUES_IN_BYTE, histo.red_, m->red_);
+ VALUES_IN_BYTE, histo->red_, m->red_);
ConvertPopulationCountTableToBitEstimates(
- VALUES_IN_BYTE, histo.blue_, m->blue_);
+ VALUES_IN_BYTE, histo->blue_, m->blue_);
ConvertPopulationCountTableToBitEstimates(
- VALUES_IN_BYTE, histo.alpha_, m->alpha_);
+ VALUES_IN_BYTE, histo->alpha_, m->alpha_);
ConvertPopulationCountTableToBitEstimates(
- NUM_DISTANCE_CODES, histo.distance_, m->distance_);
+ NUM_DISTANCE_CODES, histo->distance_, m->distance_);
ok = 1;
Error:
- VP8LClearBackwardRefs(&refs);
+ VP8LFreeHistogram(histo);
return ok;
}
@@ -438,203 +562,211 @@ static WEBP_INLINE double GetCacheCost(const CostModel* const m, uint32_t idx) {
static WEBP_INLINE double GetLengthCost(const CostModel* const m,
uint32_t length) {
- int code, extra_bits_count, extra_bits_value;
- PrefixEncode(length, &code, &extra_bits_count, &extra_bits_value);
- return m->literal_[VALUES_IN_BYTE + code] + extra_bits_count;
+ int code, extra_bits;
+ VP8LPrefixEncodeBits(length, &code, &extra_bits);
+ return m->literal_[VALUES_IN_BYTE + code] + extra_bits;
}
static WEBP_INLINE double GetDistanceCost(const CostModel* const m,
uint32_t distance) {
- int code, extra_bits_count, extra_bits_value;
- PrefixEncode(distance, &code, &extra_bits_count, &extra_bits_value);
- return m->distance_[code] + extra_bits_count;
+ int code, extra_bits;
+ VP8LPrefixEncodeBits(distance, &code, &extra_bits);
+ return m->distance_[code] + extra_bits;
+}
+
+static void AddSingleLiteralWithCostModel(
+ const uint32_t* const argb, VP8LHashChain* const hash_chain,
+ VP8LColorCache* const hashers, const CostModel* const cost_model, int idx,
+ int is_last, int use_color_cache, double prev_cost, float* const cost,
+ uint16_t* const dist_array) {
+ double cost_val = prev_cost;
+ const uint32_t color = argb[0];
+ if (!is_last) {
+ HashChainInsert(hash_chain, argb, idx);
+ }
+ if (use_color_cache && VP8LColorCacheContains(hashers, color)) {
+ const double mul0 = 0.68;
+ const int ix = VP8LColorCacheGetIndex(hashers, color);
+ cost_val += GetCacheCost(cost_model, ix) * mul0;
+ } else {
+ const double mul1 = 0.82;
+ if (use_color_cache) VP8LColorCacheInsert(hashers, color);
+ cost_val += GetLiteralCost(cost_model, color) * mul1;
+ }
+ if (cost[idx] > cost_val) {
+ cost[idx] = (float)cost_val;
+ dist_array[idx] = 1; // only one is inserted.
+ }
}
static int BackwardReferencesHashChainDistanceOnly(
- int xsize, int ysize, int recursive_cost_model, const uint32_t* const argb,
- int cache_bits, uint32_t* const dist_array) {
+ int xsize, int ysize, const uint32_t* const argb,
+ int quality, int cache_bits, VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs* const refs, uint16_t* const dist_array) {
int i;
int ok = 0;
int cc_init = 0;
- const int quality = 100;
const int pix_count = xsize * ysize;
const int use_color_cache = (cache_bits > 0);
- double* const cost =
- (double*)WebPSafeMalloc((uint64_t)pix_count, sizeof(*cost));
- CostModel* cost_model = (CostModel*)malloc(sizeof(*cost_model));
- HashChain* hash_chain = (HashChain*)malloc(sizeof(*hash_chain));
+ float* const cost =
+ (float*)WebPSafeMalloc(pix_count, sizeof(*cost));
+ const size_t literal_array_size = sizeof(double) *
+ (NUM_LITERAL_CODES + NUM_LENGTH_CODES +
+ ((cache_bits > 0) ? (1 << cache_bits) : 0));
+ const size_t cost_model_size = sizeof(CostModel) + literal_array_size;
+ CostModel* const cost_model =
+ (CostModel*)WebPSafeMalloc(1ULL, cost_model_size);
VP8LColorCache hashers;
- const double mul0 = (recursive_cost_model != 0) ? 1.0 : 0.68;
- const double mul1 = (recursive_cost_model != 0) ? 1.0 : 0.82;
-
- if (cost == NULL || cost_model == NULL || hash_chain == NULL) goto Error;
+ const int skip_length = 32 + quality;
+ const int skip_min_distance_code = 2;
+ int iter_max = GetMaxItersForQuality(quality, 0);
+ const int window_size = GetWindowSizeForHashChain(quality, xsize);
- if (!HashChainInit(hash_chain, pix_count)) goto Error;
+ if (cost == NULL || cost_model == NULL) goto Error;
+ cost_model->literal_ = (double*)(cost_model + 1);
if (use_color_cache) {
cc_init = VP8LColorCacheInit(&hashers, cache_bits);
if (!cc_init) goto Error;
}
- if (!CostModelBuild(cost_model, xsize, ysize, recursive_cost_model, argb,
- cache_bits)) {
+ if (!CostModelBuild(cost_model, cache_bits, refs)) {
goto Error;
}
- for (i = 0; i < pix_count; ++i) cost[i] = 1e100;
+ for (i = 0; i < pix_count; ++i) cost[i] = 1e38f;
// We loop one pixel at a time, but store all currently best points to
// non-processed locations from this point.
dist_array[0] = 0;
- for (i = 0; i < pix_count; ++i) {
- double prev_cost = 0.0;
- int shortmax;
- if (i > 0) {
- prev_cost = cost[i - 1];
- }
- for (shortmax = 0; shortmax < 2; ++shortmax) {
- int offset = 0;
- int len = 0;
- if (i < pix_count - 1) { // FindCopy reads pixels at [i] and [i + 1].
- int maxlen = shortmax ? 2 : MAX_LENGTH;
- if (maxlen > pix_count - i) {
- maxlen = pix_count - i;
+ HashChainReset(hash_chain);
+ // Add first pixel as literal.
+ AddSingleLiteralWithCostModel(argb + 0, hash_chain, &hashers, cost_model, 0,
+ 0, use_color_cache, 0.0, cost, dist_array);
+ for (i = 1; i < pix_count - 1; ++i) {
+ int offset = 0;
+ int len = 0;
+ double prev_cost = cost[i - 1];
+ const int max_len = MaxFindCopyLength(pix_count - i);
+ HashChainFindCopy(hash_chain, i, argb, max_len, window_size,
+ iter_max, &offset, &len);
+ if (len >= MIN_LENGTH) {
+ const int code = DistanceToPlaneCode(xsize, offset);
+ const double distance_cost =
+ prev_cost + GetDistanceCost(cost_model, code);
+ int k;
+ for (k = 1; k < len; ++k) {
+ const double cost_val = distance_cost + GetLengthCost(cost_model, k);
+ if (cost[i + k] > cost_val) {
+ cost[i + k] = (float)cost_val;
+ dist_array[i + k] = k + 1;
}
- HashChainFindCopy(hash_chain, quality, i, xsize, argb, maxlen,
- &offset, &len);
}
- if (len >= MIN_LENGTH) {
- const int code = DistanceToPlaneCode(xsize, offset);
- const double distance_cost =
- prev_cost + GetDistanceCost(cost_model, code);
- int k;
- for (k = 1; k < len; ++k) {
- const double cost_val =
- distance_cost + GetLengthCost(cost_model, k);
- if (cost[i + k] > cost_val) {
- cost[i + k] = cost_val;
- dist_array[i + k] = k + 1;
+ // This if is for speedup only. It roughly doubles the speed, and
+ // makes compression worse by .1 %.
+ if (len >= skip_length && code <= skip_min_distance_code) {
+ // Long copy for short distances, let's skip the middle
+ // lookups for better copies.
+ // 1) insert the hashes.
+ if (use_color_cache) {
+ for (k = 0; k < len; ++k) {
+ VP8LColorCacheInsert(&hashers, argb[i + k]);
}
}
- // This if is for speedup only. It roughly doubles the speed, and
- // makes compression worse by .1 %.
- if (len >= 128 && code < 2) {
- // Long copy for short distances, let's skip the middle
- // lookups for better copies.
- // 1) insert the hashes.
- if (use_color_cache) {
- for (k = 0; k < len; ++k) {
- VP8LColorCacheInsert(&hashers, argb[i + k]);
- }
- }
- // 2) Add to the hash_chain (but cannot add the last pixel)
- {
- const int last = (len < pix_count - 1 - i) ? len
- : pix_count - 1 - i;
- for (k = 0; k < last; ++k) {
- HashChainInsert(hash_chain, &argb[i + k], i + k);
- }
+ // 2) Add to the hash_chain (but cannot add the last pixel)
+ {
+ const int last = (len + i < pix_count - 1) ? len + i
+ : pix_count - 1;
+ for (k = i; k < last; ++k) {
+ HashChainInsert(hash_chain, &argb[k], k);
}
- // 3) jump.
- i += len - 1; // for loop does ++i, thus -1 here.
- goto next_symbol;
}
+ // 3) jump.
+ i += len - 1; // for loop does ++i, thus -1 here.
+ goto next_symbol;
}
- }
- if (i < pix_count - 1) {
- HashChainInsert(hash_chain, &argb[i], i);
- }
- {
- // inserting a literal pixel
- double cost_val = prev_cost;
- if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) {
- const int ix = VP8LColorCacheGetIndex(&hashers, argb[i]);
- cost_val += GetCacheCost(cost_model, ix) * mul0;
- } else {
- cost_val += GetLiteralCost(cost_model, argb[i]) * mul1;
- }
- if (cost[i] > cost_val) {
- cost[i] = cost_val;
- dist_array[i] = 1; // only one is inserted.
+ if (len != MIN_LENGTH) {
+ int code_min_length;
+ double cost_total;
+ HashChainFindOffset(hash_chain, i, argb, MIN_LENGTH, window_size,
+ &offset);
+ code_min_length = DistanceToPlaneCode(xsize, offset);
+ cost_total = prev_cost +
+ GetDistanceCost(cost_model, code_min_length) +
+ GetLengthCost(cost_model, 1);
+ if (cost[i + 1] > cost_total) {
+ cost[i + 1] = (float)cost_total;
+ dist_array[i + 1] = 2;
+ }
}
- if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
}
+ AddSingleLiteralWithCostModel(argb + i, hash_chain, &hashers, cost_model, i,
+ 0, use_color_cache, prev_cost, cost,
+ dist_array);
next_symbol: ;
}
- // Last pixel still to do, it can only be a single step if not reached
- // through cheaper means already.
- ok = 1;
-Error:
+ // Handle the last pixel.
+ if (i == (pix_count - 1)) {
+ AddSingleLiteralWithCostModel(argb + i, hash_chain, &hashers, cost_model, i,
+ 1, use_color_cache, cost[pix_count - 2], cost,
+ dist_array);
+ }
+ ok = !refs->error_;
+ Error:
if (cc_init) VP8LColorCacheClear(&hashers);
- HashChainDelete(hash_chain);
- free(cost_model);
- free(cost);
+ WebPSafeFree(cost_model);
+ WebPSafeFree(cost);
return ok;
}
-static int TraceBackwards(const uint32_t* const dist_array,
- int dist_array_size,
- uint32_t** const chosen_path,
- int* const chosen_path_size) {
- int i;
- // Count how many.
- int count = 0;
- for (i = dist_array_size - 1; i >= 0; ) {
- int k = dist_array[i];
- assert(k >= 1);
- ++count;
- i -= k;
- }
- // Allocate.
- *chosen_path_size = count;
- *chosen_path =
- (uint32_t*)WebPSafeMalloc((uint64_t)count, sizeof(**chosen_path));
- if (*chosen_path == NULL) return 0;
-
- // Write in reverse order.
- for (i = dist_array_size - 1; i >= 0; ) {
- int k = dist_array[i];
- assert(k >= 1);
- (*chosen_path)[--count] = k;
- i -= k;
+// We pack the path at the end of *dist_array and return
+// a pointer to this part of the array. Example:
+// dist_array = [1x2xx3x2] => packed [1x2x1232], chosen_path = [1232]
+static void TraceBackwards(uint16_t* const dist_array,
+ int dist_array_size,
+ uint16_t** const chosen_path,
+ int* const chosen_path_size) {
+ uint16_t* path = dist_array + dist_array_size;
+ uint16_t* cur = dist_array + dist_array_size - 1;
+ while (cur >= dist_array) {
+ const int k = *cur;
+ --path;
+ *path = k;
+ cur -= k;
}
- return 1;
+ *chosen_path = path;
+ *chosen_path_size = (int)(dist_array + dist_array_size - path);
}
static int BackwardReferencesHashChainFollowChosenPath(
- int xsize, int ysize, const uint32_t* const argb, int cache_bits,
- const uint32_t* const chosen_path, int chosen_path_size,
+ int xsize, int ysize, const uint32_t* const argb,
+ int quality, int cache_bits,
+ const uint16_t* const chosen_path, int chosen_path_size,
+ VP8LHashChain* const hash_chain,
VP8LBackwardRefs* const refs) {
- const int quality = 100;
const int pix_count = xsize * ysize;
const int use_color_cache = (cache_bits > 0);
- int size = 0;
- int i = 0;
- int k;
int ix;
+ int i = 0;
int ok = 0;
int cc_init = 0;
- HashChain* hash_chain = (HashChain*)malloc(sizeof(*hash_chain));
+ const int window_size = GetWindowSizeForHashChain(quality, xsize);
VP8LColorCache hashers;
- if (hash_chain == NULL || !HashChainInit(hash_chain, pix_count)) {
- goto Error;
- }
if (use_color_cache) {
cc_init = VP8LColorCacheInit(&hashers, cache_bits);
if (!cc_init) goto Error;
}
- refs->size = 0;
- for (ix = 0; ix < chosen_path_size; ++ix, ++size) {
+ ClearBackwardRefs(refs);
+ HashChainReset(hash_chain);
+ for (ix = 0; ix < chosen_path_size; ++ix) {
int offset = 0;
- int len = 0;
- int maxlen = chosen_path[ix];
- if (maxlen != 1) {
- HashChainFindCopy(hash_chain, quality,
- i, xsize, argb, maxlen, &offset, &len);
- assert(len == maxlen);
- refs->refs[size] = PixOrCopyCreateCopy(offset, len);
+ const int len = chosen_path[ix];
+ if (len != 1) {
+ int k;
+ HashChainFindOffset(hash_chain, i, argb, len, window_size, &offset);
+ BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len));
if (use_color_cache) {
for (k = 0; k < len; ++k) {
VP8LColorCacheInsert(&hashers, argb[i + k]);
@@ -648,227 +780,330 @@ static int BackwardReferencesHashChainFollowChosenPath(
}
i += len;
} else {
+ PixOrCopy v;
if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) {
// push pixel as a color cache index
const int idx = VP8LColorCacheGetIndex(&hashers, argb[i]);
- refs->refs[size] = PixOrCopyCreateCacheIdx(idx);
+ v = PixOrCopyCreateCacheIdx(idx);
} else {
- refs->refs[size] = PixOrCopyCreateLiteral(argb[i]);
+ if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
+ v = PixOrCopyCreateLiteral(argb[i]);
}
- if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
+ BackwardRefsCursorAdd(refs, v);
if (i + 1 < pix_count) {
HashChainInsert(hash_chain, &argb[i], i);
}
++i;
}
}
- assert(size <= refs->max_size);
- refs->size = size;
- ok = 1;
-Error:
+ ok = !refs->error_;
+ Error:
if (cc_init) VP8LColorCacheClear(&hashers);
- HashChainDelete(hash_chain);
return ok;
}
// Returns 1 on success.
static int BackwardReferencesTraceBackwards(int xsize, int ysize,
- int recursive_cost_model,
const uint32_t* const argb,
- int cache_bits,
+ int quality, int cache_bits,
+ VP8LHashChain* const hash_chain,
VP8LBackwardRefs* const refs) {
int ok = 0;
const int dist_array_size = xsize * ysize;
- uint32_t* chosen_path = NULL;
+ uint16_t* chosen_path = NULL;
int chosen_path_size = 0;
- uint32_t* dist_array =
- (uint32_t*)WebPSafeMalloc((uint64_t)dist_array_size, sizeof(*dist_array));
+ uint16_t* dist_array =
+ (uint16_t*)WebPSafeMalloc(dist_array_size, sizeof(*dist_array));
if (dist_array == NULL) goto Error;
if (!BackwardReferencesHashChainDistanceOnly(
- xsize, ysize, recursive_cost_model, argb, cache_bits, dist_array)) {
- goto Error;
- }
- if (!TraceBackwards(dist_array, dist_array_size,
- &chosen_path, &chosen_path_size)) {
+ xsize, ysize, argb, quality, cache_bits, hash_chain,
+ refs, dist_array)) {
goto Error;
}
- free(dist_array); // no need to retain this memory any longer
- dist_array = NULL;
+ TraceBackwards(dist_array, dist_array_size, &chosen_path, &chosen_path_size);
if (!BackwardReferencesHashChainFollowChosenPath(
- xsize, ysize, argb, cache_bits, chosen_path, chosen_path_size, refs)) {
+ xsize, ysize, argb, quality, cache_bits, chosen_path, chosen_path_size,
+ hash_chain, refs)) {
goto Error;
}
ok = 1;
Error:
- free(chosen_path);
- free(dist_array);
+ WebPSafeFree(dist_array);
return ok;
}
static void BackwardReferences2DLocality(int xsize,
- VP8LBackwardRefs* const refs) {
- int i;
- for (i = 0; i < refs->size; ++i) {
- if (PixOrCopyIsCopy(&refs->refs[i])) {
- const int dist = refs->refs[i].argb_or_distance;
+ const VP8LBackwardRefs* const refs) {
+ VP8LRefsCursor c = VP8LRefsCursorInit(refs);
+ while (VP8LRefsCursorOk(&c)) {
+ if (PixOrCopyIsCopy(c.cur_pos)) {
+ const int dist = c.cur_pos->argb_or_distance;
const int transformed_dist = DistanceToPlaneCode(xsize, dist);
- refs->refs[i].argb_or_distance = transformed_dist;
+ c.cur_pos->argb_or_distance = transformed_dist;
}
+ VP8LRefsCursorNext(&c);
}
}
-int VP8LGetBackwardReferences(int width, int height,
- const uint32_t* const argb,
- int quality, int cache_bits, int use_2d_locality,
- VP8LBackwardRefs* const best) {
- int ok = 0;
- int lz77_is_useful;
- VP8LBackwardRefs refs_rle, refs_lz77;
- const int num_pix = width * height;
-
- VP8LBackwardRefsAlloc(&refs_rle, num_pix);
- VP8LBackwardRefsAlloc(&refs_lz77, num_pix);
- VP8LInitBackwardRefs(best);
- if (refs_rle.refs == NULL || refs_lz77.refs == NULL) {
- Error1:
- VP8LClearBackwardRefs(&refs_rle);
- VP8LClearBackwardRefs(&refs_lz77);
- goto End;
- }
-
- if (!BackwardReferencesHashChain(width, height, argb, cache_bits, quality,
- &refs_lz77)) {
- goto End;
- }
- // Backward Reference using RLE only.
- BackwardReferencesRle(width, height, argb, &refs_rle);
+// Returns entropy for the given cache bits.
+static double ComputeCacheEntropy(const uint32_t* argb,
+ const VP8LBackwardRefs* const refs,
+ int cache_bits) {
+ const int use_color_cache = (cache_bits > 0);
+ int cc_init = 0;
+ double entropy = MAX_ENTROPY;
+ const double kSmallPenaltyForLargeCache = 4.0;
+ VP8LColorCache hashers;
+ VP8LRefsCursor c = VP8LRefsCursorInit(refs);
+ VP8LHistogram* histo = VP8LAllocateHistogram(cache_bits);
+ if (histo == NULL) goto Error;
- {
- double bit_cost_lz77, bit_cost_rle;
- VP8LHistogram* const histo = (VP8LHistogram*)malloc(sizeof(*histo));
- if (histo == NULL) goto Error1;
- // Evaluate lz77 coding
- VP8LHistogramCreate(histo, &refs_lz77, cache_bits);
- bit_cost_lz77 = VP8LHistogramEstimateBits(histo);
- // Evaluate RLE coding
- VP8LHistogramCreate(histo, &refs_rle, cache_bits);
- bit_cost_rle = VP8LHistogramEstimateBits(histo);
- // Decide if LZ77 is useful.
- lz77_is_useful = (bit_cost_lz77 < bit_cost_rle);
- free(histo);
+ if (use_color_cache) {
+ cc_init = VP8LColorCacheInit(&hashers, cache_bits);
+ if (!cc_init) goto Error;
}
-
- // Choose appropriate backward reference.
- if (lz77_is_useful) {
- // TraceBackwards is costly. Run it for higher qualities.
- const int try_lz77_trace_backwards = (quality >= 75);
- *best = refs_lz77; // default guess: lz77 is better
- VP8LClearBackwardRefs(&refs_rle);
- if (try_lz77_trace_backwards) {
- const int recursion_level = (num_pix < 320 * 200) ? 1 : 0;
- VP8LBackwardRefs refs_trace;
- if (!VP8LBackwardRefsAlloc(&refs_trace, num_pix)) {
- goto End;
- }
- if (BackwardReferencesTraceBackwards(
- width, height, recursion_level, argb, cache_bits, &refs_trace)) {
- VP8LClearBackwardRefs(&refs_lz77);
- *best = refs_trace;
- }
+ if (!use_color_cache) {
+ while (VP8LRefsCursorOk(&c)) {
+ VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos);
+ VP8LRefsCursorNext(&c);
}
} else {
- VP8LClearBackwardRefs(&refs_lz77);
- *best = refs_rle;
+ while (VP8LRefsCursorOk(&c)) {
+ const PixOrCopy* const v = c.cur_pos;
+ if (PixOrCopyIsLiteral(v)) {
+ const uint32_t pix = *argb++;
+ const uint32_t key = VP8LColorCacheGetIndex(&hashers, pix);
+ if (VP8LColorCacheLookup(&hashers, key) == pix) {
+ ++histo->literal_[NUM_LITERAL_CODES + NUM_LENGTH_CODES + key];
+ } else {
+ VP8LColorCacheSet(&hashers, key, pix);
+ ++histo->blue_[pix & 0xff];
+ ++histo->literal_[(pix >> 8) & 0xff];
+ ++histo->red_[(pix >> 16) & 0xff];
+ ++histo->alpha_[pix >> 24];
+ }
+ } else {
+ int len = PixOrCopyLength(v);
+ int code, extra_bits;
+ VP8LPrefixEncodeBits(len, &code, &extra_bits);
+ ++histo->literal_[NUM_LITERAL_CODES + code];
+ VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits);
+ ++histo->distance_[code];
+ do {
+ VP8LColorCacheInsert(&hashers, *argb++);
+ } while(--len != 0);
+ }
+ VP8LRefsCursorNext(&c);
+ }
}
+ entropy = VP8LHistogramEstimateBits(histo) +
+ kSmallPenaltyForLargeCache * cache_bits;
+ Error:
+ if (cc_init) VP8LColorCacheClear(&hashers);
+ VP8LFreeHistogram(histo);
+ return entropy;
+}
- if (use_2d_locality) BackwardReferences2DLocality(width, best);
-
- ok = 1;
-
- End:
- if (!ok) {
- VP8LClearBackwardRefs(best);
+// Evaluate optimal cache bits for the local color cache.
+// The input *best_cache_bits sets the maximum cache bits to use (passing 0
+// implies disabling the local color cache). The local color cache is also
+// disabled for the lower (<= 25) quality.
+// Returns 0 in case of memory error.
+static int CalculateBestCacheSize(const uint32_t* const argb,
+ int xsize, int ysize, int quality,
+ VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs* const refs,
+ int* const lz77_computed,
+ int* const best_cache_bits) {
+ int eval_low = 1;
+ int eval_high = 1;
+ double entropy_low = MAX_ENTROPY;
+ double entropy_high = MAX_ENTROPY;
+ const double cost_mul = 5e-4;
+ int cache_bits_low = 0;
+ int cache_bits_high = (quality <= 25) ? 0 : *best_cache_bits;
+
+ assert(cache_bits_high <= MAX_COLOR_CACHE_BITS);
+
+ *lz77_computed = 0;
+ if (cache_bits_high == 0) {
+ *best_cache_bits = 0;
+ // Local color cache is disabled.
+ return 1;
}
- return ok;
+ if (!BackwardReferencesLz77(xsize, ysize, argb, cache_bits_low, quality, 0,
+ hash_chain, refs)) {
+ return 0;
+ }
+ // Do a binary search to find the optimal entropy for cache_bits.
+ while (eval_low || eval_high) {
+ if (eval_low) {
+ entropy_low = ComputeCacheEntropy(argb, refs, cache_bits_low);
+ entropy_low += entropy_low * cache_bits_low * cost_mul;
+ eval_low = 0;
+ }
+ if (eval_high) {
+ entropy_high = ComputeCacheEntropy(argb, refs, cache_bits_high);
+ entropy_high += entropy_high * cache_bits_high * cost_mul;
+ eval_high = 0;
+ }
+ if (entropy_high < entropy_low) {
+ const int prev_cache_bits_low = cache_bits_low;
+ *best_cache_bits = cache_bits_high;
+ cache_bits_low = (cache_bits_low + cache_bits_high) / 2;
+ if (cache_bits_low != prev_cache_bits_low) eval_low = 1;
+ } else {
+ *best_cache_bits = cache_bits_low;
+ cache_bits_high = (cache_bits_low + cache_bits_high) / 2;
+ if (cache_bits_high != cache_bits_low) eval_high = 1;
+ }
+ }
+ *lz77_computed = 1;
+ return 1;
}
-// Returns 1 on success.
-static int ComputeCacheHistogram(const uint32_t* const argb,
- int xsize, int ysize,
- const VP8LBackwardRefs* const refs,
- int cache_bits,
- VP8LHistogram* const histo) {
+// Update (in-place) backward references for specified cache_bits.
+static int BackwardRefsWithLocalCache(const uint32_t* const argb,
+ int cache_bits,
+ VP8LBackwardRefs* const refs) {
int pixel_index = 0;
- int i;
- uint32_t k;
VP8LColorCache hashers;
- const int use_color_cache = (cache_bits > 0);
- int cc_init = 0;
+ VP8LRefsCursor c = VP8LRefsCursorInit(refs);
+ if (!VP8LColorCacheInit(&hashers, cache_bits)) return 0;
- if (use_color_cache) {
- cc_init = VP8LColorCacheInit(&hashers, cache_bits);
- if (!cc_init) return 0;
- }
-
- for (i = 0; i < refs->size; ++i) {
- const PixOrCopy* const v = &refs->refs[i];
+ while (VP8LRefsCursorOk(&c)) {
+ PixOrCopy* const v = c.cur_pos;
if (PixOrCopyIsLiteral(v)) {
- if (use_color_cache &&
- VP8LColorCacheContains(&hashers, argb[pixel_index])) {
- // push pixel as a cache index
- const int ix = VP8LColorCacheGetIndex(&hashers, argb[pixel_index]);
- const PixOrCopy token = PixOrCopyCreateCacheIdx(ix);
- VP8LHistogramAddSinglePixOrCopy(histo, &token);
+ const uint32_t argb_literal = v->argb_or_distance;
+ if (VP8LColorCacheContains(&hashers, argb_literal)) {
+ const int ix = VP8LColorCacheGetIndex(&hashers, argb_literal);
+ *v = PixOrCopyCreateCacheIdx(ix);
} else {
- VP8LHistogramAddSinglePixOrCopy(histo, v);
+ VP8LColorCacheInsert(&hashers, argb_literal);
}
+ ++pixel_index;
} else {
- VP8LHistogramAddSinglePixOrCopy(histo, v);
- }
- if (use_color_cache) {
- for (k = 0; k < PixOrCopyLength(v); ++k) {
- VP8LColorCacheInsert(&hashers, argb[pixel_index + k]);
+ // refs was created without local cache, so it can not have cache indexes.
+ int k;
+ assert(PixOrCopyIsCopy(v));
+ for (k = 0; k < v->len; ++k) {
+ VP8LColorCacheInsert(&hashers, argb[pixel_index++]);
}
}
- pixel_index += PixOrCopyLength(v);
+ VP8LRefsCursorNext(&c);
}
- assert(pixel_index == xsize * ysize);
- (void)xsize; // xsize is not used in non-debug compilations otherwise.
- (void)ysize; // ysize is not used in non-debug compilations otherwise.
- if (cc_init) VP8LColorCacheClear(&hashers);
+ VP8LColorCacheClear(&hashers);
return 1;
}
-// Returns how many bits are to be used for a color cache.
-int VP8LCalculateEstimateForCacheSize(const uint32_t* const argb,
- int xsize, int ysize,
- int* const best_cache_bits) {
- int ok = 0;
- int cache_bits;
- double lowest_entropy = 1e99;
- VP8LBackwardRefs refs;
- static const double kSmallPenaltyForLargeCache = 4.0;
- static const int quality = 30;
- if (!VP8LBackwardRefsAlloc(&refs, xsize * ysize) ||
- !BackwardReferencesHashChain(xsize, ysize, argb, 0, quality, &refs)) {
+static VP8LBackwardRefs* GetBackwardReferencesLowEffort(
+ int width, int height, const uint32_t* const argb, int quality,
+ int* const cache_bits, VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs refs_array[2]) {
+ VP8LBackwardRefs* refs_lz77 = &refs_array[0];
+ *cache_bits = 0;
+ if (!BackwardReferencesLz77(width, height, argb, 0, quality,
+ 1 /* Low effort. */, hash_chain, refs_lz77)) {
+ return NULL;
+ }
+ BackwardReferences2DLocality(width, refs_lz77);
+ return refs_lz77;
+}
+
+static VP8LBackwardRefs* GetBackwardReferences(
+ int width, int height, const uint32_t* const argb, int quality,
+ int* const cache_bits, VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs refs_array[2]) {
+ int lz77_is_useful;
+ int lz77_computed;
+ double bit_cost_lz77, bit_cost_rle;
+ VP8LBackwardRefs* best = NULL;
+ VP8LBackwardRefs* refs_lz77 = &refs_array[0];
+ VP8LBackwardRefs* refs_rle = &refs_array[1];
+ VP8LHistogram* histo = NULL;
+
+ if (!CalculateBestCacheSize(argb, width, height, quality, hash_chain,
+ refs_lz77, &lz77_computed, cache_bits)) {
goto Error;
}
- for (cache_bits = 0; cache_bits <= MAX_COLOR_CACHE_BITS; ++cache_bits) {
- double cur_entropy;
- VP8LHistogram histo;
- VP8LHistogramInit(&histo, cache_bits);
- ComputeCacheHistogram(argb, xsize, ysize, &refs, cache_bits, &histo);
- cur_entropy = VP8LHistogramEstimateBits(&histo) +
- kSmallPenaltyForLargeCache * cache_bits;
- if (cache_bits == 0 || cur_entropy < lowest_entropy) {
- *best_cache_bits = cache_bits;
- lowest_entropy = cur_entropy;
+
+ if (lz77_computed) {
+ // Transform refs_lz77 for the optimized cache_bits.
+ if (*cache_bits > 0) {
+ if (!BackwardRefsWithLocalCache(argb, *cache_bits, refs_lz77)) {
+ goto Error;
+ }
+ }
+ } else {
+ if (!BackwardReferencesLz77(width, height, argb, *cache_bits, quality,
+ 0 /* Low effort. */, hash_chain, refs_lz77)) {
+ goto Error;
}
}
- ok = 1;
+
+ if (!BackwardReferencesRle(width, height, argb, *cache_bits, refs_rle)) {
+ goto Error;
+ }
+
+ histo = VP8LAllocateHistogram(*cache_bits);
+ if (histo == NULL) goto Error;
+
+ {
+ // Evaluate LZ77 coding.
+ VP8LHistogramCreate(histo, refs_lz77, *cache_bits);
+ bit_cost_lz77 = VP8LHistogramEstimateBits(histo);
+ // Evaluate RLE coding.
+ VP8LHistogramCreate(histo, refs_rle, *cache_bits);
+ bit_cost_rle = VP8LHistogramEstimateBits(histo);
+ // Decide if LZ77 is useful.
+ lz77_is_useful = (bit_cost_lz77 < bit_cost_rle);
+ }
+
+ // Choose appropriate backward reference.
+ if (lz77_is_useful) {
+ // TraceBackwards is costly. Don't execute it at lower quality.
+ const int try_lz77_trace_backwards = (quality >= 25);
+ best = refs_lz77; // default guess: lz77 is better
+ if (try_lz77_trace_backwards) {
+ VP8LBackwardRefs* const refs_trace = refs_rle;
+ if (!VP8LBackwardRefsCopy(refs_lz77, refs_trace)) {
+ best = NULL;
+ goto Error;
+ }
+ if (BackwardReferencesTraceBackwards(width, height, argb, quality,
+ *cache_bits, hash_chain,
+ refs_trace)) {
+ double bit_cost_trace;
+ // Evaluate LZ77 coding.
+ VP8LHistogramCreate(histo, refs_trace, *cache_bits);
+ bit_cost_trace = VP8LHistogramEstimateBits(histo);
+ if (bit_cost_trace < bit_cost_lz77) {
+ best = refs_trace;
+ }
+ }
+ }
+ } else {
+ best = refs_rle;
+ }
+
+ BackwardReferences2DLocality(width, best);
+
Error:
- VP8LClearBackwardRefs(&refs);
- return ok;
+ VP8LFreeHistogram(histo);
+ return best;
+}
+
+VP8LBackwardRefs* VP8LGetBackwardReferences(
+ int width, int height, const uint32_t* const argb, int quality,
+ int low_effort, int* const cache_bits, VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs refs_array[2]) {
+ if (low_effort) {
+ return GetBackwardReferencesLowEffort(width, height, argb, quality,
+ cache_bits, hash_chain, refs_array);
+ } else {
+ return GetBackwardReferences(width, height, argb, quality, cache_bits,
+ hash_chain, refs_array);
+ }
}
diff --git a/drivers/webp/enc/backward_references.h b/drivers/webp/enc/backward_references.h
index 8006a56ba1..e410b06f7d 100644
--- a/drivers/webp/enc/backward_references.h
+++ b/drivers/webp/enc/backward_references.h
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Author: Jyrki Alakuijala (jyrki@google.com)
@@ -13,82 +15,15 @@
#include <assert.h>
#include <stdlib.h>
-#include "../types.h"
-#include "../format_constants.h"
+#include "webp/types.h"
+#include "webp/format_constants.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
-// The spec allows 11, we use 9 bits to reduce memory consumption in encoding.
-// Having 9 instead of 11 only removes about 0.25 % of compression density.
-#define MAX_COLOR_CACHE_BITS 9
-
-// Max ever number of codes we'll use:
-#define PIX_OR_COPY_CODES_MAX \
- (NUM_LITERAL_CODES + NUM_LENGTH_CODES + (1 << MAX_COLOR_CACHE_BITS))
-
-// -----------------------------------------------------------------------------
-// PrefixEncode()
-
-// use GNU builtins where available.
-#if defined(__GNUC__) && \
- ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4)
-static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
- return n == 0 ? -1 : 31 ^ __builtin_clz(n);
-}
-#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
-#include <intrin.h>
-#pragma intrinsic(_BitScanReverse)
-
-static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
- unsigned long first_set_bit;
- return _BitScanReverse(&first_set_bit, n) ? first_set_bit : -1;
-}
-#else
-static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
- int log = 0;
- uint32_t value = n;
- int i;
-
- if (value == 0) return -1;
- for (i = 4; i >= 0; --i) {
- const int shift = (1 << i);
- const uint32_t x = value >> shift;
- if (x != 0) {
- value = x;
- log += shift;
- }
- }
- return log;
-}
-#endif
-
-static WEBP_INLINE int VP8LBitsLog2Ceiling(uint32_t n) {
- const int floor = BitsLog2Floor(n);
- if (n == (n & ~(n - 1))) // zero or a power of two.
- return floor;
- else
- return floor + 1;
-}
-
-// Splitting of distance and length codes into prefixes and
-// extra bits. The prefixes are encoded with an entropy code
-// while the extra bits are stored just as normal bits.
-static WEBP_INLINE void PrefixEncode(int distance, int* const code,
- int* const extra_bits_count,
- int* const extra_bits_value) {
- // Collect the two most significant bits where the highest bit is 1.
- const int highest_bit = BitsLog2Floor(--distance);
- // & 0x3f is to make behavior well defined when highest_bit
- // does not exist or is the least significant bit.
- const int second_highest_bit =
- (distance >> ((highest_bit - 1) & 0x3f)) & 1;
- *extra_bits_count = (highest_bit > 0) ? (highest_bit - 1) : 0;
- *extra_bits_value = distance & ((1 << *extra_bits_count) - 1);
- *code = (highest_bit > 0) ? (2 * highest_bit + second_highest_bit)
- : (highest_bit == 0) ? 1 : 0;
-}
+// The maximum allowed limit is 11.
+#define MAX_COLOR_CACHE_BITS 10
// -----------------------------------------------------------------------------
// PixOrCopy
@@ -173,39 +108,94 @@ static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) {
}
// -----------------------------------------------------------------------------
-// VP8LBackwardRefs
+// VP8LHashChain
+
+#define HASH_BITS 18
+#define HASH_SIZE (1 << HASH_BITS)
+
+typedef struct VP8LHashChain VP8LHashChain;
+struct VP8LHashChain {
+ // Stores the most recently added position with the given hash value.
+ int32_t hash_to_first_index_[HASH_SIZE];
+ // chain_[pos] stores the previous position with the same hash value
+ // for every pixel in the image.
+ int32_t* chain_;
+ // This is the maximum size of the hash_chain that can be constructed.
+ // Typically this is the pixel count (width x height) for a given image.
+ int size_;
+};
-typedef struct {
- PixOrCopy* refs;
- int size; // currently used
- int max_size; // maximum capacity
-} VP8LBackwardRefs;
+// Must be called first, to set size.
+int VP8LHashChainInit(VP8LHashChain* const p, int size);
+void VP8LHashChainClear(VP8LHashChain* const p); // release memory
-// Initialize the object. Must be called first. 'refs' can be NULL.
-void VP8LInitBackwardRefs(VP8LBackwardRefs* const refs);
+// -----------------------------------------------------------------------------
+// VP8LBackwardRefs (block-based backward-references storage)
+
+// maximum number of reference blocks the image will be segmented into
+#define MAX_REFS_BLOCK_PER_IMAGE 16
+
+typedef struct PixOrCopyBlock PixOrCopyBlock; // forward declaration
+typedef struct VP8LBackwardRefs VP8LBackwardRefs;
+
+// Container for blocks chain
+struct VP8LBackwardRefs {
+ int block_size_; // common block-size
+ int error_; // set to true if some memory error occurred
+ PixOrCopyBlock* refs_; // list of currently used blocks
+ PixOrCopyBlock** tail_; // for list recycling
+ PixOrCopyBlock* free_blocks_; // free-list
+ PixOrCopyBlock* last_block_; // used for adding new refs (internal)
+};
-// Release memory and re-initialize the object. 'refs' can be NULL.
-void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs);
+// Initialize the object. 'block_size' is the common block size to store
+// references (typically, width * height / MAX_REFS_BLOCK_PER_IMAGE).
+void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size);
+// Release memory for backward references.
+void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs);
+// Copies the 'src' backward refs to the 'dst'. Returns 0 in case of error.
+int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src,
+ VP8LBackwardRefs* const dst);
-// Allocate 'max_size' references. Returns false in case of memory error.
-int VP8LBackwardRefsAlloc(VP8LBackwardRefs* const refs, int max_size);
+// Cursor for iterating on references content
+typedef struct {
+ // public:
+ PixOrCopy* cur_pos; // current position
+ // private:
+ PixOrCopyBlock* cur_block_; // current block in the refs list
+ const PixOrCopy* last_pos_; // sentinel for switching to next block
+} VP8LRefsCursor;
+
+// Returns a cursor positioned at the beginning of the references list.
+VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs);
+// Returns true if cursor is pointing at a valid position.
+static WEBP_INLINE int VP8LRefsCursorOk(const VP8LRefsCursor* const c) {
+ return (c->cur_pos != NULL);
+}
+// Move to next block of references. Internal, not to be called directly.
+void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c);
+// Move to next position, or NULL. Should not be called if !VP8LRefsCursorOk().
+static WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) {
+ assert(c != NULL);
+ assert(VP8LRefsCursorOk(c));
+ if (++c->cur_pos == c->last_pos_) VP8LRefsCursorNextBlock(c);
+}
// -----------------------------------------------------------------------------
// Main entry points
// Evaluates best possible backward references for specified quality.
-// Further optimize for 2D locality if use_2d_locality flag is set.
-int VP8LGetBackwardReferences(int width, int height,
- const uint32_t* const argb,
- int quality, int cache_bits, int use_2d_locality,
- VP8LBackwardRefs* const best);
-
-// Produce an estimate for a good color cache size for the image.
-int VP8LCalculateEstimateForCacheSize(const uint32_t* const argb,
- int xsize, int ysize,
- int* const best_cache_bits);
-
-#if defined(__cplusplus) || defined(c_plusplus)
+// The input cache_bits to 'VP8LGetBackwardReferences' sets the maximum cache
+// bits to use (passing 0 implies disabling the local color cache).
+// The optimal cache bits is evaluated and set for the *cache_bits parameter.
+// The return value is the pointer to the best of the two backward refs viz,
+// refs[0] or refs[1].
+VP8LBackwardRefs* VP8LGetBackwardReferences(
+ int width, int height, const uint32_t* const argb, int quality,
+ int low_effort, int* const cache_bits, VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs refs[2]);
+
+#ifdef __cplusplus
}
#endif
diff --git a/drivers/webp/enc/config.c b/drivers/webp/enc/config.c
index 4136f6c227..8fd2276cb5 100644
--- a/drivers/webp/enc/config.c
+++ b/drivers/webp/enc/config.c
@@ -1,19 +1,17 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Coding tools configuration
//
// Author: Skal (pascal.massimino@gmail.com)
-#include "../encode.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+#include "webp/encode.h"
//------------------------------------------------------------------------------
// WebPConfig
@@ -31,9 +29,9 @@ int WebPConfigInitInternal(WebPConfig* config,
config->target_PSNR = 0.;
config->method = 4;
config->sns_strength = 50;
- config->filter_strength = 20; // default: light filtering
+ config->filter_strength = 60; // mid-filtering
config->filter_sharpness = 0;
- config->filter_type = 0; // default: simple
+ config->filter_type = 1; // default: strong (so U/V is filtered too)
config->partitions = 0;
config->segments = 4;
config->pass = 1;
@@ -45,7 +43,15 @@ int WebPConfigInitInternal(WebPConfig* config,
config->alpha_filtering = 1;
config->alpha_quality = 100;
config->lossless = 0;
+ config->exact = 0;
config->image_hint = WEBP_HINT_DEFAULT;
+ config->emulate_jpeg_size = 0;
+ config->thread_level = 0;
+ config->low_memory = 0;
+ config->near_lossless = 100;
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ config->delta_palettization = 0;
+#endif // WEBP_EXPERIMENTAL_FEATURES
// TODO(skal): tune.
switch (preset) {
@@ -53,11 +59,13 @@ int WebPConfigInitInternal(WebPConfig* config,
config->sns_strength = 80;
config->filter_sharpness = 4;
config->filter_strength = 35;
+ config->preprocessing &= ~2; // no dithering
break;
case WEBP_PRESET_PHOTO:
config->sns_strength = 80;
config->filter_sharpness = 3;
config->filter_strength = 30;
+ config->preprocessing |= 2;
break;
case WEBP_PRESET_DRAWING:
config->sns_strength = 25;
@@ -67,10 +75,12 @@ int WebPConfigInitInternal(WebPConfig* config,
case WEBP_PRESET_ICON:
config->sns_strength = 0;
config->filter_strength = 0; // disable filtering to retain sharpness
+ config->preprocessing &= ~2; // no dithering
break;
case WEBP_PRESET_TEXT:
config->sns_strength = 0;
config->filter_strength = 0; // disable filtering to retain sharpness
+ config->preprocessing &= ~2; // no dithering
config->segments = 2;
break;
case WEBP_PRESET_DEFAULT:
@@ -106,7 +116,7 @@ int WebPValidateConfig(const WebPConfig* config) {
return 0;
if (config->show_compressed < 0 || config->show_compressed > 1)
return 0;
- if (config->preprocessing < 0 || config->preprocessing > 1)
+ if (config->preprocessing < 0 || config->preprocessing > 7)
return 0;
if (config->partitions < 0 || config->partitions > 3)
return 0;
@@ -120,13 +130,44 @@ int WebPValidateConfig(const WebPConfig* config) {
return 0;
if (config->lossless < 0 || config->lossless > 1)
return 0;
+ if (config->near_lossless < 0 || config->near_lossless > 100)
+ return 0;
if (config->image_hint >= WEBP_HINT_LAST)
return 0;
+ if (config->emulate_jpeg_size < 0 || config->emulate_jpeg_size > 1)
+ return 0;
+ if (config->thread_level < 0 || config->thread_level > 1)
+ return 0;
+ if (config->low_memory < 0 || config->low_memory > 1)
+ return 0;
+ if (config->exact < 0 || config->exact > 1)
+ return 0;
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ if (config->delta_palettization < 0 || config->delta_palettization > 1)
+ return 0;
+#endif // WEBP_EXPERIMENTAL_FEATURES
return 1;
}
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
+#define MAX_LEVEL 9
+
+// Mapping between -z level and -m / -q parameter settings.
+static const struct {
+ uint8_t method_;
+ uint8_t quality_;
+} kLosslessPresets[MAX_LEVEL + 1] = {
+ { 0, 0 }, { 1, 20 }, { 2, 25 }, { 3, 30 }, { 3, 50 },
+ { 4, 50 }, { 4, 75 }, { 4, 90 }, { 5, 90 }, { 6, 100 }
+};
+
+int WebPConfigLosslessPreset(WebPConfig* config, int level) {
+ if (config == NULL || level < 0 || level > MAX_LEVEL) return 0;
+ config->lossless = 1;
+ config->method = kLosslessPresets[level].method_;
+ config->quality = kLosslessPresets[level].quality_;
+ return 1;
+}
+
+//------------------------------------------------------------------------------
diff --git a/drivers/webp/enc/cost.c b/drivers/webp/enc/cost.c
index 92e0cc713c..ae7fe01388 100644
--- a/drivers/webp/enc/cost.c
+++ b/drivers/webp/enc/cost.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Cost tables for level and modes
@@ -11,42 +13,6 @@
#include "./cost.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// Boolean-cost cost table
-
-const uint16_t VP8EntropyCost[256] = {
- 1792, 1792, 1792, 1536, 1536, 1408, 1366, 1280, 1280, 1216,
- 1178, 1152, 1110, 1076, 1061, 1024, 1024, 992, 968, 951,
- 939, 911, 896, 878, 871, 854, 838, 820, 811, 794,
- 786, 768, 768, 752, 740, 732, 720, 709, 704, 690,
- 683, 672, 666, 655, 647, 640, 631, 622, 615, 607,
- 598, 592, 586, 576, 572, 564, 559, 555, 547, 541,
- 534, 528, 522, 512, 512, 504, 500, 494, 488, 483,
- 477, 473, 467, 461, 458, 452, 448, 443, 438, 434,
- 427, 424, 419, 415, 410, 406, 403, 399, 394, 390,
- 384, 384, 377, 374, 370, 366, 362, 359, 355, 351,
- 347, 342, 342, 336, 333, 330, 326, 323, 320, 316,
- 312, 308, 305, 302, 299, 296, 293, 288, 287, 283,
- 280, 277, 274, 272, 268, 266, 262, 256, 256, 256,
- 251, 248, 245, 242, 240, 237, 234, 232, 228, 226,
- 223, 221, 218, 216, 214, 211, 208, 205, 203, 201,
- 198, 196, 192, 191, 188, 187, 183, 181, 179, 176,
- 175, 171, 171, 168, 165, 163, 160, 159, 156, 154,
- 152, 150, 148, 146, 144, 142, 139, 138, 135, 133,
- 131, 128, 128, 125, 123, 121, 119, 117, 115, 113,
- 111, 110, 107, 105, 103, 102, 100, 98, 96, 94,
- 92, 91, 89, 86, 86, 83, 82, 80, 77, 76,
- 74, 73, 71, 69, 67, 66, 64, 63, 61, 59,
- 57, 55, 54, 52, 51, 49, 47, 46, 44, 43,
- 41, 40, 38, 36, 35, 33, 32, 30, 29, 27,
- 25, 24, 22, 21, 19, 18, 16, 15, 13, 12,
- 10, 9, 7, 6, 4, 3
-};
-
//------------------------------------------------------------------------------
// Level cost tables
@@ -73,267 +39,6 @@ const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2] = {
{0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x153}
};
-// fixed costs for coding levels, deduce from the coding tree.
-// This is only the part that doesn't depend on the probability state.
-const uint16_t VP8LevelFixedCosts[2048] = {
- 0, 256, 256, 256, 256, 432, 618, 630,
- 731, 640, 640, 828, 901, 948, 1021, 1101,
- 1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202,
- 1245, 1275, 1318, 1337, 1380, 1410, 1453, 1497,
- 1540, 1570, 1613, 1280, 1295, 1317, 1332, 1358,
- 1373, 1395, 1410, 1454, 1469, 1491, 1506, 1532,
- 1547, 1569, 1584, 1601, 1616, 1638, 1653, 1679,
- 1694, 1716, 1731, 1775, 1790, 1812, 1827, 1853,
- 1868, 1890, 1905, 1727, 1733, 1742, 1748, 1759,
- 1765, 1774, 1780, 1800, 1806, 1815, 1821, 1832,
- 1838, 1847, 1853, 1878, 1884, 1893, 1899, 1910,
- 1916, 1925, 1931, 1951, 1957, 1966, 1972, 1983,
- 1989, 1998, 2004, 2027, 2033, 2042, 2048, 2059,
- 2065, 2074, 2080, 2100, 2106, 2115, 2121, 2132,
- 2138, 2147, 2153, 2178, 2184, 2193, 2199, 2210,
- 2216, 2225, 2231, 2251, 2257, 2266, 2272, 2283,
- 2289, 2298, 2304, 2168, 2174, 2183, 2189, 2200,
- 2206, 2215, 2221, 2241, 2247, 2256, 2262, 2273,
- 2279, 2288, 2294, 2319, 2325, 2334, 2340, 2351,
- 2357, 2366, 2372, 2392, 2398, 2407, 2413, 2424,
- 2430, 2439, 2445, 2468, 2474, 2483, 2489, 2500,
- 2506, 2515, 2521, 2541, 2547, 2556, 2562, 2573,
- 2579, 2588, 2594, 2619, 2625, 2634, 2640, 2651,
- 2657, 2666, 2672, 2692, 2698, 2707, 2713, 2724,
- 2730, 2739, 2745, 2540, 2546, 2555, 2561, 2572,
- 2578, 2587, 2593, 2613, 2619, 2628, 2634, 2645,
- 2651, 2660, 2666, 2691, 2697, 2706, 2712, 2723,
- 2729, 2738, 2744, 2764, 2770, 2779, 2785, 2796,
- 2802, 2811, 2817, 2840, 2846, 2855, 2861, 2872,
- 2878, 2887, 2893, 2913, 2919, 2928, 2934, 2945,
- 2951, 2960, 2966, 2991, 2997, 3006, 3012, 3023,
- 3029, 3038, 3044, 3064, 3070, 3079, 3085, 3096,
- 3102, 3111, 3117, 2981, 2987, 2996, 3002, 3013,
- 3019, 3028, 3034, 3054, 3060, 3069, 3075, 3086,
- 3092, 3101, 3107, 3132, 3138, 3147, 3153, 3164,
- 3170, 3179, 3185, 3205, 3211, 3220, 3226, 3237,
- 3243, 3252, 3258, 3281, 3287, 3296, 3302, 3313,
- 3319, 3328, 3334, 3354, 3360, 3369, 3375, 3386,
- 3392, 3401, 3407, 3432, 3438, 3447, 3453, 3464,
- 3470, 3479, 3485, 3505, 3511, 3520, 3526, 3537,
- 3543, 3552, 3558, 2816, 2822, 2831, 2837, 2848,
- 2854, 2863, 2869, 2889, 2895, 2904, 2910, 2921,
- 2927, 2936, 2942, 2967, 2973, 2982, 2988, 2999,
- 3005, 3014, 3020, 3040, 3046, 3055, 3061, 3072,
- 3078, 3087, 3093, 3116, 3122, 3131, 3137, 3148,
- 3154, 3163, 3169, 3189, 3195, 3204, 3210, 3221,
- 3227, 3236, 3242, 3267, 3273, 3282, 3288, 3299,
- 3305, 3314, 3320, 3340, 3346, 3355, 3361, 3372,
- 3378, 3387, 3393, 3257, 3263, 3272, 3278, 3289,
- 3295, 3304, 3310, 3330, 3336, 3345, 3351, 3362,
- 3368, 3377, 3383, 3408, 3414, 3423, 3429, 3440,
- 3446, 3455, 3461, 3481, 3487, 3496, 3502, 3513,
- 3519, 3528, 3534, 3557, 3563, 3572, 3578, 3589,
- 3595, 3604, 3610, 3630, 3636, 3645, 3651, 3662,
- 3668, 3677, 3683, 3708, 3714, 3723, 3729, 3740,
- 3746, 3755, 3761, 3781, 3787, 3796, 3802, 3813,
- 3819, 3828, 3834, 3629, 3635, 3644, 3650, 3661,
- 3667, 3676, 3682, 3702, 3708, 3717, 3723, 3734,
- 3740, 3749, 3755, 3780, 3786, 3795, 3801, 3812,
- 3818, 3827, 3833, 3853, 3859, 3868, 3874, 3885,
- 3891, 3900, 3906, 3929, 3935, 3944, 3950, 3961,
- 3967, 3976, 3982, 4002, 4008, 4017, 4023, 4034,
- 4040, 4049, 4055, 4080, 4086, 4095, 4101, 4112,
- 4118, 4127, 4133, 4153, 4159, 4168, 4174, 4185,
- 4191, 4200, 4206, 4070, 4076, 4085, 4091, 4102,
- 4108, 4117, 4123, 4143, 4149, 4158, 4164, 4175,
- 4181, 4190, 4196, 4221, 4227, 4236, 4242, 4253,
- 4259, 4268, 4274, 4294, 4300, 4309, 4315, 4326,
- 4332, 4341, 4347, 4370, 4376, 4385, 4391, 4402,
- 4408, 4417, 4423, 4443, 4449, 4458, 4464, 4475,
- 4481, 4490, 4496, 4521, 4527, 4536, 4542, 4553,
- 4559, 4568, 4574, 4594, 4600, 4609, 4615, 4626,
- 4632, 4641, 4647, 3515, 3521, 3530, 3536, 3547,
- 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620,
- 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698,
- 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771,
- 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847,
- 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920,
- 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998,
- 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071,
- 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988,
- 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061,
- 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139,
- 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212,
- 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288,
- 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361,
- 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439,
- 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512,
- 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360,
- 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433,
- 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511,
- 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584,
- 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660,
- 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733,
- 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811,
- 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884,
- 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801,
- 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874,
- 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952,
- 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025,
- 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101,
- 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174,
- 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252,
- 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325,
- 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636,
- 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709,
- 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787,
- 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860,
- 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936,
- 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009,
- 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087,
- 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160,
- 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077,
- 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150,
- 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228,
- 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301,
- 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377,
- 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450,
- 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528,
- 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601,
- 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449,
- 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522,
- 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600,
- 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673,
- 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749,
- 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822,
- 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900,
- 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973,
- 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890,
- 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963,
- 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041,
- 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114,
- 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190,
- 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263,
- 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341,
- 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414,
- 6420, 6429, 6435, 3515, 3521, 3530, 3536, 3547,
- 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620,
- 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698,
- 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771,
- 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847,
- 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920,
- 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998,
- 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071,
- 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988,
- 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061,
- 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139,
- 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212,
- 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288,
- 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361,
- 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439,
- 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512,
- 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360,
- 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433,
- 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511,
- 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584,
- 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660,
- 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733,
- 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811,
- 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884,
- 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801,
- 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874,
- 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952,
- 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025,
- 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101,
- 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174,
- 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252,
- 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325,
- 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636,
- 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709,
- 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787,
- 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860,
- 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936,
- 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009,
- 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087,
- 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160,
- 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077,
- 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150,
- 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228,
- 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301,
- 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377,
- 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450,
- 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528,
- 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601,
- 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449,
- 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522,
- 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600,
- 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673,
- 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749,
- 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822,
- 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900,
- 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973,
- 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890,
- 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963,
- 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041,
- 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114,
- 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190,
- 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263,
- 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341,
- 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414,
- 6420, 6429, 6435, 5303, 5309, 5318, 5324, 5335,
- 5341, 5350, 5356, 5376, 5382, 5391, 5397, 5408,
- 5414, 5423, 5429, 5454, 5460, 5469, 5475, 5486,
- 5492, 5501, 5507, 5527, 5533, 5542, 5548, 5559,
- 5565, 5574, 5580, 5603, 5609, 5618, 5624, 5635,
- 5641, 5650, 5656, 5676, 5682, 5691, 5697, 5708,
- 5714, 5723, 5729, 5754, 5760, 5769, 5775, 5786,
- 5792, 5801, 5807, 5827, 5833, 5842, 5848, 5859,
- 5865, 5874, 5880, 5744, 5750, 5759, 5765, 5776,
- 5782, 5791, 5797, 5817, 5823, 5832, 5838, 5849,
- 5855, 5864, 5870, 5895, 5901, 5910, 5916, 5927,
- 5933, 5942, 5948, 5968, 5974, 5983, 5989, 6000,
- 6006, 6015, 6021, 6044, 6050, 6059, 6065, 6076,
- 6082, 6091, 6097, 6117, 6123, 6132, 6138, 6149,
- 6155, 6164, 6170, 6195, 6201, 6210, 6216, 6227,
- 6233, 6242, 6248, 6268, 6274, 6283, 6289, 6300,
- 6306, 6315, 6321, 6116, 6122, 6131, 6137, 6148,
- 6154, 6163, 6169, 6189, 6195, 6204, 6210, 6221,
- 6227, 6236, 6242, 6267, 6273, 6282, 6288, 6299,
- 6305, 6314, 6320, 6340, 6346, 6355, 6361, 6372,
- 6378, 6387, 6393, 6416, 6422, 6431, 6437, 6448,
- 6454, 6463, 6469, 6489, 6495, 6504, 6510, 6521,
- 6527, 6536, 6542, 6567, 6573, 6582, 6588, 6599,
- 6605, 6614, 6620, 6640, 6646, 6655, 6661, 6672,
- 6678, 6687, 6693, 6557, 6563, 6572, 6578, 6589,
- 6595, 6604, 6610, 6630, 6636, 6645, 6651, 6662,
- 6668, 6677, 6683, 6708, 6714, 6723, 6729, 6740,
- 6746, 6755, 6761, 6781, 6787, 6796, 6802, 6813,
- 6819, 6828, 6834, 6857, 6863, 6872, 6878, 6889,
- 6895, 6904, 6910, 6930, 6936, 6945, 6951, 6962,
- 6968, 6977, 6983, 7008, 7014, 7023, 7029, 7040,
- 7046, 7055, 7061, 7081, 7087, 7096, 7102, 7113,
- 7119, 7128, 7134, 6392, 6398, 6407, 6413, 6424,
- 6430, 6439, 6445, 6465, 6471, 6480, 6486, 6497,
- 6503, 6512, 6518, 6543, 6549, 6558, 6564, 6575,
- 6581, 6590, 6596, 6616, 6622, 6631, 6637, 6648,
- 6654, 6663, 6669, 6692, 6698, 6707, 6713, 6724,
- 6730, 6739, 6745, 6765, 6771, 6780, 6786, 6797,
- 6803, 6812, 6818, 6843, 6849, 6858, 6864, 6875,
- 6881, 6890, 6896, 6916, 6922, 6931, 6937, 6948,
- 6954, 6963, 6969, 6833, 6839, 6848, 6854, 6865,
- 6871, 6880, 6886, 6906, 6912, 6921, 6927, 6938,
- 6944, 6953, 6959, 6984, 6990, 6999, 7005, 7016,
- 7022, 7031, 7037, 7057, 7063, 7072, 7078, 7089,
- 7095, 7104, 7110, 7133, 7139, 7148, 7154, 7165,
- 7171, 7180, 7186, 7206, 7212, 7221, 7227, 7238,
- 7244, 7253, 7259, 7284, 7290, 7299, 7305, 7316,
- 7322, 7331, 7337, 7357, 7363, 7372, 7378, 7389,
- 7395, 7404, 7410, 7205, 7211, 7220, 7226, 7237,
- 7243, 7252, 7258, 7278, 7284, 7293, 7299, 7310,
- 7316, 7325, 7331, 7356, 7362, 7371, 7377, 7388,
- 7394, 7403, 7409, 7429, 7435, 7444, 7450, 7461,
- 7467, 7476, 7482, 7505, 7511, 7520, 7526, 7537,
- 7543, 7552, 7558, 7578, 7584, 7593, 7599, 7610,
- 7616, 7625, 7631, 7656, 7662, 7671, 7677, 7688,
- 7694, 7703, 7709, 7729, 7735, 7744, 7750, 7761
-};
-
static int VariableLevelCost(int level, const uint8_t probas[NUM_PROBAS]) {
int pattern = VP8LevelCodes[level - 1][0];
int bits = VP8LevelCodes[level - 1][1];
@@ -352,19 +57,21 @@ static int VariableLevelCost(int level, const uint8_t probas[NUM_PROBAS]) {
//------------------------------------------------------------------------------
// Pre-calc level costs once for all
-void VP8CalculateLevelCosts(VP8Proba* const proba) {
+void VP8CalculateLevelCosts(VP8EncProba* const proba) {
int ctype, band, ctx;
if (!proba->dirty_) return; // nothing to do.
for (ctype = 0; ctype < NUM_TYPES; ++ctype) {
+ int n;
for (band = 0; band < NUM_BANDS; ++band) {
- for(ctx = 0; ctx < NUM_CTX; ++ctx) {
+ for (ctx = 0; ctx < NUM_CTX; ++ctx) {
const uint8_t* const p = proba->coeffs_[ctype][band][ctx];
uint16_t* const table = proba->level_cost_[ctype][band][ctx];
- const int cost_base = VP8BitCost(1, p[1]);
+ const int cost0 = (ctx > 0) ? VP8BitCost(1, p[0]) : 0;
+ const int cost_base = VP8BitCost(1, p[1]) + cost0;
int v;
- table[0] = VP8BitCost(0, p[1]);
+ table[0] = VP8BitCost(0, p[1]) + cost0;
for (v = 1; v <= MAX_VARIABLE_LEVEL; ++v) {
table[v] = cost_base + VariableLevelCost(v, p);
}
@@ -372,6 +79,12 @@ void VP8CalculateLevelCosts(VP8Proba* const proba) {
// actually constant.
}
}
+ for (n = 0; n < 16; ++n) { // replicate bands. We don't need to sentinel.
+ for (ctx = 0; ctx < NUM_CTX; ++ctx) {
+ proba->remapped_costs_[ctype][n][ctx] =
+ proba->level_cost_[ctype][VP8EncBands[n]][ctx];
+ }
+ }
}
proba->dirty_ = 0;
}
@@ -385,110 +98,257 @@ const uint16_t VP8FixedCostsUV[4] = { 302, 984, 439, 642 };
// note: these values include the fixed VP8BitCost(1, 145) mode selection cost.
const uint16_t VP8FixedCostsI16[4] = { 663, 919, 872, 919 };
const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES] = {
- { { 251, 1362, 1934, 2085, 2314, 2230, 1839, 1988, 2437, 2348 },
- { 403, 680, 1507, 1519, 2060, 2005, 1992, 1914, 1924, 1733 },
- { 353, 1121, 973, 1895, 2060, 1787, 1671, 1516, 2012, 1868 },
- { 770, 852, 1581, 632, 1393, 1780, 1823, 1936, 1074, 1218 },
- { 510, 1270, 1467, 1319, 847, 1279, 1792, 2094, 1080, 1353 },
- { 488, 1322, 918, 1573, 1300, 883, 1814, 1752, 1756, 1502 },
- { 425, 992, 1820, 1514, 1843, 2440, 937, 1771, 1924, 1129 },
- { 363, 1248, 1257, 1970, 2194, 2385, 1569, 953, 1951, 1601 },
- { 723, 1257, 1631, 964, 963, 1508, 1697, 1824, 671, 1418 },
- { 635, 1038, 1573, 930, 1673, 1413, 1410, 1687, 1410, 749 } },
- { { 451, 613, 1345, 1702, 1870, 1716, 1728, 1766, 2190, 2310 },
- { 678, 453, 1171, 1443, 1925, 1831, 2045, 1781, 1887, 1602 },
- { 711, 666, 674, 1718, 1910, 1493, 1775, 1193, 2325, 2325 },
- { 883, 854, 1583, 542, 1800, 1878, 1664, 2149, 1207, 1087 },
- { 669, 994, 1248, 1122, 949, 1179, 1376, 1729, 1070, 1244 },
- { 715, 1026, 715, 1350, 1430, 930, 1717, 1296, 1479, 1479 },
- { 544, 841, 1656, 1450, 2094, 3883, 1010, 1759, 2076, 809 },
- { 610, 855, 957, 1553, 2067, 1561, 1704, 824, 2066, 1226 },
- { 833, 960, 1416, 819, 1277, 1619, 1501, 1617, 757, 1182 },
- { 711, 964, 1252, 879, 1441, 1828, 1508, 1636, 1594, 734 } },
- { { 605, 764, 734, 1713, 1747, 1192, 1819, 1353, 1877, 2392 },
- { 866, 641, 586, 1622, 2072, 1431, 1888, 1346, 2189, 1764 },
- { 901, 851, 456, 2165, 2281, 1405, 1739, 1193, 2183, 2443 },
- { 770, 1045, 952, 1078, 1342, 1191, 1436, 1063, 1303, 995 },
- { 901, 1086, 727, 1170, 884, 1105, 1267, 1401, 1739, 1337 },
- { 951, 1162, 595, 1488, 1388, 703, 1790, 1366, 2057, 1724 },
- { 534, 986, 1273, 1987, 3273, 1485, 1024, 1399, 1583, 866 },
- { 699, 1182, 695, 1978, 1726, 1986, 1326, 714, 1750, 1672 },
- { 951, 1217, 1209, 920, 1062, 1441, 1548, 999, 952, 932 },
- { 733, 1284, 784, 1256, 1557, 1098, 1257, 1357, 1414, 908 } },
- { { 316, 1075, 1653, 1220, 2145, 2051, 1730, 2131, 1884, 1790 },
- { 745, 516, 1404, 894, 1599, 2375, 2013, 2105, 1475, 1381 },
- { 516, 729, 1088, 1319, 1637, 3426, 1636, 1275, 1531, 1453 },
- { 894, 943, 2138, 468, 1704, 2259, 2069, 1763, 1266, 1158 },
- { 605, 1025, 1235, 871, 1170, 1767, 1493, 1500, 1104, 1258 },
- { 739, 826, 1207, 1151, 1412, 846, 1305, 2726, 1014, 1569 },
- { 558, 825, 1820, 1398, 3344, 1556, 1218, 1550, 1228, 878 },
- { 429, 951, 1089, 1816, 3861, 3861, 1556, 969, 1568, 1828 },
- { 883, 961, 1752, 769, 1468, 1810, 2081, 2346, 613, 1298 },
- { 803, 895, 1372, 641, 1303, 1708, 1686, 1700, 1306, 1033 } },
- { { 439, 1267, 1270, 1579, 963, 1193, 1723, 1729, 1198, 1993 },
- { 705, 725, 1029, 1153, 1176, 1103, 1821, 1567, 1259, 1574 },
- { 723, 859, 802, 1253, 972, 1202, 1407, 1665, 1520, 1674 },
- { 894, 960, 1254, 887, 1052, 1607, 1344, 1349, 865, 1150 },
- { 833, 1312, 1337, 1205, 572, 1288, 1414, 1529, 1088, 1430 },
- { 842, 1279, 1068, 1861, 862, 688, 1861, 1630, 1039, 1381 },
- { 766, 938, 1279, 1546, 3338, 1550, 1031, 1542, 1288, 640 },
- { 715, 1090, 835, 1609, 1100, 1100, 1603, 1019, 1102, 1617 },
- { 894, 1813, 1500, 1188, 789, 1194, 1491, 1919, 617, 1333 },
- { 610, 1076, 1644, 1281, 1283, 975, 1179, 1688, 1434, 889 } },
- { { 544, 971, 1146, 1849, 1221, 740, 1857, 1621, 1683, 2430 },
- { 723, 705, 961, 1371, 1426, 821, 2081, 2079, 1839, 1380 },
- { 783, 857, 703, 2145, 1419, 814, 1791, 1310, 1609, 2206 },
- { 997, 1000, 1153, 792, 1229, 1162, 1810, 1418, 942, 979 },
- { 901, 1226, 883, 1289, 793, 715, 1904, 1649, 1319, 3108 },
- { 979, 1478, 782, 2216, 1454, 455, 3092, 1591, 1997, 1664 },
- { 663, 1110, 1504, 1114, 1522, 3311, 676, 1522, 1530, 1024 },
- { 605, 1138, 1153, 1314, 1569, 1315, 1157, 804, 1574, 1320 },
- { 770, 1216, 1218, 1227, 869, 1384, 1232, 1375, 834, 1239 },
- { 775, 1007, 843, 1216, 1225, 1074, 2527, 1479, 1149, 975 } },
- { { 477, 817, 1309, 1439, 1708, 1454, 1159, 1241, 1945, 1672 },
- { 577, 796, 1112, 1271, 1618, 1458, 1087, 1345, 1831, 1265 },
- { 663, 776, 753, 1940, 1690, 1690, 1227, 1097, 3149, 1361 },
- { 766, 1299, 1744, 1161, 1565, 1106, 1045, 1230, 1232, 707 },
- { 915, 1026, 1404, 1182, 1184, 851, 1428, 2425, 1043, 789 },
- { 883, 1456, 790, 1082, 1086, 985, 1083, 1484, 1238, 1160 },
- { 507, 1345, 2261, 1995, 1847, 3636, 653, 1761, 2287, 933 },
- { 553, 1193, 1470, 2057, 2059, 2059, 833, 779, 2058, 1263 },
- { 766, 1275, 1515, 1039, 957, 1554, 1286, 1540, 1289, 705 },
- { 499, 1378, 1496, 1385, 1850, 1850, 1044, 2465, 1515, 720 } },
- { { 553, 930, 978, 2077, 1968, 1481, 1457, 761, 1957, 2362 },
- { 694, 864, 905, 1720, 1670, 1621, 1429, 718, 2125, 1477 },
- { 699, 968, 658, 3190, 2024, 1479, 1865, 750, 2060, 2320 },
- { 733, 1308, 1296, 1062, 1576, 1322, 1062, 1112, 1172, 816 },
- { 920, 927, 1052, 939, 947, 1156, 1152, 1073, 3056, 1268 },
- { 723, 1534, 711, 1547, 1294, 892, 1553, 928, 1815, 1561 },
- { 663, 1366, 1583, 2111, 1712, 3501, 522, 1155, 2130, 1133 },
- { 614, 1731, 1188, 2343, 1944, 3733, 1287, 487, 3546, 1758 },
- { 770, 1585, 1312, 826, 884, 2673, 1185, 1006, 1195, 1195 },
- { 758, 1333, 1273, 1023, 1621, 1162, 1351, 833, 1479, 862 } },
- { { 376, 1193, 1446, 1149, 1545, 1577, 1870, 1789, 1175, 1823 },
- { 803, 633, 1136, 1058, 1350, 1323, 1598, 2247, 1072, 1252 },
- { 614, 1048, 943, 981, 1152, 1869, 1461, 1020, 1618, 1618 },
- { 1107, 1085, 1282, 592, 1779, 1933, 1648, 2403, 691, 1246 },
- { 851, 1309, 1223, 1243, 895, 1593, 1792, 2317, 627, 1076 },
- { 770, 1216, 1030, 1125, 921, 981, 1629, 1131, 1049, 1646 },
- { 626, 1469, 1456, 1081, 1489, 3278, 981, 1232, 1498, 733 },
- { 617, 1201, 812, 1220, 1476, 1476, 1478, 970, 1228, 1488 },
- { 1179, 1393, 1540, 999, 1243, 1503, 1916, 1925, 414, 1614 },
- { 943, 1088, 1490, 682, 1112, 1372, 1756, 1505, 966, 966 } },
- { { 322, 1142, 1589, 1396, 2144, 1859, 1359, 1925, 2084, 1518 },
- { 617, 625, 1241, 1234, 2121, 1615, 1524, 1858, 1720, 1004 },
- { 553, 851, 786, 1299, 1452, 1560, 1372, 1561, 1967, 1713 },
- { 770, 977, 1396, 568, 1893, 1639, 1540, 2108, 1430, 1013 },
- { 684, 1120, 1375, 982, 930, 2719, 1638, 1643, 933, 993 },
- { 553, 1103, 996, 1356, 1361, 1005, 1507, 1761, 1184, 1268 },
- { 419, 1247, 1537, 1554, 1817, 3606, 1026, 1666, 1829, 923 },
- { 439, 1139, 1101, 1257, 3710, 1922, 1205, 1040, 1931, 1529 },
- { 979, 935, 1269, 847, 1202, 1286, 1530, 1535, 827, 1036 },
- { 516, 1378, 1569, 1110, 1798, 1798, 1198, 2199, 1543, 712 } },
+ { { 40, 1151, 1723, 1874, 2103, 2019, 1628, 1777, 2226, 2137 },
+ { 192, 469, 1296, 1308, 1849, 1794, 1781, 1703, 1713, 1522 },
+ { 142, 910, 762, 1684, 1849, 1576, 1460, 1305, 1801, 1657 },
+ { 559, 641, 1370, 421, 1182, 1569, 1612, 1725, 863, 1007 },
+ { 299, 1059, 1256, 1108, 636, 1068, 1581, 1883, 869, 1142 },
+ { 277, 1111, 707, 1362, 1089, 672, 1603, 1541, 1545, 1291 },
+ { 214, 781, 1609, 1303, 1632, 2229, 726, 1560, 1713, 918 },
+ { 152, 1037, 1046, 1759, 1983, 2174, 1358, 742, 1740, 1390 },
+ { 512, 1046, 1420, 753, 752, 1297, 1486, 1613, 460, 1207 },
+ { 424, 827, 1362, 719, 1462, 1202, 1199, 1476, 1199, 538 } },
+ { { 240, 402, 1134, 1491, 1659, 1505, 1517, 1555, 1979, 2099 },
+ { 467, 242, 960, 1232, 1714, 1620, 1834, 1570, 1676, 1391 },
+ { 500, 455, 463, 1507, 1699, 1282, 1564, 982, 2114, 2114 },
+ { 672, 643, 1372, 331, 1589, 1667, 1453, 1938, 996, 876 },
+ { 458, 783, 1037, 911, 738, 968, 1165, 1518, 859, 1033 },
+ { 504, 815, 504, 1139, 1219, 719, 1506, 1085, 1268, 1268 },
+ { 333, 630, 1445, 1239, 1883, 3672, 799, 1548, 1865, 598 },
+ { 399, 644, 746, 1342, 1856, 1350, 1493, 613, 1855, 1015 },
+ { 622, 749, 1205, 608, 1066, 1408, 1290, 1406, 546, 971 },
+ { 500, 753, 1041, 668, 1230, 1617, 1297, 1425, 1383, 523 } },
+ { { 394, 553, 523, 1502, 1536, 981, 1608, 1142, 1666, 2181 },
+ { 655, 430, 375, 1411, 1861, 1220, 1677, 1135, 1978, 1553 },
+ { 690, 640, 245, 1954, 2070, 1194, 1528, 982, 1972, 2232 },
+ { 559, 834, 741, 867, 1131, 980, 1225, 852, 1092, 784 },
+ { 690, 875, 516, 959, 673, 894, 1056, 1190, 1528, 1126 },
+ { 740, 951, 384, 1277, 1177, 492, 1579, 1155, 1846, 1513 },
+ { 323, 775, 1062, 1776, 3062, 1274, 813, 1188, 1372, 655 },
+ { 488, 971, 484, 1767, 1515, 1775, 1115, 503, 1539, 1461 },
+ { 740, 1006, 998, 709, 851, 1230, 1337, 788, 741, 721 },
+ { 522, 1073, 573, 1045, 1346, 887, 1046, 1146, 1203, 697 } },
+ { { 105, 864, 1442, 1009, 1934, 1840, 1519, 1920, 1673, 1579 },
+ { 534, 305, 1193, 683, 1388, 2164, 1802, 1894, 1264, 1170 },
+ { 305, 518, 877, 1108, 1426, 3215, 1425, 1064, 1320, 1242 },
+ { 683, 732, 1927, 257, 1493, 2048, 1858, 1552, 1055, 947 },
+ { 394, 814, 1024, 660, 959, 1556, 1282, 1289, 893, 1047 },
+ { 528, 615, 996, 940, 1201, 635, 1094, 2515, 803, 1358 },
+ { 347, 614, 1609, 1187, 3133, 1345, 1007, 1339, 1017, 667 },
+ { 218, 740, 878, 1605, 3650, 3650, 1345, 758, 1357, 1617 },
+ { 672, 750, 1541, 558, 1257, 1599, 1870, 2135, 402, 1087 },
+ { 592, 684, 1161, 430, 1092, 1497, 1475, 1489, 1095, 822 } },
+ { { 228, 1056, 1059, 1368, 752, 982, 1512, 1518, 987, 1782 },
+ { 494, 514, 818, 942, 965, 892, 1610, 1356, 1048, 1363 },
+ { 512, 648, 591, 1042, 761, 991, 1196, 1454, 1309, 1463 },
+ { 683, 749, 1043, 676, 841, 1396, 1133, 1138, 654, 939 },
+ { 622, 1101, 1126, 994, 361, 1077, 1203, 1318, 877, 1219 },
+ { 631, 1068, 857, 1650, 651, 477, 1650, 1419, 828, 1170 },
+ { 555, 727, 1068, 1335, 3127, 1339, 820, 1331, 1077, 429 },
+ { 504, 879, 624, 1398, 889, 889, 1392, 808, 891, 1406 },
+ { 683, 1602, 1289, 977, 578, 983, 1280, 1708, 406, 1122 },
+ { 399, 865, 1433, 1070, 1072, 764, 968, 1477, 1223, 678 } },
+ { { 333, 760, 935, 1638, 1010, 529, 1646, 1410, 1472, 2219 },
+ { 512, 494, 750, 1160, 1215, 610, 1870, 1868, 1628, 1169 },
+ { 572, 646, 492, 1934, 1208, 603, 1580, 1099, 1398, 1995 },
+ { 786, 789, 942, 581, 1018, 951, 1599, 1207, 731, 768 },
+ { 690, 1015, 672, 1078, 582, 504, 1693, 1438, 1108, 2897 },
+ { 768, 1267, 571, 2005, 1243, 244, 2881, 1380, 1786, 1453 },
+ { 452, 899, 1293, 903, 1311, 3100, 465, 1311, 1319, 813 },
+ { 394, 927, 942, 1103, 1358, 1104, 946, 593, 1363, 1109 },
+ { 559, 1005, 1007, 1016, 658, 1173, 1021, 1164, 623, 1028 },
+ { 564, 796, 632, 1005, 1014, 863, 2316, 1268, 938, 764 } },
+ { { 266, 606, 1098, 1228, 1497, 1243, 948, 1030, 1734, 1461 },
+ { 366, 585, 901, 1060, 1407, 1247, 876, 1134, 1620, 1054 },
+ { 452, 565, 542, 1729, 1479, 1479, 1016, 886, 2938, 1150 },
+ { 555, 1088, 1533, 950, 1354, 895, 834, 1019, 1021, 496 },
+ { 704, 815, 1193, 971, 973, 640, 1217, 2214, 832, 578 },
+ { 672, 1245, 579, 871, 875, 774, 872, 1273, 1027, 949 },
+ { 296, 1134, 2050, 1784, 1636, 3425, 442, 1550, 2076, 722 },
+ { 342, 982, 1259, 1846, 1848, 1848, 622, 568, 1847, 1052 },
+ { 555, 1064, 1304, 828, 746, 1343, 1075, 1329, 1078, 494 },
+ { 288, 1167, 1285, 1174, 1639, 1639, 833, 2254, 1304, 509 } },
+ { { 342, 719, 767, 1866, 1757, 1270, 1246, 550, 1746, 2151 },
+ { 483, 653, 694, 1509, 1459, 1410, 1218, 507, 1914, 1266 },
+ { 488, 757, 447, 2979, 1813, 1268, 1654, 539, 1849, 2109 },
+ { 522, 1097, 1085, 851, 1365, 1111, 851, 901, 961, 605 },
+ { 709, 716, 841, 728, 736, 945, 941, 862, 2845, 1057 },
+ { 512, 1323, 500, 1336, 1083, 681, 1342, 717, 1604, 1350 },
+ { 452, 1155, 1372, 1900, 1501, 3290, 311, 944, 1919, 922 },
+ { 403, 1520, 977, 2132, 1733, 3522, 1076, 276, 3335, 1547 },
+ { 559, 1374, 1101, 615, 673, 2462, 974, 795, 984, 984 },
+ { 547, 1122, 1062, 812, 1410, 951, 1140, 622, 1268, 651 } },
+ { { 165, 982, 1235, 938, 1334, 1366, 1659, 1578, 964, 1612 },
+ { 592, 422, 925, 847, 1139, 1112, 1387, 2036, 861, 1041 },
+ { 403, 837, 732, 770, 941, 1658, 1250, 809, 1407, 1407 },
+ { 896, 874, 1071, 381, 1568, 1722, 1437, 2192, 480, 1035 },
+ { 640, 1098, 1012, 1032, 684, 1382, 1581, 2106, 416, 865 },
+ { 559, 1005, 819, 914, 710, 770, 1418, 920, 838, 1435 },
+ { 415, 1258, 1245, 870, 1278, 3067, 770, 1021, 1287, 522 },
+ { 406, 990, 601, 1009, 1265, 1265, 1267, 759, 1017, 1277 },
+ { 968, 1182, 1329, 788, 1032, 1292, 1705, 1714, 203, 1403 },
+ { 732, 877, 1279, 471, 901, 1161, 1545, 1294, 755, 755 } },
+ { { 111, 931, 1378, 1185, 1933, 1648, 1148, 1714, 1873, 1307 },
+ { 406, 414, 1030, 1023, 1910, 1404, 1313, 1647, 1509, 793 },
+ { 342, 640, 575, 1088, 1241, 1349, 1161, 1350, 1756, 1502 },
+ { 559, 766, 1185, 357, 1682, 1428, 1329, 1897, 1219, 802 },
+ { 473, 909, 1164, 771, 719, 2508, 1427, 1432, 722, 782 },
+ { 342, 892, 785, 1145, 1150, 794, 1296, 1550, 973, 1057 },
+ { 208, 1036, 1326, 1343, 1606, 3395, 815, 1455, 1618, 712 },
+ { 228, 928, 890, 1046, 3499, 1711, 994, 829, 1720, 1318 },
+ { 768, 724, 1058, 636, 991, 1075, 1319, 1324, 616, 825 },
+ { 305, 1167, 1358, 899, 1587, 1587, 987, 1988, 1332, 501 } }
};
//------------------------------------------------------------------------------
+// helper functions for residuals struct VP8Residual.
+
+void VP8InitResidual(int first, int coeff_type,
+ VP8Encoder* const enc, VP8Residual* const res) {
+ res->coeff_type = coeff_type;
+ res->prob = enc->proba_.coeffs_[coeff_type];
+ res->stats = enc->proba_.stats_[coeff_type];
+ res->costs = enc->proba_.remapped_costs_[coeff_type];
+ res->first = first;
+}
+
+//------------------------------------------------------------------------------
+// Mode costs
+
+int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) {
+ const int x = (it->i4_ & 3), y = (it->i4_ >> 2);
+ VP8Residual res;
+ VP8Encoder* const enc = it->enc_;
+ int R = 0;
+ int ctx;
+
+ VP8InitResidual(0, 3, enc, &res);
+ ctx = it->top_nz_[x] + it->left_nz_[y];
+ VP8SetResidualCoeffs(levels, &res);
+ R += VP8GetResidualCost(ctx, &res);
+ return R;
+}
+
+int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd) {
+ VP8Residual res;
+ VP8Encoder* const enc = it->enc_;
+ int x, y;
+ int R = 0;
+
+ VP8IteratorNzToBytes(it); // re-import the non-zero context
+
+ // DC
+ VP8InitResidual(0, 1, enc, &res);
+ VP8SetResidualCoeffs(rd->y_dc_levels, &res);
+ R += VP8GetResidualCost(it->top_nz_[8] + it->left_nz_[8], &res);
+
+ // AC
+ VP8InitResidual(1, 0, enc, &res);
+ for (y = 0; y < 4; ++y) {
+ for (x = 0; x < 4; ++x) {
+ const int ctx = it->top_nz_[x] + it->left_nz_[y];
+ VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
+ R += VP8GetResidualCost(ctx, &res);
+ it->top_nz_[x] = it->left_nz_[y] = (res.last >= 0);
+ }
+ }
+ return R;
+}
+
+int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) {
+ VP8Residual res;
+ VP8Encoder* const enc = it->enc_;
+ int ch, x, y;
+ int R = 0;
+
+ VP8IteratorNzToBytes(it); // re-import the non-zero context
+
+ VP8InitResidual(0, 2, enc, &res);
+ for (ch = 0; ch <= 2; ch += 2) {
+ for (y = 0; y < 2; ++y) {
+ for (x = 0; x < 2; ++x) {
+ const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
+ VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
+ R += VP8GetResidualCost(ctx, &res);
+ it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = (res.last >= 0);
+ }
+ }
+ }
+ return R;
+}
+
+
+//------------------------------------------------------------------------------
+// Recording of token probabilities.
+
+// Record proba context used
+static int Record(int bit, proba_t* const stats) {
+ proba_t p = *stats;
+ if (p >= 0xffff0000u) { // an overflow is inbound.
+ p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2.
+ }
+ // record bit count (lower 16 bits) and increment total count (upper 16 bits).
+ p += 0x00010000u + bit;
+ *stats = p;
+ return bit;
+}
+
+// We keep the table-free variant around for reference, in case.
+#define USE_LEVEL_CODE_TABLE
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
+// Simulate block coding, but only record statistics.
+// Note: no need to record the fixed probas.
+int VP8RecordCoeffs(int ctx, const VP8Residual* const res) {
+ int n = res->first;
+ // should be stats[VP8EncBands[n]], but it's equivalent for n=0 or 1
+ proba_t* s = res->stats[n][ctx];
+ if (res->last < 0) {
+ Record(0, s + 0);
+ return 0;
+ }
+ while (n <= res->last) {
+ int v;
+ Record(1, s + 0); // order of record doesn't matter
+ while ((v = res->coeffs[n++]) == 0) {
+ Record(0, s + 1);
+ s = res->stats[VP8EncBands[n]][0];
+ }
+ Record(1, s + 1);
+ if (!Record(2u < (unsigned int)(v + 1), s + 2)) { // v = -1 or 1
+ s = res->stats[VP8EncBands[n]][1];
+ } else {
+ v = abs(v);
+#if !defined(USE_LEVEL_CODE_TABLE)
+ if (!Record(v > 4, s + 3)) {
+ if (Record(v != 2, s + 4))
+ Record(v == 4, s + 5);
+ } else if (!Record(v > 10, s + 6)) {
+ Record(v > 6, s + 7);
+ } else if (!Record((v >= 3 + (8 << 2)), s + 8)) {
+ Record((v >= 3 + (8 << 1)), s + 9);
+ } else {
+ Record((v >= 3 + (8 << 3)), s + 10);
+ }
+#else
+ if (v > MAX_VARIABLE_LEVEL) {
+ v = MAX_VARIABLE_LEVEL;
+ }
+
+ {
+ const int bits = VP8LevelCodes[v - 1][1];
+ int pattern = VP8LevelCodes[v - 1][0];
+ int i;
+ for (i = 0; (pattern >>= 1) != 0; ++i) {
+ const int mask = 2 << i;
+ if (pattern & 1) Record(!!(bits & mask), s + 3 + i);
+ }
+ }
#endif
+ s = res->stats[VP8EncBands[n]][2];
+ }
+ }
+ if (n < 16) Record(0, s + 0);
+ return 1;
+}
+
+//------------------------------------------------------------------------------
diff --git a/drivers/webp/enc/cost.h b/drivers/webp/enc/cost.h
index 09b75b699d..20960d6d74 100644
--- a/drivers/webp/enc/cost.h
+++ b/drivers/webp/enc/cost.h
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Cost tables for level and modes.
@@ -12,14 +14,32 @@
#ifndef WEBP_ENC_COST_H_
#define WEBP_ENC_COST_H_
+#include <assert.h>
+#include <stdlib.h>
#include "./vp8enci.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
-extern const uint16_t VP8LevelFixedCosts[2048]; // approximate cost per level
-extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p)
+// On-the-fly info about the current set of residuals. Handy to avoid
+// passing zillions of params.
+typedef struct VP8Residual VP8Residual;
+struct VP8Residual {
+ int first;
+ int last;
+ const int16_t* coeffs;
+
+ int coeff_type;
+ ProbaArray* prob;
+ StatsArray* stats;
+ CostArrayPtr costs;
+};
+
+void VP8InitResidual(int first, int coeff_type,
+ VP8Encoder* const enc, VP8Residual* const res);
+
+int VP8RecordCoeffs(int ctx, const VP8Residual* const res);
// Cost of coding one event with probability 'proba'.
static WEBP_INLINE int VP8BitCost(int bit, uint8_t proba) {
@@ -28,7 +48,7 @@ static WEBP_INLINE int VP8BitCost(int bit, uint8_t proba) {
// Level cost calculations
extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2];
-void VP8CalculateLevelCosts(VP8Proba* const proba);
+void VP8CalculateLevelCosts(VP8EncProba* const proba);
static WEBP_INLINE int VP8LevelCost(const uint16_t* const table, int level) {
return VP8LevelFixedCosts[level]
+ table[(level > MAX_VARIABLE_LEVEL) ? MAX_VARIABLE_LEVEL : level];
@@ -41,7 +61,7 @@ extern const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES];
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/enc/delta_palettization.c b/drivers/webp/enc/delta_palettization.c
new file mode 100644
index 0000000000..8bd3a3d233
--- /dev/null
+++ b/drivers/webp/enc/delta_palettization.c
@@ -0,0 +1,455 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Author: Mislav Bradac (mislavm@google.com)
+//
+
+#include "./delta_palettization.h"
+
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+#include "webp/types.h"
+#include "../dsp/lossless.h"
+
+#define MK_COL(r, g, b) (((r) << 16) + ((g) << 8) + (b))
+
+// Format allows palette up to 256 entries, but more palette entries produce
+// bigger entropy. In the future it will probably be useful to add more entries
+// that are far from the origin of the palette or choose remaining entries
+// dynamically.
+#define DELTA_PALETTE_SIZE 226
+
+// Palette used for delta_palettization. Entries are roughly sorted by distance
+// of their signed equivalents from the origin.
+static const uint32_t kDeltaPalette[DELTA_PALETTE_SIZE] = {
+ MK_COL(0u, 0u, 0u),
+ MK_COL(255u, 255u, 255u),
+ MK_COL(1u, 1u, 1u),
+ MK_COL(254u, 254u, 254u),
+ MK_COL(2u, 2u, 2u),
+ MK_COL(4u, 4u, 4u),
+ MK_COL(252u, 252u, 252u),
+ MK_COL(250u, 0u, 0u),
+ MK_COL(0u, 250u, 0u),
+ MK_COL(0u, 0u, 250u),
+ MK_COL(6u, 0u, 0u),
+ MK_COL(0u, 6u, 0u),
+ MK_COL(0u, 0u, 6u),
+ MK_COL(0u, 0u, 248u),
+ MK_COL(0u, 0u, 8u),
+ MK_COL(0u, 248u, 0u),
+ MK_COL(0u, 248u, 248u),
+ MK_COL(0u, 248u, 8u),
+ MK_COL(0u, 8u, 0u),
+ MK_COL(0u, 8u, 248u),
+ MK_COL(0u, 8u, 8u),
+ MK_COL(8u, 8u, 8u),
+ MK_COL(248u, 0u, 0u),
+ MK_COL(248u, 0u, 248u),
+ MK_COL(248u, 0u, 8u),
+ MK_COL(248u, 248u, 0u),
+ MK_COL(248u, 8u, 0u),
+ MK_COL(8u, 0u, 0u),
+ MK_COL(8u, 0u, 248u),
+ MK_COL(8u, 0u, 8u),
+ MK_COL(8u, 248u, 0u),
+ MK_COL(8u, 8u, 0u),
+ MK_COL(23u, 23u, 23u),
+ MK_COL(13u, 13u, 13u),
+ MK_COL(232u, 232u, 232u),
+ MK_COL(244u, 244u, 244u),
+ MK_COL(245u, 245u, 250u),
+ MK_COL(50u, 50u, 50u),
+ MK_COL(204u, 204u, 204u),
+ MK_COL(236u, 236u, 236u),
+ MK_COL(16u, 16u, 16u),
+ MK_COL(240u, 16u, 16u),
+ MK_COL(16u, 240u, 16u),
+ MK_COL(240u, 240u, 16u),
+ MK_COL(16u, 16u, 240u),
+ MK_COL(240u, 16u, 240u),
+ MK_COL(16u, 240u, 240u),
+ MK_COL(240u, 240u, 240u),
+ MK_COL(0u, 0u, 232u),
+ MK_COL(0u, 232u, 0u),
+ MK_COL(232u, 0u, 0u),
+ MK_COL(0u, 0u, 24u),
+ MK_COL(0u, 24u, 0u),
+ MK_COL(24u, 0u, 0u),
+ MK_COL(32u, 32u, 32u),
+ MK_COL(224u, 32u, 32u),
+ MK_COL(32u, 224u, 32u),
+ MK_COL(224u, 224u, 32u),
+ MK_COL(32u, 32u, 224u),
+ MK_COL(224u, 32u, 224u),
+ MK_COL(32u, 224u, 224u),
+ MK_COL(224u, 224u, 224u),
+ MK_COL(0u, 0u, 176u),
+ MK_COL(0u, 0u, 80u),
+ MK_COL(0u, 176u, 0u),
+ MK_COL(0u, 176u, 176u),
+ MK_COL(0u, 176u, 80u),
+ MK_COL(0u, 80u, 0u),
+ MK_COL(0u, 80u, 176u),
+ MK_COL(0u, 80u, 80u),
+ MK_COL(176u, 0u, 0u),
+ MK_COL(176u, 0u, 176u),
+ MK_COL(176u, 0u, 80u),
+ MK_COL(176u, 176u, 0u),
+ MK_COL(176u, 80u, 0u),
+ MK_COL(80u, 0u, 0u),
+ MK_COL(80u, 0u, 176u),
+ MK_COL(80u, 0u, 80u),
+ MK_COL(80u, 176u, 0u),
+ MK_COL(80u, 80u, 0u),
+ MK_COL(0u, 0u, 152u),
+ MK_COL(0u, 0u, 104u),
+ MK_COL(0u, 152u, 0u),
+ MK_COL(0u, 152u, 152u),
+ MK_COL(0u, 152u, 104u),
+ MK_COL(0u, 104u, 0u),
+ MK_COL(0u, 104u, 152u),
+ MK_COL(0u, 104u, 104u),
+ MK_COL(152u, 0u, 0u),
+ MK_COL(152u, 0u, 152u),
+ MK_COL(152u, 0u, 104u),
+ MK_COL(152u, 152u, 0u),
+ MK_COL(152u, 104u, 0u),
+ MK_COL(104u, 0u, 0u),
+ MK_COL(104u, 0u, 152u),
+ MK_COL(104u, 0u, 104u),
+ MK_COL(104u, 152u, 0u),
+ MK_COL(104u, 104u, 0u),
+ MK_COL(216u, 216u, 216u),
+ MK_COL(216u, 216u, 40u),
+ MK_COL(216u, 216u, 176u),
+ MK_COL(216u, 216u, 80u),
+ MK_COL(216u, 40u, 216u),
+ MK_COL(216u, 40u, 40u),
+ MK_COL(216u, 40u, 176u),
+ MK_COL(216u, 40u, 80u),
+ MK_COL(216u, 176u, 216u),
+ MK_COL(216u, 176u, 40u),
+ MK_COL(216u, 176u, 176u),
+ MK_COL(216u, 176u, 80u),
+ MK_COL(216u, 80u, 216u),
+ MK_COL(216u, 80u, 40u),
+ MK_COL(216u, 80u, 176u),
+ MK_COL(216u, 80u, 80u),
+ MK_COL(40u, 216u, 216u),
+ MK_COL(40u, 216u, 40u),
+ MK_COL(40u, 216u, 176u),
+ MK_COL(40u, 216u, 80u),
+ MK_COL(40u, 40u, 216u),
+ MK_COL(40u, 40u, 40u),
+ MK_COL(40u, 40u, 176u),
+ MK_COL(40u, 40u, 80u),
+ MK_COL(40u, 176u, 216u),
+ MK_COL(40u, 176u, 40u),
+ MK_COL(40u, 176u, 176u),
+ MK_COL(40u, 176u, 80u),
+ MK_COL(40u, 80u, 216u),
+ MK_COL(40u, 80u, 40u),
+ MK_COL(40u, 80u, 176u),
+ MK_COL(40u, 80u, 80u),
+ MK_COL(80u, 216u, 216u),
+ MK_COL(80u, 216u, 40u),
+ MK_COL(80u, 216u, 176u),
+ MK_COL(80u, 216u, 80u),
+ MK_COL(80u, 40u, 216u),
+ MK_COL(80u, 40u, 40u),
+ MK_COL(80u, 40u, 176u),
+ MK_COL(80u, 40u, 80u),
+ MK_COL(80u, 176u, 216u),
+ MK_COL(80u, 176u, 40u),
+ MK_COL(80u, 176u, 176u),
+ MK_COL(80u, 176u, 80u),
+ MK_COL(80u, 80u, 216u),
+ MK_COL(80u, 80u, 40u),
+ MK_COL(80u, 80u, 176u),
+ MK_COL(80u, 80u, 80u),
+ MK_COL(0u, 0u, 192u),
+ MK_COL(0u, 0u, 64u),
+ MK_COL(0u, 0u, 128u),
+ MK_COL(0u, 192u, 0u),
+ MK_COL(0u, 192u, 192u),
+ MK_COL(0u, 192u, 64u),
+ MK_COL(0u, 192u, 128u),
+ MK_COL(0u, 64u, 0u),
+ MK_COL(0u, 64u, 192u),
+ MK_COL(0u, 64u, 64u),
+ MK_COL(0u, 64u, 128u),
+ MK_COL(0u, 128u, 0u),
+ MK_COL(0u, 128u, 192u),
+ MK_COL(0u, 128u, 64u),
+ MK_COL(0u, 128u, 128u),
+ MK_COL(176u, 216u, 216u),
+ MK_COL(176u, 216u, 40u),
+ MK_COL(176u, 216u, 176u),
+ MK_COL(176u, 216u, 80u),
+ MK_COL(176u, 40u, 216u),
+ MK_COL(176u, 40u, 40u),
+ MK_COL(176u, 40u, 176u),
+ MK_COL(176u, 40u, 80u),
+ MK_COL(176u, 176u, 216u),
+ MK_COL(176u, 176u, 40u),
+ MK_COL(176u, 176u, 176u),
+ MK_COL(176u, 176u, 80u),
+ MK_COL(176u, 80u, 216u),
+ MK_COL(176u, 80u, 40u),
+ MK_COL(176u, 80u, 176u),
+ MK_COL(176u, 80u, 80u),
+ MK_COL(192u, 0u, 0u),
+ MK_COL(192u, 0u, 192u),
+ MK_COL(192u, 0u, 64u),
+ MK_COL(192u, 0u, 128u),
+ MK_COL(192u, 192u, 0u),
+ MK_COL(192u, 192u, 192u),
+ MK_COL(192u, 192u, 64u),
+ MK_COL(192u, 192u, 128u),
+ MK_COL(192u, 64u, 0u),
+ MK_COL(192u, 64u, 192u),
+ MK_COL(192u, 64u, 64u),
+ MK_COL(192u, 64u, 128u),
+ MK_COL(192u, 128u, 0u),
+ MK_COL(192u, 128u, 192u),
+ MK_COL(192u, 128u, 64u),
+ MK_COL(192u, 128u, 128u),
+ MK_COL(64u, 0u, 0u),
+ MK_COL(64u, 0u, 192u),
+ MK_COL(64u, 0u, 64u),
+ MK_COL(64u, 0u, 128u),
+ MK_COL(64u, 192u, 0u),
+ MK_COL(64u, 192u, 192u),
+ MK_COL(64u, 192u, 64u),
+ MK_COL(64u, 192u, 128u),
+ MK_COL(64u, 64u, 0u),
+ MK_COL(64u, 64u, 192u),
+ MK_COL(64u, 64u, 64u),
+ MK_COL(64u, 64u, 128u),
+ MK_COL(64u, 128u, 0u),
+ MK_COL(64u, 128u, 192u),
+ MK_COL(64u, 128u, 64u),
+ MK_COL(64u, 128u, 128u),
+ MK_COL(128u, 0u, 0u),
+ MK_COL(128u, 0u, 192u),
+ MK_COL(128u, 0u, 64u),
+ MK_COL(128u, 0u, 128u),
+ MK_COL(128u, 192u, 0u),
+ MK_COL(128u, 192u, 192u),
+ MK_COL(128u, 192u, 64u),
+ MK_COL(128u, 192u, 128u),
+ MK_COL(128u, 64u, 0u),
+ MK_COL(128u, 64u, 192u),
+ MK_COL(128u, 64u, 64u),
+ MK_COL(128u, 64u, 128u),
+ MK_COL(128u, 128u, 0u),
+ MK_COL(128u, 128u, 192u),
+ MK_COL(128u, 128u, 64u),
+ MK_COL(128u, 128u, 128u),
+};
+
+#undef MK_COL
+
+//------------------------------------------------------------------------------
+// TODO(skal): move the functions to dsp/lossless.c when the correct
+// granularity is found. For now, we'll just copy-paste some useful bits
+// here instead.
+
+// In-place sum of each component with mod 256.
+static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) {
+ const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u);
+ const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu);
+ *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
+}
+
+static WEBP_INLINE uint32_t Clip255(uint32_t a) {
+ if (a < 256) {
+ return a;
+ }
+ // return 0, when a is a negative integer.
+ // return 255, when a is positive.
+ return ~a >> 24;
+}
+
+// Delta palettization functions.
+static WEBP_INLINE int Square(int x) {
+ return x * x;
+}
+
+static WEBP_INLINE uint32_t Intensity(uint32_t a) {
+ return
+ 30 * ((a >> 16) & 0xff) +
+ 59 * ((a >> 8) & 0xff) +
+ 11 * ((a >> 0) & 0xff);
+}
+
+static uint32_t CalcDist(uint32_t predicted_value, uint32_t actual_value,
+ uint32_t palette_entry) {
+ int i;
+ uint32_t distance = 0;
+ AddPixelsEq(&predicted_value, palette_entry);
+ for (i = 0; i < 32; i += 8) {
+ const int32_t av = (actual_value >> i) & 0xff;
+ const int32_t pv = (predicted_value >> i) & 0xff;
+ distance += Square(pv - av);
+ }
+ // We sum square of intensity difference with factor 10, but because Intensity
+ // returns 100 times real intensity we need to multiply differences of colors
+ // by 1000.
+ distance *= 1000u;
+ distance += Square(Intensity(predicted_value)
+ - Intensity(actual_value));
+ return distance;
+}
+
+static uint32_t Predict(int x, int y, uint32_t* image) {
+ const uint32_t t = (y == 0) ? ARGB_BLACK : image[x];
+ const uint32_t l = (x == 0) ? ARGB_BLACK : image[x - 1];
+ const uint32_t p =
+ (((((t >> 24) & 0xff) + ((l >> 24) & 0xff)) / 2) << 24) +
+ (((((t >> 16) & 0xff) + ((l >> 16) & 0xff)) / 2) << 16) +
+ (((((t >> 8) & 0xff) + ((l >> 8) & 0xff)) / 2) << 8) +
+ (((((t >> 0) & 0xff) + ((l >> 0) & 0xff)) / 2) << 0);
+ if (x == 0 && y == 0) return ARGB_BLACK;
+ if (x == 0) return t;
+ if (y == 0) return l;
+ return p;
+}
+
+static WEBP_INLINE int AddSubtractComponentFullWithCoefficient(
+ int a, int b, int c) {
+ return Clip255(a + ((b - c) >> 2));
+}
+
+static WEBP_INLINE uint32_t ClampedAddSubtractFullWithCoefficient(
+ uint32_t c0, uint32_t c1, uint32_t c2) {
+ const int a = AddSubtractComponentFullWithCoefficient(
+ c0 >> 24, c1 >> 24, c2 >> 24);
+ const int r = AddSubtractComponentFullWithCoefficient((c0 >> 16) & 0xff,
+ (c1 >> 16) & 0xff,
+ (c2 >> 16) & 0xff);
+ const int g = AddSubtractComponentFullWithCoefficient((c0 >> 8) & 0xff,
+ (c1 >> 8) & 0xff,
+ (c2 >> 8) & 0xff);
+ const int b = AddSubtractComponentFullWithCoefficient(
+ c0 & 0xff, c1 & 0xff, c2 & 0xff);
+ return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
+}
+
+//------------------------------------------------------------------------------
+
+// Find palette entry with minimum error from difference of actual pixel value
+// and predicted pixel value. Propagate error of pixel to its top and left pixel
+// in src array. Write predicted_value + palette_entry to new_image. Return
+// index of best palette entry.
+static int FindBestPaletteEntry(uint32_t src, uint32_t predicted_value,
+ const uint32_t palette[], int palette_size) {
+ int i;
+ int idx = 0;
+ uint32_t best_distance = CalcDist(predicted_value, src, palette[0]);
+ for (i = 1; i < palette_size; ++i) {
+ const uint32_t distance = CalcDist(predicted_value, src, palette[i]);
+ if (distance < best_distance) {
+ best_distance = distance;
+ idx = i;
+ }
+ }
+ return idx;
+}
+
+static void ApplyBestPaletteEntry(int x, int y,
+ uint32_t new_value, uint32_t palette_value,
+ uint32_t* src, int src_stride,
+ uint32_t* new_image) {
+ AddPixelsEq(&new_value, palette_value);
+ if (x > 0) {
+ src[x - 1] = ClampedAddSubtractFullWithCoefficient(src[x - 1],
+ new_value, src[x]);
+ }
+ if (y > 0) {
+ src[x - src_stride] =
+ ClampedAddSubtractFullWithCoefficient(src[x - src_stride],
+ new_value, src[x]);
+ }
+ new_image[x] = new_value;
+}
+
+//------------------------------------------------------------------------------
+// Main entry point
+
+static WebPEncodingError ApplyDeltaPalette(uint32_t* src, uint32_t* dst,
+ uint32_t src_stride,
+ uint32_t dst_stride,
+ const uint32_t* palette,
+ int palette_size,
+ int width, int height,
+ int num_passes) {
+ int x, y;
+ WebPEncodingError err = VP8_ENC_OK;
+ uint32_t* new_image = (uint32_t*)WebPSafeMalloc(width, sizeof(*new_image));
+ uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row));
+ if (new_image == NULL || tmp_row == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+
+ while (num_passes--) {
+ uint32_t* cur_src = src;
+ uint32_t* cur_dst = dst;
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ const uint32_t predicted_value = Predict(x, y, new_image);
+ tmp_row[x] = FindBestPaletteEntry(cur_src[x], predicted_value,
+ palette, palette_size);
+ ApplyBestPaletteEntry(x, y, predicted_value, palette[tmp_row[x]],
+ cur_src, src_stride, new_image);
+ }
+ for (x = 0; x < width; ++x) {
+ cur_dst[x] = palette[tmp_row[x]];
+ }
+ cur_src += src_stride;
+ cur_dst += dst_stride;
+ }
+ }
+ Error:
+ WebPSafeFree(new_image);
+ WebPSafeFree(tmp_row);
+ return err;
+}
+
+// replaces enc->argb_ by a palettizable approximation of it,
+// and generates optimal enc->palette_[]
+WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) {
+ const WebPPicture* const pic = enc->pic_;
+ uint32_t* src = pic->argb;
+ uint32_t* dst = enc->argb_;
+ const int width = pic->width;
+ const int height = pic->height;
+
+ WebPEncodingError err = VP8_ENC_OK;
+ memcpy(enc->palette_, kDeltaPalette, sizeof(kDeltaPalette));
+ enc->palette_[DELTA_PALETTE_SIZE - 1] = src[0] - 0xff000000u;
+ enc->palette_size_ = DELTA_PALETTE_SIZE;
+ err = ApplyDeltaPalette(src, dst, pic->argb_stride, enc->current_width_,
+ enc->palette_, enc->palette_size_,
+ width, height, 2);
+ if (err != VP8_ENC_OK) goto Error;
+
+ Error:
+ return err;
+}
+
+#else // !WEBP_EXPERIMENTAL_FEATURES
+
+WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) {
+ (void)enc;
+ return VP8_ENC_ERROR_INVALID_CONFIGURATION;
+}
+
+#endif // WEBP_EXPERIMENTAL_FEATURES
diff --git a/drivers/webp/enc/delta_palettization.h b/drivers/webp/enc/delta_palettization.h
new file mode 100644
index 0000000000..54195d452c
--- /dev/null
+++ b/drivers/webp/enc/delta_palettization.h
@@ -0,0 +1,25 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Author: Mislav Bradac (mislavm@google.com)
+//
+
+#ifndef WEBP_ENC_DELTA_PALETTIZATION_H_
+#define WEBP_ENC_DELTA_PALETTIZATION_H_
+
+#include "webp/encode.h"
+#include "../enc/vp8li.h"
+
+// Replaces enc->argb_[] input by a palettizable approximation of it,
+// and generates optimal enc->palette_[].
+// This function can revert enc->use_palette_ / enc->use_predict_ flag
+// if delta-palettization is not producing expected saving.
+WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc);
+
+#endif // WEBP_ENC_DELTA_PALETTIZATION_H_
diff --git a/drivers/webp/enc/filter.c b/drivers/webp/enc/filter.c
index 7fb78a3949..1a4dd947fb 100644
--- a/drivers/webp/enc/filter.c
+++ b/drivers/webp/enc/filter.c
@@ -1,194 +1,68 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Selecting filter level
//
// Author: somnath@google.com (Somnath Banerjee)
+#include <assert.h>
#include "./vp8enci.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-// NOTE: clip1, tables and InitTables are repeated entries of dsp.c
-static uint8_t abs0[255 + 255 + 1]; // abs(i)
-static uint8_t abs1[255 + 255 + 1]; // abs(i)>>1
-static int8_t sclip1[1020 + 1020 + 1]; // clips [-1020, 1020] to [-128, 127]
-static int8_t sclip2[112 + 112 + 1]; // clips [-112, 112] to [-16, 15]
-static uint8_t clip1[255 + 510 + 1]; // clips [-255,510] to [0,255]
-
-static int tables_ok = 0;
-
-static void InitTables(void) {
- if (!tables_ok) {
- int i;
- for (i = -255; i <= 255; ++i) {
- abs0[255 + i] = (i < 0) ? -i : i;
- abs1[255 + i] = abs0[255 + i] >> 1;
- }
- for (i = -1020; i <= 1020; ++i) {
- sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i;
- }
- for (i = -112; i <= 112; ++i) {
- sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i;
- }
- for (i = -255; i <= 255 + 255; ++i) {
- clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i;
- }
- tables_ok = 1;
- }
-}
-
-//------------------------------------------------------------------------------
-// Edge filtering functions
-
-// 4 pixels in, 2 pixels out
-static WEBP_INLINE void do_filter2(uint8_t* p, int step) {
- const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
- const int a = 3 * (q0 - p0) + sclip1[1020 + p1 - q1];
- const int a1 = sclip2[112 + ((a + 4) >> 3)];
- const int a2 = sclip2[112 + ((a + 3) >> 3)];
- p[-step] = clip1[255 + p0 + a2];
- p[ 0] = clip1[255 + q0 - a1];
-}
-
-// 4 pixels in, 4 pixels out
-static WEBP_INLINE void do_filter4(uint8_t* p, int step) {
- const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
- const int a = 3 * (q0 - p0);
- const int a1 = sclip2[112 + ((a + 4) >> 3)];
- const int a2 = sclip2[112 + ((a + 3) >> 3)];
- const int a3 = (a1 + 1) >> 1;
- p[-2*step] = clip1[255 + p1 + a3];
- p[- step] = clip1[255 + p0 + a2];
- p[ 0] = clip1[255 + q0 - a1];
- p[ step] = clip1[255 + q1 - a3];
-}
-
-// high edge-variance
-static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) {
- const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
- return (abs0[255 + p1 - p0] > thresh) || (abs0[255 + q1 - q0] > thresh);
-}
-
-static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int thresh) {
- const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
- return (2 * abs0[255 + p0 - q0] + abs1[255 + p1 - q1]) <= thresh;
-}
-
-static WEBP_INLINE int needs_filter2(const uint8_t* p,
- int step, int t, int it) {
- const int p3 = p[-4*step], p2 = p[-3*step], p1 = p[-2*step], p0 = p[-step];
- const int q0 = p[0], q1 = p[step], q2 = p[2*step], q3 = p[3*step];
- if ((2 * abs0[255 + p0 - q0] + abs1[255 + p1 - q1]) > t)
- return 0;
- return abs0[255 + p3 - p2] <= it && abs0[255 + p2 - p1] <= it &&
- abs0[255 + p1 - p0] <= it && abs0[255 + q3 - q2] <= it &&
- abs0[255 + q2 - q1] <= it && abs0[255 + q1 - q0] <= it;
+#include "../dsp/dsp.h"
+
+// This table gives, for a given sharpness, the filtering strength to be
+// used (at least) in order to filter a given edge step delta.
+// This is constructed by brute force inspection: for all delta, we iterate
+// over all possible filtering strength / thresh until needs_filter() returns
+// true.
+#define MAX_DELTA_SIZE 64
+static const uint8_t kLevelsFromDelta[8][MAX_DELTA_SIZE] = {
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 },
+ { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 17, 18,
+ 20, 21, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42,
+ 44, 45, 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 },
+ { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 19,
+ 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43,
+ 44, 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 },
+ { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19,
+ 21, 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43,
+ 45, 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 },
+ { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 14, 15, 17, 18, 20,
+ 21, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, 44,
+ 45, 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 },
+ { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19, 20,
+ 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, 44,
+ 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 },
+ { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 21,
+ 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, 45,
+ 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 },
+ { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21,
+ 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, 44, 45,
+ 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }
+};
+
+int VP8FilterStrengthFromDelta(int sharpness, int delta) {
+ const int pos = (delta < MAX_DELTA_SIZE) ? delta : MAX_DELTA_SIZE - 1;
+ assert(sharpness >= 0 && sharpness <= 7);
+ return kLevelsFromDelta[sharpness][pos];
}
//------------------------------------------------------------------------------
-// Simple In-loop filtering (Paragraph 15.2)
-
-static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
- int i;
- for (i = 0; i < 16; ++i) {
- if (needs_filter(p + i, stride, thresh)) {
- do_filter2(p + i, stride);
- }
- }
-}
-
-static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
- int i;
- for (i = 0; i < 16; ++i) {
- if (needs_filter(p + i * stride, 1, thresh)) {
- do_filter2(p + i * stride, 1);
- }
- }
-}
-
-static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4 * stride;
- SimpleVFilter16(p, stride, thresh);
- }
-}
-
-static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4;
- SimpleHFilter16(p, stride, thresh);
- }
-}
-
-//------------------------------------------------------------------------------
-// Complex In-loop filtering (Paragraph 15.3)
-
-static WEBP_INLINE void FilterLoop24(uint8_t* p,
- int hstride, int vstride, int size,
- int thresh, int ithresh, int hev_thresh) {
- while (size-- > 0) {
- if (needs_filter2(p, hstride, thresh, ithresh)) {
- if (hev(p, hstride, hev_thresh)) {
- do_filter2(p, hstride);
- } else {
- do_filter4(p, hstride);
- }
- }
- p += vstride;
- }
-}
-
-// on three inner edges
-static void VFilter16i(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4 * stride;
- FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh);
- }
-}
-
-static void HFilter16i(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4;
- FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh);
- }
-}
-
-static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
- FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
-}
-
-static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
- FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
-}
-
-//------------------------------------------------------------------------------
-
-void (*VP8EncVFilter16i)(uint8_t*, int, int, int, int) = VFilter16i;
-void (*VP8EncHFilter16i)(uint8_t*, int, int, int, int) = HFilter16i;
-void (*VP8EncVFilter8i)(uint8_t*, uint8_t*, int, int, int, int) = VFilter8i;
-void (*VP8EncHFilter8i)(uint8_t*, uint8_t*, int, int, int, int) = HFilter8i;
-
-void (*VP8EncSimpleVFilter16i)(uint8_t*, int, int) = SimpleVFilter16i;
-void (*VP8EncSimpleHFilter16i)(uint8_t*, int, int) = SimpleHFilter16i;
-
-//------------------------------------------------------------------------------
// Paragraph 15.4: compute the inner-edge filtering strength
static int GetILevel(int sharpness, int level) {
@@ -211,22 +85,22 @@ static void DoFilter(const VP8EncIterator* const it, int level) {
const int ilevel = GetILevel(enc->config_->filter_sharpness, level);
const int limit = 2 * level + ilevel;
- uint8_t* const y_dst = it->yuv_out2_ + Y_OFF;
- uint8_t* const u_dst = it->yuv_out2_ + U_OFF;
- uint8_t* const v_dst = it->yuv_out2_ + V_OFF;
+ uint8_t* const y_dst = it->yuv_out2_ + Y_OFF_ENC;
+ uint8_t* const u_dst = it->yuv_out2_ + U_OFF_ENC;
+ uint8_t* const v_dst = it->yuv_out2_ + V_OFF_ENC;
// copy current block to yuv_out2_
- memcpy(y_dst, it->yuv_out_, YUV_SIZE * sizeof(uint8_t));
+ memcpy(y_dst, it->yuv_out_, YUV_SIZE_ENC * sizeof(uint8_t));
if (enc->filter_hdr_.simple_ == 1) { // simple
- VP8EncSimpleHFilter16i(y_dst, BPS, limit);
- VP8EncSimpleVFilter16i(y_dst, BPS, limit);
+ VP8SimpleHFilter16i(y_dst, BPS, limit);
+ VP8SimpleVFilter16i(y_dst, BPS, limit);
} else { // complex
const int hev_thresh = (level >= 40) ? 2 : (level >= 15) ? 1 : 0;
- VP8EncHFilter16i(y_dst, BPS, limit, ilevel, hev_thresh);
- VP8EncHFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh);
- VP8EncVFilter16i(y_dst, BPS, limit, ilevel, hev_thresh);
- VP8EncVFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh);
+ VP8HFilter16i(y_dst, BPS, limit, ilevel, hev_thresh);
+ VP8HFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh);
+ VP8VFilter16i(y_dst, BPS, limit, ilevel, hev_thresh);
+ VP8VFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh);
}
}
@@ -321,13 +195,16 @@ static double GetMBSSIM(const uint8_t* yuv1, const uint8_t* yuv2) {
// compute SSIM in a 10 x 10 window
for (x = 3; x < 13; x++) {
for (y = 3; y < 13; y++) {
- VP8SSIMAccumulate(yuv1 + Y_OFF, BPS, yuv2 + Y_OFF, BPS, x, y, 16, 16, &s);
+ VP8SSIMAccumulate(yuv1 + Y_OFF_ENC, BPS, yuv2 + Y_OFF_ENC, BPS,
+ x, y, 16, 16, &s);
}
}
for (x = 1; x < 7; x++) {
for (y = 1; y < 7; y++) {
- VP8SSIMAccumulate(yuv1 + U_OFF, BPS, yuv2 + U_OFF, BPS, x, y, 8, 8, &s);
- VP8SSIMAccumulate(yuv1 + V_OFF, BPS, yuv2 + V_OFF, BPS, x, y, 8, 8, &s);
+ VP8SSIMAccumulate(yuv1 + U_OFF_ENC, BPS, yuv2 + U_OFF_ENC, BPS,
+ x, y, 8, 8, &s);
+ VP8SSIMAccumulate(yuv1 + V_OFF_ENC, BPS, yuv2 + V_OFF_ENC, BPS,
+ x, y, 8, 8, &s);
}
}
return VP8SSIMGet(&s);
@@ -338,28 +215,28 @@ static double GetMBSSIM(const uint8_t* yuv1, const uint8_t* yuv2) {
// loop filter strength
void VP8InitFilter(VP8EncIterator* const it) {
- int s, i;
- if (!it->lf_stats_) return;
-
- InitTables();
- for (s = 0; s < NUM_MB_SEGMENTS; s++) {
- for (i = 0; i < MAX_LF_LEVELS; i++) {
- (*it->lf_stats_)[s][i] = 0;
+ if (it->lf_stats_ != NULL) {
+ int s, i;
+ for (s = 0; s < NUM_MB_SEGMENTS; s++) {
+ for (i = 0; i < MAX_LF_LEVELS; i++) {
+ (*it->lf_stats_)[s][i] = 0;
+ }
}
}
}
void VP8StoreFilterStats(VP8EncIterator* const it) {
int d;
+ VP8Encoder* const enc = it->enc_;
const int s = it->mb_->segment_;
- const int level0 = it->enc_->dqm_[s].fstrength_; // TODO: ref_lf_delta[]
+ const int level0 = enc->dqm_[s].fstrength_; // TODO: ref_lf_delta[]
// explore +/-quant range of values around level0
- const int delta_min = -it->enc_->dqm_[s].quant_;
- const int delta_max = it->enc_->dqm_[s].quant_;
+ const int delta_min = -enc->dqm_[s].quant_;
+ const int delta_max = enc->dqm_[s].quant_;
const int step_size = (delta_max - delta_min >= 4) ? 4 : 1;
- if (!it->lf_stats_) return;
+ if (it->lf_stats_ == NULL) return;
// NOTE: Currently we are applying filter only across the sublock edges
// There are two reasons for that.
@@ -383,27 +260,40 @@ void VP8StoreFilterStats(VP8EncIterator* const it) {
}
void VP8AdjustFilterStrength(VP8EncIterator* const it) {
- int s;
VP8Encoder* const enc = it->enc_;
-
- if (!it->lf_stats_) {
- return;
- }
- for (s = 0; s < NUM_MB_SEGMENTS; s++) {
- int i, best_level = 0;
- // Improvement over filter level 0 should be at least 1e-5 (relatively)
- double best_v = 1.00001 * (*it->lf_stats_)[s][0];
- for (i = 1; i < MAX_LF_LEVELS; i++) {
- const double v = (*it->lf_stats_)[s][i];
- if (v > best_v) {
- best_v = v;
- best_level = i;
+ if (it->lf_stats_ != NULL) {
+ int s;
+ for (s = 0; s < NUM_MB_SEGMENTS; s++) {
+ int i, best_level = 0;
+ // Improvement over filter level 0 should be at least 1e-5 (relatively)
+ double best_v = 1.00001 * (*it->lf_stats_)[s][0];
+ for (i = 1; i < MAX_LF_LEVELS; i++) {
+ const double v = (*it->lf_stats_)[s][i];
+ if (v > best_v) {
+ best_v = v;
+ best_level = i;
+ }
}
+ enc->dqm_[s].fstrength_ = best_level;
}
- enc->dqm_[s].fstrength_ = best_level;
+ } else if (enc->config_->filter_strength > 0) {
+ int max_level = 0;
+ int s;
+ for (s = 0; s < NUM_MB_SEGMENTS; s++) {
+ VP8SegmentInfo* const dqm = &enc->dqm_[s];
+ // this '>> 3' accounts for some inverse WHT scaling
+ const int delta = (dqm->max_edge_ * dqm->y2_.q_[1]) >> 3;
+ const int level =
+ VP8FilterStrengthFromDelta(enc->filter_hdr_.sharpness_, delta);
+ if (level > dqm->fstrength_) {
+ dqm->fstrength_ = level;
+ }
+ if (max_level < dqm->fstrength_) {
+ max_level = dqm->fstrength_;
+ }
+ }
+ enc->filter_hdr_.level_ = max_level;
}
}
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
+// -----------------------------------------------------------------------------
diff --git a/drivers/webp/enc/frame.c b/drivers/webp/enc/frame.c
index bdd360069b..65a98ada4d 100644
--- a/drivers/webp/enc/frame.c
+++ b/drivers/webp/enc/frame.c
@@ -1,61 +1,98 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// frame coding and analysis
//
// Author: Skal (pascal.massimino@gmail.com)
-#include <assert.h>
-#include <stdlib.h>
#include <string.h>
#include <math.h>
-#include "./vp8enci.h"
#include "./cost.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+#include "./vp8enci.h"
+#include "../dsp/dsp.h"
+#include "webp/format_constants.h" // RIFF constants
#define SEGMENT_VISU 0
#define DEBUG_SEARCH 0 // useful to track search convergence
-// On-the-fly info about the current set of residuals. Handy to avoid
-// passing zillions of params.
-typedef struct {
- int first;
- int last;
- const int16_t* coeffs;
-
- int coeff_type;
- ProbaArray* prob;
- StatsArray* stats;
- CostArray* cost;
-} VP8Residual;
+//------------------------------------------------------------------------------
+// multi-pass convergence
+
+#define HEADER_SIZE_ESTIMATE (RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + \
+ VP8_FRAME_HEADER_SIZE)
+#define DQ_LIMIT 0.4 // convergence is considered reached if dq < DQ_LIMIT
+// we allow 2k of extra head-room in PARTITION0 limit.
+#define PARTITION0_SIZE_LIMIT ((VP8_MAX_PARTITION0_SIZE - 2048ULL) << 11)
+
+typedef struct { // struct for organizing convergence in either size or PSNR
+ int is_first;
+ float dq;
+ float q, last_q;
+ double value, last_value; // PSNR or size
+ double target;
+ int do_size_search;
+} PassStats;
+
+static int InitPassStats(const VP8Encoder* const enc, PassStats* const s) {
+ const uint64_t target_size = (uint64_t)enc->config_->target_size;
+ const int do_size_search = (target_size != 0);
+ const float target_PSNR = enc->config_->target_PSNR;
+
+ s->is_first = 1;
+ s->dq = 10.f;
+ s->q = s->last_q = enc->config_->quality;
+ s->target = do_size_search ? (double)target_size
+ : (target_PSNR > 0.) ? target_PSNR
+ : 40.; // default, just in case
+ s->value = s->last_value = 0.;
+ s->do_size_search = do_size_search;
+ return do_size_search;
+}
+
+static float Clamp(float v, float min, float max) {
+ return (v < min) ? min : (v > max) ? max : v;
+}
+
+static float ComputeNextQ(PassStats* const s) {
+ float dq;
+ if (s->is_first) {
+ dq = (s->value > s->target) ? -s->dq : s->dq;
+ s->is_first = 0;
+ } else if (s->value != s->last_value) {
+ const double slope = (s->target - s->value) / (s->last_value - s->value);
+ dq = (float)(slope * (s->last_q - s->q));
+ } else {
+ dq = 0.; // we're done?!
+ }
+ // Limit variable to avoid large swings.
+ s->dq = Clamp(dq, -30.f, 30.f);
+ s->last_q = s->q;
+ s->last_value = s->value;
+ s->q = Clamp(s->q + s->dq, 0.f, 100.f);
+ return s->q;
+}
//------------------------------------------------------------------------------
// Tables for level coding
-const uint8_t VP8EncBands[16 + 1] = {
- 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
- 0 // sentinel
-};
-
-static const uint8_t kCat3[] = { 173, 148, 140 };
-static const uint8_t kCat4[] = { 176, 155, 140, 135 };
-static const uint8_t kCat5[] = { 180, 157, 141, 134, 130 };
-static const uint8_t kCat6[] =
+const uint8_t VP8Cat3[] = { 173, 148, 140 };
+const uint8_t VP8Cat4[] = { 176, 155, 140, 135 };
+const uint8_t VP8Cat5[] = { 180, 157, 141, 134, 130 };
+const uint8_t VP8Cat6[] =
{ 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 };
//------------------------------------------------------------------------------
// Reset the statistics about: number of skips, token proba, level cost,...
static void ResetStats(VP8Encoder* const enc) {
- VP8Proba* const proba = &enc->proba_;
+ VP8EncProba* const proba = &enc->proba_;
VP8CalculateLevelCosts(proba);
proba->nb_skip_ = 0;
}
@@ -71,7 +108,7 @@ static int CalcSkipProba(uint64_t nb, uint64_t total) {
// Returns the bit-cost for coding the skip probability.
static int FinalizeSkipProba(VP8Encoder* const enc) {
- VP8Proba* const proba = &enc->proba_;
+ VP8EncProba* const proba = &enc->proba_;
const int nb_mbs = enc->mb_w_ * enc->mb_h_;
const int nb_events = proba->nb_skip_;
int size;
@@ -86,82 +123,6 @@ static int FinalizeSkipProba(VP8Encoder* const enc) {
return size;
}
-//------------------------------------------------------------------------------
-// Recording of token probabilities.
-
-static void ResetTokenStats(VP8Encoder* const enc) {
- VP8Proba* const proba = &enc->proba_;
- memset(proba->stats_, 0, sizeof(proba->stats_));
-}
-
-// Record proba context used
-static int Record(int bit, proba_t* const stats) {
- proba_t p = *stats;
- if (p >= 0xffff0000u) { // an overflow is inbound.
- p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2.
- }
- // record bit count (lower 16 bits) and increment total count (upper 16 bits).
- p += 0x00010000u + bit;
- *stats = p;
- return bit;
-}
-
-// We keep the table free variant around for reference, in case.
-#define USE_LEVEL_CODE_TABLE
-
-// Simulate block coding, but only record statistics.
-// Note: no need to record the fixed probas.
-static int RecordCoeffs(int ctx, const VP8Residual* const res) {
- int n = res->first;
- proba_t* s = res->stats[VP8EncBands[n]][ctx];
- if (res->last < 0) {
- Record(0, s + 0);
- return 0;
- }
- while (n <= res->last) {
- int v;
- Record(1, s + 0);
- while ((v = res->coeffs[n++]) == 0) {
- Record(0, s + 1);
- s = res->stats[VP8EncBands[n]][0];
- }
- Record(1, s + 1);
- if (!Record(2u < (unsigned int)(v + 1), s + 2)) { // v = -1 or 1
- s = res->stats[VP8EncBands[n]][1];
- } else {
- v = abs(v);
-#if !defined(USE_LEVEL_CODE_TABLE)
- if (!Record(v > 4, s + 3)) {
- if (Record(v != 2, s + 4))
- Record(v == 4, s + 5);
- } else if (!Record(v > 10, s + 6)) {
- Record(v > 6, s + 7);
- } else if (!Record((v >= 3 + (8 << 2)), s + 8)) {
- Record((v >= 3 + (8 << 1)), s + 9);
- } else {
- Record((v >= 3 + (8 << 3)), s + 10);
- }
-#else
- if (v > MAX_VARIABLE_LEVEL)
- v = MAX_VARIABLE_LEVEL;
-
- {
- const int bits = VP8LevelCodes[v - 1][1];
- int pattern = VP8LevelCodes[v - 1][0];
- int i;
- for (i = 0; (pattern >>= 1) != 0; ++i) {
- const int mask = 2 << i;
- if (pattern & 1) Record(!!(bits & mask), s + 3 + i);
- }
- }
-#endif
- s = res->stats[VP8EncBands[n]][2];
- }
- }
- if (n < 16) Record(0, s + 0);
- return 1;
-}
-
// Collect statistics and deduce probabilities for next coding pass.
// Return the total bit-cost for coding the probability updates.
static int CalcTokenProba(int nb, int total) {
@@ -174,8 +135,12 @@ static int BranchCost(int nb, int total, int proba) {
return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba);
}
-static int FinalizeTokenProbas(VP8Encoder* const enc) {
- VP8Proba* const proba = &enc->proba_;
+static void ResetTokenStats(VP8Encoder* const enc) {
+ VP8EncProba* const proba = &enc->proba_;
+ memset(proba->stats_, 0, sizeof(proba->stats_));
+}
+
+static int FinalizeTokenProbas(VP8EncProba* const proba) {
int has_changed = 0;
int size = 0;
int t, b, c, p;
@@ -212,129 +177,44 @@ static int FinalizeTokenProbas(VP8Encoder* const enc) {
}
//------------------------------------------------------------------------------
-// helper functions for residuals struct VP8Residual.
-
-static void InitResidual(int first, int coeff_type,
- VP8Encoder* const enc, VP8Residual* const res) {
- res->coeff_type = coeff_type;
- res->prob = enc->proba_.coeffs_[coeff_type];
- res->stats = enc->proba_.stats_[coeff_type];
- res->cost = enc->proba_.level_cost_[coeff_type];
- res->first = first;
-}
+// Finalize Segment probability based on the coding tree
-static void SetResidualCoeffs(const int16_t* const coeffs,
- VP8Residual* const res) {
- int n;
- res->last = -1;
- for (n = 15; n >= res->first; --n) {
- if (coeffs[n]) {
- res->last = n;
- break;
- }
- }
- res->coeffs = coeffs;
+static int GetProba(int a, int b) {
+ const int total = a + b;
+ return (total == 0) ? 255 // that's the default probability.
+ : (255 * a + total / 2) / total; // rounded proba
}
-//------------------------------------------------------------------------------
-// Mode costs
-
-static int GetResidualCost(int ctx, const VP8Residual* const res) {
- int n = res->first;
- int p0 = res->prob[VP8EncBands[n]][ctx][0];
- const uint16_t* t = res->cost[VP8EncBands[n]][ctx];
- int cost;
+static void SetSegmentProbas(VP8Encoder* const enc) {
+ int p[NUM_MB_SEGMENTS] = { 0 };
+ int n;
- if (res->last < 0) {
- return VP8BitCost(0, p0);
- }
- cost = 0;
- while (n <= res->last) {
- const int v = res->coeffs[n];
- const int b = VP8EncBands[n + 1];
- ++n;
- if (v == 0) {
- // short-case for VP8LevelCost(t, 0) (note: VP8LevelFixedCosts[0] == 0):
- cost += t[0];
- t = res->cost[b][0];
- continue;
- }
- cost += VP8BitCost(1, p0);
- if (2u >= (unsigned int)(v + 1)) { // v = -1 or 1
- // short-case for "VP8LevelCost(t, 1)" (256 is VP8LevelFixedCosts[1]):
- cost += 256 + t[1];
- p0 = res->prob[b][1][0];
- t = res->cost[b][1];
- } else {
- cost += VP8LevelCost(t, abs(v));
- p0 = res->prob[b][2][0];
- t = res->cost[b][2];
- }
+ for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) {
+ const VP8MBInfo* const mb = &enc->mb_info_[n];
+ p[mb->segment_]++;
}
- if (n < 16) cost += VP8BitCost(0, p0);
- return cost;
-}
-
-int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) {
- const int x = (it->i4_ & 3), y = (it->i4_ >> 2);
- VP8Residual res;
- VP8Encoder* const enc = it->enc_;
- int R = 0;
- int ctx;
-
- InitResidual(0, 3, enc, &res);
- ctx = it->top_nz_[x] + it->left_nz_[y];
- SetResidualCoeffs(levels, &res);
- R += GetResidualCost(ctx, &res);
- return R;
-}
-
-int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd) {
- VP8Residual res;
- VP8Encoder* const enc = it->enc_;
- int x, y;
- int R = 0;
-
- VP8IteratorNzToBytes(it); // re-import the non-zero context
-
- // DC
- InitResidual(0, 1, enc, &res);
- SetResidualCoeffs(rd->y_dc_levels, &res);
- R += GetResidualCost(it->top_nz_[8] + it->left_nz_[8], &res);
-
- // AC
- InitResidual(1, 0, enc, &res);
- for (y = 0; y < 4; ++y) {
- for (x = 0; x < 4; ++x) {
- const int ctx = it->top_nz_[x] + it->left_nz_[y];
- SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
- R += GetResidualCost(ctx, &res);
- it->top_nz_[x] = it->left_nz_[y] = (res.last >= 0);
+ if (enc->pic_->stats != NULL) {
+ for (n = 0; n < NUM_MB_SEGMENTS; ++n) {
+ enc->pic_->stats->segment_size[n] = p[n];
}
}
- return R;
-}
-
-int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) {
- VP8Residual res;
- VP8Encoder* const enc = it->enc_;
- int ch, x, y;
- int R = 0;
-
- VP8IteratorNzToBytes(it); // re-import the non-zero context
-
- InitResidual(0, 2, enc, &res);
- for (ch = 0; ch <= 2; ch += 2) {
- for (y = 0; y < 2; ++y) {
- for (x = 0; x < 2; ++x) {
- const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
- SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
- R += GetResidualCost(ctx, &res);
- it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = (res.last >= 0);
- }
- }
+ if (enc->segment_hdr_.num_segments_ > 1) {
+ uint8_t* const probas = enc->proba_.segments_;
+ probas[0] = GetProba(p[0] + p[1], p[2] + p[3]);
+ probas[1] = GetProba(p[0], p[1]);
+ probas[2] = GetProba(p[2], p[3]);
+
+ enc->segment_hdr_.update_map_ =
+ (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255);
+ enc->segment_hdr_.size_ =
+ p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) +
+ p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) +
+ p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) +
+ p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2]));
+ } else {
+ enc->segment_hdr_.update_map_ = 0;
+ enc->segment_hdr_.size_ = 0;
}
- return R;
}
//------------------------------------------------------------------------------
@@ -342,7 +222,8 @@ int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) {
static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) {
int n = res->first;
- const uint8_t* p = res->prob[VP8EncBands[n]][ctx];
+ // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
+ const uint8_t* p = res->prob[n][ctx];
if (!VP8PutBit(bw, res->last >= 0, p[0])) {
return 0;
}
@@ -371,30 +252,30 @@ static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) {
} else {
int mask;
const uint8_t* tab;
- if (v < 3 + (8 << 1)) { // kCat3 (3b)
+ if (v < 3 + (8 << 1)) { // VP8Cat3 (3b)
VP8PutBit(bw, 0, p[8]);
VP8PutBit(bw, 0, p[9]);
v -= 3 + (8 << 0);
mask = 1 << 2;
- tab = kCat3;
- } else if (v < 3 + (8 << 2)) { // kCat4 (4b)
+ tab = VP8Cat3;
+ } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b)
VP8PutBit(bw, 0, p[8]);
VP8PutBit(bw, 1, p[9]);
v -= 3 + (8 << 1);
mask = 1 << 3;
- tab = kCat4;
- } else if (v < 3 + (8 << 3)) { // kCat5 (5b)
+ tab = VP8Cat4;
+ } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b)
VP8PutBit(bw, 1, p[8]);
VP8PutBit(bw, 0, p[10]);
v -= 3 + (8 << 2);
mask = 1 << 4;
- tab = kCat5;
- } else { // kCat6 (11b)
+ tab = VP8Cat5;
+ } else { // VP8Cat6 (11b)
VP8PutBit(bw, 1, p[8]);
VP8PutBit(bw, 1, p[10]);
v -= 3 + (8 << 3);
mask = 1 << 10;
- tab = kCat6;
+ tab = VP8Cat6;
}
while (mask) {
VP8PutBit(bw, !!(v & mask), *tab++);
@@ -411,8 +292,7 @@ static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) {
return 1;
}
-static void CodeResiduals(VP8BitWriter* const bw,
- VP8EncIterator* const it,
+static void CodeResiduals(VP8BitWriter* const bw, VP8EncIterator* const it,
const VP8ModeScore* const rd) {
int x, y, ch;
VP8Residual res;
@@ -425,32 +305,32 @@ static void CodeResiduals(VP8BitWriter* const bw,
pos1 = VP8BitWriterPos(bw);
if (i16) {
- InitResidual(0, 1, enc, &res);
- SetResidualCoeffs(rd->y_dc_levels, &res);
+ VP8InitResidual(0, 1, enc, &res);
+ VP8SetResidualCoeffs(rd->y_dc_levels, &res);
it->top_nz_[8] = it->left_nz_[8] =
PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res);
- InitResidual(1, 0, enc, &res);
+ VP8InitResidual(1, 0, enc, &res);
} else {
- InitResidual(0, 3, enc, &res);
+ VP8InitResidual(0, 3, enc, &res);
}
// luma-AC
for (y = 0; y < 4; ++y) {
for (x = 0; x < 4; ++x) {
const int ctx = it->top_nz_[x] + it->left_nz_[y];
- SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
+ VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res);
}
}
pos2 = VP8BitWriterPos(bw);
// U/V
- InitResidual(0, 2, enc, &res);
+ VP8InitResidual(0, 2, enc, &res);
for (ch = 0; ch <= 2; ch += 2) {
for (y = 0; y < 2; ++y) {
for (x = 0; x < 2; ++x) {
const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
- SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
+ VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
PutCoeffs(bw, ctx, &res);
}
@@ -475,33 +355,33 @@ static void RecordResiduals(VP8EncIterator* const it,
VP8IteratorNzToBytes(it);
if (it->mb_->type_ == 1) { // i16x16
- InitResidual(0, 1, enc, &res);
- SetResidualCoeffs(rd->y_dc_levels, &res);
+ VP8InitResidual(0, 1, enc, &res);
+ VP8SetResidualCoeffs(rd->y_dc_levels, &res);
it->top_nz_[8] = it->left_nz_[8] =
- RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res);
- InitResidual(1, 0, enc, &res);
+ VP8RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res);
+ VP8InitResidual(1, 0, enc, &res);
} else {
- InitResidual(0, 3, enc, &res);
+ VP8InitResidual(0, 3, enc, &res);
}
// luma-AC
for (y = 0; y < 4; ++y) {
for (x = 0; x < 4; ++x) {
const int ctx = it->top_nz_[x] + it->left_nz_[y];
- SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
- it->top_nz_[x] = it->left_nz_[y] = RecordCoeffs(ctx, &res);
+ VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
+ it->top_nz_[x] = it->left_nz_[y] = VP8RecordCoeffs(ctx, &res);
}
}
// U/V
- InitResidual(0, 2, enc, &res);
+ VP8InitResidual(0, 2, enc, &res);
for (ch = 0; ch <= 2; ch += 2) {
for (y = 0; y < 2; ++y) {
for (x = 0; x < 2; ++x) {
const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
- SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
+ VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
- RecordCoeffs(ctx, &res);
+ VP8RecordCoeffs(ctx, &res);
}
}
}
@@ -512,176 +392,59 @@ static void RecordResiduals(VP8EncIterator* const it,
//------------------------------------------------------------------------------
// Token buffer
-#ifdef USE_TOKEN_BUFFER
-
-void VP8TBufferInit(VP8TBuffer* const b) {
- b->rows_ = NULL;
- b->tokens_ = NULL;
- b->last_ = &b->rows_;
- b->left_ = 0;
- b->error_ = 0;
-}
-
-int VP8TBufferNewPage(VP8TBuffer* const b) {
- VP8Tokens* const page = b->error_ ? NULL : (VP8Tokens*)malloc(sizeof(*page));
- if (page == NULL) {
- b->error_ = 1;
- return 0;
- }
- *b->last_ = page;
- b->last_ = &page->next_;
- b->left_ = MAX_NUM_TOKEN;
- b->tokens_ = page->tokens_;
- return 1;
-}
-
-void VP8TBufferClear(VP8TBuffer* const b) {
- if (b != NULL) {
- const VP8Tokens* p = b->rows_;
- while (p != NULL) {
- const VP8Tokens* const next = p->next_;
- free((void*)p);
- p = next;
- }
- VP8TBufferInit(b);
- }
-}
-
-int VP8EmitTokens(const VP8TBuffer* const b, VP8BitWriter* const bw,
- const uint8_t* const probas) {
- VP8Tokens* p = b->rows_;
- if (b->error_) return 0;
- while (p != NULL) {
- const int N = (p->next_ == NULL) ? b->left_ : 0;
- int n = MAX_NUM_TOKEN;
- while (n-- > N) {
- VP8PutBit(bw, (p->tokens_[n] >> 15) & 1, probas[p->tokens_[n] & 0x7fff]);
- }
- p = p->next_;
- }
- return 1;
-}
-
-#define TOKEN_ID(b, ctx, p) ((p) + NUM_PROBAS * ((ctx) + (b) * NUM_CTX))
-
-static int RecordCoeffTokens(int ctx, const VP8Residual* const res,
- VP8TBuffer* tokens) {
- int n = res->first;
- int b = VP8EncBands[n];
- if (!VP8AddToken(tokens, res->last >= 0, TOKEN_ID(b, ctx, 0))) {
- return 0;
- }
-
- while (n < 16) {
- const int c = res->coeffs[n++];
- const int sign = c < 0;
- int v = sign ? -c : c;
- const int base_id = TOKEN_ID(b, ctx, 0);
- if (!VP8AddToken(tokens, v != 0, base_id + 1)) {
- b = VP8EncBands[n];
- ctx = 0;
- continue;
- }
- if (!VP8AddToken(tokens, v > 1, base_id + 2)) {
- b = VP8EncBands[n];
- ctx = 1;
- } else {
- if (!VP8AddToken(tokens, v > 4, base_id + 3)) {
- if (VP8AddToken(tokens, v != 2, base_id + 4))
- VP8AddToken(tokens, v == 4, base_id + 5);
- } else if (!VP8AddToken(tokens, v > 10, base_id + 6)) {
- if (!VP8AddToken(tokens, v > 6, base_id + 7)) {
-// VP8AddToken(tokens, v == 6, 159);
- } else {
-// VP8AddToken(tokens, v >= 9, 165);
-// VP8AddToken(tokens, !(v & 1), 145);
- }
- } else {
- int mask;
- const uint8_t* tab;
- if (v < 3 + (8 << 1)) { // kCat3 (3b)
- VP8AddToken(tokens, 0, base_id + 8);
- VP8AddToken(tokens, 0, base_id + 9);
- v -= 3 + (8 << 0);
- mask = 1 << 2;
- tab = kCat3;
- } else if (v < 3 + (8 << 2)) { // kCat4 (4b)
- VP8AddToken(tokens, 0, base_id + 8);
- VP8AddToken(tokens, 1, base_id + 9);
- v -= 3 + (8 << 1);
- mask = 1 << 3;
- tab = kCat4;
- } else if (v < 3 + (8 << 3)) { // kCat5 (5b)
- VP8AddToken(tokens, 1, base_id + 8);
- VP8AddToken(tokens, 0, base_id + 10);
- v -= 3 + (8 << 2);
- mask = 1 << 4;
- tab = kCat5;
- } else { // kCat6 (11b)
- VP8AddToken(tokens, 1, base_id + 8);
- VP8AddToken(tokens, 1, base_id + 10);
- v -= 3 + (8 << 3);
- mask = 1 << 10;
- tab = kCat6;
- }
- while (mask) {
- // VP8AddToken(tokens, !!(v & mask), *tab++);
- mask >>= 1;
- }
- }
- ctx = 2;
- }
- b = VP8EncBands[n];
- // VP8PutBitUniform(bw, sign);
- if (n == 16 || !VP8AddToken(tokens, n <= res->last, TOKEN_ID(b, ctx, 0))) {
- return 1; // EOB
- }
- }
- return 1;
-}
+#if !defined(DISABLE_TOKEN_BUFFER)
-static void RecordTokens(VP8EncIterator* const it,
- const VP8ModeScore* const rd, VP8TBuffer tokens[2]) {
+static int RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd,
+ VP8TBuffer* const tokens) {
int x, y, ch;
VP8Residual res;
VP8Encoder* const enc = it->enc_;
VP8IteratorNzToBytes(it);
if (it->mb_->type_ == 1) { // i16x16
- InitResidual(0, 1, enc, &res);
- SetResidualCoeffs(rd->y_dc_levels, &res);
-// TODO(skal): FIX -> it->top_nz_[8] = it->left_nz_[8] =
- RecordCoeffTokens(it->top_nz_[8] + it->left_nz_[8], &res, &tokens[0]);
- InitResidual(1, 0, enc, &res);
+ const int ctx = it->top_nz_[8] + it->left_nz_[8];
+ VP8InitResidual(0, 1, enc, &res);
+ VP8SetResidualCoeffs(rd->y_dc_levels, &res);
+ it->top_nz_[8] = it->left_nz_[8] =
+ VP8RecordCoeffTokens(ctx, 1,
+ res.first, res.last, res.coeffs, tokens);
+ VP8RecordCoeffs(ctx, &res);
+ VP8InitResidual(1, 0, enc, &res);
} else {
- InitResidual(0, 3, enc, &res);
+ VP8InitResidual(0, 3, enc, &res);
}
// luma-AC
for (y = 0; y < 4; ++y) {
for (x = 0; x < 4; ++x) {
const int ctx = it->top_nz_[x] + it->left_nz_[y];
- SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
+ VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
it->top_nz_[x] = it->left_nz_[y] =
- RecordCoeffTokens(ctx, &res, &tokens[0]);
+ VP8RecordCoeffTokens(ctx, res.coeff_type,
+ res.first, res.last, res.coeffs, tokens);
+ VP8RecordCoeffs(ctx, &res);
}
}
// U/V
- InitResidual(0, 2, enc, &res);
+ VP8InitResidual(0, 2, enc, &res);
for (ch = 0; ch <= 2; ch += 2) {
for (y = 0; y < 2; ++y) {
for (x = 0; x < 2; ++x) {
const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
- SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
+ VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
- RecordCoeffTokens(ctx, &res, &tokens[1]);
+ VP8RecordCoeffTokens(ctx, 2,
+ res.first, res.last, res.coeffs, tokens);
+ VP8RecordCoeffs(ctx, &res);
}
}
}
+ VP8IteratorBytesToNz(it);
+ return !tokens->error_;
}
-#endif // USE_TOKEN_BUFFER
+#endif // !DISABLE_TOKEN_BUFFER
//------------------------------------------------------------------------------
// ExtraInfo map / Debug function
@@ -697,7 +460,10 @@ static void SetBlock(uint8_t* p, int value, int size) {
#endif
static void ResetSSE(VP8Encoder* const enc) {
- memset(enc->sse_, 0, sizeof(enc->sse_));
+ enc->sse_[0] = 0;
+ enc->sse_[1] = 0;
+ enc->sse_[2] = 0;
+ // Note: enc->sse_[3] is managed by alpha.c
enc->sse_count_ = 0;
}
@@ -706,9 +472,9 @@ static void StoreSSE(const VP8EncIterator* const it) {
const uint8_t* const in = it->yuv_in_;
const uint8_t* const out = it->yuv_out_;
// Note: not totally accurate at boundary. And doesn't include in-loop filter.
- enc->sse_[0] += VP8SSE16x16(in + Y_OFF, out + Y_OFF);
- enc->sse_[1] += VP8SSE8x8(in + U_OFF, out + U_OFF);
- enc->sse_[2] += VP8SSE8x8(in + V_OFF, out + V_OFF);
+ enc->sse_[0] += VP8SSE16x16(in + Y_OFF_ENC, out + Y_OFF_ENC);
+ enc->sse_[1] += VP8SSE8x8(in + U_OFF_ENC, out + U_OFF_ENC);
+ enc->sse_[2] += VP8SSE8x8(in + V_OFF_ENC, out + V_OFF_ENC);
enc->sse_count_ += 16 * 16;
}
@@ -736,72 +502,163 @@ static void StoreSideInfo(const VP8EncIterator* const it) {
const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3);
*info = (b > 255) ? 255 : b; break;
}
+ case 7: *info = mb->alpha_; break;
default: *info = 0; break;
- };
+ }
}
#if SEGMENT_VISU // visualize segments and prediction modes
- SetBlock(it->yuv_out_ + Y_OFF, mb->segment_ * 64, 16);
- SetBlock(it->yuv_out_ + U_OFF, it->preds_[0] * 64, 8);
- SetBlock(it->yuv_out_ + V_OFF, mb->uv_mode_ * 64, 8);
+ SetBlock(it->yuv_out_ + Y_OFF_ENC, mb->segment_ * 64, 16);
+ SetBlock(it->yuv_out_ + U_OFF_ENC, it->preds_[0] * 64, 8);
+ SetBlock(it->yuv_out_ + V_OFF_ENC, mb->uv_mode_ * 64, 8);
#endif
}
-//------------------------------------------------------------------------------
-// Main loops
-//
-// VP8EncLoop(): does the final bitstream coding.
-
-static void ResetAfterSkip(VP8EncIterator* const it) {
- if (it->mb_->type_ == 1) {
- *it->nz_ = 0; // reset all predictors
- it->left_nz_[8] = 0;
- } else {
- *it->nz_ &= (1 << 24); // preserve the dc_nz bit
- }
+static double GetPSNR(uint64_t mse, uint64_t size) {
+ return (mse > 0 && size > 0) ? 10. * log10(255. * 255. * size / mse) : 99;
}
-int VP8EncLoop(VP8Encoder* const enc) {
- int i, s, p;
- int ok = 1;
- VP8EncIterator it;
- VP8ModeScore info;
- const int dont_use_skip = !enc->proba_.use_skip_proba_;
- const int rd_opt = enc->rd_opt_level_;
- const int kAverageBytesPerMB = 5; // TODO: have a kTable[quality/10]
- const int bytes_per_parts =
- enc->mb_w_ * enc->mb_h_ * kAverageBytesPerMB / enc->num_parts_;
+//------------------------------------------------------------------------------
+// StatLoop(): only collect statistics (number of skips, token usage, ...).
+// This is used for deciding optimal probabilities. It also modifies the
+// quantizer value if some target (size, PSNR) was specified.
- // Initialize the bit-writers
- for (p = 0; p < enc->num_parts_; ++p) {
- VP8BitWriterInit(enc->parts_ + p, bytes_per_parts);
- }
+static void SetLoopParams(VP8Encoder* const enc, float q) {
+ // Make sure the quality parameter is inside valid bounds
+ q = Clamp(q, 0.f, 100.f);
+
+ VP8SetSegmentParams(enc, q); // setup segment quantizations and filters
+ SetSegmentProbas(enc); // compute segment probabilities
ResetStats(enc);
ResetSSE(enc);
+}
+
+static uint64_t OneStatPass(VP8Encoder* const enc, VP8RDLevel rd_opt,
+ int nb_mbs, int percent_delta,
+ PassStats* const s) {
+ VP8EncIterator it;
+ uint64_t size = 0;
+ uint64_t size_p0 = 0;
+ uint64_t distortion = 0;
+ const uint64_t pixel_count = nb_mbs * 384;
VP8IteratorInit(enc, &it);
- VP8InitFilter(&it);
+ SetLoopParams(enc, s->q);
do {
- VP8IteratorImport(&it);
- // Warning! order is important: first call VP8Decimate() and
- // *then* decide how to code the skip decision if there's one.
- if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) {
- CodeResiduals(it.bw_, &it, &info);
- } else { // reset predictors after a skip
- ResetAfterSkip(&it);
+ VP8ModeScore info;
+ VP8IteratorImport(&it, NULL);
+ if (VP8Decimate(&it, &info, rd_opt)) {
+ // Just record the number of skips and act like skip_proba is not used.
+ enc->proba_.nb_skip_++;
}
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- if (enc->use_layer_) {
- VP8EncCodeLayerBlock(&it);
+ RecordResiduals(&it, &info);
+ size += info.R + info.H;
+ size_p0 += info.H;
+ distortion += info.D;
+ if (percent_delta && !VP8IteratorProgress(&it, percent_delta))
+ return 0;
+ VP8IteratorSaveBoundary(&it);
+ } while (VP8IteratorNext(&it) && --nb_mbs > 0);
+
+ size_p0 += enc->segment_hdr_.size_;
+ if (s->do_size_search) {
+ size += FinalizeSkipProba(enc);
+ size += FinalizeTokenProbas(&enc->proba_);
+ size = ((size + size_p0 + 1024) >> 11) + HEADER_SIZE_ESTIMATE;
+ s->value = (double)size;
+ } else {
+ s->value = GetPSNR(distortion, pixel_count);
+ }
+ return size_p0;
+}
+
+static int StatLoop(VP8Encoder* const enc) {
+ const int method = enc->method_;
+ const int do_search = enc->do_search_;
+ const int fast_probe = ((method == 0 || method == 3) && !do_search);
+ int num_pass_left = enc->config_->pass;
+ const int task_percent = 20;
+ const int percent_per_pass =
+ (task_percent + num_pass_left / 2) / num_pass_left;
+ const int final_percent = enc->percent_ + task_percent;
+ const VP8RDLevel rd_opt =
+ (method >= 3 || do_search) ? RD_OPT_BASIC : RD_OPT_NONE;
+ int nb_mbs = enc->mb_w_ * enc->mb_h_;
+ PassStats stats;
+
+ InitPassStats(enc, &stats);
+ ResetTokenStats(enc);
+
+ // Fast mode: quick analysis pass over few mbs. Better than nothing.
+ if (fast_probe) {
+ if (method == 3) { // we need more stats for method 3 to be reliable.
+ nb_mbs = (nb_mbs > 200) ? nb_mbs >> 1 : 100;
+ } else {
+ nb_mbs = (nb_mbs > 200) ? nb_mbs >> 2 : 50;
}
+ }
+
+ while (num_pass_left-- > 0) {
+ const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) ||
+ (num_pass_left == 0) ||
+ (enc->max_i4_header_bits_ == 0);
+ const uint64_t size_p0 =
+ OneStatPass(enc, rd_opt, nb_mbs, percent_per_pass, &stats);
+ if (size_p0 == 0) return 0;
+#if (DEBUG_SEARCH > 0)
+ printf("#%d value:%.1lf -> %.1lf q:%.2f -> %.2f\n",
+ num_pass_left, stats.last_value, stats.value, stats.last_q, stats.q);
#endif
- StoreSideInfo(&it);
- VP8StoreFilterStats(&it);
- VP8IteratorExport(&it);
- ok = VP8IteratorProgress(&it, 20);
- } while (ok && VP8IteratorNext(&it, it.yuv_out_));
+ if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) {
+ ++num_pass_left;
+ enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation...
+ continue; // ...and start over
+ }
+ if (is_last_pass) {
+ break;
+ }
+ // If no target size: just do several pass without changing 'q'
+ if (do_search) {
+ ComputeNextQ(&stats);
+ if (fabs(stats.dq) <= DQ_LIMIT) break;
+ }
+ }
+ if (!do_search || !stats.do_size_search) {
+ // Need to finalize probas now, since it wasn't done during the search.
+ FinalizeSkipProba(enc);
+ FinalizeTokenProbas(&enc->proba_);
+ }
+ VP8CalculateLevelCosts(&enc->proba_); // finalize costs
+ return WebPReportProgress(enc->pic_, final_percent, &enc->percent_);
+}
+
+//------------------------------------------------------------------------------
+// Main loops
+//
+
+static const int kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 };
+static int PreLoopInitialize(VP8Encoder* const enc) {
+ int p;
+ int ok = 1;
+ const int average_bytes_per_MB = kAverageBytesPerMB[enc->base_quant_ >> 4];
+ const int bytes_per_parts =
+ enc->mb_w_ * enc->mb_h_ * average_bytes_per_MB / enc->num_parts_;
+ // Initialize the bit-writers
+ for (p = 0; ok && p < enc->num_parts_; ++p) {
+ ok = VP8BitWriterInit(enc->parts_ + p, bytes_per_parts);
+ }
+ if (!ok) {
+ VP8EncFreeBitWriters(enc); // malloc error occurred
+ WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
+ }
+ return ok;
+}
+
+static int PostLoopFinalize(VP8EncIterator* const it, int ok) {
+ VP8Encoder* const enc = it->enc_;
if (ok) { // Finalize the partitions, check for extra errors.
+ int p;
for (p = 0; p < enc->num_parts_; ++p) {
VP8BitWriterFinish(enc->parts_ + p);
ok &= !enc->parts_[p].error_;
@@ -809,131 +666,185 @@ int VP8EncLoop(VP8Encoder* const enc) {
}
if (ok) { // All good. Finish up.
- if (enc->pic_->stats) { // finalize byte counters...
+ if (enc->pic_->stats != NULL) { // finalize byte counters...
+ int i, s;
for (i = 0; i <= 2; ++i) {
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- enc->residual_bytes_[i][s] = (int)((it.bit_count_[s][i] + 7) >> 3);
+ enc->residual_bytes_[i][s] = (int)((it->bit_count_[s][i] + 7) >> 3);
}
}
}
- VP8AdjustFilterStrength(&it); // ...and store filter stats.
+ VP8AdjustFilterStrength(it); // ...and store filter stats.
} else {
// Something bad happened -> need to do some memory cleanup.
VP8EncFreeBitWriters(enc);
}
-
return ok;
}
//------------------------------------------------------------------------------
-// VP8StatLoop(): only collect statistics (number of skips, token usage, ...)
-// This is used for deciding optimal probabilities. It also
-// modifies the quantizer value if some target (size, PNSR)
-// was specified.
-
-#define kHeaderSizeEstimate (15 + 20 + 10) // TODO: fix better
-
-static int OneStatPass(VP8Encoder* const enc, float q, int rd_opt, int nb_mbs,
- float* const PSNR, int percent_delta) {
- VP8EncIterator it;
- uint64_t size = 0;
- uint64_t distortion = 0;
- const uint64_t pixel_count = nb_mbs * 384;
+// VP8EncLoop(): does the final bitstream coding.
- // Make sure the quality parameter is inside valid bounds
- if (q < 0.) {
- q = 0;
- } else if (q > 100.) {
- q = 100;
+static void ResetAfterSkip(VP8EncIterator* const it) {
+ if (it->mb_->type_ == 1) {
+ *it->nz_ = 0; // reset all predictors
+ it->left_nz_[8] = 0;
+ } else {
+ *it->nz_ &= (1 << 24); // preserve the dc_nz bit
}
+}
- VP8SetSegmentParams(enc, q); // setup segment quantizations and filters
+int VP8EncLoop(VP8Encoder* const enc) {
+ VP8EncIterator it;
+ int ok = PreLoopInitialize(enc);
+ if (!ok) return 0;
- ResetStats(enc);
- ResetTokenStats(enc);
+ StatLoop(enc); // stats-collection loop
VP8IteratorInit(enc, &it);
+ VP8InitFilter(&it);
do {
VP8ModeScore info;
- VP8IteratorImport(&it);
- if (VP8Decimate(&it, &info, rd_opt)) {
- // Just record the number of skips and act like skip_proba is not used.
- enc->proba_.nb_skip_++;
+ const int dont_use_skip = !enc->proba_.use_skip_proba_;
+ const VP8RDLevel rd_opt = enc->rd_opt_level_;
+
+ VP8IteratorImport(&it, NULL);
+ // Warning! order is important: first call VP8Decimate() and
+ // *then* decide how to code the skip decision if there's one.
+ if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) {
+ CodeResiduals(it.bw_, &it, &info);
+ } else { // reset predictors after a skip
+ ResetAfterSkip(&it);
}
- RecordResiduals(&it, &info);
- size += info.R;
- distortion += info.D;
- if (percent_delta && !VP8IteratorProgress(&it, percent_delta))
- return 0;
- } while (VP8IteratorNext(&it, it.yuv_out_) && --nb_mbs > 0);
- size += FinalizeSkipProba(enc);
- size += FinalizeTokenProbas(enc);
- size += enc->segment_hdr_.size_;
- size = ((size + 1024) >> 11) + kHeaderSizeEstimate;
-
- if (PSNR) {
- *PSNR = (float)(10.* log10(255. * 255. * pixel_count / distortion));
- }
- return (int)size;
+ StoreSideInfo(&it);
+ VP8StoreFilterStats(&it);
+ VP8IteratorExport(&it);
+ ok = VP8IteratorProgress(&it, 20);
+ VP8IteratorSaveBoundary(&it);
+ } while (ok && VP8IteratorNext(&it));
+
+ return PostLoopFinalize(&it, ok);
}
-// successive refinement increments.
-static const int dqs[] = { 20, 15, 10, 8, 6, 4, 2, 1, 0 };
+//------------------------------------------------------------------------------
+// Single pass using Token Buffer.
-int VP8StatLoop(VP8Encoder* const enc) {
- const int do_search =
- (enc->config_->target_size > 0 || enc->config_->target_PSNR > 0);
- const int fast_probe = (enc->method_ < 2 && !do_search);
- float q = enc->config_->quality;
- const int max_passes = enc->config_->pass;
- const int task_percent = 20;
- const int percent_per_pass = (task_percent + max_passes / 2) / max_passes;
- const int final_percent = enc->percent_ + task_percent;
- int pass;
- int nb_mbs;
+#if !defined(DISABLE_TOKEN_BUFFER)
- // Fast mode: quick analysis pass over few mbs. Better than nothing.
- nb_mbs = enc->mb_w_ * enc->mb_h_;
- if (fast_probe && nb_mbs > 100) nb_mbs = 100;
-
- // No target size: just do several pass without changing 'q'
- if (!do_search) {
- for (pass = 0; pass < max_passes; ++pass) {
- const int rd_opt = (enc->method_ > 2);
- if (!OneStatPass(enc, q, rd_opt, nb_mbs, NULL, percent_per_pass)) {
- return 0;
- }
+#define MIN_COUNT 96 // minimum number of macroblocks before updating stats
+
+int VP8EncTokenLoop(VP8Encoder* const enc) {
+ // Roughly refresh the proba eight times per pass
+ int max_count = (enc->mb_w_ * enc->mb_h_) >> 3;
+ int num_pass_left = enc->config_->pass;
+ const int do_search = enc->do_search_;
+ VP8EncIterator it;
+ VP8EncProba* const proba = &enc->proba_;
+ const VP8RDLevel rd_opt = enc->rd_opt_level_;
+ const uint64_t pixel_count = enc->mb_w_ * enc->mb_h_ * 384;
+ PassStats stats;
+ int ok;
+
+ InitPassStats(enc, &stats);
+ ok = PreLoopInitialize(enc);
+ if (!ok) return 0;
+
+ if (max_count < MIN_COUNT) max_count = MIN_COUNT;
+
+ assert(enc->num_parts_ == 1);
+ assert(enc->use_tokens_);
+ assert(proba->use_skip_proba_ == 0);
+ assert(rd_opt >= RD_OPT_BASIC); // otherwise, token-buffer won't be useful
+ assert(num_pass_left > 0);
+
+ while (ok && num_pass_left-- > 0) {
+ const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) ||
+ (num_pass_left == 0) ||
+ (enc->max_i4_header_bits_ == 0);
+ uint64_t size_p0 = 0;
+ uint64_t distortion = 0;
+ int cnt = max_count;
+ VP8IteratorInit(enc, &it);
+ SetLoopParams(enc, stats.q);
+ if (is_last_pass) {
+ ResetTokenStats(enc);
+ VP8InitFilter(&it); // don't collect stats until last pass (too costly)
}
- } else {
- // binary search for a size close to target
- for (pass = 0; pass < max_passes && (dqs[pass] > 0); ++pass) {
- const int rd_opt = 1;
- float PSNR;
- int criterion;
- const int size = OneStatPass(enc, q, rd_opt, nb_mbs, &PSNR,
- percent_per_pass);
-#if DEBUG_SEARCH
- printf("#%d size=%d PSNR=%.2f q=%.2f\n", pass, size, PSNR, q);
-#endif
- if (!size) return 0;
- if (enc->config_->target_PSNR > 0) {
- criterion = (PSNR < enc->config_->target_PSNR);
- } else {
- criterion = (size < enc->config_->target_size);
+ VP8TBufferClear(&enc->tokens_);
+ do {
+ VP8ModeScore info;
+ VP8IteratorImport(&it, NULL);
+ if (--cnt < 0) {
+ FinalizeTokenProbas(proba);
+ VP8CalculateLevelCosts(proba); // refresh cost tables for rd-opt
+ cnt = max_count;
}
- // dichotomize
- if (criterion) {
- q += dqs[pass];
- } else {
- q -= dqs[pass];
+ VP8Decimate(&it, &info, rd_opt);
+ ok = RecordTokens(&it, &info, &enc->tokens_);
+ if (!ok) {
+ WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
+ break;
+ }
+ size_p0 += info.H;
+ distortion += info.D;
+ if (is_last_pass) {
+ StoreSideInfo(&it);
+ VP8StoreFilterStats(&it);
+ VP8IteratorExport(&it);
+ ok = VP8IteratorProgress(&it, 20);
}
+ VP8IteratorSaveBoundary(&it);
+ } while (ok && VP8IteratorNext(&it));
+ if (!ok) break;
+
+ size_p0 += enc->segment_hdr_.size_;
+ if (stats.do_size_search) {
+ uint64_t size = FinalizeTokenProbas(&enc->proba_);
+ size += VP8EstimateTokenSize(&enc->tokens_,
+ (const uint8_t*)proba->coeffs_);
+ size = (size + size_p0 + 1024) >> 11; // -> size in bytes
+ size += HEADER_SIZE_ESTIMATE;
+ stats.value = (double)size;
+ } else { // compute and store PSNR
+ stats.value = GetPSNR(distortion, pixel_count);
+ }
+
+#if (DEBUG_SEARCH > 0)
+ printf("#%2d metric:%.1lf -> %.1lf last_q=%.2lf q=%.2lf dq=%.2lf\n",
+ num_pass_left, stats.last_value, stats.value,
+ stats.last_q, stats.q, stats.dq);
+#endif
+ if (size_p0 > PARTITION0_SIZE_LIMIT) {
+ ++num_pass_left;
+ enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation...
+ continue; // ...and start over
+ }
+ if (is_last_pass) {
+ break; // done
+ }
+ if (do_search) {
+ ComputeNextQ(&stats); // Adjust q
}
}
- return WebPReportProgress(enc->pic_, final_percent, &enc->percent_);
+ if (ok) {
+ if (!stats.do_size_search) {
+ FinalizeTokenProbas(&enc->proba_);
+ }
+ ok = VP8EmitTokens(&enc->tokens_, enc->parts_ + 0,
+ (const uint8_t*)proba->coeffs_, 1);
+ }
+ ok = ok && WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_);
+ return PostLoopFinalize(&it, ok);
+}
+
+#else
+
+int VP8EncTokenLoop(VP8Encoder* const enc) {
+ (void)enc;
+ return 0; // we shouldn't be here.
}
+#endif // DISABLE_TOKEN_BUFFER
+
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/enc/histogram.c b/drivers/webp/enc/histogram.c
index ca838e064d..68c27fb1db 100644
--- a/drivers/webp/enc/histogram.c
+++ b/drivers/webp/enc/histogram.c
@@ -1,38 +1,82 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Author: Jyrki Alakuijala (jyrki@google.com)
//
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include "webp/config.h"
#endif
#include <math.h>
-#include <stdio.h>
#include "./backward_references.h"
#include "./histogram.h"
#include "../dsp/lossless.h"
#include "../utils/utils.h"
+#define MAX_COST 1.e38
+
+// Number of partitions for the three dominant (literal, red and blue) symbol
+// costs.
+#define NUM_PARTITIONS 4
+// The size of the bin-hash corresponding to the three dominant costs.
+#define BIN_SIZE (NUM_PARTITIONS * NUM_PARTITIONS * NUM_PARTITIONS)
+// Maximum number of histograms allowed in greedy combining algorithm.
+#define MAX_HISTO_GREEDY 100
+
static void HistogramClear(VP8LHistogram* const p) {
- memset(p->literal_, 0, sizeof(p->literal_));
- memset(p->red_, 0, sizeof(p->red_));
- memset(p->blue_, 0, sizeof(p->blue_));
- memset(p->alpha_, 0, sizeof(p->alpha_));
- memset(p->distance_, 0, sizeof(p->distance_));
- p->bit_cost_ = 0;
+ uint32_t* const literal = p->literal_;
+ const int cache_bits = p->palette_code_bits_;
+ const int histo_size = VP8LGetHistogramSize(cache_bits);
+ memset(p, 0, histo_size);
+ p->palette_code_bits_ = cache_bits;
+ p->literal_ = literal;
+}
+
+// Swap two histogram pointers.
+static void HistogramSwap(VP8LHistogram** const A, VP8LHistogram** const B) {
+ VP8LHistogram* const tmp = *A;
+ *A = *B;
+ *B = tmp;
+}
+
+static void HistogramCopy(const VP8LHistogram* const src,
+ VP8LHistogram* const dst) {
+ uint32_t* const dst_literal = dst->literal_;
+ const int dst_cache_bits = dst->palette_code_bits_;
+ const int histo_size = VP8LGetHistogramSize(dst_cache_bits);
+ assert(src->palette_code_bits_ == dst_cache_bits);
+ memcpy(dst, src, histo_size);
+ dst->literal_ = dst_literal;
+}
+
+int VP8LGetHistogramSize(int cache_bits) {
+ const int literal_size = VP8LHistogramNumCodes(cache_bits);
+ const size_t total_size = sizeof(VP8LHistogram) + sizeof(int) * literal_size;
+ assert(total_size <= (size_t)0x7fffffff);
+ return (int)total_size;
+}
+
+void VP8LFreeHistogram(VP8LHistogram* const histo) {
+ WebPSafeFree(histo);
+}
+
+void VP8LFreeHistogramSet(VP8LHistogramSet* const histo) {
+ WebPSafeFree(histo);
}
void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs,
VP8LHistogram* const histo) {
- int i;
- for (i = 0; i < refs->size; ++i) {
- VP8LHistogramAddSinglePixOrCopy(histo, &refs->refs[i]);
+ VP8LRefsCursor c = VP8LRefsCursorInit(refs);
+ while (VP8LRefsCursorOk(&c)) {
+ VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos);
+ VP8LRefsCursorNext(&c);
}
}
@@ -51,13 +95,25 @@ void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits) {
HistogramClear(p);
}
+VP8LHistogram* VP8LAllocateHistogram(int cache_bits) {
+ VP8LHistogram* histo = NULL;
+ const int total_size = VP8LGetHistogramSize(cache_bits);
+ uint8_t* const memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory));
+ if (memory == NULL) return NULL;
+ histo = (VP8LHistogram*)memory;
+ // literal_ won't necessary be aligned.
+ histo->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram));
+ VP8LHistogramInit(histo, cache_bits);
+ return histo;
+}
+
VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) {
int i;
VP8LHistogramSet* set;
- VP8LHistogram* bulk;
- const uint64_t total_size = (uint64_t)sizeof(*set)
- + size * sizeof(*set->histograms)
- + size * sizeof(**set->histograms);
+ const int histo_size = VP8LGetHistogramSize(cache_bits);
+ const size_t total_size =
+ sizeof(*set) + size * (sizeof(*set->histograms) +
+ histo_size + WEBP_ALIGN_CST);
uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory));
if (memory == NULL) return NULL;
@@ -65,12 +121,15 @@ VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) {
memory += sizeof(*set);
set->histograms = (VP8LHistogram**)memory;
memory += size * sizeof(*set->histograms);
- bulk = (VP8LHistogram*)memory;
set->max_size = size;
set->size = size;
for (i = 0; i < size; ++i) {
- set->histograms[i] = bulk + i;
+ memory = (uint8_t*)WEBP_ALIGN(memory);
+ set->histograms[i] = (VP8LHistogram*)memory;
+ // literal_ won't necessary be aligned.
+ set->histograms[i]->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram));
VP8LHistogramInit(set->histograms[i], cache_bits);
+ memory += histo_size;
}
return set;
}
@@ -85,151 +144,183 @@ void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
++histo->literal_[PixOrCopyLiteral(v, 1)];
++histo->blue_[PixOrCopyLiteral(v, 0)];
} else if (PixOrCopyIsCacheIdx(v)) {
- int literal_ix = 256 + NUM_LENGTH_CODES + PixOrCopyCacheIdx(v);
+ const int literal_ix =
+ NUM_LITERAL_CODES + NUM_LENGTH_CODES + PixOrCopyCacheIdx(v);
++histo->literal_[literal_ix];
} else {
- int code, extra_bits_count, extra_bits_value;
- PrefixEncode(PixOrCopyLength(v),
- &code, &extra_bits_count, &extra_bits_value);
- ++histo->literal_[256 + code];
- PrefixEncode(PixOrCopyDistance(v),
- &code, &extra_bits_count, &extra_bits_value);
+ int code, extra_bits;
+ VP8LPrefixEncodeBits(PixOrCopyLength(v), &code, &extra_bits);
+ ++histo->literal_[NUM_LITERAL_CODES + code];
+ VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits);
++histo->distance_[code];
}
}
+// -----------------------------------------------------------------------------
+// Various histogram combine/cost-eval functions
+
+static int GetCombinedHistogramEntropy(const VP8LHistogram* const a,
+ const VP8LHistogram* const b,
+ double cost_threshold,
+ double* cost) {
+ const int palette_code_bits = a->palette_code_bits_;
+ assert(a->palette_code_bits_ == b->palette_code_bits_);
+ *cost += VP8LGetCombinedEntropy(a->literal_, b->literal_,
+ VP8LHistogramNumCodes(palette_code_bits));
+ *cost += VP8LExtraCostCombined(a->literal_ + NUM_LITERAL_CODES,
+ b->literal_ + NUM_LITERAL_CODES,
+ NUM_LENGTH_CODES);
+ if (*cost > cost_threshold) return 0;
+
+ *cost += VP8LGetCombinedEntropy(a->red_, b->red_, NUM_LITERAL_CODES);
+ if (*cost > cost_threshold) return 0;
+
+ *cost += VP8LGetCombinedEntropy(a->blue_, b->blue_, NUM_LITERAL_CODES);
+ if (*cost > cost_threshold) return 0;
+
+ *cost += VP8LGetCombinedEntropy(a->alpha_, b->alpha_, NUM_LITERAL_CODES);
+ if (*cost > cost_threshold) return 0;
+
+ *cost += VP8LGetCombinedEntropy(a->distance_, b->distance_,
+ NUM_DISTANCE_CODES);
+ *cost += VP8LExtraCostCombined(a->distance_, b->distance_,
+ NUM_DISTANCE_CODES);
+ if (*cost > cost_threshold) return 0;
+
+ return 1;
+}
-
-static double BitsEntropy(const int* const array, int n) {
- double retval = 0.;
- int sum = 0;
- int nonzeros = 0;
- int max_val = 0;
- int i;
- double mix;
- for (i = 0; i < n; ++i) {
- if (array[i] != 0) {
- sum += array[i];
- ++nonzeros;
- retval -= VP8LFastSLog2(array[i]);
- if (max_val < array[i]) {
- max_val = array[i];
- }
- }
+// Performs out = a + b, computing the cost C(a+b) - C(a) - C(b) while comparing
+// to the threshold value 'cost_threshold'. The score returned is
+// Score = C(a+b) - C(a) - C(b), where C(a) + C(b) is known and fixed.
+// Since the previous score passed is 'cost_threshold', we only need to compare
+// the partial cost against 'cost_threshold + C(a) + C(b)' to possibly bail-out
+// early.
+static double HistogramAddEval(const VP8LHistogram* const a,
+ const VP8LHistogram* const b,
+ VP8LHistogram* const out,
+ double cost_threshold) {
+ double cost = 0;
+ const double sum_cost = a->bit_cost_ + b->bit_cost_;
+ cost_threshold += sum_cost;
+
+ if (GetCombinedHistogramEntropy(a, b, cost_threshold, &cost)) {
+ VP8LHistogramAdd(a, b, out);
+ out->bit_cost_ = cost;
+ out->palette_code_bits_ = a->palette_code_bits_;
+ out->trivial_symbol_ = (a->trivial_symbol_ == b->trivial_symbol_) ?
+ a->trivial_symbol_ : VP8L_NON_TRIVIAL_SYM;
}
- retval += VP8LFastSLog2(sum);
- if (nonzeros < 5) {
- if (nonzeros <= 1) {
- return 0;
- }
- // Two symbols, they will be 0 and 1 in a Huffman code.
- // Let's mix in a bit of entropy to favor good clustering when
- // distributions of these are combined.
- if (nonzeros == 2) {
- return 0.99 * sum + 0.01 * retval;
- }
- // No matter what the entropy says, we cannot be better than min_limit
- // with Huffman coding. I am mixing a bit of entropy into the
- // min_limit since it produces much better (~0.5 %) compression results
- // perhaps because of better entropy clustering.
- if (nonzeros == 3) {
- mix = 0.95;
- } else {
- mix = 0.7; // nonzeros == 4.
- }
- } else {
- mix = 0.627;
- }
+ return cost - sum_cost;
+}
- {
- double min_limit = 2 * sum - max_val;
- min_limit = mix * min_limit + (1.0 - mix) * retval;
- return (retval < min_limit) ? min_limit : retval;
- }
+// Same as HistogramAddEval(), except that the resulting histogram
+// is not stored. Only the cost C(a+b) - C(a) is evaluated. We omit
+// the term C(b) which is constant over all the evaluations.
+static double HistogramAddThresh(const VP8LHistogram* const a,
+ const VP8LHistogram* const b,
+ double cost_threshold) {
+ double cost = -a->bit_cost_;
+ GetCombinedHistogramEntropy(a, b, cost_threshold, &cost);
+ return cost;
}
-double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p) {
- double retval = BitsEntropy(&p->literal_[0], VP8LHistogramNumCodes(p))
- + BitsEntropy(&p->red_[0], 256)
- + BitsEntropy(&p->blue_[0], 256)
- + BitsEntropy(&p->alpha_[0], 256)
- + BitsEntropy(&p->distance_[0], NUM_DISTANCE_CODES);
- // Compute the extra bits cost.
- int i;
- for (i = 2; i < NUM_LENGTH_CODES - 2; ++i) {
- retval +=
- (i >> 1) * p->literal_[256 + i + 2];
- }
- for (i = 2; i < NUM_DISTANCE_CODES - 2; ++i) {
- retval += (i >> 1) * p->distance_[i + 2];
- }
- return retval;
-}
-
-
-// Returns the cost encode the rle-encoded entropy code.
-// The constants in this function are experimental.
-static double HuffmanCost(const int* const population, int length) {
- // Small bias because Huffman code length is typically not stored in
- // full length.
- static const int kHuffmanCodeOfHuffmanCodeSize = CODE_LENGTH_CODES * 3;
- static const double kSmallBias = 9.1;
- double retval = kHuffmanCodeOfHuffmanCodeSize - kSmallBias;
- int streak = 0;
- int i = 0;
- for (; i < length - 1; ++i) {
- ++streak;
- if (population[i] == population[i + 1]) {
- continue;
- }
- last_streak_hack:
- // population[i] points now to the symbol in the streak of same values.
- if (streak > 3) {
- if (population[i] == 0) {
- retval += 1.5625 + 0.234375 * streak;
- } else {
- retval += 2.578125 + 0.703125 * streak;
- }
- } else {
- if (population[i] == 0) {
- retval += 1.796875 * streak;
- } else {
- retval += 3.28125 * streak;
- }
- }
- streak = 0;
- }
- if (i == length - 1) {
- ++streak;
- goto last_streak_hack;
+// -----------------------------------------------------------------------------
+
+// The structure to keep track of cost range for the three dominant entropy
+// symbols.
+// TODO(skal): Evaluate if float can be used here instead of double for
+// representing the entropy costs.
+typedef struct {
+ double literal_max_;
+ double literal_min_;
+ double red_max_;
+ double red_min_;
+ double blue_max_;
+ double blue_min_;
+} DominantCostRange;
+
+static void DominantCostRangeInit(DominantCostRange* const c) {
+ c->literal_max_ = 0.;
+ c->literal_min_ = MAX_COST;
+ c->red_max_ = 0.;
+ c->red_min_ = MAX_COST;
+ c->blue_max_ = 0.;
+ c->blue_min_ = MAX_COST;
+}
+
+static void UpdateDominantCostRange(
+ const VP8LHistogram* const h, DominantCostRange* const c) {
+ if (c->literal_max_ < h->literal_cost_) c->literal_max_ = h->literal_cost_;
+ if (c->literal_min_ > h->literal_cost_) c->literal_min_ = h->literal_cost_;
+ if (c->red_max_ < h->red_cost_) c->red_max_ = h->red_cost_;
+ if (c->red_min_ > h->red_cost_) c->red_min_ = h->red_cost_;
+ if (c->blue_max_ < h->blue_cost_) c->blue_max_ = h->blue_cost_;
+ if (c->blue_min_ > h->blue_cost_) c->blue_min_ = h->blue_cost_;
+}
+
+static void UpdateHistogramCost(VP8LHistogram* const h) {
+ uint32_t alpha_sym, red_sym, blue_sym;
+ const double alpha_cost = VP8LPopulationCost(h->alpha_, NUM_LITERAL_CODES,
+ &alpha_sym);
+ const double distance_cost =
+ VP8LPopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL) +
+ VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES);
+ const int num_codes = VP8LHistogramNumCodes(h->palette_code_bits_);
+ h->literal_cost_ = VP8LPopulationCost(h->literal_, num_codes, NULL) +
+ VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES,
+ NUM_LENGTH_CODES);
+ h->red_cost_ = VP8LPopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym);
+ h->blue_cost_ = VP8LPopulationCost(h->blue_, NUM_LITERAL_CODES, &blue_sym);
+ h->bit_cost_ = h->literal_cost_ + h->red_cost_ + h->blue_cost_ +
+ alpha_cost + distance_cost;
+ if ((alpha_sym | red_sym | blue_sym) == VP8L_NON_TRIVIAL_SYM) {
+ h->trivial_symbol_ = VP8L_NON_TRIVIAL_SYM;
+ } else {
+ h->trivial_symbol_ =
+ ((uint32_t)alpha_sym << 24) | (red_sym << 16) | (blue_sym << 0);
}
- return retval;
}
-// Estimates the Huffman dictionary + other block overhead size.
-static double HistogramEstimateBitsHeader(const VP8LHistogram* const p) {
- return HuffmanCost(&p->alpha_[0], 256) +
- HuffmanCost(&p->red_[0], 256) +
- HuffmanCost(&p->literal_[0], VP8LHistogramNumCodes(p)) +
- HuffmanCost(&p->blue_[0], 256) +
- HuffmanCost(&p->distance_[0], NUM_DISTANCE_CODES);
+static int GetBinIdForEntropy(double min, double max, double val) {
+ const double range = max - min + 1e-6;
+ const double delta = val - min;
+ return (int)(NUM_PARTITIONS * delta / range);
}
-double VP8LHistogramEstimateBits(const VP8LHistogram* const p) {
- return HistogramEstimateBitsHeader(p) + VP8LHistogramEstimateBitsBulk(p);
+static int GetHistoBinIndexLowEffort(
+ const VP8LHistogram* const h, const DominantCostRange* const c) {
+ const int bin_id = GetBinIdForEntropy(c->literal_min_, c->literal_max_,
+ h->literal_cost_);
+ assert(bin_id < NUM_PARTITIONS);
+ return bin_id;
}
-static void HistogramBuildImage(int xsize, int histo_bits,
- const VP8LBackwardRefs* const backward_refs,
- VP8LHistogramSet* const image) {
- int i;
+static int GetHistoBinIndex(
+ const VP8LHistogram* const h, const DominantCostRange* const c) {
+ const int bin_id =
+ GetBinIdForEntropy(c->blue_min_, c->blue_max_, h->blue_cost_) +
+ NUM_PARTITIONS * GetBinIdForEntropy(c->red_min_, c->red_max_,
+ h->red_cost_) +
+ NUM_PARTITIONS * NUM_PARTITIONS * GetBinIdForEntropy(c->literal_min_,
+ c->literal_max_,
+ h->literal_cost_);
+ assert(bin_id < BIN_SIZE);
+ return bin_id;
+}
+
+// Construct the histograms from backward references.
+static void HistogramBuild(
+ int xsize, int histo_bits, const VP8LBackwardRefs* const backward_refs,
+ VP8LHistogramSet* const image_histo) {
int x = 0, y = 0;
const int histo_xsize = VP8LSubSampleSize(xsize, histo_bits);
- VP8LHistogram** const histograms = image->histograms;
+ VP8LHistogram** const histograms = image_histo->histograms;
+ VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs);
assert(histo_bits > 0);
- for (i = 0; i < backward_refs->size; ++i) {
- const PixOrCopy* const v = &backward_refs->refs[i];
+ while (VP8LRefsCursorOk(&c)) {
+ const PixOrCopy* const v = c.cur_pos;
const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits);
VP8LHistogramAddSinglePixOrCopy(histograms[ix], v);
x += PixOrCopyLength(v);
@@ -237,7 +328,134 @@ static void HistogramBuildImage(int xsize, int histo_bits,
x -= xsize;
++y;
}
+ VP8LRefsCursorNext(&c);
+ }
+}
+
+// Copies the histograms and computes its bit_cost.
+static void HistogramCopyAndAnalyze(
+ VP8LHistogramSet* const orig_histo, VP8LHistogramSet* const image_histo) {
+ int i;
+ const int histo_size = orig_histo->size;
+ VP8LHistogram** const orig_histograms = orig_histo->histograms;
+ VP8LHistogram** const histograms = image_histo->histograms;
+ for (i = 0; i < histo_size; ++i) {
+ VP8LHistogram* const histo = orig_histograms[i];
+ UpdateHistogramCost(histo);
+ // Copy histograms from orig_histo[] to image_histo[].
+ HistogramCopy(histo, histograms[i]);
+ }
+}
+
+// Partition histograms to different entropy bins for three dominant (literal,
+// red and blue) symbol costs and compute the histogram aggregate bit_cost.
+static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo,
+ int16_t* const bin_map, int low_effort) {
+ int i;
+ VP8LHistogram** const histograms = image_histo->histograms;
+ const int histo_size = image_histo->size;
+ const int bin_depth = histo_size + 1;
+ DominantCostRange cost_range;
+ DominantCostRangeInit(&cost_range);
+
+ // Analyze the dominant (literal, red and blue) entropy costs.
+ for (i = 0; i < histo_size; ++i) {
+ VP8LHistogram* const histo = histograms[i];
+ UpdateDominantCostRange(histo, &cost_range);
+ }
+
+ // bin-hash histograms on three of the dominant (literal, red and blue)
+ // symbol costs.
+ for (i = 0; i < histo_size; ++i) {
+ int num_histos;
+ VP8LHistogram* const histo = histograms[i];
+ const int16_t bin_id = low_effort ?
+ (int16_t)GetHistoBinIndexLowEffort(histo, &cost_range) :
+ (int16_t)GetHistoBinIndex(histo, &cost_range);
+ const int bin_offset = bin_id * bin_depth;
+ // bin_map[n][0] for every bin 'n' maintains the counter for the number of
+ // histograms in that bin.
+ // Get and increment the num_histos in that bin.
+ num_histos = ++bin_map[bin_offset];
+ assert(bin_offset + num_histos < bin_depth * BIN_SIZE);
+ // Add histogram i'th index at num_histos (last) position in the bin_map.
+ bin_map[bin_offset + num_histos] = i;
+ }
+}
+
+// Compact the histogram set by removing unused entries.
+static void HistogramCompactBins(VP8LHistogramSet* const image_histo) {
+ VP8LHistogram** const histograms = image_histo->histograms;
+ int i, j;
+
+ for (i = 0, j = 0; i < image_histo->size; ++i) {
+ if (histograms[i] != NULL && histograms[i]->bit_cost_ != 0.) {
+ if (j < i) {
+ histograms[j] = histograms[i];
+ histograms[i] = NULL;
+ }
+ ++j;
+ }
}
+ image_histo->size = j;
+}
+
+static VP8LHistogram* HistogramCombineEntropyBin(
+ VP8LHistogramSet* const image_histo,
+ VP8LHistogram* cur_combo,
+ int16_t* const bin_map, int bin_depth, int num_bins,
+ double combine_cost_factor, int low_effort) {
+ int bin_id;
+ VP8LHistogram** const histograms = image_histo->histograms;
+
+ for (bin_id = 0; bin_id < num_bins; ++bin_id) {
+ const int bin_offset = bin_id * bin_depth;
+ const int num_histos = bin_map[bin_offset];
+ const int idx1 = bin_map[bin_offset + 1];
+ int num_combine_failures = 0;
+ int n;
+ for (n = 2; n <= num_histos; ++n) {
+ const int idx2 = bin_map[bin_offset + n];
+ if (low_effort) {
+ // Merge all histograms with the same bin index, irrespective of cost of
+ // the merged histograms.
+ VP8LHistogramAdd(histograms[idx1], histograms[idx2], histograms[idx1]);
+ histograms[idx2]->bit_cost_ = 0.;
+ } else {
+ const double bit_cost_idx2 = histograms[idx2]->bit_cost_;
+ if (bit_cost_idx2 > 0.) {
+ const double bit_cost_thresh = -bit_cost_idx2 * combine_cost_factor;
+ const double curr_cost_diff =
+ HistogramAddEval(histograms[idx1], histograms[idx2],
+ cur_combo, bit_cost_thresh);
+ if (curr_cost_diff < bit_cost_thresh) {
+ // Try to merge two histograms only if the combo is a trivial one or
+ // the two candidate histograms are already non-trivial.
+ // For some images, 'try_combine' turns out to be false for a lot of
+ // histogram pairs. In that case, we fallback to combining
+ // histograms as usual to avoid increasing the header size.
+ const int try_combine =
+ (cur_combo->trivial_symbol_ != VP8L_NON_TRIVIAL_SYM) ||
+ ((histograms[idx1]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM) &&
+ (histograms[idx2]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM));
+ const int max_combine_failures = 32;
+ if (try_combine || (num_combine_failures >= max_combine_failures)) {
+ HistogramSwap(&cur_combo, &histograms[idx1]);
+ histograms[idx2]->bit_cost_ = 0.;
+ } else {
+ ++num_combine_failures;
+ }
+ }
+ }
+ }
+ }
+ if (low_effort) {
+ // Update the bit_cost for the merged histograms (per bin index).
+ UpdateHistogramCost(histograms[idx1]);
+ }
+ }
+ HistogramCompactBins(image_histo);
+ return cur_combo;
}
static uint32_t MyRand(uint32_t *seed) {
@@ -248,159 +466,433 @@ static uint32_t MyRand(uint32_t *seed) {
return *seed;
}
-static int HistogramCombine(const VP8LHistogramSet* const in,
- VP8LHistogramSet* const out, int num_pairs) {
+// -----------------------------------------------------------------------------
+// Histogram pairs priority queue
+
+// Pair of histograms. Negative idx1 value means that pair is out-of-date.
+typedef struct {
+ int idx1;
+ int idx2;
+ double cost_diff;
+ double cost_combo;
+} HistogramPair;
+
+typedef struct {
+ HistogramPair* heap;
+ int* positions;
+ int size;
+ int max_index;
+} HistoHeap;
+
+static int HistoHeapInit(HistoHeap* const histo_heap, const int max_index) {
+ histo_heap->size = 0;
+ histo_heap->max_index = max_index;
+ histo_heap->heap = WebPSafeMalloc(max_index * max_index,
+ sizeof(*histo_heap->heap));
+ histo_heap->positions = WebPSafeMalloc(max_index * max_index,
+ sizeof(*histo_heap->positions));
+ return histo_heap->heap != NULL && histo_heap->positions != NULL;
+}
+
+static void HistoHeapClear(HistoHeap* const histo_heap) {
+ assert(histo_heap != NULL);
+ WebPSafeFree(histo_heap->heap);
+ WebPSafeFree(histo_heap->positions);
+}
+
+static void SwapHistogramPairs(HistogramPair *p1,
+ HistogramPair *p2) {
+ const HistogramPair tmp = *p1;
+ *p1 = *p2;
+ *p2 = tmp;
+}
+
+// Given a valid min-heap in range [0, heap_size-1) this function places value
+// heap[heap_size-1] into right location within heap and sets its position in
+// positions array.
+static void HeapPush(HistoHeap* const histo_heap) {
+ HistogramPair* const heap = histo_heap->heap - 1;
+ int* const positions = histo_heap->positions;
+ const int max_index = histo_heap->max_index;
+ int v;
+ ++histo_heap->size;
+ v = histo_heap->size;
+ while (v > 1 && heap[v].cost_diff < heap[v >> 1].cost_diff) {
+ SwapHistogramPairs(&heap[v], &heap[v >> 1]);
+ // Change position of moved pair in heap.
+ if (heap[v].idx1 >= 0) {
+ const int pos = heap[v].idx1 * max_index + heap[v].idx2;
+ assert(pos >= 0 && pos < max_index * max_index);
+ positions[pos] = v;
+ }
+ v >>= 1;
+ }
+ positions[heap[v].idx1 * max_index + heap[v].idx2] = v;
+}
+
+// Given a valid min-heap in range [0, heap_size) this function shortens heap
+// range by one and places element with the lowest value to (heap_size-1).
+static void HeapPop(HistoHeap* const histo_heap) {
+ HistogramPair* const heap = histo_heap->heap - 1;
+ int* const positions = histo_heap->positions;
+ const int heap_size = histo_heap->size;
+ const int max_index = histo_heap->max_index;
+ int v = 1;
+ if (heap[v].idx1 >= 0) {
+ positions[heap[v].idx1 * max_index + heap[v].idx2] = -1;
+ }
+ SwapHistogramPairs(&heap[v], &heap[heap_size]);
+ while ((v << 1) < heap_size) {
+ int son = (heap[v << 1].cost_diff < heap[v].cost_diff) ? (v << 1) : v;
+ if (((v << 1) + 1) < heap_size &&
+ heap[(v << 1) + 1].cost_diff < heap[son].cost_diff) {
+ son = (v << 1) + 1;
+ }
+ if (son == v) break;
+ SwapHistogramPairs(&heap[v], &heap[son]);
+ // Change position of moved pair in heap.
+ if (heap[v].idx1 >= 0) {
+ positions[heap[v].idx1 * max_index + heap[v].idx2] = v;
+ }
+ v = son;
+ }
+ if (heap[v].idx1 >= 0) {
+ positions[heap[v].idx1 * max_index + heap[v].idx2] = v;
+ }
+ --histo_heap->size;
+}
+
+// -----------------------------------------------------------------------------
+
+static void PreparePair(VP8LHistogram** histograms, int idx1, int idx2,
+ HistogramPair* const pair,
+ VP8LHistogram* const histos) {
+ if (idx1 > idx2) {
+ const int tmp = idx2;
+ idx2 = idx1;
+ idx1 = tmp;
+ }
+ pair->idx1 = idx1;
+ pair->idx2 = idx2;
+ pair->cost_diff =
+ HistogramAddEval(histograms[idx1], histograms[idx2], histos, 0);
+ pair->cost_combo = histos->bit_cost_;
+}
+
+#define POSITION_INVALID (-1)
+
+// Invalidates pairs intersecting (idx1, idx2) in heap.
+static void InvalidatePairs(int idx1, int idx2,
+ const HistoHeap* const histo_heap) {
+ HistogramPair* const heap = histo_heap->heap - 1;
+ int* const positions = histo_heap->positions;
+ const int max_index = histo_heap->max_index;
+ int i;
+ for (i = 0; i < idx1; ++i) {
+ const int pos = positions[i * max_index + idx1];
+ if (pos >= 0) {
+ heap[pos].idx1 = POSITION_INVALID;
+ }
+ }
+ for (i = idx1 + 1; i < max_index; ++i) {
+ const int pos = positions[idx1 * max_index + i];
+ if (pos >= 0) {
+ heap[pos].idx1 = POSITION_INVALID;
+ }
+ }
+ for (i = 0; i < idx2; ++i) {
+ const int pos = positions[i * max_index + idx2];
+ if (pos >= 0) {
+ heap[pos].idx1 = POSITION_INVALID;
+ }
+ }
+ for (i = idx2 + 1; i < max_index; ++i) {
+ const int pos = positions[idx2 * max_index + i];
+ if (pos >= 0) {
+ heap[pos].idx1 = POSITION_INVALID;
+ }
+ }
+}
+
+// Combines histograms by continuously choosing the one with the highest cost
+// reduction.
+static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo,
+ VP8LHistogram* const histos) {
int ok = 0;
- int i, iter;
+ int image_histo_size = image_histo->size;
+ int i, j;
+ VP8LHistogram** const histograms = image_histo->histograms;
+ // Indexes of remaining histograms.
+ int* const clusters = WebPSafeMalloc(image_histo_size, sizeof(*clusters));
+ // Heap of histogram pairs.
+ HistoHeap histo_heap;
+
+ if (!HistoHeapInit(&histo_heap, image_histo_size) || clusters == NULL) {
+ goto End;
+ }
+
+ for (i = 0; i < image_histo_size; ++i) {
+ // Initialize clusters indexes.
+ clusters[i] = i;
+ for (j = i + 1; j < image_histo_size; ++j) {
+ // Initialize positions array.
+ histo_heap.positions[i * histo_heap.max_index + j] = POSITION_INVALID;
+ PreparePair(histograms, i, j, &histo_heap.heap[histo_heap.size], histos);
+ if (histo_heap.heap[histo_heap.size].cost_diff < 0) {
+ HeapPush(&histo_heap);
+ }
+ }
+ }
+
+ while (image_histo_size > 1 && histo_heap.size > 0) {
+ const int idx1 = histo_heap.heap[0].idx1;
+ const int idx2 = histo_heap.heap[0].idx2;
+ VP8LHistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]);
+ histograms[idx1]->bit_cost_ = histo_heap.heap[0].cost_combo;
+ // Remove merged histogram.
+ for (i = 0; i + 1 < image_histo_size; ++i) {
+ if (clusters[i] >= idx2) {
+ clusters[i] = clusters[i + 1];
+ }
+ }
+ --image_histo_size;
+
+ // Invalidate pairs intersecting the just combined best pair.
+ InvalidatePairs(idx1, idx2, &histo_heap);
+
+ // Pop invalid pairs from the top of the heap.
+ while (histo_heap.size > 0 && histo_heap.heap[0].idx1 < 0) {
+ HeapPop(&histo_heap);
+ }
+
+ // Push new pairs formed with combined histogram to the heap.
+ for (i = 0; i < image_histo_size; ++i) {
+ if (clusters[i] != idx1) {
+ PreparePair(histograms, idx1, clusters[i],
+ &histo_heap.heap[histo_heap.size], histos);
+ if (histo_heap.heap[histo_heap.size].cost_diff < 0) {
+ HeapPush(&histo_heap);
+ }
+ }
+ }
+ }
+ // Move remaining histograms to the beginning of the array.
+ for (i = 0; i < image_histo_size; ++i) {
+ if (i != clusters[i]) { // swap the two histograms
+ HistogramSwap(&histograms[i], &histograms[clusters[i]]);
+ }
+ }
+
+ image_histo->size = image_histo_size;
+ ok = 1;
+
+ End:
+ WebPSafeFree(clusters);
+ HistoHeapClear(&histo_heap);
+ return ok;
+}
+
+static VP8LHistogram* HistogramCombineStochastic(
+ VP8LHistogramSet* const image_histo,
+ VP8LHistogram* tmp_histo,
+ VP8LHistogram* best_combo,
+ int quality, int min_cluster_size) {
+ int iter;
uint32_t seed = 0;
int tries_with_no_success = 0;
- const int min_cluster_size = 2;
- int out_size = in->size;
- const int outer_iters = in->size * 3;
- VP8LHistogram* const histos = (VP8LHistogram*)malloc(2 * sizeof(*histos));
- VP8LHistogram* cur_combo = histos + 0; // trial merged histogram
- VP8LHistogram* best_combo = histos + 1; // best merged histogram so far
- if (histos == NULL) goto End;
-
- // Copy histograms from in[] to out[].
- assert(in->size <= out->size);
- for (i = 0; i < in->size; ++i) {
- in->histograms[i]->bit_cost_ = VP8LHistogramEstimateBits(in->histograms[i]);
- *out->histograms[i] = *in->histograms[i];
- }
-
- // Collapse similar histograms in 'out'.
- for (iter = 0; iter < outer_iters && out_size >= min_cluster_size; ++iter) {
- // We pick the best pair to be combined out of 'inner_iters' pairs.
+ int image_histo_size = image_histo->size;
+ const int iter_mult = (quality < 25) ? 2 : 2 + (quality - 25) / 8;
+ const int outer_iters = image_histo_size * iter_mult;
+ const int num_pairs = image_histo_size / 2;
+ const int num_tries_no_success = outer_iters / 2;
+ VP8LHistogram** const histograms = image_histo->histograms;
+
+ // Collapse similar histograms in 'image_histo'.
+ ++min_cluster_size;
+ for (iter = 0;
+ iter < outer_iters && image_histo_size >= min_cluster_size;
+ ++iter) {
double best_cost_diff = 0.;
- int best_idx1 = 0, best_idx2 = 1;
+ int best_idx1 = -1, best_idx2 = 1;
int j;
+ const int num_tries =
+ (num_pairs < image_histo_size) ? num_pairs : image_histo_size;
seed += iter;
- for (j = 0; j < num_pairs; ++j) {
+ for (j = 0; j < num_tries; ++j) {
double curr_cost_diff;
// Choose two histograms at random and try to combine them.
- const uint32_t idx1 = MyRand(&seed) % out_size;
- const uint32_t tmp = ((j & 7) + 1) % (out_size - 1);
- const uint32_t diff = (tmp < 3) ? tmp : MyRand(&seed) % (out_size - 1);
- const uint32_t idx2 = (idx1 + diff + 1) % out_size;
+ const uint32_t idx1 = MyRand(&seed) % image_histo_size;
+ const uint32_t tmp = (j & 7) + 1;
+ const uint32_t diff =
+ (tmp < 3) ? tmp : MyRand(&seed) % (image_histo_size - 1);
+ const uint32_t idx2 = (idx1 + diff + 1) % image_histo_size;
if (idx1 == idx2) {
continue;
}
- *cur_combo = *out->histograms[idx1];
- VP8LHistogramAdd(cur_combo, out->histograms[idx2]);
- cur_combo->bit_cost_ = VP8LHistogramEstimateBits(cur_combo);
+
// Calculate cost reduction on combining.
- curr_cost_diff = cur_combo->bit_cost_
- - out->histograms[idx1]->bit_cost_
- - out->histograms[idx2]->bit_cost_;
- if (best_cost_diff > curr_cost_diff) { // found a better pair?
- { // swap cur/best combo histograms
- VP8LHistogram* const tmp_histo = cur_combo;
- cur_combo = best_combo;
- best_combo = tmp_histo;
- }
+ curr_cost_diff = HistogramAddEval(histograms[idx1], histograms[idx2],
+ tmp_histo, best_cost_diff);
+ if (curr_cost_diff < best_cost_diff) { // found a better pair?
+ HistogramSwap(&best_combo, &tmp_histo);
best_cost_diff = curr_cost_diff;
best_idx1 = idx1;
best_idx2 = idx2;
}
}
- if (best_cost_diff < 0.0) {
- *out->histograms[best_idx1] = *best_combo;
+ if (best_idx1 >= 0) {
+ HistogramSwap(&best_combo, &histograms[best_idx1]);
// swap best_idx2 slot with last one (which is now unused)
- --out_size;
- if (best_idx2 != out_size) {
- out->histograms[best_idx2] = out->histograms[out_size];
- out->histograms[out_size] = NULL; // just for sanity check.
+ --image_histo_size;
+ if (best_idx2 != image_histo_size) {
+ HistogramSwap(&histograms[image_histo_size], &histograms[best_idx2]);
+ histograms[image_histo_size] = NULL;
}
tries_with_no_success = 0;
}
- if (++tries_with_no_success >= 50) {
+ if (++tries_with_no_success >= num_tries_no_success) {
break;
}
}
- out->size = out_size;
- ok = 1;
-
- End:
- free(histos);
- return ok;
+ image_histo->size = image_histo_size;
+ return best_combo;
}
// -----------------------------------------------------------------------------
// Histogram refinement
-// What is the bit cost of moving square_histogram from
-// cur_symbol to candidate_symbol.
-// TODO(skal): we don't really need to copy the histogram and Add(). Instead
-// we just need VP8LDualHistogramEstimateBits(A, B) estimation function.
-static double HistogramDistance(const VP8LHistogram* const square_histogram,
- const VP8LHistogram* const candidate) {
- const double previous_bit_cost = candidate->bit_cost_;
- double new_bit_cost;
- VP8LHistogram modified_histo;
- modified_histo = *candidate;
- VP8LHistogramAdd(&modified_histo, square_histogram);
- new_bit_cost = VP8LHistogramEstimateBits(&modified_histo);
-
- return new_bit_cost - previous_bit_cost;
-}
-
// Find the best 'out' histogram for each of the 'in' histograms.
// Note: we assume that out[]->bit_cost_ is already up-to-date.
-static void HistogramRemap(const VP8LHistogramSet* const in,
- const VP8LHistogramSet* const out,
+static void HistogramRemap(const VP8LHistogramSet* const orig_histo,
+ const VP8LHistogramSet* const image_histo,
uint16_t* const symbols) {
int i;
- for (i = 0; i < in->size; ++i) {
- int best_out = 0;
- double best_bits = HistogramDistance(in->histograms[i], out->histograms[0]);
- int k;
- for (k = 1; k < out->size; ++k) {
- const double cur_bits =
- HistogramDistance(in->histograms[i], out->histograms[k]);
- if (cur_bits < best_bits) {
- best_bits = cur_bits;
- best_out = k;
+ VP8LHistogram** const orig_histograms = orig_histo->histograms;
+ VP8LHistogram** const histograms = image_histo->histograms;
+ const int orig_histo_size = orig_histo->size;
+ const int image_histo_size = image_histo->size;
+ if (image_histo_size > 1) {
+ for (i = 0; i < orig_histo_size; ++i) {
+ int best_out = 0;
+ double best_bits =
+ HistogramAddThresh(histograms[0], orig_histograms[i], MAX_COST);
+ int k;
+ for (k = 1; k < image_histo_size; ++k) {
+ const double cur_bits =
+ HistogramAddThresh(histograms[k], orig_histograms[i], best_bits);
+ if (cur_bits < best_bits) {
+ best_bits = cur_bits;
+ best_out = k;
+ }
}
+ symbols[i] = best_out;
+ }
+ } else {
+ assert(image_histo_size == 1);
+ for (i = 0; i < orig_histo_size; ++i) {
+ symbols[i] = 0;
}
- symbols[i] = best_out;
}
// Recompute each out based on raw and symbols.
- for (i = 0; i < out->size; ++i) {
- HistogramClear(out->histograms[i]);
+ for (i = 0; i < image_histo_size; ++i) {
+ HistogramClear(histograms[i]);
}
- for (i = 0; i < in->size; ++i) {
- VP8LHistogramAdd(out->histograms[symbols[i]], in->histograms[i]);
+
+ for (i = 0; i < orig_histo_size; ++i) {
+ const int idx = symbols[i];
+ VP8LHistogramAdd(orig_histograms[i], histograms[idx], histograms[idx]);
}
}
+static double GetCombineCostFactor(int histo_size, int quality) {
+ double combine_cost_factor = 0.16;
+ if (quality < 90) {
+ if (histo_size > 256) combine_cost_factor /= 2.;
+ if (histo_size > 512) combine_cost_factor /= 2.;
+ if (histo_size > 1024) combine_cost_factor /= 2.;
+ if (quality <= 50) combine_cost_factor /= 2.;
+ }
+ return combine_cost_factor;
+}
+
int VP8LGetHistoImageSymbols(int xsize, int ysize,
const VP8LBackwardRefs* const refs,
- int quality, int histo_bits, int cache_bits,
- VP8LHistogramSet* const image_in,
+ int quality, int low_effort,
+ int histo_bits, int cache_bits,
+ VP8LHistogramSet* const image_histo,
+ VP8LHistogramSet* const tmp_histos,
uint16_t* const histogram_symbols) {
int ok = 0;
const int histo_xsize = histo_bits ? VP8LSubSampleSize(xsize, histo_bits) : 1;
const int histo_ysize = histo_bits ? VP8LSubSampleSize(ysize, histo_bits) : 1;
- const int num_histo_pairs = 10 + quality / 2; // For HistogramCombine().
- const int histo_image_raw_size = histo_xsize * histo_ysize;
- VP8LHistogramSet* const image_out =
- VP8LAllocateHistogramSet(histo_image_raw_size, cache_bits);
- if (image_out == NULL) return 0;
-
- // Build histogram image.
- HistogramBuildImage(xsize, histo_bits, refs, image_out);
- // Collapse similar histograms.
- if (!HistogramCombine(image_out, image_in, num_histo_pairs)) {
- goto Error;
+ const int image_histo_raw_size = histo_xsize * histo_ysize;
+ const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE;
+
+ // The bin_map for every bin follows following semantics:
+ // bin_map[n][0] = num_histo; // The number of histograms in that bin.
+ // bin_map[n][1] = index of first histogram in that bin;
+ // bin_map[n][num_histo] = index of last histogram in that bin;
+ // bin_map[n][num_histo + 1] ... bin_map[n][bin_depth - 1] = unused indices.
+ const int bin_depth = image_histo_raw_size + 1;
+ int16_t* bin_map = NULL;
+ VP8LHistogramSet* const orig_histo =
+ VP8LAllocateHistogramSet(image_histo_raw_size, cache_bits);
+ VP8LHistogram* cur_combo;
+ const int entropy_combine =
+ (orig_histo->size > entropy_combine_num_bins * 2) && (quality < 100);
+
+ if (orig_histo == NULL) goto Error;
+
+ // Don't attempt linear bin-partition heuristic for:
+ // histograms of small sizes, as bin_map will be very sparse and;
+ // Maximum quality (q==100), to preserve the compression gains at that level.
+ if (entropy_combine) {
+ const int bin_map_size = bin_depth * entropy_combine_num_bins;
+ bin_map = (int16_t*)WebPSafeCalloc(bin_map_size, sizeof(*bin_map));
+ if (bin_map == NULL) goto Error;
}
+
+ // Construct the histograms from backward references.
+ HistogramBuild(xsize, histo_bits, refs, orig_histo);
+ // Copies the histograms and computes its bit_cost.
+ HistogramCopyAndAnalyze(orig_histo, image_histo);
+
+ cur_combo = tmp_histos->histograms[1]; // pick up working slot
+ if (entropy_combine) {
+ const double combine_cost_factor =
+ GetCombineCostFactor(image_histo_raw_size, quality);
+ HistogramAnalyzeEntropyBin(orig_histo, bin_map, low_effort);
+ // Collapse histograms with similar entropy.
+ cur_combo = HistogramCombineEntropyBin(image_histo, cur_combo, bin_map,
+ bin_depth, entropy_combine_num_bins,
+ combine_cost_factor, low_effort);
+ }
+
+ // Don't combine the histograms using stochastic and greedy heuristics for
+ // low-effort compression mode.
+ if (!low_effort || !entropy_combine) {
+ const float x = quality / 100.f;
+ // cubic ramp between 1 and MAX_HISTO_GREEDY:
+ const int threshold_size = (int)(1 + (x * x * x) * (MAX_HISTO_GREEDY - 1));
+ cur_combo = HistogramCombineStochastic(image_histo,
+ tmp_histos->histograms[0],
+ cur_combo, quality, threshold_size);
+ if ((image_histo->size <= threshold_size) &&
+ !HistogramCombineGreedy(image_histo, cur_combo)) {
+ goto Error;
+ }
+ }
+
+ // TODO(vikasa): Optimize HistogramRemap for low-effort compression mode also.
// Find the optimal map from original histograms to the final ones.
- HistogramRemap(image_out, image_in, histogram_symbols);
+ HistogramRemap(orig_histo, image_histo, histogram_symbols);
+
ok = 1;
-Error:
- free(image_out);
+ Error:
+ WebPSafeFree(bin_map);
+ VP8LFreeHistogramSet(orig_histo);
return ok;
}
diff --git a/drivers/webp/enc/histogram.h b/drivers/webp/enc/histogram.h
index 5b5de25539..72f045793a 100644
--- a/drivers/webp/enc/histogram.h
+++ b/drivers/webp/enc/histogram.h
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Author: Jyrki Alakuijala (jyrki@google.com)
@@ -12,17 +14,13 @@
#ifndef WEBP_ENC_HISTOGRAM_H_
#define WEBP_ENC_HISTOGRAM_H_
-#include <assert.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdio.h>
#include <string.h>
#include "./backward_references.h"
-#include "../format_constants.h"
-#include "../types.h"
+#include "webp/format_constants.h"
+#include "webp/types.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
@@ -30,18 +28,23 @@ extern "C" {
typedef struct {
// literal_ contains green literal, palette-code and
// copy-length-prefix histogram
- int literal_[PIX_OR_COPY_CODES_MAX];
- int red_[256];
- int blue_[256];
- int alpha_[256];
+ uint32_t* literal_; // Pointer to the allocated buffer for literal.
+ uint32_t red_[NUM_LITERAL_CODES];
+ uint32_t blue_[NUM_LITERAL_CODES];
+ uint32_t alpha_[NUM_LITERAL_CODES];
// Backward reference prefix-code histogram.
- int distance_[NUM_DISTANCE_CODES];
+ uint32_t distance_[NUM_DISTANCE_CODES];
int palette_code_bits_;
- double bit_cost_; // cached value of VP8LHistogramEstimateBits(this)
+ uint32_t trivial_symbol_; // True, if histograms for Red, Blue & Alpha
+ // literal symbols are single valued.
+ double bit_cost_; // cached value of bit cost.
+ double literal_cost_; // Cached values of dominant entropy costs:
+ double red_cost_; // literal, red & blue.
+ double blue_cost_;
} VP8LHistogram;
// Collection of histograms with fixed capacity, allocated as one
-// big memory chunk. Can be destroyed by simply calling 'free()'.
+// big memory chunk. Can be destroyed by calling WebPSafeFree().
typedef struct {
int size; // number of slots currently in use
int max_size; // maximum capacity
@@ -57,6 +60,9 @@ void VP8LHistogramCreate(VP8LHistogram* const p,
const VP8LBackwardRefs* const refs,
int palette_code_bits);
+// Return the size of the histogram for a given palette_code_bits.
+int VP8LGetHistogramSize(int palette_code_bits);
+
// Set the palette_code_bits and reset the stats.
void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits);
@@ -64,51 +70,40 @@ void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits);
void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs,
VP8LHistogram* const histo);
+// Free the memory allocated for the histogram.
+void VP8LFreeHistogram(VP8LHistogram* const histo);
+
+// Free the memory allocated for the histogram set.
+void VP8LFreeHistogramSet(VP8LHistogramSet* const histo);
+
// Allocate an array of pointer to histograms, allocated and initialized
// using 'cache_bits'. Return NULL in case of memory error.
VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits);
+// Allocate and initialize histogram object with specified 'cache_bits'.
+// Returns NULL in case of memory error.
+// Special case of VP8LAllocateHistogramSet, with size equals 1.
+VP8LHistogram* VP8LAllocateHistogram(int cache_bits);
+
// Accumulate a token 'v' into a histogram.
void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
const PixOrCopy* const v);
-// Estimate how many bits the combined entropy of literals and distance
-// approximately maps to.
-double VP8LHistogramEstimateBits(const VP8LHistogram* const p);
-
-// This function estimates the cost in bits excluding the bits needed to
-// represent the entropy code itself.
-double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p);
-
-static WEBP_INLINE void VP8LHistogramAdd(VP8LHistogram* const p,
- const VP8LHistogram* const a) {
- int i;
- for (i = 0; i < PIX_OR_COPY_CODES_MAX; ++i) {
- p->literal_[i] += a->literal_[i];
- }
- for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
- p->distance_[i] += a->distance_[i];
- }
- for (i = 0; i < 256; ++i) {
- p->red_[i] += a->red_[i];
- p->blue_[i] += a->blue_[i];
- p->alpha_[i] += a->alpha_[i];
- }
-}
-
-static WEBP_INLINE int VP8LHistogramNumCodes(const VP8LHistogram* const p) {
- return 256 + NUM_LENGTH_CODES +
- ((p->palette_code_bits_ > 0) ? (1 << p->palette_code_bits_) : 0);
+static WEBP_INLINE int VP8LHistogramNumCodes(int palette_code_bits) {
+ return NUM_LITERAL_CODES + NUM_LENGTH_CODES +
+ ((palette_code_bits > 0) ? (1 << palette_code_bits) : 0);
}
// Builds the histogram image.
int VP8LGetHistoImageSymbols(int xsize, int ysize,
const VP8LBackwardRefs* const refs,
- int quality, int histogram_bits, int cache_bits,
+ int quality, int low_effort,
+ int histogram_bits, int cache_bits,
VP8LHistogramSet* const image_in,
+ VP8LHistogramSet* const tmp_histos,
uint16_t* const histogram_symbols);
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
}
#endif
diff --git a/drivers/webp/enc/iterator.c b/drivers/webp/enc/iterator.c
index 86e473bcf0..99d960a547 100644
--- a/drivers/webp/enc/iterator.c
+++ b/drivers/webp/enc/iterator.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// VP8Iterator: block iterator
@@ -13,21 +15,16 @@
#include "./vp8enci.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
//------------------------------------------------------------------------------
// VP8Iterator
//------------------------------------------------------------------------------
static void InitLeft(VP8EncIterator* const it) {
- const VP8Encoder* const enc = it->enc_;
- enc->y_left_[-1] = enc->u_left_[-1] = enc->v_left_[-1] =
+ it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] =
(it->y_ > 0) ? 129 : 127;
- memset(enc->y_left_, 129, 16);
- memset(enc->u_left_, 129, 8);
- memset(enc->v_left_, 129, 8);
+ memset(it->y_left_, 129, 16);
+ memset(it->u_left_, 129, 8);
+ memset(it->v_left_, 129, 8);
it->left_nz_[8] = 0;
}
@@ -38,43 +35,60 @@ static void InitTop(VP8EncIterator* const it) {
memset(enc->nz_, 0, enc->mb_w_ * sizeof(*enc->nz_));
}
-void VP8IteratorReset(VP8EncIterator* const it) {
+void VP8IteratorSetRow(VP8EncIterator* const it, int y) {
VP8Encoder* const enc = it->enc_;
it->x_ = 0;
- it->y_ = 0;
- it->y_offset_ = 0;
- it->uv_offset_ = 0;
- it->mb_ = enc->mb_info_;
- it->preds_ = enc->preds_;
+ it->y_ = y;
+ it->bw_ = &enc->parts_[y & (enc->num_parts_ - 1)];
+ it->preds_ = enc->preds_ + y * 4 * enc->preds_w_;
it->nz_ = enc->nz_;
- it->bw_ = &enc->parts_[0];
- it->done_ = enc->mb_w_* enc->mb_h_;
+ it->mb_ = enc->mb_info_ + y * enc->mb_w_;
+ it->y_top_ = enc->y_top_;
+ it->uv_top_ = enc->uv_top_;
+ InitLeft(it);
+}
+
+void VP8IteratorReset(VP8EncIterator* const it) {
+ VP8Encoder* const enc = it->enc_;
+ VP8IteratorSetRow(it, 0);
+ VP8IteratorSetCountDown(it, enc->mb_w_ * enc->mb_h_); // default
InitTop(it);
InitLeft(it);
memset(it->bit_count_, 0, sizeof(it->bit_count_));
it->do_trellis_ = 0;
}
+void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down) {
+ it->count_down_ = it->count_down0_ = count_down;
+}
+
+int VP8IteratorIsDone(const VP8EncIterator* const it) {
+ return (it->count_down_ <= 0);
+}
+
void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) {
it->enc_ = enc;
it->y_stride_ = enc->pic_->y_stride;
it->uv_stride_ = enc->pic_->uv_stride;
- // TODO(later): for multithreading, these should be owned by 'it'.
- it->yuv_in_ = enc->yuv_in_;
- it->yuv_out_ = enc->yuv_out_;
- it->yuv_out2_ = enc->yuv_out2_;
- it->yuv_p_ = enc->yuv_p_;
+ it->yuv_in_ = (uint8_t*)WEBP_ALIGN(it->yuv_mem_);
+ it->yuv_out_ = it->yuv_in_ + YUV_SIZE_ENC;
+ it->yuv_out2_ = it->yuv_out_ + YUV_SIZE_ENC;
+ it->yuv_p_ = it->yuv_out2_ + YUV_SIZE_ENC;
it->lf_stats_ = enc->lf_stats_;
it->percent0_ = enc->percent_;
+ it->y_left_ = (uint8_t*)WEBP_ALIGN(it->yuv_left_mem_ + 1);
+ it->u_left_ = it->y_left_ + 16 + 16;
+ it->v_left_ = it->u_left_ + 16;
VP8IteratorReset(it);
}
int VP8IteratorProgress(const VP8EncIterator* const it, int delta) {
VP8Encoder* const enc = it->enc_;
- if (delta && enc->pic_->progress_hook) {
- const int percent = (enc->mb_h_ <= 1)
+ if (delta && enc->pic_->progress_hook != NULL) {
+ const int done = it->count_down0_ - it->count_down_;
+ const int percent = (it->count_down0_ <= 0)
? it->percent0_
- : it->percent0_ + delta * it->y_ / (enc->mb_h_ - 1);
+ : it->percent0_ + delta * done / it->count_down0_;
return WebPReportProgress(enc->pic_, percent, &enc->percent_);
}
return 1;
@@ -84,6 +98,8 @@ int VP8IteratorProgress(const VP8EncIterator* const it, int delta) {
// Import the source samples into the cache. Takes care of replicating
// boundary pixels if necessary.
+static WEBP_INLINE int MinSize(int a, int b) { return (a < b) ? a : b; }
+
static void ImportBlock(const uint8_t* src, int src_stride,
uint8_t* dst, int w, int h, int size) {
int i;
@@ -101,30 +117,55 @@ static void ImportBlock(const uint8_t* src, int src_stride,
}
}
-void VP8IteratorImport(const VP8EncIterator* const it) {
+static void ImportLine(const uint8_t* src, int src_stride,
+ uint8_t* dst, int len, int total_len) {
+ int i;
+ for (i = 0; i < len; ++i, src += src_stride) dst[i] = *src;
+ for (; i < total_len; ++i) dst[i] = dst[len - 1];
+}
+
+void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32) {
const VP8Encoder* const enc = it->enc_;
const int x = it->x_, y = it->y_;
const WebPPicture* const pic = enc->pic_;
- const uint8_t* const ysrc = pic->y + (y * pic->y_stride + x) * 16;
+ const uint8_t* const ysrc = pic->y + (y * pic->y_stride + x) * 16;
const uint8_t* const usrc = pic->u + (y * pic->uv_stride + x) * 8;
const uint8_t* const vsrc = pic->v + (y * pic->uv_stride + x) * 8;
- uint8_t* const ydst = it->yuv_in_ + Y_OFF;
- uint8_t* const udst = it->yuv_in_ + U_OFF;
- uint8_t* const vdst = it->yuv_in_ + V_OFF;
- int w = (pic->width - x * 16);
- int h = (pic->height - y * 16);
-
- if (w > 16) w = 16;
- if (h > 16) h = 16;
-
- // Luma plane
- ImportBlock(ysrc, pic->y_stride, ydst, w, h, 16);
-
- { // U/V planes
- const int uv_w = (w + 1) >> 1;
- const int uv_h = (h + 1) >> 1;
- ImportBlock(usrc, pic->uv_stride, udst, uv_w, uv_h, 8);
- ImportBlock(vsrc, pic->uv_stride, vdst, uv_w, uv_h, 8);
+ const int w = MinSize(pic->width - x * 16, 16);
+ const int h = MinSize(pic->height - y * 16, 16);
+ const int uv_w = (w + 1) >> 1;
+ const int uv_h = (h + 1) >> 1;
+
+ ImportBlock(ysrc, pic->y_stride, it->yuv_in_ + Y_OFF_ENC, w, h, 16);
+ ImportBlock(usrc, pic->uv_stride, it->yuv_in_ + U_OFF_ENC, uv_w, uv_h, 8);
+ ImportBlock(vsrc, pic->uv_stride, it->yuv_in_ + V_OFF_ENC, uv_w, uv_h, 8);
+
+ if (tmp_32 == NULL) return;
+
+ // Import source (uncompressed) samples into boundary.
+ if (x == 0) {
+ InitLeft(it);
+ } else {
+ if (y == 0) {
+ it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] = 127;
+ } else {
+ it->y_left_[-1] = ysrc[- 1 - pic->y_stride];
+ it->u_left_[-1] = usrc[- 1 - pic->uv_stride];
+ it->v_left_[-1] = vsrc[- 1 - pic->uv_stride];
+ }
+ ImportLine(ysrc - 1, pic->y_stride, it->y_left_, h, 16);
+ ImportLine(usrc - 1, pic->uv_stride, it->u_left_, uv_h, 8);
+ ImportLine(vsrc - 1, pic->uv_stride, it->v_left_, uv_h, 8);
+ }
+
+ it->y_top_ = tmp_32 + 0;
+ it->uv_top_ = tmp_32 + 16;
+ if (y == 0) {
+ memset(tmp_32, 127, 32 * sizeof(*tmp_32));
+ } else {
+ ImportLine(ysrc - pic->y_stride, 1, tmp_32, w, 16);
+ ImportLine(usrc - pic->uv_stride, 1, tmp_32 + 16, uv_w, 8);
+ ImportLine(vsrc - pic->uv_stride, 1, tmp_32 + 16 + 8, uv_w, 8);
}
}
@@ -144,9 +185,9 @@ void VP8IteratorExport(const VP8EncIterator* const it) {
const VP8Encoder* const enc = it->enc_;
if (enc->config_->show_compressed) {
const int x = it->x_, y = it->y_;
- const uint8_t* const ysrc = it->yuv_out_ + Y_OFF;
- const uint8_t* const usrc = it->yuv_out_ + U_OFF;
- const uint8_t* const vsrc = it->yuv_out_ + V_OFF;
+ const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC;
+ const uint8_t* const usrc = it->yuv_out_ + U_OFF_ENC;
+ const uint8_t* const vsrc = it->yuv_out_ + V_OFF_ENC;
const WebPPicture* const pic = enc->pic_;
uint8_t* const ydst = pic->y + (y * pic->y_stride + x) * 16;
uint8_t* const udst = pic->u + (y * pic->uv_stride + x) * 8;
@@ -240,48 +281,44 @@ void VP8IteratorBytesToNz(VP8EncIterator* const it) {
#undef BIT
//------------------------------------------------------------------------------
-// Advance to the next position, doing the bookeeping.
+// Advance to the next position, doing the bookkeeping.
-int VP8IteratorNext(VP8EncIterator* const it,
- const uint8_t* const block_to_save) {
+void VP8IteratorSaveBoundary(VP8EncIterator* const it) {
VP8Encoder* const enc = it->enc_;
- if (block_to_save) {
- const int x = it->x_, y = it->y_;
- const uint8_t* const ysrc = block_to_save + Y_OFF;
- const uint8_t* const usrc = block_to_save + U_OFF;
- if (x < enc->mb_w_ - 1) { // left
- int i;
- for (i = 0; i < 16; ++i) {
- enc->y_left_[i] = ysrc[15 + i * BPS];
- }
- for (i = 0; i < 8; ++i) {
- enc->u_left_[i] = usrc[7 + i * BPS];
- enc->v_left_[i] = usrc[15 + i * BPS];
- }
- // top-left (before 'top'!)
- enc->y_left_[-1] = enc->y_top_[x * 16 + 15];
- enc->u_left_[-1] = enc->uv_top_[x * 16 + 0 + 7];
- enc->v_left_[-1] = enc->uv_top_[x * 16 + 8 + 7];
+ const int x = it->x_, y = it->y_;
+ const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC;
+ const uint8_t* const uvsrc = it->yuv_out_ + U_OFF_ENC;
+ if (x < enc->mb_w_ - 1) { // left
+ int i;
+ for (i = 0; i < 16; ++i) {
+ it->y_left_[i] = ysrc[15 + i * BPS];
}
- if (y < enc->mb_h_ - 1) { // top
- memcpy(enc->y_top_ + x * 16, ysrc + 15 * BPS, 16);
- memcpy(enc->uv_top_ + x * 16, usrc + 7 * BPS, 8 + 8);
+ for (i = 0; i < 8; ++i) {
+ it->u_left_[i] = uvsrc[7 + i * BPS];
+ it->v_left_[i] = uvsrc[15 + i * BPS];
}
+ // top-left (before 'top'!)
+ it->y_left_[-1] = it->y_top_[15];
+ it->u_left_[-1] = it->uv_top_[0 + 7];
+ it->v_left_[-1] = it->uv_top_[8 + 7];
}
+ if (y < enc->mb_h_ - 1) { // top
+ memcpy(it->y_top_, ysrc + 15 * BPS, 16);
+ memcpy(it->uv_top_, uvsrc + 7 * BPS, 8 + 8);
+ }
+}
- it->mb_++;
+int VP8IteratorNext(VP8EncIterator* const it) {
it->preds_ += 4;
- it->nz_++;
- it->x_++;
- if (it->x_ == enc->mb_w_) {
- it->x_ = 0;
- it->y_++;
- it->bw_ = &enc->parts_[it->y_ & (enc->num_parts_ - 1)];
- it->preds_ = enc->preds_ + it->y_ * 4 * enc->preds_w_;
- it->nz_ = enc->nz_;
- InitLeft(it);
+ it->mb_ += 1;
+ it->nz_ += 1;
+ it->y_top_ += 16;
+ it->uv_top_ += 16;
+ it->x_ += 1;
+ if (it->x_ == it->enc_->mb_w_) {
+ VP8IteratorSetRow(it, ++it->y_);
}
- return (0 < --it->done_);
+ return (0 < --it->count_down_);
}
//------------------------------------------------------------------------------
@@ -368,15 +405,15 @@ void VP8IteratorStartI4(VP8EncIterator* const it) {
// Import the boundary samples
for (i = 0; i < 17; ++i) { // left
- it->i4_boundary_[i] = enc->y_left_[15 - i];
+ it->i4_boundary_[i] = it->y_left_[15 - i];
}
for (i = 0; i < 16; ++i) { // top
- it->i4_boundary_[17 + i] = enc->y_top_[it->x_ * 16 + i];
+ it->i4_boundary_[17 + i] = it->y_top_[i];
}
// top-right samples have a special case on the far right of the picture
if (it->x_ < enc->mb_w_ - 1) {
for (i = 16; i < 16 + 4; ++i) {
- it->i4_boundary_[17 + i] = enc->y_top_[it->x_ * 16 + i];
+ it->i4_boundary_[17 + i] = it->y_top_[i];
}
} else { // else, replicate the last valid pixel four times
for (i = 16; i < 16 + 4; ++i) {
@@ -417,6 +454,3 @@ int VP8IteratorRotateI4(VP8EncIterator* const it,
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/enc/near_lossless.c b/drivers/webp/enc/near_lossless.c
new file mode 100644
index 0000000000..9bc0f0e786
--- /dev/null
+++ b/drivers/webp/enc/near_lossless.c
@@ -0,0 +1,160 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Near-lossless image preprocessing adjusts pixel values to help
+// compressibility with a guarantee of maximum deviation between original and
+// resulting pixel values.
+//
+// Author: Jyrki Alakuijala (jyrki@google.com)
+// Converted to C by Aleksander Kramarz (akramarz@google.com)
+
+#include <stdlib.h>
+
+#include "../dsp/lossless.h"
+#include "../utils/utils.h"
+#include "./vp8enci.h"
+
+#define MIN_DIM_FOR_NEAR_LOSSLESS 64
+#define MAX_LIMIT_BITS 5
+
+// Computes quantized pixel value and distance from original value.
+static void GetValAndDistance(int a, int initial, int bits,
+ int* const val, int* const distance) {
+ const int mask = ~((1 << bits) - 1);
+ *val = (initial & mask) | (initial >> (8 - bits));
+ *distance = 2 * abs(a - *val);
+}
+
+// Clamps the value to range [0, 255].
+static int Clamp8b(int val) {
+ const int min_val = 0;
+ const int max_val = 0xff;
+ return (val < min_val) ? min_val : (val > max_val) ? max_val : val;
+}
+
+// Quantizes values {a, a+(1<<bits), a-(1<<bits)} and returns the nearest one.
+static int FindClosestDiscretized(int a, int bits) {
+ int best_val = a, i;
+ int min_distance = 256;
+
+ for (i = -1; i <= 1; ++i) {
+ int candidate, distance;
+ const int val = Clamp8b(a + i * (1 << bits));
+ GetValAndDistance(a, val, bits, &candidate, &distance);
+ if (i != 0) {
+ ++distance;
+ }
+ // Smallest distance but favor i == 0 over i == -1 and i == 1
+ // since that keeps the overall intensity more constant in the
+ // images.
+ if (distance < min_distance) {
+ min_distance = distance;
+ best_val = candidate;
+ }
+ }
+ return best_val;
+}
+
+// Applies FindClosestDiscretized to all channels of pixel.
+static uint32_t ClosestDiscretizedArgb(uint32_t a, int bits) {
+ return
+ (FindClosestDiscretized(a >> 24, bits) << 24) |
+ (FindClosestDiscretized((a >> 16) & 0xff, bits) << 16) |
+ (FindClosestDiscretized((a >> 8) & 0xff, bits) << 8) |
+ (FindClosestDiscretized(a & 0xff, bits));
+}
+
+// Checks if distance between corresponding channel values of pixels a and b
+// is within the given limit.
+static int IsNear(uint32_t a, uint32_t b, int limit) {
+ int k;
+ for (k = 0; k < 4; ++k) {
+ const int delta =
+ (int)((a >> (k * 8)) & 0xff) - (int)((b >> (k * 8)) & 0xff);
+ if (delta >= limit || delta <= -limit) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int IsSmooth(const uint32_t* const prev_row,
+ const uint32_t* const curr_row,
+ const uint32_t* const next_row,
+ int ix, int limit) {
+ // Check that all pixels in 4-connected neighborhood are smooth.
+ return (IsNear(curr_row[ix], curr_row[ix - 1], limit) &&
+ IsNear(curr_row[ix], curr_row[ix + 1], limit) &&
+ IsNear(curr_row[ix], prev_row[ix], limit) &&
+ IsNear(curr_row[ix], next_row[ix], limit));
+}
+
+// Adjusts pixel values of image with given maximum error.
+static void NearLossless(int xsize, int ysize, uint32_t* argb,
+ int limit_bits, uint32_t* copy_buffer) {
+ int x, y;
+ const int limit = 1 << limit_bits;
+ uint32_t* prev_row = copy_buffer;
+ uint32_t* curr_row = prev_row + xsize;
+ uint32_t* next_row = curr_row + xsize;
+ memcpy(copy_buffer, argb, xsize * 2 * sizeof(argb[0]));
+
+ for (y = 1; y < ysize - 1; ++y) {
+ uint32_t* const curr_argb_row = argb + y * xsize;
+ uint32_t* const next_argb_row = curr_argb_row + xsize;
+ memcpy(next_row, next_argb_row, xsize * sizeof(argb[0]));
+ for (x = 1; x < xsize - 1; ++x) {
+ if (!IsSmooth(prev_row, curr_row, next_row, x, limit)) {
+ curr_argb_row[x] = ClosestDiscretizedArgb(curr_row[x], limit_bits);
+ }
+ }
+ {
+ // Three-way swap.
+ uint32_t* const temp = prev_row;
+ prev_row = curr_row;
+ curr_row = next_row;
+ next_row = temp;
+ }
+ }
+}
+
+static int QualityToLimitBits(int quality) {
+ // quality mapping:
+ // 0..19 -> 5
+ // 0..39 -> 4
+ // 0..59 -> 3
+ // 0..79 -> 2
+ // 0..99 -> 1
+ // 100 -> 0
+ return MAX_LIMIT_BITS - quality / 20;
+}
+
+int VP8ApplyNearLossless(int xsize, int ysize, uint32_t* argb, int quality) {
+ int i;
+ uint32_t* const copy_buffer =
+ (uint32_t*)WebPSafeMalloc(xsize * 3, sizeof(*copy_buffer));
+ const int limit_bits = QualityToLimitBits(quality);
+ assert(argb != NULL);
+ assert(limit_bits >= 0);
+ assert(limit_bits <= MAX_LIMIT_BITS);
+ if (copy_buffer == NULL) {
+ return 0;
+ }
+ // For small icon images, don't attempt to apply near-lossless compression.
+ if (xsize < MIN_DIM_FOR_NEAR_LOSSLESS && ysize < MIN_DIM_FOR_NEAR_LOSSLESS) {
+ WebPSafeFree(copy_buffer);
+ return 1;
+ }
+
+ for (i = limit_bits; i != 0; --i) {
+ NearLossless(xsize, ysize, argb, i, copy_buffer);
+ }
+ WebPSafeFree(copy_buffer);
+ return 1;
+}
diff --git a/drivers/webp/enc/picture.c b/drivers/webp/enc/picture.c
index 44eed06083..26679a72e4 100644
--- a/drivers/webp/enc/picture.c
+++ b/drivers/webp/enc/picture.c
@@ -1,470 +1,179 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
-// WebPPicture utils: colorspace conversion, crop, ...
+// WebPPicture class basis
//
// Author: Skal (pascal.massimino@gmail.com)
#include <assert.h>
#include <stdlib.h>
-#include <math.h>
#include "./vp8enci.h"
-#include "../utils/rescaler.h"
-#include "../utils/utils.h"
#include "../dsp/dsp.h"
-#include "../dsp/yuv.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-#define HALVE(x) (((x) + 1) >> 1)
-#define IS_YUV_CSP(csp, YUV_CSP) (((csp) & WEBP_CSP_UV_MASK) == (YUV_CSP))
-
-static const union {
- uint32_t argb;
- uint8_t bytes[4];
-} test_endian = { 0xff000000u };
-#define ALPHA_IS_LAST (test_endian.bytes[3] == 0xff)
+#include "../utils/utils.h"
//------------------------------------------------------------------------------
// WebPPicture
//------------------------------------------------------------------------------
-int WebPPictureAlloc(WebPPicture* picture) {
- if (picture != NULL) {
- const WebPEncCSP uv_csp = picture->colorspace & WEBP_CSP_UV_MASK;
- const int has_alpha = picture->colorspace & WEBP_CSP_ALPHA_BIT;
- const int width = picture->width;
- const int height = picture->height;
-
- if (!picture->use_argb) {
- const int y_stride = width;
- const int uv_width = HALVE(width);
- const int uv_height = HALVE(height);
- const int uv_stride = uv_width;
- int uv0_stride = 0;
- int a_width, a_stride;
- uint64_t y_size, uv_size, uv0_size, a_size, total_size;
- uint8_t* mem;
-
- // U/V
- switch (uv_csp) {
- case WEBP_YUV420:
- break;
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- case WEBP_YUV400: // for now, we'll just reset the U/V samples
- break;
- case WEBP_YUV422:
- uv0_stride = uv_width;
- break;
- case WEBP_YUV444:
- uv0_stride = width;
- break;
-#endif
- default:
- return 0;
- }
- uv0_size = height * uv0_stride;
-
- // alpha
- a_width = has_alpha ? width : 0;
- a_stride = a_width;
- y_size = (uint64_t)y_stride * height;
- uv_size = (uint64_t)uv_stride * uv_height;
- a_size = (uint64_t)a_stride * height;
-
- total_size = y_size + a_size + 2 * uv_size + 2 * uv0_size;
-
- // Security and validation checks
- if (width <= 0 || height <= 0 || // luma/alpha param error
- uv_width < 0 || uv_height < 0) { // u/v param error
- return 0;
- }
- // Clear previous buffer and allocate a new one.
- WebPPictureFree(picture); // erase previous buffer
- mem = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*mem));
- if (mem == NULL) return 0;
-
- // From now on, we're in the clear, we can no longer fail...
- picture->memory_ = (void*)mem;
- picture->y_stride = y_stride;
- picture->uv_stride = uv_stride;
- picture->a_stride = a_stride;
- picture->uv0_stride = uv0_stride;
- // TODO(skal): we could align the y/u/v planes and adjust stride.
- picture->y = mem;
- mem += y_size;
-
- picture->u = mem;
- mem += uv_size;
- picture->v = mem;
- mem += uv_size;
-
- if (a_size) {
- picture->a = mem;
- mem += a_size;
- }
- if (uv0_size) {
- picture->u0 = mem;
- mem += uv0_size;
- picture->v0 = mem;
- mem += uv0_size;
- }
- } else {
- void* memory;
- const uint64_t argb_size = (uint64_t)width * height;
- if (width <= 0 || height <= 0) {
- return 0;
- }
- // Clear previous buffer and allocate a new one.
- WebPPictureFree(picture); // erase previous buffer
- memory = WebPSafeMalloc(argb_size, sizeof(*picture->argb));
- if (memory == NULL) return 0;
+static int DummyWriter(const uint8_t* data, size_t data_size,
+ const WebPPicture* const picture) {
+ // The following are to prevent 'unused variable' error message.
+ (void)data;
+ (void)data_size;
+ (void)picture;
+ return 1;
+}
- // TODO(skal): align plane to cache line?
- picture->memory_argb_ = memory;
- picture->argb = (uint32_t*)memory;
- picture->argb_stride = width;
- }
+int WebPPictureInitInternal(WebPPicture* picture, int version) {
+ if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) {
+ return 0; // caller/system version mismatch!
+ }
+ if (picture != NULL) {
+ memset(picture, 0, sizeof(*picture));
+ picture->writer = DummyWriter;
+ WebPEncodingSetError(picture, VP8_ENC_OK);
}
return 1;
}
-// Remove reference to the ARGB buffer (doesn't free anything).
-static void PictureResetARGB(WebPPicture* const picture) {
+//------------------------------------------------------------------------------
+
+static void WebPPictureResetBufferARGB(WebPPicture* const picture) {
picture->memory_argb_ = NULL;
picture->argb = NULL;
picture->argb_stride = 0;
}
-// Remove reference to the YUVA buffer (doesn't free anything).
-static void PictureResetYUVA(WebPPicture* const picture) {
+static void WebPPictureResetBufferYUVA(WebPPicture* const picture) {
picture->memory_ = NULL;
picture->y = picture->u = picture->v = picture->a = NULL;
- picture->u0 = picture->v0 = NULL;
picture->y_stride = picture->uv_stride = 0;
picture->a_stride = 0;
- picture->uv0_stride = 0;
}
-// Grab the 'specs' (writer, *opaque, width, height...) from 'src' and copy them
-// into 'dst'. Mark 'dst' as not owning any memory.
-static void WebPPictureGrabSpecs(const WebPPicture* const src,
- WebPPicture* const dst) {
- assert(src != NULL && dst != NULL);
- *dst = *src;
- PictureResetYUVA(dst);
- PictureResetARGB(dst);
+void WebPPictureResetBuffers(WebPPicture* const picture) {
+ WebPPictureResetBufferARGB(picture);
+ WebPPictureResetBufferYUVA(picture);
}
-// Allocate a new argb buffer, discarding any existing one and preserving
-// the other YUV(A) buffer.
-static int PictureAllocARGB(WebPPicture* const picture) {
- WebPPicture tmp;
- free(picture->memory_argb_);
- PictureResetARGB(picture);
- picture->use_argb = 1;
- WebPPictureGrabSpecs(picture, &tmp);
- if (!WebPPictureAlloc(&tmp)) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
- }
- picture->memory_argb_ = tmp.memory_argb_;
- picture->argb = tmp.argb;
- picture->argb_stride = tmp.argb_stride;
- return 1;
-}
+int WebPPictureAllocARGB(WebPPicture* const picture, int width, int height) {
+ void* memory;
+ const uint64_t argb_size = (uint64_t)width * height;
-// Release memory owned by 'picture' (both YUV and ARGB buffers).
-void WebPPictureFree(WebPPicture* picture) {
- if (picture != NULL) {
- free(picture->memory_);
- free(picture->memory_argb_);
- PictureResetYUVA(picture);
- PictureResetARGB(picture);
- }
-}
+ assert(picture != NULL);
-//------------------------------------------------------------------------------
-// Picture copying
+ WebPSafeFree(picture->memory_argb_);
+ WebPPictureResetBufferARGB(picture);
-// Not worth moving to dsp/enc.c (only used here).
-static void CopyPlane(const uint8_t* src, int src_stride,
- uint8_t* dst, int dst_stride, int width, int height) {
- while (height-- > 0) {
- memcpy(dst, src, width);
- src += src_stride;
- dst += dst_stride;
+ if (width <= 0 || height <= 0) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
}
-}
-
-// Adjust top-left corner to chroma sample position.
-static void SnapTopLeftPosition(const WebPPicture* const pic,
- int* const left, int* const top) {
- if (!pic->use_argb) {
- const int is_yuv422 = IS_YUV_CSP(pic->colorspace, WEBP_YUV422);
- if (IS_YUV_CSP(pic->colorspace, WEBP_YUV420) || is_yuv422) {
- *left &= ~1;
- if (!is_yuv422) *top &= ~1;
- }
+ // allocate a new buffer.
+ memory = WebPSafeMalloc(argb_size, sizeof(*picture->argb));
+ if (memory == NULL) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
-}
-
-// Adjust top-left corner and verify that the sub-rectangle is valid.
-static int AdjustAndCheckRectangle(const WebPPicture* const pic,
- int* const left, int* const top,
- int width, int height) {
- SnapTopLeftPosition(pic, left, top);
- if ((*left) < 0 || (*top) < 0) return 0;
- if (width <= 0 || height <= 0) return 0;
- if ((*left) + width > pic->width) return 0;
- if ((*top) + height > pic->height) return 0;
+ // TODO(skal): align plane to cache line?
+ picture->memory_argb_ = memory;
+ picture->argb = (uint32_t*)memory;
+ picture->argb_stride = width;
return 1;
}
-int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst) {
- if (src == NULL || dst == NULL) return 0;
- if (src == dst) return 1;
+int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height) {
+ const WebPEncCSP uv_csp = picture->colorspace & WEBP_CSP_UV_MASK;
+ const int has_alpha = picture->colorspace & WEBP_CSP_ALPHA_BIT;
+ const int y_stride = width;
+ const int uv_width = (width + 1) >> 1;
+ const int uv_height = (height + 1) >> 1;
+ const int uv_stride = uv_width;
+ int a_width, a_stride;
+ uint64_t y_size, uv_size, a_size, total_size;
+ uint8_t* mem;
- WebPPictureGrabSpecs(src, dst);
- if (!WebPPictureAlloc(dst)) return 0;
+ assert(picture != NULL);
- if (!src->use_argb) {
- CopyPlane(src->y, src->y_stride,
- dst->y, dst->y_stride, dst->width, dst->height);
- CopyPlane(src->u, src->uv_stride,
- dst->u, dst->uv_stride, HALVE(dst->width), HALVE(dst->height));
- CopyPlane(src->v, src->uv_stride,
- dst->v, dst->uv_stride, HALVE(dst->width), HALVE(dst->height));
- if (dst->a != NULL) {
- CopyPlane(src->a, src->a_stride,
- dst->a, dst->a_stride, dst->width, dst->height);
- }
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- if (dst->u0 != NULL) {
- int uv0_width = src->width;
- if (IS_YUV_CSP(dst->colorspace, WEBP_YUV422)) {
- uv0_width = HALVE(uv0_width);
- }
- CopyPlane(src->u0, src->uv0_stride,
- dst->u0, dst->uv0_stride, uv0_width, dst->height);
- CopyPlane(src->v0, src->uv0_stride,
- dst->v0, dst->uv0_stride, uv0_width, dst->height);
- }
-#endif
- } else {
- CopyPlane((const uint8_t*)src->argb, 4 * src->argb_stride,
- (uint8_t*)dst->argb, 4 * dst->argb_stride,
- 4 * dst->width, dst->height);
- }
- return 1;
-}
+ WebPSafeFree(picture->memory_);
+ WebPPictureResetBufferYUVA(picture);
-int WebPPictureIsView(const WebPPicture* picture) {
- if (picture == NULL) return 0;
- if (picture->use_argb) {
- return (picture->memory_argb_ == NULL);
+ if (uv_csp != WEBP_YUV420) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
}
- return (picture->memory_ == NULL);
-}
-int WebPPictureView(const WebPPicture* src,
- int left, int top, int width, int height,
- WebPPicture* dst) {
- if (src == NULL || dst == NULL) return 0;
+ // alpha
+ a_width = has_alpha ? width : 0;
+ a_stride = a_width;
+ y_size = (uint64_t)y_stride * height;
+ uv_size = (uint64_t)uv_stride * uv_height;
+ a_size = (uint64_t)a_stride * height;
- // verify rectangle position.
- if (!AdjustAndCheckRectangle(src, &left, &top, width, height)) return 0;
+ total_size = y_size + a_size + 2 * uv_size;
- if (src != dst) { // beware of aliasing! We don't want to leak 'memory_'.
- WebPPictureGrabSpecs(src, dst);
+ // Security and validation checks
+ if (width <= 0 || height <= 0 || // luma/alpha param error
+ uv_width < 0 || uv_height < 0) { // u/v param error
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
}
- dst->width = width;
- dst->height = height;
- if (!src->use_argb) {
- dst->y = src->y + top * src->y_stride + left;
- dst->u = src->u + (top >> 1) * src->uv_stride + (left >> 1);
- dst->v = src->v + (top >> 1) * src->uv_stride + (left >> 1);
- if (src->a != NULL) {
- dst->a = src->a + top * src->a_stride + left;
- }
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- if (src->u0 != NULL) {
- const int left_pos =
- IS_YUV_CSP(dst->colorspace, WEBP_YUV422) ? (left >> 1) : left;
- dst->u0 = src->u0 + top * src->uv0_stride + left_pos;
- dst->v0 = src->v0 + top * src->uv0_stride + left_pos;
- }
-#endif
- } else {
- dst->argb = src->argb + top * src->argb_stride + left;
+ // allocate a new buffer.
+ mem = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*mem));
+ if (mem == NULL) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
- return 1;
-}
-//------------------------------------------------------------------------------
-// Picture cropping
+ // From now on, we're in the clear, we can no longer fail...
+ picture->memory_ = (void*)mem;
+ picture->y_stride = y_stride;
+ picture->uv_stride = uv_stride;
+ picture->a_stride = a_stride;
-int WebPPictureCrop(WebPPicture* pic,
- int left, int top, int width, int height) {
- WebPPicture tmp;
+ // TODO(skal): we could align the y/u/v planes and adjust stride.
+ picture->y = mem;
+ mem += y_size;
- if (pic == NULL) return 0;
- if (!AdjustAndCheckRectangle(pic, &left, &top, width, height)) return 0;
+ picture->u = mem;
+ mem += uv_size;
+ picture->v = mem;
+ mem += uv_size;
- WebPPictureGrabSpecs(pic, &tmp);
- tmp.width = width;
- tmp.height = height;
- if (!WebPPictureAlloc(&tmp)) return 0;
-
- if (!pic->use_argb) {
- const int y_offset = top * pic->y_stride + left;
- const int uv_offset = (top / 2) * pic->uv_stride + left / 2;
- CopyPlane(pic->y + y_offset, pic->y_stride,
- tmp.y, tmp.y_stride, width, height);
- CopyPlane(pic->u + uv_offset, pic->uv_stride,
- tmp.u, tmp.uv_stride, HALVE(width), HALVE(height));
- CopyPlane(pic->v + uv_offset, pic->uv_stride,
- tmp.v, tmp.uv_stride, HALVE(width), HALVE(height));
-
- if (tmp.a != NULL) {
- const int a_offset = top * pic->a_stride + left;
- CopyPlane(pic->a + a_offset, pic->a_stride,
- tmp.a, tmp.a_stride, width, height);
- }
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- if (tmp.u0 != NULL) {
- int w = width;
- int left_pos = left;
- if (IS_YUV_CSP(tmp.colorspace, WEBP_YUV422)) {
- w = HALVE(w);
- left_pos = HALVE(left_pos);
- }
- CopyPlane(pic->u0 + top * pic->uv0_stride + left_pos, pic->uv0_stride,
- tmp.u0, tmp.uv0_stride, w, height);
- CopyPlane(pic->v0 + top * pic->uv0_stride + left_pos, pic->uv0_stride,
- tmp.v0, tmp.uv0_stride, w, height);
- }
-#endif
- } else {
- const uint8_t* const src =
- (const uint8_t*)(pic->argb + top * pic->argb_stride + left);
- CopyPlane(src, pic->argb_stride * 4,
- (uint8_t*)tmp.argb, tmp.argb_stride * 4,
- width * 4, height);
+ if (a_size > 0) {
+ picture->a = mem;
+ mem += a_size;
}
- WebPPictureFree(pic);
- *pic = tmp;
+ (void)mem; // makes the static analyzer happy
return 1;
}
-//------------------------------------------------------------------------------
-// Simple picture rescaler
-
-static void RescalePlane(const uint8_t* src,
- int src_width, int src_height, int src_stride,
- uint8_t* dst,
- int dst_width, int dst_height, int dst_stride,
- int32_t* const work,
- int num_channels) {
- WebPRescaler rescaler;
- int y = 0;
- WebPRescalerInit(&rescaler, src_width, src_height,
- dst, dst_width, dst_height, dst_stride,
- num_channels,
- src_width, dst_width,
- src_height, dst_height,
- work);
- memset(work, 0, 2 * dst_width * num_channels * sizeof(*work));
- while (y < src_height) {
- y += WebPRescalerImport(&rescaler, src_height - y,
- src + y * src_stride, src_stride);
- WebPRescalerExport(&rescaler);
- }
-}
-
-int WebPPictureRescale(WebPPicture* pic, int width, int height) {
- WebPPicture tmp;
- int prev_width, prev_height;
- int32_t* work;
-
- if (pic == NULL) return 0;
- prev_width = pic->width;
- prev_height = pic->height;
- // if width is unspecified, scale original proportionally to height ratio.
- if (width == 0) {
- width = (prev_width * height + prev_height / 2) / prev_height;
- }
- // if height is unspecified, scale original proportionally to width ratio.
- if (height == 0) {
- height = (prev_height * width + prev_width / 2) / prev_width;
- }
- // Check if the overall dimensions still make sense.
- if (width <= 0 || height <= 0) return 0;
-
- WebPPictureGrabSpecs(pic, &tmp);
- tmp.width = width;
- tmp.height = height;
- if (!WebPPictureAlloc(&tmp)) return 0;
-
- if (!pic->use_argb) {
- work = (int32_t*)WebPSafeMalloc(2ULL * width, sizeof(*work));
- if (work == NULL) {
- WebPPictureFree(&tmp);
- return 0;
- }
+int WebPPictureAlloc(WebPPicture* picture) {
+ if (picture != NULL) {
+ const int width = picture->width;
+ const int height = picture->height;
- RescalePlane(pic->y, prev_width, prev_height, pic->y_stride,
- tmp.y, width, height, tmp.y_stride, work, 1);
- RescalePlane(pic->u,
- HALVE(prev_width), HALVE(prev_height), pic->uv_stride,
- tmp.u,
- HALVE(width), HALVE(height), tmp.uv_stride, work, 1);
- RescalePlane(pic->v,
- HALVE(prev_width), HALVE(prev_height), pic->uv_stride,
- tmp.v,
- HALVE(width), HALVE(height), tmp.uv_stride, work, 1);
+ WebPPictureFree(picture); // erase previous buffer
- if (tmp.a != NULL) {
- RescalePlane(pic->a, prev_width, prev_height, pic->a_stride,
- tmp.a, width, height, tmp.a_stride, work, 1);
- }
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- if (tmp.u0 != NULL) {
- const int s = IS_YUV_CSP(tmp.colorspace, WEBP_YUV422) ? 2 : 1;
- RescalePlane(
- pic->u0, (prev_width + s / 2) / s, prev_height, pic->uv0_stride,
- tmp.u0, (width + s / 2) / s, height, tmp.uv0_stride, work, 1);
- RescalePlane(
- pic->v0, (prev_width + s / 2) / s, prev_height, pic->uv0_stride,
- tmp.v0, (width + s / 2) / s, height, tmp.uv0_stride, work, 1);
- }
-#endif
- } else {
- work = (int32_t*)WebPSafeMalloc(2ULL * width * 4, sizeof(*work));
- if (work == NULL) {
- WebPPictureFree(&tmp);
- return 0;
+ if (!picture->use_argb) {
+ return WebPPictureAllocYUVA(picture, width, height);
+ } else {
+ return WebPPictureAllocARGB(picture, width, height);
}
-
- RescalePlane((const uint8_t*)pic->argb, prev_width, prev_height,
- pic->argb_stride * 4,
- (uint8_t*)tmp.argb, width, height,
- tmp.argb_stride * 4,
- work, 4);
-
}
- WebPPictureFree(pic);
- free(work);
- *pic = tmp;
return 1;
}
+void WebPPictureFree(WebPPicture* picture) {
+ if (picture != NULL) {
+ WebPSafeFree(picture->memory_);
+ WebPSafeFree(picture->memory_argb_);
+ WebPPictureResetBuffers(picture);
+ }
+}
+
//------------------------------------------------------------------------------
// WebPMemoryWriter: Write-to-memory
@@ -494,7 +203,7 @@ int WebPMemoryWrite(const uint8_t* data, size_t data_size,
if (w->size > 0) {
memcpy(new_mem, w->mem, w->size);
}
- free(w->mem);
+ WebPSafeFree(w->mem);
w->mem = new_mem;
// down-cast is ok, thanks to WebPSafeMalloc
w->max_size = (size_t)next_max_size;
@@ -506,469 +215,13 @@ int WebPMemoryWrite(const uint8_t* data, size_t data_size,
return 1;
}
-//------------------------------------------------------------------------------
-// Detection of non-trivial transparency
-
-// Returns true if alpha[] has non-0xff values.
-static int CheckNonOpaque(const uint8_t* alpha, int width, int height,
- int x_step, int y_step) {
- if (alpha == NULL) return 0;
- while (height-- > 0) {
- int x;
- for (x = 0; x < width * x_step; x += x_step) {
- if (alpha[x] != 0xff) return 1; // TODO(skal): check 4/8 bytes at a time.
- }
- alpha += y_step;
- }
- return 0;
-}
-
-// Checking for the presence of non-opaque alpha.
-int WebPPictureHasTransparency(const WebPPicture* picture) {
- if (picture == NULL) return 0;
- if (!picture->use_argb) {
- return CheckNonOpaque(picture->a, picture->width, picture->height,
- 1, picture->a_stride);
- } else {
- int x, y;
- const uint32_t* argb = picture->argb;
- if (argb == NULL) return 0;
- for (y = 0; y < picture->height; ++y) {
- for (x = 0; x < picture->width; ++x) {
- if (argb[x] < 0xff000000u) return 1; // test any alpha values != 0xff
- }
- argb += picture->argb_stride;
- }
- }
- return 0;
-}
-
-//------------------------------------------------------------------------------
-// RGB -> YUV conversion
-
-// TODO: we can do better than simply 2x2 averaging on U/V samples.
-#define SUM4(ptr) ((ptr)[0] + (ptr)[step] + \
- (ptr)[rgb_stride] + (ptr)[rgb_stride + step])
-#define SUM2H(ptr) (2 * (ptr)[0] + 2 * (ptr)[step])
-#define SUM2V(ptr) (2 * (ptr)[0] + 2 * (ptr)[rgb_stride])
-#define SUM1(ptr) (4 * (ptr)[0])
-#define RGB_TO_UV(x, y, SUM) { \
- const int src = (2 * (step * (x) + (y) * rgb_stride)); \
- const int dst = (x) + (y) * picture->uv_stride; \
- const int r = SUM(r_ptr + src); \
- const int g = SUM(g_ptr + src); \
- const int b = SUM(b_ptr + src); \
- picture->u[dst] = VP8RGBToU(r, g, b); \
- picture->v[dst] = VP8RGBToV(r, g, b); \
-}
-
-#define RGB_TO_UV0(x_in, x_out, y, SUM) { \
- const int src = (step * (x_in) + (y) * rgb_stride); \
- const int dst = (x_out) + (y) * picture->uv0_stride; \
- const int r = SUM(r_ptr + src); \
- const int g = SUM(g_ptr + src); \
- const int b = SUM(b_ptr + src); \
- picture->u0[dst] = VP8RGBToU(r, g, b); \
- picture->v0[dst] = VP8RGBToV(r, g, b); \
-}
-
-static void MakeGray(WebPPicture* const picture) {
- int y;
- const int uv_width = HALVE(picture->width);
- const int uv_height = HALVE(picture->height);
- for (y = 0; y < uv_height; ++y) {
- memset(picture->u + y * picture->uv_stride, 128, uv_width);
- memset(picture->v + y * picture->uv_stride, 128, uv_width);
- }
-}
-
-static int ImportYUVAFromRGBA(const uint8_t* const r_ptr,
- const uint8_t* const g_ptr,
- const uint8_t* const b_ptr,
- const uint8_t* const a_ptr,
- int step, // bytes per pixel
- int rgb_stride, // bytes per scanline
- WebPPicture* const picture) {
- const WebPEncCSP uv_csp = picture->colorspace & WEBP_CSP_UV_MASK;
- int x, y;
- const int width = picture->width;
- const int height = picture->height;
- const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride);
-
- picture->colorspace = uv_csp;
- picture->use_argb = 0;
- if (has_alpha) {
- picture->colorspace |= WEBP_CSP_ALPHA_BIT;
- }
- if (!WebPPictureAlloc(picture)) return 0;
-
- // Import luma plane
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; ++x) {
- const int offset = step * x + y * rgb_stride;
- picture->y[x + y * picture->y_stride] =
- VP8RGBToY(r_ptr[offset], g_ptr[offset], b_ptr[offset]);
- }
- }
-
- // Downsample U/V plane
- if (uv_csp != WEBP_YUV400) {
- for (y = 0; y < (height >> 1); ++y) {
- for (x = 0; x < (width >> 1); ++x) {
- RGB_TO_UV(x, y, SUM4);
- }
- if (width & 1) {
- RGB_TO_UV(x, y, SUM2V);
- }
- }
- if (height & 1) {
- for (x = 0; x < (width >> 1); ++x) {
- RGB_TO_UV(x, y, SUM2H);
- }
- if (width & 1) {
- RGB_TO_UV(x, y, SUM1);
- }
- }
-
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- // Store original U/V samples too
- if (uv_csp == WEBP_YUV422) {
- for (y = 0; y < height; ++y) {
- for (x = 0; x < (width >> 1); ++x) {
- RGB_TO_UV0(2 * x, x, y, SUM2H);
- }
- if (width & 1) {
- RGB_TO_UV0(2 * x, x, y, SUM1);
- }
- }
- } else if (uv_csp == WEBP_YUV444) {
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; ++x) {
- RGB_TO_UV0(x, x, y, SUM1);
- }
- }
- }
-#endif
- } else {
- MakeGray(picture);
- }
-
- if (has_alpha) {
- assert(step >= 4);
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; ++x) {
- picture->a[x + y * picture->a_stride] =
- a_ptr[step * x + y * rgb_stride];
- }
- }
- }
- return 1;
-}
-
-static int Import(WebPPicture* const picture,
- const uint8_t* const rgb, int rgb_stride,
- int step, int swap_rb, int import_alpha) {
- const uint8_t* const r_ptr = rgb + (swap_rb ? 2 : 0);
- const uint8_t* const g_ptr = rgb + 1;
- const uint8_t* const b_ptr = rgb + (swap_rb ? 0 : 2);
- const uint8_t* const a_ptr = import_alpha ? rgb + 3 : NULL;
- const int width = picture->width;
- const int height = picture->height;
-
- if (!picture->use_argb) {
- return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride,
- picture);
- }
- if (import_alpha) {
- picture->colorspace |= WEBP_CSP_ALPHA_BIT;
- } else {
- picture->colorspace &= ~WEBP_CSP_ALPHA_BIT;
- }
- if (!WebPPictureAlloc(picture)) return 0;
-
- if (!import_alpha) {
- int x, y;
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; ++x) {
- const int offset = step * x + y * rgb_stride;
- const uint32_t argb =
- 0xff000000u |
- (r_ptr[offset] << 16) |
- (g_ptr[offset] << 8) |
- (b_ptr[offset]);
- picture->argb[x + y * picture->argb_stride] = argb;
- }
- }
- } else {
- int x, y;
- assert(step >= 4);
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; ++x) {
- const int offset = step * x + y * rgb_stride;
- const uint32_t argb = (a_ptr[offset] << 24) |
- (r_ptr[offset] << 16) |
- (g_ptr[offset] << 8) |
- (b_ptr[offset]);
- picture->argb[x + y * picture->argb_stride] = argb;
- }
- }
- }
- return 1;
-}
-#undef SUM4
-#undef SUM2V
-#undef SUM2H
-#undef SUM1
-#undef RGB_TO_UV
-
-int WebPPictureImportRGB(WebPPicture* picture,
- const uint8_t* rgb, int rgb_stride) {
- return Import(picture, rgb, rgb_stride, 3, 0, 0);
-}
-
-int WebPPictureImportBGR(WebPPicture* picture,
- const uint8_t* rgb, int rgb_stride) {
- return Import(picture, rgb, rgb_stride, 3, 1, 0);
-}
-
-int WebPPictureImportRGBA(WebPPicture* picture,
- const uint8_t* rgba, int rgba_stride) {
- return Import(picture, rgba, rgba_stride, 4, 0, 1);
-}
-
-int WebPPictureImportBGRA(WebPPicture* picture,
- const uint8_t* rgba, int rgba_stride) {
- return Import(picture, rgba, rgba_stride, 4, 1, 1);
-}
-
-int WebPPictureImportRGBX(WebPPicture* picture,
- const uint8_t* rgba, int rgba_stride) {
- return Import(picture, rgba, rgba_stride, 4, 0, 0);
-}
-
-int WebPPictureImportBGRX(WebPPicture* picture,
- const uint8_t* rgba, int rgba_stride) {
- return Import(picture, rgba, rgba_stride, 4, 1, 0);
-}
-
-//------------------------------------------------------------------------------
-// Automatic YUV <-> ARGB conversions.
-
-int WebPPictureYUVAToARGB(WebPPicture* picture) {
- if (picture == NULL) return 0;
- if (picture->memory_ == NULL || picture->y == NULL ||
- picture->u == NULL || picture->v == NULL) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
- }
- if ((picture->colorspace & WEBP_CSP_ALPHA_BIT) && picture->a == NULL) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
- }
- if ((picture->colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
- }
- // Allocate a new argb buffer (discarding the previous one).
- if (!PictureAllocARGB(picture)) return 0;
-
- // Convert
- {
- int y;
- const int width = picture->width;
- const int height = picture->height;
- const int argb_stride = 4 * picture->argb_stride;
- uint8_t* dst = (uint8_t*)picture->argb;
- const uint8_t *cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y;
- WebPUpsampleLinePairFunc upsample = WebPGetLinePairConverter(ALPHA_IS_LAST);
-
- // First row, with replicated top samples.
- upsample(NULL, cur_y, cur_u, cur_v, cur_u, cur_v, NULL, dst, width);
- cur_y += picture->y_stride;
- dst += argb_stride;
- // Center rows.
- for (y = 1; y + 1 < height; y += 2) {
- const uint8_t* const top_u = cur_u;
- const uint8_t* const top_v = cur_v;
- cur_u += picture->uv_stride;
- cur_v += picture->uv_stride;
- upsample(cur_y, cur_y + picture->y_stride, top_u, top_v, cur_u, cur_v,
- dst, dst + argb_stride, width);
- cur_y += 2 * picture->y_stride;
- dst += 2 * argb_stride;
- }
- // Last row (if needed), with replicated bottom samples.
- if (height > 1 && !(height & 1)) {
- upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width);
- }
- // Insert alpha values if needed, in replacement for the default 0xff ones.
- if (picture->colorspace & WEBP_CSP_ALPHA_BIT) {
- for (y = 0; y < height; ++y) {
- uint32_t* const dst = picture->argb + y * picture->argb_stride;
- const uint8_t* const src = picture->a + y * picture->a_stride;
- int x;
- for (x = 0; x < width; ++x) {
- dst[x] = (dst[x] & 0x00ffffffu) | (src[x] << 24);
- }
- }
- }
- }
- return 1;
-}
-
-int WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) {
- if (picture == NULL) return 0;
- if (picture->argb == NULL) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
- } else {
- const uint8_t* const argb = (const uint8_t*)picture->argb;
- const uint8_t* const r = ALPHA_IS_LAST ? argb + 2 : argb + 1;
- const uint8_t* const g = ALPHA_IS_LAST ? argb + 1 : argb + 2;
- const uint8_t* const b = ALPHA_IS_LAST ? argb + 0 : argb + 3;
- const uint8_t* const a = ALPHA_IS_LAST ? argb + 3 : argb + 0;
- // We work on a tmp copy of 'picture', because ImportYUVAFromRGBA()
- // would be calling WebPPictureFree(picture) otherwise.
- WebPPicture tmp = *picture;
- PictureResetARGB(&tmp); // reset ARGB buffer so that it's not free()'d.
- tmp.use_argb = 0;
- tmp.colorspace = colorspace & WEBP_CSP_UV_MASK;
- if (!ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride, &tmp)) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
- }
- // Copy back the YUV specs into 'picture'.
- tmp.argb = picture->argb;
- tmp.argb_stride = picture->argb_stride;
- tmp.memory_argb_ = picture->memory_argb_;
- *picture = tmp;
+void WebPMemoryWriterClear(WebPMemoryWriter* writer) {
+ if (writer != NULL) {
+ WebPSafeFree(writer->mem);
+ writer->mem = NULL;
+ writer->size = 0;
+ writer->max_size = 0;
}
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Helper: clean up fully transparent area to help compressibility.
-
-#define SIZE 8
-#define SIZE2 (SIZE / 2)
-static int is_transparent_area(const uint8_t* ptr, int stride, int size) {
- int y, x;
- for (y = 0; y < size; ++y) {
- for (x = 0; x < size; ++x) {
- if (ptr[x]) {
- return 0;
- }
- }
- ptr += stride;
- }
- return 1;
-}
-
-static WEBP_INLINE void flatten(uint8_t* ptr, int v, int stride, int size) {
- int y;
- for (y = 0; y < size; ++y) {
- memset(ptr, v, size);
- ptr += stride;
- }
-}
-
-void WebPCleanupTransparentArea(WebPPicture* pic) {
- int x, y, w, h;
- const uint8_t* a_ptr;
- int values[3] = { 0 };
-
- if (pic == NULL) return;
-
- a_ptr = pic->a;
- if (a_ptr == NULL) return; // nothing to do
-
- w = pic->width / SIZE;
- h = pic->height / SIZE;
- for (y = 0; y < h; ++y) {
- int need_reset = 1;
- for (x = 0; x < w; ++x) {
- const int off_a = (y * pic->a_stride + x) * SIZE;
- const int off_y = (y * pic->y_stride + x) * SIZE;
- const int off_uv = (y * pic->uv_stride + x) * SIZE2;
- if (is_transparent_area(a_ptr + off_a, pic->a_stride, SIZE)) {
- if (need_reset) {
- values[0] = pic->y[off_y];
- values[1] = pic->u[off_uv];
- values[2] = pic->v[off_uv];
- need_reset = 0;
- }
- flatten(pic->y + off_y, values[0], pic->y_stride, SIZE);
- flatten(pic->u + off_uv, values[1], pic->uv_stride, SIZE2);
- flatten(pic->v + off_uv, values[2], pic->uv_stride, SIZE2);
- } else {
- need_reset = 1;
- }
- }
- // ignore the left-overs on right/bottom
- }
-}
-
-#undef SIZE
-#undef SIZE2
-
-
-//------------------------------------------------------------------------------
-// Distortion
-
-// Max value returned in case of exact similarity.
-static const double kMinDistortion_dB = 99.;
-
-int WebPPictureDistortion(const WebPPicture* pic1, const WebPPicture* pic2,
- int type, float result[5]) {
- int c;
- DistoStats stats[5];
- int has_alpha;
-
- if (pic1 == NULL || pic2 == NULL ||
- pic1->width != pic2->width || pic1->height != pic2->height ||
- pic1->y == NULL || pic2->y == NULL ||
- pic1->u == NULL || pic2->u == NULL ||
- pic1->v == NULL || pic2->v == NULL ||
- result == NULL) {
- return 0;
- }
- // TODO(skal): provide distortion for ARGB too.
- if (pic1->use_argb == 1 || pic1->use_argb != pic2->use_argb) {
- return 0;
- }
-
- has_alpha = !!(pic1->colorspace & WEBP_CSP_ALPHA_BIT);
- if (has_alpha != !!(pic2->colorspace & WEBP_CSP_ALPHA_BIT) ||
- (has_alpha && (pic1->a == NULL || pic2->a == NULL))) {
- return 0;
- }
-
- memset(stats, 0, sizeof(stats));
- VP8SSIMAccumulatePlane(pic1->y, pic1->y_stride,
- pic2->y, pic2->y_stride,
- pic1->width, pic1->height, &stats[0]);
- VP8SSIMAccumulatePlane(pic1->u, pic1->uv_stride,
- pic2->u, pic2->uv_stride,
- (pic1->width + 1) >> 1, (pic1->height + 1) >> 1,
- &stats[1]);
- VP8SSIMAccumulatePlane(pic1->v, pic1->uv_stride,
- pic2->v, pic2->uv_stride,
- (pic1->width + 1) >> 1, (pic1->height + 1) >> 1,
- &stats[2]);
- if (has_alpha) {
- VP8SSIMAccumulatePlane(pic1->a, pic1->a_stride,
- pic2->a, pic2->a_stride,
- pic1->width, pic1->height, &stats[3]);
- }
- for (c = 0; c <= 4; ++c) {
- if (type == 1) {
- const double v = VP8SSIMGet(&stats[c]);
- result[c] = (float)((v < 1.) ? -10.0 * log10(1. - v)
- : kMinDistortion_dB);
- } else {
- const double v = VP8SSIMGetSquaredError(&stats[c]);
- result[c] = (float)((v > 0.) ? -4.3429448 * log(v / (255 * 255.))
- : kMinDistortion_dB);
- }
- // Accumulate forward
- if (c < 4) VP8SSIMAddStats(&stats[c], &stats[4]);
- }
- return 1;
}
//------------------------------------------------------------------------------
@@ -1000,7 +253,7 @@ static size_t Encode(const uint8_t* rgba, int width, int height, int stride,
ok = import(&pic, rgba, stride) && WebPEncode(&config, &pic);
WebPPictureFree(&pic);
if (!ok) {
- free(wrt.mem);
+ WebPMemoryWriterClear(&wrt);
*output = NULL;
return 0;
}
@@ -1014,10 +267,10 @@ size_t NAME(const uint8_t* in, int w, int h, int bps, float q, \
return Encode(in, w, h, bps, IMPORTER, q, 0, out); \
}
-ENCODE_FUNC(WebPEncodeRGB, WebPPictureImportRGB);
-ENCODE_FUNC(WebPEncodeBGR, WebPPictureImportBGR);
-ENCODE_FUNC(WebPEncodeRGBA, WebPPictureImportRGBA);
-ENCODE_FUNC(WebPEncodeBGRA, WebPPictureImportBGRA);
+ENCODE_FUNC(WebPEncodeRGB, WebPPictureImportRGB)
+ENCODE_FUNC(WebPEncodeBGR, WebPPictureImportBGR)
+ENCODE_FUNC(WebPEncodeRGBA, WebPPictureImportRGBA)
+ENCODE_FUNC(WebPEncodeBGRA, WebPPictureImportBGRA)
#undef ENCODE_FUNC
@@ -1027,15 +280,11 @@ size_t NAME(const uint8_t* in, int w, int h, int bps, uint8_t** out) { \
return Encode(in, w, h, bps, IMPORTER, LOSSLESS_DEFAULT_QUALITY, 1, out); \
}
-LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGB, WebPPictureImportRGB);
-LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGR, WebPPictureImportBGR);
-LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGBA, WebPPictureImportRGBA);
-LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGRA, WebPPictureImportBGRA);
+LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGB, WebPPictureImportRGB)
+LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGR, WebPPictureImportBGR)
+LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGBA, WebPPictureImportRGBA)
+LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGRA, WebPPictureImportBGRA)
#undef LOSSLESS_ENCODE_FUNC
//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/enc/picture_csp.c b/drivers/webp/enc/picture_csp.c
new file mode 100644
index 0000000000..0ef5f9eee2
--- /dev/null
+++ b/drivers/webp/enc/picture_csp.c
@@ -0,0 +1,1156 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// WebPPicture utils for colorspace conversion
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "./vp8enci.h"
+#include "../utils/random.h"
+#include "../utils/utils.h"
+#include "../dsp/yuv.h"
+
+// Uncomment to disable gamma-compression during RGB->U/V averaging
+#define USE_GAMMA_COMPRESSION
+
+// If defined, use table to compute x / alpha.
+#define USE_INVERSE_ALPHA_TABLE
+
+static const union {
+ uint32_t argb;
+ uint8_t bytes[4];
+} test_endian = { 0xff000000u };
+#define ALPHA_IS_LAST (test_endian.bytes[3] == 0xff)
+
+//------------------------------------------------------------------------------
+// Detection of non-trivial transparency
+
+// Returns true if alpha[] has non-0xff values.
+static int CheckNonOpaque(const uint8_t* alpha, int width, int height,
+ int x_step, int y_step) {
+ if (alpha == NULL) return 0;
+ while (height-- > 0) {
+ int x;
+ for (x = 0; x < width * x_step; x += x_step) {
+ if (alpha[x] != 0xff) return 1; // TODO(skal): check 4/8 bytes at a time.
+ }
+ alpha += y_step;
+ }
+ return 0;
+}
+
+// Checking for the presence of non-opaque alpha.
+int WebPPictureHasTransparency(const WebPPicture* picture) {
+ if (picture == NULL) return 0;
+ if (!picture->use_argb) {
+ return CheckNonOpaque(picture->a, picture->width, picture->height,
+ 1, picture->a_stride);
+ } else {
+ int x, y;
+ const uint32_t* argb = picture->argb;
+ if (argb == NULL) return 0;
+ for (y = 0; y < picture->height; ++y) {
+ for (x = 0; x < picture->width; ++x) {
+ if (argb[x] < 0xff000000u) return 1; // test any alpha values != 0xff
+ }
+ argb += picture->argb_stride;
+ }
+ }
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+// Code for gamma correction
+
+#if defined(USE_GAMMA_COMPRESSION)
+
+// gamma-compensates loss of resolution during chroma subsampling
+#define kGamma 0.80 // for now we use a different gamma value than kGammaF
+#define kGammaFix 12 // fixed-point precision for linear values
+#define kGammaScale ((1 << kGammaFix) - 1)
+#define kGammaTabFix 7 // fixed-point fractional bits precision
+#define kGammaTabScale (1 << kGammaTabFix)
+#define kGammaTabRounder (kGammaTabScale >> 1)
+#define kGammaTabSize (1 << (kGammaFix - kGammaTabFix))
+
+static int kLinearToGammaTab[kGammaTabSize + 1];
+static uint16_t kGammaToLinearTab[256];
+static volatile int kGammaTablesOk = 0;
+
+static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTables(void) {
+ if (!kGammaTablesOk) {
+ int v;
+ const double scale = (double)(1 << kGammaTabFix) / kGammaScale;
+ const double norm = 1. / 255.;
+ for (v = 0; v <= 255; ++v) {
+ kGammaToLinearTab[v] =
+ (uint16_t)(pow(norm * v, kGamma) * kGammaScale + .5);
+ }
+ for (v = 0; v <= kGammaTabSize; ++v) {
+ kLinearToGammaTab[v] = (int)(255. * pow(scale * v, 1. / kGamma) + .5);
+ }
+ kGammaTablesOk = 1;
+ }
+}
+
+static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) {
+ return kGammaToLinearTab[v];
+}
+
+static WEBP_INLINE int Interpolate(int v) {
+ const int tab_pos = v >> (kGammaTabFix + 2); // integer part
+ const int x = v & ((kGammaTabScale << 2) - 1); // fractional part
+ const int v0 = kLinearToGammaTab[tab_pos];
+ const int v1 = kLinearToGammaTab[tab_pos + 1];
+ const int y = v1 * x + v0 * ((kGammaTabScale << 2) - x); // interpolate
+ assert(tab_pos + 1 < kGammaTabSize + 1);
+ return y;
+}
+
+// Convert a linear value 'v' to YUV_FIX+2 fixed-point precision
+// U/V value, suitable for RGBToU/V calls.
+static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) {
+ const int y = Interpolate(base_value << shift); // final uplifted value
+ return (y + kGammaTabRounder) >> kGammaTabFix; // descale
+}
+
+#else
+
+static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTables(void) {}
+static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { return v; }
+static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) {
+ return (int)(base_value << shift);
+}
+
+#endif // USE_GAMMA_COMPRESSION
+
+//------------------------------------------------------------------------------
+// RGB -> YUV conversion
+
+static int RGBToY(int r, int g, int b, VP8Random* const rg) {
+ return (rg == NULL) ? VP8RGBToY(r, g, b, YUV_HALF)
+ : VP8RGBToY(r, g, b, VP8RandomBits(rg, YUV_FIX));
+}
+
+static int RGBToU(int r, int g, int b, VP8Random* const rg) {
+ return (rg == NULL) ? VP8RGBToU(r, g, b, YUV_HALF << 2)
+ : VP8RGBToU(r, g, b, VP8RandomBits(rg, YUV_FIX + 2));
+}
+
+static int RGBToV(int r, int g, int b, VP8Random* const rg) {
+ return (rg == NULL) ? VP8RGBToV(r, g, b, YUV_HALF << 2)
+ : VP8RGBToV(r, g, b, VP8RandomBits(rg, YUV_FIX + 2));
+}
+
+//------------------------------------------------------------------------------
+// Smart RGB->YUV conversion
+
+static const int kNumIterations = 6;
+static const int kMinDimensionIterativeConversion = 4;
+
+// We could use SFIX=0 and only uint8_t for fixed_y_t, but it produces some
+// banding sometimes. Better use extra precision.
+#define SFIX 2 // fixed-point precision of RGB and Y/W
+typedef int16_t fixed_t; // signed type with extra SFIX precision for UV
+typedef uint16_t fixed_y_t; // unsigned type with extra SFIX precision for W
+
+#define SHALF (1 << SFIX >> 1)
+#define MAX_Y_T ((256 << SFIX) - 1)
+#define SROUNDER (1 << (YUV_FIX + SFIX - 1))
+
+#if defined(USE_GAMMA_COMPRESSION)
+
+// float variant of gamma-correction
+// We use tables of different size and precision, along with a 'real-world'
+// Gamma value close to ~2.
+#define kGammaF 2.2
+static float kGammaToLinearTabF[MAX_Y_T + 1]; // size scales with Y_FIX
+static float kLinearToGammaTabF[kGammaTabSize + 2];
+static volatile int kGammaTablesFOk = 0;
+
+static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTablesF(void) {
+ if (!kGammaTablesFOk) {
+ int v;
+ const double norm = 1. / MAX_Y_T;
+ const double scale = 1. / kGammaTabSize;
+ for (v = 0; v <= MAX_Y_T; ++v) {
+ kGammaToLinearTabF[v] = (float)pow(norm * v, kGammaF);
+ }
+ for (v = 0; v <= kGammaTabSize; ++v) {
+ kLinearToGammaTabF[v] = (float)(MAX_Y_T * pow(scale * v, 1. / kGammaF));
+ }
+ // to prevent small rounding errors to cause read-overflow:
+ kLinearToGammaTabF[kGammaTabSize + 1] = kLinearToGammaTabF[kGammaTabSize];
+ kGammaTablesFOk = 1;
+ }
+}
+
+static WEBP_INLINE float GammaToLinearF(int v) {
+ return kGammaToLinearTabF[v];
+}
+
+static WEBP_INLINE int LinearToGammaF(float value) {
+ const float v = value * kGammaTabSize;
+ const int tab_pos = (int)v;
+ const float x = v - (float)tab_pos; // fractional part
+ const float v0 = kLinearToGammaTabF[tab_pos + 0];
+ const float v1 = kLinearToGammaTabF[tab_pos + 1];
+ const float y = v1 * x + v0 * (1.f - x); // interpolate
+ return (int)(y + .5);
+}
+
+#else
+
+static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTablesF(void) {}
+static WEBP_INLINE float GammaToLinearF(int v) {
+ const float norm = 1.f / MAX_Y_T;
+ return norm * v;
+}
+static WEBP_INLINE int LinearToGammaF(float value) {
+ return (int)(MAX_Y_T * value + .5);
+}
+
+#endif // USE_GAMMA_COMPRESSION
+
+//------------------------------------------------------------------------------
+
+static uint8_t clip_8b(fixed_t v) {
+ return (!(v & ~0xff)) ? (uint8_t)v : (v < 0) ? 0u : 255u;
+}
+
+static fixed_y_t clip_y(int y) {
+ return (!(y & ~MAX_Y_T)) ? (fixed_y_t)y : (y < 0) ? 0 : MAX_Y_T;
+}
+
+//------------------------------------------------------------------------------
+
+static int RGBToGray(int r, int g, int b) {
+ const int luma = 19595 * r + 38470 * g + 7471 * b + YUV_HALF;
+ return (luma >> YUV_FIX);
+}
+
+static float RGBToGrayF(float r, float g, float b) {
+ return 0.299f * r + 0.587f * g + 0.114f * b;
+}
+
+static int ScaleDown(int a, int b, int c, int d) {
+ const float A = GammaToLinearF(a);
+ const float B = GammaToLinearF(b);
+ const float C = GammaToLinearF(c);
+ const float D = GammaToLinearF(d);
+ return LinearToGammaF(0.25f * (A + B + C + D));
+}
+
+static WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int len) {
+ while (len-- > 0) {
+ const float R = GammaToLinearF(src[0]);
+ const float G = GammaToLinearF(src[1]);
+ const float B = GammaToLinearF(src[2]);
+ const float Y = RGBToGrayF(R, G, B);
+ *dst++ = (fixed_y_t)LinearToGammaF(Y);
+ src += 3;
+ }
+}
+
+static int UpdateChroma(const fixed_y_t* src1,
+ const fixed_y_t* src2,
+ fixed_t* dst, fixed_y_t* tmp, int len) {
+ int diff = 0;
+ while (len--> 0) {
+ const int r = ScaleDown(src1[0], src1[3], src2[0], src2[3]);
+ const int g = ScaleDown(src1[1], src1[4], src2[1], src2[4]);
+ const int b = ScaleDown(src1[2], src1[5], src2[2], src2[5]);
+ const int W = RGBToGray(r, g, b);
+ const int r_avg = (src1[0] + src1[3] + src2[0] + src2[3] + 2) >> 2;
+ const int g_avg = (src1[1] + src1[4] + src2[1] + src2[4] + 2) >> 2;
+ const int b_avg = (src1[2] + src1[5] + src2[2] + src2[5] + 2) >> 2;
+ dst[0] = (fixed_t)(r - W);
+ dst[1] = (fixed_t)(g - W);
+ dst[2] = (fixed_t)(b - W);
+ dst += 3;
+ src1 += 6;
+ src2 += 6;
+ if (tmp != NULL) {
+ tmp[0] = tmp[1] = clip_y(W);
+ tmp += 2;
+ }
+ diff += abs(RGBToGray(r_avg, g_avg, b_avg) - W);
+ }
+ return diff;
+}
+
+//------------------------------------------------------------------------------
+
+static WEBP_INLINE int Filter(const fixed_t* const A, const fixed_t* const B,
+ int rightwise) {
+ int v;
+ if (!rightwise) {
+ v = (A[0] * 9 + A[-3] * 3 + B[0] * 3 + B[-3]);
+ } else {
+ v = (A[0] * 9 + A[+3] * 3 + B[0] * 3 + B[+3]);
+ }
+ return (v + 8) >> 4;
+}
+
+static WEBP_INLINE int Filter2(int A, int B) { return (A * 3 + B + 2) >> 2; }
+
+//------------------------------------------------------------------------------
+
+static WEBP_INLINE fixed_y_t UpLift(uint8_t a) { // 8bit -> SFIX
+ return ((fixed_y_t)a << SFIX) | SHALF;
+}
+
+static void ImportOneRow(const uint8_t* const r_ptr,
+ const uint8_t* const g_ptr,
+ const uint8_t* const b_ptr,
+ int step,
+ int pic_width,
+ fixed_y_t* const dst) {
+ int i;
+ for (i = 0; i < pic_width; ++i) {
+ const int off = i * step;
+ dst[3 * i + 0] = UpLift(r_ptr[off]);
+ dst[3 * i + 1] = UpLift(g_ptr[off]);
+ dst[3 * i + 2] = UpLift(b_ptr[off]);
+ }
+ if (pic_width & 1) { // replicate rightmost pixel
+ memcpy(dst + 3 * pic_width, dst + 3 * (pic_width - 1), 3 * sizeof(*dst));
+ }
+}
+
+static void InterpolateTwoRows(const fixed_y_t* const best_y,
+ const fixed_t* const prev_uv,
+ const fixed_t* const cur_uv,
+ const fixed_t* const next_uv,
+ int w,
+ fixed_y_t* const out1,
+ fixed_y_t* const out2) {
+ int i, k;
+ { // special boundary case for i==0
+ const int W0 = best_y[0];
+ const int W1 = best_y[w];
+ for (k = 0; k <= 2; ++k) {
+ out1[k] = clip_y(Filter2(cur_uv[k], prev_uv[k]) + W0);
+ out2[k] = clip_y(Filter2(cur_uv[k], next_uv[k]) + W1);
+ }
+ }
+ for (i = 1; i < w - 1; ++i) {
+ const int W0 = best_y[i + 0];
+ const int W1 = best_y[i + w];
+ const int off = 3 * (i >> 1);
+ for (k = 0; k <= 2; ++k) {
+ const int tmp0 = Filter(cur_uv + off + k, prev_uv + off + k, i & 1);
+ const int tmp1 = Filter(cur_uv + off + k, next_uv + off + k, i & 1);
+ out1[3 * i + k] = clip_y(tmp0 + W0);
+ out2[3 * i + k] = clip_y(tmp1 + W1);
+ }
+ }
+ { // special boundary case for i == w - 1
+ const int W0 = best_y[i + 0];
+ const int W1 = best_y[i + w];
+ const int off = 3 * (i >> 1);
+ for (k = 0; k <= 2; ++k) {
+ out1[3 * i + k] = clip_y(Filter2(cur_uv[off + k], prev_uv[off + k]) + W0);
+ out2[3 * i + k] = clip_y(Filter2(cur_uv[off + k], next_uv[off + k]) + W1);
+ }
+ }
+}
+
+static WEBP_INLINE uint8_t ConvertRGBToY(int r, int g, int b) {
+ const int luma = 16839 * r + 33059 * g + 6420 * b + SROUNDER;
+ return clip_8b(16 + (luma >> (YUV_FIX + SFIX)));
+}
+
+static WEBP_INLINE uint8_t ConvertRGBToU(int r, int g, int b) {
+ const int u = -9719 * r - 19081 * g + 28800 * b + SROUNDER;
+ return clip_8b(128 + (u >> (YUV_FIX + SFIX)));
+}
+
+static WEBP_INLINE uint8_t ConvertRGBToV(int r, int g, int b) {
+ const int v = +28800 * r - 24116 * g - 4684 * b + SROUNDER;
+ return clip_8b(128 + (v >> (YUV_FIX + SFIX)));
+}
+
+static int ConvertWRGBToYUV(const fixed_y_t* const best_y,
+ const fixed_t* const best_uv,
+ WebPPicture* const picture) {
+ int i, j;
+ const int w = (picture->width + 1) & ~1;
+ const int h = (picture->height + 1) & ~1;
+ const int uv_w = w >> 1;
+ const int uv_h = h >> 1;
+ for (j = 0; j < picture->height; ++j) {
+ for (i = 0; i < picture->width; ++i) {
+ const int off = 3 * ((i >> 1) + (j >> 1) * uv_w);
+ const int off2 = i + j * picture->y_stride;
+ const int W = best_y[i + j * w];
+ const int r = best_uv[off + 0] + W;
+ const int g = best_uv[off + 1] + W;
+ const int b = best_uv[off + 2] + W;
+ picture->y[off2] = ConvertRGBToY(r, g, b);
+ }
+ }
+ for (j = 0; j < uv_h; ++j) {
+ uint8_t* const dst_u = picture->u + j * picture->uv_stride;
+ uint8_t* const dst_v = picture->v + j * picture->uv_stride;
+ for (i = 0; i < uv_w; ++i) {
+ const int off = 3 * (i + j * uv_w);
+ const int r = best_uv[off + 0];
+ const int g = best_uv[off + 1];
+ const int b = best_uv[off + 2];
+ dst_u[i] = ConvertRGBToU(r, g, b);
+ dst_v[i] = ConvertRGBToV(r, g, b);
+ }
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Main function
+
+#define SAFE_ALLOC(W, H, T) ((T*)WebPSafeMalloc((W) * (H), sizeof(T)))
+
+static int PreprocessARGB(const uint8_t* const r_ptr,
+ const uint8_t* const g_ptr,
+ const uint8_t* const b_ptr,
+ int step, int rgb_stride,
+ WebPPicture* const picture) {
+ // we expand the right/bottom border if needed
+ const int w = (picture->width + 1) & ~1;
+ const int h = (picture->height + 1) & ~1;
+ const int uv_w = w >> 1;
+ const int uv_h = h >> 1;
+ int i, j, iter;
+
+ // TODO(skal): allocate one big memory chunk. But for now, it's easier
+ // for valgrind debugging to have several chunks.
+ fixed_y_t* const tmp_buffer = SAFE_ALLOC(w * 3, 2, fixed_y_t); // scratch
+ fixed_y_t* const best_y = SAFE_ALLOC(w, h, fixed_y_t);
+ fixed_y_t* const target_y = SAFE_ALLOC(w, h, fixed_y_t);
+ fixed_y_t* const best_rgb_y = SAFE_ALLOC(w, 2, fixed_y_t);
+ fixed_t* const best_uv = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t);
+ fixed_t* const target_uv = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t);
+ fixed_t* const best_rgb_uv = SAFE_ALLOC(uv_w * 3, 1, fixed_t);
+ int ok;
+ int diff_sum = 0;
+ const int first_diff_threshold = (int)(2.5 * w * h);
+ const int min_improvement = 5; // stop if improvement is below this %
+ const int min_first_improvement = 80;
+
+ if (best_y == NULL || best_uv == NULL ||
+ target_y == NULL || target_uv == NULL ||
+ best_rgb_y == NULL || best_rgb_uv == NULL ||
+ tmp_buffer == NULL) {
+ ok = WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
+ goto End;
+ }
+ assert(picture->width >= kMinDimensionIterativeConversion);
+ assert(picture->height >= kMinDimensionIterativeConversion);
+
+ // Import RGB samples to W/RGB representation.
+ for (j = 0; j < picture->height; j += 2) {
+ const int is_last_row = (j == picture->height - 1);
+ fixed_y_t* const src1 = tmp_buffer;
+ fixed_y_t* const src2 = tmp_buffer + 3 * w;
+ const int off1 = j * rgb_stride;
+ const int off2 = off1 + rgb_stride;
+ const int uv_off = (j >> 1) * 3 * uv_w;
+ fixed_y_t* const dst_y = best_y + j * w;
+
+ // prepare two rows of input
+ ImportOneRow(r_ptr + off1, g_ptr + off1, b_ptr + off1,
+ step, picture->width, src1);
+ if (!is_last_row) {
+ ImportOneRow(r_ptr + off2, g_ptr + off2, b_ptr + off2,
+ step, picture->width, src2);
+ } else {
+ memcpy(src2, src1, 3 * w * sizeof(*src2));
+ }
+ UpdateW(src1, target_y + (j + 0) * w, w);
+ UpdateW(src2, target_y + (j + 1) * w, w);
+ diff_sum += UpdateChroma(src1, src2, target_uv + uv_off, dst_y, uv_w);
+ memcpy(best_uv + uv_off, target_uv + uv_off, 3 * uv_w * sizeof(*best_uv));
+ memcpy(dst_y + w, dst_y, w * sizeof(*dst_y));
+ }
+
+ // Iterate and resolve clipping conflicts.
+ for (iter = 0; iter < kNumIterations; ++iter) {
+ int k;
+ const fixed_t* cur_uv = best_uv;
+ const fixed_t* prev_uv = best_uv;
+ const int old_diff_sum = diff_sum;
+ diff_sum = 0;
+ for (j = 0; j < h; j += 2) {
+ fixed_y_t* const src1 = tmp_buffer;
+ fixed_y_t* const src2 = tmp_buffer + 3 * w;
+ {
+ const fixed_t* const next_uv = cur_uv + ((j < h - 2) ? 3 * uv_w : 0);
+ InterpolateTwoRows(best_y + j * w, prev_uv, cur_uv, next_uv,
+ w, src1, src2);
+ prev_uv = cur_uv;
+ cur_uv = next_uv;
+ }
+
+ UpdateW(src1, best_rgb_y + 0 * w, w);
+ UpdateW(src2, best_rgb_y + 1 * w, w);
+ diff_sum += UpdateChroma(src1, src2, best_rgb_uv, NULL, uv_w);
+
+ // update two rows of Y and one row of RGB
+ for (i = 0; i < 2 * w; ++i) {
+ const int off = i + j * w;
+ const int diff_y = target_y[off] - best_rgb_y[i];
+ const int new_y = (int)best_y[off] + diff_y;
+ best_y[off] = clip_y(new_y);
+ }
+ for (i = 0; i < uv_w; ++i) {
+ const int off = 3 * (i + (j >> 1) * uv_w);
+ int W;
+ for (k = 0; k <= 2; ++k) {
+ const int diff_uv = (int)target_uv[off + k] - best_rgb_uv[3 * i + k];
+ best_uv[off + k] += diff_uv;
+ }
+ W = RGBToGray(best_uv[off + 0], best_uv[off + 1], best_uv[off + 2]);
+ for (k = 0; k <= 2; ++k) {
+ best_uv[off + k] -= W;
+ }
+ }
+ }
+ // test exit condition
+ if (diff_sum > 0) {
+ const int improvement = 100 * abs(diff_sum - old_diff_sum) / diff_sum;
+ // Check if first iteration gave good result already, without a large
+ // jump of improvement (otherwise it means we need to try few extra
+ // iterations, just to be sure).
+ if (iter == 0 && diff_sum < first_diff_threshold &&
+ improvement < min_first_improvement) {
+ break;
+ }
+ // then, check if improvement is stalling.
+ if (improvement < min_improvement) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ // final reconstruction
+ ok = ConvertWRGBToYUV(best_y, best_uv, picture);
+
+ End:
+ WebPSafeFree(best_y);
+ WebPSafeFree(best_uv);
+ WebPSafeFree(target_y);
+ WebPSafeFree(target_uv);
+ WebPSafeFree(best_rgb_y);
+ WebPSafeFree(best_rgb_uv);
+ WebPSafeFree(tmp_buffer);
+ return ok;
+}
+#undef SAFE_ALLOC
+
+//------------------------------------------------------------------------------
+// "Fast" regular RGB->YUV
+
+#define SUM4(ptr, step) LinearToGamma( \
+ GammaToLinear((ptr)[0]) + \
+ GammaToLinear((ptr)[(step)]) + \
+ GammaToLinear((ptr)[rgb_stride]) + \
+ GammaToLinear((ptr)[rgb_stride + (step)]), 0) \
+
+#define SUM2(ptr) \
+ LinearToGamma(GammaToLinear((ptr)[0]) + GammaToLinear((ptr)[rgb_stride]), 1)
+
+#define SUM2ALPHA(ptr) ((ptr)[0] + (ptr)[rgb_stride])
+#define SUM4ALPHA(ptr) (SUM2ALPHA(ptr) + SUM2ALPHA((ptr) + 4))
+
+#if defined(USE_INVERSE_ALPHA_TABLE)
+
+static const int kAlphaFix = 19;
+// Following table is (1 << kAlphaFix) / a. The (v * kInvAlpha[a]) >> kAlphaFix
+// formula is then equal to v / a in most (99.6%) cases. Note that this table
+// and constant are adjusted very tightly to fit 32b arithmetic.
+// In particular, they use the fact that the operands for 'v / a' are actually
+// derived as v = (a0.p0 + a1.p1 + a2.p2 + a3.p3) and a = a0 + a1 + a2 + a3
+// with ai in [0..255] and pi in [0..1<<kGammaFix). The constraint to avoid
+// overflow is: kGammaFix + kAlphaFix <= 31.
+static const uint32_t kInvAlpha[4 * 0xff + 1] = {
+ 0, /* alpha = 0 */
+ 524288, 262144, 174762, 131072, 104857, 87381, 74898, 65536,
+ 58254, 52428, 47662, 43690, 40329, 37449, 34952, 32768,
+ 30840, 29127, 27594, 26214, 24966, 23831, 22795, 21845,
+ 20971, 20164, 19418, 18724, 18078, 17476, 16912, 16384,
+ 15887, 15420, 14979, 14563, 14169, 13797, 13443, 13107,
+ 12787, 12483, 12192, 11915, 11650, 11397, 11155, 10922,
+ 10699, 10485, 10280, 10082, 9892, 9709, 9532, 9362,
+ 9198, 9039, 8886, 8738, 8594, 8456, 8322, 8192,
+ 8065, 7943, 7825, 7710, 7598, 7489, 7384, 7281,
+ 7182, 7084, 6990, 6898, 6808, 6721, 6636, 6553,
+ 6472, 6393, 6316, 6241, 6168, 6096, 6026, 5957,
+ 5890, 5825, 5761, 5698, 5637, 5577, 5518, 5461,
+ 5405, 5349, 5295, 5242, 5190, 5140, 5090, 5041,
+ 4993, 4946, 4899, 4854, 4809, 4766, 4723, 4681,
+ 4639, 4599, 4559, 4519, 4481, 4443, 4405, 4369,
+ 4332, 4297, 4262, 4228, 4194, 4161, 4128, 4096,
+ 4064, 4032, 4002, 3971, 3942, 3912, 3883, 3855,
+ 3826, 3799, 3771, 3744, 3718, 3692, 3666, 3640,
+ 3615, 3591, 3566, 3542, 3518, 3495, 3472, 3449,
+ 3426, 3404, 3382, 3360, 3339, 3318, 3297, 3276,
+ 3256, 3236, 3216, 3196, 3177, 3158, 3139, 3120,
+ 3102, 3084, 3066, 3048, 3030, 3013, 2995, 2978,
+ 2962, 2945, 2928, 2912, 2896, 2880, 2864, 2849,
+ 2833, 2818, 2803, 2788, 2774, 2759, 2744, 2730,
+ 2716, 2702, 2688, 2674, 2661, 2647, 2634, 2621,
+ 2608, 2595, 2582, 2570, 2557, 2545, 2532, 2520,
+ 2508, 2496, 2484, 2473, 2461, 2449, 2438, 2427,
+ 2416, 2404, 2394, 2383, 2372, 2361, 2351, 2340,
+ 2330, 2319, 2309, 2299, 2289, 2279, 2269, 2259,
+ 2250, 2240, 2231, 2221, 2212, 2202, 2193, 2184,
+ 2175, 2166, 2157, 2148, 2139, 2131, 2122, 2114,
+ 2105, 2097, 2088, 2080, 2072, 2064, 2056, 2048,
+ 2040, 2032, 2024, 2016, 2008, 2001, 1993, 1985,
+ 1978, 1971, 1963, 1956, 1949, 1941, 1934, 1927,
+ 1920, 1913, 1906, 1899, 1892, 1885, 1879, 1872,
+ 1865, 1859, 1852, 1846, 1839, 1833, 1826, 1820,
+ 1814, 1807, 1801, 1795, 1789, 1783, 1777, 1771,
+ 1765, 1759, 1753, 1747, 1741, 1736, 1730, 1724,
+ 1718, 1713, 1707, 1702, 1696, 1691, 1685, 1680,
+ 1675, 1669, 1664, 1659, 1653, 1648, 1643, 1638,
+ 1633, 1628, 1623, 1618, 1613, 1608, 1603, 1598,
+ 1593, 1588, 1583, 1579, 1574, 1569, 1565, 1560,
+ 1555, 1551, 1546, 1542, 1537, 1533, 1528, 1524,
+ 1519, 1515, 1510, 1506, 1502, 1497, 1493, 1489,
+ 1485, 1481, 1476, 1472, 1468, 1464, 1460, 1456,
+ 1452, 1448, 1444, 1440, 1436, 1432, 1428, 1424,
+ 1420, 1416, 1413, 1409, 1405, 1401, 1398, 1394,
+ 1390, 1387, 1383, 1379, 1376, 1372, 1368, 1365,
+ 1361, 1358, 1354, 1351, 1347, 1344, 1340, 1337,
+ 1334, 1330, 1327, 1323, 1320, 1317, 1314, 1310,
+ 1307, 1304, 1300, 1297, 1294, 1291, 1288, 1285,
+ 1281, 1278, 1275, 1272, 1269, 1266, 1263, 1260,
+ 1257, 1254, 1251, 1248, 1245, 1242, 1239, 1236,
+ 1233, 1230, 1227, 1224, 1222, 1219, 1216, 1213,
+ 1210, 1208, 1205, 1202, 1199, 1197, 1194, 1191,
+ 1188, 1186, 1183, 1180, 1178, 1175, 1172, 1170,
+ 1167, 1165, 1162, 1159, 1157, 1154, 1152, 1149,
+ 1147, 1144, 1142, 1139, 1137, 1134, 1132, 1129,
+ 1127, 1125, 1122, 1120, 1117, 1115, 1113, 1110,
+ 1108, 1106, 1103, 1101, 1099, 1096, 1094, 1092,
+ 1089, 1087, 1085, 1083, 1081, 1078, 1076, 1074,
+ 1072, 1069, 1067, 1065, 1063, 1061, 1059, 1057,
+ 1054, 1052, 1050, 1048, 1046, 1044, 1042, 1040,
+ 1038, 1036, 1034, 1032, 1030, 1028, 1026, 1024,
+ 1022, 1020, 1018, 1016, 1014, 1012, 1010, 1008,
+ 1006, 1004, 1002, 1000, 998, 996, 994, 992,
+ 991, 989, 987, 985, 983, 981, 979, 978,
+ 976, 974, 972, 970, 969, 967, 965, 963,
+ 961, 960, 958, 956, 954, 953, 951, 949,
+ 948, 946, 944, 942, 941, 939, 937, 936,
+ 934, 932, 931, 929, 927, 926, 924, 923,
+ 921, 919, 918, 916, 914, 913, 911, 910,
+ 908, 907, 905, 903, 902, 900, 899, 897,
+ 896, 894, 893, 891, 890, 888, 887, 885,
+ 884, 882, 881, 879, 878, 876, 875, 873,
+ 872, 870, 869, 868, 866, 865, 863, 862,
+ 860, 859, 858, 856, 855, 853, 852, 851,
+ 849, 848, 846, 845, 844, 842, 841, 840,
+ 838, 837, 836, 834, 833, 832, 830, 829,
+ 828, 826, 825, 824, 823, 821, 820, 819,
+ 817, 816, 815, 814, 812, 811, 810, 809,
+ 807, 806, 805, 804, 802, 801, 800, 799,
+ 798, 796, 795, 794, 793, 791, 790, 789,
+ 788, 787, 786, 784, 783, 782, 781, 780,
+ 779, 777, 776, 775, 774, 773, 772, 771,
+ 769, 768, 767, 766, 765, 764, 763, 762,
+ 760, 759, 758, 757, 756, 755, 754, 753,
+ 752, 751, 750, 748, 747, 746, 745, 744,
+ 743, 742, 741, 740, 739, 738, 737, 736,
+ 735, 734, 733, 732, 731, 730, 729, 728,
+ 727, 726, 725, 724, 723, 722, 721, 720,
+ 719, 718, 717, 716, 715, 714, 713, 712,
+ 711, 710, 709, 708, 707, 706, 705, 704,
+ 703, 702, 701, 700, 699, 699, 698, 697,
+ 696, 695, 694, 693, 692, 691, 690, 689,
+ 688, 688, 687, 686, 685, 684, 683, 682,
+ 681, 680, 680, 679, 678, 677, 676, 675,
+ 674, 673, 673, 672, 671, 670, 669, 668,
+ 667, 667, 666, 665, 664, 663, 662, 661,
+ 661, 660, 659, 658, 657, 657, 656, 655,
+ 654, 653, 652, 652, 651, 650, 649, 648,
+ 648, 647, 646, 645, 644, 644, 643, 642,
+ 641, 640, 640, 639, 638, 637, 637, 636,
+ 635, 634, 633, 633, 632, 631, 630, 630,
+ 629, 628, 627, 627, 626, 625, 624, 624,
+ 623, 622, 621, 621, 620, 619, 618, 618,
+ 617, 616, 616, 615, 614, 613, 613, 612,
+ 611, 611, 610, 609, 608, 608, 607, 606,
+ 606, 605, 604, 604, 603, 602, 601, 601,
+ 600, 599, 599, 598, 597, 597, 596, 595,
+ 595, 594, 593, 593, 592, 591, 591, 590,
+ 589, 589, 588, 587, 587, 586, 585, 585,
+ 584, 583, 583, 582, 581, 581, 580, 579,
+ 579, 578, 578, 577, 576, 576, 575, 574,
+ 574, 573, 572, 572, 571, 571, 570, 569,
+ 569, 568, 568, 567, 566, 566, 565, 564,
+ 564, 563, 563, 562, 561, 561, 560, 560,
+ 559, 558, 558, 557, 557, 556, 555, 555,
+ 554, 554, 553, 553, 552, 551, 551, 550,
+ 550, 549, 548, 548, 547, 547, 546, 546,
+ 545, 544, 544, 543, 543, 542, 542, 541,
+ 541, 540, 539, 539, 538, 538, 537, 537,
+ 536, 536, 535, 534, 534, 533, 533, 532,
+ 532, 531, 531, 530, 530, 529, 529, 528,
+ 527, 527, 526, 526, 525, 525, 524, 524,
+ 523, 523, 522, 522, 521, 521, 520, 520,
+ 519, 519, 518, 518, 517, 517, 516, 516,
+ 515, 515, 514, 514
+};
+
+// Note that LinearToGamma() expects the values to be premultiplied by 4,
+// so we incorporate this factor 4 inside the DIVIDE_BY_ALPHA macro directly.
+#define DIVIDE_BY_ALPHA(sum, a) (((sum) * kInvAlpha[(a)]) >> (kAlphaFix - 2))
+
+#else
+
+#define DIVIDE_BY_ALPHA(sum, a) (4 * (sum) / (a))
+
+#endif // USE_INVERSE_ALPHA_TABLE
+
+static WEBP_INLINE int LinearToGammaWeighted(const uint8_t* src,
+ const uint8_t* a_ptr,
+ uint32_t total_a, int step,
+ int rgb_stride) {
+ const uint32_t sum =
+ a_ptr[0] * GammaToLinear(src[0]) +
+ a_ptr[step] * GammaToLinear(src[step]) +
+ a_ptr[rgb_stride] * GammaToLinear(src[rgb_stride]) +
+ a_ptr[rgb_stride + step] * GammaToLinear(src[rgb_stride + step]);
+ assert(total_a > 0 && total_a <= 4 * 0xff);
+#if defined(USE_INVERSE_ALPHA_TABLE)
+ assert((uint64_t)sum * kInvAlpha[total_a] < ((uint64_t)1 << 32));
+#endif
+ return LinearToGamma(DIVIDE_BY_ALPHA(sum, total_a), 0);
+}
+
+static WEBP_INLINE void ConvertRowToY(const uint8_t* const r_ptr,
+ const uint8_t* const g_ptr,
+ const uint8_t* const b_ptr,
+ int step,
+ uint8_t* const dst_y,
+ int width,
+ VP8Random* const rg) {
+ int i, j;
+ for (i = 0, j = 0; i < width; i += 1, j += step) {
+ dst_y[i] = RGBToY(r_ptr[j], g_ptr[j], b_ptr[j], rg);
+ }
+}
+
+static WEBP_INLINE void AccumulateRGBA(const uint8_t* const r_ptr,
+ const uint8_t* const g_ptr,
+ const uint8_t* const b_ptr,
+ const uint8_t* const a_ptr,
+ int rgb_stride,
+ uint16_t* dst, int width) {
+ int i, j;
+ // we loop over 2x2 blocks and produce one R/G/B/A value for each.
+ for (i = 0, j = 0; i < (width >> 1); i += 1, j += 2 * 4, dst += 4) {
+ const uint32_t a = SUM4ALPHA(a_ptr + j);
+ int r, g, b;
+ if (a == 4 * 0xff || a == 0) {
+ r = SUM4(r_ptr + j, 4);
+ g = SUM4(g_ptr + j, 4);
+ b = SUM4(b_ptr + j, 4);
+ } else {
+ r = LinearToGammaWeighted(r_ptr + j, a_ptr + j, a, 4, rgb_stride);
+ g = LinearToGammaWeighted(g_ptr + j, a_ptr + j, a, 4, rgb_stride);
+ b = LinearToGammaWeighted(b_ptr + j, a_ptr + j, a, 4, rgb_stride);
+ }
+ dst[0] = r;
+ dst[1] = g;
+ dst[2] = b;
+ dst[3] = a;
+ }
+ if (width & 1) {
+ const uint32_t a = 2u * SUM2ALPHA(a_ptr + j);
+ int r, g, b;
+ if (a == 4 * 0xff || a == 0) {
+ r = SUM2(r_ptr + j);
+ g = SUM2(g_ptr + j);
+ b = SUM2(b_ptr + j);
+ } else {
+ r = LinearToGammaWeighted(r_ptr + j, a_ptr + j, a, 0, rgb_stride);
+ g = LinearToGammaWeighted(g_ptr + j, a_ptr + j, a, 0, rgb_stride);
+ b = LinearToGammaWeighted(b_ptr + j, a_ptr + j, a, 0, rgb_stride);
+ }
+ dst[0] = r;
+ dst[1] = g;
+ dst[2] = b;
+ dst[3] = a;
+ }
+}
+
+static WEBP_INLINE void AccumulateRGB(const uint8_t* const r_ptr,
+ const uint8_t* const g_ptr,
+ const uint8_t* const b_ptr,
+ int step, int rgb_stride,
+ uint16_t* dst, int width) {
+ int i, j;
+ for (i = 0, j = 0; i < (width >> 1); i += 1, j += 2 * step, dst += 4) {
+ dst[0] = SUM4(r_ptr + j, step);
+ dst[1] = SUM4(g_ptr + j, step);
+ dst[2] = SUM4(b_ptr + j, step);
+ }
+ if (width & 1) {
+ dst[0] = SUM2(r_ptr + j);
+ dst[1] = SUM2(g_ptr + j);
+ dst[2] = SUM2(b_ptr + j);
+ }
+}
+
+static WEBP_INLINE void ConvertRowsToUV(const uint16_t* rgb,
+ uint8_t* const dst_u,
+ uint8_t* const dst_v,
+ int width,
+ VP8Random* const rg) {
+ int i;
+ for (i = 0; i < width; i += 1, rgb += 4) {
+ const int r = rgb[0], g = rgb[1], b = rgb[2];
+ dst_u[i] = RGBToU(r, g, b, rg);
+ dst_v[i] = RGBToV(r, g, b, rg);
+ }
+}
+
+static int ImportYUVAFromRGBA(const uint8_t* const r_ptr,
+ const uint8_t* const g_ptr,
+ const uint8_t* const b_ptr,
+ const uint8_t* const a_ptr,
+ int step, // bytes per pixel
+ int rgb_stride, // bytes per scanline
+ float dithering,
+ int use_iterative_conversion,
+ WebPPicture* const picture) {
+ int y;
+ const int width = picture->width;
+ const int height = picture->height;
+ const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride);
+ const int is_rgb = (r_ptr < b_ptr); // otherwise it's bgr
+
+ picture->colorspace = has_alpha ? WEBP_YUV420A : WEBP_YUV420;
+ picture->use_argb = 0;
+
+ // disable smart conversion if source is too small (overkill).
+ if (width < kMinDimensionIterativeConversion ||
+ height < kMinDimensionIterativeConversion) {
+ use_iterative_conversion = 0;
+ }
+
+ if (!WebPPictureAllocYUVA(picture, width, height)) {
+ return 0;
+ }
+ if (has_alpha) {
+ WebPInitAlphaProcessing();
+ assert(step == 4);
+#if defined(USE_GAMMA_COMPRESSION) && defined(USE_INVERSE_ALPHA_TABLE)
+ assert(kAlphaFix + kGammaFix <= 31);
+#endif
+ }
+
+ if (use_iterative_conversion) {
+ InitGammaTablesF();
+ if (!PreprocessARGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, picture)) {
+ return 0;
+ }
+ if (has_alpha) {
+ WebPExtractAlpha(a_ptr, rgb_stride, width, height,
+ picture->a, picture->a_stride);
+ }
+ } else {
+ const int uv_width = (width + 1) >> 1;
+ int use_dsp = (step == 3); // use special function in this case
+ // temporary storage for accumulated R/G/B values during conversion to U/V
+ uint16_t* const tmp_rgb =
+ (uint16_t*)WebPSafeMalloc(4 * uv_width, sizeof(*tmp_rgb));
+ uint8_t* dst_y = picture->y;
+ uint8_t* dst_u = picture->u;
+ uint8_t* dst_v = picture->v;
+ uint8_t* dst_a = picture->a;
+
+ VP8Random base_rg;
+ VP8Random* rg = NULL;
+ if (dithering > 0.) {
+ VP8InitRandom(&base_rg, dithering);
+ rg = &base_rg;
+ use_dsp = 0; // can't use dsp in this case
+ }
+ WebPInitConvertARGBToYUV();
+ InitGammaTables();
+
+ if (tmp_rgb == NULL) return 0; // malloc error
+
+ // Downsample Y/U/V planes, two rows at a time
+ for (y = 0; y < (height >> 1); ++y) {
+ int rows_have_alpha = has_alpha;
+ const int off1 = (2 * y + 0) * rgb_stride;
+ const int off2 = (2 * y + 1) * rgb_stride;
+ if (use_dsp) {
+ if (is_rgb) {
+ WebPConvertRGB24ToY(r_ptr + off1, dst_y, width);
+ WebPConvertRGB24ToY(r_ptr + off2, dst_y + picture->y_stride, width);
+ } else {
+ WebPConvertBGR24ToY(b_ptr + off1, dst_y, width);
+ WebPConvertBGR24ToY(b_ptr + off2, dst_y + picture->y_stride, width);
+ }
+ } else {
+ ConvertRowToY(r_ptr + off1, g_ptr + off1, b_ptr + off1, step,
+ dst_y, width, rg);
+ ConvertRowToY(r_ptr + off2, g_ptr + off2, b_ptr + off2, step,
+ dst_y + picture->y_stride, width, rg);
+ }
+ dst_y += 2 * picture->y_stride;
+ if (has_alpha) {
+ rows_have_alpha &= !WebPExtractAlpha(a_ptr + off1, rgb_stride,
+ width, 2,
+ dst_a, picture->a_stride);
+ dst_a += 2 * picture->a_stride;
+ }
+ // Collect averaged R/G/B(/A)
+ if (!rows_have_alpha) {
+ AccumulateRGB(r_ptr + off1, g_ptr + off1, b_ptr + off1,
+ step, rgb_stride, tmp_rgb, width);
+ } else {
+ AccumulateRGBA(r_ptr + off1, g_ptr + off1, b_ptr + off1, a_ptr + off1,
+ rgb_stride, tmp_rgb, width);
+ }
+ // Convert to U/V
+ if (rg == NULL) {
+ WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width);
+ } else {
+ ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg);
+ }
+ dst_u += picture->uv_stride;
+ dst_v += picture->uv_stride;
+ }
+ if (height & 1) { // extra last row
+ const int off = 2 * y * rgb_stride;
+ int row_has_alpha = has_alpha;
+ if (use_dsp) {
+ if (r_ptr < b_ptr) {
+ WebPConvertRGB24ToY(r_ptr + off, dst_y, width);
+ } else {
+ WebPConvertBGR24ToY(b_ptr + off, dst_y, width);
+ }
+ } else {
+ ConvertRowToY(r_ptr + off, g_ptr + off, b_ptr + off, step,
+ dst_y, width, rg);
+ }
+ if (row_has_alpha) {
+ row_has_alpha &= !WebPExtractAlpha(a_ptr + off, 0, width, 1, dst_a, 0);
+ }
+ // Collect averaged R/G/B(/A)
+ if (!row_has_alpha) {
+ // Collect averaged R/G/B
+ AccumulateRGB(r_ptr + off, g_ptr + off, b_ptr + off,
+ step, /* rgb_stride = */ 0, tmp_rgb, width);
+ } else {
+ AccumulateRGBA(r_ptr + off, g_ptr + off, b_ptr + off, a_ptr + off,
+ /* rgb_stride = */ 0, tmp_rgb, width);
+ }
+ if (rg == NULL) {
+ WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width);
+ } else {
+ ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg);
+ }
+ }
+ WebPSafeFree(tmp_rgb);
+ }
+ return 1;
+}
+
+#undef SUM4
+#undef SUM2
+#undef SUM4ALPHA
+#undef SUM2ALPHA
+
+//------------------------------------------------------------------------------
+// call for ARGB->YUVA conversion
+
+static int PictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace,
+ float dithering, int use_iterative_conversion) {
+ if (picture == NULL) return 0;
+ if (picture->argb == NULL) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
+ } else if ((colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
+ } else {
+ const uint8_t* const argb = (const uint8_t*)picture->argb;
+ const uint8_t* const r = ALPHA_IS_LAST ? argb + 2 : argb + 1;
+ const uint8_t* const g = ALPHA_IS_LAST ? argb + 1 : argb + 2;
+ const uint8_t* const b = ALPHA_IS_LAST ? argb + 0 : argb + 3;
+ const uint8_t* const a = ALPHA_IS_LAST ? argb + 3 : argb + 0;
+
+ picture->colorspace = WEBP_YUV420;
+ return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride,
+ dithering, use_iterative_conversion, picture);
+ }
+}
+
+int WebPPictureARGBToYUVADithered(WebPPicture* picture, WebPEncCSP colorspace,
+ float dithering) {
+ return PictureARGBToYUVA(picture, colorspace, dithering, 0);
+}
+
+int WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) {
+ return PictureARGBToYUVA(picture, colorspace, 0.f, 0);
+}
+
+int WebPPictureSmartARGBToYUVA(WebPPicture* picture) {
+ return PictureARGBToYUVA(picture, WEBP_YUV420, 0.f, 1);
+}
+
+//------------------------------------------------------------------------------
+// call for YUVA -> ARGB conversion
+
+int WebPPictureYUVAToARGB(WebPPicture* picture) {
+ if (picture == NULL) return 0;
+ if (picture->y == NULL || picture->u == NULL || picture->v == NULL) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
+ }
+ if ((picture->colorspace & WEBP_CSP_ALPHA_BIT) && picture->a == NULL) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
+ }
+ if ((picture->colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
+ }
+ // Allocate a new argb buffer (discarding the previous one).
+ if (!WebPPictureAllocARGB(picture, picture->width, picture->height)) return 0;
+ picture->use_argb = 1;
+
+ // Convert
+ {
+ int y;
+ const int width = picture->width;
+ const int height = picture->height;
+ const int argb_stride = 4 * picture->argb_stride;
+ uint8_t* dst = (uint8_t*)picture->argb;
+ const uint8_t *cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y;
+ WebPUpsampleLinePairFunc upsample = WebPGetLinePairConverter(ALPHA_IS_LAST);
+
+ // First row, with replicated top samples.
+ upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width);
+ cur_y += picture->y_stride;
+ dst += argb_stride;
+ // Center rows.
+ for (y = 1; y + 1 < height; y += 2) {
+ const uint8_t* const top_u = cur_u;
+ const uint8_t* const top_v = cur_v;
+ cur_u += picture->uv_stride;
+ cur_v += picture->uv_stride;
+ upsample(cur_y, cur_y + picture->y_stride, top_u, top_v, cur_u, cur_v,
+ dst, dst + argb_stride, width);
+ cur_y += 2 * picture->y_stride;
+ dst += 2 * argb_stride;
+ }
+ // Last row (if needed), with replicated bottom samples.
+ if (height > 1 && !(height & 1)) {
+ upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width);
+ }
+ // Insert alpha values if needed, in replacement for the default 0xff ones.
+ if (picture->colorspace & WEBP_CSP_ALPHA_BIT) {
+ for (y = 0; y < height; ++y) {
+ uint32_t* const argb_dst = picture->argb + y * picture->argb_stride;
+ const uint8_t* const src = picture->a + y * picture->a_stride;
+ int x;
+ for (x = 0; x < width; ++x) {
+ argb_dst[x] = (argb_dst[x] & 0x00ffffffu) | ((uint32_t)src[x] << 24);
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// automatic import / conversion
+
+static int Import(WebPPicture* const picture,
+ const uint8_t* const rgb, int rgb_stride,
+ int step, int swap_rb, int import_alpha) {
+ int y;
+ const uint8_t* const r_ptr = rgb + (swap_rb ? 2 : 0);
+ const uint8_t* const g_ptr = rgb + 1;
+ const uint8_t* const b_ptr = rgb + (swap_rb ? 0 : 2);
+ const uint8_t* const a_ptr = import_alpha ? rgb + 3 : NULL;
+ const int width = picture->width;
+ const int height = picture->height;
+
+ if (!picture->use_argb) {
+ return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride,
+ 0.f /* no dithering */, 0, picture);
+ }
+ if (!WebPPictureAlloc(picture)) return 0;
+
+ VP8EncDspARGBInit();
+
+ if (import_alpha) {
+ assert(step == 4);
+ for (y = 0; y < height; ++y) {
+ uint32_t* const dst = &picture->argb[y * picture->argb_stride];
+ const int offset = y * rgb_stride;
+ VP8PackARGB(a_ptr + offset, r_ptr + offset, g_ptr + offset,
+ b_ptr + offset, width, dst);
+ }
+ } else {
+ assert(step >= 3);
+ for (y = 0; y < height; ++y) {
+ uint32_t* const dst = &picture->argb[y * picture->argb_stride];
+ const int offset = y * rgb_stride;
+ VP8PackRGB(r_ptr + offset, g_ptr + offset, b_ptr + offset,
+ width, step, dst);
+ }
+ }
+ return 1;
+}
+
+// Public API
+
+int WebPPictureImportRGB(WebPPicture* picture,
+ const uint8_t* rgb, int rgb_stride) {
+ return (picture != NULL) ? Import(picture, rgb, rgb_stride, 3, 0, 0) : 0;
+}
+
+int WebPPictureImportBGR(WebPPicture* picture,
+ const uint8_t* rgb, int rgb_stride) {
+ return (picture != NULL) ? Import(picture, rgb, rgb_stride, 3, 1, 0) : 0;
+}
+
+int WebPPictureImportRGBA(WebPPicture* picture,
+ const uint8_t* rgba, int rgba_stride) {
+ return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 0, 1) : 0;
+}
+
+int WebPPictureImportBGRA(WebPPicture* picture,
+ const uint8_t* rgba, int rgba_stride) {
+ return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 1, 1) : 0;
+}
+
+int WebPPictureImportRGBX(WebPPicture* picture,
+ const uint8_t* rgba, int rgba_stride) {
+ return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 0, 0) : 0;
+}
+
+int WebPPictureImportBGRX(WebPPicture* picture,
+ const uint8_t* rgba, int rgba_stride) {
+ return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 1, 0) : 0;
+}
+
+//------------------------------------------------------------------------------
diff --git a/drivers/webp/enc/picture_psnr.c b/drivers/webp/enc/picture_psnr.c
new file mode 100644
index 0000000000..40214efc95
--- /dev/null
+++ b/drivers/webp/enc/picture_psnr.c
@@ -0,0 +1,175 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// WebPPicture tools for measuring distortion
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "./vp8enci.h"
+#include "../utils/utils.h"
+
+//------------------------------------------------------------------------------
+// local-min distortion
+//
+// For every pixel in the *reference* picture, we search for the local best
+// match in the compressed image. This is not a symmetrical measure.
+
+#define RADIUS 2 // search radius. Shouldn't be too large.
+
+static void AccumulateLSIM(const uint8_t* src, int src_stride,
+ const uint8_t* ref, int ref_stride,
+ int w, int h, DistoStats* stats) {
+ int x, y;
+ double total_sse = 0.;
+ for (y = 0; y < h; ++y) {
+ const int y_0 = (y - RADIUS < 0) ? 0 : y - RADIUS;
+ const int y_1 = (y + RADIUS + 1 >= h) ? h : y + RADIUS + 1;
+ for (x = 0; x < w; ++x) {
+ const int x_0 = (x - RADIUS < 0) ? 0 : x - RADIUS;
+ const int x_1 = (x + RADIUS + 1 >= w) ? w : x + RADIUS + 1;
+ double best_sse = 255. * 255.;
+ const double value = (double)ref[y * ref_stride + x];
+ int i, j;
+ for (j = y_0; j < y_1; ++j) {
+ const uint8_t* const s = src + j * src_stride;
+ for (i = x_0; i < x_1; ++i) {
+ const double diff = s[i] - value;
+ const double sse = diff * diff;
+ if (sse < best_sse) best_sse = sse;
+ }
+ }
+ total_sse += best_sse;
+ }
+ }
+ stats->w = w * h;
+ stats->xm = 0;
+ stats->ym = 0;
+ stats->xxm = total_sse;
+ stats->yym = 0;
+ stats->xxm = 0;
+}
+#undef RADIUS
+
+//------------------------------------------------------------------------------
+// Distortion
+
+// Max value returned in case of exact similarity.
+static const double kMinDistortion_dB = 99.;
+static float GetPSNR(const double v) {
+ return (float)((v > 0.) ? -4.3429448 * log(v / (255 * 255.))
+ : kMinDistortion_dB);
+}
+
+int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref,
+ int type, float result[5]) {
+ DistoStats stats[5];
+ int w, h;
+
+ memset(stats, 0, sizeof(stats));
+
+ if (src == NULL || ref == NULL ||
+ src->width != ref->width || src->height != ref->height ||
+ src->use_argb != ref->use_argb || result == NULL) {
+ return 0;
+ }
+ w = src->width;
+ h = src->height;
+
+ if (src->use_argb == 1) {
+ if (src->argb == NULL || ref->argb == NULL) {
+ return 0;
+ } else {
+ int i, j, c;
+ uint8_t* tmp1, *tmp2;
+ uint8_t* const tmp_plane =
+ (uint8_t*)WebPSafeMalloc(2ULL * w * h, sizeof(*tmp_plane));
+ if (tmp_plane == NULL) return 0;
+ tmp1 = tmp_plane;
+ tmp2 = tmp_plane + w * h;
+ for (c = 0; c < 4; ++c) {
+ for (j = 0; j < h; ++j) {
+ for (i = 0; i < w; ++i) {
+ tmp1[j * w + i] = src->argb[i + j * src->argb_stride] >> (c * 8);
+ tmp2[j * w + i] = ref->argb[i + j * ref->argb_stride] >> (c * 8);
+ }
+ }
+ if (type >= 2) {
+ AccumulateLSIM(tmp1, w, tmp2, w, w, h, &stats[c]);
+ } else {
+ VP8SSIMAccumulatePlane(tmp1, w, tmp2, w, w, h, &stats[c]);
+ }
+ }
+ free(tmp_plane);
+ }
+ } else {
+ int has_alpha, uv_w, uv_h;
+ if (src->y == NULL || ref->y == NULL ||
+ src->u == NULL || ref->u == NULL ||
+ src->v == NULL || ref->v == NULL) {
+ return 0;
+ }
+ has_alpha = !!(src->colorspace & WEBP_CSP_ALPHA_BIT);
+ if (has_alpha != !!(ref->colorspace & WEBP_CSP_ALPHA_BIT) ||
+ (has_alpha && (src->a == NULL || ref->a == NULL))) {
+ return 0;
+ }
+
+ uv_w = (src->width + 1) >> 1;
+ uv_h = (src->height + 1) >> 1;
+ if (type >= 2) {
+ AccumulateLSIM(src->y, src->y_stride, ref->y, ref->y_stride,
+ w, h, &stats[0]);
+ AccumulateLSIM(src->u, src->uv_stride, ref->u, ref->uv_stride,
+ uv_w, uv_h, &stats[1]);
+ AccumulateLSIM(src->v, src->uv_stride, ref->v, ref->uv_stride,
+ uv_w, uv_h, &stats[2]);
+ if (has_alpha) {
+ AccumulateLSIM(src->a, src->a_stride, ref->a, ref->a_stride,
+ w, h, &stats[3]);
+ }
+ } else {
+ VP8SSIMAccumulatePlane(src->y, src->y_stride,
+ ref->y, ref->y_stride,
+ w, h, &stats[0]);
+ VP8SSIMAccumulatePlane(src->u, src->uv_stride,
+ ref->u, ref->uv_stride,
+ uv_w, uv_h, &stats[1]);
+ VP8SSIMAccumulatePlane(src->v, src->uv_stride,
+ ref->v, ref->uv_stride,
+ uv_w, uv_h, &stats[2]);
+ if (has_alpha) {
+ VP8SSIMAccumulatePlane(src->a, src->a_stride,
+ ref->a, ref->a_stride,
+ w, h, &stats[3]);
+ }
+ }
+ }
+ // Final stat calculations.
+ {
+ int c;
+ for (c = 0; c <= 4; ++c) {
+ if (type == 1) {
+ const double v = VP8SSIMGet(&stats[c]);
+ result[c] = (float)((v < 1.) ? -10.0 * log10(1. - v)
+ : kMinDistortion_dB);
+ } else {
+ const double v = VP8SSIMGetSquaredError(&stats[c]);
+ result[c] = GetPSNR(v);
+ }
+ // Accumulate forward
+ if (c < 4) VP8SSIMAddStats(&stats[c], &stats[4]);
+ }
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
diff --git a/drivers/webp/enc/picture_rescale.c b/drivers/webp/enc/picture_rescale.c
new file mode 100644
index 0000000000..9f19e8e80f
--- /dev/null
+++ b/drivers/webp/enc/picture_rescale.c
@@ -0,0 +1,264 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// WebPPicture tools: copy, crop, rescaling and view.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "./vp8enci.h"
+#include "../utils/rescaler.h"
+#include "../utils/utils.h"
+
+#define HALVE(x) (((x) + 1) >> 1)
+
+// Grab the 'specs' (writer, *opaque, width, height...) from 'src' and copy them
+// into 'dst'. Mark 'dst' as not owning any memory.
+static void PictureGrabSpecs(const WebPPicture* const src,
+ WebPPicture* const dst) {
+ assert(src != NULL && dst != NULL);
+ *dst = *src;
+ WebPPictureResetBuffers(dst);
+}
+
+//------------------------------------------------------------------------------
+
+// Adjust top-left corner to chroma sample position.
+static void SnapTopLeftPosition(const WebPPicture* const pic,
+ int* const left, int* const top) {
+ if (!pic->use_argb) {
+ *left &= ~1;
+ *top &= ~1;
+ }
+}
+
+// Adjust top-left corner and verify that the sub-rectangle is valid.
+static int AdjustAndCheckRectangle(const WebPPicture* const pic,
+ int* const left, int* const top,
+ int width, int height) {
+ SnapTopLeftPosition(pic, left, top);
+ if ((*left) < 0 || (*top) < 0) return 0;
+ if (width <= 0 || height <= 0) return 0;
+ if ((*left) + width > pic->width) return 0;
+ if ((*top) + height > pic->height) return 0;
+ return 1;
+}
+
+int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst) {
+ if (src == NULL || dst == NULL) return 0;
+ if (src == dst) return 1;
+
+ PictureGrabSpecs(src, dst);
+ if (!WebPPictureAlloc(dst)) return 0;
+
+ if (!src->use_argb) {
+ WebPCopyPlane(src->y, src->y_stride,
+ dst->y, dst->y_stride, dst->width, dst->height);
+ WebPCopyPlane(src->u, src->uv_stride, dst->u, dst->uv_stride,
+ HALVE(dst->width), HALVE(dst->height));
+ WebPCopyPlane(src->v, src->uv_stride, dst->v, dst->uv_stride,
+ HALVE(dst->width), HALVE(dst->height));
+ if (dst->a != NULL) {
+ WebPCopyPlane(src->a, src->a_stride,
+ dst->a, dst->a_stride, dst->width, dst->height);
+ }
+ } else {
+ WebPCopyPlane((const uint8_t*)src->argb, 4 * src->argb_stride,
+ (uint8_t*)dst->argb, 4 * dst->argb_stride,
+ 4 * dst->width, dst->height);
+ }
+ return 1;
+}
+
+int WebPPictureIsView(const WebPPicture* picture) {
+ if (picture == NULL) return 0;
+ if (picture->use_argb) {
+ return (picture->memory_argb_ == NULL);
+ }
+ return (picture->memory_ == NULL);
+}
+
+int WebPPictureView(const WebPPicture* src,
+ int left, int top, int width, int height,
+ WebPPicture* dst) {
+ if (src == NULL || dst == NULL) return 0;
+
+ // verify rectangle position.
+ if (!AdjustAndCheckRectangle(src, &left, &top, width, height)) return 0;
+
+ if (src != dst) { // beware of aliasing! We don't want to leak 'memory_'.
+ PictureGrabSpecs(src, dst);
+ }
+ dst->width = width;
+ dst->height = height;
+ if (!src->use_argb) {
+ dst->y = src->y + top * src->y_stride + left;
+ dst->u = src->u + (top >> 1) * src->uv_stride + (left >> 1);
+ dst->v = src->v + (top >> 1) * src->uv_stride + (left >> 1);
+ dst->y_stride = src->y_stride;
+ dst->uv_stride = src->uv_stride;
+ if (src->a != NULL) {
+ dst->a = src->a + top * src->a_stride + left;
+ dst->a_stride = src->a_stride;
+ }
+ } else {
+ dst->argb = src->argb + top * src->argb_stride + left;
+ dst->argb_stride = src->argb_stride;
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Picture cropping
+
+int WebPPictureCrop(WebPPicture* pic,
+ int left, int top, int width, int height) {
+ WebPPicture tmp;
+
+ if (pic == NULL) return 0;
+ if (!AdjustAndCheckRectangle(pic, &left, &top, width, height)) return 0;
+
+ PictureGrabSpecs(pic, &tmp);
+ tmp.width = width;
+ tmp.height = height;
+ if (!WebPPictureAlloc(&tmp)) return 0;
+
+ if (!pic->use_argb) {
+ const int y_offset = top * pic->y_stride + left;
+ const int uv_offset = (top / 2) * pic->uv_stride + left / 2;
+ WebPCopyPlane(pic->y + y_offset, pic->y_stride,
+ tmp.y, tmp.y_stride, width, height);
+ WebPCopyPlane(pic->u + uv_offset, pic->uv_stride,
+ tmp.u, tmp.uv_stride, HALVE(width), HALVE(height));
+ WebPCopyPlane(pic->v + uv_offset, pic->uv_stride,
+ tmp.v, tmp.uv_stride, HALVE(width), HALVE(height));
+
+ if (tmp.a != NULL) {
+ const int a_offset = top * pic->a_stride + left;
+ WebPCopyPlane(pic->a + a_offset, pic->a_stride,
+ tmp.a, tmp.a_stride, width, height);
+ }
+ } else {
+ const uint8_t* const src =
+ (const uint8_t*)(pic->argb + top * pic->argb_stride + left);
+ WebPCopyPlane(src, pic->argb_stride * 4, (uint8_t*)tmp.argb,
+ tmp.argb_stride * 4, width * 4, height);
+ }
+ WebPPictureFree(pic);
+ *pic = tmp;
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Simple picture rescaler
+
+static void RescalePlane(const uint8_t* src,
+ int src_width, int src_height, int src_stride,
+ uint8_t* dst,
+ int dst_width, int dst_height, int dst_stride,
+ rescaler_t* const work,
+ int num_channels) {
+ WebPRescaler rescaler;
+ int y = 0;
+ WebPRescalerInit(&rescaler, src_width, src_height,
+ dst, dst_width, dst_height, dst_stride,
+ num_channels, work);
+ while (y < src_height) {
+ y += WebPRescalerImport(&rescaler, src_height - y,
+ src + y * src_stride, src_stride);
+ WebPRescalerExport(&rescaler);
+ }
+}
+
+static void AlphaMultiplyARGB(WebPPicture* const pic, int inverse) {
+ assert(pic->argb != NULL);
+ WebPMultARGBRows((uint8_t*)pic->argb, pic->argb_stride * sizeof(*pic->argb),
+ pic->width, pic->height, inverse);
+}
+
+static void AlphaMultiplyY(WebPPicture* const pic, int inverse) {
+ if (pic->a != NULL) {
+ WebPMultRows(pic->y, pic->y_stride, pic->a, pic->a_stride,
+ pic->width, pic->height, inverse);
+ }
+}
+
+int WebPPictureRescale(WebPPicture* pic, int width, int height) {
+ WebPPicture tmp;
+ int prev_width, prev_height;
+ rescaler_t* work;
+
+ if (pic == NULL) return 0;
+ prev_width = pic->width;
+ prev_height = pic->height;
+ if (!WebPRescalerGetScaledDimensions(
+ prev_width, prev_height, &width, &height)) {
+ return 0;
+ }
+
+ PictureGrabSpecs(pic, &tmp);
+ tmp.width = width;
+ tmp.height = height;
+ if (!WebPPictureAlloc(&tmp)) return 0;
+
+ if (!pic->use_argb) {
+ work = (rescaler_t*)WebPSafeMalloc(2ULL * width, sizeof(*work));
+ if (work == NULL) {
+ WebPPictureFree(&tmp);
+ return 0;
+ }
+ // If present, we need to rescale alpha first (for AlphaMultiplyY).
+ if (pic->a != NULL) {
+ WebPInitAlphaProcessing();
+ RescalePlane(pic->a, prev_width, prev_height, pic->a_stride,
+ tmp.a, width, height, tmp.a_stride, work, 1);
+ }
+
+ // We take transparency into account on the luma plane only. That's not
+ // totally exact blending, but still is a good approximation.
+ AlphaMultiplyY(pic, 0);
+ RescalePlane(pic->y, prev_width, prev_height, pic->y_stride,
+ tmp.y, width, height, tmp.y_stride, work, 1);
+ AlphaMultiplyY(&tmp, 1);
+
+ RescalePlane(pic->u,
+ HALVE(prev_width), HALVE(prev_height), pic->uv_stride,
+ tmp.u,
+ HALVE(width), HALVE(height), tmp.uv_stride, work, 1);
+ RescalePlane(pic->v,
+ HALVE(prev_width), HALVE(prev_height), pic->uv_stride,
+ tmp.v,
+ HALVE(width), HALVE(height), tmp.uv_stride, work, 1);
+ } else {
+ work = (rescaler_t*)WebPSafeMalloc(2ULL * width * 4, sizeof(*work));
+ if (work == NULL) {
+ WebPPictureFree(&tmp);
+ return 0;
+ }
+ // In order to correctly interpolate colors, we need to apply the alpha
+ // weighting first (black-matting), scale the RGB values, and remove
+ // the premultiplication afterward (while preserving the alpha channel).
+ WebPInitAlphaProcessing();
+ AlphaMultiplyARGB(pic, 0);
+ RescalePlane((const uint8_t*)pic->argb, prev_width, prev_height,
+ pic->argb_stride * 4,
+ (uint8_t*)tmp.argb, width, height,
+ tmp.argb_stride * 4,
+ work, 4);
+ AlphaMultiplyARGB(&tmp, 1);
+ }
+ WebPPictureFree(pic);
+ WebPSafeFree(work);
+ *pic = tmp;
+ return 1;
+}
+
+//------------------------------------------------------------------------------
diff --git a/drivers/webp/enc/picture_tools.c b/drivers/webp/enc/picture_tools.c
new file mode 100644
index 0000000000..7c73646397
--- /dev/null
+++ b/drivers/webp/enc/picture_tools.c
@@ -0,0 +1,206 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// WebPPicture tools: alpha handling, etc.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./vp8enci.h"
+#include "../dsp/yuv.h"
+
+static WEBP_INLINE uint32_t MakeARGB32(int r, int g, int b) {
+ return (0xff000000u | (r << 16) | (g << 8) | b);
+}
+
+//------------------------------------------------------------------------------
+// Helper: clean up fully transparent area to help compressibility.
+
+#define SIZE 8
+#define SIZE2 (SIZE / 2)
+static int is_transparent_area(const uint8_t* ptr, int stride, int size) {
+ int y, x;
+ for (y = 0; y < size; ++y) {
+ for (x = 0; x < size; ++x) {
+ if (ptr[x]) {
+ return 0;
+ }
+ }
+ ptr += stride;
+ }
+ return 1;
+}
+
+static int is_transparent_argb_area(const uint32_t* ptr, int stride, int size) {
+ int y, x;
+ for (y = 0; y < size; ++y) {
+ for (x = 0; x < size; ++x) {
+ if (ptr[x] & 0xff000000u) {
+ return 0;
+ }
+ }
+ ptr += stride;
+ }
+ return 1;
+}
+
+static void flatten(uint8_t* ptr, int v, int stride, int size) {
+ int y;
+ for (y = 0; y < size; ++y) {
+ memset(ptr, v, size);
+ ptr += stride;
+ }
+}
+
+static void flatten_argb(uint32_t* ptr, uint32_t v, int stride, int size) {
+ int x, y;
+ for (y = 0; y < size; ++y) {
+ for (x = 0; x < size; ++x) ptr[x] = v;
+ ptr += stride;
+ }
+}
+
+void WebPCleanupTransparentArea(WebPPicture* pic) {
+ int x, y, w, h;
+ if (pic == NULL) return;
+ w = pic->width / SIZE;
+ h = pic->height / SIZE;
+
+ // note: we ignore the left-overs on right/bottom
+ if (pic->use_argb) {
+ uint32_t argb_value = 0;
+ for (y = 0; y < h; ++y) {
+ int need_reset = 1;
+ for (x = 0; x < w; ++x) {
+ const int off = (y * pic->argb_stride + x) * SIZE;
+ if (is_transparent_argb_area(pic->argb + off, pic->argb_stride, SIZE)) {
+ if (need_reset) {
+ argb_value = pic->argb[off];
+ need_reset = 0;
+ }
+ flatten_argb(pic->argb + off, argb_value, pic->argb_stride, SIZE);
+ } else {
+ need_reset = 1;
+ }
+ }
+ }
+ } else {
+ const uint8_t* const a_ptr = pic->a;
+ int values[3] = { 0 };
+ if (a_ptr == NULL) return; // nothing to do
+ for (y = 0; y < h; ++y) {
+ int need_reset = 1;
+ for (x = 0; x < w; ++x) {
+ const int off_a = (y * pic->a_stride + x) * SIZE;
+ const int off_y = (y * pic->y_stride + x) * SIZE;
+ const int off_uv = (y * pic->uv_stride + x) * SIZE2;
+ if (is_transparent_area(a_ptr + off_a, pic->a_stride, SIZE)) {
+ if (need_reset) {
+ values[0] = pic->y[off_y];
+ values[1] = pic->u[off_uv];
+ values[2] = pic->v[off_uv];
+ need_reset = 0;
+ }
+ flatten(pic->y + off_y, values[0], pic->y_stride, SIZE);
+ flatten(pic->u + off_uv, values[1], pic->uv_stride, SIZE2);
+ flatten(pic->v + off_uv, values[2], pic->uv_stride, SIZE2);
+ } else {
+ need_reset = 1;
+ }
+ }
+ }
+ }
+}
+
+#undef SIZE
+#undef SIZE2
+
+//------------------------------------------------------------------------------
+// Blend color and remove transparency info
+
+#define BLEND(V0, V1, ALPHA) \
+ ((((V0) * (255 - (ALPHA)) + (V1) * (ALPHA)) * 0x101) >> 16)
+#define BLEND_10BIT(V0, V1, ALPHA) \
+ ((((V0) * (1020 - (ALPHA)) + (V1) * (ALPHA)) * 0x101) >> 18)
+
+void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb) {
+ const int red = (background_rgb >> 16) & 0xff;
+ const int green = (background_rgb >> 8) & 0xff;
+ const int blue = (background_rgb >> 0) & 0xff;
+ int x, y;
+ if (pic == NULL) return;
+ if (!pic->use_argb) {
+ const int uv_width = (pic->width >> 1); // omit last pixel during u/v loop
+ const int Y0 = VP8RGBToY(red, green, blue, YUV_HALF);
+ // VP8RGBToU/V expects the u/v values summed over four pixels
+ const int U0 = VP8RGBToU(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF);
+ const int V0 = VP8RGBToV(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF);
+ const int has_alpha = pic->colorspace & WEBP_CSP_ALPHA_BIT;
+ if (!has_alpha || pic->a == NULL) return; // nothing to do
+ for (y = 0; y < pic->height; ++y) {
+ // Luma blending
+ uint8_t* const y_ptr = pic->y + y * pic->y_stride;
+ uint8_t* const a_ptr = pic->a + y * pic->a_stride;
+ for (x = 0; x < pic->width; ++x) {
+ const int alpha = a_ptr[x];
+ if (alpha < 0xff) {
+ y_ptr[x] = BLEND(Y0, y_ptr[x], a_ptr[x]);
+ }
+ }
+ // Chroma blending every even line
+ if ((y & 1) == 0) {
+ uint8_t* const u = pic->u + (y >> 1) * pic->uv_stride;
+ uint8_t* const v = pic->v + (y >> 1) * pic->uv_stride;
+ uint8_t* const a_ptr2 =
+ (y + 1 == pic->height) ? a_ptr : a_ptr + pic->a_stride;
+ for (x = 0; x < uv_width; ++x) {
+ // Average four alpha values into a single blending weight.
+ // TODO(skal): might lead to visible contouring. Can we do better?
+ const int alpha =
+ a_ptr[2 * x + 0] + a_ptr[2 * x + 1] +
+ a_ptr2[2 * x + 0] + a_ptr2[2 * x + 1];
+ u[x] = BLEND_10BIT(U0, u[x], alpha);
+ v[x] = BLEND_10BIT(V0, v[x], alpha);
+ }
+ if (pic->width & 1) { // rightmost pixel
+ const int alpha = 2 * (a_ptr[2 * x + 0] + a_ptr2[2 * x + 0]);
+ u[x] = BLEND_10BIT(U0, u[x], alpha);
+ v[x] = BLEND_10BIT(V0, v[x], alpha);
+ }
+ }
+ memset(a_ptr, 0xff, pic->width);
+ }
+ } else {
+ uint32_t* argb = pic->argb;
+ const uint32_t background = MakeARGB32(red, green, blue);
+ for (y = 0; y < pic->height; ++y) {
+ for (x = 0; x < pic->width; ++x) {
+ const int alpha = (argb[x] >> 24) & 0xff;
+ if (alpha != 0xff) {
+ if (alpha > 0) {
+ int r = (argb[x] >> 16) & 0xff;
+ int g = (argb[x] >> 8) & 0xff;
+ int b = (argb[x] >> 0) & 0xff;
+ r = BLEND(red, r, alpha);
+ g = BLEND(green, g, alpha);
+ b = BLEND(blue, b, alpha);
+ argb[x] = MakeARGB32(r, g, b);
+ } else {
+ argb[x] = background;
+ }
+ }
+ }
+ argb += pic->argb_stride;
+ }
+ }
+}
+
+#undef BLEND
+#undef BLEND_10BIT
+
+//------------------------------------------------------------------------------
diff --git a/drivers/webp/enc/quant.c b/drivers/webp/enc/quant.c
index ea153849c8..002c326b82 100644
--- a/drivers/webp/enc/quant.c
+++ b/drivers/webp/enc/quant.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Quantization
@@ -11,6 +13,7 @@
#include <assert.h>
#include <math.h>
+#include <stdlib.h> // for abs()
#include "./vp8enci.h"
#include "./cost.h"
@@ -22,16 +25,78 @@
#define MID_ALPHA 64 // neutral value for susceptibility
#define MIN_ALPHA 30 // lowest usable value for susceptibility
-#define MAX_ALPHA 100 // higher meaninful value for susceptibility
+#define MAX_ALPHA 100 // higher meaningful value for susceptibility
#define SNS_TO_DQ 0.9 // Scaling constant between the sns value and the QP
// power-law modulation. Must be strictly less than 1.
+#define I4_PENALTY 4000 // Rate-penalty for quick i4/i16 decision
+
+// number of non-zero coeffs below which we consider the block very flat
+// (and apply a penalty to complex predictions)
+#define FLATNESS_LIMIT_I16 10 // I16 mode
+#define FLATNESS_LIMIT_I4 3 // I4 mode
+#define FLATNESS_LIMIT_UV 2 // UV mode
+#define FLATNESS_PENALTY 140 // roughly ~1bit per block
+
#define MULT_8B(a, b) (((a) * (b) + 128) >> 8)
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+// #define DEBUG_BLOCK
+
+//------------------------------------------------------------------------------
+
+#if defined(DEBUG_BLOCK)
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static void PrintBlockInfo(const VP8EncIterator* const it,
+ const VP8ModeScore* const rd) {
+ int i, j;
+ const int is_i16 = (it->mb_->type_ == 1);
+ printf("SOURCE / OUTPUT / ABS DELTA\n");
+ for (j = 0; j < 24; ++j) {
+ if (j == 16) printf("\n"); // newline before the U/V block
+ for (i = 0; i < 16; ++i) printf("%3d ", it->yuv_in_[i + j * BPS]);
+ printf(" ");
+ for (i = 0; i < 16; ++i) printf("%3d ", it->yuv_out_[i + j * BPS]);
+ printf(" ");
+ for (i = 0; i < 16; ++i) {
+ printf("%1d ", abs(it->yuv_out_[i + j * BPS] - it->yuv_in_[i + j * BPS]));
+ }
+ printf("\n");
+ }
+ printf("\nD:%d SD:%d R:%d H:%d nz:0x%x score:%d\n",
+ (int)rd->D, (int)rd->SD, (int)rd->R, (int)rd->H, (int)rd->nz,
+ (int)rd->score);
+ if (is_i16) {
+ printf("Mode: %d\n", rd->mode_i16);
+ printf("y_dc_levels:");
+ for (i = 0; i < 16; ++i) printf("%3d ", rd->y_dc_levels[i]);
+ printf("\n");
+ } else {
+ printf("Modes[16]: ");
+ for (i = 0; i < 16; ++i) printf("%d ", rd->modes_i4[i]);
+ printf("\n");
+ }
+ printf("y_ac_levels:\n");
+ for (j = 0; j < 16; ++j) {
+ for (i = is_i16 ? 1 : 0; i < 16; ++i) {
+ printf("%4d ", rd->y_ac_levels[j][i]);
+ }
+ printf("\n");
+ }
+ printf("\n");
+ printf("uv_levels (mode=%d):\n", rd->mode_uv);
+ for (j = 0; j < 8; ++j) {
+ for (i = 0; i < 16; ++i) {
+ printf("%4d ", rd->uv_levels[j][i]);
+ }
+ printf("\n");
+ }
+}
+
+#endif // DEBUG_BLOCK
//------------------------------------------------------------------------------
@@ -100,31 +165,13 @@ static const uint16_t kAcTable2[128] = {
385, 393, 401, 409, 416, 424, 432, 440
};
-static const uint16_t kCoeffThresh[16] = {
- 0, 10, 20, 30,
- 10, 20, 30, 30,
- 20, 30, 30, 30,
- 30, 30, 30, 30
-};
-
-// TODO(skal): tune more. Coeff thresholding?
-static const uint8_t kBiasMatrices[3][16] = { // [3] = [luma-ac,luma-dc,chroma]
- { 96, 96, 96, 96,
- 96, 96, 96, 96,
- 96, 96, 96, 96,
- 96, 96, 96, 96 },
- { 96, 96, 96, 96,
- 96, 96, 96, 96,
- 96, 96, 96, 96,
- 96, 96, 96, 96 },
- { 96, 96, 96, 96,
- 96, 96, 96, 96,
- 96, 96, 96, 96,
- 96, 96, 96, 96 }
+static const uint8_t kBiasMatrices[3][2] = { // [luma-ac,luma-dc,chroma][dc,ac]
+ { 96, 110 }, { 96, 108 }, { 110, 115 }
};
-// Sharpening by (slightly) raising the hi-frequency coeffs (only for trellis).
+// Sharpening by (slightly) raising the hi-frequency coeffs.
// Hack-ish but helpful for mid-bitrate range. Use with care.
+#define SHARPEN_BITS 11 // number of descaling bits for sharpening bias
static const uint8_t kFreqSharpening[16] = {
0, 30, 60, 90,
30, 60, 90, 90,
@@ -137,20 +184,30 @@ static const uint8_t kFreqSharpening[16] = {
// Returns the average quantizer
static int ExpandMatrix(VP8Matrix* const m, int type) {
- int i;
- int sum = 0;
+ int i, sum;
+ for (i = 0; i < 2; ++i) {
+ const int is_ac_coeff = (i > 0);
+ const int bias = kBiasMatrices[type][is_ac_coeff];
+ m->iq_[i] = (1 << QFIX) / m->q_[i];
+ m->bias_[i] = BIAS(bias);
+ // zthresh_ is the exact value such that QUANTDIV(coeff, iQ, B) is:
+ // * zero if coeff <= zthresh
+ // * non-zero if coeff > zthresh
+ m->zthresh_[i] = ((1 << QFIX) - 1 - m->bias_[i]) / m->iq_[i];
+ }
for (i = 2; i < 16; ++i) {
m->q_[i] = m->q_[1];
+ m->iq_[i] = m->iq_[1];
+ m->bias_[i] = m->bias_[1];
+ m->zthresh_[i] = m->zthresh_[1];
}
- for (i = 0; i < 16; ++i) {
- const int j = kZigzag[i];
- const int bias = kBiasMatrices[type][j];
- m->iq_[j] = (1 << QFIX) / m->q_[j];
- m->bias_[j] = BIAS(bias);
- // TODO(skal): tune kCoeffThresh[]
- m->zthresh_[j] = ((256 /*+ kCoeffThresh[j]*/ - bias) * m->q_[j] + 127) >> 8;
- m->sharpen_[j] = (kFreqSharpening[j] * m->q_[j]) >> 11;
- sum += m->q_[j];
+ for (sum = 0, i = 0; i < 16; ++i) {
+ if (type == 0) { // we only use sharpening for AC luma coeffs
+ m->sharpen_[i] = (kFreqSharpening[i] * m->q_[i]) >> SHARPEN_BITS;
+ } else {
+ m->sharpen_[i] = 0;
+ }
+ sum += m->q_[i];
}
return (sum + 8) >> 4;
}
@@ -178,17 +235,17 @@ static void SetupMatrices(VP8Encoder* enc) {
q16 = ExpandMatrix(&m->y2_, 1);
quv = ExpandMatrix(&m->uv_, 2);
- // TODO: Switch to kLambda*[] tables?
- {
- m->lambda_i4_ = (3 * q4 * q4) >> 7;
- m->lambda_i16_ = (3 * q16 * q16);
- m->lambda_uv_ = (3 * quv * quv) >> 6;
- m->lambda_mode_ = (1 * q4 * q4) >> 7;
- m->lambda_trellis_i4_ = (7 * q4 * q4) >> 3;
- m->lambda_trellis_i16_ = (q16 * q16) >> 2;
- m->lambda_trellis_uv_ = (quv *quv) << 1;
- m->tlambda_ = (tlambda_scale * q4) >> 5;
- }
+ m->lambda_i4_ = (3 * q4 * q4) >> 7;
+ m->lambda_i16_ = (3 * q16 * q16);
+ m->lambda_uv_ = (3 * quv * quv) >> 6;
+ m->lambda_mode_ = (1 * q4 * q4) >> 7;
+ m->lambda_trellis_i4_ = (7 * q4 * q4) >> 3;
+ m->lambda_trellis_i16_ = (q16 * q16) >> 2;
+ m->lambda_trellis_uv_ = (quv *quv) << 1;
+ m->tlambda_ = (tlambda_scale * q4) >> 5;
+
+ m->min_disto_ = 10 * m->y1_.q_[0]; // quantization-aware min disto
+ m->max_edge_ = 0;
}
}
@@ -197,16 +254,21 @@ static void SetupMatrices(VP8Encoder* enc) {
// Very small filter-strength values have close to no visual effect. So we can
// save a little decoding-CPU by turning filtering off for these.
-#define FSTRENGTH_CUTOFF 3
+#define FSTRENGTH_CUTOFF 2
static void SetupFilterStrength(VP8Encoder* const enc) {
int i;
- const int level0 = enc->config_->filter_strength;
+ // level0 is in [0..500]. Using '-f 50' as filter_strength is mid-filtering.
+ const int level0 = 5 * enc->config_->filter_strength;
for (i = 0; i < NUM_MB_SEGMENTS; ++i) {
- // Segments with lower quantizer will be less filtered. TODO: tune (wrt SNS)
- const int level = level0 * 256 * enc->dqm_[i].quant_ / 128;
- const int f = level / (256 + enc->dqm_[i].beta_);
- enc->dqm_[i].fstrength_ = (f < FSTRENGTH_CUTOFF) ? 0 : (f > 63) ? 63 : f;
+ VP8SegmentInfo* const m = &enc->dqm_[i];
+ // We focus on the quantization of AC coeffs.
+ const int qstep = kAcTable[clip(m->quant_, 0, 127)] >> 2;
+ const int base_strength =
+ VP8FilterStrengthFromDelta(enc->filter_hdr_.sharpness_, qstep);
+ // Segments with lower complexity ('beta') will be less filtered.
+ const int f = base_strength * level0 / (256 + m->beta_);
+ m->fstrength_ = (f < FSTRENGTH_CUTOFF) ? 0 : (f > 63) ? 63 : f;
}
// We record the initial strength (mainly for the case of 1-segment only).
enc->filter_hdr_.level_ = enc->dqm_[0].fstrength_;
@@ -224,28 +286,90 @@ static void SetupFilterStrength(VP8Encoder* const enc) {
// We want to emulate jpeg-like behaviour where the expected "good" quality
// is around q=75. Internally, our "good" middle is around c=50. So we
// map accordingly using linear piece-wise function
-static double QualityToCompression(double q) {
- const double c = q / 100.;
- return (c < 0.75) ? c * (2. / 3.) : 2. * c - 1.;
+static double QualityToCompression(double c) {
+ const double linear_c = (c < 0.75) ? c * (2. / 3.) : 2. * c - 1.;
+ // The file size roughly scales as pow(quantizer, 3.). Actually, the
+ // exponent is somewhere between 2.8 and 3.2, but we're mostly interested
+ // in the mid-quant range. So we scale the compressibility inversely to
+ // this power-law: quant ~= compression ^ 1/3. This law holds well for
+ // low quant. Finer modeling for high-quant would make use of kAcTable[]
+ // more explicitly.
+ const double v = pow(linear_c, 1 / 3.);
+ return v;
+}
+
+static double QualityToJPEGCompression(double c, double alpha) {
+ // We map the complexity 'alpha' and quality setting 'c' to a compression
+ // exponent empirically matched to the compression curve of libjpeg6b.
+ // On average, the WebP output size will be roughly similar to that of a
+ // JPEG file compressed with same quality factor.
+ const double amin = 0.30;
+ const double amax = 0.85;
+ const double exp_min = 0.4;
+ const double exp_max = 0.9;
+ const double slope = (exp_min - exp_max) / (amax - amin);
+ // Linearly interpolate 'expn' from exp_min to exp_max
+ // in the [amin, amax] range.
+ const double expn = (alpha > amax) ? exp_min
+ : (alpha < amin) ? exp_max
+ : exp_max + slope * (alpha - amin);
+ const double v = pow(c, expn);
+ return v;
+}
+
+static int SegmentsAreEquivalent(const VP8SegmentInfo* const S1,
+ const VP8SegmentInfo* const S2) {
+ return (S1->quant_ == S2->quant_) && (S1->fstrength_ == S2->fstrength_);
+}
+
+static void SimplifySegments(VP8Encoder* const enc) {
+ int map[NUM_MB_SEGMENTS] = { 0, 1, 2, 3 };
+ const int num_segments = enc->segment_hdr_.num_segments_;
+ int num_final_segments = 1;
+ int s1, s2;
+ for (s1 = 1; s1 < num_segments; ++s1) { // find similar segments
+ const VP8SegmentInfo* const S1 = &enc->dqm_[s1];
+ int found = 0;
+ // check if we already have similar segment
+ for (s2 = 0; s2 < num_final_segments; ++s2) {
+ const VP8SegmentInfo* const S2 = &enc->dqm_[s2];
+ if (SegmentsAreEquivalent(S1, S2)) {
+ found = 1;
+ break;
+ }
+ }
+ map[s1] = s2;
+ if (!found) {
+ if (num_final_segments != s1) {
+ enc->dqm_[num_final_segments] = enc->dqm_[s1];
+ }
+ ++num_final_segments;
+ }
+ }
+ if (num_final_segments < num_segments) { // Remap
+ int i = enc->mb_w_ * enc->mb_h_;
+ while (i-- > 0) enc->mb_info_[i].segment_ = map[enc->mb_info_[i].segment_];
+ enc->segment_hdr_.num_segments_ = num_final_segments;
+ // Replicate the trailing segment infos (it's mostly cosmetics)
+ for (i = num_final_segments; i < num_segments; ++i) {
+ enc->dqm_[i] = enc->dqm_[num_final_segments - 1];
+ }
+ }
}
void VP8SetSegmentParams(VP8Encoder* const enc, float quality) {
int i;
int dq_uv_ac, dq_uv_dc;
- const int num_segments = enc->config_->segments;
+ const int num_segments = enc->segment_hdr_.num_segments_;
const double amp = SNS_TO_DQ * enc->config_->sns_strength / 100. / 128.;
- const double c_base = QualityToCompression(quality);
+ const double Q = quality / 100.;
+ const double c_base = enc->config_->emulate_jpeg_size ?
+ QualityToJPEGCompression(Q, enc->alpha_ / 255.) :
+ QualityToCompression(Q);
for (i = 0; i < num_segments; ++i) {
- // The file size roughly scales as pow(quantizer, 3.). Actually, the
- // exponent is somewhere between 2.8 and 3.2, but we're mostly interested
- // in the mid-quant range. So we scale the compressibility inversely to
- // this power-law: quant ~= compression ^ 1/3. This law holds well for
- // low quant. Finer modelling for high-quant would make use of kAcTable[]
- // more explicitely.
- // Additionally, we modulate the base exponent 1/3 to accommodate for the
- // quantization susceptibility and allow denser segments to be quantized
- // more.
- const double expn = (1. - amp * enc->dqm_[i].alpha_) / 3.;
+ // We modulate the base coefficient to accommodate for the quantization
+ // susceptibility and allow denser segments to be quantized more.
+ const double expn = 1. - amp * enc->dqm_[i].alpha_;
const double c = pow(c_base, expn);
const int q = (int)(127. * (1. - c));
assert(expn > 0.);
@@ -271,7 +395,7 @@ void VP8SetSegmentParams(VP8Encoder* const enc, float quality) {
dq_uv_ac = clip(dq_uv_ac, MIN_DQ_UV, MAX_DQ_UV);
// We also boost the dc-uv-quant a little, based on sns-strength, since
// U/V channels are quite more reactive to high quants (flat DC-blocks
- // tend to appear, and are displeasant).
+ // tend to appear, and are unpleasant).
dq_uv_dc = -4 * enc->config_->sns_strength / 100;
dq_uv_dc = clip(dq_uv_dc, -15, 15); // 4bit-signed max allowed
@@ -281,9 +405,11 @@ void VP8SetSegmentParams(VP8Encoder* const enc, float quality) {
enc->dq_uv_dc_ = dq_uv_dc;
enc->dq_uv_ac_ = dq_uv_ac;
- SetupMatrices(enc);
-
SetupFilterStrength(enc); // initialize segments' filtering, eventually
+
+ if (num_segments > 1) SimplifySegments(enc);
+
+ SetupMatrices(enc); // finalize quantization matrices
}
//------------------------------------------------------------------------------
@@ -299,16 +425,14 @@ const int VP8I4ModeOffsets[NUM_BMODES] = {
};
void VP8MakeLuma16Preds(const VP8EncIterator* const it) {
- const VP8Encoder* const enc = it->enc_;
- const uint8_t* const left = it->x_ ? enc->y_left_ : NULL;
- const uint8_t* const top = it->y_ ? enc->y_top_ + it->x_ * 16 : NULL;
+ const uint8_t* const left = it->x_ ? it->y_left_ : NULL;
+ const uint8_t* const top = it->y_ ? it->y_top_ : NULL;
VP8EncPredLuma16(it->yuv_p_, left, top);
}
void VP8MakeChroma8Preds(const VP8EncIterator* const it) {
- const VP8Encoder* const enc = it->enc_;
- const uint8_t* const left = it->x_ ? enc->u_left_ : NULL;
- const uint8_t* const top = it->y_ ? enc->uv_top_ + it->x_ * 16 : NULL;
+ const uint8_t* const left = it->x_ ? it->u_left_ : NULL;
+ const uint8_t* const top = it->y_ ? it->uv_top_ : NULL;
VP8EncPredChroma8(it->yuv_p_, left, top);
}
@@ -320,23 +444,21 @@ void VP8MakeIntra4Preds(const VP8EncIterator* const it) {
// Quantize
// Layout:
-// +----+
-// |YYYY| 0
-// |YYYY| 4
-// |YYYY| 8
-// |YYYY| 12
-// +----+
-// |UUVV| 16
-// |UUVV| 20
-// +----+
-
-const int VP8Scan[16 + 4 + 4] = {
- // Luma
+// +----+----+
+// |YYYY|UUVV| 0
+// |YYYY|UUVV| 4
+// |YYYY|....| 8
+// |YYYY|....| 12
+// +----+----+
+
+const int VP8Scan[16] = { // Luma
0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS,
0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS,
0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS,
0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS,
+};
+static const int VP8ScanUV[4 + 4] = {
0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U
8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V
};
@@ -364,6 +486,7 @@ static void InitScore(VP8ModeScore* const rd) {
rd->D = 0;
rd->SD = 0;
rd->R = 0;
+ rd->H = 0;
rd->nz = 0;
rd->score = MAX_COST;
}
@@ -372,6 +495,7 @@ static void CopyScore(VP8ModeScore* const dst, const VP8ModeScore* const src) {
dst->D = src->D;
dst->SD = src->SD;
dst->R = src->R;
+ dst->H = src->H;
dst->nz = src->nz; // note that nz is not accumulated, but just copied.
dst->score = src->score;
}
@@ -380,6 +504,7 @@ static void AddScore(VP8ModeScore* const dst, const VP8ModeScore* const src) {
dst->D += src->D;
dst->SD += src->SD;
dst->R += src->R;
+ dst->H += src->H;
dst->nz |= src->nz; // here, new nz bits are accumulated.
dst->score += src->score;
}
@@ -387,28 +512,31 @@ static void AddScore(VP8ModeScore* const dst, const VP8ModeScore* const src) {
//------------------------------------------------------------------------------
// Performs trellis-optimized quantization.
-// Trellis
-
+// Trellis node
typedef struct {
- int prev; // best previous
- int level; // level
- int sign; // sign of coeff_i
- score_t cost; // bit cost
- score_t error; // distortion = sum of (|coeff_i| - level_i * Q_i)^2
- int ctx; // context (only depends on 'level'. Could be spared.)
+ int8_t prev; // best previous node
+ int8_t sign; // sign of coeff_i
+ int16_t level; // level
} Node;
+// Score state
+typedef struct {
+ score_t score; // partial RD score
+ const uint16_t* costs; // shortcut to cost tables
+} ScoreState;
+
// If a coefficient was quantized to a value Q (using a neutral bias),
// we test all alternate possibilities between [Q-MIN_DELTA, Q+MAX_DELTA]
// We don't test negative values though.
#define MIN_DELTA 0 // how much lower level to try
#define MAX_DELTA 1 // how much higher
#define NUM_NODES (MIN_DELTA + 1 + MAX_DELTA)
-#define NODE(n, l) (nodes[(n) + 1][(l) + MIN_DELTA])
+#define NODE(n, l) (nodes[(n)][(l) + MIN_DELTA])
+#define SCORE_STATE(n, l) (score_states[n][(l) + MIN_DELTA])
static WEBP_INLINE void SetRDScore(int lambda, VP8ModeScore* const rd) {
// TODO: incorporate the "* 256" in the tables?
- rd->score = rd->R * lambda + 256 * (rd->D + rd->SD);
+ rd->score = (rd->R + rd->H) * lambda + 256 * (rd->D + rd->SD);
}
static WEBP_INLINE score_t RDScoreTrellis(int lambda, score_t rate,
@@ -416,34 +544,37 @@ static WEBP_INLINE score_t RDScoreTrellis(int lambda, score_t rate,
return rate * lambda + 256 * distortion;
}
-static int TrellisQuantizeBlock(const VP8EncIterator* const it,
+static int TrellisQuantizeBlock(const VP8Encoder* const enc,
int16_t in[16], int16_t out[16],
int ctx0, int coeff_type,
const VP8Matrix* const mtx,
int lambda) {
- ProbaArray* const last_costs = it->enc_->proba_.coeffs_[coeff_type];
- CostArray* const costs = it->enc_->proba_.level_cost_[coeff_type];
+ const ProbaArray* const probas = enc->proba_.coeffs_[coeff_type];
+ CostArrayPtr const costs =
+ (CostArrayPtr)enc->proba_.remapped_costs_[coeff_type];
const int first = (coeff_type == 0) ? 1 : 0;
- Node nodes[17][NUM_NODES];
+ Node nodes[16][NUM_NODES];
+ ScoreState score_states[2][NUM_NODES];
+ ScoreState* ss_cur = &SCORE_STATE(0, MIN_DELTA);
+ ScoreState* ss_prev = &SCORE_STATE(1, MIN_DELTA);
int best_path[3] = {-1, -1, -1}; // store best-last/best-level/best-previous
score_t best_score;
- int best_node;
- int last = first - 1;
- int n, m, p, nz;
+ int n, m, p, last;
{
score_t cost;
- score_t max_error;
const int thresh = mtx->q_[1] * mtx->q_[1] / 4;
- const int last_proba = last_costs[VP8EncBands[first]][ctx0][0];
+ const int last_proba = probas[VP8EncBands[first]][ctx0][0];
- // compute maximal distortion.
- max_error = 0;
- for (n = first; n < 16; ++n) {
- const int j = kZigzag[n];
+ // compute the position of the last interesting coefficient
+ last = first - 1;
+ for (n = 15; n >= first; --n) {
+ const int j = kZigzag[n];
const int err = in[j] * in[j];
- max_error += kWeightTrellis[j] * err;
- if (err > thresh) last = n;
+ if (err > thresh) {
+ last = n;
+ break;
+ }
}
// we don't need to go inspect up to n = 16 coeffs. We can just go up
// to last + 1 (inclusive) without losing much.
@@ -451,93 +582,95 @@ static int TrellisQuantizeBlock(const VP8EncIterator* const it,
// compute 'skip' score. This is the max score one can do.
cost = VP8BitCost(0, last_proba);
- best_score = RDScoreTrellis(lambda, cost, max_error);
+ best_score = RDScoreTrellis(lambda, cost, 0);
// initialize source node.
- n = first - 1;
for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) {
- NODE(n, m).cost = 0;
- NODE(n, m).error = max_error;
- NODE(n, m).ctx = ctx0;
+ const score_t rate = (ctx0 == 0) ? VP8BitCost(1, last_proba) : 0;
+ ss_cur[m].score = RDScoreTrellis(lambda, rate, 0);
+ ss_cur[m].costs = costs[first][ctx0];
}
}
// traverse trellis.
for (n = first; n <= last; ++n) {
- const int j = kZigzag[n];
- const int Q = mtx->q_[j];
- const int iQ = mtx->iq_[j];
- const int B = BIAS(0x00); // neutral bias
+ const int j = kZigzag[n];
+ const uint32_t Q = mtx->q_[j];
+ const uint32_t iQ = mtx->iq_[j];
+ const uint32_t B = BIAS(0x00); // neutral bias
// note: it's important to take sign of the _original_ coeff,
// so we don't have to consider level < 0 afterward.
const int sign = (in[j] < 0);
- int coeff0 = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
- int level0;
- if (coeff0 > 2047) coeff0 = 2047;
+ const uint32_t coeff0 = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
+ int level0 = QUANTDIV(coeff0, iQ, B);
+ if (level0 > MAX_LEVEL) level0 = MAX_LEVEL;
+
+ { // Swap current and previous score states
+ ScoreState* const tmp = ss_cur;
+ ss_cur = ss_prev;
+ ss_prev = tmp;
+ }
- level0 = QUANTDIV(coeff0, iQ, B);
// test all alternate level values around level0.
for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) {
Node* const cur = &NODE(n, m);
- int delta_error, new_error;
- score_t cur_score = MAX_COST;
int level = level0 + m;
- int last_proba;
-
- cur->sign = sign;
- cur->level = level;
- cur->ctx = (level == 0) ? 0 : (level == 1) ? 1 : 2;
- if (level >= 2048 || level < 0) { // node is dead?
- cur->cost = MAX_COST;
+ const int ctx = (level > 2) ? 2 : level;
+ const int band = VP8EncBands[n + 1];
+ score_t base_score, last_pos_score;
+ score_t best_cur_score = MAX_COST;
+ int best_prev = 0; // default, in case
+
+ ss_cur[m].score = MAX_COST;
+ ss_cur[m].costs = costs[n + 1][ctx];
+ if (level > MAX_LEVEL || level < 0) { // node is dead?
continue;
}
- last_proba = last_costs[VP8EncBands[n + 1]][cur->ctx][0];
- // Compute delta_error = how much coding this level will
- // subtract as distortion to max_error
- new_error = coeff0 - level * Q;
- delta_error =
- kWeightTrellis[j] * (coeff0 * coeff0 - new_error * new_error);
+ // Compute extra rate cost if last coeff's position is < 15
+ {
+ const score_t last_pos_cost =
+ (n < 15) ? VP8BitCost(0, probas[band][ctx][0]) : 0;
+ last_pos_score = RDScoreTrellis(lambda, last_pos_cost, 0);
+ }
+
+ {
+ // Compute delta_error = how much coding this level will
+ // subtract to max_error as distortion.
+ // Here, distortion = sum of (|coeff_i| - level_i * Q_i)^2
+ const int new_error = coeff0 - level * Q;
+ const int delta_error =
+ kWeightTrellis[j] * (new_error * new_error - coeff0 * coeff0);
+ base_score = RDScoreTrellis(lambda, 0, delta_error);
+ }
// Inspect all possible non-dead predecessors. Retain only the best one.
for (p = -MIN_DELTA; p <= MAX_DELTA; ++p) {
- const Node* const prev = &NODE(n - 1, p);
- const int prev_ctx = prev->ctx;
- const uint16_t* const tcost = costs[VP8EncBands[n]][prev_ctx];
- const score_t total_error = prev->error - delta_error;
- score_t cost, base_cost, score;
-
- if (prev->cost >= MAX_COST) { // dead node?
- continue;
- }
-
- // Base cost of both terminal/non-terminal
- base_cost = prev->cost + VP8LevelCost(tcost, level);
-
+ // Dead nodes (with ss_prev[p].score >= MAX_COST) are automatically
+ // eliminated since their score can't be better than the current best.
+ const score_t cost = VP8LevelCost(ss_prev[p].costs, level);
// Examine node assuming it's a non-terminal one.
- cost = base_cost;
- if (level && n < 15) {
- cost += VP8BitCost(1, last_proba);
+ const score_t score =
+ base_score + ss_prev[p].score + RDScoreTrellis(lambda, cost, 0);
+ if (score < best_cur_score) {
+ best_cur_score = score;
+ best_prev = p;
}
- score = RDScoreTrellis(lambda, cost, total_error);
- if (score < cur_score) {
- cur_score = score;
- cur->cost = cost;
- cur->error = total_error;
- cur->prev = p;
- }
-
- // Now, record best terminal node (and thus best entry in the graph).
- if (level) {
- cost = base_cost;
- if (n < 15) cost += VP8BitCost(0, last_proba);
- score = RDScoreTrellis(lambda, cost, total_error);
- if (score < best_score) {
- best_score = score;
- best_path[0] = n; // best eob position
- best_path[1] = m; // best level
- best_path[2] = p; // best predecessor
- }
+ }
+ // Store best finding in current node.
+ cur->sign = sign;
+ cur->level = level;
+ cur->prev = best_prev;
+ ss_cur[m].score = best_cur_score;
+
+ // Now, record best terminal node (and thus best entry in the graph).
+ if (level != 0) {
+ const score_t score = best_cur_score + last_pos_score;
+ if (score < best_score) {
+ best_score = score;
+ best_path[0] = n; // best eob position
+ best_path[1] = m; // best node index
+ best_path[2] = best_prev; // best predecessor
}
}
}
@@ -550,23 +683,25 @@ static int TrellisQuantizeBlock(const VP8EncIterator* const it,
return 0; // skip!
}
- // Unwind the best path.
- // Note: best-prev on terminal node is not necessarily equal to the
- // best_prev for non-terminal. So we patch best_path[2] in.
- n = best_path[0];
- best_node = best_path[1];
- NODE(n, best_node).prev = best_path[2]; // force best-prev for terminal
- nz = 0;
-
- for (; n >= first; --n) {
- const Node* const node = &NODE(n, best_node);
- const int j = kZigzag[n];
- out[n] = node->sign ? -node->level : node->level;
- nz |= (node->level != 0);
- in[j] = out[n] * mtx->q_[j];
- best_node = node->prev;
+ {
+ // Unwind the best path.
+ // Note: best-prev on terminal node is not necessarily equal to the
+ // best_prev for non-terminal. So we patch best_path[2] in.
+ int nz = 0;
+ int best_node = best_path[1];
+ n = best_path[0];
+ NODE(n, best_node).prev = best_path[2]; // force best-prev for terminal
+
+ for (; n >= first; --n) {
+ const Node* const node = &NODE(n, best_node);
+ const int j = kZigzag[n];
+ out[n] = node->sign ? -node->level : node->level;
+ nz |= node->level;
+ in[j] = out[n] * mtx->q_[j];
+ best_node = node->prev;
+ }
+ return (nz != 0);
}
- return nz;
}
#undef NODE
@@ -582,17 +717,17 @@ static int ReconstructIntra16(VP8EncIterator* const it,
int mode) {
const VP8Encoder* const enc = it->enc_;
const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode];
- const uint8_t* const src = it->yuv_in_ + Y_OFF;
+ const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC;
const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
int nz = 0;
int n;
int16_t tmp[16][16], dc_tmp[16];
- for (n = 0; n < 16; ++n) {
- VP8FTransform(src + VP8Scan[n], ref + VP8Scan[n], tmp[n]);
+ for (n = 0; n < 16; n += 2) {
+ VP8FTransform2(src + VP8Scan[n], ref + VP8Scan[n], tmp[n]);
}
VP8FTransformWHT(tmp[0], dc_tmp);
- nz |= VP8EncQuantizeBlock(dc_tmp, rd->y_dc_levels, 0, &dqm->y2_) << 24;
+ nz |= VP8EncQuantizeBlockWHT(dc_tmp, rd->y_dc_levels, &dqm->y2_) << 24;
if (DO_TRELLIS_I16 && it->do_trellis_) {
int x, y;
@@ -601,20 +736,26 @@ static int ReconstructIntra16(VP8EncIterator* const it,
for (x = 0; x < 4; ++x, ++n) {
const int ctx = it->top_nz_[x] + it->left_nz_[y];
const int non_zero =
- TrellisQuantizeBlock(it, tmp[n], rd->y_ac_levels[n], ctx, 0,
- &dqm->y1_, dqm->lambda_trellis_i16_);
+ TrellisQuantizeBlock(enc, tmp[n], rd->y_ac_levels[n], ctx, 0,
+ &dqm->y1_, dqm->lambda_trellis_i16_);
it->top_nz_[x] = it->left_nz_[y] = non_zero;
+ rd->y_ac_levels[n][0] = 0;
nz |= non_zero << n;
}
}
} else {
- for (n = 0; n < 16; ++n) {
- nz |= VP8EncQuantizeBlock(tmp[n], rd->y_ac_levels[n], 1, &dqm->y1_) << n;
+ for (n = 0; n < 16; n += 2) {
+ // Zero-out the first coeff, so that: a) nz is correct below, and
+ // b) finding 'last' non-zero coeffs in SetResidualCoeffs() is simplified.
+ tmp[n][0] = tmp[n + 1][0] = 0;
+ nz |= VP8EncQuantize2Blocks(tmp[n], rd->y_ac_levels[n], &dqm->y1_) << n;
+ assert(rd->y_ac_levels[n + 0][0] == 0);
+ assert(rd->y_ac_levels[n + 1][0] == 0);
}
}
// Transform back
- VP8ITransformWHT(dc_tmp, tmp[0]);
+ VP8TransformWHT(dc_tmp, tmp[0]);
for (n = 0; n < 16; n += 2) {
VP8ITransform(ref + VP8Scan[n], tmp[n], yuv_out + VP8Scan[n], 1);
}
@@ -637,10 +778,10 @@ static int ReconstructIntra4(VP8EncIterator* const it,
if (DO_TRELLIS_I4 && it->do_trellis_) {
const int x = it->i4_ & 3, y = it->i4_ >> 2;
const int ctx = it->top_nz_[x] + it->left_nz_[y];
- nz = TrellisQuantizeBlock(it, tmp, levels, ctx, 3, &dqm->y1_,
+ nz = TrellisQuantizeBlock(enc, tmp, levels, ctx, 3, &dqm->y1_,
dqm->lambda_trellis_i4_);
} else {
- nz = VP8EncQuantizeBlock(tmp, levels, 0, &dqm->y1_);
+ nz = VP8EncQuantizeBlock(tmp, levels, &dqm->y1_);
}
VP8ITransform(ref, tmp, yuv_out, 0);
return nz;
@@ -650,14 +791,14 @@ static int ReconstructUV(VP8EncIterator* const it, VP8ModeScore* const rd,
uint8_t* const yuv_out, int mode) {
const VP8Encoder* const enc = it->enc_;
const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode];
- const uint8_t* const src = it->yuv_in_ + U_OFF;
+ const uint8_t* const src = it->yuv_in_ + U_OFF_ENC;
const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
int nz = 0;
int n;
int16_t tmp[8][16];
- for (n = 0; n < 8; ++n) {
- VP8FTransform(src + VP8Scan[16 + n], ref + VP8Scan[16 + n], tmp[n]);
+ for (n = 0; n < 8; n += 2) {
+ VP8FTransform2(src + VP8ScanUV[n], ref + VP8ScanUV[n], tmp[n]);
}
if (DO_TRELLIS_UV && it->do_trellis_) {
int ch, x, y;
@@ -666,28 +807,45 @@ static int ReconstructUV(VP8EncIterator* const it, VP8ModeScore* const rd,
for (x = 0; x < 2; ++x, ++n) {
const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
const int non_zero =
- TrellisQuantizeBlock(it, tmp[n], rd->uv_levels[n], ctx, 2,
- &dqm->uv_, dqm->lambda_trellis_uv_);
+ TrellisQuantizeBlock(enc, tmp[n], rd->uv_levels[n], ctx, 2,
+ &dqm->uv_, dqm->lambda_trellis_uv_);
it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = non_zero;
nz |= non_zero << n;
}
}
}
} else {
- for (n = 0; n < 8; ++n) {
- nz |= VP8EncQuantizeBlock(tmp[n], rd->uv_levels[n], 0, &dqm->uv_) << n;
+ for (n = 0; n < 8; n += 2) {
+ nz |= VP8EncQuantize2Blocks(tmp[n], rd->uv_levels[n], &dqm->uv_) << n;
}
}
for (n = 0; n < 8; n += 2) {
- VP8ITransform(ref + VP8Scan[16 + n], tmp[n], yuv_out + VP8Scan[16 + n], 1);
+ VP8ITransform(ref + VP8ScanUV[n], tmp[n], yuv_out + VP8ScanUV[n], 1);
}
return (nz << 16);
}
//------------------------------------------------------------------------------
// RD-opt decision. Reconstruct each modes, evalue distortion and bit-cost.
-// Pick the mode is lower RD-cost = Rate + lamba * Distortion.
+// Pick the mode is lower RD-cost = Rate + lambda * Distortion.
+
+static void StoreMaxDelta(VP8SegmentInfo* const dqm, const int16_t DCs[16]) {
+ // We look at the first three AC coefficients to determine what is the average
+ // delta between each sub-4x4 block.
+ const int v0 = abs(DCs[1]);
+ const int v1 = abs(DCs[4]);
+ const int v2 = abs(DCs[5]);
+ int max_v = (v0 > v1) ? v1 : v0;
+ max_v = (v2 > max_v) ? v2 : max_v;
+ if (max_v > dqm->max_edge_) dqm->max_edge_ = max_v;
+}
+
+static void SwapModeScore(VP8ModeScore** a, VP8ModeScore** b) {
+ VP8ModeScore* const tmp = *a;
+ *a = *b;
+ *b = tmp;
+}
static void SwapPtr(uint8_t** a, uint8_t** b) {
uint8_t* const tmp = *a;
@@ -699,43 +857,69 @@ static void SwapOut(VP8EncIterator* const it) {
SwapPtr(&it->yuv_out_, &it->yuv_out2_);
}
-static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* const rd) {
- const VP8Encoder* const enc = it->enc_;
- const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
+static score_t IsFlat(const int16_t* levels, int num_blocks, score_t thresh) {
+ score_t score = 0;
+ while (num_blocks-- > 0) { // TODO(skal): refine positional scoring?
+ int i;
+ for (i = 1; i < 16; ++i) { // omit DC, we're only interested in AC
+ score += (levels[i] != 0);
+ if (score > thresh) return 0;
+ }
+ levels += 16;
+ }
+ return 1;
+}
+
+static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* rd) {
+ const int kNumBlocks = 16;
+ VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
const int lambda = dqm->lambda_i16_;
const int tlambda = dqm->tlambda_;
- const uint8_t* const src = it->yuv_in_ + Y_OFF;
- VP8ModeScore rd16;
+ const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC;
+ VP8ModeScore rd_tmp;
+ VP8ModeScore* rd_cur = &rd_tmp;
+ VP8ModeScore* rd_best = rd;
int mode;
rd->mode_i16 = -1;
- for (mode = 0; mode < 4; ++mode) {
- uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF; // scratch buffer
- int nz;
+ for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
+ uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC; // scratch buffer
+ rd_cur->mode_i16 = mode;
// Reconstruct
- nz = ReconstructIntra16(it, &rd16, tmp_dst, mode);
+ rd_cur->nz = ReconstructIntra16(it, rd_cur, tmp_dst, mode);
// Measure RD-score
- rd16.D = VP8SSE16x16(src, tmp_dst);
- rd16.SD = tlambda ? MULT_8B(tlambda, VP8TDisto16x16(src, tmp_dst, kWeightY))
- : 0;
- rd16.R = VP8GetCostLuma16(it, &rd16);
- rd16.R += VP8FixedCostsI16[mode];
+ rd_cur->D = VP8SSE16x16(src, tmp_dst);
+ rd_cur->SD =
+ tlambda ? MULT_8B(tlambda, VP8TDisto16x16(src, tmp_dst, kWeightY)) : 0;
+ rd_cur->H = VP8FixedCostsI16[mode];
+ rd_cur->R = VP8GetCostLuma16(it, rd_cur);
+ if (mode > 0 &&
+ IsFlat(rd_cur->y_ac_levels[0], kNumBlocks, FLATNESS_LIMIT_I16)) {
+ // penalty to avoid flat area to be mispredicted by complex mode
+ rd_cur->R += FLATNESS_PENALTY * kNumBlocks;
+ }
// Since we always examine Intra16 first, we can overwrite *rd directly.
- SetRDScore(lambda, &rd16);
- if (mode == 0 || rd16.score < rd->score) {
- CopyScore(rd, &rd16);
- rd->mode_i16 = mode;
- rd->nz = nz;
- memcpy(rd->y_ac_levels, rd16.y_ac_levels, sizeof(rd16.y_ac_levels));
- memcpy(rd->y_dc_levels, rd16.y_dc_levels, sizeof(rd16.y_dc_levels));
+ SetRDScore(lambda, rd_cur);
+ if (mode == 0 || rd_cur->score < rd_best->score) {
+ SwapModeScore(&rd_cur, &rd_best);
SwapOut(it);
}
}
+ if (rd_best != rd) {
+ memcpy(rd, rd_best, sizeof(*rd));
+ }
SetRDScore(dqm->lambda_mode_, rd); // finalize score for mode decision.
VP8SetIntra16Mode(it, rd->mode_i16);
+
+ // we have a blocky macroblock (only DCs are non-zero) with fairly high
+ // distortion, record max delta so we can later adjust the minimal filtering
+ // strength needed to smooth these blocks out.
+ if ((rd->nz & 0xffff) == 0 && rd->D > dqm->min_disto_) {
+ StoreMaxDelta(dqm, rd->y_dc_levels);
+ }
}
//------------------------------------------------------------------------------
@@ -755,8 +939,8 @@ static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) {
const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
const int lambda = dqm->lambda_i4_;
const int tlambda = dqm->tlambda_;
- const uint8_t* const src0 = it->yuv_in_ + Y_OFF;
- uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF;
+ const uint8_t* const src0 = it->yuv_in_ + Y_OFF_ENC;
+ uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF_ENC;
int total_header_bits = 0;
VP8ModeScore rd_best;
@@ -765,9 +949,11 @@ static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) {
}
InitScore(&rd_best);
- rd_best.score = 211; // '211' is the value of VP8BitCost(0, 145)
+ rd_best.H = 211; // '211' is the value of VP8BitCost(0, 145)
+ SetRDScore(dqm->lambda_mode_, &rd_best);
VP8IteratorStartI4(it);
do {
+ const int kNumBlocks = 1;
VP8ModeScore rd_i4;
int mode;
int best_mode = -1;
@@ -791,27 +977,44 @@ static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) {
rd_tmp.SD =
tlambda ? MULT_8B(tlambda, VP8TDisto4x4(src, tmp_dst, kWeightY))
: 0;
- rd_tmp.R = VP8GetCostLuma4(it, tmp_levels);
- rd_tmp.R += mode_costs[mode];
+ rd_tmp.H = mode_costs[mode];
+
+ // Add flatness penalty
+ if (mode > 0 && IsFlat(tmp_levels, kNumBlocks, FLATNESS_LIMIT_I4)) {
+ rd_tmp.R = FLATNESS_PENALTY * kNumBlocks;
+ } else {
+ rd_tmp.R = 0;
+ }
+ // early-out check
SetRDScore(lambda, &rd_tmp);
+ if (best_mode >= 0 && rd_tmp.score >= rd_i4.score) continue;
+
+ // finish computing score
+ rd_tmp.R += VP8GetCostLuma4(it, tmp_levels);
+ SetRDScore(lambda, &rd_tmp);
+
if (best_mode < 0 || rd_tmp.score < rd_i4.score) {
CopyScore(&rd_i4, &rd_tmp);
best_mode = mode;
SwapPtr(&tmp_dst, &best_block);
- memcpy(rd_best.y_ac_levels[it->i4_], tmp_levels, sizeof(tmp_levels));
+ memcpy(rd_best.y_ac_levels[it->i4_], tmp_levels,
+ sizeof(rd_best.y_ac_levels[it->i4_]));
}
}
SetRDScore(dqm->lambda_mode_, &rd_i4);
AddScore(&rd_best, &rd_i4);
- total_header_bits += mode_costs[best_mode];
- if (rd_best.score >= rd->score ||
- total_header_bits > enc->max_i4_header_bits_) {
+ if (rd_best.score >= rd->score) {
+ return 0;
+ }
+ total_header_bits += (int)rd_i4.H; // <- equal to mode_costs[best_mode];
+ if (total_header_bits > enc->max_i4_header_bits_) {
return 0;
}
// Copy selected samples if not in the right place already.
- if (best_block != best_blocks + VP8Scan[it->i4_])
+ if (best_block != best_blocks + VP8Scan[it->i4_]) {
VP8Copy4x4(best_block, best_blocks + VP8Scan[it->i4_]);
+ }
rd->modes_i4[it->i4_] = best_mode;
it->top_nz_[it->i4_ & 3] = it->left_nz_[it->i4_ >> 2] = (rd_i4.nz ? 1 : 0);
} while (VP8IteratorRotateI4(it, best_blocks));
@@ -827,18 +1030,19 @@ static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) {
//------------------------------------------------------------------------------
static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) {
- const VP8Encoder* const enc = it->enc_;
- const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
+ const int kNumBlocks = 8;
+ const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
const int lambda = dqm->lambda_uv_;
- const uint8_t* const src = it->yuv_in_ + U_OFF;
- uint8_t* const tmp_dst = it->yuv_out2_ + U_OFF; // scratch buffer
- uint8_t* const dst0 = it->yuv_out_ + U_OFF;
+ const uint8_t* const src = it->yuv_in_ + U_OFF_ENC;
+ uint8_t* tmp_dst = it->yuv_out2_ + U_OFF_ENC; // scratch buffer
+ uint8_t* dst0 = it->yuv_out_ + U_OFF_ENC;
+ uint8_t* dst = dst0;
VP8ModeScore rd_best;
int mode;
rd->mode_uv = -1;
InitScore(&rd_best);
- for (mode = 0; mode < 4; ++mode) {
+ for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
VP8ModeScore rd_uv;
// Reconstruct
@@ -847,19 +1051,25 @@ static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) {
// Compute RD-score
rd_uv.D = VP8SSE16x8(src, tmp_dst);
rd_uv.SD = 0; // TODO: should we call TDisto? it tends to flatten areas.
+ rd_uv.H = VP8FixedCostsUV[mode];
rd_uv.R = VP8GetCostUV(it, &rd_uv);
- rd_uv.R += VP8FixedCostsUV[mode];
+ if (mode > 0 && IsFlat(rd_uv.uv_levels[0], kNumBlocks, FLATNESS_LIMIT_UV)) {
+ rd_uv.R += FLATNESS_PENALTY * kNumBlocks;
+ }
SetRDScore(lambda, &rd_uv);
if (mode == 0 || rd_uv.score < rd_best.score) {
CopyScore(&rd_best, &rd_uv);
rd->mode_uv = mode;
memcpy(rd->uv_levels, rd_uv.uv_levels, sizeof(rd->uv_levels));
- memcpy(dst0, tmp_dst, UV_SIZE); // TODO: SwapUVOut() ?
+ SwapPtr(&dst, &tmp_dst);
}
}
VP8SetIntraUVMode(it, rd->mode_uv);
AddScore(rd, &rd_best);
+ if (dst != dst0) { // copy 16x8 block if needed
+ VP8Copy16x8(dst, dst0);
+ }
}
//------------------------------------------------------------------------------
@@ -867,33 +1077,88 @@ static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) {
static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) {
const VP8Encoder* const enc = it->enc_;
- const int i16 = (it->mb_->type_ == 1);
+ const int is_i16 = (it->mb_->type_ == 1);
int nz = 0;
- if (i16) {
- nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF, it->preds_[0]);
+ if (is_i16) {
+ nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]);
} else {
VP8IteratorStartI4(it);
do {
const int mode =
it->preds_[(it->i4_ & 3) + (it->i4_ >> 2) * enc->preds_w_];
- const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_];
- uint8_t* const dst = it->yuv_out_ + Y_OFF + VP8Scan[it->i4_];
+ const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_];
+ uint8_t* const dst = it->yuv_out_ + Y_OFF_ENC + VP8Scan[it->i4_];
VP8MakeIntra4Preds(it);
nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_],
src, dst, mode) << it->i4_;
- } while (VP8IteratorRotateI4(it, it->yuv_out_ + Y_OFF));
+ } while (VP8IteratorRotateI4(it, it->yuv_out_ + Y_OFF_ENC));
}
- nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF, it->mb_->uv_mode_);
+ nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_);
rd->nz = nz;
}
+// Refine intra16/intra4 sub-modes based on distortion only (not rate).
+static void DistoRefine(VP8EncIterator* const it, int try_both_i4_i16) {
+ const int is_i16 = (it->mb_->type_ == 1);
+ score_t best_score = MAX_COST;
+
+ if (try_both_i4_i16 || is_i16) {
+ int mode;
+ int best_mode = -1;
+ for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
+ const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode];
+ const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC;
+ const score_t score = VP8SSE16x16(src, ref);
+ if (score < best_score) {
+ best_mode = mode;
+ best_score = score;
+ }
+ }
+ VP8SetIntra16Mode(it, best_mode);
+ }
+ if (try_both_i4_i16 || !is_i16) {
+ uint8_t modes_i4[16];
+ // We don't evaluate the rate here, but just account for it through a
+ // constant penalty (i4 mode usually needs more bits compared to i16).
+ score_t score_i4 = (score_t)I4_PENALTY;
+
+ VP8IteratorStartI4(it);
+ do {
+ int mode;
+ int best_sub_mode = -1;
+ score_t best_sub_score = MAX_COST;
+ const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_];
+
+ // TODO(skal): we don't really need the prediction pixels here,
+ // but just the distortion against 'src'.
+ VP8MakeIntra4Preds(it);
+ for (mode = 0; mode < NUM_BMODES; ++mode) {
+ const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode];
+ const score_t score = VP8SSE4x4(src, ref);
+ if (score < best_sub_score) {
+ best_sub_mode = mode;
+ best_sub_score = score;
+ }
+ }
+ modes_i4[it->i4_] = best_sub_mode;
+ score_i4 += best_sub_score;
+ if (score_i4 >= best_score) break;
+ } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF_ENC));
+ if (score_i4 < best_score) {
+ VP8SetIntra4Mode(it, modes_i4);
+ }
+ }
+}
+
//------------------------------------------------------------------------------
// Entry point
-int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, int rd_opt) {
+int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd,
+ VP8RDLevel rd_opt) {
int is_skipped;
+ const int method = it->enc_->method_;
InitScore(rd);
@@ -902,22 +1167,21 @@ int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, int rd_opt) {
VP8MakeLuma16Preds(it);
VP8MakeChroma8Preds(it);
- // for rd_opt = 2, we perform trellis-quant on the final decision only.
- // for rd_opt > 2, we use it for every scoring (=much slower).
- if (rd_opt > 0) {
- it->do_trellis_ = (rd_opt > 2);
+ if (rd_opt > RD_OPT_NONE) {
+ it->do_trellis_ = (rd_opt >= RD_OPT_TRELLIS_ALL);
PickBestIntra16(it, rd);
- if (it->enc_->method_ >= 2) {
+ if (method >= 2) {
PickBestIntra4(it, rd);
}
PickBestUV(it, rd);
- if (rd_opt == 2) {
+ if (rd_opt == RD_OPT_TRELLIS) { // finish off with trellis-optim now
it->do_trellis_ = 1;
SimpleQuantize(it, rd);
}
} else {
- // TODO: for method_ == 2, pick the best intra4/intra16 based on SSE
- it->do_trellis_ = (it->enc_->method_ == 2);
+ // For method == 2, pick the best intra4/intra16 based on SSE (~tad slower).
+ // For method <= 1, we refine intra4 or intra16 (but don't re-examine mode).
+ DistoRefine(it, (method >= 2));
SimpleQuantize(it, rd);
}
is_skipped = (rd->nz == 0);
@@ -925,6 +1189,3 @@ int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, int rd_opt) {
return is_skipped;
}
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/enc/syntax.c b/drivers/webp/enc/syntax.c
index 4221436ff9..2b65f15ca1 100644
--- a/drivers/webp/enc/syntax.c
+++ b/drivers/webp/enc/syntax.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Header syntax writing
@@ -11,35 +13,20 @@
#include <assert.h>
-#include "../format_constants.h"
+#include "../utils/utils.h"
+#include "webp/format_constants.h" // RIFF constants
+#include "webp/mux_types.h" // ALPHA_FLAG
#include "./vp8enci.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
//------------------------------------------------------------------------------
// Helper functions
-// TODO(later): Move to webp/format_constants.h?
-static void PutLE24(uint8_t* const data, uint32_t val) {
- data[0] = (val >> 0) & 0xff;
- data[1] = (val >> 8) & 0xff;
- data[2] = (val >> 16) & 0xff;
-}
-
-static void PutLE32(uint8_t* const data, uint32_t val) {
- PutLE24(data, val);
- data[3] = (val >> 24) & 0xff;
-}
-
static int IsVP8XNeeded(const VP8Encoder* const enc) {
return !!enc->has_alpha_; // Currently the only case when VP8X is needed.
// This could change in the future.
}
static int PutPaddingByte(const WebPPicture* const pic) {
-
const uint8_t pad_byte[1] = { 0 };
return !!pic->writer(pad_byte, 1, pic);
}
@@ -73,14 +60,14 @@ static WebPEncodingError PutVP8XHeader(const VP8Encoder* const enc) {
assert(pic->width <= MAX_CANVAS_SIZE && pic->height <= MAX_CANVAS_SIZE);
if (enc->has_alpha_) {
- flags |= ALPHA_FLAG_BIT;
+ flags |= ALPHA_FLAG;
}
PutLE32(vp8x + TAG_SIZE, VP8X_CHUNK_SIZE);
PutLE32(vp8x + CHUNK_HEADER_SIZE, flags);
PutLE24(vp8x + CHUNK_HEADER_SIZE + 4, pic->width - 1);
PutLE24(vp8x + CHUNK_HEADER_SIZE + 7, pic->height - 1);
- if(!pic->writer(vp8x, sizeof(vp8x), pic)) {
+ if (!pic->writer(vp8x, sizeof(vp8x), pic)) {
return VP8_ENC_ERROR_BAD_WRITE;
}
return VP8_ENC_OK;
@@ -199,8 +186,8 @@ static int PutWebPHeaders(const VP8Encoder* const enc, size_t size0,
// Segmentation header
static void PutSegmentHeader(VP8BitWriter* const bw,
const VP8Encoder* const enc) {
- const VP8SegmentHeader* const hdr = &enc->segment_hdr_;
- const VP8Proba* const proba = &enc->proba_;
+ const VP8EncSegmentHeader* const hdr = &enc->segment_hdr_;
+ const VP8EncProba* const proba = &enc->proba_;
if (VP8PutBitUniform(bw, (hdr->num_segments_ > 1))) {
// We always 'update' the quant and filter strength values
const int update_data = 1;
@@ -210,16 +197,16 @@ static void PutSegmentHeader(VP8BitWriter* const bw,
// we always use absolute values, not relative ones
VP8PutBitUniform(bw, 1); // (segment_feature_mode = 1. Paragraph 9.3.)
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- VP8PutSignedValue(bw, enc->dqm_[s].quant_, 7);
+ VP8PutSignedBits(bw, enc->dqm_[s].quant_, 7);
}
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- VP8PutSignedValue(bw, enc->dqm_[s].fstrength_, 6);
+ VP8PutSignedBits(bw, enc->dqm_[s].fstrength_, 6);
}
}
if (hdr->update_map_) {
for (s = 0; s < 3; ++s) {
if (VP8PutBitUniform(bw, (proba->segments_[s] != 255u))) {
- VP8PutValue(bw, proba->segments_[s], 8);
+ VP8PutBits(bw, proba->segments_[s], 8);
}
}
}
@@ -228,20 +215,20 @@ static void PutSegmentHeader(VP8BitWriter* const bw,
// Filtering parameters header
static void PutFilterHeader(VP8BitWriter* const bw,
- const VP8FilterHeader* const hdr) {
+ const VP8EncFilterHeader* const hdr) {
const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0);
VP8PutBitUniform(bw, hdr->simple_);
- VP8PutValue(bw, hdr->level_, 6);
- VP8PutValue(bw, hdr->sharpness_, 3);
+ VP8PutBits(bw, hdr->level_, 6);
+ VP8PutBits(bw, hdr->sharpness_, 3);
if (VP8PutBitUniform(bw, use_lf_delta)) {
// '0' is the default value for i4x4_lf_delta_ at frame #0.
const int need_update = (hdr->i4x4_lf_delta_ != 0);
if (VP8PutBitUniform(bw, need_update)) {
// we don't use ref_lf_delta => emit four 0 bits
- VP8PutValue(bw, 0, 4);
+ VP8PutBits(bw, 0, 4);
// we use mode_lf_delta for i4x4
- VP8PutSignedValue(bw, hdr->i4x4_lf_delta_, 6);
- VP8PutValue(bw, 0, 3); // all others unused
+ VP8PutSignedBits(bw, hdr->i4x4_lf_delta_, 6);
+ VP8PutBits(bw, 0, 3); // all others unused
}
}
}
@@ -249,12 +236,12 @@ static void PutFilterHeader(VP8BitWriter* const bw,
// Nominal quantization parameters
static void PutQuant(VP8BitWriter* const bw,
const VP8Encoder* const enc) {
- VP8PutValue(bw, enc->base_quant_, 7);
- VP8PutSignedValue(bw, enc->dq_y1_dc_, 4);
- VP8PutSignedValue(bw, enc->dq_y2_dc_, 4);
- VP8PutSignedValue(bw, enc->dq_y2_ac_, 4);
- VP8PutSignedValue(bw, enc->dq_uv_dc_, 4);
- VP8PutSignedValue(bw, enc->dq_uv_ac_, 4);
+ VP8PutBits(bw, enc->base_quant_, 7);
+ VP8PutSignedBits(bw, enc->dq_y1_dc_, 4);
+ VP8PutSignedBits(bw, enc->dq_y2_dc_, 4);
+ VP8PutSignedBits(bw, enc->dq_y2_ac_, 4);
+ VP8PutSignedBits(bw, enc->dq_uv_dc_, 4);
+ VP8PutSignedBits(bw, enc->dq_uv_ac_, 4);
}
// Partition sizes
@@ -276,58 +263,23 @@ static int EmitPartitionsSize(const VP8Encoder* const enc,
//------------------------------------------------------------------------------
-#ifdef WEBP_EXPERIMENTAL_FEATURES
-
-#define KTRAILER_SIZE 8
-
-static int WriteExtensions(VP8Encoder* const enc) {
- uint8_t buffer[KTRAILER_SIZE];
- VP8BitWriter* const bw = &enc->bw_;
- WebPPicture* const pic = enc->pic_;
-
- // Layer (bytes 0..3)
- PutLE24(buffer + 0, enc->layer_data_size_);
- buffer[3] = enc->pic_->colorspace & WEBP_CSP_UV_MASK;
- if (enc->layer_data_size_ > 0) {
- assert(enc->use_layer_);
- // append layer data to last partition
- if (!VP8BitWriterAppend(&enc->parts_[enc->num_parts_ - 1],
- enc->layer_data_, enc->layer_data_size_)) {
- return WebPEncodingSetError(pic, VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY);
- }
- }
-
- buffer[KTRAILER_SIZE - 1] = 0x01; // marker
- if (!VP8BitWriterAppend(bw, buffer, KTRAILER_SIZE)) {
- return WebPEncodingSetError(pic, VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY);
- }
- return 1;
-}
-
-#endif /* WEBP_EXPERIMENTAL_FEATURES */
-
-//------------------------------------------------------------------------------
-
-static size_t GeneratePartition0(VP8Encoder* const enc) {
+static int GeneratePartition0(VP8Encoder* const enc) {
VP8BitWriter* const bw = &enc->bw_;
const int mb_size = enc->mb_w_ * enc->mb_h_;
uint64_t pos1, pos2, pos3;
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- const int need_extensions = enc->use_layer_;
-#endif
pos1 = VP8BitWriterPos(bw);
- VP8BitWriterInit(bw, mb_size * 7 / 8); // ~7 bits per macroblock
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- VP8PutBitUniform(bw, need_extensions); // extensions
-#else
+ if (!VP8BitWriterInit(bw, mb_size * 7 / 8)) { // ~7 bits per macroblock
+ return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
+ }
VP8PutBitUniform(bw, 0); // colorspace
-#endif
VP8PutBitUniform(bw, 0); // clamp type
PutSegmentHeader(bw, enc);
PutFilterHeader(bw, &enc->filter_hdr_);
- VP8PutValue(bw, enc->config_->partitions, 2);
+ VP8PutBits(bw, enc->num_parts_ == 8 ? 3 :
+ enc->num_parts_ == 4 ? 2 :
+ enc->num_parts_ == 2 ? 1 : 0, 2);
PutQuant(bw, enc);
VP8PutBitUniform(bw, 0); // no proba update
VP8WriteProbas(bw, &enc->proba_);
@@ -335,21 +287,17 @@ static size_t GeneratePartition0(VP8Encoder* const enc) {
VP8CodeIntraModes(enc);
VP8BitWriterFinish(bw);
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- if (need_extensions && !WriteExtensions(enc)) {
- return 0;
- }
-#endif
-
pos3 = VP8BitWriterPos(bw);
if (enc->pic_->stats) {
enc->pic_->stats->header_bytes[0] = (int)((pos2 - pos1 + 7) >> 3);
enc->pic_->stats->header_bytes[1] = (int)((pos3 - pos2 + 7) >> 3);
enc->pic_->stats->alpha_data_size = (int)enc->alpha_data_size_;
- enc->pic_->stats->layer_data_size = (int)enc->layer_data_size_;
}
- return !bw->error_;
+ if (bw->error_) {
+ return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
+ }
+ return 1;
}
void VP8EncFreeBitWriters(VP8Encoder* const enc) {
@@ -371,7 +319,8 @@ int VP8EncWrite(VP8Encoder* const enc) {
int p;
// Partition #0 with header and partition sizes
- ok = !!GeneratePartition0(enc);
+ ok = GeneratePartition0(enc);
+ if (!ok) return 0;
// Compute VP8 size
vp8_size = VP8_FRAME_HEADER_SIZE +
@@ -432,6 +381,3 @@ int VP8EncWrite(VP8Encoder* const enc) {
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/enc/token.c b/drivers/webp/enc/token.c
new file mode 100644
index 0000000000..e73256b37e
--- /dev/null
+++ b/drivers/webp/enc/token.c
@@ -0,0 +1,285 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Paginated token buffer
+//
+// A 'token' is a bit value associated with a probability, either fixed
+// or a later-to-be-determined after statistics have been collected.
+// For dynamic probability, we just record the slot id (idx) for the probability
+// value in the final probability array (uint8_t* probas in VP8EmitTokens).
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "./cost.h"
+#include "./vp8enci.h"
+#include "../utils/utils.h"
+
+#if !defined(DISABLE_TOKEN_BUFFER)
+
+// we use pages to reduce the number of memcpy()
+#define MIN_PAGE_SIZE 8192 // minimum number of token per page
+#define FIXED_PROBA_BIT (1u << 14)
+
+typedef uint16_t token_t; // bit #15: bit value
+ // bit #14: flags for constant proba or idx
+ // bits #0..13: slot or constant proba
+struct VP8Tokens {
+ VP8Tokens* next_; // pointer to next page
+};
+// Token data is located in memory just after the next_ field.
+// This macro is used to return their address and hide the trick.
+#define TOKEN_DATA(p) ((const token_t*)&(p)[1])
+
+//------------------------------------------------------------------------------
+
+void VP8TBufferInit(VP8TBuffer* const b, int page_size) {
+ b->tokens_ = NULL;
+ b->pages_ = NULL;
+ b->last_page_ = &b->pages_;
+ b->left_ = 0;
+ b->page_size_ = (page_size < MIN_PAGE_SIZE) ? MIN_PAGE_SIZE : page_size;
+ b->error_ = 0;
+}
+
+void VP8TBufferClear(VP8TBuffer* const b) {
+ if (b != NULL) {
+ VP8Tokens* p = b->pages_;
+ while (p != NULL) {
+ VP8Tokens* const next = p->next_;
+ WebPSafeFree(p);
+ p = next;
+ }
+ VP8TBufferInit(b, b->page_size_);
+ }
+}
+
+static int TBufferNewPage(VP8TBuffer* const b) {
+ VP8Tokens* page = NULL;
+ if (!b->error_) {
+ const size_t size = sizeof(*page) + b->page_size_ * sizeof(token_t);
+ page = (VP8Tokens*)WebPSafeMalloc(1ULL, size);
+ }
+ if (page == NULL) {
+ b->error_ = 1;
+ return 0;
+ }
+ page->next_ = NULL;
+
+ *b->last_page_ = page;
+ b->last_page_ = &page->next_;
+ b->left_ = b->page_size_;
+ b->tokens_ = (token_t*)TOKEN_DATA(page);
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+
+#define TOKEN_ID(t, b, ctx) \
+ (NUM_PROBAS * ((ctx) + NUM_CTX * ((b) + NUM_BANDS * (t))))
+
+static WEBP_INLINE uint32_t AddToken(VP8TBuffer* const b,
+ uint32_t bit, uint32_t proba_idx) {
+ assert(proba_idx < FIXED_PROBA_BIT);
+ assert(bit <= 1);
+ if (b->left_ > 0 || TBufferNewPage(b)) {
+ const int slot = --b->left_;
+ b->tokens_[slot] = (bit << 15) | proba_idx;
+ }
+ return bit;
+}
+
+static WEBP_INLINE void AddConstantToken(VP8TBuffer* const b,
+ uint32_t bit, uint32_t proba) {
+ assert(proba < 256);
+ assert(bit <= 1);
+ if (b->left_ > 0 || TBufferNewPage(b)) {
+ const int slot = --b->left_;
+ b->tokens_[slot] = (bit << 15) | FIXED_PROBA_BIT | proba;
+ }
+}
+
+int VP8RecordCoeffTokens(const int ctx, const int coeff_type,
+ int first, int last,
+ const int16_t* const coeffs,
+ VP8TBuffer* const tokens) {
+ int n = first;
+ uint32_t base_id = TOKEN_ID(coeff_type, n, ctx);
+ if (!AddToken(tokens, last >= 0, base_id + 0)) {
+ return 0;
+ }
+
+ while (n < 16) {
+ const int c = coeffs[n++];
+ const int sign = c < 0;
+ const uint32_t v = sign ? -c : c;
+ if (!AddToken(tokens, v != 0, base_id + 1)) {
+ base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 0); // ctx=0
+ continue;
+ }
+ if (!AddToken(tokens, v > 1, base_id + 2)) {
+ base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 1); // ctx=1
+ } else {
+ if (!AddToken(tokens, v > 4, base_id + 3)) {
+ if (AddToken(tokens, v != 2, base_id + 4))
+ AddToken(tokens, v == 4, base_id + 5);
+ } else if (!AddToken(tokens, v > 10, base_id + 6)) {
+ if (!AddToken(tokens, v > 6, base_id + 7)) {
+ AddConstantToken(tokens, v == 6, 159);
+ } else {
+ AddConstantToken(tokens, v >= 9, 165);
+ AddConstantToken(tokens, !(v & 1), 145);
+ }
+ } else {
+ int mask;
+ const uint8_t* tab;
+ uint32_t residue = v - 3;
+ if (residue < (8 << 1)) { // VP8Cat3 (3b)
+ AddToken(tokens, 0, base_id + 8);
+ AddToken(tokens, 0, base_id + 9);
+ residue -= (8 << 0);
+ mask = 1 << 2;
+ tab = VP8Cat3;
+ } else if (residue < (8 << 2)) { // VP8Cat4 (4b)
+ AddToken(tokens, 0, base_id + 8);
+ AddToken(tokens, 1, base_id + 9);
+ residue -= (8 << 1);
+ mask = 1 << 3;
+ tab = VP8Cat4;
+ } else if (residue < (8 << 3)) { // VP8Cat5 (5b)
+ AddToken(tokens, 1, base_id + 8);
+ AddToken(tokens, 0, base_id + 10);
+ residue -= (8 << 2);
+ mask = 1 << 4;
+ tab = VP8Cat5;
+ } else { // VP8Cat6 (11b)
+ AddToken(tokens, 1, base_id + 8);
+ AddToken(tokens, 1, base_id + 10);
+ residue -= (8 << 3);
+ mask = 1 << 10;
+ tab = VP8Cat6;
+ }
+ while (mask) {
+ AddConstantToken(tokens, !!(residue & mask), *tab++);
+ mask >>= 1;
+ }
+ }
+ base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 2); // ctx=2
+ }
+ AddConstantToken(tokens, sign, 128);
+ if (n == 16 || !AddToken(tokens, n <= last, base_id + 0)) {
+ return 1; // EOB
+ }
+ }
+ return 1;
+}
+
+#undef TOKEN_ID
+
+//------------------------------------------------------------------------------
+// This function works, but isn't currently used. Saved for later.
+
+#if 0
+
+static void Record(int bit, proba_t* const stats) {
+ proba_t p = *stats;
+ if (p >= 0xffff0000u) { // an overflow is inbound.
+ p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2.
+ }
+ // record bit count (lower 16 bits) and increment total count (upper 16 bits).
+ p += 0x00010000u + bit;
+ *stats = p;
+}
+
+void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats) {
+ const VP8Tokens* p = b->pages_;
+ while (p != NULL) {
+ const int N = (p->next_ == NULL) ? b->left_ : 0;
+ int n = MAX_NUM_TOKEN;
+ const token_t* const tokens = TOKEN_DATA(p);
+ while (n-- > N) {
+ const token_t token = tokens[n];
+ if (!(token & FIXED_PROBA_BIT)) {
+ Record((token >> 15) & 1, stats + (token & 0x3fffu));
+ }
+ }
+ p = p->next_;
+ }
+}
+
+#endif // 0
+
+//------------------------------------------------------------------------------
+// Final coding pass, with known probabilities
+
+int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw,
+ const uint8_t* const probas, int final_pass) {
+ const VP8Tokens* p = b->pages_;
+ assert(!b->error_);
+ while (p != NULL) {
+ const VP8Tokens* const next = p->next_;
+ const int N = (next == NULL) ? b->left_ : 0;
+ int n = b->page_size_;
+ const token_t* const tokens = TOKEN_DATA(p);
+ while (n-- > N) {
+ const token_t token = tokens[n];
+ const int bit = (token >> 15) & 1;
+ if (token & FIXED_PROBA_BIT) {
+ VP8PutBit(bw, bit, token & 0xffu); // constant proba
+ } else {
+ VP8PutBit(bw, bit, probas[token & 0x3fffu]);
+ }
+ }
+ if (final_pass) WebPSafeFree((void*)p);
+ p = next;
+ }
+ if (final_pass) b->pages_ = NULL;
+ return 1;
+}
+
+// Size estimation
+size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas) {
+ size_t size = 0;
+ const VP8Tokens* p = b->pages_;
+ assert(!b->error_);
+ while (p != NULL) {
+ const VP8Tokens* const next = p->next_;
+ const int N = (next == NULL) ? b->left_ : 0;
+ int n = b->page_size_;
+ const token_t* const tokens = TOKEN_DATA(p);
+ while (n-- > N) {
+ const token_t token = tokens[n];
+ const int bit = token & (1 << 15);
+ if (token & FIXED_PROBA_BIT) {
+ size += VP8BitCost(bit, token & 0xffu);
+ } else {
+ size += VP8BitCost(bit, probas[token & 0x3fffu]);
+ }
+ }
+ p = next;
+ }
+ return size;
+}
+
+//------------------------------------------------------------------------------
+
+#else // DISABLE_TOKEN_BUFFER
+
+void VP8TBufferInit(VP8TBuffer* const b) {
+ (void)b;
+}
+void VP8TBufferClear(VP8TBuffer* const b) {
+ (void)b;
+}
+
+#endif // !DISABLE_TOKEN_BUFFER
+
diff --git a/drivers/webp/enc/tree.c b/drivers/webp/enc/tree.c
index 8b25e5e488..f141006d19 100644
--- a/drivers/webp/enc/tree.c
+++ b/drivers/webp/enc/tree.c
@@ -1,27 +1,24 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
-// Token probabilities
+// Coding of token probabilities, intra modes and segments.
//
// Author: Skal (pascal.massimino@gmail.com)
#include "./vp8enci.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
//------------------------------------------------------------------------------
// Default probabilities
// Paragraph 13.5
const uint8_t
VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
- // genereated using vp8_default_coef_probs() in entropy.c:129
{ { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
{ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
{ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
@@ -157,7 +154,7 @@ const uint8_t
};
void VP8DefaultProbas(VP8Encoder* const enc) {
- VP8Proba* const probas = &enc->proba_;
+ VP8EncProba* const probas = &enc->proba_;
probas->use_skip_proba_ = 0;
memset(probas->segments_, 255u, sizeof(probas->segments_));
memcpy(probas->coeffs_, VP8CoeffsProba0, sizeof(VP8CoeffsProba0));
@@ -318,7 +315,7 @@ void VP8CodeIntraModes(VP8Encoder* const enc) {
VP8EncIterator it;
VP8IteratorInit(enc, &it);
do {
- const VP8MBInfo* mb = it.mb_;
+ const VP8MBInfo* const mb = it.mb_;
const uint8_t* preds = it.preds_;
if (enc->segment_hdr_.update_map_) {
PutSegment(bw, mb->segment_, enc->proba_.segments_);
@@ -343,7 +340,7 @@ void VP8CodeIntraModes(VP8Encoder* const enc) {
}
}
PutUVMode(bw, mb->uv_mode_);
- } while (VP8IteratorNext(&it, 0));
+ } while (VP8IteratorNext(&it));
}
//------------------------------------------------------------------------------
@@ -485,7 +482,7 @@ const uint8_t
}
};
-void VP8WriteProbas(VP8BitWriter* const bw, const VP8Proba* const probas) {
+void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas) {
int t, b, c, p;
for (t = 0; t < NUM_TYPES; ++t) {
for (b = 0; b < NUM_BANDS; ++b) {
@@ -494,17 +491,14 @@ void VP8WriteProbas(VP8BitWriter* const bw, const VP8Proba* const probas) {
const uint8_t p0 = probas->coeffs_[t][b][c][p];
const int update = (p0 != VP8CoeffsProba0[t][b][c][p]);
if (VP8PutBit(bw, update, VP8CoeffsUpdateProba[t][b][c][p])) {
- VP8PutValue(bw, p0, 8);
+ VP8PutBits(bw, p0, 8);
}
}
}
}
}
if (VP8PutBitUniform(bw, probas->use_skip_proba_)) {
- VP8PutValue(bw, probas->skip_proba_, 8);
+ VP8PutBits(bw, probas->skip_proba_, 8);
}
}
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/enc/vp8enci.h b/drivers/webp/enc/vp8enci.h
index 936e1c18ce..0cb2ccc353 100644
--- a/drivers/webp/enc/vp8enci.h
+++ b/drivers/webp/enc/vp8enci.h
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// WebP encoder: internal header.
@@ -13,11 +15,18 @@
#define WEBP_ENC_VP8ENCI_H_
#include <string.h> // for memcpy()
-#include "../encode.h"
+#include "../dec/common.h"
#include "../dsp/dsp.h"
#include "../utils/bit_writer.h"
+#include "../utils/thread.h"
+#include "../utils/utils.h"
+#include "webp/encode.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+#include "./vp8li.h"
+#endif // WEBP_EXPERIMENTAL_FEATURES
+
+#ifdef __cplusplus
extern "C" {
#endif
@@ -26,141 +35,94 @@ extern "C" {
// version numbers
#define ENC_MAJ_VERSION 0
-#define ENC_MIN_VERSION 2
-#define ENC_REV_VERSION 0
-
-// size of histogram used by CollectHistogram.
-#define MAX_COEFF_THRESH 64
-
-// intra prediction modes
-enum { B_DC_PRED = 0, // 4x4 modes
- B_TM_PRED = 1,
- B_VE_PRED = 2,
- B_HE_PRED = 3,
- B_RD_PRED = 4,
- B_VR_PRED = 5,
- B_LD_PRED = 6,
- B_VL_PRED = 7,
- B_HD_PRED = 8,
- B_HU_PRED = 9,
- NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10
-
- // Luma16 or UV modes
- DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED,
- H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED
- };
+#define ENC_MIN_VERSION 4
+#define ENC_REV_VERSION 4
-enum { NUM_MB_SEGMENTS = 4,
- MAX_NUM_PARTITIONS = 8,
- NUM_TYPES = 4, // 0: i16-AC, 1: i16-DC, 2:chroma-AC, 3:i4-AC
- NUM_BANDS = 8,
- NUM_CTX = 3,
- NUM_PROBAS = 11,
- MAX_LF_LEVELS = 64, // Maximum loop filter level
- MAX_VARIABLE_LEVEL = 67 // last (inclusive) level with variable cost
+enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
+ MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
+ MAX_LEVEL = 2047 // max level (note: max codable is 2047 + 67)
};
-// YUV-cache parameters. Cache is 16-pixels wide.
-// The original or reconstructed samples can be accessed using VP8Scan[]
+typedef enum { // Rate-distortion optimization levels
+ RD_OPT_NONE = 0, // no rd-opt
+ RD_OPT_BASIC = 1, // basic scoring (no trellis)
+ RD_OPT_TRELLIS = 2, // perform trellis-quant on the final decision only
+ RD_OPT_TRELLIS_ALL = 3 // trellis-quant for every scoring (much slower)
+} VP8RDLevel;
+
+// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
+// The original or reconstructed samples can be accessed using VP8Scan[].
// The predicted blocks can be accessed using offsets to yuv_p_ and
-// the arrays VP8*ModeOffsets[];
-// +----+ YUV Samples area. See VP8Scan[] for accessing the blocks.
-// Y_OFF |YYYY| <- original samples (enc->yuv_in_)
-// |YYYY|
-// |YYYY|
-// |YYYY|
-// U_OFF |UUVV| V_OFF (=U_OFF + 8)
-// |UUVV|
-// +----+
-// Y_OFF |YYYY| <- compressed/decoded samples ('yuv_out_')
-// |YYYY| There are two buffers like this ('yuv_out_'/'yuv_out2_')
-// |YYYY|
-// |YYYY|
-// U_OFF |UUVV| V_OFF
-// |UUVV|
-// x2 (for yuv_out2_)
-// +----+ Prediction area ('yuv_p_', size = PRED_SIZE)
-// I16DC16 |YYYY| Intra16 predictions (16x16 block each)
-// |YYYY|
-// |YYYY|
-// |YYYY|
-// I16TM16 |YYYY|
-// |YYYY|
-// |YYYY|
-// |YYYY|
-// I16VE16 |YYYY|
-// |YYYY|
-// |YYYY|
-// |YYYY|
-// I16HE16 |YYYY|
-// |YYYY|
-// |YYYY|
-// |YYYY|
-// +----+ Chroma U/V predictions (16x8 block each)
-// C8DC8 |UUVV|
-// |UUVV|
-// C8TM8 |UUVV|
-// |UUVV|
-// C8VE8 |UUVV|
-// |UUVV|
-// C8HE8 |UUVV|
-// |UUVV|
-// +----+ Intra 4x4 predictions (4x4 block each)
-// |YYYY| I4DC4 I4TM4 I4VE4 I4HE4
-// |YYYY| I4RD4 I4VR4 I4LD4 I4VL4
-// |YY..| I4HD4 I4HU4 I4TMP
-// +----+
-#define BPS 16 // this is the common stride
-#define Y_SIZE (BPS * 16)
-#define UV_SIZE (BPS * 8)
-#define YUV_SIZE (Y_SIZE + UV_SIZE)
-#define PRED_SIZE (6 * 16 * BPS + 12 * BPS)
-#define Y_OFF (0)
-#define U_OFF (Y_SIZE)
-#define V_OFF (U_OFF + 8)
-#define ALIGN_CST 15
-#define DO_ALIGN(PTR) ((uintptr_t)((PTR) + ALIGN_CST) & ~ALIGN_CST)
-
-extern const int VP8Scan[16 + 4 + 4]; // in quant.c
-extern const int VP8UVModeOffsets[4]; // in analyze.c
+// the arrays VP8*ModeOffsets[].
+// * YUV Samples area (yuv_in_/yuv_out_/yuv_out2_)
+// (see VP8Scan[] for accessing the blocks, along with
+// Y_OFF_ENC/U_OFF_ENC/V_OFF_ENC):
+// +----+----+
+// Y_OFF_ENC |YYYY|UUVV|
+// U_OFF_ENC |YYYY|UUVV|
+// V_OFF_ENC |YYYY|....| <- 25% wasted U/V area
+// |YYYY|....|
+// +----+----+
+// * Prediction area ('yuv_p_', size = PRED_SIZE_ENC)
+// Intra16 predictions (16x16 block each, two per row):
+// |I16DC16|I16TM16|
+// |I16VE16|I16HE16|
+// Chroma U/V predictions (16x8 block each, two per row):
+// |C8DC8|C8TM8|
+// |C8VE8|C8HE8|
+// Intra 4x4 predictions (4x4 block each)
+// |I4DC4 I4TM4 I4VE4 I4HE4|I4RD4 I4VR4 I4LD4 I4VL4|
+// |I4HD4 I4HU4 I4TMP .....|.......................| <- ~31% wasted
+#define YUV_SIZE_ENC (BPS * 16)
+#define PRED_SIZE_ENC (32 * BPS + 16 * BPS + 8 * BPS) // I16+Chroma+I4 preds
+#define Y_OFF_ENC (0)
+#define U_OFF_ENC (16)
+#define V_OFF_ENC (16 + 8)
+
+extern const int VP8Scan[16]; // in quant.c
+extern const int VP8UVModeOffsets[4]; // in analyze.c
extern const int VP8I16ModeOffsets[4];
extern const int VP8I4ModeOffsets[NUM_BMODES];
// Layout of prediction blocks
// intra 16x16
#define I16DC16 (0 * 16 * BPS)
-#define I16TM16 (1 * 16 * BPS)
-#define I16VE16 (2 * 16 * BPS)
-#define I16HE16 (3 * 16 * BPS)
+#define I16TM16 (I16DC16 + 16)
+#define I16VE16 (1 * 16 * BPS)
+#define I16HE16 (I16VE16 + 16)
// chroma 8x8, two U/V blocks side by side (hence: 16x8 each)
-#define C8DC8 (4 * 16 * BPS)
-#define C8TM8 (4 * 16 * BPS + 8 * BPS)
-#define C8VE8 (5 * 16 * BPS)
-#define C8HE8 (5 * 16 * BPS + 8 * BPS)
+#define C8DC8 (2 * 16 * BPS)
+#define C8TM8 (C8DC8 + 1 * 16)
+#define C8VE8 (2 * 16 * BPS + 8 * BPS)
+#define C8HE8 (C8VE8 + 1 * 16)
// intra 4x4
-#define I4DC4 (6 * 16 * BPS + 0)
-#define I4TM4 (6 * 16 * BPS + 4)
-#define I4VE4 (6 * 16 * BPS + 8)
-#define I4HE4 (6 * 16 * BPS + 12)
-#define I4RD4 (6 * 16 * BPS + 4 * BPS + 0)
-#define I4VR4 (6 * 16 * BPS + 4 * BPS + 4)
-#define I4LD4 (6 * 16 * BPS + 4 * BPS + 8)
-#define I4VL4 (6 * 16 * BPS + 4 * BPS + 12)
-#define I4HD4 (6 * 16 * BPS + 8 * BPS + 0)
-#define I4HU4 (6 * 16 * BPS + 8 * BPS + 4)
-#define I4TMP (6 * 16 * BPS + 8 * BPS + 8)
+#define I4DC4 (3 * 16 * BPS + 0)
+#define I4TM4 (I4DC4 + 4)
+#define I4VE4 (I4DC4 + 8)
+#define I4HE4 (I4DC4 + 12)
+#define I4RD4 (I4DC4 + 16)
+#define I4VR4 (I4DC4 + 20)
+#define I4LD4 (I4DC4 + 24)
+#define I4VL4 (I4DC4 + 28)
+#define I4HD4 (3 * 16 * BPS + 4 * BPS)
+#define I4HU4 (I4HD4 + 4)
+#define I4TMP (I4HD4 + 8)
typedef int64_t score_t; // type used for scores, rate, distortion
+// Note that MAX_COST is not the maximum allowed by sizeof(score_t),
+// in order to allow overflowing computations.
#define MAX_COST ((score_t)0x7fffffffffffffLL)
#define QFIX 17
#define BIAS(b) ((b) << (QFIX - 8))
// Fun fact: this is the _only_ line where we're actually being lossy and
// discarding bits.
-static WEBP_INLINE int QUANTDIV(int n, int iQ, int B) {
- return (n * iQ + B) >> QFIX;
+static WEBP_INLINE int QUANTDIV(uint32_t n, uint32_t iQ, uint32_t B) {
+ return (int)((n * iQ + B) >> QFIX);
}
-extern const uint8_t VP8Zigzag[16];
+
+// Uncomment the following to remove token-buffer code:
+// #define DISABLE_TOKEN_BUFFER
//------------------------------------------------------------------------------
// Headers
@@ -169,6 +131,8 @@ typedef uint32_t proba_t; // 16b + 16b
typedef uint8_t ProbaArray[NUM_CTX][NUM_PROBAS];
typedef proba_t StatsArray[NUM_CTX][NUM_PROBAS];
typedef uint16_t CostArray[NUM_CTX][MAX_VARIABLE_LEVEL + 1];
+typedef const uint16_t* (*CostArrayPtr)[NUM_CTX]; // for easy casting
+typedef const uint16_t* CostArrayMap[16][NUM_CTX];
typedef double LFStats[NUM_MB_SEGMENTS][MAX_LF_LEVELS]; // filter stats
typedef struct VP8Encoder VP8Encoder;
@@ -179,19 +143,20 @@ typedef struct {
int update_map_; // whether to update the segment map or not.
// must be 0 if there's only 1 segment.
int size_; // bit-cost for transmitting the segment map
-} VP8SegmentHeader;
+} VP8EncSegmentHeader;
// Struct collecting all frame-persistent probabilities.
typedef struct {
uint8_t segments_[3]; // probabilities for segment tree
uint8_t skip_proba_; // final probability of being skipped.
- ProbaArray coeffs_[NUM_TYPES][NUM_BANDS]; // 924 bytes
+ ProbaArray coeffs_[NUM_TYPES][NUM_BANDS]; // 1056 bytes
StatsArray stats_[NUM_TYPES][NUM_BANDS]; // 4224 bytes
- CostArray level_cost_[NUM_TYPES][NUM_BANDS]; // 11.4k
+ CostArray level_cost_[NUM_TYPES][NUM_BANDS]; // 13056 bytes
+ CostArrayMap remapped_costs_[NUM_TYPES]; // 1536 bytes
int dirty_; // if true, need to call VP8CalculateLevelCosts()
int use_skip_proba_; // Note: we always use skip_proba for now.
int nb_skip_; // number of skipped blocks
-} VP8Proba;
+} VP8EncProba;
// Filter parameters. Not actually used in the code (we don't perform
// the in-loop filtering), but filled from user's config
@@ -200,7 +165,7 @@ typedef struct {
int level_; // base filter level [0..63]
int sharpness_; // [0..7]
int i4x4_lf_delta_; // delta filter level for i4x4 relative to i16x16
-} VP8FilterHeader;
+} VP8EncFilterHeader;
//------------------------------------------------------------------------------
// Informations about the macroblocks.
@@ -217,8 +182,8 @@ typedef struct {
typedef struct VP8Matrix {
uint16_t q_[16]; // quantizer steps
uint16_t iq_[16]; // reciprocals, fixed point.
- uint16_t bias_[16]; // rounding bias
- uint16_t zthresh_[16]; // value under which a coefficient is zeroed
+ uint32_t bias_[16]; // rounding bias
+ uint32_t zthresh_[16]; // value below which a coefficient is zeroed
uint16_t sharpen_[16]; // frequency boosters for slight sharpening
} VP8Matrix;
@@ -229,16 +194,19 @@ typedef struct {
int beta_; // filter-susceptibility, range [0,255].
int quant_; // final segment quantizer.
int fstrength_; // final in-loop filtering strength
+ int max_edge_; // max edge delta (for filtering strength)
+ int min_disto_; // minimum distortion required to trigger filtering record
// reactivities
int lambda_i16_, lambda_i4_, lambda_uv_;
int lambda_mode_, lambda_trellis_, tlambda_;
int lambda_trellis_i16_, lambda_trellis_i4_, lambda_trellis_uv_;
} VP8SegmentInfo;
-// Handy transcient struct to accumulate score and info during RD-optimization
+// Handy transient struct to accumulate score and info during RD-optimization
// and mode evaluation.
typedef struct {
- score_t D, SD, R, score; // Distortion, spectral distortion, rate, score.
+ score_t D, SD; // Distortion, spectral distortion
+ score_t H, R, score; // header bits, rate, score.
int16_t y_dc_levels[16]; // Quantized levels for luma-DC, luma-AC, chroma.
int16_t y_ac_levels[16][16];
int16_t uv_levels[4 + 4][16];
@@ -252,12 +220,11 @@ typedef struct {
// right neighbouring data (samples, predictions, contexts, ...)
typedef struct {
int x_, y_; // current macroblock
- int y_offset_, uv_offset_; // offset to the luma / chroma planes
int y_stride_, uv_stride_; // respective strides
- uint8_t* yuv_in_; // borrowed from enc_ (for now)
- uint8_t* yuv_out_; // ''
- uint8_t* yuv_out2_; // ''
- uint8_t* yuv_p_; // ''
+ uint8_t* yuv_in_; // input samples
+ uint8_t* yuv_out_; // output samples
+ uint8_t* yuv_out2_; // secondary buffer swapped with yuv_out_.
+ uint8_t* yuv_p_; // scratch buffer for prediction
VP8Encoder* enc_; // back-pointer
VP8MBInfo* mb_; // current macroblock
VP8BitWriter* bw_; // current bit-writer
@@ -273,24 +240,44 @@ typedef struct {
uint64_t uv_bits_; // macroblock bit-cost for chroma
LFStats* lf_stats_; // filter stats (borrowed from enc_)
int do_trellis_; // if true, perform extra level optimisation
- int done_; // true when scan is finished
+ int count_down_; // number of mb still to be processed
+ int count_down0_; // starting counter value (for progress)
int percent0_; // saved initial progress percent
+
+ uint8_t* y_left_; // left luma samples (addressable from index -1 to 15).
+ uint8_t* u_left_; // left u samples (addressable from index -1 to 7)
+ uint8_t* v_left_; // left v samples (addressable from index -1 to 7)
+
+ uint8_t* y_top_; // top luma samples at position 'x_'
+ uint8_t* uv_top_; // top u/v samples at position 'x_', packed as 16 bytes
+
+ // memory for storing y/u/v_left_
+ uint8_t yuv_left_mem_[17 + 16 + 16 + 8 + WEBP_ALIGN_CST];
+ // memory for yuv_*
+ uint8_t yuv_mem_[3 * YUV_SIZE_ENC + PRED_SIZE_ENC + WEBP_ALIGN_CST];
} VP8EncIterator;
// in iterator.c
-// must be called first.
+// must be called first
void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it);
-// restart a scan.
+// restart a scan
void VP8IteratorReset(VP8EncIterator* const it);
-// import samples from source
-void VP8IteratorImport(const VP8EncIterator* const it);
+// reset iterator position to row 'y'
+void VP8IteratorSetRow(VP8EncIterator* const it, int y);
+// set count down (=number of iterations to go)
+void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down);
+// return true if iteration is finished
+int VP8IteratorIsDone(const VP8EncIterator* const it);
+// Import uncompressed samples from source.
+// If tmp_32 is not NULL, import boundary samples too.
+// tmp_32 is a 32-bytes scratch buffer that must be aligned in memory.
+void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32);
// export decimated samples
void VP8IteratorExport(const VP8EncIterator* const it);
-// go to next macroblock. Returns !done_. If *block_to_save is non-null, will
-// save the boundary values to top_/left_ arrays. block_to_save can be
-// it->yuv_out_ or it->yuv_in_.
-int VP8IteratorNext(VP8EncIterator* const it,
- const uint8_t* const block_to_save);
+// go to next macroblock. Returns false if not finished.
+int VP8IteratorNext(VP8EncIterator* const it);
+// save the yuv_out_ boundary values to top_/left_ arrays for next iterations.
+void VP8IteratorSaveBoundary(VP8EncIterator* const it);
// Report progression based on macroblock rows. Return 0 for user-abort request.
int VP8IteratorProgress(const VP8EncIterator* const it,
int final_delta_percent);
@@ -314,44 +301,43 @@ void VP8SetSegment(const VP8EncIterator* const it, int segment);
//------------------------------------------------------------------------------
// Paginated token buffer
-// WIP: #define USE_TOKEN_BUFFER
+typedef struct VP8Tokens VP8Tokens; // struct details in token.c
-#ifdef USE_TOKEN_BUFFER
+typedef struct {
+#if !defined(DISABLE_TOKEN_BUFFER)
+ VP8Tokens* pages_; // first page
+ VP8Tokens** last_page_; // last page
+ uint16_t* tokens_; // set to (*last_page_)->tokens_
+ int left_; // how many free tokens left before the page is full
+ int page_size_; // number of tokens per page
+#endif
+ int error_; // true in case of malloc error
+} VP8TBuffer;
-#define MAX_NUM_TOKEN 2048
+// initialize an empty buffer
+void VP8TBufferInit(VP8TBuffer* const b, int page_size);
+void VP8TBufferClear(VP8TBuffer* const b); // de-allocate pages memory
-typedef struct VP8Tokens VP8Tokens;
-struct VP8Tokens {
- uint16_t tokens_[MAX_NUM_TOKEN]; // bit#15: bit, bits 0..14: slot
- int left_;
- VP8Tokens* next_;
-};
+#if !defined(DISABLE_TOKEN_BUFFER)
-typedef struct {
- VP8Tokens* rows_;
- uint16_t* tokens_; // set to (*last_)->tokens_
- VP8Tokens** last_;
- int left_;
- int error_; // true in case of malloc error
-} VP8TBuffer;
+// Finalizes bitstream when probabilities are known.
+// Deletes the allocated token memory if final_pass is true.
+int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw,
+ const uint8_t* const probas, int final_pass);
-void VP8TBufferInit(VP8TBuffer* const b); // initialize an empty buffer
-int VP8TBufferNewPage(VP8TBuffer* const b); // allocate a new page
-void VP8TBufferClear(VP8TBuffer* const b); // de-allocate memory
+// record the coding of coefficients without knowing the probabilities yet
+int VP8RecordCoeffTokens(const int ctx, const int coeff_type,
+ int first, int last,
+ const int16_t* const coeffs,
+ VP8TBuffer* const tokens);
-int VP8EmitTokens(const VP8TBuffer* const b, VP8BitWriter* const bw,
- const uint8_t* const probas);
+// Estimate the final coded size given a set of 'probas'.
+size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas);
-static WEBP_INLINE int VP8AddToken(VP8TBuffer* const b,
- int bit, int proba_idx) {
- if (b->left_ > 0 || VP8TBufferNewPage(b)) {
- const int slot = --b->left_;
- b->tokens_[slot] = (bit << 15) | proba_idx;
- }
- return bit;
-}
+// unused for now
+void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats);
-#endif // USE_TOKEN_BUFFER
+#endif // !DISABLE_TOKEN_BUFFER
//------------------------------------------------------------------------------
// VP8Encoder
@@ -361,8 +347,8 @@ struct VP8Encoder {
WebPPicture* pic_; // input / output picture
// headers
- VP8FilterHeader filter_hdr_; // filtering information
- VP8SegmentHeader segment_hdr_; // segment information
+ VP8EncFilterHeader filter_hdr_; // filtering information
+ VP8EncSegmentHeader segment_hdr_; // segment information
int profile_; // VP8's profile, deduced from Config.
@@ -376,6 +362,7 @@ struct VP8Encoder {
// per-partition boolean decoders.
VP8BitWriter bw_; // part0
VP8BitWriter parts_[MAX_NUM_PARTITIONS]; // token partitions
+ VP8TBuffer tokens_; // token buffer
int percent_; // for progress
@@ -383,17 +370,13 @@ struct VP8Encoder {
int has_alpha_;
uint8_t* alpha_data_; // non-NULL if transparency is present
uint32_t alpha_data_size_;
-
- // enhancement layer
- int use_layer_;
- VP8BitWriter layer_bw_;
- uint8_t* layer_data_;
- size_t layer_data_size_;
+ WebPWorker alpha_worker_;
// quantization info (one set of DC/AC dequant factor per segment)
VP8SegmentInfo dqm_[NUM_MB_SEGMENTS];
int base_quant_; // nominal quantizer value. Only used
// for relative coding of segments' quant.
+ int alpha_; // global susceptibility (<=> complexity)
int uv_alpha_; // U/V quantization susceptibility
// global offset of quantizers, shared by all segments
int dq_y1_dc_;
@@ -401,34 +384,29 @@ struct VP8Encoder {
int dq_uv_dc_, dq_uv_ac_;
// probabilities and statistics
- VP8Proba proba_;
- uint64_t sse_[4]; // sum of Y/U/V/A squared errors for all macroblocks
- uint64_t sse_count_; // pixel count for the sse_[] stats
- int coded_size_;
- int residual_bytes_[3][4];
- int block_count_[3];
+ VP8EncProba proba_;
+ uint64_t sse_[4]; // sum of Y/U/V/A squared errors for all macroblocks
+ uint64_t sse_count_; // pixel count for the sse_[] stats
+ int coded_size_;
+ int residual_bytes_[3][4];
+ int block_count_[3];
// quality/speed settings
- int method_; // 0=fastest, 6=best/slowest.
- int rd_opt_level_; // Deduced from method_.
- int max_i4_header_bits_; // partition #0 safeness factor
+ int method_; // 0=fastest, 6=best/slowest.
+ VP8RDLevel rd_opt_level_; // Deduced from method_.
+ int max_i4_header_bits_; // partition #0 safeness factor
+ int thread_level_; // derived from config->thread_level
+ int do_search_; // derived from config->target_XXX
+ int use_tokens_; // if true, use token buffer
// Memory
VP8MBInfo* mb_info_; // contextual macroblock infos (mb_w_ + 1)
uint8_t* preds_; // predictions modes: (4*mb_w+1) * (4*mb_h+1)
uint32_t* nz_; // non-zero bit context: mb_w+1
- uint8_t* yuv_in_; // input samples
- uint8_t* yuv_out_; // output samples
- uint8_t* yuv_out2_; // secondary scratch out-buffer. swapped with yuv_out_.
- uint8_t* yuv_p_; // scratch buffer for prediction
- uint8_t *y_top_; // top luma samples.
- uint8_t *uv_top_; // top u/v samples.
- // U and V are packed into 16 pixels (8 U + 8 V)
- uint8_t *y_left_; // left luma samples (adressable from index -1 to 15).
- uint8_t *u_left_; // left u samples (adressable from index -1 to 7)
- uint8_t *v_left_; // left v samples (adressable from index -1 to 7)
-
- LFStats *lf_stats_; // autofilter stats (if NULL, autofilter is off)
+ uint8_t* y_top_; // top luma samples.
+ uint8_t* uv_top_; // top u/v samples.
+ // U and V are packed into 16 bytes (8 U + 8 V)
+ LFStats* lf_stats_; // autofilter stats (if NULL, autofilter is off)
};
//------------------------------------------------------------------------------
@@ -441,7 +419,7 @@ extern const uint8_t
// Reset the token probabilities to their initial (default) values
void VP8DefaultProbas(VP8Encoder* const enc);
// Write the token probabilities
-void VP8WriteProbas(VP8BitWriter* const bw, const VP8Proba* const probas);
+void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas);
// Writes the partition #0 modes (that is: all intra modes)
void VP8CodeIntraModes(VP8Encoder* const enc);
@@ -454,7 +432,11 @@ int VP8EncWrite(VP8Encoder* const enc);
void VP8EncFreeBitWriters(VP8Encoder* const enc);
// in frame.c
-extern const uint8_t VP8EncBands[16 + 1];
+extern const uint8_t VP8Cat3[];
+extern const uint8_t VP8Cat4[];
+extern const uint8_t VP8Cat5[];
+extern const uint8_t VP8Cat6[];
+
// Form all the four Intra16x16 predictions in the yuv_p_ cache
void VP8MakeLuma16Preds(const VP8EncIterator* const it);
// Form all the four Chroma8x8 predictions in the yuv_p_ cache
@@ -466,9 +448,9 @@ void VP8MakeIntra4Preds(const VP8EncIterator* const it);
int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd);
int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]);
int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd);
-// Main stat / coding passes
+// Main coding calls
int VP8EncLoop(VP8Encoder* const enc);
-int VP8StatLoop(VP8Encoder* const enc);
+int VP8EncTokenLoop(VP8Encoder* const enc);
// in webpenc.c
// Assign an error code to a picture. Return false for convenience.
@@ -485,18 +467,14 @@ int VP8EncAnalyze(VP8Encoder* const enc);
// Sets up segment's quantization values, base_quant_ and filter strengths.
void VP8SetSegmentParams(VP8Encoder* const enc, float quality);
// Pick best modes and fills the levels. Returns true if skipped.
-int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, int rd_opt);
+int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd,
+ VP8RDLevel rd_opt);
// in alpha.c
void VP8EncInitAlpha(VP8Encoder* const enc); // initialize alpha compression
+int VP8EncStartAlpha(VP8Encoder* const enc); // start alpha coding process
int VP8EncFinishAlpha(VP8Encoder* const enc); // finalize compressed data
-void VP8EncDeleteAlpha(VP8Encoder* const enc); // delete compressed data
-
- // in layer.c
-void VP8EncInitLayer(VP8Encoder* const enc); // init everything
-void VP8EncCodeLayerBlock(VP8EncIterator* it); // code one more macroblock
-int VP8EncFinishLayer(VP8Encoder* const enc); // finalize coding
-void VP8EncDeleteLayer(VP8Encoder* enc); // reclaim memory
+int VP8EncDeleteAlpha(VP8Encoder* const enc); // delete compressed data
// in filter.c
@@ -516,9 +494,38 @@ void VP8InitFilter(VP8EncIterator* const it);
void VP8StoreFilterStats(VP8EncIterator* const it);
void VP8AdjustFilterStrength(VP8EncIterator* const it);
+// returns the approximate filtering strength needed to smooth a edge
+// step of 'delta', given a sharpness parameter 'sharpness'.
+int VP8FilterStrengthFromDelta(int sharpness, int delta);
+
+ // misc utils for picture_*.c:
+
+// Remove reference to the ARGB/YUVA buffer (doesn't free anything).
+void WebPPictureResetBuffers(WebPPicture* const picture);
+
+// Allocates ARGB buffer of given dimension (previous one is always free'd).
+// Preserves the YUV(A) buffer. Returns false in case of error (invalid param,
+// out-of-memory).
+int WebPPictureAllocARGB(WebPPicture* const picture, int width, int height);
+
+// Allocates YUVA buffer of given dimension (previous one is always free'd).
+// Uses picture->csp to determine whether an alpha buffer is needed.
+// Preserves the ARGB buffer.
+// Returns false in case of error (invalid param, out-of-memory).
+int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height);
+
+ // in near_lossless.c
+// Near lossless preprocessing in RGB color-space.
+int VP8ApplyNearLossless(int xsize, int ysize, uint32_t* argb, int quality);
+// Near lossless adjustment for predictors.
+void VP8ApplyNearLosslessPredict(int xsize, int ysize, int pred_bits,
+ const uint32_t* argb_orig,
+ uint32_t* argb, uint32_t* argb_scratch,
+ const uint32_t* const transform_data,
+ int quality, int subtract_green);
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/enc/vp8l.c b/drivers/webp/enc/vp8l.c
index f4eb6e783f..284995e830 100644
--- a/drivers/webp/enc/vp8l.c
+++ b/drivers/webp/enc/vp8l.c
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// main entry for the lossless encoder.
@@ -11,7 +13,6 @@
//
#include <assert.h>
-#include <stdio.h>
#include <stdlib.h>
#include "./backward_references.h"
@@ -21,28 +22,107 @@
#include "../utils/bit_writer.h"
#include "../utils/huffman_encode.h"
#include "../utils/utils.h"
-#include "../format_constants.h"
+#include "webp/format_constants.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+#include "./delta_palettization.h"
#define PALETTE_KEY_RIGHT_SHIFT 22 // Key for 1K buffer.
-#define MAX_HUFF_IMAGE_SIZE (16 * 1024 * 1024)
-#define MAX_COLORS_FOR_GRAPH 64
+// Maximum number of histogram images (sub-blocks).
+#define MAX_HUFF_IMAGE_SIZE 2600
-// -----------------------------------------------------------------------------
-// Palette
+// Palette reordering for smaller sum of deltas (and for smaller storage).
-static int CompareColors(const void* p1, const void* p2) {
+static int PaletteCompareColorsForQsort(const void* p1, const void* p2) {
const uint32_t a = *(const uint32_t*)p1;
const uint32_t b = *(const uint32_t*)p2;
- return (a < b) ? -1 : (a > b) ? 1 : 0;
+ assert(a != b);
+ return (a < b) ? -1 : 1;
+}
+
+static WEBP_INLINE uint32_t PaletteComponentDistance(uint32_t v) {
+ return (v <= 128) ? v : (256 - v);
+}
+
+// Computes a value that is related to the entropy created by the
+// palette entry diff.
+//
+// Note that the last & 0xff is a no-operation in the next statement, but
+// removed by most compilers and is here only for regularity of the code.
+static WEBP_INLINE uint32_t PaletteColorDistance(uint32_t col1, uint32_t col2) {
+ const uint32_t diff = VP8LSubPixels(col1, col2);
+ const int kMoreWeightForRGBThanForAlpha = 9;
+ uint32_t score;
+ score = PaletteComponentDistance((diff >> 0) & 0xff);
+ score += PaletteComponentDistance((diff >> 8) & 0xff);
+ score += PaletteComponentDistance((diff >> 16) & 0xff);
+ score *= kMoreWeightForRGBThanForAlpha;
+ score += PaletteComponentDistance((diff >> 24) & 0xff);
+ return score;
+}
+
+static WEBP_INLINE void SwapColor(uint32_t* const col1, uint32_t* const col2) {
+ const uint32_t tmp = *col1;
+ *col1 = *col2;
+ *col2 = tmp;
+}
+
+static void GreedyMinimizeDeltas(uint32_t palette[], int num_colors) {
+ // Find greedily always the closest color of the predicted color to minimize
+ // deltas in the palette. This reduces storage needs since the
+ // palette is stored with delta encoding.
+ uint32_t predict = 0x00000000;
+ int i, k;
+ for (i = 0; i < num_colors; ++i) {
+ int best_ix = i;
+ uint32_t best_score = ~0U;
+ for (k = i; k < num_colors; ++k) {
+ const uint32_t cur_score = PaletteColorDistance(palette[k], predict);
+ if (best_score > cur_score) {
+ best_score = cur_score;
+ best_ix = k;
+ }
+ }
+ SwapColor(&palette[best_ix], &palette[i]);
+ predict = palette[i];
+ }
+}
+
+// The palette has been sorted by alpha. This function checks if the other
+// components of the palette have a monotonic development with regards to
+// position in the palette. If all have monotonic development, there is
+// no benefit to re-organize them greedily. A monotonic development
+// would be spotted in green-only situations (like lossy alpha) or gray-scale
+// images.
+static int PaletteHasNonMonotonousDeltas(uint32_t palette[], int num_colors) {
+ uint32_t predict = 0x000000;
+ int i;
+ uint8_t sign_found = 0x00;
+ for (i = 0; i < num_colors; ++i) {
+ const uint32_t diff = VP8LSubPixels(palette[i], predict);
+ const uint8_t rd = (diff >> 16) & 0xff;
+ const uint8_t gd = (diff >> 8) & 0xff;
+ const uint8_t bd = (diff >> 0) & 0xff;
+ if (rd != 0x00) {
+ sign_found |= (rd < 0x80) ? 1 : 2;
+ }
+ if (gd != 0x00) {
+ sign_found |= (gd < 0x80) ? 8 : 16;
+ }
+ if (bd != 0x00) {
+ sign_found |= (bd < 0x80) ? 64 : 128;
+ }
+ predict = palette[i];
+ }
+ return (sign_found & (sign_found << 1)) != 0; // two consequent signs.
}
+// -----------------------------------------------------------------------------
+// Palette
+
// If number of colors in the image is less than or equal to MAX_PALETTE_SIZE,
// creates a palette and returns true, else returns false.
static int AnalyzeAndCreatePalette(const WebPPicture* const pic,
+ int low_effort,
uint32_t palette[MAX_PALETTE_SIZE],
int* const palette_size) {
int i, x, y, key;
@@ -85,7 +165,7 @@ static int AnalyzeAndCreatePalette(const WebPPicture* const pic,
argb += pic->argb_stride;
}
- // TODO(skal): could we reuse in_use[] to speed up ApplyPalette()?
+ // TODO(skal): could we reuse in_use[] to speed up EncodePalette()?
num_colors = 0;
for (i = 0; i < (int)(sizeof(in_use) / sizeof(in_use[0])); ++i) {
if (in_use[i]) {
@@ -93,106 +173,272 @@ static int AnalyzeAndCreatePalette(const WebPPicture* const pic,
++num_colors;
}
}
-
- qsort(palette, num_colors, sizeof(*palette), CompareColors);
*palette_size = num_colors;
+ qsort(palette, num_colors, sizeof(*palette), PaletteCompareColorsForQsort);
+ if (!low_effort && PaletteHasNonMonotonousDeltas(palette, num_colors)) {
+ GreedyMinimizeDeltas(palette, num_colors);
+ }
return 1;
}
+// These five modes are evaluated and their respective entropy is computed.
+typedef enum {
+ kDirect = 0,
+ kSpatial = 1,
+ kSubGreen = 2,
+ kSpatialSubGreen = 3,
+ kPalette = 4,
+ kNumEntropyIx = 5
+} EntropyIx;
+
+typedef enum {
+ kHistoAlpha = 0,
+ kHistoAlphaPred,
+ kHistoGreen,
+ kHistoGreenPred,
+ kHistoRed,
+ kHistoRedPred,
+ kHistoBlue,
+ kHistoBluePred,
+ kHistoRedSubGreen,
+ kHistoRedPredSubGreen,
+ kHistoBlueSubGreen,
+ kHistoBluePredSubGreen,
+ kHistoPalette,
+ kHistoTotal // Must be last.
+} HistoIx;
+
+static void AddSingleSubGreen(uint32_t p, uint32_t* r, uint32_t* b) {
+ const uint32_t green = p >> 8; // The upper bits are masked away later.
+ ++r[((p >> 16) - green) & 0xff];
+ ++b[(p - green) & 0xff];
+}
+
+static void AddSingle(uint32_t p,
+ uint32_t* a, uint32_t* r, uint32_t* g, uint32_t* b) {
+ ++a[p >> 24];
+ ++r[(p >> 16) & 0xff];
+ ++g[(p >> 8) & 0xff];
+ ++b[(p & 0xff)];
+}
+
static int AnalyzeEntropy(const uint32_t* argb,
int width, int height, int argb_stride,
- double* const nonpredicted_bits,
- double* const predicted_bits) {
- int x, y;
- const uint32_t* last_line = NULL;
- uint32_t last_pix = argb[0]; // so we're sure that pix_diff == 0
-
- VP8LHistogram* nonpredicted = NULL;
- VP8LHistogram* predicted =
- (VP8LHistogram*)malloc(2 * sizeof(*predicted));
- if (predicted == NULL) return 0;
- nonpredicted = predicted + 1;
-
- VP8LHistogramInit(predicted, 0);
- VP8LHistogramInit(nonpredicted, 0);
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; ++x) {
- const uint32_t pix = argb[x];
- const uint32_t pix_diff = VP8LSubPixels(pix, last_pix);
- if (pix_diff == 0) continue;
- if (last_line != NULL && pix == last_line[x]) {
- continue;
+ int use_palette,
+ EntropyIx* const min_entropy_ix,
+ int* const red_and_blue_always_zero) {
+ // Allocate histogram set with cache_bits = 0.
+ uint32_t* const histo =
+ (uint32_t*)WebPSafeCalloc(kHistoTotal, sizeof(*histo) * 256);
+ if (histo != NULL) {
+ int i, x, y;
+ const uint32_t* prev_row = argb;
+ const uint32_t* curr_row = argb + argb_stride;
+ for (y = 1; y < height; ++y) {
+ uint32_t prev_pix = curr_row[0];
+ for (x = 1; x < width; ++x) {
+ const uint32_t pix = curr_row[x];
+ const uint32_t pix_diff = VP8LSubPixels(pix, prev_pix);
+ if ((pix_diff == 0) || (pix == prev_row[x])) continue;
+ prev_pix = pix;
+ AddSingle(pix,
+ &histo[kHistoAlpha * 256],
+ &histo[kHistoRed * 256],
+ &histo[kHistoGreen * 256],
+ &histo[kHistoBlue * 256]);
+ AddSingle(pix_diff,
+ &histo[kHistoAlphaPred * 256],
+ &histo[kHistoRedPred * 256],
+ &histo[kHistoGreenPred * 256],
+ &histo[kHistoBluePred * 256]);
+ AddSingleSubGreen(pix,
+ &histo[kHistoRedSubGreen * 256],
+ &histo[kHistoBlueSubGreen * 256]);
+ AddSingleSubGreen(pix_diff,
+ &histo[kHistoRedPredSubGreen * 256],
+ &histo[kHistoBluePredSubGreen * 256]);
+ {
+ // Approximate the palette by the entropy of the multiplicative hash.
+ const int hash = ((pix + (pix >> 19)) * 0x39c5fba7) >> 24;
+ ++histo[kHistoPalette * 256 + (hash & 0xff)];
+ }
+ }
+ prev_row = curr_row;
+ curr_row += argb_stride;
+ }
+ {
+ double entropy_comp[kHistoTotal];
+ double entropy[kNumEntropyIx];
+ EntropyIx k;
+ EntropyIx last_mode_to_analyze =
+ use_palette ? kPalette : kSpatialSubGreen;
+ int j;
+ // Let's add one zero to the predicted histograms. The zeros are removed
+ // too efficiently by the pix_diff == 0 comparison, at least one of the
+ // zeros is likely to exist.
+ ++histo[kHistoRedPredSubGreen * 256];
+ ++histo[kHistoBluePredSubGreen * 256];
+ ++histo[kHistoRedPred * 256];
+ ++histo[kHistoGreenPred * 256];
+ ++histo[kHistoBluePred * 256];
+ ++histo[kHistoAlphaPred * 256];
+
+ for (j = 0; j < kHistoTotal; ++j) {
+ entropy_comp[j] = VP8LBitsEntropy(&histo[j * 256], 256, NULL);
+ }
+ entropy[kDirect] = entropy_comp[kHistoAlpha] +
+ entropy_comp[kHistoRed] +
+ entropy_comp[kHistoGreen] +
+ entropy_comp[kHistoBlue];
+ entropy[kSpatial] = entropy_comp[kHistoAlphaPred] +
+ entropy_comp[kHistoRedPred] +
+ entropy_comp[kHistoGreenPred] +
+ entropy_comp[kHistoBluePred];
+ entropy[kSubGreen] = entropy_comp[kHistoAlpha] +
+ entropy_comp[kHistoRedSubGreen] +
+ entropy_comp[kHistoGreen] +
+ entropy_comp[kHistoBlueSubGreen];
+ entropy[kSpatialSubGreen] = entropy_comp[kHistoAlphaPred] +
+ entropy_comp[kHistoRedPredSubGreen] +
+ entropy_comp[kHistoGreenPred] +
+ entropy_comp[kHistoBluePredSubGreen];
+ // Palette mode seems more efficient in a breakeven case. Bias with 1.0.
+ entropy[kPalette] = entropy_comp[kHistoPalette] - 1.0;
+
+ *min_entropy_ix = kDirect;
+ for (k = kDirect + 1; k <= last_mode_to_analyze; ++k) {
+ if (entropy[*min_entropy_ix] > entropy[k]) {
+ *min_entropy_ix = k;
+ }
}
- last_pix = pix;
+ *red_and_blue_always_zero = 1;
+ // Let's check if the histogram of the chosen entropy mode has
+ // non-zero red and blue values. If all are zero, we can later skip
+ // the cross color optimization.
{
- const PixOrCopy pix_token = PixOrCopyCreateLiteral(pix);
- const PixOrCopy pix_diff_token = PixOrCopyCreateLiteral(pix_diff);
- VP8LHistogramAddSinglePixOrCopy(nonpredicted, &pix_token);
- VP8LHistogramAddSinglePixOrCopy(predicted, &pix_diff_token);
+ static const uint8_t kHistoPairs[5][2] = {
+ { kHistoRed, kHistoBlue },
+ { kHistoRedPred, kHistoBluePred },
+ { kHistoRedSubGreen, kHistoBlueSubGreen },
+ { kHistoRedPredSubGreen, kHistoBluePredSubGreen },
+ { kHistoRed, kHistoBlue }
+ };
+ const uint32_t* const red_histo =
+ &histo[256 * kHistoPairs[*min_entropy_ix][0]];
+ const uint32_t* const blue_histo =
+ &histo[256 * kHistoPairs[*min_entropy_ix][1]];
+ for (i = 1; i < 256; ++i) {
+ if ((red_histo[i] | blue_histo[i]) != 0) {
+ *red_and_blue_always_zero = 0;
+ break;
+ }
+ }
}
}
- last_line = argb;
- argb += argb_stride;
+ free(histo);
+ return 1;
+ } else {
+ return 0;
}
- *nonpredicted_bits = VP8LHistogramEstimateBitsBulk(nonpredicted);
- *predicted_bits = VP8LHistogramEstimateBitsBulk(predicted);
- free(predicted);
- return 1;
}
-static int VP8LEncAnalyze(VP8LEncoder* const enc, WebPImageHint image_hint) {
+static int GetHistoBits(int method, int use_palette, int width, int height) {
+ // Make tile size a function of encoding method (Range: 0 to 6).
+ int histo_bits = (use_palette ? 9 : 7) - method;
+ while (1) {
+ const int huff_image_size = VP8LSubSampleSize(width, histo_bits) *
+ VP8LSubSampleSize(height, histo_bits);
+ if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break;
+ ++histo_bits;
+ }
+ return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS :
+ (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits;
+}
+
+static int GetTransformBits(int method, int histo_bits) {
+ const int max_transform_bits = (method < 4) ? 6 : (method > 4) ? 4 : 5;
+ return (histo_bits > max_transform_bits) ? max_transform_bits : histo_bits;
+}
+
+static int AnalyzeAndInit(VP8LEncoder* const enc) {
const WebPPicture* const pic = enc->pic_;
+ const int width = pic->width;
+ const int height = pic->height;
+ const int pix_cnt = width * height;
+ const WebPConfig* const config = enc->config_;
+ const int method = config->method;
+ const int low_effort = (config->method == 0);
+ // we round the block size up, so we're guaranteed to have
+ // at max MAX_REFS_BLOCK_PER_IMAGE blocks used:
+ int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1;
assert(pic != NULL && pic->argb != NULL);
+ enc->use_cross_color_ = 0;
+ enc->use_predict_ = 0;
+ enc->use_subtract_green_ = 0;
enc->use_palette_ =
- AnalyzeAndCreatePalette(pic, enc->palette_, &enc->palette_size_);
-
- if (image_hint == WEBP_HINT_GRAPH) {
- if (enc->use_palette_ && enc->palette_size_ < MAX_COLORS_FOR_GRAPH) {
- enc->use_palette_ = 0;
+ AnalyzeAndCreatePalette(pic, low_effort,
+ enc->palette_, &enc->palette_size_);
+
+ // TODO(jyrki): replace the decision to be based on an actual estimate
+ // of entropy, or even spatial variance of entropy.
+ enc->histo_bits_ = GetHistoBits(method, enc->use_palette_,
+ pic->width, pic->height);
+ enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_);
+
+ if (low_effort) {
+ // AnalyzeEntropy is somewhat slow.
+ enc->use_predict_ = !enc->use_palette_;
+ enc->use_subtract_green_ = !enc->use_palette_;
+ enc->use_cross_color_ = 0;
+ } else {
+ int red_and_blue_always_zero;
+ EntropyIx min_entropy_ix;
+ if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride,
+ enc->use_palette_, &min_entropy_ix,
+ &red_and_blue_always_zero)) {
+ return 0;
}
+ enc->use_palette_ = (min_entropy_ix == kPalette);
+ enc->use_subtract_green_ =
+ (min_entropy_ix == kSubGreen) || (min_entropy_ix == kSpatialSubGreen);
+ enc->use_predict_ =
+ (min_entropy_ix == kSpatial) || (min_entropy_ix == kSpatialSubGreen);
+ enc->use_cross_color_ = red_and_blue_always_zero ? 0 : enc->use_predict_;
}
- if (!enc->use_palette_) {
- if (image_hint == WEBP_HINT_PHOTO) {
- enc->use_predict_ = 1;
- enc->use_cross_color_ = 1;
- } else {
- double non_pred_entropy, pred_entropy;
- if (!AnalyzeEntropy(pic->argb, pic->width, pic->height, pic->argb_stride,
- &non_pred_entropy, &pred_entropy)) {
- return 0;
- }
- if (pred_entropy < 0.95 * non_pred_entropy) {
- enc->use_predict_ = 1;
- // TODO(vikasa): Observed some correlation of cross_color transform with
- // predict. Need to investigate this further and add separate heuristic
- // for setting use_cross_color flag.
- enc->use_cross_color_ = 1;
- }
- }
- }
+ if (!VP8LHashChainInit(&enc->hash_chain_, pix_cnt)) return 0;
+
+ // palette-friendly input typically uses less literals
+ // -> reduce block size a bit
+ if (enc->use_palette_) refs_block_size /= 2;
+ VP8LBackwardRefsInit(&enc->refs_[0], refs_block_size);
+ VP8LBackwardRefsInit(&enc->refs_[1], refs_block_size);
return 1;
}
+// Returns false in case of memory error.
static int GetHuffBitLengthsAndCodes(
const VP8LHistogramSet* const histogram_image,
HuffmanTreeCode* const huffman_codes) {
int i, k;
- int ok = 1;
+ int ok = 0;
uint64_t total_length_size = 0;
uint8_t* mem_buf = NULL;
const int histogram_image_size = histogram_image->size;
+ int max_num_symbols = 0;
+ uint8_t* buf_rle = NULL;
+ HuffmanTree* huff_tree = NULL;
// Iterate over all histograms and get the aggregate number of codes used.
for (i = 0; i < histogram_image_size; ++i) {
const VP8LHistogram* const histo = histogram_image->histograms[i];
HuffmanTreeCode* const codes = &huffman_codes[5 * i];
for (k = 0; k < 5; ++k) {
- const int num_symbols = (k == 0) ? VP8LHistogramNumCodes(histo)
- : (k == 4) ? NUM_DISTANCE_CODES
- : 256;
+ const int num_symbols =
+ (k == 0) ? VP8LHistogramNumCodes(histo->palette_code_bits_) :
+ (k == 4) ? NUM_DISTANCE_CODES : 256;
codes[k].num_symbols = num_symbols;
total_length_size += num_symbols;
}
@@ -204,10 +450,8 @@ static int GetHuffBitLengthsAndCodes(
uint8_t* lengths;
mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size,
sizeof(*lengths) + sizeof(*codes));
- if (mem_buf == NULL) {
- ok = 0;
- goto End;
- }
+ if (mem_buf == NULL) goto End;
+
codes = (uint16_t*)mem_buf;
lengths = (uint8_t*)&codes[total_length_size];
for (i = 0; i < 5 * histogram_image_size; ++i) {
@@ -216,22 +460,35 @@ static int GetHuffBitLengthsAndCodes(
huffman_codes[i].code_lengths = lengths;
codes += bit_length;
lengths += bit_length;
+ if (max_num_symbols < bit_length) {
+ max_num_symbols = bit_length;
+ }
}
}
+ buf_rle = (uint8_t*)WebPSafeMalloc(1ULL, max_num_symbols);
+ huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * max_num_symbols,
+ sizeof(*huff_tree));
+ if (buf_rle == NULL || huff_tree == NULL) goto End;
+
// Create Huffman trees.
for (i = 0; i < histogram_image_size; ++i) {
HuffmanTreeCode* const codes = &huffman_codes[5 * i];
VP8LHistogram* const histo = histogram_image->histograms[i];
- ok = ok && VP8LCreateHuffmanTree(histo->literal_, 15, codes + 0);
- ok = ok && VP8LCreateHuffmanTree(histo->red_, 15, codes + 1);
- ok = ok && VP8LCreateHuffmanTree(histo->blue_, 15, codes + 2);
- ok = ok && VP8LCreateHuffmanTree(histo->alpha_, 15, codes + 3);
- ok = ok && VP8LCreateHuffmanTree(histo->distance_, 15, codes + 4);
+ VP8LCreateHuffmanTree(histo->literal_, 15, buf_rle, huff_tree, codes + 0);
+ VP8LCreateHuffmanTree(histo->red_, 15, buf_rle, huff_tree, codes + 1);
+ VP8LCreateHuffmanTree(histo->blue_, 15, buf_rle, huff_tree, codes + 2);
+ VP8LCreateHuffmanTree(histo->alpha_, 15, buf_rle, huff_tree, codes + 3);
+ VP8LCreateHuffmanTree(histo->distance_, 15, buf_rle, huff_tree, codes + 4);
}
-
+ ok = 1;
End:
- if (!ok) free(mem_buf);
+ WebPSafeFree(huff_tree);
+ WebPSafeFree(buf_rle);
+ if (!ok) {
+ WebPSafeFree(mem_buf);
+ memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes));
+ }
return ok;
}
@@ -251,9 +508,9 @@ static void StoreHuffmanTreeOfHuffmanTreeToBitMask(
break;
}
}
- VP8LWriteBits(bw, 4, codes_to_store - 4);
+ VP8LPutBits(bw, codes_to_store - 4, 4);
for (i = 0; i < codes_to_store; ++i) {
- VP8LWriteBits(bw, 3, code_length_bitdepth[kStorageOrder[i]]);
+ VP8LPutBits(bw, code_length_bitdepth[kStorageOrder[i]], 3);
}
}
@@ -281,49 +538,46 @@ static void StoreHuffmanTreeToBitMask(
for (i = 0; i < num_tokens; ++i) {
const int ix = tokens[i].code;
const int extra_bits = tokens[i].extra_bits;
- VP8LWriteBits(bw, huffman_code->code_lengths[ix], huffman_code->codes[ix]);
+ VP8LPutBits(bw, huffman_code->codes[ix], huffman_code->code_lengths[ix]);
switch (ix) {
case 16:
- VP8LWriteBits(bw, 2, extra_bits);
+ VP8LPutBits(bw, extra_bits, 2);
break;
case 17:
- VP8LWriteBits(bw, 3, extra_bits);
+ VP8LPutBits(bw, extra_bits, 3);
break;
case 18:
- VP8LWriteBits(bw, 7, extra_bits);
+ VP8LPutBits(bw, extra_bits, 7);
break;
}
}
}
-static int StoreFullHuffmanCode(VP8LBitWriter* const bw,
- const HuffmanTreeCode* const tree) {
- int ok = 0;
+// 'huff_tree' and 'tokens' are pre-alloacted buffers.
+static void StoreFullHuffmanCode(VP8LBitWriter* const bw,
+ HuffmanTree* const huff_tree,
+ HuffmanTreeToken* const tokens,
+ const HuffmanTreeCode* const tree) {
uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 };
uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 };
const int max_tokens = tree->num_symbols;
int num_tokens;
HuffmanTreeCode huffman_code;
- HuffmanTreeToken* const tokens =
- (HuffmanTreeToken*)WebPSafeMalloc((uint64_t)max_tokens, sizeof(*tokens));
- if (tokens == NULL) return 0;
-
huffman_code.num_symbols = CODE_LENGTH_CODES;
huffman_code.code_lengths = code_length_bitdepth;
huffman_code.codes = code_length_bitdepth_symbols;
- VP8LWriteBits(bw, 1, 0);
+ VP8LPutBits(bw, 0, 1);
num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens);
{
- int histogram[CODE_LENGTH_CODES] = { 0 };
+ uint32_t histogram[CODE_LENGTH_CODES] = { 0 };
+ uint8_t buf_rle[CODE_LENGTH_CODES] = { 0 };
int i;
for (i = 0; i < num_tokens; ++i) {
++histogram[tokens[i].code];
}
- if (!VP8LCreateHuffmanTree(histogram, 7, &huffman_code)) {
- goto End;
- }
+ VP8LCreateHuffmanTree(histogram, 7, buf_rle, huff_tree, &huffman_code);
}
StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth);
@@ -350,24 +604,23 @@ static int StoreFullHuffmanCode(VP8LBitWriter* const bw,
}
write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12);
length = write_trimmed_length ? trimmed_length : num_tokens;
- VP8LWriteBits(bw, 1, write_trimmed_length);
+ VP8LPutBits(bw, write_trimmed_length, 1);
if (write_trimmed_length) {
const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1);
const int nbitpairs = (nbits == 0) ? 1 : (nbits + 1) / 2;
- VP8LWriteBits(bw, 3, nbitpairs - 1);
+ VP8LPutBits(bw, nbitpairs - 1, 3);
assert(trimmed_length >= 2);
- VP8LWriteBits(bw, nbitpairs * 2, trimmed_length - 2);
+ VP8LPutBits(bw, trimmed_length - 2, nbitpairs * 2);
}
StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code);
}
- ok = 1;
- End:
- free(tokens);
- return ok;
}
-static int StoreHuffmanCode(VP8LBitWriter* const bw,
- const HuffmanTreeCode* const huffman_code) {
+// 'huff_tree' and 'tokens' are pre-alloacted buffers.
+static void StoreHuffmanCode(VP8LBitWriter* const bw,
+ HuffmanTree* const huff_tree,
+ HuffmanTreeToken* const tokens,
+ const HuffmanTreeCode* const huffman_code) {
int i;
int count = 0;
int symbols[2] = { 0, 0 };
@@ -384,163 +637,248 @@ static int StoreHuffmanCode(VP8LBitWriter* const bw,
if (count == 0) { // emit minimal tree for empty cases
// bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0
- VP8LWriteBits(bw, 4, 0x01);
- return 1;
+ VP8LPutBits(bw, 0x01, 4);
} else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) {
- VP8LWriteBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols.
- VP8LWriteBits(bw, 1, count - 1);
+ VP8LPutBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols.
+ VP8LPutBits(bw, count - 1, 1);
if (symbols[0] <= 1) {
- VP8LWriteBits(bw, 1, 0); // Code bit for small (1 bit) symbol value.
- VP8LWriteBits(bw, 1, symbols[0]);
+ VP8LPutBits(bw, 0, 1); // Code bit for small (1 bit) symbol value.
+ VP8LPutBits(bw, symbols[0], 1);
} else {
- VP8LWriteBits(bw, 1, 1);
- VP8LWriteBits(bw, 8, symbols[0]);
+ VP8LPutBits(bw, 1, 1);
+ VP8LPutBits(bw, symbols[0], 8);
}
if (count == 2) {
- VP8LWriteBits(bw, 8, symbols[1]);
+ VP8LPutBits(bw, symbols[1], 8);
}
- return 1;
} else {
- return StoreFullHuffmanCode(bw, huffman_code);
+ StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code);
}
}
-static void WriteHuffmanCode(VP8LBitWriter* const bw,
- const HuffmanTreeCode* const code, int index) {
- const int depth = code->code_lengths[index];
- const int symbol = code->codes[index];
- VP8LWriteBits(bw, depth, symbol);
+static WEBP_INLINE void WriteHuffmanCode(VP8LBitWriter* const bw,
+ const HuffmanTreeCode* const code,
+ int code_index) {
+ const int depth = code->code_lengths[code_index];
+ const int symbol = code->codes[code_index];
+ VP8LPutBits(bw, symbol, depth);
}
-static void StoreImageToBitMask(
+static WEBP_INLINE void WriteHuffmanCodeWithExtraBits(
+ VP8LBitWriter* const bw,
+ const HuffmanTreeCode* const code,
+ int code_index,
+ int bits,
+ int n_bits) {
+ const int depth = code->code_lengths[code_index];
+ const int symbol = code->codes[code_index];
+ VP8LPutBits(bw, (bits << depth) | symbol, depth + n_bits);
+}
+
+static WebPEncodingError StoreImageToBitMask(
VP8LBitWriter* const bw, int width, int histo_bits,
- const VP8LBackwardRefs* const refs,
+ VP8LBackwardRefs* const refs,
const uint16_t* histogram_symbols,
const HuffmanTreeCode* const huffman_codes) {
+ const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1;
+ const int tile_mask = (histo_bits == 0) ? 0 : -(1 << histo_bits);
// x and y trace the position in the image.
int x = 0;
int y = 0;
- const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1;
- int i;
- for (i = 0; i < refs->size; ++i) {
- const PixOrCopy* const v = &refs->refs[i];
- const int histogram_ix = histogram_symbols[histo_bits ?
- (y >> histo_bits) * histo_xsize +
- (x >> histo_bits) : 0];
- const HuffmanTreeCode* const codes = huffman_codes + 5 * histogram_ix;
- if (PixOrCopyIsCacheIdx(v)) {
- const int code = PixOrCopyCacheIdx(v);
- const int literal_ix = 256 + NUM_LENGTH_CODES + code;
- WriteHuffmanCode(bw, codes, literal_ix);
- } else if (PixOrCopyIsLiteral(v)) {
+ int tile_x = x & tile_mask;
+ int tile_y = y & tile_mask;
+ int histogram_ix = histogram_symbols[0];
+ const HuffmanTreeCode* codes = huffman_codes + 5 * histogram_ix;
+ VP8LRefsCursor c = VP8LRefsCursorInit(refs);
+ while (VP8LRefsCursorOk(&c)) {
+ const PixOrCopy* const v = c.cur_pos;
+ if ((tile_x != (x & tile_mask)) || (tile_y != (y & tile_mask))) {
+ tile_x = x & tile_mask;
+ tile_y = y & tile_mask;
+ histogram_ix = histogram_symbols[(y >> histo_bits) * histo_xsize +
+ (x >> histo_bits)];
+ codes = huffman_codes + 5 * histogram_ix;
+ }
+ if (PixOrCopyIsLiteral(v)) {
static const int order[] = { 1, 2, 0, 3 };
int k;
for (k = 0; k < 4; ++k) {
const int code = PixOrCopyLiteral(v, order[k]);
WriteHuffmanCode(bw, codes + k, code);
}
+ } else if (PixOrCopyIsCacheIdx(v)) {
+ const int code = PixOrCopyCacheIdx(v);
+ const int literal_ix = 256 + NUM_LENGTH_CODES + code;
+ WriteHuffmanCode(bw, codes, literal_ix);
} else {
int bits, n_bits;
- int code, distance;
+ int code;
- PrefixEncode(v->len, &code, &n_bits, &bits);
- WriteHuffmanCode(bw, codes, 256 + code);
- VP8LWriteBits(bw, n_bits, bits);
+ const int distance = PixOrCopyDistance(v);
+ VP8LPrefixEncode(v->len, &code, &n_bits, &bits);
+ WriteHuffmanCodeWithExtraBits(bw, codes, 256 + code, bits, n_bits);
- distance = PixOrCopyDistance(v);
- PrefixEncode(distance, &code, &n_bits, &bits);
+ // Don't write the distance with the extra bits code since
+ // the distance can be up to 18 bits of extra bits, and the prefix
+ // 15 bits, totaling to 33, and our PutBits only supports up to 32 bits.
+ // TODO(jyrki): optimize this further.
+ VP8LPrefixEncode(distance, &code, &n_bits, &bits);
WriteHuffmanCode(bw, codes + 4, code);
- VP8LWriteBits(bw, n_bits, bits);
+ VP8LPutBits(bw, bits, n_bits);
}
x += PixOrCopyLength(v);
while (x >= width) {
x -= width;
++y;
}
+ VP8LRefsCursorNext(&c);
}
+ return bw->error_ ? VP8_ENC_ERROR_OUT_OF_MEMORY : VP8_ENC_OK;
}
// Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31
-static int EncodeImageNoHuffman(VP8LBitWriter* const bw,
- const uint32_t* const argb,
- int width, int height, int quality) {
+static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw,
+ const uint32_t* const argb,
+ VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs refs_array[2],
+ int width, int height,
+ int quality) {
int i;
- int ok = 0;
- VP8LBackwardRefs refs;
+ int max_tokens = 0;
+ WebPEncodingError err = VP8_ENC_OK;
+ VP8LBackwardRefs* refs;
+ HuffmanTreeToken* tokens = NULL;
HuffmanTreeCode huffman_codes[5] = { { 0, NULL, NULL } };
const uint16_t histogram_symbols[1] = { 0 }; // only one tree, one symbol
- VP8LHistogramSet* const histogram_image = VP8LAllocateHistogramSet(1, 0);
- if (histogram_image == NULL) return 0;
+ int cache_bits = 0;
+ VP8LHistogramSet* histogram_image = NULL;
+ HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc(
+ 3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree));
+ if (huff_tree == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
// Calculate backward references from ARGB image.
- if (!VP8LGetBackwardReferences(width, height, argb, quality, 0, 1, &refs)) {
+ refs = VP8LGetBackwardReferences(width, height, argb, quality, 0, &cache_bits,
+ hash_chain, refs_array);
+ if (refs == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
goto Error;
}
+ histogram_image = VP8LAllocateHistogramSet(1, cache_bits);
+ if (histogram_image == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+
// Build histogram image and symbols from backward references.
- VP8LHistogramStoreRefs(&refs, histogram_image->histograms[0]);
+ VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]);
// Create Huffman bit lengths and codes for each histogram image.
assert(histogram_image->size == 1);
if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
goto Error;
}
// No color cache, no Huffman image.
- VP8LWriteBits(bw, 1, 0);
+ VP8LPutBits(bw, 0, 1);
- // Store Huffman codes.
+ // Find maximum number of symbols for the huffman tree-set.
for (i = 0; i < 5; ++i) {
HuffmanTreeCode* const codes = &huffman_codes[i];
- if (!StoreHuffmanCode(bw, codes)) {
- goto Error;
+ if (max_tokens < codes->num_symbols) {
+ max_tokens = codes->num_symbols;
}
+ }
+
+ tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens));
+ if (tokens == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+
+ // Store Huffman codes.
+ for (i = 0; i < 5; ++i) {
+ HuffmanTreeCode* const codes = &huffman_codes[i];
+ StoreHuffmanCode(bw, huff_tree, tokens, codes);
ClearHuffmanTreeIfOnlyOneSymbol(codes);
}
// Store actual literals.
- StoreImageToBitMask(bw, width, 0, &refs, histogram_symbols, huffman_codes);
- ok = 1;
+ err = StoreImageToBitMask(bw, width, 0, refs, histogram_symbols,
+ huffman_codes);
Error:
- free(histogram_image);
- VP8LClearBackwardRefs(&refs);
- free(huffman_codes[0].codes);
- return ok;
+ WebPSafeFree(tokens);
+ WebPSafeFree(huff_tree);
+ VP8LFreeHistogramSet(histogram_image);
+ WebPSafeFree(huffman_codes[0].codes);
+ return err;
}
-static int EncodeImageInternal(VP8LBitWriter* const bw,
- const uint32_t* const argb,
- int width, int height, int quality,
- int cache_bits, int histogram_bits) {
- int ok = 0;
- const int use_2d_locality = 1;
- const int use_color_cache = (cache_bits > 0);
+static WebPEncodingError EncodeImageInternal(VP8LBitWriter* const bw,
+ const uint32_t* const argb,
+ VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs refs_array[2],
+ int width, int height, int quality,
+ int low_effort, int* cache_bits,
+ int histogram_bits,
+ size_t init_byte_position,
+ int* const hdr_size,
+ int* const data_size) {
+ WebPEncodingError err = VP8_ENC_OK;
const uint32_t histogram_image_xysize =
VP8LSubSampleSize(width, histogram_bits) *
VP8LSubSampleSize(height, histogram_bits);
- VP8LHistogramSet* histogram_image =
- VP8LAllocateHistogramSet(histogram_image_xysize, 0);
+ VP8LHistogramSet* histogram_image = NULL;
+ VP8LHistogramSet* tmp_histos = NULL;
int histogram_image_size = 0;
size_t bit_array_size = 0;
+ HuffmanTree* huff_tree = NULL;
+ HuffmanTreeToken* tokens = NULL;
HuffmanTreeCode* huffman_codes = NULL;
VP8LBackwardRefs refs;
+ VP8LBackwardRefs* best_refs;
uint16_t* const histogram_symbols =
- (uint16_t*)WebPSafeMalloc((uint64_t)histogram_image_xysize,
+ (uint16_t*)WebPSafeMalloc(histogram_image_xysize,
sizeof(*histogram_symbols));
assert(histogram_bits >= MIN_HUFFMAN_BITS);
assert(histogram_bits <= MAX_HUFFMAN_BITS);
- if (histogram_image == NULL || histogram_symbols == NULL) goto Error;
+ assert(hdr_size != NULL);
+ assert(data_size != NULL);
+ VP8LBackwardRefsInit(&refs, refs_array[0].block_size_);
+ if (histogram_symbols == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+
+ *cache_bits = MAX_COLOR_CACHE_BITS;
+ // 'best_refs' is the reference to the best backward refs and points to one
+ // of refs_array[0] or refs_array[1].
// Calculate backward references from ARGB image.
- if (!VP8LGetBackwardReferences(width, height, argb, quality, cache_bits,
- use_2d_locality, &refs)) {
+ best_refs = VP8LGetBackwardReferences(width, height, argb, quality,
+ low_effort, cache_bits, hash_chain,
+ refs_array);
+ if (best_refs == NULL || !VP8LBackwardRefsCopy(best_refs, &refs)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
goto Error;
}
+ histogram_image =
+ VP8LAllocateHistogramSet(histogram_image_xysize, *cache_bits);
+ tmp_histos = VP8LAllocateHistogramSet(2, *cache_bits);
+ if (histogram_image == NULL || tmp_histos == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+
// Build histogram image and symbols from backward references.
- if (!VP8LGetHistoImageSymbols(width, height, &refs,
- quality, histogram_bits, cache_bits,
- histogram_image,
- histogram_symbols)) {
+ if (!VP8LGetHistoImageSymbols(width, height, &refs, quality, low_effort,
+ histogram_bits, *cache_bits, histogram_image,
+ tmp_histos, histogram_symbols)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
goto Error;
}
// Create Huffman bit lengths and codes for each histogram image.
@@ -548,171 +886,167 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
bit_array_size = 5 * histogram_image_size;
huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size,
sizeof(*huffman_codes));
+ // Note: some histogram_image entries may point to tmp_histos[], so the latter
+ // need to outlive the following call to GetHuffBitLengthsAndCodes().
if (huffman_codes == NULL ||
!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
goto Error;
}
+ // Free combined histograms.
+ VP8LFreeHistogramSet(histogram_image);
+ histogram_image = NULL;
+
+ // Free scratch histograms.
+ VP8LFreeHistogramSet(tmp_histos);
+ tmp_histos = NULL;
// Color Cache parameters.
- VP8LWriteBits(bw, 1, use_color_cache);
- if (use_color_cache) {
- VP8LWriteBits(bw, 4, cache_bits);
+ if (*cache_bits > 0) {
+ VP8LPutBits(bw, 1, 1);
+ VP8LPutBits(bw, *cache_bits, 4);
+ } else {
+ VP8LPutBits(bw, 0, 1);
}
// Huffman image + meta huffman.
{
const int write_histogram_image = (histogram_image_size > 1);
- VP8LWriteBits(bw, 1, write_histogram_image);
+ VP8LPutBits(bw, write_histogram_image, 1);
if (write_histogram_image) {
uint32_t* const histogram_argb =
- (uint32_t*)WebPSafeMalloc((uint64_t)histogram_image_xysize,
+ (uint32_t*)WebPSafeMalloc(histogram_image_xysize,
sizeof(*histogram_argb));
int max_index = 0;
uint32_t i;
- if (histogram_argb == NULL) goto Error;
+ if (histogram_argb == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
for (i = 0; i < histogram_image_xysize; ++i) {
- const int index = histogram_symbols[i] & 0xffff;
- histogram_argb[i] = 0xff000000 | (index << 8);
- if (index >= max_index) {
- max_index = index + 1;
+ const int symbol_index = histogram_symbols[i] & 0xffff;
+ histogram_argb[i] = (symbol_index << 8);
+ if (symbol_index >= max_index) {
+ max_index = symbol_index + 1;
}
}
histogram_image_size = max_index;
- VP8LWriteBits(bw, 3, histogram_bits - 2);
- ok = EncodeImageNoHuffman(bw, histogram_argb,
- VP8LSubSampleSize(width, histogram_bits),
- VP8LSubSampleSize(height, histogram_bits),
- quality);
- free(histogram_argb);
- if (!ok) goto Error;
+ VP8LPutBits(bw, histogram_bits - 2, 3);
+ err = EncodeImageNoHuffman(bw, histogram_argb, hash_chain, refs_array,
+ VP8LSubSampleSize(width, histogram_bits),
+ VP8LSubSampleSize(height, histogram_bits),
+ quality);
+ WebPSafeFree(histogram_argb);
+ if (err != VP8_ENC_OK) goto Error;
}
}
// Store Huffman codes.
{
int i;
+ int max_tokens = 0;
+ huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * CODE_LENGTH_CODES,
+ sizeof(*huff_tree));
+ if (huff_tree == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+ // Find maximum number of symbols for the huffman tree-set.
for (i = 0; i < 5 * histogram_image_size; ++i) {
HuffmanTreeCode* const codes = &huffman_codes[i];
- if (!StoreHuffmanCode(bw, codes)) goto Error;
+ if (max_tokens < codes->num_symbols) {
+ max_tokens = codes->num_symbols;
+ }
+ }
+ tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens,
+ sizeof(*tokens));
+ if (tokens == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+ for (i = 0; i < 5 * histogram_image_size; ++i) {
+ HuffmanTreeCode* const codes = &huffman_codes[i];
+ StoreHuffmanCode(bw, huff_tree, tokens, codes);
ClearHuffmanTreeIfOnlyOneSymbol(codes);
}
}
- // Free combined histograms.
- free(histogram_image);
- histogram_image = NULL;
+ *hdr_size = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position);
// Store actual literals.
- StoreImageToBitMask(bw, width, histogram_bits, &refs,
- histogram_symbols, huffman_codes);
- ok = 1;
+ err = StoreImageToBitMask(bw, width, histogram_bits, &refs,
+ histogram_symbols, huffman_codes);
+ *data_size =
+ (int)(VP8LBitWriterNumBytes(bw) - init_byte_position - *hdr_size);
Error:
- if (!ok) free(histogram_image);
-
- VP8LClearBackwardRefs(&refs);
+ WebPSafeFree(tokens);
+ WebPSafeFree(huff_tree);
+ VP8LFreeHistogramSet(histogram_image);
+ VP8LFreeHistogramSet(tmp_histos);
+ VP8LBackwardRefsClear(&refs);
if (huffman_codes != NULL) {
- free(huffman_codes->codes);
- free(huffman_codes);
+ WebPSafeFree(huffman_codes->codes);
+ WebPSafeFree(huffman_codes);
}
- free(histogram_symbols);
- return ok;
+ WebPSafeFree(histogram_symbols);
+ return err;
}
// -----------------------------------------------------------------------------
// Transforms
-// Check if it would be a good idea to subtract green from red and blue. We
-// only impact entropy in red/blue components, don't bother to look at others.
-static int EvalAndApplySubtractGreen(VP8LEncoder* const enc,
- int width, int height,
- VP8LBitWriter* const bw) {
- if (!enc->use_palette_) {
- int i;
- const uint32_t* const argb = enc->argb_;
- double bit_cost_before, bit_cost_after;
- VP8LHistogram* const histo = (VP8LHistogram*)malloc(sizeof(*histo));
- if (histo == NULL) return 0;
-
- VP8LHistogramInit(histo, 1);
- for (i = 0; i < width * height; ++i) {
- const uint32_t c = argb[i];
- ++histo->red_[(c >> 16) & 0xff];
- ++histo->blue_[(c >> 0) & 0xff];
- }
- bit_cost_before = VP8LHistogramEstimateBits(histo);
-
- VP8LHistogramInit(histo, 1);
- for (i = 0; i < width * height; ++i) {
- const uint32_t c = argb[i];
- const int green = (c >> 8) & 0xff;
- ++histo->red_[((c >> 16) - green) & 0xff];
- ++histo->blue_[((c >> 0) - green) & 0xff];
- }
- bit_cost_after = VP8LHistogramEstimateBits(histo);
- free(histo);
-
- // Check if subtracting green yields low entropy.
- enc->use_subtract_green_ = (bit_cost_after < bit_cost_before);
- if (enc->use_subtract_green_) {
- VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
- VP8LWriteBits(bw, 2, SUBTRACT_GREEN);
- VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height);
- }
- }
- return 1;
+static void ApplySubtractGreen(VP8LEncoder* const enc, int width, int height,
+ VP8LBitWriter* const bw) {
+ VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
+ VP8LPutBits(bw, SUBTRACT_GREEN, 2);
+ VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height);
}
-static int ApplyPredictFilter(const VP8LEncoder* const enc,
- int width, int height, int quality,
- VP8LBitWriter* const bw) {
+static WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc,
+ int width, int height,
+ int quality, int low_effort,
+ VP8LBitWriter* const bw) {
const int pred_bits = enc->transform_bits_;
const int transform_width = VP8LSubSampleSize(width, pred_bits);
const int transform_height = VP8LSubSampleSize(height, pred_bits);
- VP8LResidualImage(width, height, pred_bits, enc->argb_, enc->argb_scratch_,
- enc->transform_data_);
- VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
- VP8LWriteBits(bw, 2, PREDICTOR_TRANSFORM);
+ VP8LResidualImage(width, height, pred_bits, low_effort, enc->argb_,
+ enc->argb_scratch_, enc->transform_data_);
+ VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
+ VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2);
assert(pred_bits >= 2);
- VP8LWriteBits(bw, 3, pred_bits - 2);
- if (!EncodeImageNoHuffman(bw, enc->transform_data_,
- transform_width, transform_height, quality)) {
- return 0;
- }
- return 1;
+ VP8LPutBits(bw, pred_bits - 2, 3);
+ return EncodeImageNoHuffman(bw, enc->transform_data_,
+ (VP8LHashChain*)&enc->hash_chain_,
+ (VP8LBackwardRefs*)enc->refs_, // cast const away
+ transform_width, transform_height,
+ quality);
}
-static int ApplyCrossColorFilter(const VP8LEncoder* const enc,
- int width, int height, int quality,
- VP8LBitWriter* const bw) {
+static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc,
+ int width, int height,
+ int quality,
+ VP8LBitWriter* const bw) {
const int ccolor_transform_bits = enc->transform_bits_;
const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits);
const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits);
- const int step = (quality == 0) ? 32 : 8;
- VP8LColorSpaceTransform(width, height, ccolor_transform_bits, step,
+ VP8LColorSpaceTransform(width, height, ccolor_transform_bits, quality,
enc->argb_, enc->transform_data_);
- VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
- VP8LWriteBits(bw, 2, CROSS_COLOR_TRANSFORM);
+ VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
+ VP8LPutBits(bw, CROSS_COLOR_TRANSFORM, 2);
assert(ccolor_transform_bits >= 2);
- VP8LWriteBits(bw, 3, ccolor_transform_bits - 2);
- if (!EncodeImageNoHuffman(bw, enc->transform_data_,
- transform_width, transform_height, quality)) {
- return 0;
- }
- return 1;
+ VP8LPutBits(bw, ccolor_transform_bits - 2, 3);
+ return EncodeImageNoHuffman(bw, enc->transform_data_,
+ (VP8LHashChain*)&enc->hash_chain_,
+ (VP8LBackwardRefs*)enc->refs_, // cast const away
+ transform_width, transform_height,
+ quality);
}
// -----------------------------------------------------------------------------
-static void PutLE32(uint8_t* const data, uint32_t val) {
- data[0] = (val >> 0) & 0xff;
- data[1] = (val >> 8) & 0xff;
- data[2] = (val >> 16) & 0xff;
- data[3] = (val >> 24) & 0xff;
-}
-
static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic,
size_t riff_size, size_t vp8l_size) {
uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = {
@@ -733,14 +1067,14 @@ static int WriteImageSize(const WebPPicture* const pic,
const int height = pic->height - 1;
assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION);
- VP8LWriteBits(bw, VP8L_IMAGE_SIZE_BITS, width);
- VP8LWriteBits(bw, VP8L_IMAGE_SIZE_BITS, height);
+ VP8LPutBits(bw, width, VP8L_IMAGE_SIZE_BITS);
+ VP8LPutBits(bw, height, VP8L_IMAGE_SIZE_BITS);
return !bw->error_;
}
static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) {
- VP8LWriteBits(bw, 1, has_alpha);
- VP8LWriteBits(bw, VP8L_VERSION_BITS, VP8L_VERSION);
+ VP8LPutBits(bw, has_alpha, 1);
+ VP8LPutBits(bw, VP8L_VERSION, VP8L_VERSION_BITS);
return !bw->error_;
}
@@ -780,166 +1114,261 @@ static WebPEncodingError WriteImage(const WebPPicture* const pic,
// Allocates the memory for argb (W x H) buffer, 2 rows of context for
// prediction and transform data.
+// Flags influencing the memory allocated:
+// enc->transform_bits_
+// enc->use_predict_, enc->use_cross_color_
static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc,
int width, int height) {
WebPEncodingError err = VP8_ENC_OK;
- const int tile_size = 1 << enc->transform_bits_;
- const uint64_t image_size = width * height;
- const uint64_t argb_scratch_size = tile_size * width + width;
- const uint64_t transform_data_size =
- (uint64_t)VP8LSubSampleSize(width, enc->transform_bits_) *
- (uint64_t)VP8LSubSampleSize(height, enc->transform_bits_);
- const uint64_t total_size =
- image_size + argb_scratch_size + transform_data_size;
- uint32_t* mem = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*mem));
- if (mem == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
+ if (enc->argb_ == NULL) {
+ const int tile_size = 1 << enc->transform_bits_;
+ const uint64_t image_size = width * height;
+ // Ensure enough size for tiles, as well as for two scanlines and two
+ // extra pixels for CopyImageWithPrediction.
+ const uint64_t argb_scratch_size =
+ enc->use_predict_ ? tile_size * width + width + 2 : 0;
+ const int transform_data_size =
+ (enc->use_predict_ || enc->use_cross_color_)
+ ? VP8LSubSampleSize(width, enc->transform_bits_) *
+ VP8LSubSampleSize(height, enc->transform_bits_)
+ : 0;
+ const uint64_t total_size =
+ image_size + WEBP_ALIGN_CST +
+ argb_scratch_size + WEBP_ALIGN_CST +
+ (uint64_t)transform_data_size;
+ uint32_t* mem = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*mem));
+ if (mem == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+ enc->argb_ = mem;
+ mem = (uint32_t*)WEBP_ALIGN(mem + image_size);
+ enc->argb_scratch_ = mem;
+ mem = (uint32_t*)WEBP_ALIGN(mem + argb_scratch_size);
+ enc->transform_data_ = mem;
+ enc->current_width_ = width;
}
- enc->argb_ = mem;
- mem += image_size;
- enc->argb_scratch_ = mem;
- mem += argb_scratch_size;
- enc->transform_data_ = mem;
- enc->current_width_ = width;
-
Error:
return err;
}
-// Bundles multiple (2, 4 or 8) pixels into a single pixel.
-// Returns the new xsize.
-static void BundleColorMap(const WebPPicture* const pic,
- int xbits, uint32_t* bundled_argb, int xs) {
- int y;
- const int bit_depth = 1 << (3 - xbits);
- uint32_t code = 0;
- const uint32_t* argb = pic->argb;
- const int width = pic->width;
- const int height = pic->height;
+static void ClearTransformBuffer(VP8LEncoder* const enc) {
+ WebPSafeFree(enc->argb_);
+ enc->argb_ = NULL;
+}
+static WebPEncodingError MakeInputImageCopy(VP8LEncoder* const enc) {
+ WebPEncodingError err = VP8_ENC_OK;
+ const WebPPicture* const picture = enc->pic_;
+ const int width = picture->width;
+ const int height = picture->height;
+ int y;
+ err = AllocateTransformBuffer(enc, width, height);
+ if (err != VP8_ENC_OK) return err;
for (y = 0; y < height; ++y) {
- int x;
- for (x = 0; x < width; ++x) {
- const int mask = (1 << xbits) - 1;
- const int xsub = x & mask;
- if (xsub == 0) {
- code = 0;
- }
- // TODO(vikasa): simplify the bundling logic.
- code |= (argb[x] & 0xff00) << (bit_depth * xsub);
- bundled_argb[y * xs + (x >> xbits)] = 0xff000000 | code;
- }
- argb += pic->argb_stride;
+ memcpy(enc->argb_ + y * width,
+ picture->argb + y * picture->argb_stride,
+ width * sizeof(*enc->argb_));
}
+ assert(enc->current_width_ == width);
+ return VP8_ENC_OK;
}
-// Note: Expects "enc->palette_" to be set properly.
-// Also, "enc->palette_" will be modified after this call and should not be used
-// later.
-static WebPEncodingError ApplyPalette(VP8LBitWriter* const bw,
- VP8LEncoder* const enc, int quality) {
- WebPEncodingError err = VP8_ENC_OK;
- int i, x, y;
- const WebPPicture* const pic = enc->pic_;
- uint32_t* argb = pic->argb;
- const int width = pic->width;
- const int height = pic->height;
- uint32_t* const palette = enc->palette_;
- const int palette_size = enc->palette_size_;
+// -----------------------------------------------------------------------------
- // Replace each input pixel by corresponding palette index.
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; ++x) {
- const uint32_t pix = argb[x];
- for (i = 0; i < palette_size; ++i) {
+static void MapToPalette(const uint32_t palette[], int num_colors,
+ uint32_t* const last_pix, int* const last_idx,
+ const uint32_t* src, uint8_t* dst, int width) {
+ int x;
+ int prev_idx = *last_idx;
+ uint32_t prev_pix = *last_pix;
+ for (x = 0; x < width; ++x) {
+ const uint32_t pix = src[x];
+ if (pix != prev_pix) {
+ int i;
+ for (i = 0; i < num_colors; ++i) {
if (pix == palette[i]) {
- argb[x] = 0xff000000u | (i << 8);
+ prev_idx = i;
+ prev_pix = pix;
break;
}
}
}
- argb += pic->argb_stride;
+ dst[x] = prev_idx;
}
+ *last_idx = prev_idx;
+ *last_pix = prev_pix;
+}
- // Save palette to bitstream.
- VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
- VP8LWriteBits(bw, 2, COLOR_INDEXING_TRANSFORM);
- assert(palette_size >= 1);
- VP8LWriteBits(bw, 8, palette_size - 1);
- for (i = palette_size - 1; i >= 1; --i) {
- palette[i] = VP8LSubPixels(palette[i], palette[i - 1]);
- }
- if (!EncodeImageNoHuffman(bw, palette, palette_size, 1, quality)) {
- err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
- goto Error;
+// Remap argb values in src[] to packed palettes entries in dst[]
+// using 'row' as a temporary buffer of size 'width'.
+// We assume that all src[] values have a corresponding entry in the palette.
+// Note: src[] can be the same as dst[]
+static WebPEncodingError ApplyPalette(const uint32_t* src, uint32_t src_stride,
+ uint32_t* dst, uint32_t dst_stride,
+ const uint32_t* palette, int palette_size,
+ int width, int height, int xbits) {
+ // TODO(skal): this tmp buffer is not needed if VP8LBundleColorMap() can be
+ // made to work in-place.
+ uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row));
+ int i, x, y;
+ int use_LUT = 1;
+
+ if (tmp_row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY;
+ for (i = 0; i < palette_size; ++i) {
+ if ((palette[i] & 0xffff00ffu) != 0) {
+ use_LUT = 0;
+ break;
+ }
}
- if (palette_size <= 16) {
- // Image can be packed (multiple pixels per uint32_t).
- int xbits = 1;
- if (palette_size <= 2) {
- xbits = 3;
- } else if (palette_size <= 4) {
- xbits = 2;
+ if (use_LUT) {
+ uint8_t inv_palette[MAX_PALETTE_SIZE] = { 0 };
+ for (i = 0; i < palette_size; ++i) {
+ const int color = (palette[i] >> 8) & 0xff;
+ inv_palette[color] = i;
+ }
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ const int color = (src[x] >> 8) & 0xff;
+ tmp_row[x] = inv_palette[color];
+ }
+ VP8LBundleColorMap(tmp_row, width, xbits, dst);
+ src += src_stride;
+ dst += dst_stride;
+ }
+ } else {
+ // Use 1 pixel cache for ARGB pixels.
+ uint32_t last_pix = palette[0];
+ int last_idx = 0;
+ for (y = 0; y < height; ++y) {
+ MapToPalette(palette, palette_size, &last_pix, &last_idx,
+ src, tmp_row, width);
+ VP8LBundleColorMap(tmp_row, width, xbits, dst);
+ src += src_stride;
+ dst += dst_stride;
}
- err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height);
- if (err != VP8_ENC_OK) goto Error;
- BundleColorMap(pic, xbits, enc->argb_, enc->current_width_);
}
+ WebPSafeFree(tmp_row);
+ return VP8_ENC_OK;
+}
- Error:
+// Note: Expects "enc->palette_" to be set properly.
+static WebPEncodingError MapImageFromPalette(VP8LEncoder* const enc,
+ int in_place) {
+ WebPEncodingError err = VP8_ENC_OK;
+ const WebPPicture* const pic = enc->pic_;
+ const int width = pic->width;
+ const int height = pic->height;
+ const uint32_t* const palette = enc->palette_;
+ const uint32_t* src = in_place ? enc->argb_ : pic->argb;
+ const int src_stride = in_place ? enc->current_width_ : pic->argb_stride;
+ const int palette_size = enc->palette_size_;
+ int xbits;
+
+ // Replace each input pixel by corresponding palette index.
+ // This is done line by line.
+ if (palette_size <= 4) {
+ xbits = (palette_size <= 2) ? 3 : 2;
+ } else {
+ xbits = (palette_size <= 16) ? 1 : 0;
+ }
+
+ err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height);
+ if (err != VP8_ENC_OK) return err;
+
+ err = ApplyPalette(src, src_stride,
+ enc->argb_, enc->current_width_,
+ palette, palette_size, width, height, xbits);
return err;
}
-// -----------------------------------------------------------------------------
+// Save palette_[] to bitstream.
+static WebPEncodingError EncodePalette(VP8LBitWriter* const bw,
+ VP8LEncoder* const enc) {
+ int i;
+ uint32_t tmp_palette[MAX_PALETTE_SIZE];
+ const int palette_size = enc->palette_size_;
+ const uint32_t* const palette = enc->palette_;
+ VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
+ VP8LPutBits(bw, COLOR_INDEXING_TRANSFORM, 2);
+ assert(palette_size >= 1 && palette_size <= MAX_PALETTE_SIZE);
+ VP8LPutBits(bw, palette_size - 1, 8);
+ for (i = palette_size - 1; i >= 1; --i) {
+ tmp_palette[i] = VP8LSubPixels(palette[i], palette[i - 1]);
+ }
+ tmp_palette[0] = palette[0];
+ return EncodeImageNoHuffman(bw, tmp_palette, &enc->hash_chain_, enc->refs_,
+ palette_size, 1, 20 /* quality */);
+}
-static int GetHistoBits(const WebPConfig* const config,
- const WebPPicture* const pic) {
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+
+static WebPEncodingError EncodeDeltaPalettePredictorImage(
+ VP8LBitWriter* const bw, VP8LEncoder* const enc, int quality) {
+ const WebPPicture* const pic = enc->pic_;
const int width = pic->width;
const int height = pic->height;
- const size_t hist_size = sizeof(VP8LHistogram);
- // Make tile size a function of encoding method (Range: 0 to 6).
- int histo_bits = 7 - config->method;
- while (1) {
- const size_t huff_image_size = VP8LSubSampleSize(width, histo_bits) *
- VP8LSubSampleSize(height, histo_bits) *
- hist_size;
- if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break;
- ++histo_bits;
+
+ const int pred_bits = 5;
+ const int transform_width = VP8LSubSampleSize(width, pred_bits);
+ const int transform_height = VP8LSubSampleSize(height, pred_bits);
+ const int pred = 7; // default is Predictor7 (Top/Left Average)
+ const int tiles_per_row = VP8LSubSampleSize(width, pred_bits);
+ const int tiles_per_col = VP8LSubSampleSize(height, pred_bits);
+ uint32_t* predictors;
+ int tile_x, tile_y;
+ WebPEncodingError err = VP8_ENC_OK;
+
+ predictors = (uint32_t*)WebPSafeMalloc(tiles_per_col * tiles_per_row,
+ sizeof(*predictors));
+ if (predictors == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY;
+
+ for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) {
+ for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) {
+ predictors[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8);
+ }
}
- return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS :
- (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits;
-}
-static void InitEncParams(VP8LEncoder* const enc) {
- const WebPConfig* const config = enc->config_;
- const WebPPicture* const picture = enc->pic_;
- const int method = config->method;
- const float quality = config->quality;
- enc->transform_bits_ = (method < 4) ? 5 : (method > 4) ? 3 : 4;
- enc->histo_bits_ = GetHistoBits(config, picture);
- enc->cache_bits_ = (quality <= 25.f) ? 0 : 7;
+ VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
+ VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2);
+ VP8LPutBits(bw, pred_bits - 2, 3);
+ err = EncodeImageNoHuffman(bw, predictors, &enc->hash_chain_,
+ (VP8LBackwardRefs*)enc->refs_, // cast const away
+ transform_width, transform_height,
+ quality);
+ WebPSafeFree(predictors);
+ return err;
}
+#endif // WEBP_EXPERIMENTAL_FEATURES
+
// -----------------------------------------------------------------------------
// VP8LEncoder
static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config,
const WebPPicture* const picture) {
- VP8LEncoder* const enc = (VP8LEncoder*)calloc(1, sizeof(*enc));
+ VP8LEncoder* const enc = (VP8LEncoder*)WebPSafeCalloc(1ULL, sizeof(*enc));
if (enc == NULL) {
WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
return NULL;
}
enc->config_ = config;
enc->pic_ = picture;
+
+ VP8LEncDspInit();
+
return enc;
}
static void VP8LEncoderDelete(VP8LEncoder* enc) {
- free(enc->argb_);
- free(enc);
+ if (enc != NULL) {
+ VP8LHashChainClear(&enc->hash_chain_);
+ VP8LBackwardRefsClear(&enc->refs_[0]);
+ VP8LBackwardRefsClear(&enc->refs_[1]);
+ ClearTransformBuffer(enc);
+ WebPSafeFree(enc);
+ }
}
// -----------------------------------------------------------------------------
@@ -950,89 +1379,102 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
VP8LBitWriter* const bw) {
WebPEncodingError err = VP8_ENC_OK;
const int quality = (int)config->quality;
+ const int low_effort = (config->method == 0);
const int width = picture->width;
const int height = picture->height;
VP8LEncoder* const enc = VP8LEncoderNew(config, picture);
const size_t byte_position = VP8LBitWriterNumBytes(bw);
+ int use_near_lossless = 0;
+ int hdr_size = 0;
+ int data_size = 0;
+ int use_delta_palettization = 0;
if (enc == NULL) {
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
goto Error;
}
- InitEncParams(enc);
-
// ---------------------------------------------------------------------------
// Analyze image (entropy, num_palettes etc)
- if (!VP8LEncAnalyze(enc, config->image_hint)) {
+ if (!AnalyzeAndInit(enc)) {
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
goto Error;
}
- if (enc->use_palette_) {
- err = ApplyPalette(bw, enc, quality);
- if (err != VP8_ENC_OK) goto Error;
- // Color cache is disabled for palette.
- enc->cache_bits_ = 0;
+ // Apply near-lossless preprocessing.
+ use_near_lossless = !enc->use_palette_ && (config->near_lossless < 100);
+ if (use_near_lossless) {
+ if (!VP8ApplyNearLossless(width, height, picture->argb,
+ config->near_lossless)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
}
- // In case image is not packed.
- if (enc->argb_ == NULL) {
- int y;
- err = AllocateTransformBuffer(enc, width, height);
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ if (config->delta_palettization) {
+ enc->use_predict_ = 1;
+ enc->use_cross_color_ = 0;
+ enc->use_subtract_green_ = 0;
+ enc->use_palette_ = 1;
+ err = MakeInputImageCopy(enc);
if (err != VP8_ENC_OK) goto Error;
- for (y = 0; y < height; ++y) {
- memcpy(enc->argb_ + y * width,
- picture->argb + y * picture->argb_stride,
- width * sizeof(*enc->argb_));
+ err = WebPSearchOptimalDeltaPalette(enc);
+ if (err != VP8_ENC_OK) goto Error;
+ if (enc->use_palette_) {
+ err = AllocateTransformBuffer(enc, width, height);
+ if (err != VP8_ENC_OK) goto Error;
+ err = EncodeDeltaPalettePredictorImage(bw, enc, quality);
+ if (err != VP8_ENC_OK) goto Error;
+ use_delta_palettization = 1;
}
- enc->current_width_ = width;
}
+#endif // WEBP_EXPERIMENTAL_FEATURES
- // ---------------------------------------------------------------------------
- // Apply transforms and write transform data.
-
- if (!EvalAndApplySubtractGreen(enc, enc->current_width_, height, bw)) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
+ // Encode palette
+ if (enc->use_palette_) {
+ err = EncodePalette(bw, enc);
+ if (err != VP8_ENC_OK) goto Error;
+ err = MapImageFromPalette(enc, use_delta_palettization);
+ if (err != VP8_ENC_OK) goto Error;
}
-
- if (enc->use_predict_) {
- if (!ApplyPredictFilter(enc, enc->current_width_, height, quality, bw)) {
- err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
- goto Error;
+ if (!use_delta_palettization) {
+ // In case image is not packed.
+ if (enc->argb_ == NULL) {
+ err = MakeInputImageCopy(enc);
+ if (err != VP8_ENC_OK) goto Error;
}
- }
- if (enc->use_cross_color_) {
- if (!ApplyCrossColorFilter(enc, enc->current_width_, height, quality, bw)) {
- err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
- goto Error;
- }
- }
+ // -------------------------------------------------------------------------
+ // Apply transforms and write transform data.
- VP8LWriteBits(bw, 1, !TRANSFORM_PRESENT); // No more transforms.
+ if (enc->use_subtract_green_) {
+ ApplySubtractGreen(enc, enc->current_width_, height, bw);
+ }
- // ---------------------------------------------------------------------------
- // Estimate the color cache size.
+ if (enc->use_predict_) {
+ err = ApplyPredictFilter(enc, enc->current_width_, height, quality,
+ low_effort, bw);
+ if (err != VP8_ENC_OK) goto Error;
+ }
- if (enc->cache_bits_ > 0) {
- if (!VP8LCalculateEstimateForCacheSize(enc->argb_, enc->current_width_,
- height, &enc->cache_bits_)) {
- err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
- goto Error;
+ if (enc->use_cross_color_) {
+ err = ApplyCrossColorFilter(enc, enc->current_width_,
+ height, quality, bw);
+ if (err != VP8_ENC_OK) goto Error;
}
}
+ VP8LPutBits(bw, !TRANSFORM_PRESENT, 1); // No more transforms.
+
// ---------------------------------------------------------------------------
// Encode and write the transformed image.
-
- if (!EncodeImageInternal(bw, enc->argb_, enc->current_width_, height,
- quality, enc->cache_bits_, enc->histo_bits_)) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
+ err = EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_,
+ enc->current_width_, height, quality, low_effort,
+ &enc->cache_bits_, enc->histo_bits_, byte_position,
+ &hdr_size, &data_size);
+ if (err != VP8_ENC_OK) goto Error;
if (picture->stats != NULL) {
WebPAuxStats* const stats = picture->stats;
@@ -1046,6 +1488,8 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
stats->cache_bits = enc->cache_bits_;
stats->palette_size = enc->palette_size_;
stats->lossless_size = (int)(VP8LBitWriterNumBytes(bw) - byte_position);
+ stats->lossless_hdr_size = hdr_size;
+ stats->lossless_data_size = data_size;
}
Error:
@@ -1059,6 +1503,7 @@ int VP8LEncodeImage(const WebPConfig* const config,
int has_alpha;
size_t coded_size;
int percent = 0;
+ int initial_size;
WebPEncodingError err = VP8_ENC_OK;
VP8LBitWriter bw;
@@ -1072,7 +1517,11 @@ int VP8LEncodeImage(const WebPConfig* const config,
width = picture->width;
height = picture->height;
- if (!VP8LBitWriterInit(&bw, (width * height) >> 1)) {
+ // Initialize BitWriter with size corresponding to 16 bpp to photo images and
+ // 8 bpp for graphical images.
+ initial_size = (config->image_hint == WEBP_HINT_GRAPH) ?
+ width * height : width * height * 2;
+ if (!VP8LBitWriterInit(&bw, initial_size)) {
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
goto Error;
}
@@ -1135,7 +1584,7 @@ int VP8LEncodeImage(const WebPConfig* const config,
Error:
if (bw.error_) err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- VP8LBitWriterDestroy(&bw);
+ VP8LBitWriterWipeOut(&bw);
if (err != VP8_ENC_OK) {
WebPEncodingSetError(picture, err);
return 0;
@@ -1144,7 +1593,3 @@ int VP8LEncodeImage(const WebPConfig* const config,
}
//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/enc/vp8li.h b/drivers/webp/enc/vp8li.h
index bb111aec33..4543c3b260 100644
--- a/drivers/webp/enc/vp8li.h
+++ b/drivers/webp/enc/vp8li.h
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Lossless encoder: internal header.
@@ -12,12 +14,13 @@
#ifndef WEBP_ENC_VP8LI_H_
#define WEBP_ENC_VP8LI_H_
+#include "./backward_references.h"
#include "./histogram.h"
#include "../utils/bit_writer.h"
-#include "../encode.h"
-#include "../format_constants.h"
+#include "webp/encode.h"
+#include "webp/format_constants.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
@@ -43,6 +46,12 @@ typedef struct {
int use_palette_;
int palette_size_;
uint32_t palette_[MAX_PALETTE_SIZE];
+
+ // Some 'scratch' (potentially large) objects.
+ struct VP8LBackwardRefs refs_[2]; // Backward Refs array corresponding to
+ // LZ77 & RLE coding.
+ VP8LHashChain hash_chain_; // HashChain data for constructing
+ // backward references.
} VP8LEncoder;
//------------------------------------------------------------------------------
@@ -61,7 +70,7 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/enc/webpenc.c b/drivers/webp/enc/webpenc.c
index 3c275589fc..8ced07a2a3 100644
--- a/drivers/webp/enc/webpenc.c
+++ b/drivers/webp/enc/webpenc.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// WebP encoder: main entry point
@@ -14,16 +16,13 @@
#include <string.h>
#include <math.h>
+#include "./cost.h"
#include "./vp8enci.h"
#include "./vp8li.h"
#include "../utils/utils.h"
// #define PRINT_MEMORY_INFO
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
#ifdef PRINT_MEMORY_INFO
#include <stdio.h>
#endif
@@ -35,43 +34,18 @@ int WebPGetEncoderVersion(void) {
}
//------------------------------------------------------------------------------
-// WebPPicture
-//------------------------------------------------------------------------------
-
-static int DummyWriter(const uint8_t* data, size_t data_size,
- const WebPPicture* const picture) {
- // The following are to prevent 'unused variable' error message.
- (void)data;
- (void)data_size;
- (void)picture;
- return 1;
-}
-
-int WebPPictureInitInternal(WebPPicture* picture, int version) {
- if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) {
- return 0; // caller/system version mismatch!
- }
- if (picture != NULL) {
- memset(picture, 0, sizeof(*picture));
- picture->writer = DummyWriter;
- WebPEncodingSetError(picture, VP8_ENC_OK);
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
// VP8Encoder
//------------------------------------------------------------------------------
static void ResetSegmentHeader(VP8Encoder* const enc) {
- VP8SegmentHeader* const hdr = &enc->segment_hdr_;
+ VP8EncSegmentHeader* const hdr = &enc->segment_hdr_;
hdr->num_segments_ = enc->config_->segments;
hdr->update_map_ = (hdr->num_segments_ > 1);
hdr->size_ = 0;
}
static void ResetFilterHeader(VP8Encoder* const enc) {
- VP8FilterHeader* const hdr = &enc->filter_hdr_;
+ VP8EncFilterHeader* const hdr = &enc->filter_hdr_;
hdr->simple_ = 1;
hdr->level_ = 0;
hdr->sharpness_ = 0;
@@ -93,56 +67,73 @@ static void ResetBoundaryPredictions(VP8Encoder* const enc) {
enc->nz_[-1] = 0; // constant
}
-// Map configured quality level to coding tools used.
-//-------------+---+---+---+---+---+---+
-// Quality | 0 | 1 | 2 | 3 | 4 | 5 +
-//-------------+---+---+---+---+---+---+
-// dynamic prob| ~ | x | x | x | x | x |
-//-------------+---+---+---+---+---+---+
-// rd-opt modes| | | x | x | x | x |
-//-------------+---+---+---+---+---+---+
-// fast i4/i16 | x | x | | | | |
-//-------------+---+---+---+---+---+---+
-// rd-opt i4/16| | | x | x | x | x |
-//-------------+---+---+---+---+---+---+
-// Trellis | | x | | | x | x |
-//-------------+---+---+---+---+---+---+
-// full-SNS | | | | | | x |
-//-------------+---+---+---+---+---+---+
+// Mapping from config->method_ to coding tools used.
+//-------------------+---+---+---+---+---+---+---+
+// Method | 0 | 1 | 2 | 3 |(4)| 5 | 6 |
+//-------------------+---+---+---+---+---+---+---+
+// fast probe | x | | | x | | | |
+//-------------------+---+---+---+---+---+---+---+
+// dynamic proba | ~ | x | x | x | x | x | x |
+//-------------------+---+---+---+---+---+---+---+
+// fast mode analysis| | | | | x | x | x |
+//-------------------+---+---+---+---+---+---+---+
+// basic rd-opt | | | | x | x | x | x |
+//-------------------+---+---+---+---+---+---+---+
+// disto-score i4/16 | | | x | | | | |
+//-------------------+---+---+---+---+---+---+---+
+// rd-opt i4/16 | | | ~ | x | x | x | x |
+//-------------------+---+---+---+---+---+---+---+
+// token buffer (opt)| | | | x | x | x | x |
+//-------------------+---+---+---+---+---+---+---+
+// Trellis | | | | | | x |Ful|
+//-------------------+---+---+---+---+---+---+---+
+// full-SNS | | | | | x | x | x |
+//-------------------+---+---+---+---+---+---+---+
static void MapConfigToTools(VP8Encoder* const enc) {
- const int method = enc->config_->method;
- const int limit = 100 - enc->config_->partition_limit;
+ const WebPConfig* const config = enc->config_;
+ const int method = config->method;
+ const int limit = 100 - config->partition_limit;
enc->method_ = method;
- enc->rd_opt_level_ = (method >= 6) ? 3
- : (method >= 5) ? 2
- : (method >= 3) ? 1
- : 0;
+ enc->rd_opt_level_ = (method >= 6) ? RD_OPT_TRELLIS_ALL
+ : (method >= 5) ? RD_OPT_TRELLIS
+ : (method >= 3) ? RD_OPT_BASIC
+ : RD_OPT_NONE;
enc->max_i4_header_bits_ =
256 * 16 * 16 * // upper bound: up to 16bit per 4x4 block
(limit * limit) / (100 * 100); // ... modulated with a quadratic curve.
+
+ enc->thread_level_ = config->thread_level;
+
+ enc->do_search_ = (config->target_size > 0 || config->target_PSNR > 0);
+ if (!config->low_memory) {
+#if !defined(DISABLE_TOKEN_BUFFER)
+ enc->use_tokens_ = (enc->rd_opt_level_ >= RD_OPT_BASIC); // need rd stats
+#endif
+ if (enc->use_tokens_) {
+ enc->num_parts_ = 1; // doesn't work with multi-partition
+ }
+ }
}
// Memory scaling with dimensions:
// memory (bytes) ~= 2.25 * w + 0.0625 * w * h
//
-// Typical memory footprint (768x510 picture)
-// Memory used:
-// encoder: 33919
-// block cache: 2880
-// info: 3072
-// preds: 24897
-// top samples: 1623
-// non-zero: 196
-// lf-stats: 2048
-// total: 68635
-// Transcient object sizes:
-// VP8EncIterator: 352
-// VP8ModeScore: 912
-// VP8SegmentInfo: 532
-// VP8Proba: 31032
+// Typical memory footprint (614x440 picture)
+// encoder: 22111
+// info: 4368
+// preds: 17741
+// top samples: 1263
+// non-zero: 175
+// lf-stats: 0
+// total: 45658
+// Transient object sizes:
+// VP8EncIterator: 3360
+// VP8ModeScore: 872
+// VP8SegmentInfo: 732
+// VP8EncProba: 18352
// LFStats: 2048
-// Picture size (yuv): 589824
+// Picture size (yuv): 419328
static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
WebPPicture* const picture) {
@@ -154,20 +145,16 @@ static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
const int preds_h = 4 * mb_h + 1;
const size_t preds_size = preds_w * preds_h * sizeof(uint8_t);
const int top_stride = mb_w * 16;
- const size_t nz_size = (mb_w + 1) * sizeof(uint32_t);
- const size_t cache_size = (3 * YUV_SIZE + PRED_SIZE) * sizeof(uint8_t);
+ const size_t nz_size = (mb_w + 1) * sizeof(uint32_t) + WEBP_ALIGN_CST;
const size_t info_size = mb_w * mb_h * sizeof(VP8MBInfo);
- const size_t samples_size = (2 * top_stride + // top-luma/u/v
- 16 + 16 + 16 + 8 + 1 + // left y/u/v
- 2 * ALIGN_CST) // align all
- * sizeof(uint8_t);
+ const size_t samples_size = 2 * top_stride * sizeof(uint8_t) // top-luma/u/v
+ + WEBP_ALIGN_CST; // align all
const size_t lf_stats_size =
- config->autofilter ? sizeof(LFStats) + ALIGN_CST : 0;
+ config->autofilter ? sizeof(LFStats) + WEBP_ALIGN_CST : 0;
VP8Encoder* enc;
uint8_t* mem;
const uint64_t size = (uint64_t)sizeof(VP8Encoder) // main struct
- + ALIGN_CST // cache alignment
- + cache_size // working caches
+ + WEBP_ALIGN_CST // cache alignment
+ info_size // modes info
+ preds_size // prediction modes
+ samples_size // top/left samples
@@ -178,23 +165,22 @@ static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
printf("===================================\n");
printf("Memory used:\n"
" encoder: %ld\n"
- " block cache: %ld\n"
" info: %ld\n"
" preds: %ld\n"
" top samples: %ld\n"
" non-zero: %ld\n"
" lf-stats: %ld\n"
" total: %ld\n",
- sizeof(VP8Encoder) + ALIGN_CST, cache_size, info_size,
+ sizeof(VP8Encoder) + WEBP_ALIGN_CST, info_size,
preds_size, samples_size, nz_size, lf_stats_size, size);
- printf("Transcient object sizes:\n"
+ printf("Transient object sizes:\n"
" VP8EncIterator: %ld\n"
" VP8ModeScore: %ld\n"
" VP8SegmentInfo: %ld\n"
- " VP8Proba: %ld\n"
+ " VP8EncProba: %ld\n"
" LFStats: %ld\n",
sizeof(VP8EncIterator), sizeof(VP8ModeScore),
- sizeof(VP8SegmentInfo), sizeof(VP8Proba),
+ sizeof(VP8SegmentInfo), sizeof(VP8EncProba),
sizeof(LFStats));
printf("Picture size (yuv): %ld\n",
mb_w * mb_h * 384 * sizeof(uint8_t));
@@ -206,41 +192,27 @@ static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
return NULL;
}
enc = (VP8Encoder*)mem;
- mem = (uint8_t*)DO_ALIGN(mem + sizeof(*enc));
+ mem = (uint8_t*)WEBP_ALIGN(mem + sizeof(*enc));
memset(enc, 0, sizeof(*enc));
enc->num_parts_ = 1 << config->partitions;
enc->mb_w_ = mb_w;
enc->mb_h_ = mb_h;
enc->preds_w_ = preds_w;
- enc->yuv_in_ = (uint8_t*)mem;
- mem += YUV_SIZE;
- enc->yuv_out_ = (uint8_t*)mem;
- mem += YUV_SIZE;
- enc->yuv_out2_ = (uint8_t*)mem;
- mem += YUV_SIZE;
- enc->yuv_p_ = (uint8_t*)mem;
- mem += PRED_SIZE;
enc->mb_info_ = (VP8MBInfo*)mem;
mem += info_size;
enc->preds_ = ((uint8_t*)mem) + 1 + enc->preds_w_;
mem += preds_w * preds_h * sizeof(uint8_t);
- enc->nz_ = 1 + (uint32_t*)mem;
+ enc->nz_ = 1 + (uint32_t*)WEBP_ALIGN(mem);
mem += nz_size;
- enc->lf_stats_ = lf_stats_size ? (LFStats*)DO_ALIGN(mem) : NULL;
+ enc->lf_stats_ = lf_stats_size ? (LFStats*)WEBP_ALIGN(mem) : NULL;
mem += lf_stats_size;
// top samples (all 16-aligned)
- mem = (uint8_t*)DO_ALIGN(mem);
+ mem = (uint8_t*)WEBP_ALIGN(mem);
enc->y_top_ = (uint8_t*)mem;
enc->uv_top_ = enc->y_top_ + top_stride;
mem += 2 * top_stride;
- mem = (uint8_t*)DO_ALIGN(mem + 1);
- enc->y_left_ = (uint8_t*)mem;
- mem += 16 + 16;
- enc->u_left_ = (uint8_t*)mem;
- mem += 16;
- enc->v_left_ = (uint8_t*)mem;
- mem += 8;
+ assert(mem <= (uint8_t*)enc + size);
enc->config_ = config;
enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2;
@@ -253,29 +225,32 @@ static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
ResetSegmentHeader(enc);
ResetFilterHeader(enc);
ResetBoundaryPredictions(enc);
-
+ VP8EncDspCostInit();
VP8EncInitAlpha(enc);
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- VP8EncInitLayer(enc);
-#endif
+ // lower quality means smaller output -> we modulate a little the page
+ // size based on quality. This is just a crude 1rst-order prediction.
+ {
+ const float scale = 1.f + config->quality * 5.f / 100.f; // in [1,6]
+ VP8TBufferInit(&enc->tokens_, (int)(mb_w * mb_h * 4 * scale));
+ }
return enc;
}
-static void DeleteVP8Encoder(VP8Encoder* enc) {
+static int DeleteVP8Encoder(VP8Encoder* enc) {
+ int ok = 1;
if (enc != NULL) {
- VP8EncDeleteAlpha(enc);
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- VP8EncDeleteLayer(enc);
-#endif
- free(enc);
+ ok = VP8EncDeleteAlpha(enc);
+ VP8TBufferClear(&enc->tokens_);
+ WebPSafeFree(enc);
}
+ return ok;
}
//------------------------------------------------------------------------------
static double GetPSNR(uint64_t err, uint64_t size) {
- return err ? 10. * log10(255. * 255. * size / err) : 99.;
+ return (err > 0 && size > 0) ? 10. * log10(255. * 255. * size / err) : 99.;
}
static void FinalizePSNR(const VP8Encoder* const enc) {
@@ -332,7 +307,7 @@ int WebPReportProgress(const WebPPicture* const pic,
//------------------------------------------------------------------------------
int WebPEncode(const WebPConfig* config, WebPPicture* pic) {
- int ok;
+ int ok = 0;
if (pic == NULL)
return 0;
@@ -346,44 +321,63 @@ int WebPEncode(const WebPConfig* config, WebPPicture* pic) {
if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION)
return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
+ if (!config->exact) {
+ WebPCleanupTransparentArea(pic);
+ }
+
if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats));
if (!config->lossless) {
VP8Encoder* enc = NULL;
- if (pic->y == NULL || pic->u == NULL || pic->v == NULL) {
- if (pic->argb != NULL) {
- if (!WebPPictureARGBToYUVA(pic, WEBP_YUV420)) return 0;
+ if (pic->use_argb || pic->y == NULL || pic->u == NULL || pic->v == NULL) {
+ // Make sure we have YUVA samples.
+ if (config->preprocessing & 4) {
+ if (!WebPPictureSmartARGBToYUVA(pic)) {
+ return 0;
+ }
} else {
- return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
+ float dithering = 0.f;
+ if (config->preprocessing & 2) {
+ const float x = config->quality / 100.f;
+ const float x2 = x * x;
+ // slowly decreasing from max dithering at low quality (q->0)
+ // to 0.5 dithering amplitude at high quality (q->100)
+ dithering = 1.0f + (0.5f - 1.0f) * x2 * x2;
+ }
+ if (!WebPPictureARGBToYUVADithered(pic, WEBP_YUV420, dithering)) {
+ return 0;
+ }
}
}
enc = InitVP8Encoder(config, pic);
if (enc == NULL) return 0; // pic->error is already set.
// Note: each of the tasks below account for 20% in the progress report.
- ok = VP8EncAnalyze(enc)
- && VP8StatLoop(enc)
- && VP8EncLoop(enc)
- && VP8EncFinishAlpha(enc)
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- && VP8EncFinishLayer(enc)
-#endif
- && VP8EncWrite(enc);
+ ok = VP8EncAnalyze(enc);
+
+ // Analysis is done, proceed to actual coding.
+ ok = ok && VP8EncStartAlpha(enc); // possibly done in parallel
+ if (!enc->use_tokens_) {
+ ok = ok && VP8EncLoop(enc);
+ } else {
+ ok = ok && VP8EncTokenLoop(enc);
+ }
+ ok = ok && VP8EncFinishAlpha(enc);
+
+ ok = ok && VP8EncWrite(enc);
StoreStats(enc);
if (!ok) {
VP8EncFreeBitWriters(enc);
}
- DeleteVP8Encoder(enc);
+ ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok
} else {
- if (pic->argb == NULL)
- return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
+ // Make sure we have ARGB samples.
+ if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) {
+ return 0;
+ }
ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem.
}
return ok;
}
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/encode.h b/drivers/webp/encode.h
index 2e37cfabe7..c382ea7608 100644
--- a/drivers/webp/encode.h
+++ b/drivers/webp/encode.h
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// WebP encoder: main interface
@@ -14,11 +16,22 @@
#include "./types.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
-#define WEBP_ENCODER_ABI_VERSION 0x0200 // MAJOR(8b) + MINOR(8b)
+#define WEBP_ENCODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b)
+
+// Note: forward declaring enumerations is not allowed in (strict) C and C++,
+// the types are left here for reference.
+// typedef enum WebPImageHint WebPImageHint;
+// typedef enum WebPEncCSP WebPEncCSP;
+// typedef enum WebPPreset WebPPreset;
+// typedef enum WebPEncodingError WebPEncodingError;
+typedef struct WebPConfig WebPConfig;
+typedef struct WebPPicture WebPPicture; // main structure for I/O
+typedef struct WebPAuxStats WebPAuxStats;
+typedef struct WebPMemoryWriter WebPMemoryWriter;
// Return the encoder's version number, packed in hexadecimal using 8bits for
// each of major/minor/revision. E.g: v2.5.7 is 0x020507.
@@ -29,7 +42,7 @@ WEBP_EXTERN(int) WebPGetEncoderVersion(void);
// Returns the size of the compressed data (pointed to by *output), or 0 if
// an error occurred. The compressed data must be released by the caller
-// using the call 'free(*output)'.
+// using the call 'WebPFree(*output)'.
// These functions compress using the lossy format, and the quality_factor
// can go from 0 (smaller output, lower quality) to 100 (best quality,
// larger output).
@@ -62,11 +75,14 @@ WEBP_EXTERN(size_t) WebPEncodeLosslessBGRA(const uint8_t* bgra,
int width, int height, int stride,
uint8_t** output);
+// Releases memory returned by the WebPEncode*() functions above.
+WEBP_EXTERN(void) WebPFree(void* ptr);
+
//------------------------------------------------------------------------------
// Coding parameters
// Image characteristics hint for the underlying encoder.
-typedef enum {
+typedef enum WebPImageHint {
WEBP_HINT_DEFAULT = 0, // default preset.
WEBP_HINT_PICTURE, // digital picture, like portrait, inner shot
WEBP_HINT_PHOTO, // outdoor photograph, with natural lighting
@@ -74,7 +90,8 @@ typedef enum {
WEBP_HINT_LAST
} WebPImageHint;
-typedef struct {
+// Compression parameters.
+struct WebPConfig {
int lossless; // Lossless encoding (0=lossy(default), 1=lossless).
float quality; // between 0 (smallest file) and 100 (biggest)
int method; // quality/speed trade-off (0=fast, 6=slower-better)
@@ -103,19 +120,38 @@ typedef struct {
int show_compressed; // if true, export the compressed picture back.
// In-loop filtering is not applied.
- int preprocessing; // preprocessing filter (0=none, 1=segment-smooth)
+ int preprocessing; // preprocessing filter:
+ // 0=none, 1=segment-smooth, 2=pseudo-random dithering
int partitions; // log2(number of token partitions) in [0..3]. Default
// is set to 0 for easier progressive decoding.
int partition_limit; // quality degradation allowed to fit the 512k limit
// on prediction modes coding (0: no degradation,
// 100: maximum possible degradation).
-
- uint32_t pad[8]; // padding for later use
-} WebPConfig;
+ int emulate_jpeg_size; // If true, compression parameters will be remapped
+ // to better match the expected output size from
+ // JPEG compression. Generally, the output size will
+ // be similar but the degradation will be lower.
+ int thread_level; // If non-zero, try and use multi-threaded encoding.
+ int low_memory; // If set, reduce memory usage (but increase CPU use).
+
+ int near_lossless; // Near lossless encoding [0 = off(default) .. 100].
+ // This feature is experimental.
+ int exact; // if non-zero, preserve the exact RGB values under
+ // transparent area. Otherwise, discard this invisible
+ // RGB information for better compression. The default
+ // value is 0.
+
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ int delta_palettization;
+ uint32_t pad[2]; // padding for later use
+#else
+ uint32_t pad[3]; // padding for later use
+#endif // WEBP_EXPERIMENTAL_FEATURES
+};
// Enumerate some predefined settings for WebPConfig, depending on the type
// of source picture. These presets are used when calling WebPConfigPreset().
-typedef enum {
+typedef enum WebPPreset {
WEBP_PRESET_DEFAULT = 0, // default preset.
WEBP_PRESET_PICTURE, // digital picture, like portrait, inner shot
WEBP_PRESET_PHOTO, // outdoor photograph, with natural lighting
@@ -146,17 +182,23 @@ static WEBP_INLINE int WebPConfigPreset(WebPConfig* config,
WEBP_ENCODER_ABI_VERSION);
}
+// Activate the lossless compression mode with the desired efficiency level
+// between 0 (fastest, lowest compression) and 9 (slower, best compression).
+// A good default level is '6', providing a fair tradeoff between compression
+// speed and final compressed size.
+// This function will overwrite several fields from config: 'method', 'quality'
+// and 'lossless'. Returns false in case of parameter error.
+WEBP_EXTERN(int) WebPConfigLosslessPreset(WebPConfig* config, int level);
+
// Returns true if 'config' is non-NULL and all configuration parameters are
// within their valid ranges.
WEBP_EXTERN(int) WebPValidateConfig(const WebPConfig* config);
//------------------------------------------------------------------------------
// Input / Output
-
-typedef struct WebPPicture WebPPicture; // main structure for I/O
-
// Structure for storing auxiliary statistics (mostly for lossy encoding).
-typedef struct {
+
+struct WebPAuxStats {
int coded_size; // final size
float PSNR[5]; // peak-signal-to-noise ratio for Y/U/V/All/Alpha
@@ -180,9 +222,11 @@ typedef struct {
int cache_bits; // number of bits for color cache lookup
int palette_size; // number of color in palette, if used
int lossless_size; // final lossless size
+ int lossless_hdr_size; // lossless header (transform, huffman etc) size
+ int lossless_data_size; // lossless image data size
- uint32_t pad[4]; // padding for later use
-} WebPAuxStats;
+ uint32_t pad[2]; // padding for later use
+};
// Signature for output function. Should return true if writing was successful.
// data/data_size is the segment of data to write, and 'picture' is for
@@ -192,18 +236,22 @@ typedef int (*WebPWriterFunction)(const uint8_t* data, size_t data_size,
// WebPMemoryWrite: a special WebPWriterFunction that writes to memory using
// the following WebPMemoryWriter object (to be set as a custom_ptr).
-typedef struct {
+struct WebPMemoryWriter {
uint8_t* mem; // final buffer (of size 'max_size', larger than 'size').
size_t size; // final size
size_t max_size; // total capacity
uint32_t pad[1]; // padding for later use
-} WebPMemoryWriter;
+};
// The following must be called first before any use.
WEBP_EXTERN(void) WebPMemoryWriterInit(WebPMemoryWriter* writer);
+// The following must be called to deallocate writer->mem memory. The 'writer'
+// object itself is not deallocated.
+WEBP_EXTERN(void) WebPMemoryWriterClear(WebPMemoryWriter* writer);
// The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon
// completion, writer.mem and writer.size will hold the coded data.
+// writer.mem must be freed by calling WebPMemoryWriterClear.
WEBP_EXTERN(int) WebPMemoryWrite(const uint8_t* data, size_t data_size,
const WebPPicture* picture);
@@ -212,23 +260,17 @@ WEBP_EXTERN(int) WebPMemoryWrite(const uint8_t* data, size_t data_size,
// everything is OK.
typedef int (*WebPProgressHook)(int percent, const WebPPicture* picture);
-typedef enum {
+// Color spaces.
+typedef enum WebPEncCSP {
// chroma sampling
- WEBP_YUV420 = 0, // 4:2:0
- WEBP_YUV422 = 1, // 4:2:2
- WEBP_YUV444 = 2, // 4:4:4
- WEBP_YUV400 = 3, // grayscale
- WEBP_CSP_UV_MASK = 3, // bit-mask to get the UV sampling factors
- // alpha channel variants
- WEBP_YUV420A = 4,
- WEBP_YUV422A = 5,
- WEBP_YUV444A = 6,
- WEBP_YUV400A = 7, // grayscale + alpha
+ WEBP_YUV420 = 0, // 4:2:0
+ WEBP_YUV420A = 4, // alpha channel variant
+ WEBP_CSP_UV_MASK = 3, // bit-mask to get the UV sampling factors
WEBP_CSP_ALPHA_BIT = 4 // bit that is set if alpha is present
} WebPEncCSP;
// Encoding error conditions.
-typedef enum {
+typedef enum WebPEncodingError {
VP8_ENC_OK = 0,
VP8_ENC_ERROR_OUT_OF_MEMORY, // memory error allocating objects
VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, // memory error while flushing bits
@@ -248,7 +290,6 @@ typedef enum {
// Main exchange structure (input samples, output bytes, statistics)
struct WebPPicture {
-
// INPUT
//////////////
// Main flag for encoder selecting between ARGB or YUV input.
@@ -303,17 +344,15 @@ struct WebPPicture {
uint32_t pad3[3]; // padding for later use
- // Unused for now: original samples (for non-YUV420 modes)
- uint8_t *u0, *v0;
- int uv0_stride;
-
- uint32_t pad4[7]; // padding for later use
+ // Unused for now
+ uint8_t *pad4, *pad5;
+ uint32_t pad6[8]; // padding for later use
// PRIVATE FIELDS
////////////////////
void* memory_; // row chunk of memory for yuva planes
void* memory_argb_; // and for argb too.
- void* pad5[2]; // padding for later use
+ void* pad7[2]; // padding for later use
};
// Internal, version-checked, entry point
@@ -343,18 +382,19 @@ WEBP_EXTERN(int) WebPPictureAlloc(WebPPicture* picture);
// preserved.
WEBP_EXTERN(void) WebPPictureFree(WebPPicture* picture);
-// Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return,
-// *dst will fully own the copied pixels (this is not a view).
+// Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return, *dst
+// will fully own the copied pixels (this is not a view). The 'dst' picture need
+// not be initialized as its content is overwritten.
// Returns false in case of memory allocation error.
WEBP_EXTERN(int) WebPPictureCopy(const WebPPicture* src, WebPPicture* dst);
-// Compute PSNR or SSIM distortion between two pictures.
-// Result is in dB, stores in result[] in the Y/U/V/Alpha/All order.
-// Returns false in case of error (pic1 and pic2 don't have same dimension, ...)
+// Compute PSNR, SSIM or LSIM distortion metric between two pictures. Results
+// are in dB, stored in result[] in the Y/U/V/Alpha/All or B/G/R/A/All order.
+// Returns false in case of error (src and ref don't have same dimension, ...)
// Warning: this function is rather CPU-intensive.
WEBP_EXTERN(int) WebPPictureDistortion(
- const WebPPicture* pic1, const WebPPicture* pic2,
- int metric_type, // 0 = PSNR, 1 = SSIM
+ const WebPPicture* src, const WebPPicture* ref,
+ int metric_type, // 0 = PSNR, 1 = SSIM, 2 = LSIM
float result[5]);
// self-crops a picture to the rectangle defined by top/left/width/height.
@@ -375,7 +415,9 @@ WEBP_EXTERN(int) WebPPictureCrop(WebPPicture* picture,
// the top and left coordinates will be snapped to even values.
// Picture 'src' must out-live 'dst' picture. Self-extraction of view is allowed
// ('src' equal to 'dst') as a mean of fast-cropping (but note that doing so,
-// the original dimension will be lost).
+// the original dimension will be lost). Picture 'dst' need not be initialized
+// with WebPPictureInit() if it is different from 'src', since its content will
+// be overwritten.
// Returns false in case of memory allocation error or invalid parameters.
WEBP_EXTERN(int) WebPPictureView(const WebPPicture* src,
int left, int top, int width, int height,
@@ -386,7 +428,9 @@ WEBP_EXTERN(int) WebPPictureView(const WebPPicture* src,
WEBP_EXTERN(int) WebPPictureIsView(const WebPPicture* picture);
// Rescale a picture to new dimension width x height.
-// Now gamma correction is applied.
+// If either 'width' or 'height' (but not both) is 0 the corresponding
+// dimension will be calculated preserving the aspect ratio.
+// No gamma correction is applied.
// Returns false in case of error (invalid parameter or insufficient memory).
WEBP_EXTERN(int) WebPPictureRescale(WebPPicture* pic, int width, int height);
@@ -413,13 +457,28 @@ WEBP_EXTERN(int) WebPPictureImportBGRA(
WEBP_EXTERN(int) WebPPictureImportBGRX(
WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride);
-// Converts picture->argb data to the YUVA format specified by 'colorspace'.
+// Converts picture->argb data to the YUV420A format. The 'colorspace'
+// parameter is deprecated and should be equal to WEBP_YUV420.
// Upon return, picture->use_argb is set to false. The presence of real
// non-opaque transparent values is detected, and 'colorspace' will be
// adjusted accordingly. Note that this method is lossy.
// Returns false in case of error.
WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture,
- WebPEncCSP colorspace);
+ WebPEncCSP /*colorspace = WEBP_YUV420*/);
+
+// Same as WebPPictureARGBToYUVA(), but the conversion is done using
+// pseudo-random dithering with a strength 'dithering' between
+// 0.0 (no dithering) and 1.0 (maximum dithering). This is useful
+// for photographic picture.
+WEBP_EXTERN(int) WebPPictureARGBToYUVADithered(
+ WebPPicture* picture, WebPEncCSP colorspace, float dithering);
+
+// Performs 'smart' RGBA->YUVA420 downsampling and colorspace conversion.
+// Downsampling is handled with extra care in case of color clipping. This
+// method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better
+// YUV representation.
+// Returns false in case of error.
+WEBP_EXTERN(int) WebPPictureSmartARGBToYUVA(WebPPicture* picture);
// Converts picture->yuv to picture->argb and sets picture->use_argb to true.
// The input format must be YUV_420 or YUV_420A.
@@ -429,9 +488,9 @@ WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture,
// Returns false in case of error.
WEBP_EXTERN(int) WebPPictureYUVAToARGB(WebPPicture* picture);
-// Helper function: given a width x height plane of YUV(A) samples
-// (with stride 'stride'), clean-up the YUV samples under fully transparent
-// area, to help compressibility (no guarantee, though).
+// Helper function: given a width x height plane of RGBA or YUV(A) samples
+// clean-up the YUV or RGB samples under fully transparent area, to help
+// compressibility (no guarantee, though).
WEBP_EXTERN(void) WebPCleanupTransparentArea(WebPPicture* picture);
// Scan the picture 'picture' for the presence of non fully opaque alpha values.
@@ -439,6 +498,11 @@ WEBP_EXTERN(void) WebPCleanupTransparentArea(WebPPicture* picture);
// alpha plane can be ignored altogether e.g.).
WEBP_EXTERN(int) WebPPictureHasTransparency(const WebPPicture* picture);
+// Remove the transparency information (if present) by blending the color with
+// the background color 'background_rgb' (specified as 24bit RGB triplet).
+// After this call, all alpha values are reset to 0xff.
+WEBP_EXTERN(void) WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb);
+
//------------------------------------------------------------------------------
// Main call
@@ -456,7 +520,7 @@ WEBP_EXTERN(int) WebPEncode(const WebPConfig* config, WebPPicture* picture);
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/extras.h b/drivers/webp/extras.h
new file mode 100644
index 0000000000..1c24be2e0c
--- /dev/null
+++ b/drivers/webp/extras.h
@@ -0,0 +1,51 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+
+#ifndef WEBP_WEBP_EXTRAS_H_
+#define WEBP_WEBP_EXTRAS_H_
+
+#include "./types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "./encode.h"
+
+#define WEBP_EXTRAS_ABI_VERSION 0x0000 // MAJOR(8b) + MINOR(8b)
+
+//------------------------------------------------------------------------------
+
+// Returns the version number of the extras library, packed in hexadecimal using
+// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507.
+WEBP_EXTERN(int) WebPGetExtrasVersion(void);
+
+//------------------------------------------------------------------------------
+// Ad-hoc colorspace importers.
+
+// Import luma sample (gray scale image) into 'picture'. The 'picture'
+// width and height must be set prior to calling this function.
+WEBP_EXTERN(int) WebPImportGray(const uint8_t* gray, WebPPicture* picture);
+
+// Import rgb sample in RGB565 packed format into 'picture'. The 'picture'
+// width and height must be set prior to calling this function.
+WEBP_EXTERN(int) WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic);
+
+// Import rgb sample in RGB4444 packed format into 'picture'. The 'picture'
+// width and height must be set prior to calling this function.
+WEBP_EXTERN(int) WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic);
+
+//------------------------------------------------------------------------------
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_WEBP_EXTRAS_H_ */
diff --git a/drivers/webp/format_constants.h b/drivers/webp/format_constants.h
index 7ce498f672..b6e78a643e 100644
--- a/drivers/webp/format_constants.h
+++ b/drivers/webp/format_constants.h
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Internal header for constants related to WebP file format.
@@ -12,6 +14,9 @@
#ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_
#define WEBP_WEBP_FORMAT_CONSTANTS_H_
+// Create fourcc of the chunk from the chunk tag characters.
+#define MKFOURCC(a, b, c, d) ((a) | (b) << 8 | (c) << 16 | (uint32_t)(d) << 24)
+
// VP8 related constants.
#define VP8_SIGNATURE 0x9d012a // Signature in VP8 data.
#define VP8_MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition
@@ -65,23 +70,16 @@ typedef enum {
#define CHUNK_SIZE_BYTES 4 // Size needed to store chunk's size.
#define CHUNK_HEADER_SIZE 8 // Size of a chunk header.
#define RIFF_HEADER_SIZE 12 // Size of the RIFF header ("RIFFnnnnWEBP").
-#define FRAME_CHUNK_SIZE 15 // Size of a FRM chunk.
-#define LOOP_CHUNK_SIZE 2 // Size of a LOOP chunk.
-#define TILE_CHUNK_SIZE 6 // Size of a TILE chunk.
+#define ANMF_CHUNK_SIZE 16 // Size of an ANMF chunk.
+#define ANIM_CHUNK_SIZE 6 // Size of an ANIM chunk.
+#define FRGM_CHUNK_SIZE 6 // Size of a FRGM chunk.
#define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk.
-#define TILING_FLAG_BIT 0x01 // Set if tiles are possibly used.
-#define ANIMATION_FLAG_BIT 0x02 // Set if some animation is expected
-#define ICC_FLAG_BIT 0x04 // Whether ICC is present or not.
-#define METADATA_FLAG_BIT 0x08 // Set if some META chunk is possibly present.
-#define ALPHA_FLAG_BIT 0x10 // Should be same as the ALPHA_FLAG in mux.h
-#define ROTATION_FLAG_BITS 0xe0 // all 3 bits for rotation + symmetry
-
-#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height.
-#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height.
-#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count
-#define MAX_DURATION (1 << 24) // maximum duration
-#define MAX_POSITION_OFFSET (1 << 24) // maximum frame/tile x/y offset
+#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height.
+#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height.
+#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count
+#define MAX_DURATION (1 << 24) // maximum duration
+#define MAX_POSITION_OFFSET (1 << 24) // maximum frame/fragment x/y offset
// Maximum chunk payload is such that adding the header and padding won't
// overflow a uint32_t.
diff --git a/drivers/webp/image_loader_webp.cpp b/drivers/webp/image_loader_webp.cpp
index 9d8a616556..5fb14eaf7a 100644
--- a/drivers/webp/image_loader_webp.cpp
+++ b/drivers/webp/image_loader_webp.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/drivers/webp/image_loader_webp.h b/drivers/webp/image_loader_webp.h
index 8fc188cc9c..ea99a60676 100644
--- a/drivers/webp/image_loader_webp.h
+++ b/drivers/webp/image_loader_webp.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/drivers/webp/mux.h b/drivers/webp/mux.h
index 5139af80fa..1fddfb76d4 100644
--- a/drivers/webp/mux.h
+++ b/drivers/webp/mux.h
@@ -1,60 +1,76 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
-// RIFF container manipulation for WEBP images.
+// RIFF container manipulation and encoding for WebP images.
//
// Authors: Urvang (urvang@google.com)
// Vikas (vikasa@google.com)
-// This API allows manipulation of WebP container images containing features
-// like Color profile, XMP metadata, Animation and Tiling.
-//
-// Code Example#1: Creating a MUX with image data, color profile and XMP
-// metadata.
-//
-// int copy_data = 0;
-// WebPMux* mux = WebPMuxNew();
-// // ... (Prepare image data).
-// WebPMuxSetImage(mux, &image, copy_data);
-// // ... (Prepare ICCP color profile data).
-// WebPMuxSetColorProfile(mux, &icc_profile, copy_data);
-// // ... (Prepare XMP metadata).
-// WebPMuxSetMetadata(mux, &xmp, copy_data);
-// // Get data from mux in WebP RIFF format.
-// WebPMuxAssemble(mux, &output_data);
-// WebPMuxDelete(mux);
-// // ... (Consume output_data; e.g. write output_data.bytes_ to file).
-// WebPDataClear(&output_data);
-//
-// Code Example#2: Get image and color profile data from a WebP file.
-//
-// int copy_data = 0;
-// // ... (Read data from file).
-// WebPMux* mux = WebPMuxCreate(&data, copy_data);
-// WebPMuxGetImage(mux, &image);
-// // ... (Consume image; e.g. call WebPDecode() to decode the data).
-// WebPMuxGetColorProfile(mux, &icc_profile);
-// // ... (Consume icc_data).
-// WebPMuxDelete(mux);
-// free(data);
-
#ifndef WEBP_WEBP_MUX_H_
#define WEBP_WEBP_MUX_H_
-#include "./types.h"
+#include "./mux_types.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
-#define WEBP_MUX_ABI_VERSION 0x0100 // MAJOR(8b) + MINOR(8b)
+#define WEBP_MUX_ABI_VERSION 0x0106 // MAJOR(8b) + MINOR(8b)
+
+//------------------------------------------------------------------------------
+// Mux API
+//
+// This API allows manipulation of WebP container images containing features
+// like color profile, metadata, animation and fragmented images.
+//
+// Code Example#1: Create a WebPMux object with image data, color profile and
+// XMP metadata.
+/*
+ int copy_data = 0;
+ WebPMux* mux = WebPMuxNew();
+ // ... (Prepare image data).
+ WebPMuxSetImage(mux, &image, copy_data);
+ // ... (Prepare ICCP color profile data).
+ WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data);
+ // ... (Prepare XMP metadata).
+ WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data);
+ // Get data from mux in WebP RIFF format.
+ WebPMuxAssemble(mux, &output_data);
+ WebPMuxDelete(mux);
+ // ... (Consume output_data; e.g. write output_data.bytes to file).
+ WebPDataClear(&output_data);
+*/
+
+// Code Example#2: Get image and color profile data from a WebP file.
+/*
+ int copy_data = 0;
+ // ... (Read data from file).
+ WebPMux* mux = WebPMuxCreate(&data, copy_data);
+ WebPMuxGetFrame(mux, 1, &image);
+ // ... (Consume image; e.g. call WebPDecode() to decode the data).
+ WebPMuxGetChunk(mux, "ICCP", &icc_profile);
+ // ... (Consume icc_data).
+ WebPMuxDelete(mux);
+ free(data);
+*/
+
+// Note: forward declaring enumerations is not allowed in (strict) C and C++,
+// the types are left here for reference.
+// typedef enum WebPMuxError WebPMuxError;
+// typedef enum WebPChunkId WebPChunkId;
+typedef struct WebPMux WebPMux; // main opaque object.
+typedef struct WebPMuxFrameInfo WebPMuxFrameInfo;
+typedef struct WebPMuxAnimParams WebPMuxAnimParams;
+typedef struct WebPAnimEncoderOptions WebPAnimEncoderOptions;
// Error codes
-typedef enum {
+typedef enum WebPMuxError {
WEBP_MUX_OK = 1,
WEBP_MUX_NOT_FOUND = 0,
WEBP_MUX_INVALID_ARGUMENT = -1,
@@ -63,51 +79,26 @@ typedef enum {
WEBP_MUX_NOT_ENOUGH_DATA = -4
} WebPMuxError;
-// Flag values for different features used in VP8X chunk.
-typedef enum {
- TILE_FLAG = 0x00000001,
- ANIMATION_FLAG = 0x00000002,
- ICCP_FLAG = 0x00000004,
- META_FLAG = 0x00000008,
- ALPHA_FLAG = 0x00000010
-} WebPFeatureFlags;
-
// IDs for different types of chunks.
-typedef enum {
+typedef enum WebPChunkId {
WEBP_CHUNK_VP8X, // VP8X
WEBP_CHUNK_ICCP, // ICCP
- WEBP_CHUNK_LOOP, // LOOP
- WEBP_CHUNK_FRAME, // FRM
- WEBP_CHUNK_TILE, // TILE
+ WEBP_CHUNK_ANIM, // ANIM
+ WEBP_CHUNK_ANMF, // ANMF
+ WEBP_CHUNK_FRGM, // FRGM
WEBP_CHUNK_ALPHA, // ALPH
WEBP_CHUNK_IMAGE, // VP8/VP8L
- WEBP_CHUNK_META, // META
+ WEBP_CHUNK_EXIF, // EXIF
+ WEBP_CHUNK_XMP, // XMP
WEBP_CHUNK_UNKNOWN, // Other chunks.
WEBP_CHUNK_NIL
} WebPChunkId;
-typedef struct WebPMux WebPMux; // main opaque object.
-
-// Data type used to describe 'raw' data, e.g., chunk data
-// (ICC profile, metadata) and WebP compressed image data.
-typedef struct {
- const uint8_t* bytes_;
- size_t size_;
-} WebPData;
-
//------------------------------------------------------------------------------
-// Manipulation of a WebPData object.
-
-// Initializes the contents of the 'webp_data' object with default values.
-WEBP_EXTERN(void) WebPDataInit(WebPData* webp_data);
-// Clears the contents of the 'webp_data' object by calling free(). Does not
-// deallocate the object itself.
-WEBP_EXTERN(void) WebPDataClear(WebPData* webp_data);
-
-// Allocates necessary storage for 'dst' and copies the contents of 'src'.
-// Returns true on success.
-WEBP_EXTERN(int) WebPDataCopy(const WebPData* src, WebPData* dst);
+// Returns the version number of the mux library, packed in hexadecimal using
+// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507.
+WEBP_EXTERN(int) WebPGetMuxVersion(void);
//------------------------------------------------------------------------------
// Life of a Mux object
@@ -118,6 +109,7 @@ WEBP_EXTERN(WebPMux*) WebPNewInternal(int);
// Creates an empty mux object.
// Returns:
// A pointer to the newly created empty mux object.
+// Or NULL in case of memory error.
static WEBP_INLINE WebPMux* WebPMuxNew(void) {
return WebPNewInternal(WEBP_MUX_ABI_VERSION);
}
@@ -136,8 +128,8 @@ WEBP_EXTERN(WebPMux*) WebPMuxCreateInternal(const WebPData*, int, int);
// Creates a mux object from raw data given in WebP RIFF format.
// Parameters:
// bitstream - (in) the bitstream data in WebP RIFF format
-// copy_data - (in) value 1 indicates given data WILL copied to the mux, and
-// value 0 indicates data will NOT be copied.
+// copy_data - (in) value 1 indicates given data WILL be copied to the mux
+// object and value 0 indicates data will NOT be copied.
// Returns:
// A pointer to the mux object created from given data - on success.
// NULL - In case of invalid data or memory error.
@@ -147,295 +139,237 @@ static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream,
}
//------------------------------------------------------------------------------
-// Single Image.
-
-// Sets the image in the mux object. Any existing images (including frame/tile)
-// will be removed.
-// Parameters:
-// mux - (in/out) object in which the image is to be set
-// bitstream - (in) can either be a raw VP8/VP8L bitstream or a single-image
-// WebP file (non-animated and non-tiled)
-// copy_data - (in) value 1 indicates given data WILL copied to the mux, and
-// value 0 indicates data will NOT be copied.
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL.
-// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxSetImage(WebPMux* mux,
- const WebPData* bitstream,
- int copy_data);
-
-// Gets image data from the mux object.
-// The content of 'bitstream' is allocated using malloc(), and NOT
-// owned by the 'mux' object. It MUST be deallocated by the caller by calling
-// WebPDataClear().
-// Parameters:
-// mux - (in) object from which the image is to be fetched
-// bitstream - (out) the image data
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if either mux or bitstream is NULL
-// OR mux contains animation/tiling.
-// WEBP_MUX_NOT_FOUND - if image is not present in mux object.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxGetImage(const WebPMux* mux,
- WebPData* bitstream);
-
-// Deletes the image in the mux object.
-// Parameters:
-// mux - (in/out) object from which the image is to be deleted
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL
-// OR if mux contains animation/tiling.
-// WEBP_MUX_NOT_FOUND - if image is not present in mux object.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxDeleteImage(WebPMux* mux);
+// Non-image chunks.
-//------------------------------------------------------------------------------
-// XMP Metadata.
+// Note: Only non-image related chunks should be managed through chunk APIs.
+// (Image related chunks are: "ANMF", "FRGM", "VP8 ", "VP8L" and "ALPH").
+// To add, get and delete images, use WebPMuxSetImage(), WebPMuxPushFrame(),
+// WebPMuxGetFrame() and WebPMuxDeleteFrame().
-// Sets the XMP metadata in the mux object. Any existing metadata chunk(s) will
-// be removed.
+// Adds a chunk with id 'fourcc' and data 'chunk_data' in the mux object.
+// Any existing chunk(s) with the same id will be removed.
// Parameters:
-// mux - (in/out) object to which the XMP metadata is to be added
-// metadata - (in) the XMP metadata data to be added
-// copy_data - (in) value 1 indicates given data WILL copied to the mux, and
-// value 0 indicates data will NOT be copied.
+// mux - (in/out) object to which the chunk is to be added
+// fourcc - (in) a character array containing the fourcc of the given chunk;
+// e.g., "ICCP", "XMP ", "EXIF" etc.
+// chunk_data - (in) the chunk data to be added
+// copy_data - (in) value 1 indicates given data WILL be copied to the mux
+// object and value 0 indicates data will NOT be copied.
// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux or metadata is NULL.
+// WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL
+// or if fourcc corresponds to an image chunk.
// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxSetMetadata(WebPMux* mux,
- const WebPData* metadata,
- int copy_data);
+WEBP_EXTERN(WebPMuxError) WebPMuxSetChunk(
+ WebPMux* mux, const char fourcc[4], const WebPData* chunk_data,
+ int copy_data);
-// Gets a reference to the XMP metadata in the mux object.
+// Gets a reference to the data of the chunk with id 'fourcc' in the mux object.
// The caller should NOT free the returned data.
// Parameters:
-// mux - (in) object from which the XMP metadata is to be fetched
-// metadata - (out) XMP metadata
+// mux - (in) object from which the chunk data is to be fetched
+// fourcc - (in) a character array containing the fourcc of the chunk;
+// e.g., "ICCP", "XMP ", "EXIF" etc.
+// chunk_data - (out) returned chunk data
// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if either mux or metadata is NULL.
-// WEBP_MUX_NOT_FOUND - if metadata is not present in mux object.
+// WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL
+// or if fourcc corresponds to an image chunk.
+// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given id.
// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxGetMetadata(const WebPMux* mux,
- WebPData* metadata);
+WEBP_EXTERN(WebPMuxError) WebPMuxGetChunk(
+ const WebPMux* mux, const char fourcc[4], WebPData* chunk_data);
-// Deletes the XMP metadata in the mux object.
+// Deletes the chunk with the given 'fourcc' from the mux object.
// Parameters:
-// mux - (in/out) object from which XMP metadata is to be deleted
+// mux - (in/out) object from which the chunk is to be deleted
+// fourcc - (in) a character array containing the fourcc of the chunk;
+// e.g., "ICCP", "XMP ", "EXIF" etc.
// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL
-// WEBP_MUX_NOT_FOUND - If mux does not contain metadata.
+// WEBP_MUX_INVALID_ARGUMENT - if mux or fourcc is NULL
+// or if fourcc corresponds to an image chunk.
+// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given fourcc.
// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxDeleteMetadata(WebPMux* mux);
+WEBP_EXTERN(WebPMuxError) WebPMuxDeleteChunk(
+ WebPMux* mux, const char fourcc[4]);
//------------------------------------------------------------------------------
-// ICC Color Profile.
-
-// Sets the color profile in the mux object. Any existing color profile chunk(s)
-// will be removed.
+// Images.
+
+// Encapsulates data about a single frame/fragment.
+struct WebPMuxFrameInfo {
+ WebPData bitstream; // image data: can be a raw VP8/VP8L bitstream
+ // or a single-image WebP file.
+ int x_offset; // x-offset of the frame.
+ int y_offset; // y-offset of the frame.
+ int duration; // duration of the frame (in milliseconds).
+
+ WebPChunkId id; // frame type: should be one of WEBP_CHUNK_ANMF,
+ // WEBP_CHUNK_FRGM or WEBP_CHUNK_IMAGE
+ WebPMuxAnimDispose dispose_method; // Disposal method for the frame.
+ WebPMuxAnimBlend blend_method; // Blend operation for the frame.
+ uint32_t pad[1]; // padding for later use
+};
+
+// Sets the (non-animated and non-fragmented) image in the mux object.
+// Note: Any existing images (including frames/fragments) will be removed.
// Parameters:
-// mux - (in/out) object to which the color profile is to be added
-// color_profile - (in) the color profile data to be added
-// copy_data - (in) value 1 indicates given data WILL copied to the mux, and
-// value 0 indicates data will NOT be copied.
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux or color_profile is NULL
-// WEBP_MUX_MEMORY_ERROR - on memory allocation error
-// WEBP_MUX_OK - on success
-WEBP_EXTERN(WebPMuxError) WebPMuxSetColorProfile(WebPMux* mux,
- const WebPData* color_profile,
- int copy_data);
-
-// Gets a reference to the color profile in the mux object.
-// The caller should NOT free the returned data.
-// Parameters:
-// mux - (in) object from which the color profile data is to be fetched
-// color_profile - (out) color profile data
+// mux - (in/out) object in which the image is to be set
+// bitstream - (in) can be a raw VP8/VP8L bitstream or a single-image
+// WebP file (non-animated and non-fragmented)
+// copy_data - (in) value 1 indicates given data WILL be copied to the mux
+// object and value 0 indicates data will NOT be copied.
// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if either mux or color_profile is NULL.
-// WEBP_MUX_NOT_FOUND - if color profile is not present in mux object.
+// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL.
+// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxGetColorProfile(const WebPMux* mux,
- WebPData* color_profile);
-
-// Deletes the color profile in the mux object.
+WEBP_EXTERN(WebPMuxError) WebPMuxSetImage(
+ WebPMux* mux, const WebPData* bitstream, int copy_data);
+
+// Adds a frame at the end of the mux object.
+// Notes: (1) frame.id should be one of WEBP_CHUNK_ANMF or WEBP_CHUNK_FRGM
+// (2) For setting a non-animated non-fragmented image, use
+// WebPMuxSetImage() instead.
+// (3) Type of frame being pushed must be same as the frames in mux.
+// (4) As WebP only supports even offsets, any odd offset will be snapped
+// to an even location using: offset &= ~1
// Parameters:
-// mux - (in/out) object from which color profile is to be deleted
+// mux - (in/out) object to which the frame is to be added
+// frame - (in) frame data.
+// copy_data - (in) value 1 indicates given data WILL be copied to the mux
+// object and value 0 indicates data will NOT be copied.
// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL
-// WEBP_MUX_NOT_FOUND - If mux does not contain color profile.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxDeleteColorProfile(WebPMux* mux);
-
-//------------------------------------------------------------------------------
-// Animation.
-
-// Adds an animation frame at the end of the mux object.
-// Note: as WebP only supports even offsets, any odd offset will be snapped to
-// an even location using: offset &= ~1
-// Parameters:
-// mux - (in/out) object to which an animation frame is to be added
-// bitstream - (in) the image data corresponding to the frame. It can either
-// be a raw VP8/VP8L bitstream or a single-image WebP file
-// (non-animated and non-tiled)
-// x_offset - (in) x-offset of the frame to be added
-// y_offset - (in) y-offset of the frame to be added
-// duration - (in) duration of the frame to be added (in milliseconds)
-// copy_data - (in) value 1 indicates given data WILL copied to the mux, and
-// value 0 indicates data will NOT be copied.
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL
+// WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL
+// or if content of 'frame' is invalid.
// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
// WEBP_MUX_OK - on success.
WEBP_EXTERN(WebPMuxError) WebPMuxPushFrame(
- WebPMux* mux, const WebPData* bitstream,
- int x_offset, int y_offset, int duration, int copy_data);
-
-// TODO(urvang): Create a struct as follows to reduce argument list size:
-// typedef struct {
-// WebPData bitstream;
-// int x_offset, y_offset;
-// int duration;
-// } FrameInfo;
-
-// Gets the nth animation frame from the mux object.
-// The content of 'bitstream' is allocated using malloc(), and NOT
+ WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data);
+
+// Gets the nth frame from the mux object.
+// The content of 'frame->bitstream' is allocated using malloc(), and NOT
// owned by the 'mux' object. It MUST be deallocated by the caller by calling
// WebPDataClear().
// nth=0 has a special meaning - last position.
// Parameters:
// mux - (in) object from which the info is to be fetched
// nth - (in) index of the frame in the mux object
-// bitstream - (out) the image data
-// x_offset - (out) x-offset of the returned frame
-// y_offset - (out) y-offset of the returned frame
-// duration - (out) duration of the returned frame (in milliseconds)
+// frame - (out) data of the returned frame
// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if either mux, bitstream, x_offset,
-// y_offset, or duration is NULL
+// WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL.
// WEBP_MUX_NOT_FOUND - if there are less than nth frames in the mux object.
// WEBP_MUX_BAD_DATA - if nth frame chunk in mux is invalid.
+// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
// WEBP_MUX_OK - on success.
WEBP_EXTERN(WebPMuxError) WebPMuxGetFrame(
- const WebPMux* mux, uint32_t nth, WebPData* bitstream,
- int* x_offset, int* y_offset, int* duration);
+ const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame);
-// Deletes an animation frame from the mux object.
+// Deletes a frame from the mux object.
// nth=0 has a special meaning - last position.
// Parameters:
// mux - (in/out) object from which a frame is to be deleted
// nth - (in) The position from which the frame is to be deleted
// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL
+// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL.
// WEBP_MUX_NOT_FOUND - If there are less than nth frames in the mux object
// before deletion.
// WEBP_MUX_OK - on success.
WEBP_EXTERN(WebPMuxError) WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth);
-// Sets the animation loop count in the mux object. Any existing loop count
-// value(s) will be removed.
+//------------------------------------------------------------------------------
+// Animation.
+
+// Animation parameters.
+struct WebPMuxAnimParams {
+ uint32_t bgcolor; // Background color of the canvas stored (in MSB order) as:
+ // Bits 00 to 07: Alpha.
+ // Bits 08 to 15: Red.
+ // Bits 16 to 23: Green.
+ // Bits 24 to 31: Blue.
+ int loop_count; // Number of times to repeat the animation [0 = infinite].
+};
+
+// Sets the animation parameters in the mux object. Any existing ANIM chunks
+// will be removed.
// Parameters:
-// mux - (in/out) object in which loop chunk is to be set/added
-// loop_count - (in) animation loop count value.
-// Note that loop_count of zero denotes infinite loop.
+// mux - (in/out) object in which ANIM chunk is to be set/added
+// params - (in) animation parameters.
// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL
+// WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL.
// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxSetLoopCount(WebPMux* mux, int loop_count);
+WEBP_EXTERN(WebPMuxError) WebPMuxSetAnimationParams(
+ WebPMux* mux, const WebPMuxAnimParams* params);
-// Gets the animation loop count from the mux object.
+// Gets the animation parameters from the mux object.
// Parameters:
-// mux - (in) object from which the loop count is to be fetched
-// loop_count - (out) the loop_count value present in the LOOP chunk
+// mux - (in) object from which the animation parameters to be fetched
+// params - (out) animation parameters extracted from the ANIM chunk
// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if either of mux or loop_count is NULL
-// WEBP_MUX_NOT_FOUND - if loop chunk is not present in mux object.
+// WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL.
+// WEBP_MUX_NOT_FOUND - if ANIM chunk is not present in mux object.
// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxGetLoopCount(const WebPMux* mux,
- int* loop_count);
+WEBP_EXTERN(WebPMuxError) WebPMuxGetAnimationParams(
+ const WebPMux* mux, WebPMuxAnimParams* params);
//------------------------------------------------------------------------------
-// Tiling.
-
-// Adds a tile at the end of the mux object.
-// Note: as WebP only supports even offsets, any odd offset will be snapped to
-// an even location using: offset &= ~1
-// Parameters:
-// mux - (in/out) object to which a tile is to be added.
-// bitstream - (in) the image data corresponding to the frame. It can either
-// be a raw VP8/VP8L bitstream or a single-image WebP file
-// (non-animated and non-tiled)
-// x_offset - (in) x-offset of the tile to be added
-// y_offset - (in) y-offset of the tile to be added
-// copy_data - (in) value 1 indicates given data WILL copied to the mux, and
-// value 0 indicates data will NOT be copied.
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL
-// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxPushTile(
- WebPMux* mux, const WebPData* bitstream,
- int x_offset, int y_offset, int copy_data);
+// Misc Utilities.
-// Gets the nth tile from the mux object.
-// The content of 'bitstream' is allocated using malloc(), and NOT
-// owned by the 'mux' object. It MUST be deallocated by the caller by calling
-// WebPDataClear().
-// nth=0 has a special meaning - last position.
+// Sets the canvas size for the mux object. The width and height can be
+// specified explicitly or left as zero (0, 0).
+// * When width and height are specified explicitly, then this frame bound is
+// enforced during subsequent calls to WebPMuxAssemble() and an error is
+// reported if any animated frame does not completely fit within the canvas.
+// * When unspecified (0, 0), the constructed canvas will get the frame bounds
+// from the bounding-box over all frames after calling WebPMuxAssemble().
// Parameters:
-// mux - (in) object from which the info is to be fetched
-// nth - (in) index of the tile in the mux object
-// bitstream - (out) the image data
-// x_offset - (out) x-offset of the returned tile
-// y_offset - (out) y-offset of the returned tile
+// mux - (in) object to which the canvas size is to be set
+// width - (in) canvas width
+// height - (in) canvas height
// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if either mux, bitstream, x_offset or
-// y_offset is NULL
-// WEBP_MUX_NOT_FOUND - if there are less than nth tiles in the mux object.
-// WEBP_MUX_BAD_DATA - if nth tile chunk in mux is invalid.
+// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL; or
+// width or height are invalid or out of bounds
// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxGetTile(
- const WebPMux* mux, uint32_t nth, WebPData* bitstream,
- int* x_offset, int* y_offset);
+WEBP_EXTERN(WebPMuxError) WebPMuxSetCanvasSize(WebPMux* mux,
+ int width, int height);
-// Deletes a tile from the mux object.
-// nth=0 has a special meaning - last position
+// Gets the canvas size from the mux object.
+// Note: This method assumes that the VP8X chunk, if present, is up-to-date.
+// That is, the mux object hasn't been modified since the last call to
+// WebPMuxAssemble() or WebPMuxCreate().
// Parameters:
-// mux - (in/out) object from which a tile is to be deleted
-// nth - (in) The position from which the tile is to be deleted
+// mux - (in) object from which the canvas size is to be fetched
+// width - (out) canvas width
+// height - (out) canvas height
// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL
-// WEBP_MUX_NOT_FOUND - If there are less than nth tiles in the mux object
-// before deletion.
+// WEBP_MUX_INVALID_ARGUMENT - if mux, width or height is NULL.
+// WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid.
// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxDeleteTile(WebPMux* mux, uint32_t nth);
-
-//------------------------------------------------------------------------------
-// Misc Utilities.
+WEBP_EXTERN(WebPMuxError) WebPMuxGetCanvasSize(const WebPMux* mux,
+ int* width, int* height);
// Gets the feature flags from the mux object.
+// Note: This method assumes that the VP8X chunk, if present, is up-to-date.
+// That is, the mux object hasn't been modified since the last call to
+// WebPMuxAssemble() or WebPMuxCreate().
// Parameters:
// mux - (in) object from which the features are to be fetched
// flags - (out) the flags specifying which features are present in the
// mux object. This will be an OR of various flag values.
// Enum 'WebPFeatureFlags' can be used to test individual flag values.
// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux or flags is NULL
-// WEBP_MUX_NOT_FOUND - if VP8X chunk is not present in mux object.
-// WEBP_MUX_BAD_DATA - if VP8X chunk in mux is invalid.
+// WEBP_MUX_INVALID_ARGUMENT - if mux or flags is NULL.
+// WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid.
// WEBP_MUX_OK - on success.
WEBP_EXTERN(WebPMuxError) WebPMuxGetFeatures(const WebPMux* mux,
uint32_t* flags);
-// Gets number of chunks having tag value tag in the mux object.
+// Gets number of chunks with the given 'id' in the mux object.
// Parameters:
// mux - (in) object from which the info is to be fetched
// id - (in) chunk id specifying the type of chunk
// num_elements - (out) number of chunks with the given chunk id
// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if either mux, or num_elements is NULL
+// WEBP_MUX_INVALID_ARGUMENT - if mux, or num_elements is NULL.
// WEBP_MUX_OK - on success.
WEBP_EXTERN(WebPMuxError) WebPMuxNumChunks(const WebPMux* mux,
WebPChunkId id, int* num_elements);
@@ -445,159 +379,151 @@ WEBP_EXTERN(WebPMuxError) WebPMuxNumChunks(const WebPMux* mux,
// Note: The content of 'assembled_data' will be ignored and overwritten.
// Also, the content of 'assembled_data' is allocated using malloc(), and NOT
// owned by the 'mux' object. It MUST be deallocated by the caller by calling
-// WebPDataClear().
+// WebPDataClear(). It's always safe to call WebPDataClear() upon return,
+// even in case of error.
// Parameters:
// mux - (in/out) object whose chunks are to be assembled
// assembled_data - (out) assembled WebP data
// Returns:
// WEBP_MUX_BAD_DATA - if mux object is invalid.
-// WEBP_MUX_INVALID_ARGUMENT - if either mux, output_data or output_size is
-// NULL.
+// WEBP_MUX_INVALID_ARGUMENT - if mux or assembled_data is NULL.
// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
-// WEBP_MUX_OK - on success
+// WEBP_MUX_OK - on success.
WEBP_EXTERN(WebPMuxError) WebPMuxAssemble(WebPMux* mux,
WebPData* assembled_data);
//------------------------------------------------------------------------------
-// Demux API.
-// Enables extraction of image and extended format data from WebP files.
-
-#define WEBP_DEMUX_ABI_VERSION 0x0100 // MAJOR(8b) + MINOR(8b)
-
-typedef struct WebPDemuxer WebPDemuxer;
-
-typedef enum {
- WEBP_DEMUX_PARSING_HEADER, // Not enough data to parse full header.
- WEBP_DEMUX_PARSED_HEADER, // Header parsing complete, data may be available.
- WEBP_DEMUX_DONE // Entire file has been parsed.
-} WebPDemuxState;
-
-//------------------------------------------------------------------------------
-// Life of a Demux object
-
-// Internal, version-checked, entry point
-WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal(
- const WebPData*, int, WebPDemuxState*, int);
-
-// Parses the WebP file given by 'data'.
-// A complete WebP file must be present in 'data' for the function to succeed.
-// Returns a WebPDemuxer object on successful parse, NULL otherwise.
-static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) {
- return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION);
-}
-
-// Parses the WebP file given by 'data'.
-// If 'state' is non-NULL it will be set to indicate the status of the demuxer.
-// Returns a WebPDemuxer object on successful parse, NULL otherwise.
-static WEBP_INLINE WebPDemuxer* WebPDemuxPartial(
- const WebPData* data, WebPDemuxState* state) {
- return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION);
+// WebPAnimEncoder API
+//
+// This API allows encoding (possibly) animated WebP images.
+//
+// Code Example:
+/*
+ WebPAnimEncoderOptions enc_options;
+ WebPAnimEncoderOptionsInit(&enc_options);
+ // Tune 'enc_options' as needed.
+ WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options);
+ while(<there are more frames>) {
+ WebPConfig config;
+ WebPConfigInit(&config);
+ // Tune 'config' as needed.
+ WebPAnimEncoderAdd(enc, frame, timestamp_ms, &config);
+ }
+ WebPAnimEncoderAdd(enc, NULL, timestamp_ms, NULL);
+ WebPAnimEncoderAssemble(enc, webp_data);
+ WebPAnimEncoderDelete(enc);
+ // Write the 'webp_data' to a file, or re-mux it further.
+*/
+
+typedef struct WebPAnimEncoder WebPAnimEncoder; // Main opaque object.
+
+// Forward declarations. Defined in encode.h.
+struct WebPPicture;
+struct WebPConfig;
+
+// Global options.
+struct WebPAnimEncoderOptions {
+ WebPMuxAnimParams anim_params; // Animation parameters.
+ int minimize_size; // If true, minimize the output size (slow). Implicitly
+ // disables key-frame insertion.
+ int kmin;
+ int kmax; // Minimum and maximum distance between consecutive key
+ // frames in the output. The library may insert some key
+ // frames as needed to satisfy this criteria.
+ // Note that these conditions should hold: kmax > kmin
+ // and kmin >= kmax / 2 + 1. Also, if kmin == 0, then
+ // key-frame insertion is disabled; and if kmax == 0,
+ // then all frames will be key-frames.
+ int allow_mixed; // If true, use mixed compression mode; may choose
+ // either lossy and lossless for each frame.
+ int verbose; // If true, print info and warning messages to stderr.
+
+ uint32_t padding[4]; // Padding for later use.
+};
+
+// Internal, version-checked, entry point.
+WEBP_EXTERN(int) WebPAnimEncoderOptionsInitInternal(
+ WebPAnimEncoderOptions*, int);
+
+// Should always be called, to initialize a fresh WebPAnimEncoderOptions
+// structure before modification. Returns false in case of version mismatch.
+// WebPAnimEncoderOptionsInit() must have succeeded before using the
+// 'enc_options' object.
+static WEBP_INLINE int WebPAnimEncoderOptionsInit(
+ WebPAnimEncoderOptions* enc_options) {
+ return WebPAnimEncoderOptionsInitInternal(enc_options, WEBP_MUX_ABI_VERSION);
}
-// Frees memory associated with 'dmux'.
-WEBP_EXTERN(void) WebPDemuxDelete(WebPDemuxer* dmux);
-
-//------------------------------------------------------------------------------
-// Data/information extraction.
+// Internal, version-checked, entry point.
+WEBP_EXTERN(WebPAnimEncoder*) WebPAnimEncoderNewInternal(
+ int, int, const WebPAnimEncoderOptions*, int);
-typedef enum {
- WEBP_FF_FORMAT_FLAGS, // Extended format flags present in the 'VP8X' chunk.
- WEBP_FF_CANVAS_WIDTH,
- WEBP_FF_CANVAS_HEIGHT,
- WEBP_FF_LOOP_COUNT
-} WebPFormatFeature;
+// Creates and initializes a WebPAnimEncoder object.
+// Parameters:
+// width/height - (in) canvas width and height of the animation.
+// enc_options - (in) encoding options; can be passed NULL to pick
+// reasonable defaults.
+// Returns:
+// A pointer to the newly created WebPAnimEncoder object.
+// Or NULL in case of memory error.
+static WEBP_INLINE WebPAnimEncoder* WebPAnimEncoderNew(
+ int width, int height, const WebPAnimEncoderOptions* enc_options) {
+ return WebPAnimEncoderNewInternal(width, height, enc_options,
+ WEBP_MUX_ABI_VERSION);
+}
-// Get the 'feature' value from the 'dmux'.
-// NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial()
-// returned a state > WEBP_DEMUX_PARSING_HEADER.
-WEBP_EXTERN(uint32_t) WebPDemuxGetI(
- const WebPDemuxer* dmux, WebPFormatFeature feature);
+// Optimize the given frame for WebP, encode it and add it to the
+// WebPAnimEncoder object.
+// The last call to 'WebPAnimEncoderAdd' should be with frame = NULL, which
+// indicates that no more frames are to be added. This call is also used to
+// determine the duration of the last frame.
+// Parameters:
+// enc - (in/out) object to which the frame is to be added.
+// frame - (in/out) frame data in ARGB or YUV(A) format. If it is in YUV(A)
+// format, it will be converted to ARGB, which incurs a small loss.
+// timestamp_ms - (in) timestamp of this frame in milliseconds.
+// Duration of a frame would be calculated as
+// "timestamp of next frame - timestamp of this frame".
+// Hence, timestamps should be in non-decreasing order.
+// config - (in) encoding options; can be passed NULL to pick
+// reasonable defaults.
+// Returns:
+// On error, returns false and frame->error_code is set appropriately.
+// Otherwise, returns true.
+WEBP_EXTERN(int) WebPAnimEncoderAdd(
+ WebPAnimEncoder* enc, struct WebPPicture* frame, int timestamp_ms,
+ const struct WebPConfig* config);
+
+// Assemble all frames added so far into a WebP bitstream.
+// This call should be preceded by a call to 'WebPAnimEncoderAdd' with
+// frame = NULL; if not, the duration of the last frame will be internally
+// estimated.
+// Parameters:
+// enc - (in/out) object from which the frames are to be assembled.
+// webp_data - (out) generated WebP bitstream.
+// Returns:
+// True on success.
+WEBP_EXTERN(int) WebPAnimEncoderAssemble(WebPAnimEncoder* enc,
+ WebPData* webp_data);
-//------------------------------------------------------------------------------
-// Frame iteration.
-
-typedef struct {
- int frame_num_;
- int num_frames_;
- int tile_num_;
- int num_tiles_;
- int x_offset_, y_offset_; // offset relative to the canvas.
- int width_, height_; // dimensions of this frame or tile.
- int duration_; // display duration in milliseconds.
- int complete_; // true if 'tile_' contains a full frame. partial images may
- // still be decoded with the WebP incremental decoder.
- WebPData tile_; // The frame or tile given by 'frame_num_' and 'tile_num_'.
-
- uint32_t pad[4]; // padding for later use
- void* private_;
-} WebPIterator;
-
-// Retrieves frame 'frame_number' from 'dmux'.
-// 'iter->tile_' points to the first tile on return from this function.
-// Individual tiles may be extracted using WebPDemuxSetTile().
-// Setting 'frame_number' equal to 0 will return the last frame of the image.
-// Returns false if 'dmux' is NULL or frame 'frame_number' is not present.
-// Call WebPDemuxReleaseIterator() when use of the iterator is complete.
-// NOTE: 'dmux' must persist for the lifetime of 'iter'.
-WEBP_EXTERN(int) WebPDemuxGetFrame(
- const WebPDemuxer* dmux, int frame_number, WebPIterator* iter);
-
-// Sets 'iter->tile_' to point to the next ('iter->frame_num_' + 1) or previous
-// ('iter->frame_num_' - 1) frame. These functions do not loop.
-// Returns true on success, false otherwise.
-WEBP_EXTERN(int) WebPDemuxNextFrame(WebPIterator* iter);
-WEBP_EXTERN(int) WebPDemuxPrevFrame(WebPIterator* iter);
-
-// Sets 'iter->tile_' to reflect tile number 'tile_number'.
-// Returns true if tile 'tile_number' is present, false otherwise.
-WEBP_EXTERN(int) WebPDemuxSelectTile(WebPIterator* iter, int tile_number);
-
-// Releases any memory associated with 'iter'.
-// Must be called before destroying the associated WebPDemuxer with
-// WebPDemuxDelete().
-WEBP_EXTERN(void) WebPDemuxReleaseIterator(WebPIterator* iter);
+// Get error string corresponding to the most recent call using 'enc'. The
+// returned string is owned by 'enc' and is valid only until the next call to
+// WebPAnimEncoderAdd() or WebPAnimEncoderAssemble() or WebPAnimEncoderDelete().
+// Parameters:
+// enc - (in/out) object from which the error string is to be fetched.
+// Returns:
+// NULL if 'enc' is NULL. Otherwise, returns the error string if the last call
+// to 'enc' had an error, or an empty string if the last call was a success.
+WEBP_EXTERN(const char*) WebPAnimEncoderGetError(WebPAnimEncoder* enc);
-//------------------------------------------------------------------------------
-// Chunk iteration.
-
-typedef struct {
- // The current and total number of chunks with the fourcc given to
- // WebPDemuxGetChunk().
- int chunk_num_;
- int num_chunks_;
- WebPData chunk_; // The payload of the chunk.
-
- uint32_t pad[6]; // padding for later use
- void* private_;
-} WebPChunkIterator;
-
-// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from
-// 'dmux'.
-// 'fourcc' is a character array containing the fourcc of the chunk to return,
-// e.g., "ICCP", "META", "EXIF", etc.
-// Setting 'chunk_number' equal to 0 will return the last chunk in a set.
-// Returns true if the chunk is found, false otherwise. Image related chunk
-// payloads are accessed through WebPDemuxGetFrame() and related functions.
-// Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete.
-// NOTE: 'dmux' must persist for the lifetime of the iterator.
-WEBP_EXTERN(int) WebPDemuxGetChunk(const WebPDemuxer* dmux,
- const char fourcc[4], int chunk_number,
- WebPChunkIterator* iter);
-
-// Sets 'iter->chunk_' to point to the next ('iter->chunk_num_' + 1) or previous
-// ('iter->chunk_num_' - 1) chunk. These functions do not loop.
-// Returns true on success, false otherwise.
-WEBP_EXTERN(int) WebPDemuxNextChunk(WebPChunkIterator* iter);
-WEBP_EXTERN(int) WebPDemuxPrevChunk(WebPChunkIterator* iter);
-
-// Releases any memory associated with 'iter'.
-// Must be called before destroying the associated WebPDemuxer with
-// WebPDemuxDelete().
-WEBP_EXTERN(void) WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter);
+// Deletes the WebPAnimEncoder object.
+// Parameters:
+// enc - (in/out) object to be deleted
+WEBP_EXTERN(void) WebPAnimEncoderDelete(WebPAnimEncoder* enc);
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/mux/anim_encode.c b/drivers/webp/mux/anim_encode.c
new file mode 100644
index 0000000000..bb7c0f50b9
--- /dev/null
+++ b/drivers/webp/mux/anim_encode.c
@@ -0,0 +1,1404 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// AnimEncoder implementation.
+//
+
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../utils/utils.h"
+#include "webp/decode.h"
+#include "webp/encode.h"
+#include "webp/format_constants.h"
+#include "webp/mux.h"
+
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#define snprintf _snprintf
+#endif
+
+#define ERROR_STR_MAX_LENGTH 100
+
+//------------------------------------------------------------------------------
+// Internal structs.
+
+// Stores frame rectangle dimensions.
+typedef struct {
+ int x_offset_, y_offset_, width_, height_;
+} FrameRect;
+
+// Used to store two candidates of encoded data for an animation frame. One of
+// the two will be chosen later.
+typedef struct {
+ WebPMuxFrameInfo sub_frame_; // Encoded frame rectangle.
+ WebPMuxFrameInfo key_frame_; // Encoded frame if it is a key-frame.
+ int is_key_frame_; // True if 'key_frame' has been chosen.
+} EncodedFrame;
+
+struct WebPAnimEncoder {
+ const int canvas_width_; // Canvas width.
+ const int canvas_height_; // Canvas height.
+ const WebPAnimEncoderOptions options_; // Global encoding options.
+
+ FrameRect prev_rect_; // Previous WebP frame rectangle.
+ WebPConfig last_config_; // Cached in case a re-encode is needed.
+ WebPConfig last_config2_; // 2nd cached config; only valid if
+ // 'options_.allow_mixed' is true.
+
+ WebPPicture* curr_canvas_; // Only pointer; we don't own memory.
+
+ // Canvas buffers.
+ WebPPicture curr_canvas_copy_; // Possibly modified current canvas.
+ int curr_canvas_copy_modified_; // True if pixels in 'curr_canvas_copy_'
+ // differ from those in 'curr_canvas_'.
+
+ WebPPicture prev_canvas_; // Previous canvas.
+ WebPPicture prev_canvas_disposed_; // Previous canvas disposed to background.
+
+ // Encoded data.
+ EncodedFrame* encoded_frames_; // Array of encoded frames.
+ size_t size_; // Number of allocated frames.
+ size_t start_; // Frame start index.
+ size_t count_; // Number of valid frames.
+ size_t flush_count_; // If >0, 'flush_count' frames starting from
+ // 'start' are ready to be added to mux.
+
+ // key-frame related.
+ int64_t best_delta_; // min(canvas size - frame size) over the frames.
+ // Can be negative in certain cases due to
+ // transparent pixels in a frame.
+ int keyframe_; // Index of selected key-frame relative to 'start_'.
+ int count_since_key_frame_; // Frames seen since the last key-frame.
+
+ int first_timestamp_; // Timestamp of the first frame.
+ int prev_timestamp_; // Timestamp of the last added frame.
+ int prev_candidate_undecided_; // True if it's not yet decided if previous
+ // frame would be a sub-frame or a key-frame.
+
+ // Misc.
+ int is_first_frame_; // True if first frame is yet to be added/being added.
+ int got_null_frame_; // True if WebPAnimEncoderAdd() has already been called
+ // with a NULL frame.
+
+ size_t in_frame_count_; // Number of input frames processed so far.
+ size_t out_frame_count_; // Number of frames added to mux so far. This may be
+ // different from 'in_frame_count_' due to merging.
+
+ WebPMux* mux_; // Muxer to assemble the WebP bitstream.
+ char error_str_[ERROR_STR_MAX_LENGTH]; // Error string. Empty if no error.
+};
+
+// -----------------------------------------------------------------------------
+// Life of WebPAnimEncoder object.
+
+#define DELTA_INFINITY (1ULL << 32)
+#define KEYFRAME_NONE (-1)
+
+// Reset the counters in the WebPAnimEncoder.
+static void ResetCounters(WebPAnimEncoder* const enc) {
+ enc->start_ = 0;
+ enc->count_ = 0;
+ enc->flush_count_ = 0;
+ enc->best_delta_ = DELTA_INFINITY;
+ enc->keyframe_ = KEYFRAME_NONE;
+}
+
+static void DisableKeyframes(WebPAnimEncoderOptions* const enc_options) {
+ enc_options->kmax = INT_MAX;
+ enc_options->kmin = enc_options->kmax - 1;
+}
+
+#define MAX_CACHED_FRAMES 30
+
+static void SanitizeEncoderOptions(WebPAnimEncoderOptions* const enc_options) {
+ int print_warning = enc_options->verbose;
+
+ if (enc_options->minimize_size) {
+ DisableKeyframes(enc_options);
+ }
+
+ if (enc_options->kmin <= 0) {
+ DisableKeyframes(enc_options);
+ print_warning = 0;
+ }
+ if (enc_options->kmax <= 0) { // All frames will be key-frames.
+ enc_options->kmin = 0;
+ enc_options->kmax = 0;
+ return;
+ }
+
+ if (enc_options->kmin >= enc_options->kmax) {
+ enc_options->kmin = enc_options->kmax - 1;
+ if (print_warning) {
+ fprintf(stderr, "WARNING: Setting kmin = %d, so that kmin < kmax.\n",
+ enc_options->kmin);
+ }
+ } else {
+ const int kmin_limit = enc_options->kmax / 2 + 1;
+ if (enc_options->kmin < kmin_limit && kmin_limit < enc_options->kmax) {
+ // This ensures that enc.keyframe + kmin >= kmax is always true. So, we
+ // can flush all the frames in the 'count_since_key_frame == kmax' case.
+ enc_options->kmin = kmin_limit;
+ if (print_warning) {
+ fprintf(stderr,
+ "WARNING: Setting kmin = %d, so that kmin >= kmax / 2 + 1.\n",
+ enc_options->kmin);
+ }
+ }
+ }
+ // Limit the max number of frames that are allocated.
+ if (enc_options->kmax - enc_options->kmin > MAX_CACHED_FRAMES) {
+ enc_options->kmin = enc_options->kmax - MAX_CACHED_FRAMES;
+ if (print_warning) {
+ fprintf(stderr,
+ "WARNING: Setting kmin = %d, so that kmax - kmin <= %d.\n",
+ enc_options->kmin, MAX_CACHED_FRAMES);
+ }
+ }
+ assert(enc_options->kmin < enc_options->kmax);
+}
+
+#undef MAX_CACHED_FRAMES
+
+static void DefaultEncoderOptions(WebPAnimEncoderOptions* const enc_options) {
+ enc_options->anim_params.loop_count = 0;
+ enc_options->anim_params.bgcolor = 0xffffffff; // White.
+ enc_options->minimize_size = 0;
+ DisableKeyframes(enc_options);
+ enc_options->allow_mixed = 0;
+}
+
+int WebPAnimEncoderOptionsInitInternal(WebPAnimEncoderOptions* enc_options,
+ int abi_version) {
+ if (enc_options == NULL ||
+ WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) {
+ return 0;
+ }
+ DefaultEncoderOptions(enc_options);
+ return 1;
+}
+
+#define TRANSPARENT_COLOR 0x00ffffff
+
+static void ClearRectangle(WebPPicture* const picture,
+ int left, int top, int width, int height) {
+ int j;
+ for (j = top; j < top + height; ++j) {
+ uint32_t* const dst = picture->argb + j * picture->argb_stride;
+ int i;
+ for (i = left; i < left + width; ++i) {
+ dst[i] = TRANSPARENT_COLOR;
+ }
+ }
+}
+
+static void WebPUtilClearPic(WebPPicture* const picture,
+ const FrameRect* const rect) {
+ if (rect != NULL) {
+ ClearRectangle(picture, rect->x_offset_, rect->y_offset_,
+ rect->width_, rect->height_);
+ } else {
+ ClearRectangle(picture, 0, 0, picture->width, picture->height);
+ }
+}
+
+static void MarkNoError(WebPAnimEncoder* const enc) {
+ enc->error_str_[0] = '\0'; // Empty string.
+}
+
+static void MarkError(WebPAnimEncoder* const enc, const char* str) {
+ if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s.", str) < 0) {
+ assert(0); // FIX ME!
+ }
+}
+
+static void MarkError2(WebPAnimEncoder* const enc,
+ const char* str, int error_code) {
+ if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s: %d.", str,
+ error_code) < 0) {
+ assert(0); // FIX ME!
+ }
+}
+
+WebPAnimEncoder* WebPAnimEncoderNewInternal(
+ int width, int height, const WebPAnimEncoderOptions* enc_options,
+ int abi_version) {
+ WebPAnimEncoder* enc;
+
+ if (WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) {
+ return NULL;
+ }
+ if (width <= 0 || height <= 0 ||
+ (width * (uint64_t)height) >= MAX_IMAGE_AREA) {
+ return NULL;
+ }
+
+ enc = (WebPAnimEncoder*)WebPSafeCalloc(1, sizeof(*enc));
+ if (enc == NULL) return NULL;
+ // sanity inits, so we can call WebPAnimEncoderDelete():
+ enc->encoded_frames_ = NULL;
+ enc->mux_ = NULL;
+ MarkNoError(enc);
+
+ // Dimensions and options.
+ *(int*)&enc->canvas_width_ = width;
+ *(int*)&enc->canvas_height_ = height;
+ if (enc_options != NULL) {
+ *(WebPAnimEncoderOptions*)&enc->options_ = *enc_options;
+ SanitizeEncoderOptions((WebPAnimEncoderOptions*)&enc->options_);
+ } else {
+ DefaultEncoderOptions((WebPAnimEncoderOptions*)&enc->options_);
+ }
+
+ // Canvas buffers.
+ if (!WebPPictureInit(&enc->curr_canvas_copy_) ||
+ !WebPPictureInit(&enc->prev_canvas_) ||
+ !WebPPictureInit(&enc->prev_canvas_disposed_)) {
+ goto Err;
+ }
+ enc->curr_canvas_copy_.width = width;
+ enc->curr_canvas_copy_.height = height;
+ enc->curr_canvas_copy_.use_argb = 1;
+ if (!WebPPictureAlloc(&enc->curr_canvas_copy_) ||
+ !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_) ||
+ !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_disposed_)) {
+ goto Err;
+ }
+ WebPUtilClearPic(&enc->prev_canvas_, NULL);
+ enc->curr_canvas_copy_modified_ = 1;
+
+ // Encoded frames.
+ ResetCounters(enc);
+ // Note: one extra storage is for the previous frame.
+ enc->size_ = enc->options_.kmax - enc->options_.kmin + 1;
+ // We need space for at least 2 frames. But when kmin, kmax are both zero,
+ // enc->size_ will be 1. So we handle that special case below.
+ if (enc->size_ < 2) enc->size_ = 2;
+ enc->encoded_frames_ =
+ (EncodedFrame*)WebPSafeCalloc(enc->size_, sizeof(*enc->encoded_frames_));
+ if (enc->encoded_frames_ == NULL) goto Err;
+
+ enc->mux_ = WebPMuxNew();
+ if (enc->mux_ == NULL) goto Err;
+
+ enc->count_since_key_frame_ = 0;
+ enc->first_timestamp_ = 0;
+ enc->prev_timestamp_ = 0;
+ enc->prev_candidate_undecided_ = 0;
+ enc->is_first_frame_ = 1;
+ enc->got_null_frame_ = 0;
+
+ return enc; // All OK.
+
+ Err:
+ WebPAnimEncoderDelete(enc);
+ return NULL;
+}
+
+// Release the data contained by 'encoded_frame'.
+static void FrameRelease(EncodedFrame* const encoded_frame) {
+ if (encoded_frame != NULL) {
+ WebPDataClear(&encoded_frame->sub_frame_.bitstream);
+ WebPDataClear(&encoded_frame->key_frame_.bitstream);
+ memset(encoded_frame, 0, sizeof(*encoded_frame));
+ }
+}
+
+void WebPAnimEncoderDelete(WebPAnimEncoder* enc) {
+ if (enc != NULL) {
+ WebPPictureFree(&enc->curr_canvas_copy_);
+ WebPPictureFree(&enc->prev_canvas_);
+ WebPPictureFree(&enc->prev_canvas_disposed_);
+ if (enc->encoded_frames_ != NULL) {
+ size_t i;
+ for (i = 0; i < enc->size_; ++i) {
+ FrameRelease(&enc->encoded_frames_[i]);
+ }
+ WebPSafeFree(enc->encoded_frames_);
+ }
+ WebPMuxDelete(enc->mux_);
+ WebPSafeFree(enc);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Frame addition.
+
+// Returns cached frame at the given 'position'.
+static EncodedFrame* GetFrame(const WebPAnimEncoder* const enc,
+ size_t position) {
+ assert(enc->start_ + position < enc->size_);
+ return &enc->encoded_frames_[enc->start_ + position];
+}
+
+// Returns true if 'length' number of pixels in 'src' and 'dst' are identical,
+// assuming the given step sizes between pixels.
+static WEBP_INLINE int ComparePixels(const uint32_t* src, int src_step,
+ const uint32_t* dst, int dst_step,
+ int length) {
+ assert(length > 0);
+ while (length-- > 0) {
+ if (*src != *dst) {
+ return 0;
+ }
+ src += src_step;
+ dst += dst_step;
+ }
+ return 1;
+}
+
+static int IsEmptyRect(const FrameRect* const rect) {
+ return (rect->width_ == 0) || (rect->height_ == 0);
+}
+
+// Assumes that an initial valid guess of change rectangle 'rect' is passed.
+static void MinimizeChangeRectangle(const WebPPicture* const src,
+ const WebPPicture* const dst,
+ FrameRect* const rect) {
+ int i, j;
+ // Sanity checks.
+ assert(src->width == dst->width && src->height == dst->height);
+ assert(rect->x_offset_ + rect->width_ <= dst->width);
+ assert(rect->y_offset_ + rect->height_ <= dst->height);
+
+ // Left boundary.
+ for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) {
+ const uint32_t* const src_argb =
+ &src->argb[rect->y_offset_ * src->argb_stride + i];
+ const uint32_t* const dst_argb =
+ &dst->argb[rect->y_offset_ * dst->argb_stride + i];
+ if (ComparePixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride,
+ rect->height_)) {
+ --rect->width_; // Redundant column.
+ ++rect->x_offset_;
+ } else {
+ break;
+ }
+ }
+ if (rect->width_ == 0) goto NoChange;
+
+ // Right boundary.
+ for (i = rect->x_offset_ + rect->width_ - 1; i >= rect->x_offset_; --i) {
+ const uint32_t* const src_argb =
+ &src->argb[rect->y_offset_ * src->argb_stride + i];
+ const uint32_t* const dst_argb =
+ &dst->argb[rect->y_offset_ * dst->argb_stride + i];
+ if (ComparePixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride,
+ rect->height_)) {
+ --rect->width_; // Redundant column.
+ } else {
+ break;
+ }
+ }
+ if (rect->width_ == 0) goto NoChange;
+
+ // Top boundary.
+ for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) {
+ const uint32_t* const src_argb =
+ &src->argb[j * src->argb_stride + rect->x_offset_];
+ const uint32_t* const dst_argb =
+ &dst->argb[j * dst->argb_stride + rect->x_offset_];
+ if (ComparePixels(src_argb, 1, dst_argb, 1, rect->width_)) {
+ --rect->height_; // Redundant row.
+ ++rect->y_offset_;
+ } else {
+ break;
+ }
+ }
+ if (rect->height_ == 0) goto NoChange;
+
+ // Bottom boundary.
+ for (j = rect->y_offset_ + rect->height_ - 1; j >= rect->y_offset_; --j) {
+ const uint32_t* const src_argb =
+ &src->argb[j * src->argb_stride + rect->x_offset_];
+ const uint32_t* const dst_argb =
+ &dst->argb[j * dst->argb_stride + rect->x_offset_];
+ if (ComparePixels(src_argb, 1, dst_argb, 1, rect->width_)) {
+ --rect->height_; // Redundant row.
+ } else {
+ break;
+ }
+ }
+ if (rect->height_ == 0) goto NoChange;
+
+ if (IsEmptyRect(rect)) {
+ NoChange:
+ rect->x_offset_ = 0;
+ rect->y_offset_ = 0;
+ rect->width_ = 0;
+ rect->height_ = 0;
+ }
+}
+
+// Snap rectangle to even offsets (and adjust dimensions if needed).
+static WEBP_INLINE void SnapToEvenOffsets(FrameRect* const rect) {
+ rect->width_ += (rect->x_offset_ & 1);
+ rect->height_ += (rect->y_offset_ & 1);
+ rect->x_offset_ &= ~1;
+ rect->y_offset_ &= ~1;
+}
+
+// Given previous and current canvas, picks the optimal rectangle for the
+// current frame. The initial guess for 'rect' will be the full canvas.
+static int GetSubRect(const WebPPicture* const prev_canvas,
+ const WebPPicture* const curr_canvas, int is_key_frame,
+ int is_first_frame, int empty_rect_allowed,
+ FrameRect* const rect, WebPPicture* const sub_frame) {
+ rect->x_offset_ = 0;
+ rect->y_offset_ = 0;
+ rect->width_ = curr_canvas->width;
+ rect->height_ = curr_canvas->height;
+ if (!is_key_frame || is_first_frame) { // Optimize frame rectangle.
+ // Note: This behaves as expected for first frame, as 'prev_canvas' is
+ // initialized to a fully transparent canvas in the beginning.
+ MinimizeChangeRectangle(prev_canvas, curr_canvas, rect);
+ }
+
+ if (IsEmptyRect(rect)) {
+ if (empty_rect_allowed) { // No need to get 'sub_frame'.
+ return 1;
+ } else { // Force a 1x1 rectangle.
+ rect->width_ = 1;
+ rect->height_ = 1;
+ assert(rect->x_offset_ == 0);
+ assert(rect->y_offset_ == 0);
+ }
+ }
+
+ SnapToEvenOffsets(rect);
+ return WebPPictureView(curr_canvas, rect->x_offset_, rect->y_offset_,
+ rect->width_, rect->height_, sub_frame);
+}
+
+static void DisposeFrameRectangle(int dispose_method,
+ const FrameRect* const rect,
+ WebPPicture* const curr_canvas) {
+ assert(rect != NULL);
+ if (dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
+ WebPUtilClearPic(curr_canvas, rect);
+ }
+}
+
+static uint32_t RectArea(const FrameRect* const rect) {
+ return (uint32_t)rect->width_ * rect->height_;
+}
+
+static int IsBlendingPossible(const WebPPicture* const src,
+ const WebPPicture* const dst,
+ const FrameRect* const rect) {
+ int i, j;
+ assert(src->width == dst->width && src->height == dst->height);
+ assert(rect->x_offset_ + rect->width_ <= dst->width);
+ assert(rect->y_offset_ + rect->height_ <= dst->height);
+ for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) {
+ for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) {
+ const uint32_t src_pixel = src->argb[j * src->argb_stride + i];
+ const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i];
+ const uint32_t dst_alpha = dst_pixel >> 24;
+ if (dst_alpha != 0xff && src_pixel != dst_pixel) {
+ // In this case, if we use blending, we can't attain the desired
+ // 'dst_pixel' value for this pixel. So, blending is not possible.
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+#define MIN_COLORS_LOSSY 31 // Don't try lossy below this threshold.
+#define MAX_COLORS_LOSSLESS 194 // Don't try lossless above this threshold.
+#define MAX_COLOR_COUNT 256 // Power of 2 greater than MAX_COLORS_LOSSLESS.
+#define HASH_SIZE (MAX_COLOR_COUNT * 4)
+#define HASH_RIGHT_SHIFT 22 // 32 - log2(HASH_SIZE).
+
+// TODO(urvang): Also used in enc/vp8l.c. Move to utils.
+// If the number of colors in the 'pic' is at least MAX_COLOR_COUNT, return
+// MAX_COLOR_COUNT. Otherwise, return the exact number of colors in the 'pic'.
+static int GetColorCount(const WebPPicture* const pic) {
+ int x, y;
+ int num_colors = 0;
+ uint8_t in_use[HASH_SIZE] = { 0 };
+ uint32_t colors[HASH_SIZE];
+ static const uint32_t kHashMul = 0x1e35a7bd;
+ const uint32_t* argb = pic->argb;
+ const int width = pic->width;
+ const int height = pic->height;
+ uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0]
+
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ int key;
+ if (argb[x] == last_pix) {
+ continue;
+ }
+ last_pix = argb[x];
+ key = (kHashMul * last_pix) >> HASH_RIGHT_SHIFT;
+ while (1) {
+ if (!in_use[key]) {
+ colors[key] = last_pix;
+ in_use[key] = 1;
+ ++num_colors;
+ if (num_colors >= MAX_COLOR_COUNT) {
+ return MAX_COLOR_COUNT; // Exact count not needed.
+ }
+ break;
+ } else if (colors[key] == last_pix) {
+ break; // The color is already there.
+ } else {
+ // Some other color sits here, so do linear conflict resolution.
+ ++key;
+ key &= (HASH_SIZE - 1); // Key mask.
+ }
+ }
+ }
+ argb += pic->argb_stride;
+ }
+ return num_colors;
+}
+
+#undef MAX_COLOR_COUNT
+#undef HASH_SIZE
+#undef HASH_RIGHT_SHIFT
+
+// For pixels in 'rect', replace those pixels in 'dst' that are same as 'src' by
+// transparent pixels.
+static void IncreaseTransparency(const WebPPicture* const src,
+ const FrameRect* const rect,
+ WebPPicture* const dst) {
+ int i, j;
+ assert(src != NULL && dst != NULL && rect != NULL);
+ assert(src->width == dst->width && src->height == dst->height);
+ for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) {
+ const uint32_t* const psrc = src->argb + j * src->argb_stride;
+ uint32_t* const pdst = dst->argb + j * dst->argb_stride;
+ for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) {
+ if (psrc[i] == pdst[i]) {
+ pdst[i] = TRANSPARENT_COLOR;
+ }
+ }
+ }
+}
+
+#undef TRANSPARENT_COLOR
+
+// Replace similar blocks of pixels by a 'see-through' transparent block
+// with uniform average color.
+static void FlattenSimilarBlocks(const WebPPicture* const src,
+ const FrameRect* const rect,
+ WebPPicture* const dst) {
+ int i, j;
+ const int block_size = 8;
+ const int y_start = (rect->y_offset_ + block_size) & ~(block_size - 1);
+ const int y_end = (rect->y_offset_ + rect->height_) & ~(block_size - 1);
+ const int x_start = (rect->x_offset_ + block_size) & ~(block_size - 1);
+ const int x_end = (rect->x_offset_ + rect->width_) & ~(block_size - 1);
+ assert(src != NULL && dst != NULL && rect != NULL);
+ assert(src->width == dst->width && src->height == dst->height);
+ assert((block_size & (block_size - 1)) == 0); // must be a power of 2
+ // Iterate over each block and count similar pixels.
+ for (j = y_start; j < y_end; j += block_size) {
+ for (i = x_start; i < x_end; i += block_size) {
+ int cnt = 0;
+ int avg_r = 0, avg_g = 0, avg_b = 0;
+ int x, y;
+ const uint32_t* const psrc = src->argb + j * src->argb_stride + i;
+ uint32_t* const pdst = dst->argb + j * dst->argb_stride + i;
+ for (y = 0; y < block_size; ++y) {
+ for (x = 0; x < block_size; ++x) {
+ const uint32_t src_pixel = psrc[x + y * src->argb_stride];
+ const int alpha = src_pixel >> 24;
+ if (alpha == 0xff &&
+ src_pixel == pdst[x + y * dst->argb_stride]) {
+ ++cnt;
+ avg_r += (src_pixel >> 16) & 0xff;
+ avg_g += (src_pixel >> 8) & 0xff;
+ avg_b += (src_pixel >> 0) & 0xff;
+ }
+ }
+ }
+ // If we have a fully similar block, we replace it with an
+ // average transparent block. This compresses better in lossy mode.
+ if (cnt == block_size * block_size) {
+ const uint32_t color = (0x00 << 24) |
+ ((avg_r / cnt) << 16) |
+ ((avg_g / cnt) << 8) |
+ ((avg_b / cnt) << 0);
+ for (y = 0; y < block_size; ++y) {
+ for (x = 0; x < block_size; ++x) {
+ pdst[x + y * dst->argb_stride] = color;
+ }
+ }
+ }
+ }
+ }
+}
+
+static int EncodeFrame(const WebPConfig* const config, WebPPicture* const pic,
+ WebPMemoryWriter* const memory) {
+ pic->use_argb = 1;
+ pic->writer = WebPMemoryWrite;
+ pic->custom_ptr = memory;
+ if (!WebPEncode(config, pic)) {
+ return 0;
+ }
+ return 1;
+}
+
+// Struct representing a candidate encoded frame including its metadata.
+typedef struct {
+ WebPMemoryWriter mem_;
+ WebPMuxFrameInfo info_;
+ FrameRect rect_;
+ int evaluate_; // True if this candidate should be evaluated.
+} Candidate;
+
+// Generates a candidate encoded frame given a picture and metadata.
+static WebPEncodingError EncodeCandidate(WebPPicture* const sub_frame,
+ const FrameRect* const rect,
+ const WebPConfig* const config,
+ int use_blending,
+ Candidate* const candidate) {
+ WebPEncodingError error_code = VP8_ENC_OK;
+ assert(candidate != NULL);
+ memset(candidate, 0, sizeof(*candidate));
+
+ // Set frame rect and info.
+ candidate->rect_ = *rect;
+ candidate->info_.id = WEBP_CHUNK_ANMF;
+ candidate->info_.x_offset = rect->x_offset_;
+ candidate->info_.y_offset = rect->y_offset_;
+ candidate->info_.dispose_method = WEBP_MUX_DISPOSE_NONE; // Set later.
+ candidate->info_.blend_method =
+ use_blending ? WEBP_MUX_BLEND : WEBP_MUX_NO_BLEND;
+ candidate->info_.duration = 0; // Set in next call to WebPAnimEncoderAdd().
+
+ // Encode picture.
+ WebPMemoryWriterInit(&candidate->mem_);
+
+ if (!EncodeFrame(config, sub_frame, &candidate->mem_)) {
+ error_code = sub_frame->error_code;
+ goto Err;
+ }
+
+ candidate->evaluate_ = 1;
+ return error_code;
+
+ Err:
+ WebPMemoryWriterClear(&candidate->mem_);
+ return error_code;
+}
+
+static void CopyCurrentCanvas(WebPAnimEncoder* const enc) {
+ if (enc->curr_canvas_copy_modified_) {
+ WebPCopyPixels(enc->curr_canvas_, &enc->curr_canvas_copy_);
+ enc->curr_canvas_copy_modified_ = 0;
+ }
+}
+
+enum {
+ LL_DISP_NONE = 0,
+ LL_DISP_BG,
+ LOSSY_DISP_NONE,
+ LOSSY_DISP_BG,
+ CANDIDATE_COUNT
+};
+
+// Generates candidates for a given dispose method given pre-filled 'rect'
+// and 'sub_frame'.
+static WebPEncodingError GenerateCandidates(
+ WebPAnimEncoder* const enc, Candidate candidates[CANDIDATE_COUNT],
+ WebPMuxAnimDispose dispose_method, int is_lossless, int is_key_frame,
+ const FrameRect* const rect, WebPPicture* sub_frame,
+ const WebPConfig* const config_ll, const WebPConfig* const config_lossy) {
+ WebPEncodingError error_code = VP8_ENC_OK;
+ const int is_dispose_none = (dispose_method == WEBP_MUX_DISPOSE_NONE);
+ Candidate* const candidate_ll =
+ is_dispose_none ? &candidates[LL_DISP_NONE] : &candidates[LL_DISP_BG];
+ Candidate* const candidate_lossy = is_dispose_none
+ ? &candidates[LOSSY_DISP_NONE]
+ : &candidates[LOSSY_DISP_BG];
+ WebPPicture* const curr_canvas = &enc->curr_canvas_copy_;
+ const WebPPicture* const prev_canvas =
+ is_dispose_none ? &enc->prev_canvas_ : &enc->prev_canvas_disposed_;
+ const int use_blending =
+ !is_key_frame &&
+ IsBlendingPossible(prev_canvas, curr_canvas, rect);
+
+ // Pick candidates to be tried.
+ if (!enc->options_.allow_mixed) {
+ candidate_ll->evaluate_ = is_lossless;
+ candidate_lossy->evaluate_ = !is_lossless;
+ } else { // Use a heuristic for trying lossless and/or lossy compression.
+ const int num_colors = GetColorCount(sub_frame);
+ candidate_ll->evaluate_ = (num_colors < MAX_COLORS_LOSSLESS);
+ candidate_lossy->evaluate_ = (num_colors >= MIN_COLORS_LOSSY);
+ }
+
+ // Generate candidates.
+ if (candidate_ll->evaluate_) {
+ CopyCurrentCanvas(enc);
+ if (use_blending) {
+ IncreaseTransparency(prev_canvas, rect, curr_canvas);
+ enc->curr_canvas_copy_modified_ = 1;
+ }
+ error_code = EncodeCandidate(sub_frame, rect, config_ll, use_blending,
+ candidate_ll);
+ if (error_code != VP8_ENC_OK) return error_code;
+ }
+ if (candidate_lossy->evaluate_) {
+ CopyCurrentCanvas(enc);
+ if (use_blending) {
+ FlattenSimilarBlocks(prev_canvas, rect, curr_canvas);
+ enc->curr_canvas_copy_modified_ = 1;
+ }
+ error_code = EncodeCandidate(sub_frame, rect, config_lossy, use_blending,
+ candidate_lossy);
+ if (error_code != VP8_ENC_OK) return error_code;
+ }
+ return error_code;
+}
+
+#undef MIN_COLORS_LOSSY
+#undef MAX_COLORS_LOSSLESS
+
+static void GetEncodedData(const WebPMemoryWriter* const memory,
+ WebPData* const encoded_data) {
+ encoded_data->bytes = memory->mem;
+ encoded_data->size = memory->size;
+}
+
+// Sets dispose method of the previous frame to be 'dispose_method'.
+static void SetPreviousDisposeMethod(WebPAnimEncoder* const enc,
+ WebPMuxAnimDispose dispose_method) {
+ const size_t position = enc->count_ - 2;
+ EncodedFrame* const prev_enc_frame = GetFrame(enc, position);
+ assert(enc->count_ >= 2); // As current and previous frames are in enc.
+
+ if (enc->prev_candidate_undecided_) {
+ assert(dispose_method == WEBP_MUX_DISPOSE_NONE);
+ prev_enc_frame->sub_frame_.dispose_method = dispose_method;
+ prev_enc_frame->key_frame_.dispose_method = dispose_method;
+ } else {
+ WebPMuxFrameInfo* const prev_info = prev_enc_frame->is_key_frame_
+ ? &prev_enc_frame->key_frame_
+ : &prev_enc_frame->sub_frame_;
+ prev_info->dispose_method = dispose_method;
+ }
+}
+
+static int IncreasePreviousDuration(WebPAnimEncoder* const enc, int duration) {
+ const size_t position = enc->count_ - 1;
+ EncodedFrame* const prev_enc_frame = GetFrame(enc, position);
+ int new_duration;
+
+ assert(enc->count_ >= 1);
+ assert(prev_enc_frame->sub_frame_.duration ==
+ prev_enc_frame->key_frame_.duration);
+ assert(prev_enc_frame->sub_frame_.duration ==
+ (prev_enc_frame->sub_frame_.duration & (MAX_DURATION - 1)));
+ assert(duration == (duration & (MAX_DURATION - 1)));
+
+ new_duration = prev_enc_frame->sub_frame_.duration + duration;
+ if (new_duration >= MAX_DURATION) { // Special case.
+ // Separate out previous frame from earlier merged frames to avoid overflow.
+ // We add a 1x1 transparent frame for the previous frame, with blending on.
+ const FrameRect rect = { 0, 0, 1, 1 };
+ const uint8_t lossless_1x1_bytes[] = {
+ 0x52, 0x49, 0x46, 0x46, 0x14, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50,
+ 0x56, 0x50, 0x38, 0x4c, 0x08, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
+ 0x10, 0x88, 0x88, 0x08
+ };
+ const WebPData lossless_1x1 = {
+ lossless_1x1_bytes, sizeof(lossless_1x1_bytes)
+ };
+ const uint8_t lossy_1x1_bytes[] = {
+ 0x52, 0x49, 0x46, 0x46, 0x40, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50,
+ 0x56, 0x50, 0x38, 0x58, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x4c, 0x50, 0x48, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x56, 0x50, 0x38, 0x20, 0x18, 0x00, 0x00, 0x00,
+ 0x30, 0x01, 0x00, 0x9d, 0x01, 0x2a, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00,
+ 0x34, 0x25, 0xa4, 0x00, 0x03, 0x70, 0x00, 0xfe, 0xfb, 0xfd, 0x50, 0x00
+ };
+ const WebPData lossy_1x1 = { lossy_1x1_bytes, sizeof(lossy_1x1_bytes) };
+ const int can_use_lossless =
+ (enc->last_config_.lossless || enc->options_.allow_mixed);
+ EncodedFrame* const curr_enc_frame = GetFrame(enc, enc->count_);
+ curr_enc_frame->is_key_frame_ = 0;
+ curr_enc_frame->sub_frame_.id = WEBP_CHUNK_ANMF;
+ curr_enc_frame->sub_frame_.x_offset = 0;
+ curr_enc_frame->sub_frame_.y_offset = 0;
+ curr_enc_frame->sub_frame_.dispose_method = WEBP_MUX_DISPOSE_NONE;
+ curr_enc_frame->sub_frame_.blend_method = WEBP_MUX_BLEND;
+ curr_enc_frame->sub_frame_.duration = duration;
+ if (!WebPDataCopy(can_use_lossless ? &lossless_1x1 : &lossy_1x1,
+ &curr_enc_frame->sub_frame_.bitstream)) {
+ return 0;
+ }
+ ++enc->count_;
+ ++enc->count_since_key_frame_;
+ enc->flush_count_ = enc->count_ - 1;
+ enc->prev_candidate_undecided_ = 0;
+ enc->prev_rect_ = rect;
+ } else { // Regular case.
+ // Increase duration of the previous frame by 'duration'.
+ prev_enc_frame->sub_frame_.duration = new_duration;
+ prev_enc_frame->key_frame_.duration = new_duration;
+ }
+ return 1;
+}
+
+// Pick the candidate encoded frame with smallest size and release other
+// candidates.
+// TODO(later): Perhaps a rough SSIM/PSNR produced by the encoder should
+// also be a criteria, in addition to sizes.
+static void PickBestCandidate(WebPAnimEncoder* const enc,
+ Candidate* const candidates, int is_key_frame,
+ EncodedFrame* const encoded_frame) {
+ int i;
+ int best_idx = -1;
+ size_t best_size = ~0;
+ for (i = 0; i < CANDIDATE_COUNT; ++i) {
+ if (candidates[i].evaluate_) {
+ const size_t candidate_size = candidates[i].mem_.size;
+ if (candidate_size < best_size) {
+ best_idx = i;
+ best_size = candidate_size;
+ }
+ }
+ }
+ assert(best_idx != -1);
+ for (i = 0; i < CANDIDATE_COUNT; ++i) {
+ if (candidates[i].evaluate_) {
+ if (i == best_idx) {
+ WebPMuxFrameInfo* const dst = is_key_frame
+ ? &encoded_frame->key_frame_
+ : &encoded_frame->sub_frame_;
+ *dst = candidates[i].info_;
+ GetEncodedData(&candidates[i].mem_, &dst->bitstream);
+ if (!is_key_frame) {
+ // Note: Previous dispose method only matters for non-keyframes.
+ // Also, we don't want to modify previous dispose method that was
+ // selected when a non key-frame was assumed.
+ const WebPMuxAnimDispose prev_dispose_method =
+ (best_idx == LL_DISP_NONE || best_idx == LOSSY_DISP_NONE)
+ ? WEBP_MUX_DISPOSE_NONE
+ : WEBP_MUX_DISPOSE_BACKGROUND;
+ SetPreviousDisposeMethod(enc, prev_dispose_method);
+ }
+ enc->prev_rect_ = candidates[i].rect_; // save for next frame.
+ } else {
+ WebPMemoryWriterClear(&candidates[i].mem_);
+ candidates[i].evaluate_ = 0;
+ }
+ }
+ }
+}
+
+// Depending on the configuration, tries different compressions
+// (lossy/lossless), dispose methods, blending methods etc to encode the current
+// frame and outputs the best one in 'encoded_frame'.
+// 'frame_skipped' will be set to true if this frame should actually be skipped.
+static WebPEncodingError SetFrame(WebPAnimEncoder* const enc,
+ const WebPConfig* const config,
+ int is_key_frame,
+ EncodedFrame* const encoded_frame,
+ int* const frame_skipped) {
+ int i;
+ WebPEncodingError error_code = VP8_ENC_OK;
+ const WebPPicture* const curr_canvas = &enc->curr_canvas_copy_;
+ const WebPPicture* const prev_canvas = &enc->prev_canvas_;
+ Candidate candidates[CANDIDATE_COUNT];
+ const int is_lossless = config->lossless;
+ const int is_first_frame = enc->is_first_frame_;
+
+ int try_dispose_none = 1; // Default.
+ FrameRect rect_none;
+ WebPPicture sub_frame_none;
+ // First frame cannot be skipped as there is no 'previous frame' to merge it
+ // to. So, empty rectangle is not allowed for the first frame.
+ const int empty_rect_allowed_none = !is_first_frame;
+
+ // If current frame is a key-frame, dispose method of previous frame doesn't
+ // matter, so we don't try dispose to background.
+ // Also, if key-frame insertion is on, and previous frame could be picked as
+ // either a sub-frame or a key-frame, then we can't be sure about what frame
+ // rectangle would be disposed. In that case too, we don't try dispose to
+ // background.
+ const int dispose_bg_possible =
+ !is_key_frame && !enc->prev_candidate_undecided_;
+ int try_dispose_bg = 0; // Default.
+ FrameRect rect_bg;
+ WebPPicture sub_frame_bg;
+
+ WebPConfig config_ll = *config;
+ WebPConfig config_lossy = *config;
+ config_ll.lossless = 1;
+ config_lossy.lossless = 0;
+ enc->last_config_ = *config;
+ enc->last_config2_ = config->lossless ? config_lossy : config_ll;
+ *frame_skipped = 0;
+
+ if (!WebPPictureInit(&sub_frame_none) || !WebPPictureInit(&sub_frame_bg)) {
+ return VP8_ENC_ERROR_INVALID_CONFIGURATION;
+ }
+
+ for (i = 0; i < CANDIDATE_COUNT; ++i) {
+ candidates[i].evaluate_ = 0;
+ }
+
+ // Change-rectangle assuming previous frame was DISPOSE_NONE.
+ GetSubRect(prev_canvas, curr_canvas, is_key_frame, is_first_frame,
+ empty_rect_allowed_none, &rect_none, &sub_frame_none);
+
+ if (IsEmptyRect(&rect_none)) {
+ // Don't encode the frame at all. Instead, the duration of the previous
+ // frame will be increased later.
+ assert(empty_rect_allowed_none);
+ *frame_skipped = 1;
+ goto End;
+ }
+
+ if (dispose_bg_possible) {
+ // Change-rectangle assuming previous frame was DISPOSE_BACKGROUND.
+ WebPPicture* const prev_canvas_disposed = &enc->prev_canvas_disposed_;
+ WebPCopyPixels(prev_canvas, prev_canvas_disposed);
+ DisposeFrameRectangle(WEBP_MUX_DISPOSE_BACKGROUND, &enc->prev_rect_,
+ prev_canvas_disposed);
+ // Even if there is exact pixel match between 'disposed previous canvas' and
+ // 'current canvas', we can't skip current frame, as there may not be exact
+ // pixel match between 'previous canvas' and 'current canvas'. So, we don't
+ // allow empty rectangle in this case.
+ GetSubRect(prev_canvas_disposed, curr_canvas, is_key_frame, is_first_frame,
+ 0 /* empty_rect_allowed */, &rect_bg, &sub_frame_bg);
+ assert(!IsEmptyRect(&rect_bg));
+
+ if (enc->options_.minimize_size) { // Try both dispose methods.
+ try_dispose_bg = 1;
+ try_dispose_none = 1;
+ } else if (RectArea(&rect_bg) < RectArea(&rect_none)) {
+ try_dispose_bg = 1; // Pick DISPOSE_BACKGROUND.
+ try_dispose_none = 0;
+ }
+ }
+
+ if (try_dispose_none) {
+ error_code = GenerateCandidates(
+ enc, candidates, WEBP_MUX_DISPOSE_NONE, is_lossless, is_key_frame,
+ &rect_none, &sub_frame_none, &config_ll, &config_lossy);
+ if (error_code != VP8_ENC_OK) goto Err;
+ }
+
+ if (try_dispose_bg) {
+ assert(!enc->is_first_frame_);
+ assert(dispose_bg_possible);
+ error_code = GenerateCandidates(
+ enc, candidates, WEBP_MUX_DISPOSE_BACKGROUND, is_lossless, is_key_frame,
+ &rect_bg, &sub_frame_bg, &config_ll, &config_lossy);
+ if (error_code != VP8_ENC_OK) goto Err;
+ }
+
+ PickBestCandidate(enc, candidates, is_key_frame, encoded_frame);
+
+ goto End;
+
+ Err:
+ for (i = 0; i < CANDIDATE_COUNT; ++i) {
+ if (candidates[i].evaluate_) {
+ WebPMemoryWriterClear(&candidates[i].mem_);
+ }
+ }
+
+ End:
+ WebPPictureFree(&sub_frame_none);
+ WebPPictureFree(&sub_frame_bg);
+ return error_code;
+}
+
+// Calculate the penalty incurred if we encode given frame as a key frame
+// instead of a sub-frame.
+static int64_t KeyFramePenalty(const EncodedFrame* const encoded_frame) {
+ return ((int64_t)encoded_frame->key_frame_.bitstream.size -
+ encoded_frame->sub_frame_.bitstream.size);
+}
+
+static int CacheFrame(WebPAnimEncoder* const enc,
+ const WebPConfig* const config) {
+ int ok = 0;
+ int frame_skipped = 0;
+ WebPEncodingError error_code = VP8_ENC_OK;
+ const size_t position = enc->count_;
+ EncodedFrame* const encoded_frame = GetFrame(enc, position);
+
+ ++enc->count_;
+
+ if (enc->is_first_frame_) { // Add this as a key-frame.
+ error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped);
+ if (error_code != VP8_ENC_OK) goto End;
+ assert(frame_skipped == 0); // First frame can't be skipped, even if empty.
+ assert(position == 0 && enc->count_ == 1);
+ encoded_frame->is_key_frame_ = 1;
+ enc->flush_count_ = 0;
+ enc->count_since_key_frame_ = 0;
+ enc->prev_candidate_undecided_ = 0;
+ } else {
+ ++enc->count_since_key_frame_;
+ if (enc->count_since_key_frame_ <= enc->options_.kmin) {
+ // Add this as a frame rectangle.
+ error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped);
+ if (error_code != VP8_ENC_OK) goto End;
+ if (frame_skipped) goto Skip;
+ encoded_frame->is_key_frame_ = 0;
+ enc->flush_count_ = enc->count_ - 1;
+ enc->prev_candidate_undecided_ = 0;
+ } else {
+ int64_t curr_delta;
+
+ // Add this as a frame rectangle to enc.
+ error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped);
+ if (error_code != VP8_ENC_OK) goto End;
+ if (frame_skipped) goto Skip;
+
+ // Add this as a key-frame to enc, too.
+ error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped);
+ if (error_code != VP8_ENC_OK) goto End;
+ assert(frame_skipped == 0); // Key-frame cannot be an empty rectangle.
+
+ // Analyze size difference of the two variants.
+ curr_delta = KeyFramePenalty(encoded_frame);
+ if (curr_delta <= enc->best_delta_) { // Pick this as the key-frame.
+ if (enc->keyframe_ != KEYFRAME_NONE) {
+ EncodedFrame* const old_keyframe = GetFrame(enc, enc->keyframe_);
+ assert(old_keyframe->is_key_frame_);
+ old_keyframe->is_key_frame_ = 0;
+ }
+ encoded_frame->is_key_frame_ = 1;
+ enc->keyframe_ = (int)position;
+ enc->best_delta_ = curr_delta;
+ enc->flush_count_ = enc->count_ - 1; // We can flush previous frames.
+ } else {
+ encoded_frame->is_key_frame_ = 0;
+ }
+ // Note: We need '>=' below because when kmin and kmax are both zero,
+ // count_since_key_frame will always be > kmax.
+ if (enc->count_since_key_frame_ >= enc->options_.kmax) {
+ enc->flush_count_ = enc->count_ - 1;
+ enc->count_since_key_frame_ = 0;
+ enc->keyframe_ = KEYFRAME_NONE;
+ enc->best_delta_ = DELTA_INFINITY;
+ }
+ enc->prev_candidate_undecided_ = 1;
+ }
+ }
+
+ // Update previous to previous and previous canvases for next call.
+ WebPCopyPixels(enc->curr_canvas_, &enc->prev_canvas_);
+ enc->is_first_frame_ = 0;
+
+ Skip:
+ ok = 1;
+ ++enc->in_frame_count_;
+
+ End:
+ if (!ok || frame_skipped) {
+ FrameRelease(encoded_frame);
+ // We reset some counters, as the frame addition failed/was skipped.
+ --enc->count_;
+ if (!enc->is_first_frame_) --enc->count_since_key_frame_;
+ if (!ok) {
+ MarkError2(enc, "ERROR adding frame. WebPEncodingError", error_code);
+ }
+ }
+ enc->curr_canvas_->error_code = error_code; // report error_code
+ assert(ok || error_code != VP8_ENC_OK);
+ return ok;
+}
+
+static int FlushFrames(WebPAnimEncoder* const enc) {
+ while (enc->flush_count_ > 0) {
+ WebPMuxError err;
+ EncodedFrame* const curr = GetFrame(enc, 0);
+ const WebPMuxFrameInfo* const info =
+ curr->is_key_frame_ ? &curr->key_frame_ : &curr->sub_frame_;
+ assert(enc->mux_ != NULL);
+ err = WebPMuxPushFrame(enc->mux_, info, 1);
+ if (err != WEBP_MUX_OK) {
+ MarkError2(enc, "ERROR adding frame. WebPMuxError", err);
+ return 0;
+ }
+ if (enc->options_.verbose) {
+ fprintf(stderr, "INFO: Added frame. offset:%d,%d dispose:%d blend:%d\n",
+ info->x_offset, info->y_offset, info->dispose_method,
+ info->blend_method);
+ }
+ ++enc->out_frame_count_;
+ FrameRelease(curr);
+ ++enc->start_;
+ --enc->flush_count_;
+ --enc->count_;
+ if (enc->keyframe_ != KEYFRAME_NONE) --enc->keyframe_;
+ }
+
+ if (enc->count_ == 1 && enc->start_ != 0) {
+ // Move enc->start to index 0.
+ const int enc_start_tmp = (int)enc->start_;
+ EncodedFrame temp = enc->encoded_frames_[0];
+ enc->encoded_frames_[0] = enc->encoded_frames_[enc_start_tmp];
+ enc->encoded_frames_[enc_start_tmp] = temp;
+ FrameRelease(&enc->encoded_frames_[enc_start_tmp]);
+ enc->start_ = 0;
+ }
+ return 1;
+}
+
+#undef DELTA_INFINITY
+#undef KEYFRAME_NONE
+
+int WebPAnimEncoderAdd(WebPAnimEncoder* enc, WebPPicture* frame, int timestamp,
+ const WebPConfig* encoder_config) {
+ WebPConfig config;
+
+ if (enc == NULL) {
+ return 0;
+ }
+ MarkNoError(enc);
+
+ if (!enc->is_first_frame_) {
+ // Make sure timestamps are non-decreasing (integer wrap-around is OK).
+ const uint32_t prev_frame_duration =
+ (uint32_t)timestamp - enc->prev_timestamp_;
+ if (prev_frame_duration >= MAX_DURATION) {
+ if (frame != NULL) {
+ frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION;
+ }
+ MarkError(enc, "ERROR adding frame: timestamps must be non-decreasing");
+ return 0;
+ }
+ if (!IncreasePreviousDuration(enc, (int)prev_frame_duration)) {
+ return 0;
+ }
+ } else {
+ enc->first_timestamp_ = timestamp;
+ }
+
+ if (frame == NULL) { // Special: last call.
+ enc->got_null_frame_ = 1;
+ enc->prev_timestamp_ = timestamp;
+ return 1;
+ }
+
+ if (frame->width != enc->canvas_width_ ||
+ frame->height != enc->canvas_height_) {
+ frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION;
+ MarkError(enc, "ERROR adding frame: Invalid frame dimensions");
+ return 0;
+ }
+
+ if (!frame->use_argb) { // Convert frame from YUV(A) to ARGB.
+ if (enc->options_.verbose) {
+ fprintf(stderr, "WARNING: Converting frame from YUV(A) to ARGB format; "
+ "this incurs a small loss.\n");
+ }
+ if (!WebPPictureYUVAToARGB(frame)) {
+ MarkError(enc, "ERROR converting frame from YUV(A) to ARGB");
+ return 0;
+ }
+ }
+
+ if (encoder_config != NULL) {
+ config = *encoder_config;
+ } else {
+ WebPConfigInit(&config);
+ config.lossless = 1;
+ }
+ assert(enc->curr_canvas_ == NULL);
+ enc->curr_canvas_ = frame; // Store reference.
+ assert(enc->curr_canvas_copy_modified_ == 1);
+ CopyCurrentCanvas(enc);
+
+ if (!CacheFrame(enc, &config)) {
+ return 0;
+ }
+
+ if (!FlushFrames(enc)) {
+ return 0;
+ }
+ enc->curr_canvas_ = NULL;
+ enc->curr_canvas_copy_modified_ = 1;
+ enc->prev_timestamp_ = timestamp;
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+// Bitstream assembly.
+
+static int DecodeFrameOntoCanvas(const WebPMuxFrameInfo* const frame,
+ WebPPicture* const canvas) {
+ const WebPData* const image = &frame->bitstream;
+ WebPPicture sub_image;
+ WebPDecoderConfig config;
+ WebPInitDecoderConfig(&config);
+ WebPUtilClearPic(canvas, NULL);
+ if (WebPGetFeatures(image->bytes, image->size, &config.input) !=
+ VP8_STATUS_OK) {
+ return 0;
+ }
+ if (!WebPPictureView(canvas, frame->x_offset, frame->y_offset,
+ config.input.width, config.input.height, &sub_image)) {
+ return 0;
+ }
+ config.output.is_external_memory = 1;
+ config.output.colorspace = MODE_BGRA;
+ config.output.u.RGBA.rgba = (uint8_t*)sub_image.argb;
+ config.output.u.RGBA.stride = sub_image.argb_stride * 4;
+ config.output.u.RGBA.size = config.output.u.RGBA.stride * sub_image.height;
+
+ if (WebPDecode(image->bytes, image->size, &config) != VP8_STATUS_OK) {
+ return 0;
+ }
+ return 1;
+}
+
+static int FrameToFullCanvas(WebPAnimEncoder* const enc,
+ const WebPMuxFrameInfo* const frame,
+ WebPData* const full_image) {
+ WebPPicture* const canvas_buf = &enc->curr_canvas_copy_;
+ WebPMemoryWriter mem1, mem2;
+ WebPMemoryWriterInit(&mem1);
+ WebPMemoryWriterInit(&mem2);
+
+ if (!DecodeFrameOntoCanvas(frame, canvas_buf)) goto Err;
+ if (!EncodeFrame(&enc->last_config_, canvas_buf, &mem1)) goto Err;
+ GetEncodedData(&mem1, full_image);
+
+ if (enc->options_.allow_mixed) {
+ if (!EncodeFrame(&enc->last_config_, canvas_buf, &mem2)) goto Err;
+ if (mem2.size < mem1.size) {
+ GetEncodedData(&mem2, full_image);
+ WebPMemoryWriterClear(&mem1);
+ } else {
+ WebPMemoryWriterClear(&mem2);
+ }
+ }
+ return 1;
+
+ Err:
+ WebPMemoryWriterClear(&mem1);
+ WebPMemoryWriterClear(&mem2);
+ return 0;
+}
+
+// Convert a single-frame animation to a non-animated image if appropriate.
+// TODO(urvang): Can we pick one of the two heuristically (based on frame
+// rectangle and/or presence of alpha)?
+static WebPMuxError OptimizeSingleFrame(WebPAnimEncoder* const enc,
+ WebPData* const webp_data) {
+ WebPMuxError err = WEBP_MUX_OK;
+ int canvas_width, canvas_height;
+ WebPMuxFrameInfo frame;
+ WebPData full_image;
+ WebPData webp_data2;
+ WebPMux* const mux = WebPMuxCreate(webp_data, 0);
+ if (mux == NULL) return WEBP_MUX_BAD_DATA;
+ assert(enc->out_frame_count_ == 1);
+ WebPDataInit(&frame.bitstream);
+ WebPDataInit(&full_image);
+ WebPDataInit(&webp_data2);
+
+ err = WebPMuxGetFrame(mux, 1, &frame);
+ if (err != WEBP_MUX_OK) goto End;
+ if (frame.id != WEBP_CHUNK_ANMF) goto End; // Non-animation: nothing to do.
+ err = WebPMuxGetCanvasSize(mux, &canvas_width, &canvas_height);
+ if (err != WEBP_MUX_OK) goto End;
+ if (!FrameToFullCanvas(enc, &frame, &full_image)) {
+ err = WEBP_MUX_BAD_DATA;
+ goto End;
+ }
+ err = WebPMuxSetImage(mux, &full_image, 1);
+ if (err != WEBP_MUX_OK) goto End;
+ err = WebPMuxAssemble(mux, &webp_data2);
+ if (err != WEBP_MUX_OK) goto End;
+
+ if (webp_data2.size < webp_data->size) { // Pick 'webp_data2' if smaller.
+ WebPDataClear(webp_data);
+ *webp_data = webp_data2;
+ WebPDataInit(&webp_data2);
+ }
+
+ End:
+ WebPDataClear(&frame.bitstream);
+ WebPDataClear(&full_image);
+ WebPMuxDelete(mux);
+ WebPDataClear(&webp_data2);
+ return err;
+}
+
+int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, WebPData* webp_data) {
+ WebPMux* mux;
+ WebPMuxError err;
+
+ if (enc == NULL) {
+ return 0;
+ }
+ MarkNoError(enc);
+
+ if (webp_data == NULL) {
+ MarkError(enc, "ERROR assembling: NULL input");
+ return 0;
+ }
+
+ if (enc->in_frame_count_ == 0) {
+ MarkError(enc, "ERROR: No frames to assemble");
+ return 0;
+ }
+
+ if (!enc->got_null_frame_ && enc->in_frame_count_ > 1 && enc->count_ > 0) {
+ // set duration of the last frame to be avg of durations of previous frames.
+ const double delta_time = enc->prev_timestamp_ - enc->first_timestamp_;
+ const int average_duration = (int)(delta_time / (enc->in_frame_count_ - 1));
+ if (!IncreasePreviousDuration(enc, average_duration)) {
+ return 0;
+ }
+ }
+
+ // Flush any remaining frames.
+ enc->flush_count_ = enc->count_;
+ if (!FlushFrames(enc)) {
+ return 0;
+ }
+
+ // Set definitive canvas size.
+ mux = enc->mux_;
+ err = WebPMuxSetCanvasSize(mux, enc->canvas_width_, enc->canvas_height_);
+ if (err != WEBP_MUX_OK) goto Err;
+
+ err = WebPMuxSetAnimationParams(mux, &enc->options_.anim_params);
+ if (err != WEBP_MUX_OK) goto Err;
+
+ // Assemble into a WebP bitstream.
+ err = WebPMuxAssemble(mux, webp_data);
+ if (err != WEBP_MUX_OK) goto Err;
+
+ if (enc->out_frame_count_ == 1) {
+ err = OptimizeSingleFrame(enc, webp_data);
+ if (err != WEBP_MUX_OK) goto Err;
+ }
+ return 1;
+
+ Err:
+ MarkError2(enc, "ERROR assembling WebP", err);
+ return 0;
+}
+
+const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc) {
+ if (enc == NULL) return NULL;
+ return enc->error_str_;
+}
+
+// -----------------------------------------------------------------------------
diff --git a/drivers/webp/mux/muxedit.c b/drivers/webp/mux/muxedit.c
index 08629d4ae2..b27663f87a 100644
--- a/drivers/webp/mux/muxedit.c
+++ b/drivers/webp/mux/muxedit.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Set and delete APIs for mux.
@@ -12,50 +14,51 @@
#include <assert.h>
#include "./muxi.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+#include "../utils/utils.h"
//------------------------------------------------------------------------------
// Life of a mux object.
static void MuxInit(WebPMux* const mux) {
- if (mux == NULL) return;
+ assert(mux != NULL);
memset(mux, 0, sizeof(*mux));
+ mux->canvas_width_ = 0; // just to be explicit
+ mux->canvas_height_ = 0;
}
WebPMux* WebPNewInternal(int version) {
if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_MUX_ABI_VERSION)) {
return NULL;
} else {
- WebPMux* const mux = (WebPMux*)malloc(sizeof(WebPMux));
- // If mux is NULL MuxInit is a noop.
- MuxInit(mux);
+ WebPMux* const mux = (WebPMux*)WebPSafeMalloc(1ULL, sizeof(WebPMux));
+ if (mux != NULL) MuxInit(mux);
return mux;
}
}
-static void DeleteAllChunks(WebPChunk** const chunk_list) {
- while (*chunk_list) {
- *chunk_list = ChunkDelete(*chunk_list);
+// Delete all images in 'wpi_list'.
+static void DeleteAllImages(WebPMuxImage** const wpi_list) {
+ while (*wpi_list != NULL) {
+ *wpi_list = MuxImageDelete(*wpi_list);
}
}
static void MuxRelease(WebPMux* const mux) {
- if (mux == NULL) return;
- MuxImageDeleteAll(&mux->images_);
- DeleteAllChunks(&mux->vp8x_);
- DeleteAllChunks(&mux->iccp_);
- DeleteAllChunks(&mux->loop_);
- DeleteAllChunks(&mux->meta_);
- DeleteAllChunks(&mux->unknown_);
+ assert(mux != NULL);
+ DeleteAllImages(&mux->images_);
+ ChunkListDelete(&mux->vp8x_);
+ ChunkListDelete(&mux->iccp_);
+ ChunkListDelete(&mux->anim_);
+ ChunkListDelete(&mux->exif_);
+ ChunkListDelete(&mux->xmp_);
+ ChunkListDelete(&mux->unknown_);
}
void WebPMuxDelete(WebPMux* mux) {
- // If mux is NULL MuxRelease is a noop.
- MuxRelease(mux);
- free(mux);
+ if (mux != NULL) {
+ MuxRelease(mux);
+ WebPSafeFree(mux);
+ }
}
//------------------------------------------------------------------------------
@@ -64,81 +67,60 @@ void WebPMuxDelete(WebPMux* mux) {
// Handy MACRO, makes MuxSet() very symmetric to MuxGet().
#define SWITCH_ID_LIST(INDEX, LIST) \
if (idx == (INDEX)) { \
- err = ChunkAssignData(&chunk, data, copy_data, kChunks[(INDEX)].tag); \
+ err = ChunkAssignData(&chunk, data, copy_data, tag); \
if (err == WEBP_MUX_OK) { \
err = ChunkSetNth(&chunk, (LIST), nth); \
} \
return err; \
}
-static WebPMuxError MuxSet(WebPMux* const mux, CHUNK_INDEX idx, uint32_t nth,
+static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, uint32_t nth,
const WebPData* const data, int copy_data) {
WebPChunk chunk;
WebPMuxError err = WEBP_MUX_NOT_FOUND;
+ const CHUNK_INDEX idx = ChunkGetIndexFromTag(tag);
assert(mux != NULL);
assert(!IsWPI(kChunks[idx].id));
ChunkInit(&chunk);
- SWITCH_ID_LIST(IDX_VP8X, &mux->vp8x_);
- SWITCH_ID_LIST(IDX_ICCP, &mux->iccp_);
- SWITCH_ID_LIST(IDX_LOOP, &mux->loop_);
- SWITCH_ID_LIST(IDX_META, &mux->meta_);
- if (idx == IDX_UNKNOWN && data->size_ > TAG_SIZE) {
- // For raw-data unknown chunk, the first four bytes should be the tag to be
- // used for the chunk.
- const WebPData tmp = { data->bytes_ + TAG_SIZE, data->size_ - TAG_SIZE };
- err = ChunkAssignData(&chunk, &tmp, copy_data, GetLE32(data->bytes_ + 0));
- if (err == WEBP_MUX_OK)
- err = ChunkSetNth(&chunk, &mux->unknown_, nth);
- }
+ SWITCH_ID_LIST(IDX_VP8X, &mux->vp8x_);
+ SWITCH_ID_LIST(IDX_ICCP, &mux->iccp_);
+ SWITCH_ID_LIST(IDX_ANIM, &mux->anim_);
+ SWITCH_ID_LIST(IDX_EXIF, &mux->exif_);
+ SWITCH_ID_LIST(IDX_XMP, &mux->xmp_);
+ SWITCH_ID_LIST(IDX_UNKNOWN, &mux->unknown_);
return err;
}
#undef SWITCH_ID_LIST
-static WebPMuxError MuxAddChunk(WebPMux* const mux, uint32_t nth, uint32_t tag,
- const uint8_t* data, size_t size,
- int copy_data) {
- const CHUNK_INDEX idx = ChunkGetIndexFromTag(tag);
- const WebPData chunk_data = { data, size };
- assert(mux != NULL);
- assert(size <= MAX_CHUNK_PAYLOAD);
- assert(idx != IDX_NIL);
- return MuxSet(mux, idx, nth, &chunk_data, copy_data);
-}
+// Create data for frame/fragment given image data, offsets and duration.
+static WebPMuxError CreateFrameFragmentData(
+ int width, int height, const WebPMuxFrameInfo* const info, int is_frame,
+ WebPData* const frame_frgm) {
+ uint8_t* frame_frgm_bytes;
+ const size_t frame_frgm_size = kChunks[is_frame ? IDX_ANMF : IDX_FRGM].size;
-// Create data for frame/tile given image data, offsets and duration.
-static WebPMuxError CreateFrameTileData(const WebPData* const image,
- int x_offset, int y_offset,
- int duration, int is_lossless,
- int is_frame,
- WebPData* const frame_tile) {
- int width;
- int height;
- uint8_t* frame_tile_bytes;
- const size_t frame_tile_size = kChunks[is_frame ? IDX_FRAME : IDX_TILE].size;
-
- const int ok = is_lossless ?
- VP8LGetInfo(image->bytes_, image->size_, &width, &height, NULL) :
- VP8GetInfo(image->bytes_, image->size_, image->size_, &width, &height);
- if (!ok) return WEBP_MUX_INVALID_ARGUMENT;
-
- assert(width > 0 && height > 0 && duration > 0);
+ assert(width > 0 && height > 0 && info->duration >= 0);
+ assert(info->dispose_method == (info->dispose_method & 1));
// Note: assertion on upper bounds is done in PutLE24().
- frame_tile_bytes = (uint8_t*)malloc(frame_tile_size);
- if (frame_tile_bytes == NULL) return WEBP_MUX_MEMORY_ERROR;
+ frame_frgm_bytes = (uint8_t*)WebPSafeMalloc(1ULL, frame_frgm_size);
+ if (frame_frgm_bytes == NULL) return WEBP_MUX_MEMORY_ERROR;
- PutLE24(frame_tile_bytes + 0, x_offset / 2);
- PutLE24(frame_tile_bytes + 3, y_offset / 2);
+ PutLE24(frame_frgm_bytes + 0, info->x_offset / 2);
+ PutLE24(frame_frgm_bytes + 3, info->y_offset / 2);
if (is_frame) {
- PutLE24(frame_tile_bytes + 6, width - 1);
- PutLE24(frame_tile_bytes + 9, height - 1);
- PutLE24(frame_tile_bytes + 12, duration - 1);
+ PutLE24(frame_frgm_bytes + 6, width - 1);
+ PutLE24(frame_frgm_bytes + 9, height - 1);
+ PutLE24(frame_frgm_bytes + 12, info->duration);
+ frame_frgm_bytes[15] =
+ (info->blend_method == WEBP_MUX_NO_BLEND ? 2 : 0) |
+ (info->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ? 1 : 0);
}
- frame_tile->bytes_ = frame_tile_bytes;
- frame_tile->size_ = frame_tile_size;
+ frame_frgm->bytes = frame_frgm_bytes;
+ frame_frgm->size = frame_frgm_size;
return WEBP_MUX_OK;
}
@@ -149,8 +131,8 @@ static WebPMuxError GetImageData(const WebPData* const bitstream,
WebPData* const image, WebPData* const alpha,
int* const is_lossless) {
WebPDataInit(alpha); // Default: no alpha.
- if (bitstream->size_ < TAG_SIZE ||
- memcmp(bitstream->bytes_, "RIFF", TAG_SIZE)) {
+ if (bitstream->size < TAG_SIZE ||
+ memcmp(bitstream->bytes, "RIFF", TAG_SIZE)) {
// It is NOT webp file data. Return input data as is.
*image = *bitstream;
} else {
@@ -166,7 +148,7 @@ static WebPMuxError GetImageData(const WebPData* const bitstream,
}
WebPMuxDelete(mux);
}
- *is_lossless = VP8LCheckSignature(image->bytes_, image->size_);
+ *is_lossless = VP8LCheckSignature(image->bytes, image->size);
return WEBP_MUX_OK;
}
@@ -185,204 +167,166 @@ static WebPMuxError DeleteChunks(WebPChunk** chunk_list, uint32_t tag) {
return err;
}
-static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, CHUNK_INDEX idx) {
- const WebPChunkId id = kChunks[idx].id;
- WebPChunk** chunk_list;
-
- if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, uint32_t tag) {
+ const WebPChunkId id = ChunkGetIdFromTag(tag);
+ assert(mux != NULL);
if (IsWPI(id)) return WEBP_MUX_INVALID_ARGUMENT;
-
- chunk_list = MuxGetChunkListFromId(mux, id);
- if (chunk_list == NULL) return WEBP_MUX_INVALID_ARGUMENT;
-
- return DeleteChunks(chunk_list, kChunks[idx].tag);
-}
-
-static WebPMuxError DeleteLoopCount(WebPMux* const mux) {
- return MuxDeleteAllNamedData(mux, IDX_LOOP);
+ return DeleteChunks(MuxGetChunkListFromId(mux, id), tag);
}
//------------------------------------------------------------------------------
// Set API(s).
-WebPMuxError WebPMuxSetImage(WebPMux* mux,
- const WebPData* bitstream, int copy_data) {
+WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4],
+ const WebPData* chunk_data, int copy_data) {
+ uint32_t tag;
WebPMuxError err;
- WebPChunk chunk;
- WebPMuxImage wpi;
- WebPData image;
- WebPData alpha;
- int is_lossless;
- int image_tag;
-
- if (mux == NULL || bitstream == NULL || bitstream->bytes_ == NULL ||
- bitstream->size_ > MAX_CHUNK_PAYLOAD) {
+ if (mux == NULL || fourcc == NULL || chunk_data == NULL ||
+ chunk_data->bytes == NULL || chunk_data->size > MAX_CHUNK_PAYLOAD) {
return WEBP_MUX_INVALID_ARGUMENT;
}
+ tag = ChunkGetTagFromFourCC(fourcc);
- // If given data is for a whole webp file,
- // extract only the VP8/VP8L data from it.
- err = GetImageData(bitstream, &image, &alpha, &is_lossless);
- if (err != WEBP_MUX_OK) return err;
- image_tag = is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag;
-
- // Delete the existing images.
- MuxImageDeleteAll(&mux->images_);
-
- MuxImageInit(&wpi);
+ // Delete existing chunk(s) with the same 'fourcc'.
+ err = MuxDeleteAllNamedData(mux, tag);
+ if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
- if (alpha.bytes_ != NULL) { // Add alpha chunk.
- ChunkInit(&chunk);
- err = ChunkAssignData(&chunk, &alpha, copy_data, kChunks[IDX_ALPHA].tag);
- if (err != WEBP_MUX_OK) goto Err;
- err = ChunkSetNth(&chunk, &wpi.alpha_, 1);
- if (err != WEBP_MUX_OK) goto Err;
- }
+ // Add the given chunk.
+ return MuxSet(mux, tag, 1, chunk_data, copy_data);
+}
- // Add image chunk.
+// Creates a chunk from given 'data' and sets it as 1st chunk in 'chunk_list'.
+static WebPMuxError AddDataToChunkList(
+ const WebPData* const data, int copy_data, uint32_t tag,
+ WebPChunk** chunk_list) {
+ WebPChunk chunk;
+ WebPMuxError err;
ChunkInit(&chunk);
- err = ChunkAssignData(&chunk, &image, copy_data, image_tag);
+ err = ChunkAssignData(&chunk, data, copy_data, tag);
if (err != WEBP_MUX_OK) goto Err;
- err = ChunkSetNth(&chunk, &wpi.img_, 1);
- if (err != WEBP_MUX_OK) goto Err;
-
- // Add this image to mux.
- err = MuxImagePush(&wpi, &mux->images_);
+ err = ChunkSetNth(&chunk, chunk_list, 1);
if (err != WEBP_MUX_OK) goto Err;
-
- // All OK.
return WEBP_MUX_OK;
-
Err:
- // Something bad happened.
ChunkRelease(&chunk);
- MuxImageRelease(&wpi);
return err;
}
-WebPMuxError WebPMuxSetMetadata(WebPMux* mux, const WebPData* metadata,
- int copy_data) {
- WebPMuxError err;
-
- if (mux == NULL || metadata == NULL || metadata->bytes_ == NULL ||
- metadata->size_ > MAX_CHUNK_PAYLOAD) {
- return WEBP_MUX_INVALID_ARGUMENT;
+// Extracts image & alpha data from the given bitstream and then sets wpi.alpha_
+// and wpi.img_ appropriately.
+static WebPMuxError SetAlphaAndImageChunks(
+ const WebPData* const bitstream, int copy_data, WebPMuxImage* const wpi) {
+ int is_lossless = 0;
+ WebPData image, alpha;
+ WebPMuxError err = GetImageData(bitstream, &image, &alpha, &is_lossless);
+ const int image_tag =
+ is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag;
+ if (err != WEBP_MUX_OK) return err;
+ if (alpha.bytes != NULL) {
+ err = AddDataToChunkList(&alpha, copy_data, kChunks[IDX_ALPHA].tag,
+ &wpi->alpha_);
+ if (err != WEBP_MUX_OK) return err;
}
-
- // Delete the existing metadata chunk(s).
- err = WebPMuxDeleteMetadata(mux);
- if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
-
- // Add the given metadata chunk.
- return MuxSet(mux, IDX_META, 1, metadata, copy_data);
+ err = AddDataToChunkList(&image, copy_data, image_tag, &wpi->img_);
+ if (err != WEBP_MUX_OK) return err;
+ return MuxImageFinalize(wpi) ? WEBP_MUX_OK : WEBP_MUX_INVALID_ARGUMENT;
}
-WebPMuxError WebPMuxSetColorProfile(WebPMux* mux, const WebPData* color_profile,
- int copy_data) {
+WebPMuxError WebPMuxSetImage(WebPMux* mux, const WebPData* bitstream,
+ int copy_data) {
+ WebPMuxImage wpi;
WebPMuxError err;
- if (mux == NULL || color_profile == NULL || color_profile->bytes_ == NULL ||
- color_profile->size_ > MAX_CHUNK_PAYLOAD) {
+ // Sanity checks.
+ if (mux == NULL || bitstream == NULL || bitstream->bytes == NULL ||
+ bitstream->size > MAX_CHUNK_PAYLOAD) {
return WEBP_MUX_INVALID_ARGUMENT;
}
- // Delete the existing ICCP chunk(s).
- err = WebPMuxDeleteColorProfile(mux);
- if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
-
- // Add the given ICCP chunk.
- return MuxSet(mux, IDX_ICCP, 1, color_profile, copy_data);
-}
-
-WebPMuxError WebPMuxSetLoopCount(WebPMux* mux, int loop_count) {
- WebPMuxError err;
- uint8_t* data = NULL;
+ if (mux->images_ != NULL) {
+ // Only one 'simple image' can be added in mux. So, remove present images.
+ DeleteAllImages(&mux->images_);
+ }
- if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
- if (loop_count >= MAX_LOOP_COUNT) return WEBP_MUX_INVALID_ARGUMENT;
+ MuxImageInit(&wpi);
+ err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi);
+ if (err != WEBP_MUX_OK) goto Err;
- // Delete the existing LOOP chunk(s).
- err = DeleteLoopCount(mux);
- if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
+ // Add this WebPMuxImage to mux.
+ err = MuxImagePush(&wpi, &mux->images_);
+ if (err != WEBP_MUX_OK) goto Err;
- // Add the given loop count.
- data = (uint8_t*)malloc(kChunks[IDX_LOOP].size);
- if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
+ // All is well.
+ return WEBP_MUX_OK;
- PutLE16(data, loop_count);
- err = MuxAddChunk(mux, 1, kChunks[IDX_LOOP].tag, data,
- kChunks[IDX_LOOP].size, 1);
- free(data);
+ Err: // Something bad happened.
+ MuxImageRelease(&wpi);
return err;
}
-static WebPMuxError MuxPushFrameTileInternal(
- WebPMux* const mux, const WebPData* const bitstream, int x_offset,
- int y_offset, int duration, int copy_data, uint32_t tag) {
- WebPChunk chunk;
- WebPData image;
- WebPData alpha;
+WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame,
+ int copy_data) {
WebPMuxImage wpi;
WebPMuxError err;
- WebPData frame_tile;
- const int is_frame = (tag == kChunks[IDX_FRAME].tag) ? 1 : 0;
- int is_lossless;
- int image_tag;
+ int is_frame;
+ const WebPData* const bitstream = &frame->bitstream;
// Sanity checks.
- if (mux == NULL || bitstream == NULL || bitstream->bytes_ == NULL ||
- bitstream->size_ > MAX_CHUNK_PAYLOAD) {
+ if (mux == NULL || frame == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+
+ is_frame = (frame->id == WEBP_CHUNK_ANMF);
+ if (!(is_frame || (frame->id == WEBP_CHUNK_FRGM))) {
return WEBP_MUX_INVALID_ARGUMENT;
}
- if (x_offset < 0 || x_offset >= MAX_POSITION_OFFSET ||
- y_offset < 0 || y_offset >= MAX_POSITION_OFFSET ||
- duration <= 0 || duration > MAX_DURATION) {
+ if (frame->id == WEBP_CHUNK_FRGM) { // Dead experiment.
return WEBP_MUX_INVALID_ARGUMENT;
}
- // Snap offsets to even positions.
- x_offset &= ~1;
- y_offset &= ~1;
+ if (bitstream->bytes == NULL || bitstream->size > MAX_CHUNK_PAYLOAD) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
- // If given data is for a whole webp file,
- // extract only the VP8/VP8L data from it.
- err = GetImageData(bitstream, &image, &alpha, &is_lossless);
- if (err != WEBP_MUX_OK) return err;
- image_tag = is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag;
+ if (mux->images_ != NULL) {
+ const WebPMuxImage* const image = mux->images_;
+ const uint32_t image_id = (image->header_ != NULL) ?
+ ChunkGetIdFromTag(image->header_->tag_) : WEBP_CHUNK_IMAGE;
+ if (image_id != frame->id) {
+ return WEBP_MUX_INVALID_ARGUMENT; // Conflicting frame types.
+ }
+ }
- WebPDataInit(&frame_tile);
- ChunkInit(&chunk);
MuxImageInit(&wpi);
-
- if (alpha.bytes_ != NULL) {
- // Add alpha chunk.
- err = ChunkAssignData(&chunk, &alpha, copy_data, kChunks[IDX_ALPHA].tag);
+ err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi);
+ if (err != WEBP_MUX_OK) goto Err;
+ assert(wpi.img_ != NULL); // As SetAlphaAndImageChunks() was successful.
+
+ {
+ WebPData frame_frgm;
+ const uint32_t tag = kChunks[is_frame ? IDX_ANMF : IDX_FRGM].tag;
+ WebPMuxFrameInfo tmp = *frame;
+ tmp.x_offset &= ~1; // Snap offsets to even.
+ tmp.y_offset &= ~1;
+ if (!is_frame) { // Reset unused values.
+ tmp.duration = 1;
+ tmp.dispose_method = WEBP_MUX_DISPOSE_NONE;
+ tmp.blend_method = WEBP_MUX_BLEND;
+ }
+ if (tmp.x_offset < 0 || tmp.x_offset >= MAX_POSITION_OFFSET ||
+ tmp.y_offset < 0 || tmp.y_offset >= MAX_POSITION_OFFSET ||
+ (tmp.duration < 0 || tmp.duration >= MAX_DURATION) ||
+ tmp.dispose_method != (tmp.dispose_method & 1)) {
+ err = WEBP_MUX_INVALID_ARGUMENT;
+ goto Err;
+ }
+ err = CreateFrameFragmentData(wpi.width_, wpi.height_, &tmp, is_frame,
+ &frame_frgm);
if (err != WEBP_MUX_OK) goto Err;
- err = ChunkSetNth(&chunk, &wpi.alpha_, 1);
+ // Add frame/fragment chunk (with copy_data = 1).
+ err = AddDataToChunkList(&frame_frgm, 1, tag, &wpi.header_);
+ WebPDataClear(&frame_frgm); // frame_frgm owned by wpi.header_ now.
if (err != WEBP_MUX_OK) goto Err;
- ChunkInit(&chunk); // chunk owned by wpi.alpha_ now.
}
- // Add image chunk.
- err = ChunkAssignData(&chunk, &image, copy_data, image_tag);
- if (err != WEBP_MUX_OK) goto Err;
- err = ChunkSetNth(&chunk, &wpi.img_, 1);
- if (err != WEBP_MUX_OK) goto Err;
- ChunkInit(&chunk); // chunk owned by wpi.img_ now.
-
- // Create frame/tile data.
- err = CreateFrameTileData(&image, x_offset, y_offset, duration, is_lossless,
- is_frame, &frame_tile);
- if (err != WEBP_MUX_OK) goto Err;
-
- // Add frame/tile chunk (with copy_data = 1).
- err = ChunkAssignData(&chunk, &frame_tile, 1, tag);
- if (err != WEBP_MUX_OK) goto Err;
- WebPDataClear(&frame_tile);
- err = ChunkSetNth(&chunk, &wpi.header_, 1);
- if (err != WEBP_MUX_OK) goto Err;
- ChunkInit(&chunk); // chunk owned by wpi.header_ now.
-
// Add this WebPMuxImage to mux.
err = MuxImagePush(&wpi, &mux->images_);
if (err != WEBP_MUX_OK) goto Err;
@@ -391,128 +335,114 @@ static WebPMuxError MuxPushFrameTileInternal(
return WEBP_MUX_OK;
Err: // Something bad happened.
- WebPDataClear(&frame_tile);
- ChunkRelease(&chunk);
MuxImageRelease(&wpi);
return err;
}
-WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPData* bitstream,
- int x_offset, int y_offset,
- int duration, int copy_data) {
- return MuxPushFrameTileInternal(mux, bitstream, x_offset, y_offset,
- duration, copy_data, kChunks[IDX_FRAME].tag);
-}
-
-WebPMuxError WebPMuxPushTile(WebPMux* mux, const WebPData* bitstream,
- int x_offset, int y_offset,
- int copy_data) {
- return MuxPushFrameTileInternal(mux, bitstream, x_offset, y_offset,
- 1 /* unused duration */, copy_data,
- kChunks[IDX_TILE].tag);
-}
-
-//------------------------------------------------------------------------------
-// Delete API(s).
-
-WebPMuxError WebPMuxDeleteImage(WebPMux* mux) {
+WebPMuxError WebPMuxSetAnimationParams(WebPMux* mux,
+ const WebPMuxAnimParams* params) {
WebPMuxError err;
+ uint8_t data[ANIM_CHUNK_SIZE];
+ const WebPData anim = { data, ANIM_CHUNK_SIZE };
- if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ if (params->loop_count < 0 || params->loop_count >= MAX_LOOP_COUNT) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
- err = MuxValidateForImage(mux);
- if (err != WEBP_MUX_OK) return err;
+ // Delete any existing ANIM chunk(s).
+ err = MuxDeleteAllNamedData(mux, kChunks[IDX_ANIM].tag);
+ if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
- // All well, delete image.
- MuxImageDeleteAll(&mux->images_);
- return WEBP_MUX_OK;
+ // Set the animation parameters.
+ PutLE32(data, params->bgcolor);
+ PutLE16(data + 4, params->loop_count);
+ return MuxSet(mux, kChunks[IDX_ANIM].tag, 1, &anim, 1);
}
-WebPMuxError WebPMuxDeleteMetadata(WebPMux* mux) {
- return MuxDeleteAllNamedData(mux, IDX_META);
-}
+WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux,
+ int width, int height) {
+ WebPMuxError err;
+ if (mux == NULL) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+ if (width < 0 || height < 0 ||
+ width > MAX_CANVAS_SIZE || height > MAX_CANVAS_SIZE) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+ if (width * (uint64_t)height >= MAX_IMAGE_AREA) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+ if ((width * height) == 0 && (width | height) != 0) {
+ // one of width / height is zero, but not both -> invalid!
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+ // If we already assembled a VP8X chunk, invalidate it.
+ err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag);
+ if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
-WebPMuxError WebPMuxDeleteColorProfile(WebPMux* mux) {
- return MuxDeleteAllNamedData(mux, IDX_ICCP);
+ mux->canvas_width_ = width;
+ mux->canvas_height_ = height;
+ return WEBP_MUX_OK;
}
-static WebPMuxError DeleteFrameTileInternal(WebPMux* const mux, uint32_t nth,
- CHUNK_INDEX idx) {
- const WebPChunkId id = kChunks[idx].id;
- if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+//------------------------------------------------------------------------------
+// Delete API(s).
- assert(idx == IDX_FRAME || idx == IDX_TILE);
- return MuxImageDeleteNth(&mux->images_, nth, id);
+WebPMuxError WebPMuxDeleteChunk(WebPMux* mux, const char fourcc[4]) {
+ if (mux == NULL || fourcc == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ return MuxDeleteAllNamedData(mux, ChunkGetTagFromFourCC(fourcc));
}
WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) {
- return DeleteFrameTileInternal(mux, nth, IDX_FRAME);
-}
-
-WebPMuxError WebPMuxDeleteTile(WebPMux* mux, uint32_t nth) {
- return DeleteFrameTileInternal(mux, nth, IDX_TILE);
+ if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ return MuxImageDeleteNth(&mux->images_, nth);
}
//------------------------------------------------------------------------------
// Assembly of the WebP RIFF file.
-static WebPMuxError GetFrameTileInfo(const WebPChunk* const frame_tile_chunk,
- int* const x_offset, int* const y_offset,
- int* const duration) {
- const uint32_t tag = frame_tile_chunk->tag_;
- const int is_frame = (tag == kChunks[IDX_FRAME].tag);
- const WebPData* const data = &frame_tile_chunk->data_;
+static WebPMuxError GetFrameFragmentInfo(
+ const WebPChunk* const frame_frgm_chunk,
+ int* const x_offset, int* const y_offset, int* const duration) {
+ const uint32_t tag = frame_frgm_chunk->tag_;
+ const int is_frame = (tag == kChunks[IDX_ANMF].tag);
+ const WebPData* const data = &frame_frgm_chunk->data_;
const size_t expected_data_size =
- is_frame ? FRAME_CHUNK_SIZE : TILE_CHUNK_SIZE;
- assert(frame_tile_chunk != NULL);
- assert(tag == kChunks[IDX_FRAME].tag || tag == kChunks[IDX_TILE].tag);
- if (data->size_ != expected_data_size) return WEBP_MUX_INVALID_ARGUMENT;
-
- *x_offset = 2 * GetLE24(data->bytes_ + 0);
- *y_offset = 2 * GetLE24(data->bytes_ + 3);
- if (is_frame) *duration = 1 + GetLE24(data->bytes_ + 12);
+ is_frame ? ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE;
+ assert(frame_frgm_chunk != NULL);
+ assert(tag == kChunks[IDX_ANMF].tag || tag == kChunks[IDX_FRGM].tag);
+ if (data->size != expected_data_size) return WEBP_MUX_INVALID_ARGUMENT;
+
+ *x_offset = 2 * GetLE24(data->bytes + 0);
+ *y_offset = 2 * GetLE24(data->bytes + 3);
+ if (is_frame) *duration = GetLE24(data->bytes + 12);
return WEBP_MUX_OK;
}
-WebPMuxError MuxGetImageWidthHeight(const WebPChunk* const image_chunk,
- int* const width, int* const height) {
- const uint32_t tag = image_chunk->tag_;
- const WebPData* const data = &image_chunk->data_;
- int w, h;
- int ok;
- assert(image_chunk != NULL);
- assert(tag == kChunks[IDX_VP8].tag || tag == kChunks[IDX_VP8L].tag);
- ok = (tag == kChunks[IDX_VP8].tag) ?
- VP8GetInfo(data->bytes_, data->size_, data->size_, &w, &h) :
- VP8LGetInfo(data->bytes_, data->size_, &w, &h, NULL);
- if (ok) {
- *width = w;
- *height = h;
- return WEBP_MUX_OK;
- } else {
- return WEBP_MUX_BAD_DATA;
- }
-}
-
static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi,
int* const x_offset, int* const y_offset,
int* const duration,
int* const width, int* const height) {
- const WebPChunk* const image_chunk = wpi->img_;
- const WebPChunk* const frame_tile_chunk = wpi->header_;
+ const WebPChunk* const frame_frgm_chunk = wpi->header_;
+ WebPMuxError err;
+ assert(wpi != NULL);
+ assert(frame_frgm_chunk != NULL);
- // Get offsets and duration from FRM/TILE chunk.
- const WebPMuxError err =
- GetFrameTileInfo(frame_tile_chunk, x_offset, y_offset, duration);
+ // Get offsets and duration from ANMF/FRGM chunk.
+ err = GetFrameFragmentInfo(frame_frgm_chunk, x_offset, y_offset, duration);
if (err != WEBP_MUX_OK) return err;
// Get width and height from VP8/VP8L chunk.
- return MuxGetImageWidthHeight(image_chunk, width, height);
+ if (width != NULL) *width = wpi->width_;
+ if (height != NULL) *height = wpi->height_;
+ return WEBP_MUX_OK;
}
-static WebPMuxError GetImageCanvasWidthHeight(
- const WebPMux* const mux, uint32_t flags,
- int* const width, int* const height) {
+// Returns the tightest dimension for the canvas considering the image list.
+static WebPMuxError GetAdjustedCanvasSize(const WebPMux* const mux,
+ uint32_t flags,
+ int* const width, int* const height) {
WebPMuxImage* wpi = NULL;
assert(mux != NULL);
assert(width != NULL && height != NULL);
@@ -521,13 +451,15 @@ static WebPMuxError GetImageCanvasWidthHeight(
assert(wpi != NULL);
assert(wpi->img_ != NULL);
- if (wpi->next_) {
+ if (wpi->next_ != NULL) {
int max_x = 0;
int max_y = 0;
int64_t image_area = 0;
- // Aggregate the bounding box for animation frames & tiled images.
+ // if we have a chain of wpi's, header_ is necessarily set
+ assert(wpi->header_ != NULL);
+ // Aggregate the bounding box for animation frames & fragmented images.
for (; wpi != NULL; wpi = wpi->next_) {
- int x_offset, y_offset, duration, w, h;
+ int x_offset = 0, y_offset = 0, duration = 0, w = 0, h = 0;
const WebPMuxError err = GetImageInfo(wpi, &x_offset, &y_offset,
&duration, &w, &h);
const int max_x_pos = x_offset + w;
@@ -542,23 +474,19 @@ static WebPMuxError GetImageCanvasWidthHeight(
}
*width = max_x;
*height = max_y;
- // Crude check to validate that there are no image overlaps/holes for tile
- // images. Check that the aggregated image area for individual tiles exactly
- // matches the image area of the constructed canvas. However, the area-match
- // is necessary but not sufficient condition.
- if ((flags & TILE_FLAG) && (image_area != (max_x * max_y))) {
+ // Crude check to validate that there are no image overlaps/holes for
+ // fragmented images. Check that the aggregated image area for individual
+ // fragments exactly matches the image area of the constructed canvas.
+ // However, the area-match is necessary but not sufficient condition.
+ if ((flags & FRAGMENTS_FLAG) && (image_area != (max_x * max_y))) {
*width = 0;
*height = 0;
return WEBP_MUX_INVALID_ARGUMENT;
}
} else {
- // For a single image, extract the width & height from VP8/VP8L image-data.
- int w, h;
- const WebPChunk* const image_chunk = wpi->img_;
- const WebPMuxError err = MuxGetImageWidthHeight(image_chunk, &w, &h);
- if (err != WEBP_MUX_OK) return err;
- *width = w;
- *height = h;
+ // For a single image, canvas dimensions are same as image dimensions.
+ *width = wpi->width_;
+ *height = wpi->height_;
}
return WEBP_MUX_OK;
}
@@ -574,50 +502,45 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
int width = 0;
int height = 0;
uint8_t data[VP8X_CHUNK_SIZE];
- const size_t data_size = VP8X_CHUNK_SIZE;
+ const WebPData vp8x = { data, VP8X_CHUNK_SIZE };
const WebPMuxImage* images = NULL;
assert(mux != NULL);
images = mux->images_; // First image.
if (images == NULL || images->img_ == NULL ||
- images->img_->data_.bytes_ == NULL) {
+ images->img_->data_.bytes == NULL) {
return WEBP_MUX_INVALID_ARGUMENT;
}
// If VP8X chunk(s) is(are) already present, remove them (and later add new
// VP8X chunk with updated flags).
- err = MuxDeleteAllNamedData(mux, IDX_VP8X);
+ err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag);
if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
// Set flags.
- if (mux->iccp_ != NULL && mux->iccp_->data_.bytes_ != NULL) {
+ if (mux->iccp_ != NULL && mux->iccp_->data_.bytes != NULL) {
flags |= ICCP_FLAG;
}
-
- if (mux->meta_ != NULL && mux->meta_->data_.bytes_ != NULL) {
- flags |= META_FLAG;
+ if (mux->exif_ != NULL && mux->exif_->data_.bytes != NULL) {
+ flags |= EXIF_FLAG;
+ }
+ if (mux->xmp_ != NULL && mux->xmp_->data_.bytes != NULL) {
+ flags |= XMP_FLAG;
}
-
if (images->header_ != NULL) {
- if (images->header_->tag_ == kChunks[IDX_TILE].tag) {
- // This is a tiled image.
- flags |= TILE_FLAG;
- } else if (images->header_->tag_ == kChunks[IDX_FRAME].tag) {
+ if (images->header_->tag_ == kChunks[IDX_FRGM].tag) {
+ // This is a fragmented image.
+ flags |= FRAGMENTS_FLAG;
+ } else if (images->header_->tag_ == kChunks[IDX_ANMF].tag) {
// This is an image with animation.
flags |= ANIMATION_FLAG;
}
}
-
if (MuxImageCount(images, WEBP_CHUNK_ALPHA) > 0) {
flags |= ALPHA_FLAG; // Some images have an alpha channel.
}
- if (flags == 0) {
- // For Simple Image, VP8X chunk should not be added.
- return WEBP_MUX_OK;
- }
-
- err = GetImageCanvasWidthHeight(mux, flags, &width, &height);
+ err = GetAdjustedCanvasSize(mux, flags, &width, &height);
if (err != WEBP_MUX_OK) return err;
if (width <= 0 || height <= 0) {
@@ -627,9 +550,21 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
return WEBP_MUX_INVALID_ARGUMENT;
}
- if (MuxHasLosslessImages(images)) {
- // We have a file with a VP8X chunk having some lossless images.
- // As lossless images implicitly contain alpha, force ALPHA_FLAG to be true.
+ if (mux->canvas_width_ != 0 || mux->canvas_height_ != 0) {
+ if (width > mux->canvas_width_ || height > mux->canvas_height_) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+ width = mux->canvas_width_;
+ height = mux->canvas_height_;
+ }
+
+ if (flags == 0) {
+ // For Simple Image, VP8X chunk should not be added.
+ return WEBP_MUX_OK;
+ }
+
+ if (MuxHasAlpha(images)) {
+ // This means some frames explicitly/implicitly contain alpha.
// Note: This 'flags' update must NOT be done for a lossless image
// without a VP8X chunk!
flags |= ALPHA_FLAG;
@@ -639,74 +574,123 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
PutLE24(data + 4, width - 1); // canvas width.
PutLE24(data + 7, height - 1); // canvas height.
- err = MuxAddChunk(mux, 1, kChunks[IDX_VP8X].tag, data, data_size, 1);
- return err;
+ return MuxSet(mux, kChunks[IDX_VP8X].tag, 1, &vp8x, 1);
+}
+
+// Cleans up 'mux' by removing any unnecessary chunks.
+static WebPMuxError MuxCleanup(WebPMux* const mux) {
+ int num_frames;
+ int num_fragments;
+ int num_anim_chunks;
+
+ // If we have an image with a single fragment or frame, and its rectangle
+ // covers the whole canvas, convert it to a non-animated non-fragmented image
+ // (to avoid writing FRGM/ANMF chunk unnecessarily).
+ WebPMuxError err = WebPMuxNumChunks(mux, kChunks[IDX_ANMF].id, &num_frames);
+ if (err != WEBP_MUX_OK) return err;
+ err = WebPMuxNumChunks(mux, kChunks[IDX_FRGM].id, &num_fragments);
+ if (err != WEBP_MUX_OK) return err;
+ if (num_frames == 1 || num_fragments == 1) {
+ WebPMuxImage* frame_frag;
+ err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, &frame_frag);
+ assert(err == WEBP_MUX_OK); // We know that one frame/fragment does exist.
+ assert(frame_frag != NULL);
+ if (frame_frag->header_ != NULL &&
+ ((mux->canvas_width_ == 0 && mux->canvas_height_ == 0) ||
+ (frame_frag->width_ == mux->canvas_width_ &&
+ frame_frag->height_ == mux->canvas_height_))) {
+ assert(frame_frag->header_->tag_ == kChunks[IDX_ANMF].tag ||
+ frame_frag->header_->tag_ == kChunks[IDX_FRGM].tag);
+ ChunkDelete(frame_frag->header_); // Removes ANMF/FRGM chunk.
+ frame_frag->header_ = NULL;
+ num_frames = 0;
+ num_fragments = 0;
+ }
+ }
+ // Remove ANIM chunk if this is a non-animated image.
+ err = WebPMuxNumChunks(mux, kChunks[IDX_ANIM].id, &num_anim_chunks);
+ if (err != WEBP_MUX_OK) return err;
+ if (num_anim_chunks >= 1 && num_frames == 0) {
+ err = MuxDeleteAllNamedData(mux, kChunks[IDX_ANIM].tag);
+ if (err != WEBP_MUX_OK) return err;
+ }
+ return WEBP_MUX_OK;
+}
+
+// Total size of a list of images.
+static size_t ImageListDiskSize(const WebPMuxImage* wpi_list) {
+ size_t size = 0;
+ while (wpi_list != NULL) {
+ size += MuxImageDiskSize(wpi_list);
+ wpi_list = wpi_list->next_;
+ }
+ return size;
+}
+
+// Write out the given list of images into 'dst'.
+static uint8_t* ImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst) {
+ while (wpi_list != NULL) {
+ dst = MuxImageEmit(wpi_list, dst);
+ wpi_list = wpi_list->next_;
+ }
+ return dst;
}
WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) {
size_t size = 0;
uint8_t* data = NULL;
uint8_t* dst = NULL;
- int num_frames;
- int num_loop_chunks;
WebPMuxError err;
- if (mux == NULL || assembled_data == NULL) {
+ if (assembled_data == NULL) {
return WEBP_MUX_INVALID_ARGUMENT;
}
+ // Clean up returned data, in case something goes wrong.
+ memset(assembled_data, 0, sizeof(*assembled_data));
- // Remove LOOP chunk if unnecessary.
- err = WebPMuxNumChunks(mux, kChunks[IDX_LOOP].id, &num_loop_chunks);
- if (err != WEBP_MUX_OK) return err;
- if (num_loop_chunks >= 1) {
- err = WebPMuxNumChunks(mux, kChunks[IDX_FRAME].id, &num_frames);
- if (err != WEBP_MUX_OK) return err;
- if (num_frames == 0) {
- err = DeleteLoopCount(mux);
- if (err != WEBP_MUX_OK) return err;
- }
+ if (mux == NULL) {
+ return WEBP_MUX_INVALID_ARGUMENT;
}
- // Create VP8X chunk.
+ // Finalize mux.
+ err = MuxCleanup(mux);
+ if (err != WEBP_MUX_OK) return err;
err = CreateVP8XChunk(mux);
if (err != WEBP_MUX_OK) return err;
// Allocate data.
- size = ChunksListDiskSize(mux->vp8x_) + ChunksListDiskSize(mux->iccp_)
- + ChunksListDiskSize(mux->loop_) + MuxImageListDiskSize(mux->images_)
- + ChunksListDiskSize(mux->meta_) + ChunksListDiskSize(mux->unknown_)
- + RIFF_HEADER_SIZE;
+ size = ChunkListDiskSize(mux->vp8x_) + ChunkListDiskSize(mux->iccp_)
+ + ChunkListDiskSize(mux->anim_) + ImageListDiskSize(mux->images_)
+ + ChunkListDiskSize(mux->exif_) + ChunkListDiskSize(mux->xmp_)
+ + ChunkListDiskSize(mux->unknown_) + RIFF_HEADER_SIZE;
- data = (uint8_t*)malloc(size);
+ data = (uint8_t*)WebPSafeMalloc(1ULL, size);
if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
// Emit header & chunks.
dst = MuxEmitRiffHeader(data, size);
dst = ChunkListEmit(mux->vp8x_, dst);
dst = ChunkListEmit(mux->iccp_, dst);
- dst = ChunkListEmit(mux->loop_, dst);
- dst = MuxImageListEmit(mux->images_, dst);
- dst = ChunkListEmit(mux->meta_, dst);
+ dst = ChunkListEmit(mux->anim_, dst);
+ dst = ImageListEmit(mux->images_, dst);
+ dst = ChunkListEmit(mux->exif_, dst);
+ dst = ChunkListEmit(mux->xmp_, dst);
dst = ChunkListEmit(mux->unknown_, dst);
assert(dst == data + size);
// Validate mux.
err = MuxValidate(mux);
if (err != WEBP_MUX_OK) {
- free(data);
+ WebPSafeFree(data);
data = NULL;
size = 0;
}
- // Finalize.
- assembled_data->bytes_ = data;
- assembled_data->size_ = size;
+ // Finalize data.
+ assembled_data->bytes = data;
+ assembled_data->size = size;
return err;
}
//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/mux/muxi.h b/drivers/webp/mux/muxi.h
index 2f06f3ed03..8bd5291661 100644
--- a/drivers/webp/mux/muxi.h
+++ b/drivers/webp/mux/muxi.h
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Internal header for mux library.
@@ -15,34 +17,41 @@
#include <stdlib.h>
#include "../dec/vp8i.h"
#include "../dec/vp8li.h"
-#include "../format_constants.h"
-#include "../mux.h"
+#include "webp/mux.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
//------------------------------------------------------------------------------
// Defines and constants.
+#define MUX_MAJ_VERSION 0
+#define MUX_MIN_VERSION 2
+#define MUX_REV_VERSION 2
+
// Chunk object.
typedef struct WebPChunk WebPChunk;
struct WebPChunk {
uint32_t tag_;
int owner_; // True if *data_ memory is owned internally.
- // VP8X, Loop, and other internally created chunks
- // like frame/tile are always owned.
+ // VP8X, ANIM, and other internally created chunks
+ // like ANMF/FRGM are always owned.
WebPData data_;
WebPChunk* next_;
};
-// MuxImage object. Store a full webp image (including frame/tile chunk, alpha
+// MuxImage object. Store a full WebP image (including ANMF/FRGM chunk, ALPH
// chunk and VP8/VP8L chunk),
typedef struct WebPMuxImage WebPMuxImage;
struct WebPMuxImage {
- WebPChunk* header_; // Corresponds to WEBP_CHUNK_FRAME/WEBP_CHUNK_TILE.
+ WebPChunk* header_; // Corresponds to WEBP_CHUNK_ANMF/WEBP_CHUNK_FRGM.
WebPChunk* alpha_; // Corresponds to WEBP_CHUNK_ALPHA.
WebPChunk* img_; // Corresponds to WEBP_CHUNK_IMAGE.
+ WebPChunk* unknown_; // Corresponds to WEBP_CHUNK_UNKNOWN.
+ int width_;
+ int height_;
+ int has_alpha_; // Through ALPH chunk or as part of VP8L.
int is_partial_; // True if only some of the chunks are filled.
WebPMuxImage* next_;
};
@@ -51,11 +60,14 @@ struct WebPMuxImage {
struct WebPMux {
WebPMuxImage* images_;
WebPChunk* iccp_;
- WebPChunk* meta_;
- WebPChunk* loop_;
+ WebPChunk* exif_;
+ WebPChunk* xmp_;
+ WebPChunk* anim_;
WebPChunk* vp8x_;
- WebPChunk* unknown_;
+ WebPChunk* unknown_;
+ int canvas_width_;
+ int canvas_height_;
};
// CHUNK_INDEX enum: used for indexing within 'kChunks' (defined below) only.
@@ -65,13 +77,14 @@ struct WebPMux {
typedef enum {
IDX_VP8X = 0,
IDX_ICCP,
- IDX_LOOP,
- IDX_FRAME,
- IDX_TILE,
+ IDX_ANIM,
+ IDX_ANMF,
+ IDX_FRGM,
IDX_ALPHA,
IDX_VP8,
IDX_VP8L,
- IDX_META,
+ IDX_EXIF,
+ IDX_XMP,
IDX_UNKNOWN,
IDX_NIL,
@@ -80,8 +93,6 @@ typedef enum {
#define NIL_TAG 0x00000000u // To signal void chunk.
-#define MKFOURCC(a, b, c, d) ((uint32_t)(a) | (b) << 8 | (c) << 16 | (d) << 24)
-
typedef struct {
uint32_t tag;
WebPChunkId id;
@@ -91,55 +102,23 @@ typedef struct {
extern const ChunkInfo kChunks[IDX_LAST_CHUNK];
//------------------------------------------------------------------------------
-// Helper functions.
-
-// Read 16, 24 or 32 bits stored in little-endian order.
-static WEBP_INLINE int GetLE16(const uint8_t* const data) {
- return (int)(data[0] << 0) | (data[1] << 8);
-}
-
-static WEBP_INLINE int GetLE24(const uint8_t* const data) {
- return GetLE16(data) | (data[2] << 16);
-}
-
-static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) {
- return (uint32_t)GetLE16(data) | (GetLE16(data + 2) << 16);
-}
-
-// Store 16, 24 or 32 bits in little-endian order.
-static WEBP_INLINE void PutLE16(uint8_t* const data, int val) {
- assert(val < (1 << 16));
- data[0] = (val >> 0);
- data[1] = (val >> 8);
-}
-
-static WEBP_INLINE void PutLE24(uint8_t* const data, int val) {
- assert(val < (1 << 24));
- PutLE16(data, val & 0xffff);
- data[2] = (val >> 16);
-}
-
-static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) {
- PutLE16(data, (int)(val & 0xffff));
- PutLE16(data + 2, (int)(val >> 16));
-}
-
-static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) {
- return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U);
-}
-
-//------------------------------------------------------------------------------
// Chunk object management.
// Initialize.
void ChunkInit(WebPChunk* const chunk);
-// Get chunk index from chunk tag. Returns IDX_NIL if not found.
+// Get chunk index from chunk tag. Returns IDX_UNKNOWN if not found.
CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag);
-// Get chunk id from chunk tag. Returns WEBP_CHUNK_NIL if not found.
+// Get chunk id from chunk tag. Returns WEBP_CHUNK_UNKNOWN if not found.
WebPChunkId ChunkGetIdFromTag(uint32_t tag);
+// Convert a fourcc string to a tag.
+uint32_t ChunkGetTagFromFourCC(const char fourcc[4]);
+
+// Get chunk index from fourcc. Returns IDX_UNKNOWN if given fourcc is unknown.
+CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]);
+
// Search for nth chunk with given 'tag' in the chunk list.
// nth = 0 means "last of the list".
WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag);
@@ -150,7 +129,8 @@ WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
// Sets 'chunk' at nth position in the 'chunk_list'.
// nth = 0 has the special meaning "last of the list".
-WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
+// On success ownership is transferred from 'chunk' to the 'chunk_list'.
+WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
uint32_t nth);
// Releases chunk and returns chunk->next_.
@@ -159,23 +139,27 @@ WebPChunk* ChunkRelease(WebPChunk* const chunk);
// Deletes given chunk & returns chunk->next_.
WebPChunk* ChunkDelete(WebPChunk* const chunk);
+// Deletes all chunks in the given chunk list.
+void ChunkListDelete(WebPChunk** const chunk_list);
+
+// Returns size of the chunk including chunk header and padding byte (if any).
+static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) {
+ return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U);
+}
+
// Size of a chunk including header and padding.
static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) {
- const size_t data_size = chunk->data_.size_;
+ const size_t data_size = chunk->data_.size;
assert(data_size < MAX_CHUNK_PAYLOAD);
return SizeWithPadding(data_size);
}
// Total size of a list of chunks.
-size_t ChunksListDiskSize(const WebPChunk* chunk_list);
+size_t ChunkListDiskSize(const WebPChunk* chunk_list);
// Write out the given list of chunks into 'dst'.
uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst);
-// Get the width & height of image stored in 'image_chunk'.
-WebPMuxError MuxGetImageWidthHeight(const WebPChunk* const image_chunk,
- int* const width, int* const height);
-
//------------------------------------------------------------------------------
// MuxImage object management.
@@ -189,82 +173,59 @@ WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi);
// 'wpi' can be NULL.
WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi);
-// Delete all images in 'wpi_list'.
-void MuxImageDeleteAll(WebPMuxImage** const wpi_list);
-
// Count number of images matching the given tag id in the 'wpi_list'.
+// If id == WEBP_CHUNK_NIL, all images will be matched.
int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id);
+// Update width/height/has_alpha info from chunks within wpi.
+// Also remove ALPH chunk if not needed.
+int MuxImageFinalize(WebPMuxImage* const wpi);
+
// Check if given ID corresponds to an image related chunk.
static WEBP_INLINE int IsWPI(WebPChunkId id) {
switch (id) {
- case WEBP_CHUNK_FRAME:
- case WEBP_CHUNK_TILE:
+ case WEBP_CHUNK_ANMF:
+ case WEBP_CHUNK_FRGM:
case WEBP_CHUNK_ALPHA:
case WEBP_CHUNK_IMAGE: return 1;
default: return 0;
}
}
-// Get a reference to appropriate chunk list within an image given chunk tag.
-static WEBP_INLINE WebPChunk** MuxImageGetListFromId(
- const WebPMuxImage* const wpi, WebPChunkId id) {
- assert(wpi != NULL);
- switch (id) {
- case WEBP_CHUNK_FRAME:
- case WEBP_CHUNK_TILE: return (WebPChunk**)&wpi->header_;
- case WEBP_CHUNK_ALPHA: return (WebPChunk**)&wpi->alpha_;
- case WEBP_CHUNK_IMAGE: return (WebPChunk**)&wpi->img_;
- default: return NULL;
- }
-}
-
// Pushes 'wpi' at the end of 'wpi_list'.
WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list);
-// Delete nth image in the image list with given tag id.
-WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth,
- WebPChunkId id);
+// Delete nth image in the image list.
+WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth);
-// Get nth image in the image list with given tag id.
+// Get nth image in the image list.
WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth,
- WebPChunkId id, WebPMuxImage** wpi);
+ WebPMuxImage** wpi);
// Total size of the given image.
size_t MuxImageDiskSize(const WebPMuxImage* const wpi);
-// Total size of a list of images.
-size_t MuxImageListDiskSize(const WebPMuxImage* wpi_list);
-
// Write out the given image into 'dst'.
uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst);
-// Write out the given list of images into 'dst'.
-uint8_t* MuxImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst);
-
//------------------------------------------------------------------------------
// Helper methods for mux.
-// Checks if the given image list contains at least one lossless image.
-int MuxHasLosslessImages(const WebPMuxImage* images);
+// Checks if the given image list contains at least one image with alpha.
+int MuxHasAlpha(const WebPMuxImage* images);
// Write out RIFF header into 'data', given total data size 'size'.
uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size);
// Returns the list where chunk with given ID is to be inserted in mux.
-// Return value is NULL if this chunk should be inserted in mux->images_ list
-// or if 'id' is not known.
WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id);
-// Validates that the given mux has a single image.
-WebPMuxError MuxValidateForImage(const WebPMux* const mux);
-
// Validates the given mux object.
WebPMuxError MuxValidate(const WebPMux* const mux);
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/mux/muxinternal.c b/drivers/webp/mux/muxinternal.c
index 6c3c4fe60a..4babbe82fc 100644
--- a/drivers/webp/mux/muxinternal.c
+++ b/drivers/webp/mux/muxinternal.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Internal objects and utils for mux.
@@ -12,29 +14,33 @@
#include <assert.h>
#include "./muxi.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+#include "../utils/utils.h"
#define UNDEFINED_CHUNK_SIZE (-1)
const ChunkInfo kChunks[] = {
{ MKFOURCC('V', 'P', '8', 'X'), WEBP_CHUNK_VP8X, VP8X_CHUNK_SIZE },
{ MKFOURCC('I', 'C', 'C', 'P'), WEBP_CHUNK_ICCP, UNDEFINED_CHUNK_SIZE },
- { MKFOURCC('L', 'O', 'O', 'P'), WEBP_CHUNK_LOOP, LOOP_CHUNK_SIZE },
- { MKFOURCC('F', 'R', 'M', ' '), WEBP_CHUNK_FRAME, FRAME_CHUNK_SIZE },
- { MKFOURCC('T', 'I', 'L', 'E'), WEBP_CHUNK_TILE, TILE_CHUNK_SIZE },
+ { MKFOURCC('A', 'N', 'I', 'M'), WEBP_CHUNK_ANIM, ANIM_CHUNK_SIZE },
+ { MKFOURCC('A', 'N', 'M', 'F'), WEBP_CHUNK_ANMF, ANMF_CHUNK_SIZE },
+ { MKFOURCC('F', 'R', 'G', 'M'), WEBP_CHUNK_FRGM, FRGM_CHUNK_SIZE },
{ MKFOURCC('A', 'L', 'P', 'H'), WEBP_CHUNK_ALPHA, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('V', 'P', '8', ' '), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('V', 'P', '8', 'L'), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
- { MKFOURCC('M', 'E', 'T', 'A'), WEBP_CHUNK_META, UNDEFINED_CHUNK_SIZE },
- { MKFOURCC('U', 'N', 'K', 'N'), WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE },
+ { MKFOURCC('E', 'X', 'I', 'F'), WEBP_CHUNK_EXIF, UNDEFINED_CHUNK_SIZE },
+ { MKFOURCC('X', 'M', 'P', ' '), WEBP_CHUNK_XMP, UNDEFINED_CHUNK_SIZE },
+ { NIL_TAG, WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE },
- { NIL_TAG, WEBP_CHUNK_NIL, UNDEFINED_CHUNK_SIZE }
+ { NIL_TAG, WEBP_CHUNK_NIL, UNDEFINED_CHUNK_SIZE }
};
//------------------------------------------------------------------------------
+
+int WebPGetMuxVersion(void) {
+ return (MUX_MAJ_VERSION << 16) | (MUX_MIN_VERSION << 8) | MUX_REV_VERSION;
+}
+
+//------------------------------------------------------------------------------
// Life of a chunk object.
void ChunkInit(WebPChunk* const chunk) {
@@ -60,9 +66,9 @@ WebPChunk* ChunkRelease(WebPChunk* const chunk) {
CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag) {
int i;
for (i = 0; kChunks[i].tag != NIL_TAG; ++i) {
- if (tag == kChunks[i].tag) return i;
+ if (tag == kChunks[i].tag) return (CHUNK_INDEX)i;
}
- return IDX_NIL;
+ return IDX_UNKNOWN;
}
WebPChunkId ChunkGetIdFromTag(uint32_t tag) {
@@ -70,7 +76,16 @@ WebPChunkId ChunkGetIdFromTag(uint32_t tag) {
for (i = 0; kChunks[i].tag != NIL_TAG; ++i) {
if (tag == kChunks[i].tag) return kChunks[i].id;
}
- return WEBP_CHUNK_NIL;
+ return WEBP_CHUNK_UNKNOWN;
+}
+
+uint32_t ChunkGetTagFromFourCC(const char fourcc[4]) {
+ return MKFOURCC(fourcc[0], fourcc[1], fourcc[2], fourcc[3]);
+}
+
+CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]) {
+ const uint32_t tag = ChunkGetTagFromFourCC(fourcc);
+ return ChunkGetIndexFromTag(tag);
}
//------------------------------------------------------------------------------
@@ -78,7 +93,7 @@ WebPChunkId ChunkGetIdFromTag(uint32_t tag) {
// Returns next chunk in the chunk list with the given tag.
static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) {
- while (chunk && chunk->tag_ != tag) {
+ while (chunk != NULL && chunk->tag_ != tag) {
chunk = chunk->next_;
}
return chunk;
@@ -87,7 +102,7 @@ static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) {
WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
uint32_t iter = nth;
first = ChunkSearchNextInList(first, tag);
- if (!first) return NULL;
+ if (first == NULL) return NULL;
while (--iter != 0) {
WebPChunk* next_chunk = ChunkSearchNextInList(first->next_, tag);
@@ -99,14 +114,14 @@ WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
// Outputs a pointer to 'prev_chunk->next_',
// where 'prev_chunk' is the pointer to the chunk at position (nth - 1).
-// Returns 1 if nth chunk was found, 0 otherwise.
+// Returns true if nth chunk was found.
static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth,
WebPChunk*** const location) {
uint32_t count = 0;
- assert(chunk_list);
+ assert(chunk_list != NULL);
*location = chunk_list;
- while (*chunk_list) {
+ while (*chunk_list != NULL) {
WebPChunk* const cur_chunk = *chunk_list;
++count;
if (count == nth) return 1; // Found.
@@ -124,34 +139,25 @@ static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth,
WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
int copy_data, uint32_t tag) {
// For internally allocated chunks, always copy data & make it owner of data.
- if (tag == kChunks[IDX_VP8X].tag || tag == kChunks[IDX_LOOP].tag) {
+ if (tag == kChunks[IDX_VP8X].tag || tag == kChunks[IDX_ANIM].tag) {
copy_data = 1;
}
ChunkRelease(chunk);
if (data != NULL) {
- if (copy_data) {
- // Copy data.
- chunk->data_.bytes_ = (uint8_t*)malloc(data->size_);
- if (chunk->data_.bytes_ == NULL) return WEBP_MUX_MEMORY_ERROR;
- memcpy((uint8_t*)chunk->data_.bytes_, data->bytes_, data->size_);
- chunk->data_.size_ = data->size_;
-
- // Chunk is owner of data.
- chunk->owner_ = 1;
- } else {
- // Don't copy data.
+ if (copy_data) { // Copy data.
+ if (!WebPDataCopy(data, &chunk->data_)) return WEBP_MUX_MEMORY_ERROR;
+ chunk->owner_ = 1; // Chunk is owner of data.
+ } else { // Don't copy data.
chunk->data_ = *data;
}
}
-
chunk->tag_ = tag;
-
return WEBP_MUX_OK;
}
-WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
+WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
uint32_t nth) {
WebPChunk* new_chunk;
@@ -159,9 +165,10 @@ WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
return WEBP_MUX_NOT_FOUND;
}
- new_chunk = (WebPChunk*)malloc(sizeof(*new_chunk));
+ new_chunk = (WebPChunk*)WebPSafeMalloc(1ULL, sizeof(*new_chunk));
if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR;
*new_chunk = *chunk;
+ chunk->owner_ = 0;
new_chunk->next_ = *chunk_list;
*chunk_list = new_chunk;
return WEBP_MUX_OK;
@@ -172,70 +179,47 @@ WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
WebPChunk* ChunkDelete(WebPChunk* const chunk) {
WebPChunk* const next = ChunkRelease(chunk);
- free(chunk);
+ WebPSafeFree(chunk);
return next;
}
-//------------------------------------------------------------------------------
-// Chunk serialization methods.
-
-size_t ChunksListDiskSize(const WebPChunk* chunk_list) {
- size_t size = 0;
- while (chunk_list) {
- size += ChunkDiskSize(chunk_list);
- chunk_list = chunk_list->next_;
+void ChunkListDelete(WebPChunk** const chunk_list) {
+ while (*chunk_list != NULL) {
+ *chunk_list = ChunkDelete(*chunk_list);
}
- return size;
}
+//------------------------------------------------------------------------------
+// Chunk serialization methods.
+
static uint8_t* ChunkEmit(const WebPChunk* const chunk, uint8_t* dst) {
- const size_t chunk_size = chunk->data_.size_;
+ const size_t chunk_size = chunk->data_.size;
assert(chunk);
assert(chunk->tag_ != NIL_TAG);
PutLE32(dst + 0, chunk->tag_);
PutLE32(dst + TAG_SIZE, (uint32_t)chunk_size);
assert(chunk_size == (uint32_t)chunk_size);
- memcpy(dst + CHUNK_HEADER_SIZE, chunk->data_.bytes_, chunk_size);
+ memcpy(dst + CHUNK_HEADER_SIZE, chunk->data_.bytes, chunk_size);
if (chunk_size & 1)
dst[CHUNK_HEADER_SIZE + chunk_size] = 0; // Add padding.
return dst + ChunkDiskSize(chunk);
}
uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) {
- while (chunk_list) {
+ while (chunk_list != NULL) {
dst = ChunkEmit(chunk_list, dst);
chunk_list = chunk_list->next_;
}
return dst;
}
-//------------------------------------------------------------------------------
-// Manipulation of a WebPData object.
-
-void WebPDataInit(WebPData* webp_data) {
- if (webp_data != NULL) {
- memset(webp_data, 0, sizeof(*webp_data));
- }
-}
-
-void WebPDataClear(WebPData* webp_data) {
- if (webp_data != NULL) {
- free((void*)webp_data->bytes_);
- WebPDataInit(webp_data);
- }
-}
-
-int WebPDataCopy(const WebPData* src, WebPData* dst) {
- if (src == NULL || dst == NULL) return 0;
-
- WebPDataInit(dst);
- if (src->bytes_ != NULL && src->size_ != 0) {
- dst->bytes_ = (uint8_t*)malloc(src->size_);
- if (dst->bytes_ == NULL) return 0;
- memcpy((void*)dst->bytes_, src->bytes_, src->size_);
- dst->size_ = src->size_;
+size_t ChunkListDiskSize(const WebPChunk* chunk_list) {
+ size_t size = 0;
+ while (chunk_list != NULL) {
+ size += ChunkDiskSize(chunk_list);
+ chunk_list = chunk_list->next_;
}
- return 1;
+ return size;
}
//------------------------------------------------------------------------------
@@ -252,6 +236,7 @@ WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) {
ChunkDelete(wpi->header_);
ChunkDelete(wpi->alpha_);
ChunkDelete(wpi->img_);
+ ChunkListDelete(&wpi->unknown_);
next = wpi->next_;
MuxImageInit(wpi);
@@ -261,14 +246,31 @@ WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) {
//------------------------------------------------------------------------------
// MuxImage search methods.
+// Get a reference to appropriate chunk list within an image given chunk tag.
+static WebPChunk** GetChunkListFromId(const WebPMuxImage* const wpi,
+ WebPChunkId id) {
+ assert(wpi != NULL);
+ switch (id) {
+ case WEBP_CHUNK_ANMF:
+ case WEBP_CHUNK_FRGM: return (WebPChunk**)&wpi->header_;
+ case WEBP_CHUNK_ALPHA: return (WebPChunk**)&wpi->alpha_;
+ case WEBP_CHUNK_IMAGE: return (WebPChunk**)&wpi->img_;
+ default: return NULL;
+ }
+}
+
int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id) {
int count = 0;
const WebPMuxImage* current;
for (current = wpi_list; current != NULL; current = current->next_) {
- const WebPChunk* const wpi_chunk = *MuxImageGetListFromId(current, id);
- if (wpi_chunk != NULL) {
- const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_);
- if (wpi_chunk_id == id) ++count;
+ if (id == WEBP_CHUNK_NIL) {
+ ++count; // Special case: count all images.
+ } else {
+ const WebPChunk* const wpi_chunk = *GetChunkListFromId(current, id);
+ if (wpi_chunk != NULL) {
+ const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_);
+ if (wpi_chunk_id == id) ++count; // Count images with a matching 'id'.
+ }
}
}
return count;
@@ -276,34 +278,22 @@ int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id) {
// Outputs a pointer to 'prev_wpi->next_',
// where 'prev_wpi' is the pointer to the image at position (nth - 1).
-// Returns 1 if nth image with given id was found, 0 otherwise.
+// Returns true if nth image was found.
static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth,
- WebPChunkId id,
WebPMuxImage*** const location) {
uint32_t count = 0;
assert(wpi_list);
*location = wpi_list;
- // Search makes sense only for the following.
- assert(id == WEBP_CHUNK_FRAME || id == WEBP_CHUNK_TILE ||
- id == WEBP_CHUNK_IMAGE);
- assert(id != WEBP_CHUNK_IMAGE || nth == 1);
-
if (nth == 0) {
- nth = MuxImageCount(*wpi_list, id);
+ nth = MuxImageCount(*wpi_list, WEBP_CHUNK_NIL);
if (nth == 0) return 0; // Not found.
}
- while (*wpi_list) {
+ while (*wpi_list != NULL) {
WebPMuxImage* const cur_wpi = *wpi_list;
- const WebPChunk* const wpi_chunk = *MuxImageGetListFromId(cur_wpi, id);
- if (wpi_chunk != NULL) {
- const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_);
- if (wpi_chunk_id == id) {
- ++count;
- if (count == nth) return 1; // Found.
- }
- }
+ ++count;
+ if (count == nth) return 1; // Found.
wpi_list = &cur_wpi->next_;
*location = wpi_list;
}
@@ -322,7 +312,7 @@ WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list) {
wpi_list = &cur_wpi->next_;
}
- new_wpi = (WebPMuxImage*)malloc(sizeof(*new_wpi));
+ new_wpi = (WebPMuxImage*)WebPSafeMalloc(1ULL, sizeof(*new_wpi));
if (new_wpi == NULL) return WEBP_MUX_MEMORY_ERROR;
*new_wpi = *wpi;
new_wpi->next_ = NULL;
@@ -341,20 +331,13 @@ WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list) {
WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi) {
// Delete the components of wpi. If wpi is NULL this is a noop.
WebPMuxImage* const next = MuxImageRelease(wpi);
- free(wpi);
+ WebPSafeFree(wpi);
return next;
}
-void MuxImageDeleteAll(WebPMuxImage** const wpi_list) {
- while (*wpi_list) {
- *wpi_list = MuxImageDelete(*wpi_list);
- }
-}
-
-WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth,
- WebPChunkId id) {
+WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth) {
assert(wpi_list);
- if (!SearchImageToGetOrDelete(wpi_list, nth, id, &wpi_list)) {
+ if (!SearchImageToGetOrDelete(wpi_list, nth, &wpi_list)) {
return WEBP_MUX_NOT_FOUND;
}
*wpi_list = MuxImageDelete(*wpi_list);
@@ -365,10 +348,10 @@ WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth,
// MuxImage reader methods.
WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth,
- WebPChunkId id, WebPMuxImage** wpi) {
+ WebPMuxImage** wpi) {
assert(wpi_list);
assert(wpi);
- if (!SearchImageToGetOrDelete((WebPMuxImage**)wpi_list, nth, id,
+ if (!SearchImageToGetOrDelete((WebPMuxImage**)wpi_list, nth,
(WebPMuxImage***)&wpi_list)) {
return WEBP_MUX_NOT_FOUND;
}
@@ -385,47 +368,48 @@ size_t MuxImageDiskSize(const WebPMuxImage* const wpi) {
if (wpi->header_ != NULL) size += ChunkDiskSize(wpi->header_);
if (wpi->alpha_ != NULL) size += ChunkDiskSize(wpi->alpha_);
if (wpi->img_ != NULL) size += ChunkDiskSize(wpi->img_);
+ if (wpi->unknown_ != NULL) size += ChunkListDiskSize(wpi->unknown_);
return size;
}
-size_t MuxImageListDiskSize(const WebPMuxImage* wpi_list) {
- size_t size = 0;
- while (wpi_list) {
- size += MuxImageDiskSize(wpi_list);
- wpi_list = wpi_list->next_;
+// Special case as ANMF/FRGM chunk encapsulates other image chunks.
+static uint8_t* ChunkEmitSpecial(const WebPChunk* const header,
+ size_t total_size, uint8_t* dst) {
+ const size_t header_size = header->data_.size;
+ const size_t offset_to_next = total_size - CHUNK_HEADER_SIZE;
+ assert(header->tag_ == kChunks[IDX_ANMF].tag ||
+ header->tag_ == kChunks[IDX_FRGM].tag);
+ PutLE32(dst + 0, header->tag_);
+ PutLE32(dst + TAG_SIZE, (uint32_t)offset_to_next);
+ assert(header_size == (uint32_t)header_size);
+ memcpy(dst + CHUNK_HEADER_SIZE, header->data_.bytes, header_size);
+ if (header_size & 1) {
+ dst[CHUNK_HEADER_SIZE + header_size] = 0; // Add padding.
}
- return size;
+ return dst + ChunkDiskSize(header);
}
uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst) {
// Ordering of chunks to be emitted is strictly as follows:
- // 1. Frame/Tile chunk (if present).
- // 2. Alpha chunk (if present).
+ // 1. ANMF/FRGM chunk (if present).
+ // 2. ALPH chunk (if present).
// 3. VP8/VP8L chunk.
assert(wpi);
- if (wpi->header_ != NULL) dst = ChunkEmit(wpi->header_, dst);
+ if (wpi->header_ != NULL) {
+ dst = ChunkEmitSpecial(wpi->header_, MuxImageDiskSize(wpi), dst);
+ }
if (wpi->alpha_ != NULL) dst = ChunkEmit(wpi->alpha_, dst);
if (wpi->img_ != NULL) dst = ChunkEmit(wpi->img_, dst);
- return dst;
-}
-
-uint8_t* MuxImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst) {
- while (wpi_list) {
- dst = MuxImageEmit(wpi_list, dst);
- wpi_list = wpi_list->next_;
- }
+ if (wpi->unknown_ != NULL) dst = ChunkListEmit(wpi->unknown_, dst);
return dst;
}
//------------------------------------------------------------------------------
// Helper methods for mux.
-int MuxHasLosslessImages(const WebPMuxImage* images) {
+int MuxHasAlpha(const WebPMuxImage* images) {
while (images != NULL) {
- assert(images->img_ != NULL);
- if (images->img_->tag_ == kChunks[IDX_VP8L].tag) {
- return 1;
- }
+ if (images->has_alpha_) return 1;
images = images->next_;
}
return 0;
@@ -441,30 +425,13 @@ uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size) {
WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id) {
assert(mux != NULL);
- switch(id) {
+ switch (id) {
case WEBP_CHUNK_VP8X: return (WebPChunk**)&mux->vp8x_;
case WEBP_CHUNK_ICCP: return (WebPChunk**)&mux->iccp_;
- case WEBP_CHUNK_LOOP: return (WebPChunk**)&mux->loop_;
- case WEBP_CHUNK_META: return (WebPChunk**)&mux->meta_;
- case WEBP_CHUNK_UNKNOWN: return (WebPChunk**)&mux->unknown_;
- default: return NULL;
- }
-}
-
-WebPMuxError MuxValidateForImage(const WebPMux* const mux) {
- const int num_images = MuxImageCount(mux->images_, WEBP_CHUNK_IMAGE);
- const int num_frames = MuxImageCount(mux->images_, WEBP_CHUNK_FRAME);
- const int num_tiles = MuxImageCount(mux->images_, WEBP_CHUNK_TILE);
-
- if (num_images == 0) {
- // No images in mux.
- return WEBP_MUX_NOT_FOUND;
- } else if (num_images == 1 && num_frames == 0 && num_tiles == 0) {
- // Valid case (single image).
- return WEBP_MUX_OK;
- } else {
- // Frame/Tile case OR an invalid mux.
- return WEBP_MUX_INVALID_ARGUMENT;
+ case WEBP_CHUNK_ANIM: return (WebPChunk**)&mux->anim_;
+ case WEBP_CHUNK_EXIF: return (WebPChunk**)&mux->exif_;
+ case WEBP_CHUNK_XMP: return (WebPChunk**)&mux->xmp_;
+ default: return (WebPChunk**)&mux->unknown_;
}
}
@@ -480,7 +447,7 @@ static int IsNotCompatible(int feature, int num_items) {
// On success returns WEBP_MUX_OK and stores the chunk count in *num.
static WebPMuxError ValidateChunk(const WebPMux* const mux, CHUNK_INDEX idx,
WebPFeatureFlags feature,
- WebPFeatureFlags vp8x_flags,
+ uint32_t vp8x_flags,
int max, int* num) {
const WebPMuxError err =
WebPMuxNumChunks(mux, kChunks[idx].id, num);
@@ -494,10 +461,11 @@ static WebPMuxError ValidateChunk(const WebPMux* const mux, CHUNK_INDEX idx,
WebPMuxError MuxValidate(const WebPMux* const mux) {
int num_iccp;
- int num_meta;
- int num_loop_chunks;
+ int num_exif;
+ int num_xmp;
+ int num_anim;
int num_frames;
- int num_tiles;
+ int num_fragments;
int num_vp8x;
int num_images;
int num_alpha;
@@ -517,29 +485,33 @@ WebPMuxError MuxValidate(const WebPMux* const mux) {
err = ValidateChunk(mux, IDX_ICCP, ICCP_FLAG, flags, 1, &num_iccp);
if (err != WEBP_MUX_OK) return err;
+ // At most one EXIF metadata.
+ err = ValidateChunk(mux, IDX_EXIF, EXIF_FLAG, flags, 1, &num_exif);
+ if (err != WEBP_MUX_OK) return err;
+
// At most one XMP metadata.
- err = ValidateChunk(mux, IDX_META, META_FLAG, flags, 1, &num_meta);
+ err = ValidateChunk(mux, IDX_XMP, XMP_FLAG, flags, 1, &num_xmp);
if (err != WEBP_MUX_OK) return err;
- // Animation: ANIMATION_FLAG, loop chunk and frame chunk(s) are consistent.
- // At most one loop chunk.
- err = ValidateChunk(mux, IDX_LOOP, NO_FLAG, flags, 1, &num_loop_chunks);
+ // Animation: ANIMATION_FLAG, ANIM chunk and ANMF chunk(s) are consistent.
+ // At most one ANIM chunk.
+ err = ValidateChunk(mux, IDX_ANIM, NO_FLAG, flags, 1, &num_anim);
if (err != WEBP_MUX_OK) return err;
- err = ValidateChunk(mux, IDX_FRAME, NO_FLAG, flags, -1, &num_frames);
+ err = ValidateChunk(mux, IDX_ANMF, NO_FLAG, flags, -1, &num_frames);
if (err != WEBP_MUX_OK) return err;
{
const int has_animation = !!(flags & ANIMATION_FLAG);
- if (has_animation && (num_loop_chunks == 0 || num_frames == 0)) {
+ if (has_animation && (num_anim == 0 || num_frames == 0)) {
return WEBP_MUX_INVALID_ARGUMENT;
}
- if (!has_animation && (num_loop_chunks == 1 || num_frames > 0)) {
+ if (!has_animation && (num_anim == 1 || num_frames > 0)) {
return WEBP_MUX_INVALID_ARGUMENT;
}
}
- // Tiling: TILE_FLAG and tile chunk(s) are consistent.
- err = ValidateChunk(mux, IDX_TILE, TILE_FLAG, flags, -1, &num_tiles);
+ // Fragmentation: FRAGMENTS_FLAG and FRGM chunk(s) are consistent.
+ err = ValidateChunk(mux, IDX_FRGM, FRAGMENTS_FLAG, flags, -1, &num_fragments);
if (err != WEBP_MUX_OK) return err;
// Verify either VP8X chunk is present OR there is only one elem in
@@ -551,16 +523,22 @@ WebPMuxError MuxValidate(const WebPMux* const mux) {
if (num_vp8x == 0 && num_images != 1) return WEBP_MUX_INVALID_ARGUMENT;
// ALPHA_FLAG & alpha chunk(s) are consistent.
- if (num_vp8x > 0 && MuxHasLosslessImages(mux->images_)) {
- // Special case: we have a VP8X chunk as well as some lossless images.
- if (!(flags & ALPHA_FLAG)) return WEBP_MUX_INVALID_ARGUMENT;
- } else {
- err = ValidateChunk(mux, IDX_ALPHA, ALPHA_FLAG, flags, -1, &num_alpha);
- if (err != WEBP_MUX_OK) return err;
+ if (MuxHasAlpha(mux->images_)) {
+ if (num_vp8x > 0) {
+ // VP8X chunk is present, so it should contain ALPHA_FLAG.
+ if (!(flags & ALPHA_FLAG)) return WEBP_MUX_INVALID_ARGUMENT;
+ } else {
+ // VP8X chunk is not present, so ALPH chunks should NOT be present either.
+ err = WebPMuxNumChunks(mux, WEBP_CHUNK_ALPHA, &num_alpha);
+ if (err != WEBP_MUX_OK) return err;
+ if (num_alpha > 0) return WEBP_MUX_INVALID_ARGUMENT;
+ }
+ } else { // Mux doesn't need alpha. So, ALPHA_FLAG should NOT be present.
+ if (flags & ALPHA_FLAG) return WEBP_MUX_INVALID_ARGUMENT;
}
- // num_tiles & num_images are consistent.
- if (num_tiles > 0 && num_images != num_tiles) {
+ // num_fragments & num_images are consistent.
+ if (num_fragments > 0 && num_images != num_fragments) {
return WEBP_MUX_INVALID_ARGUMENT;
}
@@ -571,6 +549,3 @@ WebPMuxError MuxValidate(const WebPMux* const mux) {
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/mux/muxread.c b/drivers/webp/mux/muxread.c
index 21c3cfbaeb..8957a1e46e 100644
--- a/drivers/webp/mux/muxread.c
+++ b/drivers/webp/mux/muxread.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Read APIs for mux.
@@ -12,10 +14,7 @@
#include <assert.h>
#include "./muxi.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+#include "../utils/utils.h"
//------------------------------------------------------------------------------
// Helper method(s).
@@ -41,8 +40,9 @@ static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx,
SWITCH_ID_LIST(IDX_VP8X, mux->vp8x_);
SWITCH_ID_LIST(IDX_ICCP, mux->iccp_);
- SWITCH_ID_LIST(IDX_LOOP, mux->loop_);
- SWITCH_ID_LIST(IDX_META, mux->meta_);
+ SWITCH_ID_LIST(IDX_ANIM, mux->anim_);
+ SWITCH_ID_LIST(IDX_EXIF, mux->exif_);
+ SWITCH_ID_LIST(IDX_XMP, mux->xmp_);
SWITCH_ID_LIST(IDX_UNKNOWN, mux->unknown_);
return WEBP_MUX_NOT_FOUND;
}
@@ -50,15 +50,14 @@ static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx,
// Fill the chunk with the given data (includes chunk header bytes), after some
// verifications.
-static WebPMuxError ChunkVerifyAndAssignData(WebPChunk* chunk,
- const uint8_t* data,
- size_t data_size, size_t riff_size,
- int copy_data) {
+static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk,
+ const uint8_t* data, size_t data_size,
+ size_t riff_size, int copy_data) {
uint32_t chunk_size;
WebPData chunk_data;
// Sanity checks.
- if (data_size < TAG_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA;
+ if (data_size < CHUNK_HEADER_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA;
chunk_size = GetLE32(data + TAG_SIZE);
{
@@ -68,11 +67,103 @@ static WebPMuxError ChunkVerifyAndAssignData(WebPChunk* chunk,
}
// Data assignment.
- chunk_data.bytes_ = data + CHUNK_HEADER_SIZE;
- chunk_data.size_ = chunk_size;
+ chunk_data.bytes = data + CHUNK_HEADER_SIZE;
+ chunk_data.size = chunk_size;
return ChunkAssignData(chunk, &chunk_data, copy_data, GetLE32(data + 0));
}
+int MuxImageFinalize(WebPMuxImage* const wpi) {
+ const WebPChunk* const img = wpi->img_;
+ const WebPData* const image = &img->data_;
+ const int is_lossless = (img->tag_ == kChunks[IDX_VP8L].tag);
+ int w, h;
+ int vp8l_has_alpha = 0;
+ const int ok = is_lossless ?
+ VP8LGetInfo(image->bytes, image->size, &w, &h, &vp8l_has_alpha) :
+ VP8GetInfo(image->bytes, image->size, image->size, &w, &h);
+ assert(img != NULL);
+ if (ok) {
+ // Ignore ALPH chunk accompanying VP8L.
+ if (is_lossless && (wpi->alpha_ != NULL)) {
+ ChunkDelete(wpi->alpha_);
+ wpi->alpha_ = NULL;
+ }
+ wpi->width_ = w;
+ wpi->height_ = h;
+ wpi->has_alpha_ = vp8l_has_alpha || (wpi->alpha_ != NULL);
+ }
+ return ok;
+}
+
+static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
+ WebPMuxImage* const wpi) {
+ const uint8_t* bytes = chunk->data_.bytes;
+ size_t size = chunk->data_.size;
+ const uint8_t* const last = bytes + size;
+ WebPChunk subchunk;
+ size_t subchunk_size;
+ ChunkInit(&subchunk);
+
+ assert(chunk->tag_ == kChunks[IDX_ANMF].tag ||
+ chunk->tag_ == kChunks[IDX_FRGM].tag);
+ assert(!wpi->is_partial_);
+
+ // ANMF/FRGM.
+ {
+ const size_t hdr_size = (chunk->tag_ == kChunks[IDX_ANMF].tag) ?
+ ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE;
+ const WebPData temp = { bytes, hdr_size };
+ // Each of ANMF and FRGM chunk contain a header at the beginning. So, its
+ // size should at least be 'hdr_size'.
+ if (size < hdr_size) goto Fail;
+ ChunkAssignData(&subchunk, &temp, copy_data, chunk->tag_);
+ }
+ ChunkSetNth(&subchunk, &wpi->header_, 1);
+ wpi->is_partial_ = 1; // Waiting for ALPH and/or VP8/VP8L chunks.
+
+ // Rest of the chunks.
+ subchunk_size = ChunkDiskSize(&subchunk) - CHUNK_HEADER_SIZE;
+ bytes += subchunk_size;
+ size -= subchunk_size;
+
+ while (bytes != last) {
+ ChunkInit(&subchunk);
+ if (ChunkVerifyAndAssign(&subchunk, bytes, size, size,
+ copy_data) != WEBP_MUX_OK) {
+ goto Fail;
+ }
+ switch (ChunkGetIdFromTag(subchunk.tag_)) {
+ case WEBP_CHUNK_ALPHA:
+ if (wpi->alpha_ != NULL) goto Fail; // Consecutive ALPH chunks.
+ if (ChunkSetNth(&subchunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Fail;
+ wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
+ break;
+ case WEBP_CHUNK_IMAGE:
+ if (ChunkSetNth(&subchunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Fail;
+ if (!MuxImageFinalize(wpi)) goto Fail;
+ wpi->is_partial_ = 0; // wpi is completely filled.
+ break;
+ case WEBP_CHUNK_UNKNOWN:
+ if (wpi->is_partial_) goto Fail; // Encountered an unknown chunk
+ // before some image chunks.
+ if (ChunkSetNth(&subchunk, &wpi->unknown_, 0) != WEBP_MUX_OK) goto Fail;
+ break;
+ default:
+ goto Fail;
+ break;
+ }
+ subchunk_size = ChunkDiskSize(&subchunk);
+ bytes += subchunk_size;
+ size -= subchunk_size;
+ }
+ if (wpi->is_partial_) goto Fail;
+ return 1;
+
+ Fail:
+ ChunkRelease(&subchunk);
+ return 0;
+}
+
//------------------------------------------------------------------------------
// Create a mux object from WebP-RIFF data.
@@ -94,8 +185,8 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
}
if (bitstream == NULL) return NULL;
- data = bitstream->bytes_;
- size = bitstream->size_;
+ data = bitstream->bytes;
+ size = bitstream->size;
if (data == NULL) return NULL;
if (size < RIFF_HEADER_SIZE) return NULL;
@@ -129,48 +220,55 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
data += RIFF_HEADER_SIZE;
size -= RIFF_HEADER_SIZE;
- wpi = (WebPMuxImage*)malloc(sizeof(*wpi));
+ wpi = (WebPMuxImage*)WebPSafeMalloc(1ULL, sizeof(*wpi));
if (wpi == NULL) goto Err;
MuxImageInit(wpi);
// Loop over chunks.
while (data != end) {
+ size_t data_size;
WebPChunkId id;
- WebPMuxError err;
-
- err = ChunkVerifyAndAssignData(&chunk, data, size, riff_size, copy_data);
- if (err != WEBP_MUX_OK) goto Err;
-
+ WebPChunk** chunk_list;
+ if (ChunkVerifyAndAssign(&chunk, data, size, riff_size,
+ copy_data) != WEBP_MUX_OK) {
+ goto Err;
+ }
+ data_size = ChunkDiskSize(&chunk);
id = ChunkGetIdFromTag(chunk.tag_);
-
- if (IsWPI(id)) { // An image chunk (frame/tile/alpha/vp8).
- WebPChunk** wpi_chunk_ptr =
- MuxImageGetListFromId(wpi, id); // Image chunk to set.
- assert(wpi_chunk_ptr != NULL);
- if (*wpi_chunk_ptr != NULL) goto Err; // Consecutive alpha chunks or
- // consecutive frame/tile chunks.
- if (ChunkSetNth(&chunk, wpi_chunk_ptr, 1) != WEBP_MUX_OK) goto Err;
- if (id == WEBP_CHUNK_IMAGE) {
+ switch (id) {
+ case WEBP_CHUNK_ALPHA:
+ if (wpi->alpha_ != NULL) goto Err; // Consecutive ALPH chunks.
+ if (ChunkSetNth(&chunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Err;
+ wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
+ break;
+ case WEBP_CHUNK_IMAGE:
+ if (ChunkSetNth(&chunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Err;
+ if (!MuxImageFinalize(wpi)) goto Err;
wpi->is_partial_ = 0; // wpi is completely filled.
+ PushImage:
// Add this to mux->images_ list.
if (MuxImagePush(wpi, &mux->images_) != WEBP_MUX_OK) goto Err;
MuxImageInit(wpi); // Reset for reading next image.
- } else {
- wpi->is_partial_ = 1; // wpi is only partially filled.
- }
- } else { // A non-image chunk.
- WebPChunk** chunk_list;
- if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before
- // getting all chunks of an image.
- chunk_list = MuxGetChunkListFromId(mux, id); // List to add this chunk.
- if (chunk_list == NULL) chunk_list = &mux->unknown_;
- if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err;
- }
- {
- const size_t data_size = ChunkDiskSize(&chunk);
- data += data_size;
- size -= data_size;
+ break;
+ case WEBP_CHUNK_ANMF:
+ if (wpi->is_partial_) goto Err; // Previous wpi is still incomplete.
+ if (!MuxImageParse(&chunk, copy_data, wpi)) goto Err;
+ ChunkRelease(&chunk);
+ goto PushImage;
+ break;
+ default: // A non-image chunk.
+ if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before
+ // getting all chunks of an image.
+ chunk_list = MuxGetChunkListFromId(mux, id); // List to add this chunk.
+ if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err;
+ if (id == WEBP_CHUNK_VP8X) { // grab global specs
+ mux->canvas_width_ = GetLE24(data + 12) + 1;
+ mux->canvas_height_ = GetLE24(data + 15) + 1;
+ }
+ break;
}
+ data += data_size;
+ size -= data_size;
ChunkInit(&chunk);
}
@@ -190,31 +288,74 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
//------------------------------------------------------------------------------
// Get API(s).
-WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, uint32_t* flags) {
- WebPData data;
- WebPMuxError err;
+// Validates that the given mux has a single image.
+static WebPMuxError ValidateForSingleImage(const WebPMux* const mux) {
+ const int num_images = MuxImageCount(mux->images_, WEBP_CHUNK_IMAGE);
+ const int num_frames = MuxImageCount(mux->images_, WEBP_CHUNK_ANMF);
+ const int num_fragments = MuxImageCount(mux->images_, WEBP_CHUNK_FRGM);
+
+ if (num_images == 0) {
+ // No images in mux.
+ return WEBP_MUX_NOT_FOUND;
+ } else if (num_images == 1 && num_frames == 0 && num_fragments == 0) {
+ // Valid case (single image).
+ return WEBP_MUX_OK;
+ } else {
+ // Frame/Fragment case OR an invalid mux.
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+}
- if (mux == NULL || flags == NULL) return WEBP_MUX_INVALID_ARGUMENT;
- *flags = 0;
+// Get the canvas width, height and flags after validating that VP8X/VP8/VP8L
+// chunk and canvas size are valid.
+static WebPMuxError MuxGetCanvasInfo(const WebPMux* const mux,
+ int* width, int* height, uint32_t* flags) {
+ int w, h;
+ uint32_t f = 0;
+ WebPData data;
+ assert(mux != NULL);
// Check if VP8X chunk is present.
- err = MuxGet(mux, IDX_VP8X, 1, &data);
- if (err == WEBP_MUX_NOT_FOUND) {
- // Check if VP8/VP8L chunk is present.
- err = WebPMuxGetImage(mux, &data);
- WebPDataClear(&data);
- return err;
- } else if (err != WEBP_MUX_OK) {
- return err;
+ if (MuxGet(mux, IDX_VP8X, 1, &data) == WEBP_MUX_OK) {
+ if (data.size < VP8X_CHUNK_SIZE) return WEBP_MUX_BAD_DATA;
+ f = GetLE32(data.bytes + 0);
+ w = GetLE24(data.bytes + 4) + 1;
+ h = GetLE24(data.bytes + 7) + 1;
+ } else {
+ const WebPMuxImage* const wpi = mux->images_;
+ // Grab user-forced canvas size as default.
+ w = mux->canvas_width_;
+ h = mux->canvas_height_;
+ if (w == 0 && h == 0 && ValidateForSingleImage(mux) == WEBP_MUX_OK) {
+ // single image and not forced canvas size => use dimension of first frame
+ assert(wpi != NULL);
+ w = wpi->width_;
+ h = wpi->height_;
+ }
+ if (wpi != NULL) {
+ if (wpi->has_alpha_) f |= ALPHA_FLAG;
+ }
}
+ if (w * (uint64_t)h >= MAX_IMAGE_AREA) return WEBP_MUX_BAD_DATA;
- if (data.size_ < CHUNK_SIZE_BYTES) return WEBP_MUX_BAD_DATA;
-
- // All OK. Fill up flags.
- *flags = GetLE32(data.bytes_);
+ if (width != NULL) *width = w;
+ if (height != NULL) *height = h;
+ if (flags != NULL) *flags = f;
return WEBP_MUX_OK;
}
+WebPMuxError WebPMuxGetCanvasSize(const WebPMux* mux, int* width, int* height) {
+ if (mux == NULL || width == NULL || height == NULL) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+ return MuxGetCanvasInfo(mux, width, height, NULL);
+}
+
+WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, uint32_t* flags) {
+ if (mux == NULL || flags == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ return MuxGetCanvasInfo(mux, NULL, NULL, flags);
+}
+
static uint8_t* EmitVP8XChunk(uint8_t* const dst, int width,
int height, uint32_t flags) {
const size_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE;
@@ -230,7 +371,7 @@ static uint8_t* EmitVP8XChunk(uint8_t* const dst, int width,
}
// Assemble a single image WebP bitstream from 'wpi'.
-static WebPMuxError SynthesizeBitstream(WebPMuxImage* const wpi,
+static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi,
WebPData* const bitstream) {
uint8_t* dst;
@@ -238,25 +379,17 @@ static WebPMuxError SynthesizeBitstream(WebPMuxImage* const wpi,
const int need_vp8x = (wpi->alpha_ != NULL);
const size_t vp8x_size = need_vp8x ? CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE : 0;
const size_t alpha_size = need_vp8x ? ChunkDiskSize(wpi->alpha_) : 0;
- // Note: No need to output FRM/TILE chunk for a single image.
+ // Note: No need to output ANMF/FRGM chunk for a single image.
const size_t size = RIFF_HEADER_SIZE + vp8x_size + alpha_size +
ChunkDiskSize(wpi->img_);
- uint8_t* const data = (uint8_t*)malloc(size);
+ uint8_t* const data = (uint8_t*)WebPSafeMalloc(1ULL, size);
if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
// Main RIFF header.
dst = MuxEmitRiffHeader(data, size);
if (need_vp8x) {
- int w, h;
- WebPMuxError err;
- assert(wpi->img_ != NULL);
- err = MuxGetImageWidthHeight(wpi->img_, &w, &h);
- if (err != WEBP_MUX_OK) {
- free(data);
- return err;
- }
- dst = EmitVP8XChunk(dst, w, h, ALPHA_FLAG); // VP8X.
+ dst = EmitVP8XChunk(dst, wpi->width_, wpi->height_, ALPHA_FLAG); // VP8X.
dst = ChunkListEmit(wpi->alpha_, dst); // ALPH.
}
@@ -265,107 +398,115 @@ static WebPMuxError SynthesizeBitstream(WebPMuxImage* const wpi,
assert(dst == data + size);
// Output.
- bitstream->bytes_ = data;
- bitstream->size_ = size;
+ bitstream->bytes = data;
+ bitstream->size = size;
return WEBP_MUX_OK;
}
-WebPMuxError WebPMuxGetImage(const WebPMux* mux, WebPData* bitstream) {
- WebPMuxError err;
- WebPMuxImage* wpi = NULL;
-
- if (mux == NULL || bitstream == NULL) {
+WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4],
+ WebPData* chunk_data) {
+ CHUNK_INDEX idx;
+ if (mux == NULL || fourcc == NULL || chunk_data == NULL) {
return WEBP_MUX_INVALID_ARGUMENT;
}
-
- err = MuxValidateForImage(mux);
- if (err != WEBP_MUX_OK) return err;
-
- // All well. Get the image.
- err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, WEBP_CHUNK_IMAGE,
- &wpi);
- assert(err == WEBP_MUX_OK); // Already tested above.
-
- return SynthesizeBitstream(wpi, bitstream);
-}
-
-WebPMuxError WebPMuxGetMetadata(const WebPMux* mux, WebPData* metadata) {
- if (mux == NULL || metadata == NULL) return WEBP_MUX_INVALID_ARGUMENT;
- return MuxGet(mux, IDX_META, 1, metadata);
+ idx = ChunkGetIndexFromFourCC(fourcc);
+ if (IsWPI(kChunks[idx].id)) { // An image chunk.
+ return WEBP_MUX_INVALID_ARGUMENT;
+ } else if (idx != IDX_UNKNOWN) { // A known chunk type.
+ return MuxGet(mux, idx, 1, chunk_data);
+ } else { // An unknown chunk type.
+ const WebPChunk* const chunk =
+ ChunkSearchList(mux->unknown_, 1, ChunkGetTagFromFourCC(fourcc));
+ if (chunk == NULL) return WEBP_MUX_NOT_FOUND;
+ *chunk_data = chunk->data_;
+ return WEBP_MUX_OK;
+ }
}
-WebPMuxError WebPMuxGetColorProfile(const WebPMux* mux,
- WebPData* color_profile) {
- if (mux == NULL || color_profile == NULL) return WEBP_MUX_INVALID_ARGUMENT;
- return MuxGet(mux, IDX_ICCP, 1, color_profile);
+static WebPMuxError MuxGetImageInternal(const WebPMuxImage* const wpi,
+ WebPMuxFrameInfo* const info) {
+ // Set some defaults for unrelated fields.
+ info->x_offset = 0;
+ info->y_offset = 0;
+ info->duration = 1;
+ info->dispose_method = WEBP_MUX_DISPOSE_NONE;
+ info->blend_method = WEBP_MUX_BLEND;
+ // Extract data for related fields.
+ info->id = ChunkGetIdFromTag(wpi->img_->tag_);
+ return SynthesizeBitstream(wpi, &info->bitstream);
}
-WebPMuxError WebPMuxGetLoopCount(const WebPMux* mux, int* loop_count) {
- WebPData image;
- WebPMuxError err;
-
- if (mux == NULL || loop_count == NULL) return WEBP_MUX_INVALID_ARGUMENT;
-
- err = MuxGet(mux, IDX_LOOP, 1, &image);
- if (err != WEBP_MUX_OK) return err;
- if (image.size_ < kChunks[WEBP_CHUNK_LOOP].size) return WEBP_MUX_BAD_DATA;
- *loop_count = GetLE16(image.bytes_);
-
- return WEBP_MUX_OK;
+static WebPMuxError MuxGetFrameFragmentInternal(const WebPMuxImage* const wpi,
+ WebPMuxFrameInfo* const frame) {
+ const int is_frame = (wpi->header_->tag_ == kChunks[IDX_ANMF].tag);
+ const CHUNK_INDEX idx = is_frame ? IDX_ANMF : IDX_FRGM;
+ const WebPData* frame_frgm_data;
+ if (!is_frame) return WEBP_MUX_INVALID_ARGUMENT;
+ assert(wpi->header_ != NULL); // Already checked by WebPMuxGetFrame().
+ // Get frame/fragment chunk.
+ frame_frgm_data = &wpi->header_->data_;
+ if (frame_frgm_data->size < kChunks[idx].size) return WEBP_MUX_BAD_DATA;
+ // Extract info.
+ frame->x_offset = 2 * GetLE24(frame_frgm_data->bytes + 0);
+ frame->y_offset = 2 * GetLE24(frame_frgm_data->bytes + 3);
+ if (is_frame) {
+ const uint8_t bits = frame_frgm_data->bytes[15];
+ frame->duration = GetLE24(frame_frgm_data->bytes + 12);
+ frame->dispose_method =
+ (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE;
+ frame->blend_method = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND;
+ } else { // Defaults for unused values.
+ frame->duration = 1;
+ frame->dispose_method = WEBP_MUX_DISPOSE_NONE;
+ frame->blend_method = WEBP_MUX_BLEND;
+ }
+ frame->id = ChunkGetIdFromTag(wpi->header_->tag_);
+ return SynthesizeBitstream(wpi, &frame->bitstream);
}
-static WebPMuxError MuxGetFrameTileInternal(
- const WebPMux* const mux, uint32_t nth, WebPData* const bitstream,
- int* const x_offset, int* const y_offset, int* const duration,
- uint32_t tag) {
- const WebPData* frame_tile_data;
+WebPMuxError WebPMuxGetFrame(
+ const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame) {
WebPMuxError err;
WebPMuxImage* wpi;
- const int is_frame = (tag == kChunks[WEBP_CHUNK_FRAME].tag) ? 1 : 0;
- const CHUNK_INDEX idx = is_frame ? IDX_FRAME : IDX_TILE;
- const WebPChunkId id = kChunks[idx].id;
-
- if (mux == NULL || bitstream == NULL ||
- x_offset == NULL || y_offset == NULL || (is_frame && duration == NULL)) {
+ // Sanity checks.
+ if (mux == NULL || frame == NULL) {
return WEBP_MUX_INVALID_ARGUMENT;
}
// Get the nth WebPMuxImage.
- err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, id, &wpi);
+ err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, &wpi);
if (err != WEBP_MUX_OK) return err;
- // Get frame chunk.
- assert(wpi->header_ != NULL); // As MuxImageGetNth() already checked header_.
- frame_tile_data = &wpi->header_->data_;
+ // Get frame info.
+ if (wpi->header_ == NULL) {
+ return MuxGetImageInternal(wpi, frame);
+ } else {
+ return MuxGetFrameFragmentInternal(wpi, frame);
+ }
+}
- if (frame_tile_data->size_ < kChunks[idx].size) return WEBP_MUX_BAD_DATA;
- *x_offset = 2 * GetLE24(frame_tile_data->bytes_ + 0);
- *y_offset = 2 * GetLE24(frame_tile_data->bytes_ + 3);
- if (is_frame) *duration = 1 + GetLE24(frame_tile_data->bytes_ + 12);
+WebPMuxError WebPMuxGetAnimationParams(const WebPMux* mux,
+ WebPMuxAnimParams* params) {
+ WebPData anim;
+ WebPMuxError err;
- return SynthesizeBitstream(wpi, bitstream);
-}
+ if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT;
-WebPMuxError WebPMuxGetFrame(const WebPMux* mux, uint32_t nth,
- WebPData* bitstream,
- int* x_offset, int* y_offset, int* duration) {
- return MuxGetFrameTileInternal(mux, nth, bitstream, x_offset, y_offset,
- duration, kChunks[IDX_FRAME].tag);
-}
+ err = MuxGet(mux, IDX_ANIM, 1, &anim);
+ if (err != WEBP_MUX_OK) return err;
+ if (anim.size < kChunks[WEBP_CHUNK_ANIM].size) return WEBP_MUX_BAD_DATA;
+ params->bgcolor = GetLE32(anim.bytes);
+ params->loop_count = GetLE16(anim.bytes + 4);
-WebPMuxError WebPMuxGetTile(const WebPMux* mux, uint32_t nth,
- WebPData* bitstream,
- int* x_offset, int* y_offset) {
- return MuxGetFrameTileInternal(mux, nth, bitstream, x_offset, y_offset, NULL,
- kChunks[IDX_TILE].tag);
+ return WEBP_MUX_OK;
}
// Get chunk index from chunk id. Returns IDX_NIL if not found.
static CHUNK_INDEX ChunkGetIndexFromId(WebPChunkId id) {
int i;
for (i = 0; kChunks[i].id != WEBP_CHUNK_NIL; ++i) {
- if (id == kChunks[i].id) return i;
+ if (id == kChunks[i].id) return (CHUNK_INDEX)i;
}
return IDX_NIL;
}
@@ -393,19 +534,11 @@ WebPMuxError WebPMuxNumChunks(const WebPMux* mux,
*num_elements = MuxImageCount(mux->images_, id);
} else {
WebPChunk* const* chunk_list = MuxGetChunkListFromId(mux, id);
- if (chunk_list == NULL) {
- *num_elements = 0;
- } else {
- const CHUNK_INDEX idx = ChunkGetIndexFromId(id);
- *num_elements = CountChunks(*chunk_list, kChunks[idx].tag);
- }
+ const CHUNK_INDEX idx = ChunkGetIndexFromId(id);
+ *num_elements = CountChunks(*chunk_list, kChunks[idx].tag);
}
return WEBP_MUX_OK;
}
//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/mux_types.h b/drivers/webp/mux_types.h
new file mode 100644
index 0000000000..c94043a3c0
--- /dev/null
+++ b/drivers/webp/mux_types.h
@@ -0,0 +1,97 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Data-types common to the mux and demux libraries.
+//
+// Author: Urvang (urvang@google.com)
+
+#ifndef WEBP_WEBP_MUX_TYPES_H_
+#define WEBP_WEBP_MUX_TYPES_H_
+
+#include <stdlib.h> // free()
+#include <string.h> // memset()
+#include "./types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Note: forward declaring enumerations is not allowed in (strict) C and C++,
+// the types are left here for reference.
+// typedef enum WebPFeatureFlags WebPFeatureFlags;
+// typedef enum WebPMuxAnimDispose WebPMuxAnimDispose;
+// typedef enum WebPMuxAnimBlend WebPMuxAnimBlend;
+typedef struct WebPData WebPData;
+
+// VP8X Feature Flags.
+typedef enum WebPFeatureFlags {
+ FRAGMENTS_FLAG = 0x00000001,
+ ANIMATION_FLAG = 0x00000002,
+ XMP_FLAG = 0x00000004,
+ EXIF_FLAG = 0x00000008,
+ ALPHA_FLAG = 0x00000010,
+ ICCP_FLAG = 0x00000020
+} WebPFeatureFlags;
+
+// Dispose method (animation only). Indicates how the area used by the current
+// frame is to be treated before rendering the next frame on the canvas.
+typedef enum WebPMuxAnimDispose {
+ WEBP_MUX_DISPOSE_NONE, // Do not dispose.
+ WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color.
+} WebPMuxAnimDispose;
+
+// Blend operation (animation only). Indicates how transparent pixels of the
+// current frame are blended with those of the previous canvas.
+typedef enum WebPMuxAnimBlend {
+ WEBP_MUX_BLEND, // Blend.
+ WEBP_MUX_NO_BLEND // Do not blend.
+} WebPMuxAnimBlend;
+
+// Data type used to describe 'raw' data, e.g., chunk data
+// (ICC profile, metadata) and WebP compressed image data.
+struct WebPData {
+ const uint8_t* bytes;
+ size_t size;
+};
+
+// Initializes the contents of the 'webp_data' object with default values.
+static WEBP_INLINE void WebPDataInit(WebPData* webp_data) {
+ if (webp_data != NULL) {
+ memset(webp_data, 0, sizeof(*webp_data));
+ }
+}
+
+// Clears the contents of the 'webp_data' object by calling free(). Does not
+// deallocate the object itself.
+static WEBP_INLINE void WebPDataClear(WebPData* webp_data) {
+ if (webp_data != NULL) {
+ free((void*)webp_data->bytes);
+ WebPDataInit(webp_data);
+ }
+}
+
+// Allocates necessary storage for 'dst' and copies the contents of 'src'.
+// Returns true on success.
+static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) {
+ if (src == NULL || dst == NULL) return 0;
+ WebPDataInit(dst);
+ if (src->bytes != NULL && src->size != 0) {
+ dst->bytes = (uint8_t*)malloc(src->size);
+ if (dst->bytes == NULL) return 0;
+ memcpy((void*)dst->bytes, src->bytes, src->size);
+ dst->size = src->size;
+ }
+ return 1;
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_WEBP_MUX_TYPES_H_ */
diff --git a/drivers/webp/types.h b/drivers/webp/types.h
index 3e27190bef..98fff35a11 100644
--- a/drivers/webp/types.h
+++ b/drivers/webp/types.h
@@ -1,8 +1,10 @@
// Copyright 2010 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Common types
@@ -16,10 +18,11 @@
#ifndef _MSC_VER
#include <inttypes.h>
-#ifdef __STRICT_ANSI__
-#define WEBP_INLINE
-#else /* __STRICT_ANSI__ */
+#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \
+ (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
#define WEBP_INLINE inline
+#else
+#define WEBP_INLINE
#endif
#else
typedef signed char int8_t;
@@ -36,7 +39,11 @@ typedef long long int int64_t;
#ifndef WEBP_EXTERN
// This explicitly marks library functions and allows for changing the
// signature for e.g., Windows DLL builds.
-#define WEBP_EXTERN(type) extern type
+# if defined(__GNUC__) && __GNUC__ >= 4
+# define WEBP_EXTERN(type) extern __attribute__ ((visibility ("default"))) type
+# else
+# define WEBP_EXTERN(type) extern type
+# endif /* __GNUC__ >= 4 */
#endif /* WEBP_EXTERN */
// Macro to check ABI compatibility (same major revision number)
diff --git a/drivers/webp/utils/bit_reader.c b/drivers/webp/utils/bit_reader.c
index 1afb1db890..4d6b4f0164 100644
--- a/drivers/webp/utils/bit_reader.c
+++ b/drivers/webp/utils/bit_reader.c
@@ -1,36 +1,62 @@
// Copyright 2010 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
-// Boolean decoder
+// Boolean decoder non-inlined methods
//
// Author: Skal (pascal.massimino@gmail.com)
-#include "./bit_reader.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
+#ifdef HAVE_CONFIG_H
+#include "webp/config.h"
#endif
-#define MK(X) (((bit_t)(X) << (BITS)) | (MASK))
+#include "./bit_reader_inl.h"
+
+#define JAVASCRIPT_ENABLED // testing
//------------------------------------------------------------------------------
// VP8BitReader
+void VP8BitReaderSetBuffer(VP8BitReader* const br,
+ const uint8_t* const start,
+ size_t size) {
+ br->buf_ = start;
+ br->buf_end_ = start + size;
+ br->buf_max_ =
+ (size >= sizeof(lbit_t)) ? start + size - sizeof(lbit_t) + 1
+ : start;
+}
+
void VP8InitBitReader(VP8BitReader* const br,
- const uint8_t* const start, const uint8_t* const end) {
+ const uint8_t* const start, size_t size) {
assert(br != NULL);
assert(start != NULL);
- assert(start <= end);
- br->range_ = MK(255 - 1);
- br->buf_ = start;
- br->buf_end_ = end;
+ assert(size < (1u << 31)); // limit ensured by format and upstream checks
+ br->range_ = 255 - 1;
br->value_ = 0;
- br->missing_ = 8; // to load the very first 8bits
+ br->bits_ = -8; // to load the very first 8bits
br->eof_ = 0;
+ VP8BitReaderSetBuffer(br, start, size);
+
+#ifdef JAVASCRIPT_ENABLED // html5 required aligned reads
+ while(((uintptr_t)br->buf_ & 1) != 0 && !br->eof_)
+ VP8LoadFinalBytes(br);
+#else
+ VP8LoadNewBytes(br);
+#endif
+}
+
+void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) {
+ if (br->buf_ != NULL) {
+ br->buf_ += offset;
+ br->buf_end_ += offset;
+ br->buf_max_ += offset;
+ }
}
const uint8_t kVP8Log2Range[128] = {
@@ -45,36 +71,38 @@ const uint8_t kVP8Log2Range[128] = {
0
};
-// range = (range << kVP8Log2Range[range]) + trailing 1's
-const bit_t kVP8NewRange[128] = {
- MK(127), MK(127), MK(191), MK(127), MK(159), MK(191), MK(223), MK(127),
- MK(143), MK(159), MK(175), MK(191), MK(207), MK(223), MK(239), MK(127),
- MK(135), MK(143), MK(151), MK(159), MK(167), MK(175), MK(183), MK(191),
- MK(199), MK(207), MK(215), MK(223), MK(231), MK(239), MK(247), MK(127),
- MK(131), MK(135), MK(139), MK(143), MK(147), MK(151), MK(155), MK(159),
- MK(163), MK(167), MK(171), MK(175), MK(179), MK(183), MK(187), MK(191),
- MK(195), MK(199), MK(203), MK(207), MK(211), MK(215), MK(219), MK(223),
- MK(227), MK(231), MK(235), MK(239), MK(243), MK(247), MK(251), MK(127),
- MK(129), MK(131), MK(133), MK(135), MK(137), MK(139), MK(141), MK(143),
- MK(145), MK(147), MK(149), MK(151), MK(153), MK(155), MK(157), MK(159),
- MK(161), MK(163), MK(165), MK(167), MK(169), MK(171), MK(173), MK(175),
- MK(177), MK(179), MK(181), MK(183), MK(185), MK(187), MK(189), MK(191),
- MK(193), MK(195), MK(197), MK(199), MK(201), MK(203), MK(205), MK(207),
- MK(209), MK(211), MK(213), MK(215), MK(217), MK(219), MK(221), MK(223),
- MK(225), MK(227), MK(229), MK(231), MK(233), MK(235), MK(237), MK(239),
- MK(241), MK(243), MK(245), MK(247), MK(249), MK(251), MK(253), MK(127)
+// range = ((range - 1) << kVP8Log2Range[range]) + 1
+const uint8_t kVP8NewRange[128] = {
+ 127, 127, 191, 127, 159, 191, 223, 127,
+ 143, 159, 175, 191, 207, 223, 239, 127,
+ 135, 143, 151, 159, 167, 175, 183, 191,
+ 199, 207, 215, 223, 231, 239, 247, 127,
+ 131, 135, 139, 143, 147, 151, 155, 159,
+ 163, 167, 171, 175, 179, 183, 187, 191,
+ 195, 199, 203, 207, 211, 215, 219, 223,
+ 227, 231, 235, 239, 243, 247, 251, 127,
+ 129, 131, 133, 135, 137, 139, 141, 143,
+ 145, 147, 149, 151, 153, 155, 157, 159,
+ 161, 163, 165, 167, 169, 171, 173, 175,
+ 177, 179, 181, 183, 185, 187, 189, 191,
+ 193, 195, 197, 199, 201, 203, 205, 207,
+ 209, 211, 213, 215, 217, 219, 221, 223,
+ 225, 227, 229, 231, 233, 235, 237, 239,
+ 241, 243, 245, 247, 249, 251, 253, 127
};
-#undef MK
-
void VP8LoadFinalBytes(VP8BitReader* const br) {
assert(br != NULL && br->buf_ != NULL);
// Only read 8bits at a time
if (br->buf_ < br->buf_end_) {
- br->value_ |= (bit_t)(*br->buf_++) << ((BITS) - 8 + br->missing_);
- br->missing_ -= 8;
- } else {
+ br->bits_ += 8;
+ br->value_ = (bit_t)(*br->buf_++) | (br->value_ << 8);
+ } else if (!br->eof_) {
+ br->value_ <<= 8;
+ br->bits_ += 8;
br->eof_ = 1;
+ } else {
+ br->bits_ = 0; // This is to avoid undefined behaviour with shifts.
}
}
@@ -97,32 +125,47 @@ int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) {
//------------------------------------------------------------------------------
// VP8LBitReader
-#define MAX_NUM_BIT_READ 25
+#define VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits.
+
+#if !defined(WEBP_FORCE_ALIGNED) && \
+ (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \
+ defined(__i386__) || defined(_M_IX86) || \
+ defined(__x86_64__) || defined(_M_X64))
+#define VP8L_USE_UNALIGNED_LOAD
+#endif
-static const uint32_t kBitMask[MAX_NUM_BIT_READ] = {
- 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767,
- 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215
+static const uint32_t kBitMask[VP8L_MAX_NUM_BIT_READ + 1] = {
+ 0,
+ 0x000001, 0x000003, 0x000007, 0x00000f,
+ 0x00001f, 0x00003f, 0x00007f, 0x0000ff,
+ 0x0001ff, 0x0003ff, 0x0007ff, 0x000fff,
+ 0x001fff, 0x003fff, 0x007fff, 0x00ffff,
+ 0x01ffff, 0x03ffff, 0x07ffff, 0x0fffff,
+ 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff
};
-void VP8LInitBitReader(VP8LBitReader* const br,
- const uint8_t* const start,
+void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const start,
size_t length) {
size_t i;
+ vp8l_val_t value = 0;
assert(br != NULL);
assert(start != NULL);
assert(length < 0xfffffff8u); // can't happen with a RIFF chunk.
- br->buf_ = start;
br->len_ = length;
br->val_ = 0;
- br->pos_ = 0;
br->bit_pos_ = 0;
br->eos_ = 0;
- br->error_ = 0;
- for (i = 0; i < sizeof(br->val_) && i < br->len_; ++i) {
- br->val_ |= ((uint64_t)br->buf_[br->pos_]) << (8 * i);
- ++br->pos_;
+
+ if (length > sizeof(br->val_)) {
+ length = sizeof(br->val_);
+ }
+ for (i = 0; i < length; ++i) {
+ value |= (vp8l_val_t)start[i] << (8 * i);
}
+ br->val_ = value;
+ br->pos_ = length;
+ br->buf_ = start;
}
void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
@@ -130,100 +173,62 @@ void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
assert(br != NULL);
assert(buf != NULL);
assert(len < 0xfffffff8u); // can't happen with a RIFF chunk.
- br->eos_ = (br->pos_ >= len);
br->buf_ = buf;
br->len_ = len;
+ // pos_ > len_ should be considered a param error.
+ br->eos_ = (br->pos_ > br->len_) || VP8LIsEndOfStream(br);
}
+static void VP8LSetEndOfStream(VP8LBitReader* const br) {
+ br->eos_ = 1;
+ br->bit_pos_ = 0; // To avoid undefined behaviour with shifts.
+}
+
+// If not at EOS, reload up to VP8L_LBITS byte-by-byte
static void ShiftBytes(VP8LBitReader* const br) {
while (br->bit_pos_ >= 8 && br->pos_ < br->len_) {
br->val_ >>= 8;
- br->val_ |= ((uint64_t)br->buf_[br->pos_]) << 56;
+ br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8);
++br->pos_;
br->bit_pos_ -= 8;
}
-}
-
-void VP8LFillBitWindow(VP8LBitReader* const br) {
- if (br->bit_pos_ >= 32) {
-#if defined(__x86_64__) || defined(_M_X64)
- if (br->pos_ + 8 < br->len_) {
- br->val_ >>= 32;
- // The expression below needs a little-endian arch to work correctly.
- // This gives a large speedup for decoding speed.
- br->val_ |= *(const uint64_t *)(br->buf_ + br->pos_) << 32;
- br->pos_ += 4;
- br->bit_pos_ -= 32;
- } else {
- // Slow path.
- ShiftBytes(br);
- }
-#else
- // Always the slow path.
- ShiftBytes(br);
-#endif
- }
- if (br->pos_ == br->len_ && br->bit_pos_ == 64) {
- br->eos_ = 1;
+ if (VP8LIsEndOfStream(br)) {
+ VP8LSetEndOfStream(br);
}
}
-uint32_t VP8LReadOneBit(VP8LBitReader* const br) {
- const uint32_t val = (br->val_ >> br->bit_pos_) & 1;
- // Flag an error at end_of_stream.
- if (!br->eos_) {
- ++br->bit_pos_;
- if (br->bit_pos_ >= 32) {
- ShiftBytes(br);
- }
- // After this last bit is read, check if eos needs to be flagged.
- if (br->pos_ == br->len_ && br->bit_pos_ == 64) {
- br->eos_ = 1;
- }
- } else {
- br->error_ = 1;
+void VP8LDoFillBitWindow(VP8LBitReader* const br) {
+ assert(br->bit_pos_ >= VP8L_WBITS);
+ // TODO(jzern): given the fixed read size it may be possible to force
+ // alignment in this block.
+#if defined(VP8L_USE_UNALIGNED_LOAD)
+ if (br->pos_ + sizeof(br->val_) < br->len_) {
+ br->val_ >>= VP8L_WBITS;
+ br->bit_pos_ -= VP8L_WBITS;
+ // The expression below needs a little-endian arch to work correctly.
+ // This gives a large speedup for decoding speed.
+ br->val_ |= (vp8l_val_t)*(const uint32_t*)(br->buf_ + br->pos_) <<
+ (VP8L_LBITS - VP8L_WBITS);
+ br->pos_ += VP8L_LOG8_WBITS;
+ return;
}
- return val;
+#endif
+ ShiftBytes(br); // Slow path.
}
uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) {
- uint32_t val = 0;
assert(n_bits >= 0);
// Flag an error if end_of_stream or n_bits is more than allowed limit.
- if (!br->eos_ && n_bits < MAX_NUM_BIT_READ) {
- // If this read is going to cross the read buffer, set the eos flag.
- if (br->pos_ == br->len_) {
- if ((br->bit_pos_ + n_bits) >= 64) {
- br->eos_ = 1;
- if ((br->bit_pos_ + n_bits) > 64) return val;
- }
- }
- val = (br->val_ >> br->bit_pos_) & kBitMask[n_bits];
- br->bit_pos_ += n_bits;
- if (br->bit_pos_ >= 40) {
- if (br->pos_ + 5 < br->len_) {
- br->val_ >>= 40;
- br->val_ |=
- (((uint64_t)br->buf_[br->pos_ + 0]) << 24) |
- (((uint64_t)br->buf_[br->pos_ + 1]) << 32) |
- (((uint64_t)br->buf_[br->pos_ + 2]) << 40) |
- (((uint64_t)br->buf_[br->pos_ + 3]) << 48) |
- (((uint64_t)br->buf_[br->pos_ + 4]) << 56);
- br->pos_ += 5;
- br->bit_pos_ -= 40;
- }
- if (br->bit_pos_ >= 8) {
- ShiftBytes(br);
- }
- }
+ if (!br->eos_ && n_bits <= VP8L_MAX_NUM_BIT_READ) {
+ const uint32_t val = VP8LPrefetchBits(br) & kBitMask[n_bits];
+ const int new_bits = br->bit_pos_ + n_bits;
+ br->bit_pos_ = new_bits;
+ ShiftBytes(br);
+ return val;
} else {
- br->error_ = 1;
+ VP8LSetEndOfStream(br);
+ return 0;
}
- return val;
}
//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/utils/bit_reader.h b/drivers/webp/utils/bit_reader.h
index 43cd948fd4..f0f450231d 100644
--- a/drivers/webp/utils/bit_reader.h
+++ b/drivers/webp/utils/bit_reader.h
@@ -1,9 +1,10 @@
-//
// Copyright 2010 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Boolean decoder
@@ -18,44 +19,83 @@
#ifdef _MSC_VER
#include <stdlib.h> // _byteswap_ulong
#endif
-#include <string.h> // For memcpy
-#include "../types.h"
+#include "webp/types.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
-#define BITS 32 // can be 32, 16 or 8
-#define MASK ((((bit_t)1) << (BITS)) - 1)
-#if (BITS == 32)
-typedef uint64_t bit_t; // natural register type
-typedef uint32_t lbit_t; // natural type for memory I/O
-#elif (BITS == 16)
-typedef uint32_t bit_t;
-typedef uint16_t lbit_t;
+// The Boolean decoder needs to maintain infinite precision on the value_ field.
+// However, since range_ is only 8bit, we only need an active window of 8 bits
+// for value_. Left bits (MSB) gets zeroed and shifted away when value_ falls
+// below 128, range_ is updated, and fresh bits read from the bitstream are
+// brought in as LSB. To avoid reading the fresh bits one by one (slow), we
+// cache BITS of them ahead. The total of (BITS + 8) bits must fit into a
+// natural register (with type bit_t). To fetch BITS bits from bitstream we
+// use a type lbit_t.
+//
+// BITS can be any multiple of 8 from 8 to 56 (inclusive).
+// Pick values that fit natural register size.
+
+#ifdef JAVASCRIPT_ENABLED
+
+#define BITS 16
+
+#else
+
+#if defined(__i386__) || defined(_M_IX86) // x86 32bit
+#define BITS 24
+#elif defined(__x86_64__) || defined(_M_X64) // x86 64bit
+#define BITS 56
+#elif defined(__arm__) || defined(_M_ARM) // ARM
+#define BITS 24
+#elif defined(__mips__) // MIPS
+#define BITS 24
+#else // reasonable default
+#define BITS 24 // TODO(skal): test aarch64 and find the proper BITS value.
+#endif
+
+#endif
+
+//------------------------------------------------------------------------------
+// Derived types and constants:
+// bit_t = natural register type for storing 'value_' (which is BITS+8 bits)
+// range_t = register for 'range_' (which is 8bits only)
+
+#if (BITS > 24)
+typedef uint64_t bit_t;
#else
typedef uint32_t bit_t;
-typedef uint8_t lbit_t;
#endif
+typedef uint32_t range_t;
+
//------------------------------------------------------------------------------
-// Bitreader and code-tree reader
+// Bitreader
typedef struct VP8BitReader VP8BitReader;
struct VP8BitReader {
+ // boolean decoder (keep the field ordering as is!)
+ bit_t value_; // current value
+ range_t range_; // current range minus 1. In [127, 254] interval.
+ int bits_; // number of valid bits left
+ // read buffer
const uint8_t* buf_; // next byte to be read
const uint8_t* buf_end_; // end of read buffer
+ const uint8_t* buf_max_; // max packed-read position on buffer
int eof_; // true if input is exhausted
-
- // boolean decoder
- bit_t range_; // current range minus 1. In [127, 254] interval.
- bit_t value_; // current value
- int missing_; // number of missing bits in value_ (8bit)
};
// Initialize the bit reader and the boolean decoder.
void VP8InitBitReader(VP8BitReader* const br,
- const uint8_t* const start, const uint8_t* const end);
+ const uint8_t* const start, size_t size);
+// Sets the working read buffer.
+void VP8BitReaderSetBuffer(VP8BitReader* const br,
+ const uint8_t* const start, size_t size);
+
+// Update internal pointers to displace the byte buffer by the
+// relative offset 'offset'.
+void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset);
// return the next value made of 'num_bits' bits
uint32_t VP8GetValue(VP8BitReader* const br, int num_bits);
@@ -66,100 +106,31 @@ static WEBP_INLINE uint32_t VP8Get(VP8BitReader* const br) {
// return the next value with sign-extension.
int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits);
-// Read a bit with proba 'prob'. Speed-critical function!
-extern const uint8_t kVP8Log2Range[128];
-extern const bit_t kVP8NewRange[128];
-
-void VP8LoadFinalBytes(VP8BitReader* const br); // special case for the tail
-
-static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) {
- assert(br && br->buf_);
- // Read 'BITS' bits at a time if possible.
- if (br->buf_ + sizeof(lbit_t) <= br->buf_end_) {
- // convert memory type to register type (with some zero'ing!)
- bit_t bits;
- lbit_t in_bits = *(lbit_t*)br->buf_;
- br->buf_ += (BITS) >> 3;
-#if !defined(__BIG_ENDIAN__)
-#if (BITS == 32)
-#if defined(__i386__) || defined(__x86_64__)
- __asm__ volatile("bswap %k0" : "=r"(in_bits) : "0"(in_bits));
- bits = (bit_t)in_bits; // 32b -> 64b zero-extension
-#elif defined(_MSC_VER)
- bits = _byteswap_ulong(in_bits);
-#else
- bits = (bit_t)(in_bits >> 24) | ((in_bits >> 8) & 0xff00)
- | ((in_bits << 8) & 0xff0000) | (in_bits << 24);
-#endif // x86
-#elif (BITS == 16)
- // gcc will recognize a 'rorw $8, ...' here:
- bits = (bit_t)(in_bits >> 8) | ((in_bits & 0xff) << 8);
-#endif
-#else // LITTLE_ENDIAN
- bits = (bit_t)in_bits;
-#endif
- br->value_ |= bits << br->missing_;
- br->missing_ -= (BITS);
- } else {
- VP8LoadFinalBytes(br); // no need to be inlined
- }
-}
+// bit_reader_inl.h will implement the following methods:
+// static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob)
+// static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v)
+// and should be included by the .c files that actually need them.
+// This is to avoid recompiling the whole library whenever this file is touched,
+// and also allowing platform-specific ad-hoc hacks.
-static WEBP_INLINE int VP8BitUpdate(VP8BitReader* const br, bit_t split) {
- const bit_t value_split = split | (MASK);
- if (br->missing_ > 0) { // Make sure we have a least BITS bits in 'value_'
- VP8LoadNewBytes(br);
- }
- if (br->value_ > value_split) {
- br->range_ -= value_split + 1;
- br->value_ -= value_split + 1;
- return 1;
- } else {
- br->range_ = value_split;
- return 0;
- }
-}
-
-static WEBP_INLINE void VP8Shift(VP8BitReader* const br) {
- // range_ is in [0..127] interval here.
- const int idx = br->range_ >> (BITS);
- const int shift = kVP8Log2Range[idx];
- br->range_ = kVP8NewRange[idx];
- br->value_ <<= shift;
- br->missing_ += shift;
-}
-
-static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) {
- // It's important to avoid generating a 64bit x 64bit multiply here.
- // We just need an 8b x 8b after all.
- const bit_t split =
- (bit_t)((uint32_t)(br->range_ >> (BITS)) * prob) << ((BITS) - 8);
- const int bit = VP8BitUpdate(br, split);
- if (br->range_ <= (((bit_t)0x7e << (BITS)) | (MASK))) {
- VP8Shift(br);
- }
- return bit;
-}
+// -----------------------------------------------------------------------------
+// Bitreader for lossless format
-static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) {
- const bit_t split = (br->range_ >> 1);
- const int bit = VP8BitUpdate(br, split);
- VP8Shift(br);
- return bit ? -v : v;
-}
+// maximum number of bits (inclusive) the bit-reader can handle:
+#define VP8L_MAX_NUM_BIT_READ 24
+#define VP8L_LBITS 64 // Number of bits prefetched (= bit-size of vp8l_val_t).
+#define VP8L_WBITS 32 // Minimum number of bytes ready after VP8LFillBitWindow.
-// -----------------------------------------------------------------------------
-// Bitreader
+typedef uint64_t vp8l_val_t; // right now, this bit-reader can only use 64bit.
typedef struct {
- uint64_t val_;
- const uint8_t* buf_;
- size_t len_;
- size_t pos_;
- int bit_pos_;
- int eos_;
- int error_;
+ vp8l_val_t val_; // pre-fetched bits
+ const uint8_t* buf_; // input byte buffer
+ size_t len_; // buffer length
+ size_t pos_; // byte position in buf_
+ int bit_pos_; // current bit-reading position in val_
+ int eos_; // true if a bit was read past the end of buffer
} VP8LBitReader;
void VP8LInitBitReader(VP8LBitReader* const br,
@@ -170,28 +141,39 @@ void VP8LInitBitReader(VP8LBitReader* const br,
void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
const uint8_t* const buffer, size_t length);
-// Reads the specified number of bits from Read Buffer.
-// Flags an error in case end_of_stream or n_bits is more than allowed limit.
-// Flags eos if this read attempt is going to cross the read buffer.
+// Reads the specified number of bits from read buffer.
+// Flags an error in case end_of_stream or n_bits is more than the allowed limit
+// of VP8L_MAX_NUM_BIT_READ (inclusive).
+// Flags eos_ if this read attempt is going to cross the read buffer.
uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits);
-// Reads one bit from Read Buffer. Flags an error in case end_of_stream.
-// Flags eos after reading last bit from the buffer.
-uint32_t VP8LReadOneBit(VP8LBitReader* const br);
-
-// VP8LReadOneBitUnsafe is faster than VP8LReadOneBit, but it can be called only
-// 32 times after the last VP8LFillBitWindow. Any subsequent calls
-// (without VP8LFillBitWindow) will return invalid data.
-static WEBP_INLINE uint32_t VP8LReadOneBitUnsafe(VP8LBitReader* const br) {
- const uint32_t val = (br->val_ >> br->bit_pos_) & 1;
- ++br->bit_pos_;
- return val;
+// Return the prefetched bits, so they can be looked up.
+static WEBP_INLINE uint32_t VP8LPrefetchBits(VP8LBitReader* const br) {
+ return (uint32_t)(br->val_ >> (br->bit_pos_ & (VP8L_LBITS - 1)));
}
-// Advances the Read buffer by 4 bytes to make room for reading next 32 bits.
-void VP8LFillBitWindow(VP8LBitReader* const br);
+// Returns true if there was an attempt at reading bit past the end of
+// the buffer. Doesn't set br->eos_ flag.
+static WEBP_INLINE int VP8LIsEndOfStream(const VP8LBitReader* const br) {
+ assert(br->pos_ <= br->len_);
+ return br->eos_ || ((br->pos_ == br->len_) && (br->bit_pos_ > VP8L_LBITS));
+}
+
+// For jumping over a number of bits in the bit stream when accessed with
+// VP8LPrefetchBits and VP8LFillBitWindow.
+static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) {
+ br->bit_pos_ = val;
+ br->eos_ = VP8LIsEndOfStream(br);
+}
+
+// Advances the read buffer by 4 bytes to make room for reading next 32 bits.
+// Speed critical, but infrequent part of the code can be non-inlined.
+extern void VP8LDoFillBitWindow(VP8LBitReader* const br);
+static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) {
+ if (br->bit_pos_ >= VP8L_WBITS) VP8LDoFillBitWindow(br);
+}
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/utils/bit_reader_inl.h b/drivers/webp/utils/bit_reader_inl.h
new file mode 100644
index 0000000000..20ce5f3cc7
--- /dev/null
+++ b/drivers/webp/utils/bit_reader_inl.h
@@ -0,0 +1,172 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Specific inlined methods for boolean decoder [VP8GetBit() ...]
+// This file should be included by the .c sources that actually need to call
+// these methods.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_UTILS_BIT_READER_INL_H_
+#define WEBP_UTILS_BIT_READER_INL_H_
+
+#ifdef HAVE_CONFIG_H
+#include "webp/config.h"
+#endif
+
+#ifdef WEBP_FORCE_ALIGNED
+#include <string.h> // memcpy
+#endif
+
+#include "../dsp/dsp.h"
+#include "./bit_reader.h"
+#include "./endian_inl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Derived type lbit_t = natural type for memory I/O
+
+#if (BITS > 32)
+typedef uint64_t lbit_t;
+#elif (BITS > 16)
+typedef uint32_t lbit_t;
+#elif (BITS > 8)
+typedef uint16_t lbit_t;
+#else
+typedef uint8_t lbit_t;
+#endif
+
+extern const uint8_t kVP8Log2Range[128];
+extern const uint8_t kVP8NewRange[128];
+
+// special case for the tail byte-reading
+void VP8LoadFinalBytes(VP8BitReader* const br);
+
+//------------------------------------------------------------------------------
+// Inlined critical functions
+
+// makes sure br->value_ has at least BITS bits worth of data
+static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) {
+ assert(br != NULL && br->buf_ != NULL);
+ // Read 'BITS' bits at a time if possible.
+ if (br->buf_ < br->buf_max_) {
+ // convert memory type to register type (with some zero'ing!)
+ bit_t bits;
+#if defined(WEBP_FORCE_ALIGNED)
+ lbit_t in_bits;
+ memcpy(&in_bits, br->buf_, sizeof(in_bits));
+#elif defined(WEBP_USE_MIPS32)
+ // This is needed because of un-aligned read.
+ lbit_t in_bits;
+ lbit_t* p_buf_ = (lbit_t*)br->buf_;
+ __asm__ volatile(
+ ".set push \n\t"
+ ".set at \n\t"
+ ".set macro \n\t"
+ "ulw %[in_bits], 0(%[p_buf_]) \n\t"
+ ".set pop \n\t"
+ : [in_bits]"=r"(in_bits)
+ : [p_buf_]"r"(p_buf_)
+ : "memory", "at"
+ );
+#else
+ const lbit_t in_bits = *(const lbit_t*)br->buf_;
+#endif
+ br->buf_ += BITS >> 3;
+#if !defined(WORDS_BIGENDIAN)
+#if (BITS > 32)
+ bits = BSwap64(in_bits);
+ bits >>= 64 - BITS;
+#elif (BITS >= 24)
+ bits = BSwap32(in_bits);
+ bits >>= (32 - BITS);
+#elif (BITS == 16)
+ bits = BSwap16(in_bits);
+#else // BITS == 8
+ bits = (bit_t)in_bits;
+#endif // BITS > 32
+#else // WORDS_BIGENDIAN
+ bits = (bit_t)in_bits;
+ if (BITS != 8 * sizeof(bit_t)) bits >>= (8 * sizeof(bit_t) - BITS);
+#endif
+ br->value_ = bits | (br->value_ << BITS);
+ br->bits_ += BITS;
+ } else {
+ VP8LoadFinalBytes(br); // no need to be inlined
+ }
+}
+
+// Read a bit with proba 'prob'. Speed-critical function!
+static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) {
+ // Don't move this declaration! It makes a big speed difference to store
+ // 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't
+ // alter br->range_ value.
+ range_t range = br->range_;
+ if (br->bits_ < 0) {
+ VP8LoadNewBytes(br);
+ }
+ {
+ const int pos = br->bits_;
+ const range_t split = (range * prob) >> 8;
+ const range_t value = (range_t)(br->value_ >> pos);
+#if defined(__arm__) || defined(_M_ARM) // ARM-specific
+ const int bit = ((int)(split - value) >> 31) & 1;
+ if (value > split) {
+ range -= split + 1;
+ br->value_ -= (bit_t)(split + 1) << pos;
+ } else {
+ range = split;
+ }
+#else // faster version on x86
+ int bit; // Don't use 'const int bit = (value > split);", it's slower.
+ if (value > split) {
+ range -= split + 1;
+ br->value_ -= (bit_t)(split + 1) << pos;
+ bit = 1;
+ } else {
+ range = split;
+ bit = 0;
+ }
+#endif
+ if (range <= (range_t)0x7e) {
+ const int shift = kVP8Log2Range[range];
+ range = kVP8NewRange[range];
+ br->bits_ -= shift;
+ }
+ br->range_ = range;
+ return bit;
+ }
+}
+
+// simplified version of VP8GetBit() for prob=0x80 (note shift is always 1 here)
+static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) {
+ if (br->bits_ < 0) {
+ VP8LoadNewBytes(br);
+ }
+ {
+ const int pos = br->bits_;
+ const range_t split = br->range_ >> 1;
+ const range_t value = (range_t)(br->value_ >> pos);
+ const int32_t mask = (int32_t)(split - value) >> 31; // -1 or 0
+ br->bits_ -= 1;
+ br->range_ += mask;
+ br->range_ |= 1;
+ br->value_ -= (bit_t)((split + 1) & mask) << pos;
+ return (v ^ mask) - mask;
+ }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // WEBP_UTILS_BIT_READER_INL_H_
diff --git a/drivers/webp/utils/bit_writer.c b/drivers/webp/utils/bit_writer.c
index 671159cacd..064428691b 100644
--- a/drivers/webp/utils/bit_writer.c
+++ b/drivers/webp/utils/bit_writer.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Bit writing and boolean coder
@@ -13,11 +15,10 @@
#include <assert.h>
#include <string.h> // for memcpy()
#include <stdlib.h>
-#include "./bit_writer.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+#include "./bit_writer.h"
+#include "./endian_inl.h"
+#include "./utils.h"
//------------------------------------------------------------------------------
// VP8BitWriter
@@ -36,19 +37,22 @@ static int BitWriterResize(VP8BitWriter* const bw, size_t extra_size) {
new_size = 2 * bw->max_pos_;
if (new_size < needed_size) new_size = needed_size;
if (new_size < 1024) new_size = 1024;
- new_buf = (uint8_t*)malloc(new_size);
+ new_buf = (uint8_t*)WebPSafeMalloc(1ULL, new_size);
if (new_buf == NULL) {
bw->error_ = 1;
return 0;
}
- memcpy(new_buf, bw->buf_, bw->pos_);
- free(bw->buf_);
+ if (bw->pos_ > 0) {
+ assert(bw->buf_ != NULL);
+ memcpy(new_buf, bw->buf_, bw->pos_);
+ }
+ WebPSafeFree(bw->buf_);
bw->buf_ = new_buf;
bw->max_pos_ = new_size;
return 1;
}
-static void kFlush(VP8BitWriter* const bw) {
+static void Flush(VP8BitWriter* const bw) {
const int s = 8 + bw->nb_bits_;
const int32_t bits = bw->value_ >> s;
assert(bw->nb_bits_ >= 0);
@@ -114,7 +118,7 @@ int VP8PutBit(VP8BitWriter* const bw, int bit, int prob) {
bw->range_ = kNewRange[bw->range_];
bw->value_ <<= shift;
bw->nb_bits_ += shift;
- if (bw->nb_bits_ > 0) kFlush(bw);
+ if (bw->nb_bits_ > 0) Flush(bw);
}
return bit;
}
@@ -131,24 +135,25 @@ int VP8PutBitUniform(VP8BitWriter* const bw, int bit) {
bw->range_ = kNewRange[bw->range_];
bw->value_ <<= 1;
bw->nb_bits_ += 1;
- if (bw->nb_bits_ > 0) kFlush(bw);
+ if (bw->nb_bits_ > 0) Flush(bw);
}
return bit;
}
-void VP8PutValue(VP8BitWriter* const bw, int value, int nb_bits) {
- int mask;
- for (mask = 1 << (nb_bits - 1); mask; mask >>= 1)
+void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits) {
+ uint32_t mask;
+ assert(nb_bits > 0 && nb_bits < 32);
+ for (mask = 1u << (nb_bits - 1); mask; mask >>= 1)
VP8PutBitUniform(bw, value & mask);
}
-void VP8PutSignedValue(VP8BitWriter* const bw, int value, int nb_bits) {
+void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits) {
if (!VP8PutBitUniform(bw, value != 0))
return;
if (value < 0) {
- VP8PutValue(bw, ((-value) << 1) | 1, nb_bits + 1);
+ VP8PutBits(bw, ((-value) << 1) | 1, nb_bits + 1);
} else {
- VP8PutValue(bw, value << 1, nb_bits + 1);
+ VP8PutBits(bw, value << 1, nb_bits + 1);
}
}
@@ -167,16 +172,16 @@ int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size) {
}
uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw) {
- VP8PutValue(bw, 0, 9 - bw->nb_bits_);
+ VP8PutBits(bw, 0, 9 - bw->nb_bits_);
bw->nb_bits_ = 0; // pad with zeroes
- kFlush(bw);
+ Flush(bw);
return bw->buf_;
}
int VP8BitWriterAppend(VP8BitWriter* const bw,
const uint8_t* data, size_t size) {
- assert(data);
- if (bw->nb_bits_ != -8) return 0; // kFlush() must have been called
+ assert(data != NULL);
+ if (bw->nb_bits_ != -8) return 0; // Flush() must have been called
if (!BitWriterResize(bw, size)) return 0;
memcpy(bw->buf_ + bw->pos_, data, size);
bw->pos_ += size;
@@ -184,8 +189,8 @@ int VP8BitWriterAppend(VP8BitWriter* const bw,
}
void VP8BitWriterWipeOut(VP8BitWriter* const bw) {
- if (bw) {
- free(bw->buf_);
+ if (bw != NULL) {
+ WebPSafeFree(bw->buf_);
memset(bw, 0, sizeof(*bw));
}
}
@@ -193,32 +198,39 @@ void VP8BitWriterWipeOut(VP8BitWriter* const bw) {
//------------------------------------------------------------------------------
// VP8LBitWriter
+// This is the minimum amount of size the memory buffer is guaranteed to grow
+// when extra space is needed.
+#define MIN_EXTRA_SIZE (32768ULL)
+
// Returns 1 on success.
static int VP8LBitWriterResize(VP8LBitWriter* const bw, size_t extra_size) {
uint8_t* allocated_buf;
size_t allocated_size;
- const size_t current_size = VP8LBitWriterNumBytes(bw);
+ const size_t max_bytes = bw->end_ - bw->buf_;
+ const size_t current_size = bw->cur_ - bw->buf_;
const uint64_t size_required_64b = (uint64_t)current_size + extra_size;
const size_t size_required = (size_t)size_required_64b;
if (size_required != size_required_64b) {
bw->error_ = 1;
return 0;
}
- if (bw->max_bytes_ > 0 && size_required <= bw->max_bytes_) return 1;
- allocated_size = (3 * bw->max_bytes_) >> 1;
+ if (max_bytes > 0 && size_required <= max_bytes) return 1;
+ allocated_size = (3 * max_bytes) >> 1;
if (allocated_size < size_required) allocated_size = size_required;
// make allocated size multiple of 1k
allocated_size = (((allocated_size >> 10) + 1) << 10);
- allocated_buf = (uint8_t*)malloc(allocated_size);
+ allocated_buf = (uint8_t*)WebPSafeMalloc(1ULL, allocated_size);
if (allocated_buf == NULL) {
bw->error_ = 1;
return 0;
}
- memcpy(allocated_buf, bw->buf_, current_size);
- free(bw->buf_);
+ if (current_size > 0) {
+ memcpy(allocated_buf, bw->buf_, current_size);
+ }
+ WebPSafeFree(bw->buf_);
bw->buf_ = allocated_buf;
- bw->max_bytes_ = allocated_size;
- memset(allocated_buf + current_size, 0, allocated_size - current_size);
+ bw->cur_ = bw->buf_ + current_size;
+ bw->end_ = bw->buf_ + allocated_size;
return 1;
}
@@ -227,58 +239,81 @@ int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) {
return VP8LBitWriterResize(bw, expected_size);
}
-void VP8LBitWriterDestroy(VP8LBitWriter* const bw) {
+void VP8LBitWriterWipeOut(VP8LBitWriter* const bw) {
if (bw != NULL) {
- free(bw->buf_);
+ WebPSafeFree(bw->buf_);
memset(bw, 0, sizeof(*bw));
}
}
-void VP8LWriteBits(VP8LBitWriter* const bw, int n_bits, uint32_t bits) {
- if (n_bits < 1) return;
-#if !defined(__BIG_ENDIAN__)
- // Technically, this branch of the code can write up to 25 bits at a time,
- // but in prefix encoding, the maximum number of bits written is 18 at a time.
- {
- uint8_t* const p = &bw->buf_[bw->bit_pos_ >> 3];
- uint32_t v = *(const uint32_t*)p;
- v |= bits << (bw->bit_pos_ & 7);
- *(uint32_t*)p = v;
- bw->bit_pos_ += n_bits;
+void VP8LPutBitsFlushBits(VP8LBitWriter* const bw) {
+ // If needed, make some room by flushing some bits out.
+ if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) {
+ const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE;
+ if (extra_size != (size_t)extra_size ||
+ !VP8LBitWriterResize(bw, (size_t)extra_size)) {
+ bw->cur_ = bw->buf_;
+ bw->error_ = 1;
+ return;
+ }
}
-#else // BIG_ENDIAN
- {
- uint8_t* p = &bw->buf_[bw->bit_pos_ >> 3];
- const int bits_reserved_in_first_byte = bw->bit_pos_ & 7;
- const int bits_left_to_write = n_bits - 8 + bits_reserved_in_first_byte;
- // implicit & 0xff is assumed for uint8_t arithmetics
- *p++ |= bits << bits_reserved_in_first_byte;
- bits >>= 8 - bits_reserved_in_first_byte;
- if (bits_left_to_write >= 1) {
- *p++ = bits;
- bits >>= 8;
- if (bits_left_to_write >= 9) {
- *p++ = bits;
- bits >>= 8;
+ *(vp8l_wtype_t*)bw->cur_ = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)bw->bits_);
+ bw->cur_ += VP8L_WRITER_BYTES;
+ bw->bits_ >>= VP8L_WRITER_BITS;
+ bw->used_ -= VP8L_WRITER_BITS;
+}
+
+void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits) {
+ assert(n_bits <= 32);
+ // That's the max we can handle:
+ assert(sizeof(vp8l_wtype_t) == 2);
+ if (n_bits > 0) {
+ vp8l_atype_t lbits = bw->bits_;
+ int used = bw->used_;
+ // Special case of overflow handling for 32bit accumulator (2-steps flush).
+#if VP8L_WRITER_BITS == 16
+ if (used + n_bits >= VP8L_WRITER_MAX_BITS) {
+ // Fill up all the VP8L_WRITER_MAX_BITS so it can be flushed out below.
+ const int shift = VP8L_WRITER_MAX_BITS - used;
+ lbits |= (vp8l_atype_t)bits << used;
+ used = VP8L_WRITER_MAX_BITS;
+ n_bits -= shift;
+ bits >>= shift;
+ assert(n_bits <= VP8L_WRITER_MAX_BITS);
+ }
+#endif
+ // If needed, make some room by flushing some bits out.
+ while (used >= VP8L_WRITER_BITS) {
+ if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) {
+ const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE;
+ if (extra_size != (size_t)extra_size ||
+ !VP8LBitWriterResize(bw, (size_t)extra_size)) {
+ bw->cur_ = bw->buf_;
+ bw->error_ = 1;
+ return;
+ }
}
+ *(vp8l_wtype_t*)bw->cur_ = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)lbits);
+ bw->cur_ += VP8L_WRITER_BYTES;
+ lbits >>= VP8L_WRITER_BITS;
+ used -= VP8L_WRITER_BITS;
}
- assert(n_bits <= 25);
- *p = bits;
- bw->bit_pos_ += n_bits;
+ bw->bits_ = lbits | ((vp8l_atype_t)bits << used);
+ bw->used_ = used + n_bits;
}
-#endif
- if ((bw->bit_pos_ >> 3) > (bw->max_bytes_ - 8)) {
- const uint64_t extra_size = 32768ULL + bw->max_bytes_;
- if (extra_size != (size_t)extra_size ||
- !VP8LBitWriterResize(bw, (size_t)extra_size)) {
- bw->bit_pos_ = 0;
- bw->error_ = 1;
+}
+
+uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw) {
+ // flush leftover bits
+ if (VP8LBitWriterResize(bw, (bw->used_ + 7) >> 3)) {
+ while (bw->used_ > 0) {
+ *bw->cur_++ = (uint8_t)bw->bits_;
+ bw->bits_ >>= 8;
+ bw->used_ -= 8;
}
+ bw->used_ = 0;
}
+ return bw->buf_;
}
//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/utils/bit_writer.h b/drivers/webp/utils/bit_writer.h
index 57f39b11b1..867a5ee055 100644
--- a/drivers/webp/utils/bit_writer.h
+++ b/drivers/webp/utils/bit_writer.h
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Bit writing and boolean coder
@@ -12,9 +14,9 @@
#ifndef WEBP_UTILS_BIT_WRITER_H_
#define WEBP_UTILS_BIT_WRITER_H_
-#include "../types.h"
+#include "webp/types.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
@@ -43,8 +45,8 @@ void VP8BitWriterWipeOut(VP8BitWriter* const bw);
int VP8PutBit(VP8BitWriter* const bw, int bit, int prob);
int VP8PutBitUniform(VP8BitWriter* const bw, int bit);
-void VP8PutValue(VP8BitWriter* const bw, int value, int nb_bits);
-void VP8PutSignedValue(VP8BitWriter* const bw, int value, int nb_bits);
+void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits);
+void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits);
// Appends some bytes to the internal buffer. Data is copied.
int VP8BitWriterAppend(VP8BitWriter* const bw,
@@ -66,57 +68,77 @@ static WEBP_INLINE size_t VP8BitWriterSize(const VP8BitWriter* const bw) {
//------------------------------------------------------------------------------
// VP8LBitWriter
-// TODO(vikasa): VP8LBitWriter is copied as-is from lossless code. There's scope
-// of re-using VP8BitWriter. Will evaluate once basic lossless encoder is
-// implemented.
-typedef struct {
- uint8_t* buf_;
- size_t bit_pos_;
- size_t max_bytes_;
+#if defined(__x86_64__) || defined(_M_X64) // 64bit
+typedef uint64_t vp8l_atype_t; // accumulator type
+typedef uint32_t vp8l_wtype_t; // writing type
+#define WSWAP HToLE32
+#define VP8L_WRITER_BYTES 4 // sizeof(vp8l_wtype_t)
+#define VP8L_WRITER_BITS 32 // 8 * sizeof(vp8l_wtype_t)
+#define VP8L_WRITER_MAX_BITS 64 // 8 * sizeof(vp8l_atype_t)
+#else
+typedef uint32_t vp8l_atype_t;
+typedef uint16_t vp8l_wtype_t;
+#define WSWAP HToLE16
+#define VP8L_WRITER_BYTES 2
+#define VP8L_WRITER_BITS 16
+#define VP8L_WRITER_MAX_BITS 32
+#endif
- // After all bits are written, the caller must observe the state of
- // error_. A value of 1 indicates that a memory allocation failure
- // has happened during bit writing. A value of 0 indicates successful
+typedef struct {
+ vp8l_atype_t bits_; // bit accumulator
+ int used_; // number of bits used in accumulator
+ uint8_t* buf_; // start of buffer
+ uint8_t* cur_; // current write position
+ uint8_t* end_; // end of buffer
+
+ // After all bits are written (VP8LBitWriterFinish()), the caller must observe
+ // the state of error_. A value of 1 indicates that a memory allocation
+ // failure has happened during bit writing. A value of 0 indicates successful
// writing of bits.
int error_;
} VP8LBitWriter;
static WEBP_INLINE size_t VP8LBitWriterNumBytes(VP8LBitWriter* const bw) {
- return (bw->bit_pos_ + 7) >> 3;
-}
-
-static WEBP_INLINE uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw) {
- return bw->buf_;
+ return (bw->cur_ - bw->buf_) + ((bw->used_ + 7) >> 3);
}
-// Returns 0 in case of memory allocation error.
+// Returns false in case of memory allocation error.
int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size);
+// Finalize the bitstream coding. Returns a pointer to the internal buffer.
+uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw);
+// Release any pending memory and zeroes the object.
+void VP8LBitWriterWipeOut(VP8LBitWriter* const bw);
-void VP8LBitWriterDestroy(VP8LBitWriter* const bw);
+// Internal function for VP8LPutBits flushing 32 bits from the written state.
+void VP8LPutBitsFlushBits(VP8LBitWriter* const bw);
-// This function writes bits into bytes in increasing addresses, and within
-// a byte least-significant-bit first.
-//
-// The function can write up to 16 bits in one go with WriteBits
-// Example: let's assume that 3 bits (Rs below) have been written already:
-//
-// BYTE-0 BYTE+1 BYTE+2
-//
-// 0000 0RRR 0000 0000 0000 0000
-//
-// Now, we could write 5 or less bits in MSB by just sifting by 3
-// and OR'ing to BYTE-0.
-//
-// For n bits, we take the last 5 bytes, OR that with high bits in BYTE-0,
-// and locate the rest in BYTE+1 and BYTE+2.
-//
+// PutBits internal function used in the 16 bit vp8l_wtype_t case.
+void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits);
+
+// This function writes bits into bytes in increasing addresses (little endian),
+// and within a byte least-significant-bit first.
+// This function can write up to 32 bits in one go, but VP8LBitReader can only
+// read 24 bits max (VP8L_MAX_NUM_BIT_READ).
// VP8LBitWriter's error_ flag is set in case of memory allocation error.
-void VP8LWriteBits(VP8LBitWriter* const bw, int n_bits, uint32_t bits);
+static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw,
+ uint32_t bits, int n_bits) {
+ if (sizeof(vp8l_wtype_t) == 4) {
+ if (n_bits > 0) {
+ if (bw->used_ >= 32) {
+ VP8LPutBitsFlushBits(bw);
+ }
+ bw->bits_ |= (vp8l_atype_t)bits << bw->used_;
+ bw->used_ += n_bits;
+ }
+ } else {
+ VP8LPutBitsInternal(bw, bits, n_bits);
+ }
+}
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/utils/color_cache.c b/drivers/webp/utils/color_cache.c
index 560f81db10..f9ff4b5451 100644
--- a/drivers/webp/utils/color_cache.c
+++ b/drivers/webp/utils/color_cache.c
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Color Cache for WebP Lossless
@@ -11,13 +13,10 @@
#include <assert.h>
#include <stdlib.h>
+#include <string.h>
#include "./color_cache.h"
#include "../utils/utils.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
//------------------------------------------------------------------------------
// VP8LColorCache.
@@ -29,16 +28,22 @@ int VP8LColorCacheInit(VP8LColorCache* const cc, int hash_bits) {
sizeof(*cc->colors_));
if (cc->colors_ == NULL) return 0;
cc->hash_shift_ = 32 - hash_bits;
+ cc->hash_bits_ = hash_bits;
return 1;
}
void VP8LColorCacheClear(VP8LColorCache* const cc) {
if (cc != NULL) {
- free(cc->colors_);
+ WebPSafeFree(cc->colors_);
cc->colors_ = NULL;
}
}
-#if defined(__cplusplus) || defined(c_plusplus)
+void VP8LColorCacheCopy(const VP8LColorCache* const src,
+ VP8LColorCache* const dst) {
+ assert(src != NULL);
+ assert(dst != NULL);
+ assert(src->hash_bits_ == dst->hash_bits_);
+ memcpy(dst->colors_, src->colors_,
+ ((size_t)1u << dst->hash_bits_) * sizeof(*dst->colors_));
}
-#endif
diff --git a/drivers/webp/utils/color_cache.h b/drivers/webp/utils/color_cache.h
index da5e260195..34299e4c4e 100644
--- a/drivers/webp/utils/color_cache.h
+++ b/drivers/webp/utils/color_cache.h
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Color Cache for WebP Lossless
@@ -13,26 +15,33 @@
#ifndef WEBP_UTILS_COLOR_CACHE_H_
#define WEBP_UTILS_COLOR_CACHE_H_
-#include "../types.h"
+#include "webp/types.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
// Main color cache struct.
typedef struct {
uint32_t *colors_; // color entries
- int hash_shift_; // Hash shift: 32 - hash_bits.
+ int hash_shift_; // Hash shift: 32 - hash_bits_.
+ int hash_bits_;
} VP8LColorCache;
static const uint32_t kHashMul = 0x1e35a7bd;
static WEBP_INLINE uint32_t VP8LColorCacheLookup(
const VP8LColorCache* const cc, uint32_t key) {
- assert(key <= (~0U >> cc->hash_shift_));
+ assert((key >> cc->hash_bits_) == 0u);
return cc->colors_[key];
}
+static WEBP_INLINE void VP8LColorCacheSet(const VP8LColorCache* const cc,
+ uint32_t key, uint32_t argb) {
+ assert((key >> cc->hash_bits_) == 0u);
+ cc->colors_[key] = argb;
+}
+
static WEBP_INLINE void VP8LColorCacheInsert(const VP8LColorCache* const cc,
uint32_t argb) {
const uint32_t key = (kHashMul * argb) >> cc->hash_shift_;
@@ -47,7 +56,7 @@ static WEBP_INLINE int VP8LColorCacheGetIndex(const VP8LColorCache* const cc,
static WEBP_INLINE int VP8LColorCacheContains(const VP8LColorCache* const cc,
uint32_t argb) {
const uint32_t key = (kHashMul * argb) >> cc->hash_shift_;
- return cc->colors_[key] == argb;
+ return (cc->colors_[key] == argb);
}
//------------------------------------------------------------------------------
@@ -56,12 +65,15 @@ static WEBP_INLINE int VP8LColorCacheContains(const VP8LColorCache* const cc,
// Returns false in case of memory error.
int VP8LColorCacheInit(VP8LColorCache* const color_cache, int hash_bits);
+void VP8LColorCacheCopy(const VP8LColorCache* const src,
+ VP8LColorCache* const dst);
+
// Delete the memory associated to color cache.
void VP8LColorCacheClear(VP8LColorCache* const color_cache);
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
}
#endif
diff --git a/drivers/webp/utils/endian_inl.h b/drivers/webp/utils/endian_inl.h
new file mode 100644
index 0000000000..253b7be8ee
--- /dev/null
+++ b/drivers/webp/utils/endian_inl.h
@@ -0,0 +1,100 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Endian related functions.
+
+#ifndef WEBP_UTILS_ENDIAN_INL_H_
+#define WEBP_UTILS_ENDIAN_INL_H_
+
+#ifdef HAVE_CONFIG_H
+#include "webp/config.h"
+#endif
+
+#include "../dsp/dsp.h"
+#include "webp/types.h"
+
+// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__)
+#if !defined(WORDS_BIGENDIAN) && \
+ (defined(__BIG_ENDIAN__) || defined(_M_PPC) || \
+ (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
+#define WORDS_BIGENDIAN
+#endif
+
+#if defined(WORDS_BIGENDIAN)
+#define HToLE32 BSwap32
+#define HToLE16 BSwap16
+#else
+#define HToLE32(x) (x)
+#define HToLE16(x) (x)
+#endif
+
+#if !defined(HAVE_CONFIG_H)
+#if LOCAL_GCC_PREREQ(4,8) || __has_builtin(__builtin_bswap16)
+#define HAVE_BUILTIN_BSWAP16
+#endif
+#if LOCAL_GCC_PREREQ(4,3) || __has_builtin(__builtin_bswap32)
+#define HAVE_BUILTIN_BSWAP32
+#endif
+#if LOCAL_GCC_PREREQ(4,3) || __has_builtin(__builtin_bswap64)
+#define HAVE_BUILTIN_BSWAP64
+#endif
+#endif // !HAVE_CONFIG_H
+
+static WEBP_INLINE uint16_t BSwap16(uint16_t x) {
+#if defined(HAVE_BUILTIN_BSWAP16)
+ return __builtin_bswap16(x);
+#elif defined(_MSC_VER)
+ return _byteswap_ushort(x);
+#else
+ // gcc will recognize a 'rorw $8, ...' here:
+ return (x >> 8) | ((x & 0xff) << 8);
+#endif // HAVE_BUILTIN_BSWAP16
+}
+
+static WEBP_INLINE uint32_t BSwap32(uint32_t x) {
+#if defined(WEBP_USE_MIPS32_R2)
+ uint32_t ret;
+ __asm__ volatile (
+ "wsbh %[ret], %[x] \n\t"
+ "rotr %[ret], %[ret], 16 \n\t"
+ : [ret]"=r"(ret)
+ : [x]"r"(x)
+ );
+ return ret;
+#elif defined(HAVE_BUILTIN_BSWAP32)
+ return __builtin_bswap32(x);
+#elif defined(__i386__) || defined(__x86_64__)
+ uint32_t swapped_bytes;
+ __asm__ volatile("bswap %0" : "=r"(swapped_bytes) : "0"(x));
+ return swapped_bytes;
+#elif defined(_MSC_VER)
+ return (uint32_t)_byteswap_ulong(x);
+#else
+ return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24);
+#endif // HAVE_BUILTIN_BSWAP32
+}
+
+static WEBP_INLINE uint64_t BSwap64(uint64_t x) {
+#if defined(HAVE_BUILTIN_BSWAP64)
+ return __builtin_bswap64(x);
+#elif defined(__x86_64__)
+ uint64_t swapped_bytes;
+ __asm__ volatile("bswapq %0" : "=r"(swapped_bytes) : "0"(x));
+ return swapped_bytes;
+#elif defined(_MSC_VER)
+ return (uint64_t)_byteswap_uint64(x);
+#else // generic code for swapping 64-bit values (suggested by bdb@)
+ x = ((x & 0xffffffff00000000ull) >> 32) | ((x & 0x00000000ffffffffull) << 32);
+ x = ((x & 0xffff0000ffff0000ull) >> 16) | ((x & 0x0000ffff0000ffffull) << 16);
+ x = ((x & 0xff00ff00ff00ff00ull) >> 8) | ((x & 0x00ff00ff00ff00ffull) << 8);
+ return x;
+#endif // HAVE_BUILTIN_BSWAP64
+}
+
+#endif // WEBP_UTILS_ENDIAN_INL_H_
diff --git a/drivers/webp/utils/filters.c b/drivers/webp/utils/filters.c
index 08f52a3d20..15543b1271 100644
--- a/drivers/webp/utils/filters.c
+++ b/drivers/webp/utils/filters.c
@@ -1,171 +1,37 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
-// Spatial prediction using various filters
+// filter estimation
//
// Author: Urvang (urvang@google.com)
#include "./filters.h"
-#include <assert.h>
#include <stdlib.h>
#include <string.h>
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// Helpful macro.
-
-# define SANITY_CHECK(in, out) \
- assert(in != NULL); \
- assert(out != NULL); \
- assert(width > 0); \
- assert(height > 0); \
- assert(bpp > 0); \
- assert(stride >= width * bpp);
-
-static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred,
- uint8_t* dst, int length, int inverse) {
- int i;
- if (inverse) {
- for (i = 0; i < length; ++i) dst[i] = src[i] + pred[i];
- } else {
- for (i = 0; i < length; ++i) dst[i] = src[i] - pred[i];
- }
-}
-
-//------------------------------------------------------------------------------
-// Horizontal filter.
-
-static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in,
- int width, int height, int bpp, int stride, int inverse, uint8_t* out) {
- int h;
- const uint8_t* preds = (inverse ? out : in);
- SANITY_CHECK(in, out);
-
- // Filter line-by-line.
- for (h = 0; h < height; ++h) {
- // Leftmost pixel is predicted from above (except for topmost scanline).
- if (h == 0) {
- memcpy((void*)out, (const void*)in, bpp);
- } else {
- PredictLine(in, preds - stride, out, bpp, inverse);
- }
- PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse);
- preds += stride;
- in += stride;
- out += stride;
- }
-}
-
-static void HorizontalFilter(const uint8_t* data, int width, int height,
- int bpp, int stride, uint8_t* filtered_data) {
- DoHorizontalFilter(data, width, height, bpp, stride, 0, filtered_data);
-}
-
-static void HorizontalUnfilter(const uint8_t* data, int width, int height,
- int bpp, int stride, uint8_t* recon_data) {
- DoHorizontalFilter(data, width, height, bpp, stride, 1, recon_data);
-}
-
-//------------------------------------------------------------------------------
-// Vertical filter.
-
-static WEBP_INLINE void DoVerticalFilter(const uint8_t* in,
- int width, int height, int bpp, int stride, int inverse, uint8_t* out) {
- int h;
- const uint8_t* preds = (inverse ? out : in);
- SANITY_CHECK(in, out);
-
- // Very first top-left pixel is copied.
- memcpy((void*)out, (const void*)in, bpp);
- // Rest of top scan-line is left-predicted.
- PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse);
-
- // Filter line-by-line.
- for (h = 1; h < height; ++h) {
- in += stride;
- out += stride;
- PredictLine(in, preds, out, bpp * width, inverse);
- preds += stride;
- }
-}
-
-static void VerticalFilter(const uint8_t* data, int width, int height,
- int bpp, int stride, uint8_t* filtered_data) {
- DoVerticalFilter(data, width, height, bpp, stride, 0, filtered_data);
-}
-
-static void VerticalUnfilter(const uint8_t* data, int width, int height,
- int bpp, int stride, uint8_t* recon_data) {
- DoVerticalFilter(data, width, height, bpp, stride, 1, recon_data);
-}
+// -----------------------------------------------------------------------------
+// Quick estimate of a potentially interesting filter mode to try.
-//------------------------------------------------------------------------------
-// Gradient filter.
+#define SMAX 16
+#define SDIFF(a, b) (abs((a) - (b)) >> 4) // Scoring diff, in [0..SMAX)
static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) {
const int g = a + b - c;
- return (g < 0) ? 0 : (g > 255) ? 255 : g;
-}
-
-static WEBP_INLINE
-void DoGradientFilter(const uint8_t* in, int width, int height,
- int bpp, int stride, int inverse, uint8_t* out) {
- const uint8_t* preds = (inverse ? out : in);
- int h;
- SANITY_CHECK(in, out);
-
- // left prediction for top scan-line
- memcpy((void*)out, (const void*)in, bpp);
- PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse);
-
- // Filter line-by-line.
- for (h = 1; h < height; ++h) {
- int w;
- preds += stride;
- in += stride;
- out += stride;
- // leftmost pixel: predict from above.
- PredictLine(in, preds - stride, out, bpp, inverse);
- for (w = bpp; w < width * bpp; ++w) {
- const int pred = GradientPredictor(preds[w - bpp],
- preds[w - stride],
- preds[w - stride - bpp]);
- out[w] = in[w] + (inverse ? pred : -pred);
- }
- }
+ return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit
}
-static void GradientFilter(const uint8_t* data, int width, int height,
- int bpp, int stride, uint8_t* filtered_data) {
- DoGradientFilter(data, width, height, bpp, stride, 0, filtered_data);
-}
-
-static void GradientUnfilter(const uint8_t* data, int width, int height,
- int bpp, int stride, uint8_t* recon_data) {
- DoGradientFilter(data, width, height, bpp, stride, 1, recon_data);
-}
-
-#undef SANITY_CHECK
-
-// -----------------------------------------------------------------------------
-// Quick estimate of a potentially interesting filter mode to try, in addition
-// to the default NONE.
-
-#define SMAX 16
-#define SDIFF(a, b) (abs((a) - (b)) >> 4) // Scoring diff, in [0..SMAX)
-
-WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data,
- int width, int height, int stride) {
+WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data,
+ int width, int height, int stride) {
int i, j;
int bins[WEBP_FILTER_LAST][SMAX];
memset(bins, 0, sizeof(bins));
+
// We only sample every other pixels. That's enough.
for (j = 2; j < height - 1; j += 2) {
const uint8_t* const p = data + j * stride;
@@ -185,7 +51,8 @@ WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data,
}
}
{
- WEBP_FILTER_TYPE filter, best_filter = WEBP_FILTER_NONE;
+ int filter;
+ WEBP_FILTER_TYPE best_filter = WEBP_FILTER_NONE;
int best_score = 0x7fffffff;
for (filter = WEBP_FILTER_NONE; filter < WEBP_FILTER_LAST; ++filter) {
int score = 0;
@@ -196,7 +63,7 @@ WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data,
}
if (score < best_score) {
best_score = score;
- best_filter = filter;
+ best_filter = (WEBP_FILTER_TYPE)filter;
}
}
return best_filter;
@@ -207,23 +74,3 @@ WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data,
#undef SDIFF
//------------------------------------------------------------------------------
-
-const WebPFilterFunc WebPFilters[WEBP_FILTER_LAST] = {
- NULL, // WEBP_FILTER_NONE
- HorizontalFilter, // WEBP_FILTER_HORIZONTAL
- VerticalFilter, // WEBP_FILTER_VERTICAL
- GradientFilter // WEBP_FILTER_GRADIENT
-};
-
-const WebPFilterFunc WebPUnfilters[WEBP_FILTER_LAST] = {
- NULL, // WEBP_FILTER_NONE
- HorizontalUnfilter, // WEBP_FILTER_HORIZONTAL
- VerticalUnfilter, // WEBP_FILTER_VERTICAL
- GradientUnfilter // WEBP_FILTER_GRADIENT
-};
-
-//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/utils/filters.h b/drivers/webp/utils/filters.h
index db886be29a..4aba3fd3b7 100644
--- a/drivers/webp/utils/filters.h
+++ b/drivers/webp/utils/filters.h
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Spatial prediction using various filters
@@ -12,42 +14,18 @@
#ifndef WEBP_UTILS_FILTERS_H_
#define WEBP_UTILS_FILTERS_H_
-#include "../types.h"
+#include "webp/types.h"
+#include "../dsp/dsp.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
-// Filters.
-typedef enum {
- WEBP_FILTER_NONE = 0,
- WEBP_FILTER_HORIZONTAL,
- WEBP_FILTER_VERTICAL,
- WEBP_FILTER_GRADIENT,
- WEBP_FILTER_LAST = WEBP_FILTER_GRADIENT + 1, // end marker
- WEBP_FILTER_BEST,
- WEBP_FILTER_FAST
-} WEBP_FILTER_TYPE;
-
-typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height,
- int bpp, int stride, uint8_t* out);
-
-// Filter the given data using the given predictor.
-// 'in' corresponds to a 2-dimensional pixel array of size (stride * height)
-// in raster order.
-// 'bpp' is number of bytes per pixel, and
-// 'stride' is number of bytes per scan line (with possible padding).
-// 'out' should be pre-allocated.
-extern const WebPFilterFunc WebPFilters[WEBP_FILTER_LAST];
-
-// Reconstruct the original data from the given filtered data.
-extern const WebPFilterFunc WebPUnfilters[WEBP_FILTER_LAST];
-
// Fast estimate of a potentially good filter.
-extern WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data,
- int width, int height, int stride);
+WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data,
+ int width, int height, int stride);
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/utils/huffman.c b/drivers/webp/utils/huffman.c
index 1cc1cfd355..e6f482a6a8 100644
--- a/drivers/webp/utils/huffman.c
+++ b/drivers/webp/utils/huffman.c
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Utilities for building and looking up Huffman trees.
@@ -11,228 +13,193 @@
#include <assert.h>
#include <stdlib.h>
+#include <string.h>
#include "./huffman.h"
#include "../utils/utils.h"
-#include "../format_constants.h"
+#include "webp/format_constants.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+// Huffman data read via DecodeImageStream is represented in two (red and green)
+// bytes.
+#define MAX_HTREE_GROUPS 0x10000
-#define NON_EXISTENT_SYMBOL (-1)
-
-static void TreeNodeInit(HuffmanTreeNode* const node) {
- node->children_ = -1; // means: 'unassigned so far'
-}
-
-static int NodeIsEmpty(const HuffmanTreeNode* const node) {
- return (node->children_ < 0);
+HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups) {
+ HTreeGroup* const htree_groups =
+ (HTreeGroup*)WebPSafeMalloc(num_htree_groups, sizeof(*htree_groups));
+ if (htree_groups == NULL) {
+ return NULL;
+ }
+ assert(num_htree_groups <= MAX_HTREE_GROUPS);
+ return htree_groups;
}
-static int IsFull(const HuffmanTree* const tree) {
- return (tree->num_nodes_ == tree->max_nodes_);
+void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups) {
+ if (htree_groups != NULL) {
+ WebPSafeFree(htree_groups);
+ }
}
-static void AssignChildren(HuffmanTree* const tree,
- HuffmanTreeNode* const node) {
- HuffmanTreeNode* const children = tree->root_ + tree->num_nodes_;
- node->children_ = (int)(children - node);
- assert(children - node == (int)(children - node));
- tree->num_nodes_ += 2;
- TreeNodeInit(children + 0);
- TreeNodeInit(children + 1);
+// Returns reverse(reverse(key, len) + 1, len), where reverse(key, len) is the
+// bit-wise reversal of the len least significant bits of key.
+static WEBP_INLINE uint32_t GetNextKey(uint32_t key, int len) {
+ uint32_t step = 1 << (len - 1);
+ while (key & step) {
+ step >>= 1;
+ }
+ return (key & (step - 1)) + step;
}
-static int TreeInit(HuffmanTree* const tree, int num_leaves) {
- assert(tree != NULL);
- if (num_leaves == 0) return 0;
- // We allocate maximum possible nodes in the tree at once.
- // Note that a Huffman tree is a full binary tree; and in a full binary tree
- // with L leaves, the total number of nodes N = 2 * L - 1.
- tree->max_nodes_ = 2 * num_leaves - 1;
- tree->root_ = (HuffmanTreeNode*)WebPSafeMalloc((uint64_t)tree->max_nodes_,
- sizeof(*tree->root_));
- if (tree->root_ == NULL) return 0;
- TreeNodeInit(tree->root_); // Initialize root.
- tree->num_nodes_ = 1;
- return 1;
+// Stores code in table[0], table[step], table[2*step], ..., table[end].
+// Assumes that end is an integer multiple of step.
+static WEBP_INLINE void ReplicateValue(HuffmanCode* table,
+ int step, int end,
+ HuffmanCode code) {
+ assert(end % step == 0);
+ do {
+ end -= step;
+ table[end] = code;
+ } while (end > 0);
}
-void HuffmanTreeRelease(HuffmanTree* const tree) {
- if (tree != NULL) {
- free(tree->root_);
- tree->root_ = NULL;
- tree->max_nodes_ = 0;
- tree->num_nodes_ = 0;
+// Returns the table width of the next 2nd level table. count is the histogram
+// of bit lengths for the remaining symbols, len is the code length of the next
+// processed symbol
+static WEBP_INLINE int NextTableBitSize(const int* const count,
+ int len, int root_bits) {
+ int left = 1 << (len - root_bits);
+ while (len < MAX_ALLOWED_CODE_LENGTH) {
+ left -= count[len];
+ if (left <= 0) break;
+ ++len;
+ left <<= 1;
}
+ return len - root_bits;
}
-int HuffmanCodeLengthsToCodes(const int* const code_lengths,
- int code_lengths_size, int* const huff_codes) {
- int symbol;
- int code_len;
- int code_length_hist[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 };
- int curr_code;
- int next_codes[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 };
- int max_code_length = 0;
-
+int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
+ const int code_lengths[], int code_lengths_size) {
+ HuffmanCode* table = root_table; // next available space in table
+ int total_size = 1 << root_bits; // total size root table + 2nd level table
+ int* sorted = NULL; // symbols sorted by code length
+ int len; // current code length
+ int symbol; // symbol index in original or sorted table
+ // number of codes of each length:
+ int count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 };
+ // offsets in sorted table for each length:
+ int offset[MAX_ALLOWED_CODE_LENGTH + 1];
+
+ assert(code_lengths_size != 0);
assert(code_lengths != NULL);
- assert(code_lengths_size > 0);
- assert(huff_codes != NULL);
+ assert(root_table != NULL);
+ assert(root_bits > 0);
- // Calculate max code length.
+ // Build histogram of code lengths.
for (symbol = 0; symbol < code_lengths_size; ++symbol) {
- if (code_lengths[symbol] > max_code_length) {
- max_code_length = code_lengths[symbol];
+ if (code_lengths[symbol] > MAX_ALLOWED_CODE_LENGTH) {
+ return 0;
}
+ ++count[code_lengths[symbol]];
}
- if (max_code_length > MAX_ALLOWED_CODE_LENGTH) return 0;
- // Calculate code length histogram.
- for (symbol = 0; symbol < code_lengths_size; ++symbol) {
- ++code_length_hist[code_lengths[symbol]];
- }
- code_length_hist[0] = 0;
-
- // Calculate the initial values of 'next_codes' for each code length.
- // next_codes[code_len] denotes the code to be assigned to the next symbol
- // of code length 'code_len'.
- curr_code = 0;
- next_codes[0] = -1; // Unused, as code length = 0 implies code doesn't exist.
- for (code_len = 1; code_len <= max_code_length; ++code_len) {
- curr_code = (curr_code + code_length_hist[code_len - 1]) << 1;
- next_codes[code_len] = curr_code;
+ // Error, all code lengths are zeros.
+ if (count[0] == code_lengths_size) {
+ return 0;
}
- // Get symbols.
- for (symbol = 0; symbol < code_lengths_size; ++symbol) {
- if (code_lengths[symbol] > 0) {
- huff_codes[symbol] = next_codes[code_lengths[symbol]]++;
- } else {
- huff_codes[symbol] = NON_EXISTENT_SYMBOL;
- }
- }
- return 1;
-}
-
-static int TreeAddSymbol(HuffmanTree* const tree,
- int symbol, int code, int code_length) {
- HuffmanTreeNode* node = tree->root_;
- const HuffmanTreeNode* const max_node = tree->root_ + tree->max_nodes_;
- while (code_length-- > 0) {
- if (node >= max_node) {
+ // Generate offsets into sorted symbol table by code length.
+ offset[1] = 0;
+ for (len = 1; len < MAX_ALLOWED_CODE_LENGTH; ++len) {
+ if (count[len] > (1 << len)) {
return 0;
}
- if (NodeIsEmpty(node)) {
- if (IsFull(tree)) return 0; // error: too many symbols.
- AssignChildren(tree, node);
- } else if (HuffmanTreeNodeIsLeaf(node)) {
- return 0; // leaf is already occupied.
- }
- node += node->children_ + ((code >> code_length) & 1);
- }
- if (NodeIsEmpty(node)) {
- node->children_ = 0; // turn newly created node into a leaf.
- } else if (!HuffmanTreeNodeIsLeaf(node)) {
- return 0; // trying to assign a symbol to already used code.
+ offset[len + 1] = offset[len] + count[len];
}
- node->symbol_ = symbol; // Add symbol in this node.
- return 1;
-}
-int HuffmanTreeBuildImplicit(HuffmanTree* const tree,
- const int* const code_lengths,
- int code_lengths_size) {
- int symbol;
- int num_symbols = 0;
- int root_symbol = 0;
-
- assert(tree != NULL);
- assert(code_lengths != NULL);
+ sorted = (int*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
+ if (sorted == NULL) {
+ return 0;
+ }
- // Find out number of symbols and the root symbol.
+ // Sort symbols by length, by symbol order within each length.
for (symbol = 0; symbol < code_lengths_size; ++symbol) {
+ const int symbol_code_length = code_lengths[symbol];
if (code_lengths[symbol] > 0) {
- // Note: code length = 0 indicates non-existent symbol.
- ++num_symbols;
- root_symbol = symbol;
+ sorted[offset[symbol_code_length]++] = symbol;
}
}
- // Initialize the tree. Will fail for num_symbols = 0
- if (!TreeInit(tree, num_symbols)) return 0;
-
- // Build tree.
- if (num_symbols == 1) { // Trivial case.
- const int max_symbol = code_lengths_size;
- if (root_symbol < 0 || root_symbol >= max_symbol) {
- HuffmanTreeRelease(tree);
- return 0;
- }
- return TreeAddSymbol(tree, root_symbol, 0, 0);
- } else { // Normal case.
- int ok = 0;
-
- // Get Huffman codes from the code lengths.
- int* const codes =
- (int*)WebPSafeMalloc((uint64_t)code_lengths_size, sizeof(*codes));
- if (codes == NULL) goto End;
+ // Special case code with only one value.
+ if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) {
+ HuffmanCode code;
+ code.bits = 0;
+ code.value = (uint16_t)sorted[0];
+ ReplicateValue(table, 1, total_size, code);
+ WebPSafeFree(sorted);
+ return total_size;
+ }
- if (!HuffmanCodeLengthsToCodes(code_lengths, code_lengths_size, codes)) {
- goto End;
+ {
+ int step; // step size to replicate values in current table
+ uint32_t low = -1; // low bits for current root entry
+ uint32_t mask = total_size - 1; // mask for low bits
+ uint32_t key = 0; // reversed prefix code
+ int num_nodes = 1; // number of Huffman tree nodes
+ int num_open = 1; // number of open branches in current tree level
+ int table_bits = root_bits; // key length of current table
+ int table_size = 1 << table_bits; // size of current table
+ symbol = 0;
+ // Fill in root table.
+ for (len = 1, step = 2; len <= root_bits; ++len, step <<= 1) {
+ num_open <<= 1;
+ num_nodes += num_open;
+ num_open -= count[len];
+ if (num_open < 0) {
+ WebPSafeFree(sorted);
+ return 0;
+ }
+ for (; count[len] > 0; --count[len]) {
+ HuffmanCode code;
+ code.bits = (uint8_t)len;
+ code.value = (uint16_t)sorted[symbol++];
+ ReplicateValue(&table[key], step, table_size, code);
+ key = GetNextKey(key, len);
+ }
}
- // Add symbols one-by-one.
- for (symbol = 0; symbol < code_lengths_size; ++symbol) {
- if (code_lengths[symbol] > 0) {
- if (!TreeAddSymbol(tree, symbol, codes[symbol], code_lengths[symbol])) {
- goto End;
+ // Fill in 2nd level tables and add pointers to root table.
+ for (len = root_bits + 1, step = 2; len <= MAX_ALLOWED_CODE_LENGTH;
+ ++len, step <<= 1) {
+ num_open <<= 1;
+ num_nodes += num_open;
+ num_open -= count[len];
+ if (num_open < 0) {
+ WebPSafeFree(sorted);
+ return 0;
+ }
+ for (; count[len] > 0; --count[len]) {
+ HuffmanCode code;
+ if ((key & mask) != low) {
+ table += table_size;
+ table_bits = NextTableBitSize(count, len, root_bits);
+ table_size = 1 << table_bits;
+ total_size += table_size;
+ low = key & mask;
+ root_table[low].bits = (uint8_t)(table_bits + root_bits);
+ root_table[low].value = (uint16_t)((table - root_table) - low);
}
+ code.bits = (uint8_t)(len - root_bits);
+ code.value = (uint16_t)sorted[symbol++];
+ ReplicateValue(&table[key >> root_bits], step, table_size, code);
+ key = GetNextKey(key, len);
}
}
- ok = 1;
- End:
- free(codes);
- ok = ok && IsFull(tree);
- if (!ok) HuffmanTreeRelease(tree);
- return ok;
- }
-}
-
-int HuffmanTreeBuildExplicit(HuffmanTree* const tree,
- const int* const code_lengths,
- const int* const codes,
- const int* const symbols, int max_symbol,
- int num_symbols) {
- int ok = 0;
- int i;
-
- assert(tree != NULL);
- assert(code_lengths != NULL);
- assert(codes != NULL);
- assert(symbols != NULL);
-
- // Initialize the tree. Will fail if num_symbols = 0.
- if (!TreeInit(tree, num_symbols)) return 0;
- // Add symbols one-by-one.
- for (i = 0; i < num_symbols; ++i) {
- if (codes[i] != NON_EXISTENT_SYMBOL) {
- if (symbols[i] < 0 || symbols[i] >= max_symbol) {
- goto End;
- }
- if (!TreeAddSymbol(tree, symbols[i], codes[i], code_lengths[i])) {
- goto End;
- }
+ // Check if tree is full.
+ if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) {
+ WebPSafeFree(sorted);
+ return 0;
}
}
- ok = 1;
- End:
- ok = ok && IsFull(tree);
- if (!ok) HuffmanTreeRelease(tree);
- return ok;
-}
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
+ WebPSafeFree(sorted);
+ return total_size;
+}
diff --git a/drivers/webp/utils/huffman.h b/drivers/webp/utils/huffman.h
index f16447e649..a8cc0da1c3 100644
--- a/drivers/webp/utils/huffman.h
+++ b/drivers/webp/utils/huffman.h
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Utilities for building and looking up Huffman trees.
@@ -13,65 +15,73 @@
#define WEBP_UTILS_HUFFMAN_H_
#include <assert.h>
-#include "../types.h"
+#include "webp/format_constants.h"
+#include "webp/types.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
-// A node of a Huffman tree.
-typedef struct {
- int symbol_;
- int children_; // delta offset to both children (contiguous) or 0 if leaf.
-} HuffmanTreeNode;
+#define HUFFMAN_TABLE_BITS 8
+#define HUFFMAN_TABLE_MASK ((1 << HUFFMAN_TABLE_BITS) - 1)
+
+#define LENGTHS_TABLE_BITS 7
+#define LENGTHS_TABLE_MASK ((1 << LENGTHS_TABLE_BITS) - 1)
-// Huffman Tree.
-typedef struct HuffmanTree HuffmanTree;
-struct HuffmanTree {
- HuffmanTreeNode* root_; // all the nodes, starting at root.
- int max_nodes_; // max number of nodes
- int num_nodes_; // number of currently occupied nodes
-};
-// Returns true if the given node is a leaf of the Huffman tree.
-static WEBP_INLINE int HuffmanTreeNodeIsLeaf(
- const HuffmanTreeNode* const node) {
- return (node->children_ == 0);
-}
+// Huffman lookup table entry
+typedef struct {
+ uint8_t bits; // number of bits used for this symbol
+ uint16_t value; // symbol value or table offset
+} HuffmanCode;
-// Go down one level. Most critical function. 'right_child' must be 0 or 1.
-static WEBP_INLINE const HuffmanTreeNode* HuffmanTreeNextNode(
- const HuffmanTreeNode* node, int right_child) {
- return node + node->children_ + right_child;
-}
+// long version for holding 32b values
+typedef struct {
+ int bits; // number of bits used for this symbol,
+ // or an impossible value if not a literal code.
+ uint32_t value; // 32b packed ARGB value if literal,
+ // or non-literal symbol otherwise
+} HuffmanCode32;
-// Releases the nodes of the Huffman tree.
-// Note: It does NOT free 'tree' itself.
-void HuffmanTreeRelease(HuffmanTree* const tree);
+#define HUFFMAN_PACKED_BITS 6
+#define HUFFMAN_PACKED_TABLE_SIZE (1u << HUFFMAN_PACKED_BITS)
-// Builds Huffman tree assuming code lengths are implicitly in symbol order.
-// Returns false in case of error (invalid tree or memory error).
-int HuffmanTreeBuildImplicit(HuffmanTree* const tree,
- const int* const code_lengths,
- int code_lengths_size);
+// Huffman table group.
+// Includes special handling for the following cases:
+// - is_trivial_literal: one common literal base for RED/BLUE/ALPHA (not GREEN)
+// - is_trivial_code: only 1 code (no bit is read from bitstream)
+// - use_packed_table: few enough literal symbols, so all the bit codes
+// can fit into a small look-up table packed_table[]
+// The common literal base, if applicable, is stored in 'literal_arb'.
+typedef struct HTreeGroup HTreeGroup;
+struct HTreeGroup {
+ HuffmanCode* htrees[HUFFMAN_CODES_PER_META_CODE];
+ int is_trivial_literal; // True, if huffman trees for Red, Blue & Alpha
+ // Symbols are trivial (have a single code).
+ uint32_t literal_arb; // If is_trivial_literal is true, this is the
+ // ARGB value of the pixel, with Green channel
+ // being set to zero.
+ int is_trivial_code; // true if is_trivial_literal with only one code
+ int use_packed_table; // use packed table below for short literal code
+ // table mapping input bits to a packed values, or escape case to literal code
+ HuffmanCode32 packed_table[HUFFMAN_PACKED_TABLE_SIZE];
+};
-// Build a Huffman tree with explicitly given lists of code lengths, codes
-// and symbols. Verifies that all symbols added are smaller than max_symbol.
-// Returns false in case of an invalid symbol, invalid tree or memory error.
-int HuffmanTreeBuildExplicit(HuffmanTree* const tree,
- const int* const code_lengths,
- const int* const codes,
- const int* const symbols, int max_symbol,
- int num_symbols);
+// Creates the instance of HTreeGroup with specified number of tree-groups.
+HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups);
-// Utility: converts Huffman code lengths to corresponding Huffman codes.
-// 'huff_codes' should be pre-allocated.
-// Returns false in case of error (memory allocation, invalid codes).
-int HuffmanCodeLengthsToCodes(const int* const code_lengths,
- int code_lengths_size, int* const huff_codes);
+// Releases the memory allocated for HTreeGroup.
+void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups);
+// Builds Huffman lookup table assuming code lengths are in symbol order.
+// The 'code_lengths' is pre-allocated temporary memory buffer used for creating
+// the huffman table.
+// Returns built table size or 0 in case of error (invalid tree or
+// memory error).
+int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
+ const int code_lengths[], int code_lengths_size);
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/utils/huffman_encode.c b/drivers/webp/utils/huffman_encode.c
index e172b10a85..d7aad6f56d 100644
--- a/drivers/webp/utils/huffman_encode.c
+++ b/drivers/webp/utils/huffman_encode.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Author: Jyrki Alakuijala (jyrki@google.com)
@@ -14,7 +16,7 @@
#include <string.h>
#include "./huffman_encode.h"
#include "../utils/utils.h"
-#include "../format_constants.h"
+#include "webp/format_constants.h"
// -----------------------------------------------------------------------------
// Util function to optimize the symbol map for RLE coding
@@ -25,14 +27,14 @@ static int ValuesShouldBeCollapsedToStrideAverage(int a, int b) {
}
// Change the population counts in a way that the consequent
-// Hufmann tree compression, especially its RLE-part, give smaller output.
-static int OptimizeHuffmanForRle(int length, int* const counts) {
- uint8_t* good_for_rle;
+// Huffman tree compression, especially its RLE-part, give smaller output.
+static void OptimizeHuffmanForRle(int length, uint8_t* const good_for_rle,
+ uint32_t* const counts) {
// 1) Let's make the Huffman code more compatible with rle encoding.
int i;
for (; length >= 0; --length) {
if (length == 0) {
- return 1; // All zeros.
+ return; // All zeros.
}
if (counts[length - 1] != 0) {
// Now counts[0..length - 1] does not have trailing zeros.
@@ -41,15 +43,11 @@ static int OptimizeHuffmanForRle(int length, int* const counts) {
}
// 2) Let's mark all population counts that already can be encoded
// with an rle code.
- good_for_rle = (uint8_t*)calloc(length, 1);
- if (good_for_rle == NULL) {
- return 0;
- }
{
// Let's not spoil any of the existing good rle codes.
// Mark any seq of 0's that is longer as 5 as a good_for_rle.
// Mark any seq of non-0's that is longer as 7 as a good_for_rle.
- int symbol = counts[0];
+ uint32_t symbol = counts[0];
int stride = 0;
for (i = 0; i < length + 1; ++i) {
if (i == length || counts[i] != symbol) {
@@ -71,17 +69,17 @@ static int OptimizeHuffmanForRle(int length, int* const counts) {
}
// 3) Let's replace those population counts that lead to more rle codes.
{
- int stride = 0;
- int limit = counts[0];
- int sum = 0;
+ uint32_t stride = 0;
+ uint32_t limit = counts[0];
+ uint32_t sum = 0;
for (i = 0; i < length + 1; ++i) {
if (i == length || good_for_rle[i] ||
(i != 0 && good_for_rle[i - 1]) ||
!ValuesShouldBeCollapsedToStrideAverage(counts[i], limit)) {
if (stride >= 4 || (stride >= 3 && sum == 0)) {
- int k;
+ uint32_t k;
// The stride must end, collapse what we have, if we have enough (4).
- int count = (sum + stride / 2) / stride;
+ uint32_t count = (sum + stride / 2) / stride;
if (count < 1) {
count = 1;
}
@@ -117,17 +115,8 @@ static int OptimizeHuffmanForRle(int length, int* const counts) {
}
}
}
- free(good_for_rle);
- return 1;
}
-typedef struct {
- int total_count_;
- int value_;
- int pool_index_left_;
- int pool_index_right_;
-} HuffmanTree;
-
// A comparer function for two Huffman trees: sorts first by 'total count'
// (more comes first), and then by 'value' (more comes first).
static int CompareHuffmanTrees(const void* ptr1, const void* ptr2) {
@@ -138,13 +127,8 @@ static int CompareHuffmanTrees(const void* ptr1, const void* ptr2) {
} else if (t1->total_count_ < t2->total_count_) {
return 1;
} else {
- if (t1->value_ < t2->value_) {
- return -1;
- }
- if (t1->value_ > t2->value_) {
- return 1;
- }
- return 0;
+ assert(t1->value_ != t2->value_);
+ return (t1->value_ < t2->value_) ? -1 : 1;
}
}
@@ -178,12 +162,12 @@ static void SetBitDepths(const HuffmanTree* const tree,
// we are not planning to use this with extremely long blocks.
//
// See http://en.wikipedia.org/wiki/Huffman_coding
-static int GenerateOptimalTree(const int* const histogram, int histogram_size,
- int tree_depth_limit,
- uint8_t* const bit_depths) {
- int count_min;
+static void GenerateOptimalTree(const uint32_t* const histogram,
+ int histogram_size,
+ HuffmanTree* tree, int tree_depth_limit,
+ uint8_t* const bit_depths) {
+ uint32_t count_min;
HuffmanTree* tree_pool;
- HuffmanTree* tree;
int tree_size_orig = 0;
int i;
@@ -193,12 +177,10 @@ static int GenerateOptimalTree(const int* const histogram, int histogram_size,
}
}
- // 3 * tree_size is enough to cover all the nodes representing a
- // population and all the inserted nodes combining two existing nodes.
- // The tree pool needs 2 * (tree_size_orig - 1) entities, and the
- // tree needs exactly tree_size_orig entities.
- tree = (HuffmanTree*)WebPSafeMalloc(3ULL * tree_size_orig, sizeof(*tree));
- if (tree == NULL) return 0;
+ if (tree_size_orig == 0) { // pretty optimal already!
+ return;
+ }
+
tree_pool = tree + tree_size_orig;
// For block sizes with less than 64k symbols we never need to do a
@@ -214,7 +196,7 @@ static int GenerateOptimalTree(const int* const histogram, int histogram_size,
int j;
for (j = 0; j < histogram_size; ++j) {
if (histogram[j] != 0) {
- const int count =
+ const uint32_t count =
(histogram[j] < count_min) ? count_min : histogram[j];
tree[idx].total_count_ = count;
tree[idx].value_ = j;
@@ -230,11 +212,11 @@ static int GenerateOptimalTree(const int* const histogram, int histogram_size,
if (tree_size > 1) { // Normal case.
int tree_pool_size = 0;
while (tree_size > 1) { // Finish when we have only one root.
- int count;
+ uint32_t count;
tree_pool[tree_pool_size++] = tree[tree_size - 1];
tree_pool[tree_pool_size++] = tree[tree_size - 2];
count = tree_pool[tree_pool_size - 1].total_count_ +
- tree_pool[tree_pool_size - 2].total_count_;
+ tree_pool[tree_pool_size - 2].total_count_;
tree_size -= 2;
{
// Search for the insertion point.
@@ -271,8 +253,6 @@ static int GenerateOptimalTree(const int* const histogram, int histogram_size,
}
}
}
- free(tree);
- return 1;
}
// -----------------------------------------------------------------------------
@@ -423,17 +403,15 @@ static void ConvertBitDepthsToSymbols(HuffmanTreeCode* const tree) {
// -----------------------------------------------------------------------------
// Main entry point
-int VP8LCreateHuffmanTree(int* const histogram, int tree_depth_limit,
- HuffmanTreeCode* const tree) {
- const int num_symbols = tree->num_symbols;
- if (!OptimizeHuffmanForRle(num_symbols, histogram)) {
- return 0;
- }
- if (!GenerateOptimalTree(histogram, num_symbols,
- tree_depth_limit, tree->code_lengths)) {
- return 0;
- }
+void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit,
+ uint8_t* const buf_rle,
+ HuffmanTree* const huff_tree,
+ HuffmanTreeCode* const huff_code) {
+ const int num_symbols = huff_code->num_symbols;
+ memset(buf_rle, 0, num_symbols * sizeof(*buf_rle));
+ OptimizeHuffmanForRle(num_symbols, buf_rle, histogram);
+ GenerateOptimalTree(histogram, num_symbols, huff_tree, tree_depth_limit,
+ huff_code->code_lengths);
// Create the actual bit codes for the bit lengths.
- ConvertBitDepthsToSymbols(tree);
- return 1;
+ ConvertBitDepthsToSymbols(huff_code);
}
diff --git a/drivers/webp/utils/huffman_encode.h b/drivers/webp/utils/huffman_encode.h
index 7f4aedc102..93610066f3 100644
--- a/drivers/webp/utils/huffman_encode.h
+++ b/drivers/webp/utils/huffman_encode.h
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Author: Jyrki Alakuijala (jyrki@google.com)
@@ -12,9 +14,9 @@
#ifndef WEBP_UTILS_HUFFMAN_ENCODE_H_
#define WEBP_UTILS_HUFFMAN_ENCODE_H_
-#include "../types.h"
+#include "webp/types.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
@@ -31,16 +33,27 @@ typedef struct {
uint16_t* codes; // Symbol Codes.
} HuffmanTreeCode;
+// Struct to represent the Huffman tree.
+typedef struct {
+ uint32_t total_count_; // Symbol frequency.
+ int value_; // Symbol value.
+ int pool_index_left_; // Index for the left sub-tree.
+ int pool_index_right_; // Index for the right sub-tree.
+} HuffmanTree;
+
// Turn the Huffman tree into a token sequence.
// Returns the number of tokens used.
int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree,
HuffmanTreeToken* tokens, int max_tokens);
// Create an optimized tree, and tokenize it.
-int VP8LCreateHuffmanTree(int* const histogram, int tree_depth_limit,
- HuffmanTreeCode* const tree);
+// 'buf_rle' and 'huff_tree' are pre-allocated and the 'tree' is the constructed
+// huffman code tree.
+void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit,
+ uint8_t* const buf_rle, HuffmanTree* const huff_tree,
+ HuffmanTreeCode* const tree);
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
}
#endif
diff --git a/drivers/webp/utils/quant_levels.c b/drivers/webp/utils/quant_levels.c
index f6884392aa..d7c8aab922 100644
--- a/drivers/webp/utils/quant_levels.c
+++ b/drivers/webp/utils/quant_levels.c
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Quantize levels for specified number of quantization-levels ([2, 256]).
@@ -14,10 +16,6 @@
#include "./quant_levels.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
#define NUM_SYMBOLS 256
#define MAX_ITER 6 // Maximum number of convergence steps.
@@ -140,15 +138,3 @@ int QuantizeLevels(uint8_t* const data, int width, int height,
return 1;
}
-int DequantizeLevels(uint8_t* const data, int width, int height) {
- if (data == NULL || width <= 0 || height <= 0) return 0;
- // TODO(skal): implement gradient smoothing.
- (void)data;
- (void)width;
- (void)height;
- return 1;
-}
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/utils/quant_levels.h b/drivers/webp/utils/quant_levels.h
index 4f165fd230..3916b977ab 100644
--- a/drivers/webp/utils/quant_levels.h
+++ b/drivers/webp/utils/quant_levels.h
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Alpha plane quantization utility
@@ -14,9 +16,9 @@
#include <stdlib.h>
-#include "../types.h"
+#include "webp/types.h"
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
@@ -27,12 +29,7 @@ extern "C" {
int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels,
uint64_t* const sse);
-// Apply post-processing to input 'data' of size 'width'x'height' assuming
-// that the source was quantized to a reduced number of levels.
-// Returns false in case of error (data is NULL, invalid parameters, ...).
-int DequantizeLevels(uint8_t* const data, int width, int height);
-
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/utils/quant_levels_dec.c b/drivers/webp/utils/quant_levels_dec.c
new file mode 100644
index 0000000000..5b8b8b49e6
--- /dev/null
+++ b/drivers/webp/utils/quant_levels_dec.c
@@ -0,0 +1,279 @@
+// Copyright 2013 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Implement gradient smoothing: we replace a current alpha value by its
+// surrounding average if it's close enough (that is: the change will be less
+// than the minimum distance between two quantized level).
+// We use sliding window for computing the 2d moving average.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./quant_levels_dec.h"
+
+#include <string.h> // for memset
+
+#include "./utils.h"
+
+// #define USE_DITHERING // uncomment to enable ordered dithering (not vital)
+
+#define FIX 16 // fix-point precision for averaging
+#define LFIX 2 // extra precision for look-up table
+#define LUT_SIZE ((1 << (8 + LFIX)) - 1) // look-up table size
+
+#if defined(USE_DITHERING)
+
+#define DFIX 4 // extra precision for ordered dithering
+#define DSIZE 4 // dithering size (must be a power of two)
+// cf. http://en.wikipedia.org/wiki/Ordered_dithering
+static const uint8_t kOrderedDither[DSIZE][DSIZE] = {
+ { 0, 8, 2, 10 }, // coefficients are in DFIX fixed-point precision
+ { 12, 4, 14, 6 },
+ { 3, 11, 1, 9 },
+ { 15, 7, 13, 5 }
+};
+
+#else
+#define DFIX 0
+#endif
+
+typedef struct {
+ int width_, height_; // dimension
+ int row_; // current input row being processed
+ uint8_t* src_; // input pointer
+ uint8_t* dst_; // output pointer
+
+ int radius_; // filter radius (=delay)
+ int scale_; // normalization factor, in FIX bits precision
+
+ void* mem_; // all memory
+
+ // various scratch buffers
+ uint16_t* start_;
+ uint16_t* cur_;
+ uint16_t* end_;
+ uint16_t* top_;
+ uint16_t* average_;
+
+ // input levels distribution
+ int num_levels_; // number of quantized levels
+ int min_, max_; // min and max level values
+ int min_level_dist_; // smallest distance between two consecutive levels
+
+ int16_t* correction_; // size = 1 + 2*LUT_SIZE -> ~4k memory
+} SmoothParams;
+
+//------------------------------------------------------------------------------
+
+#define CLIP_MASK (int)(~0U << (8 + DFIX))
+static WEBP_INLINE uint8_t clip_8b(int v) {
+ return (!(v & CLIP_MASK)) ? (uint8_t)(v >> DFIX) : (v < 0) ? 0u : 255u;
+}
+
+// vertical accumulation
+static void VFilter(SmoothParams* const p) {
+ const uint8_t* src = p->src_;
+ const int w = p->width_;
+ uint16_t* const cur = p->cur_;
+ const uint16_t* const top = p->top_;
+ uint16_t* const out = p->end_;
+ uint16_t sum = 0; // all arithmetic is modulo 16bit
+ int x;
+
+ for (x = 0; x < w; ++x) {
+ uint16_t new_value;
+ sum += src[x];
+ new_value = top[x] + sum;
+ out[x] = new_value - cur[x]; // vertical sum of 'r' pixels.
+ cur[x] = new_value;
+ }
+ // move input pointers one row down
+ p->top_ = p->cur_;
+ p->cur_ += w;
+ if (p->cur_ == p->end_) p->cur_ = p->start_; // roll-over
+ // We replicate edges, as it's somewhat easier as a boundary condition.
+ // That's why we don't update the 'src' pointer on top/bottom area:
+ if (p->row_ >= 0 && p->row_ < p->height_ - 1) {
+ p->src_ += p->width_;
+ }
+}
+
+// horizontal accumulation. We use mirror replication of missing pixels, as it's
+// a little easier to implement (surprisingly).
+static void HFilter(SmoothParams* const p) {
+ const uint16_t* const in = p->end_;
+ uint16_t* const out = p->average_;
+ const uint32_t scale = p->scale_;
+ const int w = p->width_;
+ const int r = p->radius_;
+
+ int x;
+ for (x = 0; x <= r; ++x) { // left mirroring
+ const uint16_t delta = in[x + r - 1] + in[r - x];
+ out[x] = (delta * scale) >> FIX;
+ }
+ for (; x < w - r; ++x) { // bulk middle run
+ const uint16_t delta = in[x + r] - in[x - r - 1];
+ out[x] = (delta * scale) >> FIX;
+ }
+ for (; x < w; ++x) { // right mirroring
+ const uint16_t delta =
+ 2 * in[w - 1] - in[2 * w - 2 - r - x] - in[x - r - 1];
+ out[x] = (delta * scale) >> FIX;
+ }
+}
+
+// emit one filtered output row
+static void ApplyFilter(SmoothParams* const p) {
+ const uint16_t* const average = p->average_;
+ const int w = p->width_;
+ const int16_t* const correction = p->correction_;
+#if defined(USE_DITHERING)
+ const uint8_t* const dither = kOrderedDither[p->row_ % DSIZE];
+#endif
+ uint8_t* const dst = p->dst_;
+ int x;
+ for (x = 0; x < w; ++x) {
+ const int v = dst[x];
+ if (v < p->max_ && v > p->min_) {
+ const int c = (v << DFIX) + correction[average[x] - (v << LFIX)];
+#if defined(USE_DITHERING)
+ dst[x] = clip_8b(c + dither[x % DSIZE]);
+#else
+ dst[x] = clip_8b(c);
+#endif
+ }
+ }
+ p->dst_ += w; // advance output pointer
+}
+
+//------------------------------------------------------------------------------
+// Initialize correction table
+
+static void InitCorrectionLUT(int16_t* const lut, int min_dist) {
+ // The correction curve is:
+ // f(x) = x for x <= threshold2
+ // f(x) = 0 for x >= threshold1
+ // and a linear interpolation for range x=[threshold2, threshold1]
+ // (along with f(-x) = -f(x) symmetry).
+ // Note that: threshold2 = 3/4 * threshold1
+ const int threshold1 = min_dist << LFIX;
+ const int threshold2 = (3 * threshold1) >> 2;
+ const int max_threshold = threshold2 << DFIX;
+ const int delta = threshold1 - threshold2;
+ int i;
+ for (i = 1; i <= LUT_SIZE; ++i) {
+ int c = (i <= threshold2) ? (i << DFIX)
+ : (i < threshold1) ? max_threshold * (threshold1 - i) / delta
+ : 0;
+ c >>= LFIX;
+ lut[+i] = +c;
+ lut[-i] = -c;
+ }
+ lut[0] = 0;
+}
+
+static void CountLevels(const uint8_t* const data, int size,
+ SmoothParams* const p) {
+ int i, last_level;
+ uint8_t used_levels[256] = { 0 };
+ p->min_ = 255;
+ p->max_ = 0;
+ for (i = 0; i < size; ++i) {
+ const int v = data[i];
+ if (v < p->min_) p->min_ = v;
+ if (v > p->max_) p->max_ = v;
+ used_levels[v] = 1;
+ }
+ // Compute the mininum distance between two non-zero levels.
+ p->min_level_dist_ = p->max_ - p->min_;
+ last_level = -1;
+ for (i = 0; i < 256; ++i) {
+ if (used_levels[i]) {
+ ++p->num_levels_;
+ if (last_level >= 0) {
+ const int level_dist = i - last_level;
+ if (level_dist < p->min_level_dist_) {
+ p->min_level_dist_ = level_dist;
+ }
+ }
+ last_level = i;
+ }
+ }
+}
+
+// Initialize all params.
+static int InitParams(uint8_t* const data, int width, int height,
+ int radius, SmoothParams* const p) {
+ const int R = 2 * radius + 1; // total size of the kernel
+
+ const size_t size_scratch_m = (R + 1) * width * sizeof(*p->start_);
+ const size_t size_m = width * sizeof(*p->average_);
+ const size_t size_lut = (1 + 2 * LUT_SIZE) * sizeof(*p->correction_);
+ const size_t total_size = size_scratch_m + size_m + size_lut;
+ uint8_t* mem = (uint8_t*)WebPSafeMalloc(1U, total_size);
+
+ if (mem == NULL) return 0;
+ p->mem_ = (void*)mem;
+
+ p->start_ = (uint16_t*)mem;
+ p->cur_ = p->start_;
+ p->end_ = p->start_ + R * width;
+ p->top_ = p->end_ - width;
+ memset(p->top_, 0, width * sizeof(*p->top_));
+ mem += size_scratch_m;
+
+ p->average_ = (uint16_t*)mem;
+ mem += size_m;
+
+ p->width_ = width;
+ p->height_ = height;
+ p->src_ = data;
+ p->dst_ = data;
+ p->radius_ = radius;
+ p->scale_ = (1 << (FIX + LFIX)) / (R * R); // normalization constant
+ p->row_ = -radius;
+
+ // analyze the input distribution so we can best-fit the threshold
+ CountLevels(data, width * height, p);
+
+ // correction table
+ p->correction_ = ((int16_t*)mem) + LUT_SIZE;
+ InitCorrectionLUT(p->correction_, p->min_level_dist_);
+
+ return 1;
+}
+
+static void CleanupParams(SmoothParams* const p) {
+ WebPSafeFree(p->mem_);
+}
+
+int WebPDequantizeLevels(uint8_t* const data, int width, int height,
+ int strength) {
+ const int radius = 4 * strength / 100;
+ if (strength < 0 || strength > 100) return 0;
+ if (data == NULL || width <= 0 || height <= 0) return 0; // bad params
+ if (radius > 0) {
+ SmoothParams p;
+ memset(&p, 0, sizeof(p));
+ if (!InitParams(data, width, height, radius, &p)) return 0;
+ if (p.num_levels_ > 2) {
+ for (; p.row_ < p.height_; ++p.row_) {
+ VFilter(&p); // accumulate average of input
+ // Need to wait few rows in order to prime the filter,
+ // before emitting some output.
+ if (p.row_ >= p.radius_) {
+ HFilter(&p);
+ ApplyFilter(&p);
+ }
+ }
+ }
+ CleanupParams(&p);
+ }
+ return 1;
+}
diff --git a/drivers/webp/utils/quant_levels_dec.h b/drivers/webp/utils/quant_levels_dec.h
new file mode 100644
index 0000000000..29c7e6e205
--- /dev/null
+++ b/drivers/webp/utils/quant_levels_dec.h
@@ -0,0 +1,35 @@
+// Copyright 2013 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Alpha plane de-quantization utility
+//
+// Author: Vikas Arora (vikasa@google.com)
+
+#ifndef WEBP_UTILS_QUANT_LEVELS_DEC_H_
+#define WEBP_UTILS_QUANT_LEVELS_DEC_H_
+
+#include "webp/types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Apply post-processing to input 'data' of size 'width'x'height' assuming that
+// the source was quantized to a reduced number of levels.
+// Strength is in [0..100] and controls the amount of dithering applied.
+// Returns false in case of error (data is NULL, invalid parameters,
+// malloc failure, ...).
+int WebPDequantizeLevels(uint8_t* const data, int width, int height,
+ int strength);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_H_ */
diff --git a/drivers/webp/utils/random.c b/drivers/webp/utils/random.c
new file mode 100644
index 0000000000..24e96ad648
--- /dev/null
+++ b/drivers/webp/utils/random.c
@@ -0,0 +1,43 @@
+// Copyright 2013 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Pseudo-random utilities
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <string.h>
+#include "./random.h"
+
+//------------------------------------------------------------------------------
+
+// 31b-range values
+static const uint32_t kRandomTable[VP8_RANDOM_TABLE_SIZE] = {
+ 0x0de15230, 0x03b31886, 0x775faccb, 0x1c88626a, 0x68385c55, 0x14b3b828,
+ 0x4a85fef8, 0x49ddb84b, 0x64fcf397, 0x5c550289, 0x4a290000, 0x0d7ec1da,
+ 0x5940b7ab, 0x5492577d, 0x4e19ca72, 0x38d38c69, 0x0c01ee65, 0x32a1755f,
+ 0x5437f652, 0x5abb2c32, 0x0faa57b1, 0x73f533e7, 0x685feeda, 0x7563cce2,
+ 0x6e990e83, 0x4730a7ed, 0x4fc0d9c6, 0x496b153c, 0x4f1403fa, 0x541afb0c,
+ 0x73990b32, 0x26d7cb1c, 0x6fcc3706, 0x2cbb77d8, 0x75762f2a, 0x6425ccdd,
+ 0x24b35461, 0x0a7d8715, 0x220414a8, 0x141ebf67, 0x56b41583, 0x73e502e3,
+ 0x44cab16f, 0x28264d42, 0x73baaefb, 0x0a50ebed, 0x1d6ab6fb, 0x0d3ad40b,
+ 0x35db3b68, 0x2b081e83, 0x77ce6b95, 0x5181e5f0, 0x78853bbc, 0x009f9494,
+ 0x27e5ed3c
+};
+
+void VP8InitRandom(VP8Random* const rg, float dithering) {
+ memcpy(rg->tab_, kRandomTable, sizeof(rg->tab_));
+ rg->index1_ = 0;
+ rg->index2_ = 31;
+ rg->amp_ = (dithering < 0.0) ? 0
+ : (dithering > 1.0) ? (1 << VP8_RANDOM_DITHER_FIX)
+ : (uint32_t)((1 << VP8_RANDOM_DITHER_FIX) * dithering);
+}
+
+//------------------------------------------------------------------------------
+
diff --git a/drivers/webp/utils/random.h b/drivers/webp/utils/random.h
new file mode 100644
index 0000000000..745f3e2e87
--- /dev/null
+++ b/drivers/webp/utils/random.h
@@ -0,0 +1,63 @@
+// Copyright 2013 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Pseudo-random utilities
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_UTILS_RANDOM_H_
+#define WEBP_UTILS_RANDOM_H_
+
+#include <assert.h>
+#include "webp/types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define VP8_RANDOM_DITHER_FIX 8 // fixed-point precision for dithering
+#define VP8_RANDOM_TABLE_SIZE 55
+
+typedef struct {
+ int index1_, index2_;
+ uint32_t tab_[VP8_RANDOM_TABLE_SIZE];
+ int amp_;
+} VP8Random;
+
+// Initializes random generator with an amplitude 'dithering' in range [0..1].
+void VP8InitRandom(VP8Random* const rg, float dithering);
+
+// Returns a centered pseudo-random number with 'num_bits' amplitude.
+// (uses D.Knuth's Difference-based random generator).
+// 'amp' is in VP8_RANDOM_DITHER_FIX fixed-point precision.
+static WEBP_INLINE int VP8RandomBits2(VP8Random* const rg, int num_bits,
+ int amp) {
+ int diff;
+ assert(num_bits + VP8_RANDOM_DITHER_FIX <= 31);
+ diff = rg->tab_[rg->index1_] - rg->tab_[rg->index2_];
+ if (diff < 0) diff += (1u << 31);
+ rg->tab_[rg->index1_] = diff;
+ if (++rg->index1_ == VP8_RANDOM_TABLE_SIZE) rg->index1_ = 0;
+ if (++rg->index2_ == VP8_RANDOM_TABLE_SIZE) rg->index2_ = 0;
+ // sign-extend, 0-center
+ diff = (int)((uint32_t)diff << 1) >> (32 - num_bits);
+ diff = (diff * amp) >> VP8_RANDOM_DITHER_FIX; // restrict range
+ diff += 1 << (num_bits - 1); // shift back to 0.5-center
+ return diff;
+}
+
+static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) {
+ return VP8RandomBits2(rg, num_bits, rg->amp_);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_UTILS_RANDOM_H_ */
diff --git a/drivers/webp/utils/rescaler.c b/drivers/webp/utils/rescaler.c
index 9825dcbc5f..00c9300bfb 100644
--- a/drivers/webp/utils/rescaler.c
+++ b/drivers/webp/utils/rescaler.c
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Rescaling functions
@@ -11,124 +13,116 @@
#include <assert.h>
#include <stdlib.h>
+#include <string.h>
+#include "../dsp/dsp.h"
#include "./rescaler.h"
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-#define RFIX 30
-#define MULT_FIX(x,y) (((int64_t)(x) * (y) + (1 << (RFIX - 1))) >> RFIX)
-
void WebPRescalerInit(WebPRescaler* const wrk, int src_width, int src_height,
- uint8_t* const dst, int dst_width, int dst_height,
- int dst_stride, int num_channels, int x_add, int x_sub,
- int y_add, int y_sub, int32_t* const work) {
+ uint8_t* const dst,
+ int dst_width, int dst_height, int dst_stride,
+ int num_channels, rescaler_t* const work) {
+ const int x_add = src_width, x_sub = dst_width;
+ const int y_add = src_height, y_sub = dst_height;
wrk->x_expand = (src_width < dst_width);
+ wrk->y_expand = (src_height < dst_height);
wrk->src_width = src_width;
wrk->src_height = src_height;
wrk->dst_width = dst_width;
wrk->dst_height = dst_height;
+ wrk->src_y = 0;
+ wrk->dst_y = 0;
wrk->dst = dst;
wrk->dst_stride = dst_stride;
wrk->num_channels = num_channels;
+
// for 'x_expand', we use bilinear interpolation
- wrk->x_add = wrk->x_expand ? (x_sub - 1) : x_add - x_sub;
+ wrk->x_add = wrk->x_expand ? (x_sub - 1) : x_add;
wrk->x_sub = wrk->x_expand ? (x_add - 1) : x_sub;
- wrk->y_accum = y_add;
- wrk->y_add = y_add;
- wrk->y_sub = y_sub;
- wrk->fx_scale = (1 << RFIX) / x_sub;
- wrk->fy_scale = (1 << RFIX) / y_sub;
- wrk->fxy_scale = wrk->x_expand ?
- ((int64_t)dst_height << RFIX) / (x_sub * src_height) :
- ((int64_t)dst_height << RFIX) / (x_add * src_height);
+ if (!wrk->x_expand) { // fx_scale is not used otherwise
+ wrk->fx_scale = WEBP_RESCALER_FRAC(1, wrk->x_sub);
+ }
+ // vertical scaling parameters
+ wrk->y_add = wrk->y_expand ? y_add - 1 : y_add;
+ wrk->y_sub = wrk->y_expand ? y_sub - 1 : y_sub;
+ wrk->y_accum = wrk->y_expand ? wrk->y_sub : wrk->y_add;
+ if (!wrk->y_expand) {
+ // this is WEBP_RESCALER_FRAC(dst_height, x_add * y_add) without the cast.
+ const uint64_t ratio =
+ (uint64_t)dst_height * WEBP_RESCALER_ONE / (wrk->x_add * wrk->y_add);
+ if (ratio != (uint32_t)ratio) {
+ // We can't represent the ratio with the current fixed-point precision.
+ // => We special-case fxy_scale = 0, in WebPRescalerExportRow().
+ wrk->fxy_scale = 0;
+ } else {
+ wrk->fxy_scale = (uint32_t)ratio;
+ }
+ wrk->fy_scale = WEBP_RESCALER_FRAC(1, wrk->y_sub);
+ } else {
+ wrk->fy_scale = WEBP_RESCALER_FRAC(1, wrk->x_add);
+ // wrk->fxy_scale is unused here.
+ }
wrk->irow = work;
wrk->frow = work + num_channels * dst_width;
-}
+ memset(work, 0, 2 * dst_width * num_channels * sizeof(*work));
-void WebPRescalerImportRow(WebPRescaler* const wrk,
- const uint8_t* const src, int channel) {
- const int x_stride = wrk->num_channels;
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- int x_in = channel;
- int x_out;
- int accum = 0;
- if (!wrk->x_expand) {
- int sum = 0;
- for (x_out = channel; x_out < x_out_max; x_out += x_stride) {
- accum += wrk->x_add;
- for (; accum > 0; accum -= wrk->x_sub) {
- sum += src[x_in];
- x_in += x_stride;
- }
- { // Emit next horizontal pixel.
- const int32_t base = src[x_in];
- const int32_t frac = base * (-accum);
- x_in += x_stride;
- wrk->frow[x_out] = (sum + base) * wrk->x_sub - frac;
- // fresh fractional start for next pixel
- sum = (int)MULT_FIX(frac, wrk->fx_scale);
- }
- }
- } else { // simple bilinear interpolation
- int left = src[channel], right = src[channel];
- for (x_out = channel; x_out < x_out_max; x_out += x_stride) {
- if (accum < 0) {
- left = right;
- x_in += x_stride;
- right = src[x_in];
- accum += wrk->x_add;
- }
- wrk->frow[x_out] = right * wrk->x_add + (left - right) * accum;
- accum -= wrk->x_sub;
- }
- }
- // Accumulate the new row's contribution
- for (x_out = channel; x_out < x_out_max; x_out += x_stride) {
- wrk->irow[x_out] += wrk->frow[x_out];
- }
+ WebPRescalerDspInit();
}
-uint8_t* WebPRescalerExportRow(WebPRescaler* const wrk) {
- if (wrk->y_accum <= 0) {
- int x_out;
- uint8_t* const dst = wrk->dst;
- int32_t* const irow = wrk->irow;
- const int32_t* const frow = wrk->frow;
- const int yscale = wrk->fy_scale * (-wrk->y_accum);
- const int x_out_max = wrk->dst_width * wrk->num_channels;
+int WebPRescalerGetScaledDimensions(int src_width, int src_height,
+ int* const scaled_width,
+ int* const scaled_height) {
+ assert(scaled_width != NULL);
+ assert(scaled_height != NULL);
+ {
+ int width = *scaled_width;
+ int height = *scaled_height;
- for (x_out = 0; x_out < x_out_max; ++x_out) {
- const int frac = (int)MULT_FIX(frow[x_out], yscale);
- const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
- dst[x_out] = (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255;
- irow[x_out] = frac; // new fractional start
+ // if width is unspecified, scale original proportionally to height ratio.
+ if (width == 0) {
+ width = (src_width * height + src_height / 2) / src_height;
}
- wrk->y_accum += wrk->y_add;
- wrk->dst += wrk->dst_stride;
- return dst;
- } else {
- return NULL;
+ // if height is unspecified, scale original proportionally to width ratio.
+ if (height == 0) {
+ height = (src_height * width + src_width / 2) / src_width;
+ }
+ // Check if the overall dimensions still make sense.
+ if (width <= 0 || height <= 0) {
+ return 0;
+ }
+
+ *scaled_width = width;
+ *scaled_height = height;
+ return 1;
}
}
-#undef MULT_FIX
-#undef RFIX
-
//------------------------------------------------------------------------------
// all-in-one calls
+int WebPRescaleNeededLines(const WebPRescaler* const wrk, int max_num_lines) {
+ const int num_lines = (wrk->y_accum + wrk->y_sub - 1) / wrk->y_sub;
+ return (num_lines > max_num_lines) ? max_num_lines : num_lines;
+}
+
int WebPRescalerImport(WebPRescaler* const wrk, int num_lines,
const uint8_t* src, int src_stride) {
int total_imported = 0;
- while (total_imported < num_lines && wrk->y_accum > 0) {
- int channel;
- for (channel = 0; channel < wrk->num_channels; ++channel) {
- WebPRescalerImportRow(wrk, src, channel);
+ while (total_imported < num_lines && !WebPRescalerHasPendingOutput(wrk)) {
+ if (wrk->y_expand) {
+ rescaler_t* const tmp = wrk->irow;
+ wrk->irow = wrk->frow;
+ wrk->frow = tmp;
}
+ WebPRescalerImportRow(wrk, src);
+ if (!wrk->y_expand) { // Accumulate the contribution of the new row.
+ int x;
+ for (x = 0; x < wrk->num_channels * wrk->dst_width; ++x) {
+ wrk->irow[x] += wrk->frow[x];
+ }
+ }
+ ++wrk->src_y;
src += src_stride;
++total_imported;
wrk->y_accum -= wrk->y_sub;
@@ -146,7 +140,3 @@ int WebPRescalerExport(WebPRescaler* const rescaler) {
}
//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webp/utils/rescaler.h b/drivers/webp/utils/rescaler.h
index 9c9133d19b..868467b4d7 100644
--- a/drivers/webp/utils/rescaler.h
+++ b/drivers/webp/utils/rescaler.h
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Rescaling functions
@@ -12,64 +14,87 @@
#ifndef WEBP_UTILS_RESCALER_H_
#define WEBP_UTILS_RESCALER_H_
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
extern "C" {
#endif
-#include "../types.h"
+#include "webp/types.h"
+
+#define WEBP_RESCALER_RFIX 32 // fixed-point precision for multiplies
+#define WEBP_RESCALER_ONE (1ull << WEBP_RESCALER_RFIX)
+#define WEBP_RESCALER_FRAC(x, y) \
+ ((uint32_t)(((uint64_t)(x) << WEBP_RESCALER_RFIX) / (y)))
// Structure used for on-the-fly rescaling
-typedef struct {
+typedef uint32_t rescaler_t; // type for side-buffer
+typedef struct WebPRescaler WebPRescaler;
+struct WebPRescaler {
int x_expand; // true if we're expanding in the x direction
+ int y_expand; // true if we're expanding in the y direction
int num_channels; // bytes to jump between pixels
- int fy_scale, fx_scale; // fixed-point scaling factor
- int64_t fxy_scale; // ''
- // we need hpel-precise add/sub increments, for the downsampled U/V planes.
+ uint32_t fx_scale; // fixed-point scaling factors
+ uint32_t fy_scale; // ''
+ uint32_t fxy_scale; // ''
int y_accum; // vertical accumulator
- int y_add, y_sub; // vertical increments (add ~= src, sub ~= dst)
- int x_add, x_sub; // horizontal increments (add ~= src, sub ~= dst)
+ int y_add, y_sub; // vertical increments
+ int x_add, x_sub; // horizontal increments
int src_width, src_height; // source dimensions
int dst_width, dst_height; // destination dimensions
+ int src_y, dst_y; // row counters for input and output
uint8_t* dst;
int dst_stride;
- int32_t* irow, *frow; // work buffer
-} WebPRescaler;
+ rescaler_t* irow, *frow; // work buffer
+};
// Initialize a rescaler given scratch area 'work' and dimensions of src & dst.
-void WebPRescalerInit(WebPRescaler* const wrk, int src_width, int src_height,
+void WebPRescalerInit(WebPRescaler* const rescaler,
+ int src_width, int src_height,
uint8_t* const dst,
int dst_width, int dst_height, int dst_stride,
int num_channels,
- int x_add, int x_sub,
- int y_add, int y_sub,
- int32_t* const work);
+ rescaler_t* const work);
+
+// If either 'scaled_width' or 'scaled_height' (but not both) is 0 the value
+// will be calculated preserving the aspect ratio, otherwise the values are
+// left unmodified. Returns true on success, false if either value is 0 after
+// performing the scaling calculation.
+int WebPRescalerGetScaledDimensions(int src_width, int src_height,
+ int* const scaled_width,
+ int* const scaled_height);
-// Import a row of data and save its contribution in the rescaler.
-// 'channel' denotes the channel number to be imported.
-void WebPRescalerImportRow(WebPRescaler* const rescaler,
- const uint8_t* const src, int channel);
+// Returns the number of input lines needed next to produce one output line,
+// considering that the maximum available input lines are 'max_num_lines'.
+int WebPRescaleNeededLines(const WebPRescaler* const rescaler,
+ int max_num_lines);
// Import multiple rows over all channels, until at least one row is ready to
// be exported. Returns the actual number of lines that were imported.
int WebPRescalerImport(WebPRescaler* const rescaler, int num_rows,
const uint8_t* src, int src_stride);
-// Return true if there is pending output rows ready.
+// Export as many rows as possible. Return the numbers of rows written.
+int WebPRescalerExport(WebPRescaler* const rescaler);
+
+// Return true if input is finished
static WEBP_INLINE
-int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) {
- return (rescaler->y_accum <= 0);
+int WebPRescalerInputDone(const WebPRescaler* const rescaler) {
+ return (rescaler->src_y >= rescaler->src_height);
+}
+// Return true if output is finished
+static WEBP_INLINE
+int WebPRescalerOutputDone(const WebPRescaler* const rescaler) {
+ return (rescaler->dst_y >= rescaler->dst_height);
}
-// Export one row from rescaler. Returns the pointer where output was written,
-// or NULL if no row was pending.
-uint8_t* WebPRescalerExportRow(WebPRescaler* const wrk);
-
-// Export as many rows as possible. Return the numbers of rows written.
-int WebPRescalerExport(WebPRescaler* const wrk);
+// Return true if there are pending output rows ready.
+static WEBP_INLINE
+int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) {
+ return !WebPRescalerOutputDone(rescaler) && (rescaler->y_accum <= 0);
+}
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/utils/thread.c b/drivers/webp/utils/thread.c
index ce89cf9dc7..93f7622797 100644
--- a/drivers/webp/utils/thread.c
+++ b/drivers/webp/utils/thread.c
@@ -1,27 +1,60 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Multi-threaded worker
//
// Author: Skal (pascal.massimino@gmail.com)
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include <assert.h>
#include <string.h> // for memset()
#include "./thread.h"
+#include "./utils.h"
+
+#ifdef WEBP_USE_THREAD
+
+#if defined(_WIN32)
+
+#include <windows.h>
+typedef HANDLE pthread_t;
+typedef CRITICAL_SECTION pthread_mutex_t;
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
+#if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater
+#define USE_WINDOWS_CONDITION_VARIABLE
+typedef CONDITION_VARIABLE pthread_cond_t;
+#else
+typedef struct {
+ HANDLE waiting_sem_;
+ HANDLE received_sem_;
+ HANDLE signal_event_;
+} pthread_cond_t;
+#endif // _WIN32_WINNT >= 0x600
+
+#ifndef WINAPI_FAMILY_PARTITION
+#define WINAPI_PARTITION_DESKTOP 1
+#define WINAPI_FAMILY_PARTITION(x) x
#endif
-#ifdef WEBP_USE_THREAD
+#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#define USE_CREATE_THREAD
+#endif
+
+#else // !_WIN32
+
+#include <pthread.h>
+
+#endif // _WIN32
+
+struct WebPWorkerImpl {
+ pthread_mutex_t mutex_;
+ pthread_cond_t condition_;
+ pthread_t thread_;
+};
#if defined(_WIN32)
@@ -34,15 +67,29 @@ extern "C" {
#define THREADFN unsigned int __stdcall
#define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val)
+#if _WIN32_WINNT >= 0x0501 // Windows XP or greater
+#define WaitForSingleObject(obj, timeout) \
+ WaitForSingleObjectEx(obj, timeout, FALSE /*bAlertable*/)
+#endif
+
static int pthread_create(pthread_t* const thread, const void* attr,
unsigned int (__stdcall *start)(void*), void* arg) {
(void)attr;
+#ifdef USE_CREATE_THREAD
+ *thread = CreateThread(NULL, /* lpThreadAttributes */
+ 0, /* dwStackSize */
+ start,
+ arg,
+ 0, /* dwStackSize */
+ NULL); /* lpThreadId */
+#else
*thread = (pthread_t)_beginthreadex(NULL, /* void *security */
0, /* unsigned stack_size */
start,
arg,
0, /* unsigned initflag */
NULL); /* unsigned *thrdaddr */
+#endif
if (*thread == NULL) return 1;
SetThreadPriority(*thread, THREAD_PRIORITY_ABOVE_NORMAL);
return 0;
@@ -57,7 +104,11 @@ static int pthread_join(pthread_t thread, void** value_ptr) {
// Mutex
static int pthread_mutex_init(pthread_mutex_t* const mutex, void* mutexattr) {
(void)mutexattr;
+#if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater
+ InitializeCriticalSectionEx(mutex, 0 /*dwSpinCount*/, 0 /*Flags*/);
+#else
InitializeCriticalSection(mutex);
+#endif
return 0;
}
@@ -79,14 +130,21 @@ static int pthread_mutex_destroy(pthread_mutex_t* const mutex) {
// Condition
static int pthread_cond_destroy(pthread_cond_t* const condition) {
int ok = 1;
+#ifdef USE_WINDOWS_CONDITION_VARIABLE
+ (void)condition;
+#else
ok &= (CloseHandle(condition->waiting_sem_) != 0);
ok &= (CloseHandle(condition->received_sem_) != 0);
ok &= (CloseHandle(condition->signal_event_) != 0);
+#endif
return !ok;
}
static int pthread_cond_init(pthread_cond_t* const condition, void* cond_attr) {
(void)cond_attr;
+#ifdef USE_WINDOWS_CONDITION_VARIABLE
+ InitializeConditionVariable(condition);
+#else
condition->waiting_sem_ = CreateSemaphore(NULL, 0, 1, NULL);
condition->received_sem_ = CreateSemaphore(NULL, 0, 1, NULL);
condition->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL);
@@ -96,11 +154,15 @@ static int pthread_cond_init(pthread_cond_t* const condition, void* cond_attr) {
pthread_cond_destroy(condition);
return 1;
}
+#endif
return 0;
}
static int pthread_cond_signal(pthread_cond_t* const condition) {
int ok = 1;
+#ifdef USE_WINDOWS_CONDITION_VARIABLE
+ WakeConditionVariable(condition);
+#else
if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) {
// a thread is waiting in pthread_cond_wait: allow it to be notified
ok = SetEvent(condition->signal_event_);
@@ -109,12 +171,16 @@ static int pthread_cond_signal(pthread_cond_t* const condition) {
ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) !=
WAIT_OBJECT_0);
}
+#endif
return !ok;
}
static int pthread_cond_wait(pthread_cond_t* const condition,
pthread_mutex_t* const mutex) {
int ok;
+#ifdef USE_WINDOWS_CONDITION_VARIABLE
+ ok = SleepConditionVariableCS(condition, mutex, INFINITE);
+#else
// note that there is a consumer available so the signal isn't dropped in
// pthread_cond_signal
if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL))
@@ -125,123 +191,168 @@ static int pthread_cond_wait(pthread_cond_t* const condition,
WAIT_OBJECT_0);
ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL);
pthread_mutex_lock(mutex);
+#endif
return !ok;
}
-#else // _WIN32
+#else // !_WIN32
# define THREADFN void*
# define THREAD_RETURN(val) val
-#endif
+#endif // _WIN32
//------------------------------------------------------------------------------
-static THREADFN WebPWorkerThreadLoop(void *ptr) { // thread loop
+static void Execute(WebPWorker* const worker); // Forward declaration.
+
+static THREADFN ThreadLoop(void* ptr) {
WebPWorker* const worker = (WebPWorker*)ptr;
int done = 0;
while (!done) {
- pthread_mutex_lock(&worker->mutex_);
+ pthread_mutex_lock(&worker->impl_->mutex_);
while (worker->status_ == OK) { // wait in idling mode
- pthread_cond_wait(&worker->condition_, &worker->mutex_);
+ pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_);
}
if (worker->status_ == WORK) {
- if (worker->hook) {
- worker->had_error |= !worker->hook(worker->data1, worker->data2);
- }
+ Execute(worker);
worker->status_ = OK;
} else if (worker->status_ == NOT_OK) { // finish the worker
done = 1;
}
// signal to the main thread that we're done (for Sync())
- pthread_cond_signal(&worker->condition_);
- pthread_mutex_unlock(&worker->mutex_);
+ pthread_cond_signal(&worker->impl_->condition_);
+ pthread_mutex_unlock(&worker->impl_->mutex_);
}
return THREAD_RETURN(NULL); // Thread is finished
}
// main thread state control
-static void WebPWorkerChangeState(WebPWorker* const worker,
- WebPWorkerStatus new_status) {
- // no-op when attempting to change state on a thread that didn't come up
- if (worker->status_ < OK) return;
-
- pthread_mutex_lock(&worker->mutex_);
- // wait for the worker to finish
- while (worker->status_ != OK) {
- pthread_cond_wait(&worker->condition_, &worker->mutex_);
- }
- // assign new status and release the working thread if needed
- if (new_status != OK) {
- worker->status_ = new_status;
- pthread_cond_signal(&worker->condition_);
+static void ChangeState(WebPWorker* const worker,
+ WebPWorkerStatus new_status) {
+ // No-op when attempting to change state on a thread that didn't come up.
+ // Checking status_ without acquiring the lock first would result in a data
+ // race.
+ if (worker->impl_ == NULL) return;
+
+ pthread_mutex_lock(&worker->impl_->mutex_);
+ if (worker->status_ >= OK) {
+ // wait for the worker to finish
+ while (worker->status_ != OK) {
+ pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_);
+ }
+ // assign new status and release the working thread if needed
+ if (new_status != OK) {
+ worker->status_ = new_status;
+ pthread_cond_signal(&worker->impl_->condition_);
+ }
}
- pthread_mutex_unlock(&worker->mutex_);
+ pthread_mutex_unlock(&worker->impl_->mutex_);
}
-#endif
+#endif // WEBP_USE_THREAD
//------------------------------------------------------------------------------
-void WebPWorkerInit(WebPWorker* const worker) {
+static void Init(WebPWorker* const worker) {
memset(worker, 0, sizeof(*worker));
worker->status_ = NOT_OK;
}
-int WebPWorkerSync(WebPWorker* const worker) {
+static int Sync(WebPWorker* const worker) {
#ifdef WEBP_USE_THREAD
- WebPWorkerChangeState(worker, OK);
+ ChangeState(worker, OK);
#endif
assert(worker->status_ <= OK);
return !worker->had_error;
}
-int WebPWorkerReset(WebPWorker* const worker) {
+static int Reset(WebPWorker* const worker) {
int ok = 1;
worker->had_error = 0;
if (worker->status_ < OK) {
#ifdef WEBP_USE_THREAD
- if (pthread_mutex_init(&worker->mutex_, NULL) ||
- pthread_cond_init(&worker->condition_, NULL)) {
+ worker->impl_ = (WebPWorkerImpl*)WebPSafeCalloc(1, sizeof(*worker->impl_));
+ if (worker->impl_ == NULL) {
return 0;
}
- pthread_mutex_lock(&worker->mutex_);
- ok = !pthread_create(&worker->thread_, NULL, WebPWorkerThreadLoop, worker);
+ if (pthread_mutex_init(&worker->impl_->mutex_, NULL)) {
+ goto Error;
+ }
+ if (pthread_cond_init(&worker->impl_->condition_, NULL)) {
+ pthread_mutex_destroy(&worker->impl_->mutex_);
+ goto Error;
+ }
+ pthread_mutex_lock(&worker->impl_->mutex_);
+ ok = !pthread_create(&worker->impl_->thread_, NULL, ThreadLoop, worker);
if (ok) worker->status_ = OK;
- pthread_mutex_unlock(&worker->mutex_);
+ pthread_mutex_unlock(&worker->impl_->mutex_);
+ if (!ok) {
+ pthread_mutex_destroy(&worker->impl_->mutex_);
+ pthread_cond_destroy(&worker->impl_->condition_);
+ Error:
+ WebPSafeFree(worker->impl_);
+ worker->impl_ = NULL;
+ return 0;
+ }
#else
worker->status_ = OK;
#endif
} else if (worker->status_ > OK) {
- ok = WebPWorkerSync(worker);
+ ok = Sync(worker);
}
assert(!ok || (worker->status_ == OK));
return ok;
}
-void WebPWorkerLaunch(WebPWorker* const worker) {
+static void Execute(WebPWorker* const worker) {
+ if (worker->hook != NULL) {
+ worker->had_error |= !worker->hook(worker->data1, worker->data2);
+ }
+}
+
+static void Launch(WebPWorker* const worker) {
#ifdef WEBP_USE_THREAD
- WebPWorkerChangeState(worker, WORK);
+ ChangeState(worker, WORK);
#else
- if (worker->hook)
- worker->had_error |= !worker->hook(worker->data1, worker->data2);
+ Execute(worker);
#endif
}
-void WebPWorkerEnd(WebPWorker* const worker) {
- if (worker->status_ >= OK) {
+static void End(WebPWorker* const worker) {
#ifdef WEBP_USE_THREAD
- WebPWorkerChangeState(worker, NOT_OK);
- pthread_join(worker->thread_, NULL);
- pthread_mutex_destroy(&worker->mutex_);
- pthread_cond_destroy(&worker->condition_);
+ if (worker->impl_ != NULL) {
+ ChangeState(worker, NOT_OK);
+ pthread_join(worker->impl_->thread_, NULL);
+ pthread_mutex_destroy(&worker->impl_->mutex_);
+ pthread_cond_destroy(&worker->impl_->condition_);
+ WebPSafeFree(worker->impl_);
+ worker->impl_ = NULL;
+ }
#else
- worker->status_ = NOT_OK;
+ worker->status_ = NOT_OK;
+ assert(worker->impl_ == NULL);
#endif
- }
assert(worker->status_ == NOT_OK);
}
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
+static WebPWorkerInterface g_worker_interface = {
+ Init, Reset, Sync, Launch, Execute, End
+};
+
+int WebPSetWorkerInterface(const WebPWorkerInterface* const winterface) {
+ if (winterface == NULL ||
+ winterface->Init == NULL || winterface->Reset == NULL ||
+ winterface->Sync == NULL || winterface->Launch == NULL ||
+ winterface->Execute == NULL || winterface->End == NULL) {
+ return 0;
+ }
+ g_worker_interface = *winterface;
+ return 1;
+}
+
+const WebPWorkerInterface* WebPGetWorkerInterface(void) {
+ return &g_worker_interface;
+}
+
+//------------------------------------------------------------------------------
diff --git a/drivers/webp/utils/thread.h b/drivers/webp/utils/thread.h
index 3191890b76..6008bb7c01 100644
--- a/drivers/webp/utils/thread.h
+++ b/drivers/webp/utils/thread.h
@@ -1,8 +1,10 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Multi-threaded worker
@@ -12,29 +14,15 @@
#ifndef WEBP_UTILS_THREAD_H_
#define WEBP_UTILS_THREAD_H_
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
+#ifdef HAVE_CONFIG_H
+#include "webp/config.h"
#endif
-#if WEBP_USE_THREAD
-
-#if defined(_WIN32)
-
-#include <windows.h>
-typedef HANDLE pthread_t;
-typedef CRITICAL_SECTION pthread_mutex_t;
-typedef struct {
- HANDLE waiting_sem_;
- HANDLE received_sem_;
- HANDLE signal_event_;
-} pthread_cond_t;
+#include "webp/types.h"
-#else
-
-#include <pthread.h>
-
-#endif /* _WIN32 */
-#endif /* WEBP_USE_THREAD */
+#ifdef __cplusplus
+extern "C" {
+#endif
// State of the worker thread object
typedef enum {
@@ -47,13 +35,12 @@ typedef enum {
// arguments (data1 and data2), and should return false in case of error.
typedef int (*WebPWorkerHook)(void*, void*);
-// Synchronize object used to launch job in the worker thread
+// Platform-dependent implementation details for the worker.
+typedef struct WebPWorkerImpl WebPWorkerImpl;
+
+// Synchronization object used to launch job in the worker thread
typedef struct {
-#if WEBP_USE_THREAD
- pthread_mutex_t mutex_;
- pthread_cond_t condition_;
- pthread_t thread_;
-#endif
+ WebPWorkerImpl* impl_;
WebPWorkerStatus status_;
WebPWorkerHook hook; // hook to call
void* data1; // first argument passed to 'hook'
@@ -61,25 +48,45 @@ typedef struct {
int had_error; // return value of the last call to 'hook'
} WebPWorker;
-// Must be called first, before any other method.
-void WebPWorkerInit(WebPWorker* const worker);
-// Must be called initialize the object and spawn the thread. Re-entrant.
-// Will potentially launch the thread. Returns false in case of error.
-int WebPWorkerReset(WebPWorker* const worker);
-// Make sure the previous work is finished. Returns true if worker->had_error
-// was not set and not error condition was triggered by the working thread.
-int WebPWorkerSync(WebPWorker* const worker);
-// Trigger the thread to call hook() with data1 and data2 argument. These
-// hook/data1/data2 can be changed at any time before calling this function,
-// but not be changed afterward until the next call to WebPWorkerSync().
-void WebPWorkerLaunch(WebPWorker* const worker);
-// Kill the thread and terminate the object. To use the object again, one
-// must call WebPWorkerReset() again.
-void WebPWorkerEnd(WebPWorker* const worker);
+// The interface for all thread-worker related functions. All these functions
+// must be implemented.
+typedef struct {
+ // Must be called first, before any other method.
+ void (*Init)(WebPWorker* const worker);
+ // Must be called to initialize the object and spawn the thread. Re-entrant.
+ // Will potentially launch the thread. Returns false in case of error.
+ int (*Reset)(WebPWorker* const worker);
+ // Makes sure the previous work is finished. Returns true if worker->had_error
+ // was not set and no error condition was triggered by the working thread.
+ int (*Sync)(WebPWorker* const worker);
+ // Triggers the thread to call hook() with data1 and data2 arguments. These
+ // hook/data1/data2 values can be changed at any time before calling this
+ // function, but not be changed afterward until the next call to Sync().
+ void (*Launch)(WebPWorker* const worker);
+ // This function is similar to Launch() except that it calls the
+ // hook directly instead of using a thread. Convenient to bypass the thread
+ // mechanism while still using the WebPWorker structs. Sync() must
+ // still be called afterward (for error reporting).
+ void (*Execute)(WebPWorker* const worker);
+ // Kill the thread and terminate the object. To use the object again, one
+ // must call Reset() again.
+ void (*End)(WebPWorker* const worker);
+} WebPWorkerInterface;
+
+// Install a new set of threading functions, overriding the defaults. This
+// should be done before any workers are started, i.e., before any encoding or
+// decoding takes place. The contents of the interface struct are copied, it
+// is safe to free the corresponding memory after this call. This function is
+// not thread-safe. Return false in case of invalid pointer or methods.
+WEBP_EXTERN(int) WebPSetWorkerInterface(
+ const WebPWorkerInterface* const winterface);
+
+// Retrieve the currently set thread worker interface.
+WEBP_EXTERN(const WebPWorkerInterface*) WebPGetWorkerInterface(void);
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webp/utils/utils.c b/drivers/webp/utils/utils.c
index 673b7e284c..35aeae6ab8 100644
--- a/drivers/webp/utils/utils.c
+++ b/drivers/webp/utils/utils.c
@@ -1,8 +1,10 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Misc. common utility functions
@@ -10,35 +12,228 @@
// Author: Skal (pascal.massimino@gmail.com)
#include <stdlib.h>
+#include <string.h> // for memcpy()
+#include "webp/decode.h"
+#include "webp/encode.h"
#include "./utils.h"
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
+// If PRINT_MEM_INFO is defined, extra info (like total memory used, number of
+// alloc/free etc) is printed. For debugging/tuning purpose only (it's slow,
+// and not multi-thread safe!).
+// An interesting alternative is valgrind's 'massif' tool:
+// http://valgrind.org/docs/manual/ms-manual.html
+// Here is an example command line:
+/* valgrind --tool=massif --massif-out-file=massif.out \
+ --stacks=yes --alloc-fn=WebPSafeAlloc --alloc-fn=WebPSafeCalloc
+ ms_print massif.out
+*/
+// In addition:
+// * if PRINT_MEM_TRAFFIC is defined, all the details of the malloc/free cycles
+// are printed.
+// * if MALLOC_FAIL_AT is defined, the global environment variable
+// $MALLOC_FAIL_AT is used to simulate a memory error when calloc or malloc
+// is called for the nth time. Example usage:
+// export MALLOC_FAIL_AT=50 && ./examples/cwebp input.png
+// * if MALLOC_LIMIT is defined, the global environment variable $MALLOC_LIMIT
+// sets the maximum amount of memory (in bytes) made available to libwebp.
+// This can be used to emulate environment with very limited memory.
+// Example: export MALLOC_LIMIT=64000000 && ./examples/dwebp picture.webp
+
+// #define PRINT_MEM_INFO
+// #define PRINT_MEM_TRAFFIC
+// #define MALLOC_FAIL_AT
+// #define MALLOC_LIMIT
//------------------------------------------------------------------------------
// Checked memory allocation
-static int CheckSizeArguments(uint64_t nmemb, size_t size) {
+#if defined(PRINT_MEM_INFO)
+
+#include <stdio.h>
+
+static int num_malloc_calls = 0;
+static int num_calloc_calls = 0;
+static int num_free_calls = 0;
+static int countdown_to_fail = 0; // 0 = off
+
+typedef struct MemBlock MemBlock;
+struct MemBlock {
+ void* ptr_;
+ size_t size_;
+ MemBlock* next_;
+};
+
+static MemBlock* all_blocks = NULL;
+static size_t total_mem = 0;
+static size_t total_mem_allocated = 0;
+static size_t high_water_mark = 0;
+static size_t mem_limit = 0;
+
+static int exit_registered = 0;
+
+static void PrintMemInfo(void) {
+ fprintf(stderr, "\nMEMORY INFO:\n");
+ fprintf(stderr, "num calls to: malloc = %4d\n", num_malloc_calls);
+ fprintf(stderr, " calloc = %4d\n", num_calloc_calls);
+ fprintf(stderr, " free = %4d\n", num_free_calls);
+ fprintf(stderr, "total_mem: %u\n", (uint32_t)total_mem);
+ fprintf(stderr, "total_mem allocated: %u\n", (uint32_t)total_mem_allocated);
+ fprintf(stderr, "high-water mark: %u\n", (uint32_t)high_water_mark);
+ while (all_blocks != NULL) {
+ MemBlock* b = all_blocks;
+ all_blocks = b->next_;
+ free(b);
+ }
+}
+
+static void Increment(int* const v) {
+ if (!exit_registered) {
+#if defined(MALLOC_FAIL_AT)
+ {
+ const char* const malloc_fail_at_str = getenv("MALLOC_FAIL_AT");
+ if (malloc_fail_at_str != NULL) {
+ countdown_to_fail = atoi(malloc_fail_at_str);
+ }
+ }
+#endif
+#if defined(MALLOC_LIMIT)
+ {
+ const char* const malloc_limit_str = getenv("MALLOC_LIMIT");
+ if (malloc_limit_str != NULL) {
+ mem_limit = atoi(malloc_limit_str);
+ }
+ }
+#endif
+ (void)countdown_to_fail;
+ (void)mem_limit;
+ atexit(PrintMemInfo);
+ exit_registered = 1;
+ }
+ ++*v;
+}
+
+static void AddMem(void* ptr, size_t size) {
+ if (ptr != NULL) {
+ MemBlock* const b = (MemBlock*)malloc(sizeof(*b));
+ if (b == NULL) abort();
+ b->next_ = all_blocks;
+ all_blocks = b;
+ b->ptr_ = ptr;
+ b->size_ = size;
+ total_mem += size;
+ total_mem_allocated += size;
+#if defined(PRINT_MEM_TRAFFIC)
+#if defined(MALLOC_FAIL_AT)
+ fprintf(stderr, "fail-count: %5d [mem=%u]\n",
+ num_malloc_calls + num_calloc_calls, (uint32_t)total_mem);
+#else
+ fprintf(stderr, "Mem: %u (+%u)\n", (uint32_t)total_mem, (uint32_t)size);
+#endif
+#endif
+ if (total_mem > high_water_mark) high_water_mark = total_mem;
+ }
+}
+
+static void SubMem(void* ptr) {
+ if (ptr != NULL) {
+ MemBlock** b = &all_blocks;
+ // Inefficient search, but that's just for debugging.
+ while (*b != NULL && (*b)->ptr_ != ptr) b = &(*b)->next_;
+ if (*b == NULL) {
+ fprintf(stderr, "Invalid pointer free! (%p)\n", ptr);
+ abort();
+ }
+ {
+ MemBlock* const block = *b;
+ *b = block->next_;
+ total_mem -= block->size_;
+#if defined(PRINT_MEM_TRAFFIC)
+ fprintf(stderr, "Mem: %u (-%u)\n",
+ (uint32_t)total_mem, (uint32_t)block->size_);
+#endif
+ free(block);
+ }
+ }
+}
+
+#else
+#define Increment(v) do {} while (0)
+#define AddMem(p, s) do {} while (0)
+#define SubMem(p) do {} while (0)
+#endif
+
+// Returns 0 in case of overflow of nmemb * size.
+static int CheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) {
const uint64_t total_size = nmemb * size;
if (nmemb == 0) return 1;
if ((uint64_t)size > WEBP_MAX_ALLOCABLE_MEMORY / nmemb) return 0;
if (total_size != (size_t)total_size) return 0;
+#if defined(PRINT_MEM_INFO) && defined(MALLOC_FAIL_AT)
+ if (countdown_to_fail > 0 && --countdown_to_fail == 0) {
+ return 0; // fake fail!
+ }
+#endif
+#if defined(MALLOC_LIMIT)
+ if (mem_limit > 0 && total_mem + total_size >= mem_limit) {
+ return 0; // fake fail!
+ }
+#endif
+
return 1;
}
void* WebPSafeMalloc(uint64_t nmemb, size_t size) {
- if (!CheckSizeArguments(nmemb, size)) return NULL;
- return malloc((size_t)(nmemb * size));
+ void* ptr;
+ Increment(&num_malloc_calls);
+ if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL;
+ assert(nmemb * size > 0);
+ ptr = malloc((size_t)(nmemb * size));
+ AddMem(ptr, (size_t)(nmemb * size));
+ return ptr;
}
void* WebPSafeCalloc(uint64_t nmemb, size_t size) {
- if (!CheckSizeArguments(nmemb, size)) return NULL;
- return calloc((size_t)nmemb, size);
+ void* ptr;
+ Increment(&num_calloc_calls);
+ if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL;
+ assert(nmemb * size > 0);
+ ptr = calloc((size_t)nmemb, size);
+ AddMem(ptr, (size_t)(nmemb * size));
+ return ptr;
+}
+
+void WebPSafeFree(void* const ptr) {
+ if (ptr != NULL) {
+ Increment(&num_free_calls);
+ SubMem(ptr);
+ }
+ free(ptr);
+}
+
+// Public API function.
+void WebPFree(void* ptr) {
+ free(ptr);
}
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
+void WebPCopyPlane(const uint8_t* src, int src_stride,
+ uint8_t* dst, int dst_stride, int width, int height) {
+ assert(src != NULL && dst != NULL);
+ assert(src_stride >= width && dst_stride >= width);
+ while (height-- > 0) {
+ memcpy(dst, src, width);
+ src += src_stride;
+ dst += dst_stride;
+ }
+}
+
+void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) {
+ assert(src != NULL && dst != NULL);
+ assert(src->width == dst->width && src->height == dst->height);
+ assert(src->use_argb && dst->use_argb);
+ WebPCopyPlane((uint8_t*)src->argb, 4 * src->argb_stride, (uint8_t*)dst->argb,
+ 4 * dst->argb_stride, 4 * src->width, src->height);
+}
+
+//------------------------------------------------------------------------------
diff --git a/drivers/webp/utils/utils.h b/drivers/webp/utils/utils.h
index 316ac90612..d0e1cb250a 100644
--- a/drivers/webp/utils/utils.h
+++ b/drivers/webp/utils/utils.h
@@ -1,20 +1,25 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
-// This code is licensed under the same terms as WebM:
-// Software License Agreement: http://www.webmproject.org/license/software/
-// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Misc. common utility functions
//
-// Author: Skal (pascal.massimino@gmail.com)
+// Authors: Skal (pascal.massimino@gmail.com)
+// Urvang (urvang@google.com)
#ifndef WEBP_UTILS_UTILS_H_
#define WEBP_UTILS_UTILS_H_
-#include "../types.h"
+#include <assert.h>
-#if defined(__cplusplus) || defined(c_plusplus)
+#include "webp/types.h"
+
+#ifdef __cplusplus
extern "C" {
#endif
@@ -30,14 +35,107 @@ extern "C" {
// somewhere (like: malloc(num_pixels * sizeof(*something))). That's why this
// safe malloc() borrows the signature from calloc(), pointing at the dangerous
// underlying multiply involved.
-void* WebPSafeMalloc(uint64_t nmemb, size_t size);
+WEBP_EXTERN(void*) WebPSafeMalloc(uint64_t nmemb, size_t size);
// Note that WebPSafeCalloc() expects the second argument type to be 'size_t'
// in order to favor the "calloc(num_foo, sizeof(foo))" pattern.
-void* WebPSafeCalloc(uint64_t nmemb, size_t size);
+WEBP_EXTERN(void*) WebPSafeCalloc(uint64_t nmemb, size_t size);
+
+// Companion deallocation function to the above allocations.
+WEBP_EXTERN(void) WebPSafeFree(void* const ptr);
+
+//------------------------------------------------------------------------------
+// Alignment
+
+#define WEBP_ALIGN_CST 31
+#define WEBP_ALIGN(PTR) ((uintptr_t)((PTR) + WEBP_ALIGN_CST) & ~WEBP_ALIGN_CST)
+
+//------------------------------------------------------------------------------
+// Reading/writing data.
+
+// Read 16, 24 or 32 bits stored in little-endian order.
+static WEBP_INLINE int GetLE16(const uint8_t* const data) {
+ return (int)(data[0] << 0) | (data[1] << 8);
+}
+
+static WEBP_INLINE int GetLE24(const uint8_t* const data) {
+ return GetLE16(data) | (data[2] << 16);
+}
+
+static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) {
+ return GetLE16(data) | ((uint32_t)GetLE16(data + 2) << 16);
+}
+
+// Store 16, 24 or 32 bits in little-endian order.
+static WEBP_INLINE void PutLE16(uint8_t* const data, int val) {
+ assert(val < (1 << 16));
+ data[0] = (val >> 0);
+ data[1] = (val >> 8);
+}
+
+static WEBP_INLINE void PutLE24(uint8_t* const data, int val) {
+ assert(val < (1 << 24));
+ PutLE16(data, val & 0xffff);
+ data[2] = (val >> 16);
+}
+
+static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) {
+ PutLE16(data, (int)(val & 0xffff));
+ PutLE16(data + 2, (int)(val >> 16));
+}
+
+// Returns (int)floor(log2(n)). n must be > 0.
+// use GNU builtins where available.
+#if defined(__GNUC__) && \
+ ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4)
+static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
+ return 31 ^ __builtin_clz(n);
+}
+#elif defined(_MSC_VER) && _MSC_VER > 1310 && \
+ (defined(_M_X64) || defined(_M_IX86))
+#include <intrin.h>
+#pragma intrinsic(_BitScanReverse)
+
+static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
+ unsigned long first_set_bit;
+ _BitScanReverse(&first_set_bit, n);
+ return first_set_bit;
+}
+#else
+static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
+ int log = 0;
+ uint32_t value = n;
+ int i;
+
+ for (i = 4; i >= 0; --i) {
+ const int shift = (1 << i);
+ const uint32_t x = value >> shift;
+ if (x != 0) {
+ value = x;
+ log += shift;
+ }
+ }
+ return log;
+}
+#endif
+
+//------------------------------------------------------------------------------
+// Pixel copying.
+
+struct WebPPicture;
+
+// Copy width x height pixels from 'src' to 'dst' honoring the strides.
+WEBP_EXTERN(void) WebPCopyPlane(const uint8_t* src, int src_stride,
+ uint8_t* dst, int dst_stride,
+ int width, int height);
+
+// Copy ARGB pixels from 'src' to 'dst' honoring strides. 'src' and 'dst' are
+// assumed to be already allocated and using ARGB data.
+WEBP_EXTERN(void) WebPCopyPixels(const struct WebPPicture* const src,
+ struct WebPPicture* const dst);
//------------------------------------------------------------------------------
-#if defined(__cplusplus) || defined(c_plusplus)
+#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/drivers/webpold/SCsub b/drivers/webpold/SCsub
new file mode 100644
index 0000000000..5596edbe09
--- /dev/null
+++ b/drivers/webpold/SCsub
@@ -0,0 +1,63 @@
+Import('env')
+
+
+webp_sources = [
+ "webp/mux/muxedit.c",
+ "webp/mux/muxread.c",
+ "webp/mux/muxinternal.c",
+ "webp/mux/demux.c",
+ "webp/enc/tree.c",
+ "webp/enc/analysis.c",
+ "webp/enc/backward_references.c",
+ "webp/enc/alpha.c",
+ "webp/enc/picture.c",
+ "webp/enc/frame.c",
+ "webp/enc/webpenc.c",
+ "webp/enc/cost.c",
+ "webp/enc/filter.c",
+ "webp/enc/vp8l.c",
+ "webp/enc/quant.c",
+ "webp/enc/histogram.c",
+ "webp/enc/syntax.c",
+ "webp/enc/config.c",
+ "webp/enc/layer.c",
+ "webp/enc/iterator.c",
+ "webp/dsp/dec_sse2.c",
+ "webp/dsp/upsampling_sse2.c",
+ "webp/dsp/dec_neon.c",
+ "webp/dsp/enc.c",
+ "webp/dsp/enc_sse2.c",
+ "webp/dsp/upsampling.c",
+ "webp/dsp/lossless.c",
+ "webp/dsp/cpu.c",
+ "webp/dsp/dec.c",
+ "webp/dsp/yuv.c",
+ "webp/utils/bit_reader.c",
+ "webp/utils/filters.c",
+ "webp/utils/bit_writer.c",
+ "webp/utils/thread.c",
+ "webp/utils/quant_levels.c",
+ "webp/utils/color_cache.c",
+ "webp/utils/rescaler.c",
+ "webp/utils/utils.c",
+ "webp/utils/huffman.c",
+ "webp/utils/huffman_encode.c",
+ "webp/dec/tree.c",
+ "webp/dec/alpha.c",
+ "webp/dec/frame.c",
+ "webp/dec/vp8l.c",
+ "webp/dec/vp8.c",
+ "webp/dec/quant.c",
+ "webp/dec/webp.c",
+ "webp/dec/buffer.c",
+ "webp/dec/io.c",
+ "webp/dec/layer.c",
+ "webp/dec/idec.c",
+ "webp/image_loader_webp.cpp"
+]
+
+env.drivers_sources+=webp_sources
+
+#env.add_source_files(env.drivers_sources, webp_sources)
+
+Export('env')
diff --git a/drivers/webpold/dec/alpha.c b/drivers/webpold/dec/alpha.c
new file mode 100644
index 0000000000..d1095fa555
--- /dev/null
+++ b/drivers/webpold/dec/alpha.c
@@ -0,0 +1,140 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Alpha-plane decompression.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <stdlib.h>
+#include "./vp8i.h"
+#include "./vp8li.h"
+#include "../utils/filters.h"
+#include "../utils/quant_levels.h"
+#include "../format_constants.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+// TODO(skal): move to dsp/ ?
+static void CopyPlane(const uint8_t* src, int src_stride,
+ uint8_t* dst, int dst_stride, int width, int height) {
+ while (height-- > 0) {
+ memcpy(dst, src, width);
+ src += src_stride;
+ dst += dst_stride;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Decodes the compressed data 'data' of size 'data_size' into the 'output'.
+// The 'output' buffer should be pre-allocated and must be of the same
+// dimension 'height'x'stride', as that of the image.
+//
+// Returns 1 on successfully decoding the compressed alpha and
+// 0 if either:
+// error in bit-stream header (invalid compression mode or filter), or
+// error returned by appropriate compression method.
+
+static int DecodeAlpha(const uint8_t* data, size_t data_size,
+ int width, int height, int stride, uint8_t* output) {
+ uint8_t* decoded_data = NULL;
+ const size_t decoded_size = height * width;
+ uint8_t* unfiltered_data = NULL;
+ WEBP_FILTER_TYPE filter;
+ int pre_processing;
+ int rsrv;
+ int ok = 0;
+ int method;
+
+ assert(width > 0 && height > 0 && stride >= width);
+ assert(data != NULL && output != NULL);
+
+ if (data_size <= ALPHA_HEADER_LEN) {
+ return 0;
+ }
+
+ method = (data[0] >> 0) & 0x03;
+ filter = (data[0] >> 2) & 0x03;
+ pre_processing = (data[0] >> 4) & 0x03;
+ rsrv = (data[0] >> 6) & 0x03;
+ if (method < ALPHA_NO_COMPRESSION ||
+ method > ALPHA_LOSSLESS_COMPRESSION ||
+ filter >= WEBP_FILTER_LAST ||
+ pre_processing > ALPHA_PREPROCESSED_LEVELS ||
+ rsrv != 0) {
+ return 0;
+ }
+
+ if (method == ALPHA_NO_COMPRESSION) {
+ ok = (data_size >= decoded_size);
+ decoded_data = (uint8_t*)data + ALPHA_HEADER_LEN;
+ } else {
+ decoded_data = (uint8_t*)malloc(decoded_size);
+ if (decoded_data == NULL) return 0;
+ ok = VP8LDecodeAlphaImageStream(width, height,
+ data + ALPHA_HEADER_LEN,
+ data_size - ALPHA_HEADER_LEN,
+ decoded_data);
+ }
+
+ if (ok) {
+ WebPFilterFunc unfilter_func = WebPUnfilters[filter];
+ if (unfilter_func != NULL) {
+ unfiltered_data = (uint8_t*)malloc(decoded_size);
+ if (unfiltered_data == NULL) {
+ ok = 0;
+ goto Error;
+ }
+ // TODO(vikas): Implement on-the-fly decoding & filter mechanism to decode
+ // and apply filter per image-row.
+ unfilter_func(decoded_data, width, height, 1, width, unfiltered_data);
+ // Construct raw_data (height x stride) from alpha data (height x width).
+ CopyPlane(unfiltered_data, width, output, stride, width, height);
+ free(unfiltered_data);
+ } else {
+ // Construct raw_data (height x stride) from alpha data (height x width).
+ CopyPlane(decoded_data, width, output, stride, width, height);
+ }
+ if (pre_processing == ALPHA_PREPROCESSED_LEVELS) {
+ ok = DequantizeLevels(decoded_data, width, height);
+ }
+ }
+
+ Error:
+ if (method != ALPHA_NO_COMPRESSION) {
+ free(decoded_data);
+ }
+ return ok;
+}
+
+//------------------------------------------------------------------------------
+
+const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
+ int row, int num_rows) {
+ const int stride = dec->pic_hdr_.width_;
+
+ if (row < 0 || num_rows < 0 || row + num_rows > dec->pic_hdr_.height_) {
+ return NULL; // sanity check.
+ }
+
+ if (row == 0) {
+ // Decode everything during the first call.
+ if (!DecodeAlpha(dec->alpha_data_, (size_t)dec->alpha_data_size_,
+ dec->pic_hdr_.width_, dec->pic_hdr_.height_, stride,
+ dec->alpha_plane_)) {
+ return NULL; // Error.
+ }
+ }
+
+ // Return a pointer to the current decoded row.
+ return dec->alpha_plane_ + row * stride;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dec/buffer.c b/drivers/webpold/dec/buffer.c
new file mode 100644
index 0000000000..c159f6f248
--- /dev/null
+++ b/drivers/webpold/dec/buffer.c
@@ -0,0 +1,215 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Everything about WebPDecBuffer
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <stdlib.h>
+
+#include "./vp8i.h"
+#include "./webpi.h"
+#include "../utils/utils.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// WebPDecBuffer
+
+// Number of bytes per pixel for the different color-spaces.
+static const int kModeBpp[MODE_LAST] = {
+ 3, 4, 3, 4, 4, 2, 2,
+ 4, 4, 4, 2, // pre-multiplied modes
+ 1, 1 };
+
+// Check that webp_csp_mode is within the bounds of WEBP_CSP_MODE.
+// Convert to an integer to handle both the unsigned/signed enum cases
+// without the need for casting to remove type limit warnings.
+static int IsValidColorspace(int webp_csp_mode) {
+ return (webp_csp_mode >= MODE_RGB && webp_csp_mode < MODE_LAST);
+}
+
+static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
+ int ok = 1;
+ const WEBP_CSP_MODE mode = buffer->colorspace;
+ const int width = buffer->width;
+ const int height = buffer->height;
+ if (!IsValidColorspace(mode)) {
+ ok = 0;
+ } else if (!WebPIsRGBMode(mode)) { // YUV checks
+ const WebPYUVABuffer* const buf = &buffer->u.YUVA;
+ const uint64_t y_size = (uint64_t)buf->y_stride * height;
+ const uint64_t u_size = (uint64_t)buf->u_stride * ((height + 1) / 2);
+ const uint64_t v_size = (uint64_t)buf->v_stride * ((height + 1) / 2);
+ const uint64_t a_size = (uint64_t)buf->a_stride * height;
+ ok &= (y_size <= buf->y_size);
+ ok &= (u_size <= buf->u_size);
+ ok &= (v_size <= buf->v_size);
+ ok &= (buf->y_stride >= width);
+ ok &= (buf->u_stride >= (width + 1) / 2);
+ ok &= (buf->v_stride >= (width + 1) / 2);
+ ok &= (buf->y != NULL);
+ ok &= (buf->u != NULL);
+ ok &= (buf->v != NULL);
+ if (mode == MODE_YUVA) {
+ ok &= (buf->a_stride >= width);
+ ok &= (a_size <= buf->a_size);
+ ok &= (buf->a != NULL);
+ }
+ } else { // RGB checks
+ const WebPRGBABuffer* const buf = &buffer->u.RGBA;
+ const uint64_t size = (uint64_t)buf->stride * height;
+ ok &= (size <= buf->size);
+ ok &= (buf->stride >= width * kModeBpp[mode]);
+ ok &= (buf->rgba != NULL);
+ }
+ return ok ? VP8_STATUS_OK : VP8_STATUS_INVALID_PARAM;
+}
+
+static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) {
+ const int w = buffer->width;
+ const int h = buffer->height;
+ const WEBP_CSP_MODE mode = buffer->colorspace;
+
+ if (w <= 0 || h <= 0 || !IsValidColorspace(mode)) {
+ return VP8_STATUS_INVALID_PARAM;
+ }
+
+ if (!buffer->is_external_memory && buffer->private_memory == NULL) {
+ uint8_t* output;
+ int uv_stride = 0, a_stride = 0;
+ uint64_t uv_size = 0, a_size = 0, total_size;
+ // We need memory and it hasn't been allocated yet.
+ // => initialize output buffer, now that dimensions are known.
+ const int stride = w * kModeBpp[mode];
+ const uint64_t size = (uint64_t)stride * h;
+
+ if (!WebPIsRGBMode(mode)) {
+ uv_stride = (w + 1) / 2;
+ uv_size = (uint64_t)uv_stride * ((h + 1) / 2);
+ if (mode == MODE_YUVA) {
+ a_stride = w;
+ a_size = (uint64_t)a_stride * h;
+ }
+ }
+ total_size = size + 2 * uv_size + a_size;
+
+ // Security/sanity checks
+ output = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*output));
+ if (output == NULL) {
+ return VP8_STATUS_OUT_OF_MEMORY;
+ }
+ buffer->private_memory = output;
+
+ if (!WebPIsRGBMode(mode)) { // YUVA initialization
+ WebPYUVABuffer* const buf = &buffer->u.YUVA;
+ buf->y = output;
+ buf->y_stride = stride;
+ buf->y_size = (size_t)size;
+ buf->u = output + size;
+ buf->u_stride = uv_stride;
+ buf->u_size = (size_t)uv_size;
+ buf->v = output + size + uv_size;
+ buf->v_stride = uv_stride;
+ buf->v_size = (size_t)uv_size;
+ if (mode == MODE_YUVA) {
+ buf->a = output + size + 2 * uv_size;
+ }
+ buf->a_size = (size_t)a_size;
+ buf->a_stride = a_stride;
+ } else { // RGBA initialization
+ WebPRGBABuffer* const buf = &buffer->u.RGBA;
+ buf->rgba = output;
+ buf->stride = stride;
+ buf->size = (size_t)size;
+ }
+ }
+ return CheckDecBuffer(buffer);
+}
+
+VP8StatusCode WebPAllocateDecBuffer(int w, int h,
+ const WebPDecoderOptions* const options,
+ WebPDecBuffer* const out) {
+ if (out == NULL || w <= 0 || h <= 0) {
+ return VP8_STATUS_INVALID_PARAM;
+ }
+ if (options != NULL) { // First, apply options if there is any.
+ if (options->use_cropping) {
+ const int cw = options->crop_width;
+ const int ch = options->crop_height;
+ const int x = options->crop_left & ~1;
+ const int y = options->crop_top & ~1;
+ if (x < 0 || y < 0 || cw <= 0 || ch <= 0 || x + cw > w || y + ch > h) {
+ return VP8_STATUS_INVALID_PARAM; // out of frame boundary.
+ }
+ w = cw;
+ h = ch;
+ }
+ if (options->use_scaling) {
+ if (options->scaled_width <= 0 || options->scaled_height <= 0) {
+ return VP8_STATUS_INVALID_PARAM;
+ }
+ w = options->scaled_width;
+ h = options->scaled_height;
+ }
+ }
+ out->width = w;
+ out->height = h;
+
+ // Then, allocate buffer for real
+ return AllocateBuffer(out);
+}
+
+//------------------------------------------------------------------------------
+// constructors / destructors
+
+int WebPInitDecBufferInternal(WebPDecBuffer* buffer, int version) {
+ if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
+ return 0; // version mismatch
+ }
+ if (buffer == NULL) return 0;
+ memset(buffer, 0, sizeof(*buffer));
+ return 1;
+}
+
+void WebPFreeDecBuffer(WebPDecBuffer* buffer) {
+ if (buffer != NULL) {
+ if (!buffer->is_external_memory)
+ free(buffer->private_memory);
+ buffer->private_memory = NULL;
+ }
+}
+
+void WebPCopyDecBuffer(const WebPDecBuffer* const src,
+ WebPDecBuffer* const dst) {
+ if (src != NULL && dst != NULL) {
+ *dst = *src;
+ if (src->private_memory != NULL) {
+ dst->is_external_memory = 1; // dst buffer doesn't own the memory.
+ dst->private_memory = NULL;
+ }
+ }
+}
+
+// Copy and transfer ownership from src to dst (beware of parameter order!)
+void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst) {
+ if (src != NULL && dst != NULL) {
+ *dst = *src;
+ if (src->private_memory != NULL) {
+ src->is_external_memory = 1; // src relinquishes ownership
+ src->private_memory = NULL;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dec/decode_vp8.h b/drivers/webpold/dec/decode_vp8.h
new file mode 100644
index 0000000000..c26a9fc891
--- /dev/null
+++ b/drivers/webpold/dec/decode_vp8.h
@@ -0,0 +1,182 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Low-level API for VP8 decoder
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_WEBP_DECODE_VP8_H_
+#define WEBP_WEBP_DECODE_VP8_H_
+
+#include "../decode.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Lower-level API
+//
+// These functions provide fine-grained control of the decoding process.
+// The call flow should resemble:
+//
+// VP8Io io;
+// VP8InitIo(&io);
+// io.data = data;
+// io.data_size = size;
+// /* customize io's functions (setup()/put()/teardown()) if needed. */
+//
+// VP8Decoder* dec = VP8New();
+// bool ok = VP8Decode(dec);
+// if (!ok) printf("Error: %s\n", VP8StatusMessage(dec));
+// VP8Delete(dec);
+// return ok;
+
+// Input / Output
+typedef struct VP8Io VP8Io;
+typedef int (*VP8IoPutHook)(const VP8Io* io);
+typedef int (*VP8IoSetupHook)(VP8Io* io);
+typedef void (*VP8IoTeardownHook)(const VP8Io* io);
+
+struct VP8Io {
+ // set by VP8GetHeaders()
+ int width, height; // picture dimensions, in pixels (invariable).
+ // These are the original, uncropped dimensions.
+ // The actual area passed to put() is stored
+ // in mb_w / mb_h fields.
+
+ // set before calling put()
+ int mb_y; // position of the current rows (in pixels)
+ int mb_w; // number of columns in the sample
+ int mb_h; // number of rows in the sample
+ const uint8_t* y, *u, *v; // rows to copy (in yuv420 format)
+ int y_stride; // row stride for luma
+ int uv_stride; // row stride for chroma
+
+ void* opaque; // user data
+
+ // called when fresh samples are available. Currently, samples are in
+ // YUV420 format, and can be up to width x 24 in size (depending on the
+ // in-loop filtering level, e.g.). Should return false in case of error
+ // or abort request. The actual size of the area to update is mb_w x mb_h
+ // in size, taking cropping into account.
+ VP8IoPutHook put;
+
+ // called just before starting to decode the blocks.
+ // Must return false in case of setup error, true otherwise. If false is
+ // returned, teardown() will NOT be called. But if the setup succeeded
+ // and true is returned, then teardown() will always be called afterward.
+ VP8IoSetupHook setup;
+
+ // Called just after block decoding is finished (or when an error occurred
+ // during put()). Is NOT called if setup() failed.
+ VP8IoTeardownHook teardown;
+
+ // this is a recommendation for the user-side yuv->rgb converter. This flag
+ // is set when calling setup() hook and can be overwritten by it. It then
+ // can be taken into consideration during the put() method.
+ int fancy_upsampling;
+
+ // Input buffer.
+ size_t data_size;
+ const uint8_t* data;
+
+ // If true, in-loop filtering will not be performed even if present in the
+ // bitstream. Switching off filtering may speed up decoding at the expense
+ // of more visible blocking. Note that output will also be non-compliant
+ // with the VP8 specifications.
+ int bypass_filtering;
+
+ // Cropping parameters.
+ int use_cropping;
+ int crop_left, crop_right, crop_top, crop_bottom;
+
+ // Scaling parameters.
+ int use_scaling;
+ int scaled_width, scaled_height;
+
+ // If non NULL, pointer to the alpha data (if present) corresponding to the
+ // start of the current row (That is: it is pre-offset by mb_y and takes
+ // cropping into account).
+ const uint8_t* a;
+};
+
+// Internal, version-checked, entry point
+int VP8InitIoInternal(VP8Io* const, int);
+
+// Set the custom IO function pointers and user-data. The setter for IO hooks
+// should be called before initiating incremental decoding. Returns true if
+// WebPIDecoder object is successfully modified, false otherwise.
+int WebPISetIOHooks(WebPIDecoder* const idec,
+ VP8IoPutHook put,
+ VP8IoSetupHook setup,
+ VP8IoTeardownHook teardown,
+ void* user_data);
+
+// Main decoding object. This is an opaque structure.
+typedef struct VP8Decoder VP8Decoder;
+
+// Create a new decoder object.
+VP8Decoder* VP8New(void);
+
+// Must be called to make sure 'io' is initialized properly.
+// Returns false in case of version mismatch. Upon such failure, no other
+// decoding function should be called (VP8Decode, VP8GetHeaders, ...)
+static WEBP_INLINE int VP8InitIo(VP8Io* const io) {
+ return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION);
+}
+
+// Start decoding a new picture. Returns true if ok.
+int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io);
+
+// Decode a picture. Will call VP8GetHeaders() if it wasn't done already.
+// Returns false in case of error.
+int VP8Decode(VP8Decoder* const dec, VP8Io* const io);
+
+// Return current status of the decoder:
+VP8StatusCode VP8Status(VP8Decoder* const dec);
+
+// return readable string corresponding to the last status.
+const char* VP8StatusMessage(VP8Decoder* const dec);
+
+// Resets the decoder in its initial state, reclaiming memory.
+// Not a mandatory call between calls to VP8Decode().
+void VP8Clear(VP8Decoder* const dec);
+
+// Destroy the decoder object.
+void VP8Delete(VP8Decoder* const dec);
+
+//------------------------------------------------------------------------------
+// Miscellaneous VP8/VP8L bitstream probing functions.
+
+// Returns true if the next 3 bytes in data contain the VP8 signature.
+WEBP_EXTERN(int) VP8CheckSignature(const uint8_t* const data, size_t data_size);
+
+// Validates the VP8 data-header and retrieves basic header information viz
+// width and height. Returns 0 in case of formatting error. *width/*height
+// can be passed NULL.
+WEBP_EXTERN(int) VP8GetInfo(
+ const uint8_t* data,
+ size_t data_size, // data available so far
+ size_t chunk_size, // total data size expected in the chunk
+ int* const width, int* const height);
+
+// Returns true if the next byte(s) in data is a VP8L signature.
+WEBP_EXTERN(int) VP8LCheckSignature(const uint8_t* const data, size_t size);
+
+// Validates the VP8L data-header and retrieves basic header information viz
+// width, height and alpha. Returns 0 in case of formatting error.
+// width/height/has_alpha can be passed NULL.
+WEBP_EXTERN(int) VP8LGetInfo(
+ const uint8_t* data, size_t data_size, // data available so far
+ int* const width, int* const height, int* const has_alpha);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_WEBP_DECODE_VP8_H_ */
diff --git a/drivers/webpold/dec/frame.c b/drivers/webpold/dec/frame.c
new file mode 100644
index 0000000000..9c91a48e17
--- /dev/null
+++ b/drivers/webpold/dec/frame.c
@@ -0,0 +1,679 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Frame-reconstruction function. Memory allocation.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <stdlib.h>
+#include "./vp8i.h"
+#include "../utils/utils.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define ALIGN_MASK (32 - 1)
+
+//------------------------------------------------------------------------------
+// Filtering
+
+// kFilterExtraRows[] = How many extra lines are needed on the MB boundary
+// for caching, given a filtering level.
+// Simple filter: up to 2 luma samples are read and 1 is written.
+// Complex filter: up to 4 luma samples are read and 3 are written. Same for
+// U/V, so it's 8 samples total (because of the 2x upsampling).
+static const uint8_t kFilterExtraRows[3] = { 0, 2, 8 };
+
+static WEBP_INLINE int hev_thresh_from_level(int level, int keyframe) {
+ if (keyframe) {
+ return (level >= 40) ? 2 : (level >= 15) ? 1 : 0;
+ } else {
+ return (level >= 40) ? 3 : (level >= 20) ? 2 : (level >= 15) ? 1 : 0;
+ }
+}
+
+static void DoFilter(const VP8Decoder* const dec, int mb_x, int mb_y) {
+ const VP8ThreadContext* const ctx = &dec->thread_ctx_;
+ const int y_bps = dec->cache_y_stride_;
+ VP8FInfo* const f_info = ctx->f_info_ + mb_x;
+ uint8_t* const y_dst = dec->cache_y_ + ctx->id_ * 16 * y_bps + mb_x * 16;
+ const int level = f_info->f_level_;
+ const int ilevel = f_info->f_ilevel_;
+ const int limit = 2 * level + ilevel;
+ if (level == 0) {
+ return;
+ }
+ if (dec->filter_type_ == 1) { // simple
+ if (mb_x > 0) {
+ VP8SimpleHFilter16(y_dst, y_bps, limit + 4);
+ }
+ if (f_info->f_inner_) {
+ VP8SimpleHFilter16i(y_dst, y_bps, limit);
+ }
+ if (mb_y > 0) {
+ VP8SimpleVFilter16(y_dst, y_bps, limit + 4);
+ }
+ if (f_info->f_inner_) {
+ VP8SimpleVFilter16i(y_dst, y_bps, limit);
+ }
+ } else { // complex
+ const int uv_bps = dec->cache_uv_stride_;
+ uint8_t* const u_dst = dec->cache_u_ + ctx->id_ * 8 * uv_bps + mb_x * 8;
+ uint8_t* const v_dst = dec->cache_v_ + ctx->id_ * 8 * uv_bps + mb_x * 8;
+ const int hev_thresh =
+ hev_thresh_from_level(level, dec->frm_hdr_.key_frame_);
+ if (mb_x > 0) {
+ VP8HFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh);
+ VP8HFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh);
+ }
+ if (f_info->f_inner_) {
+ VP8HFilter16i(y_dst, y_bps, limit, ilevel, hev_thresh);
+ VP8HFilter8i(u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh);
+ }
+ if (mb_y > 0) {
+ VP8VFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh);
+ VP8VFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh);
+ }
+ if (f_info->f_inner_) {
+ VP8VFilter16i(y_dst, y_bps, limit, ilevel, hev_thresh);
+ VP8VFilter8i(u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh);
+ }
+ }
+}
+
+// Filter the decoded macroblock row (if needed)
+static void FilterRow(const VP8Decoder* const dec) {
+ int mb_x;
+ const int mb_y = dec->thread_ctx_.mb_y_;
+ assert(dec->thread_ctx_.filter_row_);
+ for (mb_x = dec->tl_mb_x_; mb_x < dec->br_mb_x_; ++mb_x) {
+ DoFilter(dec, mb_x, mb_y);
+ }
+}
+
+//------------------------------------------------------------------------------
+
+void VP8StoreBlock(VP8Decoder* const dec) {
+ if (dec->filter_type_ > 0) {
+ VP8FInfo* const info = dec->f_info_ + dec->mb_x_;
+ const int skip = dec->mb_info_[dec->mb_x_].skip_;
+ int level = dec->filter_levels_[dec->segment_];
+ if (dec->filter_hdr_.use_lf_delta_) {
+ // TODO(skal): only CURRENT is handled for now.
+ level += dec->filter_hdr_.ref_lf_delta_[0];
+ if (dec->is_i4x4_) {
+ level += dec->filter_hdr_.mode_lf_delta_[0];
+ }
+ }
+ level = (level < 0) ? 0 : (level > 63) ? 63 : level;
+ info->f_level_ = level;
+
+ if (dec->filter_hdr_.sharpness_ > 0) {
+ if (dec->filter_hdr_.sharpness_ > 4) {
+ level >>= 2;
+ } else {
+ level >>= 1;
+ }
+ if (level > 9 - dec->filter_hdr_.sharpness_) {
+ level = 9 - dec->filter_hdr_.sharpness_;
+ }
+ }
+
+ info->f_ilevel_ = (level < 1) ? 1 : level;
+ info->f_inner_ = (!skip || dec->is_i4x4_);
+ }
+ {
+ // Transfer samples to row cache
+ int y;
+ const int y_offset = dec->cache_id_ * 16 * dec->cache_y_stride_;
+ const int uv_offset = dec->cache_id_ * 8 * dec->cache_uv_stride_;
+ uint8_t* const ydst = dec->cache_y_ + dec->mb_x_ * 16 + y_offset;
+ uint8_t* const udst = dec->cache_u_ + dec->mb_x_ * 8 + uv_offset;
+ uint8_t* const vdst = dec->cache_v_ + dec->mb_x_ * 8 + uv_offset;
+ for (y = 0; y < 16; ++y) {
+ memcpy(ydst + y * dec->cache_y_stride_,
+ dec->yuv_b_ + Y_OFF + y * BPS, 16);
+ }
+ for (y = 0; y < 8; ++y) {
+ memcpy(udst + y * dec->cache_uv_stride_,
+ dec->yuv_b_ + U_OFF + y * BPS, 8);
+ memcpy(vdst + y * dec->cache_uv_stride_,
+ dec->yuv_b_ + V_OFF + y * BPS, 8);
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// This function is called after a row of macroblocks is finished decoding.
+// It also takes into account the following restrictions:
+// * In case of in-loop filtering, we must hold off sending some of the bottom
+// pixels as they are yet unfiltered. They will be when the next macroblock
+// row is decoded. Meanwhile, we must preserve them by rotating them in the
+// cache area. This doesn't hold for the very bottom row of the uncropped
+// picture of course.
+// * we must clip the remaining pixels against the cropping area. The VP8Io
+// struct must have the following fields set correctly before calling put():
+
+#define MACROBLOCK_VPOS(mb_y) ((mb_y) * 16) // vertical position of a MB
+
+// Finalize and transmit a complete row. Return false in case of user-abort.
+static int FinishRow(VP8Decoder* const dec, VP8Io* const io) {
+ int ok = 1;
+ const VP8ThreadContext* const ctx = &dec->thread_ctx_;
+ const int extra_y_rows = kFilterExtraRows[dec->filter_type_];
+ const int ysize = extra_y_rows * dec->cache_y_stride_;
+ const int uvsize = (extra_y_rows / 2) * dec->cache_uv_stride_;
+ const int y_offset = ctx->id_ * 16 * dec->cache_y_stride_;
+ const int uv_offset = ctx->id_ * 8 * dec->cache_uv_stride_;
+ uint8_t* const ydst = dec->cache_y_ - ysize + y_offset;
+ uint8_t* const udst = dec->cache_u_ - uvsize + uv_offset;
+ uint8_t* const vdst = dec->cache_v_ - uvsize + uv_offset;
+ const int first_row = (ctx->mb_y_ == 0);
+ const int last_row = (ctx->mb_y_ >= dec->br_mb_y_ - 1);
+ int y_start = MACROBLOCK_VPOS(ctx->mb_y_);
+ int y_end = MACROBLOCK_VPOS(ctx->mb_y_ + 1);
+
+ if (ctx->filter_row_) {
+ FilterRow(dec);
+ }
+
+ if (io->put) {
+ if (!first_row) {
+ y_start -= extra_y_rows;
+ io->y = ydst;
+ io->u = udst;
+ io->v = vdst;
+ } else {
+ io->y = dec->cache_y_ + y_offset;
+ io->u = dec->cache_u_ + uv_offset;
+ io->v = dec->cache_v_ + uv_offset;
+ }
+
+ if (!last_row) {
+ y_end -= extra_y_rows;
+ }
+ if (y_end > io->crop_bottom) {
+ y_end = io->crop_bottom; // make sure we don't overflow on last row.
+ }
+ io->a = NULL;
+ if (dec->alpha_data_ != NULL && y_start < y_end) {
+ // TODO(skal): several things to correct here:
+ // * testing presence of alpha with dec->alpha_data_ is not a good idea
+ // * we're actually decompressing the full plane only once. It should be
+ // more obvious from signature.
+ // * we could free alpha_data_ right after this call, but we don't own.
+ io->a = VP8DecompressAlphaRows(dec, y_start, y_end - y_start);
+ if (io->a == NULL) {
+ return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
+ "Could not decode alpha data.");
+ }
+ }
+ if (y_start < io->crop_top) {
+ const int delta_y = io->crop_top - y_start;
+ y_start = io->crop_top;
+ assert(!(delta_y & 1));
+ io->y += dec->cache_y_stride_ * delta_y;
+ io->u += dec->cache_uv_stride_ * (delta_y >> 1);
+ io->v += dec->cache_uv_stride_ * (delta_y >> 1);
+ if (io->a != NULL) {
+ io->a += io->width * delta_y;
+ }
+ }
+ if (y_start < y_end) {
+ io->y += io->crop_left;
+ io->u += io->crop_left >> 1;
+ io->v += io->crop_left >> 1;
+ if (io->a != NULL) {
+ io->a += io->crop_left;
+ }
+ io->mb_y = y_start - io->crop_top;
+ io->mb_w = io->crop_right - io->crop_left;
+ io->mb_h = y_end - y_start;
+ ok = io->put(io);
+ }
+ }
+ // rotate top samples if needed
+ if (ctx->id_ + 1 == dec->num_caches_) {
+ if (!last_row) {
+ memcpy(dec->cache_y_ - ysize, ydst + 16 * dec->cache_y_stride_, ysize);
+ memcpy(dec->cache_u_ - uvsize, udst + 8 * dec->cache_uv_stride_, uvsize);
+ memcpy(dec->cache_v_ - uvsize, vdst + 8 * dec->cache_uv_stride_, uvsize);
+ }
+ }
+
+ return ok;
+}
+
+#undef MACROBLOCK_VPOS
+
+//------------------------------------------------------------------------------
+
+int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io) {
+ int ok = 1;
+ VP8ThreadContext* const ctx = &dec->thread_ctx_;
+ if (!dec->use_threads_) {
+ // ctx->id_ and ctx->f_info_ are already set
+ ctx->mb_y_ = dec->mb_y_;
+ ctx->filter_row_ = dec->filter_row_;
+ ok = FinishRow(dec, io);
+ } else {
+ WebPWorker* const worker = &dec->worker_;
+ // Finish previous job *before* updating context
+ ok &= WebPWorkerSync(worker);
+ assert(worker->status_ == OK);
+ if (ok) { // spawn a new deblocking/output job
+ ctx->io_ = *io;
+ ctx->id_ = dec->cache_id_;
+ ctx->mb_y_ = dec->mb_y_;
+ ctx->filter_row_ = dec->filter_row_;
+ if (ctx->filter_row_) { // just swap filter info
+ VP8FInfo* const tmp = ctx->f_info_;
+ ctx->f_info_ = dec->f_info_;
+ dec->f_info_ = tmp;
+ }
+ WebPWorkerLaunch(worker);
+ if (++dec->cache_id_ == dec->num_caches_) {
+ dec->cache_id_ = 0;
+ }
+ }
+ }
+ return ok;
+}
+
+//------------------------------------------------------------------------------
+// Finish setting up the decoding parameter once user's setup() is called.
+
+VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) {
+ // Call setup() first. This may trigger additional decoding features on 'io'.
+ // Note: Afterward, we must call teardown() not matter what.
+ if (io->setup && !io->setup(io)) {
+ VP8SetError(dec, VP8_STATUS_USER_ABORT, "Frame setup failed");
+ return dec->status_;
+ }
+
+ // Disable filtering per user request
+ if (io->bypass_filtering) {
+ dec->filter_type_ = 0;
+ }
+ // TODO(skal): filter type / strength / sharpness forcing
+
+ // Define the area where we can skip in-loop filtering, in case of cropping.
+ //
+ // 'Simple' filter reads two luma samples outside of the macroblock and
+ // and filters one. It doesn't filter the chroma samples. Hence, we can
+ // avoid doing the in-loop filtering before crop_top/crop_left position.
+ // For the 'Complex' filter, 3 samples are read and up to 3 are filtered.
+ // Means: there's a dependency chain that goes all the way up to the
+ // top-left corner of the picture (MB #0). We must filter all the previous
+ // macroblocks.
+ // TODO(skal): add an 'approximate_decoding' option, that won't produce
+ // a 1:1 bit-exactness for complex filtering?
+ {
+ const int extra_pixels = kFilterExtraRows[dec->filter_type_];
+ if (dec->filter_type_ == 2) {
+ // For complex filter, we need to preserve the dependency chain.
+ dec->tl_mb_x_ = 0;
+ dec->tl_mb_y_ = 0;
+ } else {
+ // For simple filter, we can filter only the cropped region.
+ // We include 'extra_pixels' on the other side of the boundary, since
+ // vertical or horizontal filtering of the previous macroblock can
+ // modify some abutting pixels.
+ dec->tl_mb_x_ = (io->crop_left - extra_pixels) >> 4;
+ dec->tl_mb_y_ = (io->crop_top - extra_pixels) >> 4;
+ if (dec->tl_mb_x_ < 0) dec->tl_mb_x_ = 0;
+ if (dec->tl_mb_y_ < 0) dec->tl_mb_y_ = 0;
+ }
+ // We need some 'extra' pixels on the right/bottom.
+ dec->br_mb_y_ = (io->crop_bottom + 15 + extra_pixels) >> 4;
+ dec->br_mb_x_ = (io->crop_right + 15 + extra_pixels) >> 4;
+ if (dec->br_mb_x_ > dec->mb_w_) {
+ dec->br_mb_x_ = dec->mb_w_;
+ }
+ if (dec->br_mb_y_ > dec->mb_h_) {
+ dec->br_mb_y_ = dec->mb_h_;
+ }
+ }
+ return VP8_STATUS_OK;
+}
+
+int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io) {
+ int ok = 1;
+ if (dec->use_threads_) {
+ ok = WebPWorkerSync(&dec->worker_);
+ }
+
+ if (io->teardown) {
+ io->teardown(io);
+ }
+ return ok;
+}
+
+//------------------------------------------------------------------------------
+// For multi-threaded decoding we need to use 3 rows of 16 pixels as delay line.
+//
+// Reason is: the deblocking filter cannot deblock the bottom horizontal edges
+// immediately, and needs to wait for first few rows of the next macroblock to
+// be decoded. Hence, deblocking is lagging behind by 4 or 8 pixels (depending
+// on strength).
+// With two threads, the vertical positions of the rows being decoded are:
+// Decode: [ 0..15][16..31][32..47][48..63][64..79][...
+// Deblock: [ 0..11][12..27][28..43][44..59][...
+// If we use two threads and two caches of 16 pixels, the sequence would be:
+// Decode: [ 0..15][16..31][ 0..15!!][16..31][ 0..15][...
+// Deblock: [ 0..11][12..27!!][-4..11][12..27][...
+// The problem occurs during row [12..15!!] that both the decoding and
+// deblocking threads are writing simultaneously.
+// With 3 cache lines, one get a safe write pattern:
+// Decode: [ 0..15][16..31][32..47][ 0..15][16..31][32..47][0..
+// Deblock: [ 0..11][12..27][28..43][-4..11][12..27][28...
+// Note that multi-threaded output _without_ deblocking can make use of two
+// cache lines of 16 pixels only, since there's no lagging behind. The decoding
+// and output process have non-concurrent writing:
+// Decode: [ 0..15][16..31][ 0..15][16..31][...
+// io->put: [ 0..15][16..31][ 0..15][...
+
+#define MT_CACHE_LINES 3
+#define ST_CACHE_LINES 1 // 1 cache row only for single-threaded case
+
+// Initialize multi/single-thread worker
+static int InitThreadContext(VP8Decoder* const dec) {
+ dec->cache_id_ = 0;
+ if (dec->use_threads_) {
+ WebPWorker* const worker = &dec->worker_;
+ if (!WebPWorkerReset(worker)) {
+ return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY,
+ "thread initialization failed.");
+ }
+ worker->data1 = dec;
+ worker->data2 = (void*)&dec->thread_ctx_.io_;
+ worker->hook = (WebPWorkerHook)FinishRow;
+ dec->num_caches_ =
+ (dec->filter_type_ > 0) ? MT_CACHE_LINES : MT_CACHE_LINES - 1;
+ } else {
+ dec->num_caches_ = ST_CACHE_LINES;
+ }
+ return 1;
+}
+
+#undef MT_CACHE_LINES
+#undef ST_CACHE_LINES
+
+//------------------------------------------------------------------------------
+// Memory setup
+
+static int AllocateMemory(VP8Decoder* const dec) {
+ const int num_caches = dec->num_caches_;
+ const int mb_w = dec->mb_w_;
+ // Note: we use 'size_t' when there's no overflow risk, uint64_t otherwise.
+ const size_t intra_pred_mode_size = 4 * mb_w * sizeof(uint8_t);
+ const size_t top_size = (16 + 8 + 8) * mb_w;
+ const size_t mb_info_size = (mb_w + 1) * sizeof(VP8MB);
+ const size_t f_info_size =
+ (dec->filter_type_ > 0) ?
+ mb_w * (dec->use_threads_ ? 2 : 1) * sizeof(VP8FInfo)
+ : 0;
+ const size_t yuv_size = YUV_SIZE * sizeof(*dec->yuv_b_);
+ const size_t coeffs_size = 384 * sizeof(*dec->coeffs_);
+ const size_t cache_height = (16 * num_caches
+ + kFilterExtraRows[dec->filter_type_]) * 3 / 2;
+ const size_t cache_size = top_size * cache_height;
+ // alpha_size is the only one that scales as width x height.
+ const uint64_t alpha_size = (dec->alpha_data_ != NULL) ?
+ (uint64_t)dec->pic_hdr_.width_ * dec->pic_hdr_.height_ : 0ULL;
+ const uint64_t needed = (uint64_t)intra_pred_mode_size
+ + top_size + mb_info_size + f_info_size
+ + yuv_size + coeffs_size
+ + cache_size + alpha_size + ALIGN_MASK;
+ uint8_t* mem;
+
+ if (needed != (size_t)needed) return 0; // check for overflow
+ if (needed > dec->mem_size_) {
+ free(dec->mem_);
+ dec->mem_size_ = 0;
+ dec->mem_ = WebPSafeMalloc(needed, sizeof(uint8_t));
+ if (dec->mem_ == NULL) {
+ return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY,
+ "no memory during frame initialization.");
+ }
+ // down-cast is ok, thanks to WebPSafeAlloc() above.
+ dec->mem_size_ = (size_t)needed;
+ }
+
+ mem = (uint8_t*)dec->mem_;
+ dec->intra_t_ = (uint8_t*)mem;
+ mem += intra_pred_mode_size;
+
+ dec->y_t_ = (uint8_t*)mem;
+ mem += 16 * mb_w;
+ dec->u_t_ = (uint8_t*)mem;
+ mem += 8 * mb_w;
+ dec->v_t_ = (uint8_t*)mem;
+ mem += 8 * mb_w;
+
+ dec->mb_info_ = ((VP8MB*)mem) + 1;
+ mem += mb_info_size;
+
+ dec->f_info_ = f_info_size ? (VP8FInfo*)mem : NULL;
+ mem += f_info_size;
+ dec->thread_ctx_.id_ = 0;
+ dec->thread_ctx_.f_info_ = dec->f_info_;
+ if (dec->use_threads_) {
+ // secondary cache line. The deblocking process need to make use of the
+ // filtering strength from previous macroblock row, while the new ones
+ // are being decoded in parallel. We'll just swap the pointers.
+ dec->thread_ctx_.f_info_ += mb_w;
+ }
+
+ mem = (uint8_t*)((uintptr_t)(mem + ALIGN_MASK) & ~ALIGN_MASK);
+ assert((yuv_size & ALIGN_MASK) == 0);
+ dec->yuv_b_ = (uint8_t*)mem;
+ mem += yuv_size;
+
+ dec->coeffs_ = (int16_t*)mem;
+ mem += coeffs_size;
+
+ dec->cache_y_stride_ = 16 * mb_w;
+ dec->cache_uv_stride_ = 8 * mb_w;
+ {
+ const int extra_rows = kFilterExtraRows[dec->filter_type_];
+ const int extra_y = extra_rows * dec->cache_y_stride_;
+ const int extra_uv = (extra_rows / 2) * dec->cache_uv_stride_;
+ dec->cache_y_ = ((uint8_t*)mem) + extra_y;
+ dec->cache_u_ = dec->cache_y_
+ + 16 * num_caches * dec->cache_y_stride_ + extra_uv;
+ dec->cache_v_ = dec->cache_u_
+ + 8 * num_caches * dec->cache_uv_stride_ + extra_uv;
+ dec->cache_id_ = 0;
+ }
+ mem += cache_size;
+
+ // alpha plane
+ dec->alpha_plane_ = alpha_size ? (uint8_t*)mem : NULL;
+ mem += alpha_size;
+
+ // note: left-info is initialized once for all.
+ memset(dec->mb_info_ - 1, 0, mb_info_size);
+
+ // initialize top
+ memset(dec->intra_t_, B_DC_PRED, intra_pred_mode_size);
+
+ return 1;
+}
+
+static void InitIo(VP8Decoder* const dec, VP8Io* io) {
+ // prepare 'io'
+ io->mb_y = 0;
+ io->y = dec->cache_y_;
+ io->u = dec->cache_u_;
+ io->v = dec->cache_v_;
+ io->y_stride = dec->cache_y_stride_;
+ io->uv_stride = dec->cache_uv_stride_;
+ io->a = NULL;
+}
+
+int VP8InitFrame(VP8Decoder* const dec, VP8Io* io) {
+ if (!InitThreadContext(dec)) return 0; // call first. Sets dec->num_caches_.
+ if (!AllocateMemory(dec)) return 0;
+ InitIo(dec, io);
+ VP8DspInit(); // Init critical function pointers and look-up tables.
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Main reconstruction function.
+
+static const int kScan[16] = {
+ 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS,
+ 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS,
+ 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS,
+ 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS
+};
+
+static WEBP_INLINE int CheckMode(VP8Decoder* const dec, int mode) {
+ if (mode == B_DC_PRED) {
+ if (dec->mb_x_ == 0) {
+ return (dec->mb_y_ == 0) ? B_DC_PRED_NOTOPLEFT : B_DC_PRED_NOLEFT;
+ } else {
+ return (dec->mb_y_ == 0) ? B_DC_PRED_NOTOP : B_DC_PRED;
+ }
+ }
+ return mode;
+}
+
+static WEBP_INLINE void Copy32b(uint8_t* dst, uint8_t* src) {
+ *(uint32_t*)dst = *(uint32_t*)src;
+}
+
+void VP8ReconstructBlock(VP8Decoder* const dec) {
+ uint8_t* const y_dst = dec->yuv_b_ + Y_OFF;
+ uint8_t* const u_dst = dec->yuv_b_ + U_OFF;
+ uint8_t* const v_dst = dec->yuv_b_ + V_OFF;
+
+ // Rotate in the left samples from previously decoded block. We move four
+ // pixels at a time for alignment reason, and because of in-loop filter.
+ if (dec->mb_x_ > 0) {
+ int j;
+ for (j = -1; j < 16; ++j) {
+ Copy32b(&y_dst[j * BPS - 4], &y_dst[j * BPS + 12]);
+ }
+ for (j = -1; j < 8; ++j) {
+ Copy32b(&u_dst[j * BPS - 4], &u_dst[j * BPS + 4]);
+ Copy32b(&v_dst[j * BPS - 4], &v_dst[j * BPS + 4]);
+ }
+ } else {
+ int j;
+ for (j = 0; j < 16; ++j) {
+ y_dst[j * BPS - 1] = 129;
+ }
+ for (j = 0; j < 8; ++j) {
+ u_dst[j * BPS - 1] = 129;
+ v_dst[j * BPS - 1] = 129;
+ }
+ // Init top-left sample on left column too
+ if (dec->mb_y_ > 0) {
+ y_dst[-1 - BPS] = u_dst[-1 - BPS] = v_dst[-1 - BPS] = 129;
+ }
+ }
+ {
+ // bring top samples into the cache
+ uint8_t* const top_y = dec->y_t_ + dec->mb_x_ * 16;
+ uint8_t* const top_u = dec->u_t_ + dec->mb_x_ * 8;
+ uint8_t* const top_v = dec->v_t_ + dec->mb_x_ * 8;
+ const int16_t* coeffs = dec->coeffs_;
+ int n;
+
+ if (dec->mb_y_ > 0) {
+ memcpy(y_dst - BPS, top_y, 16);
+ memcpy(u_dst - BPS, top_u, 8);
+ memcpy(v_dst - BPS, top_v, 8);
+ } else if (dec->mb_x_ == 0) {
+ // we only need to do this init once at block (0,0).
+ // Afterward, it remains valid for the whole topmost row.
+ memset(y_dst - BPS - 1, 127, 16 + 4 + 1);
+ memset(u_dst - BPS - 1, 127, 8 + 1);
+ memset(v_dst - BPS - 1, 127, 8 + 1);
+ }
+
+ // predict and add residuals
+
+ if (dec->is_i4x4_) { // 4x4
+ uint32_t* const top_right = (uint32_t*)(y_dst - BPS + 16);
+
+ if (dec->mb_y_ > 0) {
+ if (dec->mb_x_ >= dec->mb_w_ - 1) { // on rightmost border
+ top_right[0] = top_y[15] * 0x01010101u;
+ } else {
+ memcpy(top_right, top_y + 16, sizeof(*top_right));
+ }
+ }
+ // replicate the top-right pixels below
+ top_right[BPS] = top_right[2 * BPS] = top_right[3 * BPS] = top_right[0];
+
+ // predict and add residues for all 4x4 blocks in turn.
+ for (n = 0; n < 16; n++) {
+ uint8_t* const dst = y_dst + kScan[n];
+ VP8PredLuma4[dec->imodes_[n]](dst);
+ if (dec->non_zero_ac_ & (1 << n)) {
+ VP8Transform(coeffs + n * 16, dst, 0);
+ } else if (dec->non_zero_ & (1 << n)) { // only DC is present
+ VP8TransformDC(coeffs + n * 16, dst);
+ }
+ }
+ } else { // 16x16
+ const int pred_func = CheckMode(dec, dec->imodes_[0]);
+ VP8PredLuma16[pred_func](y_dst);
+ if (dec->non_zero_) {
+ for (n = 0; n < 16; n++) {
+ uint8_t* const dst = y_dst + kScan[n];
+ if (dec->non_zero_ac_ & (1 << n)) {
+ VP8Transform(coeffs + n * 16, dst, 0);
+ } else if (dec->non_zero_ & (1 << n)) { // only DC is present
+ VP8TransformDC(coeffs + n * 16, dst);
+ }
+ }
+ }
+ }
+ {
+ // Chroma
+ const int pred_func = CheckMode(dec, dec->uvmode_);
+ VP8PredChroma8[pred_func](u_dst);
+ VP8PredChroma8[pred_func](v_dst);
+
+ if (dec->non_zero_ & 0x0f0000) { // chroma-U
+ const int16_t* const u_coeffs = dec->coeffs_ + 16 * 16;
+ if (dec->non_zero_ac_ & 0x0f0000) {
+ VP8TransformUV(u_coeffs, u_dst);
+ } else {
+ VP8TransformDCUV(u_coeffs, u_dst);
+ }
+ }
+ if (dec->non_zero_ & 0xf00000) { // chroma-V
+ const int16_t* const v_coeffs = dec->coeffs_ + 20 * 16;
+ if (dec->non_zero_ac_ & 0xf00000) {
+ VP8TransformUV(v_coeffs, v_dst);
+ } else {
+ VP8TransformDCUV(v_coeffs, v_dst);
+ }
+ }
+
+ // stash away top samples for next block
+ if (dec->mb_y_ < dec->mb_h_ - 1) {
+ memcpy(top_y, y_dst + 15 * BPS, 16);
+ memcpy(top_u, u_dst + 7 * BPS, 8);
+ memcpy(top_v, v_dst + 7 * BPS, 8);
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dec/idec.c b/drivers/webpold/dec/idec.c
new file mode 100644
index 0000000000..7df790ced8
--- /dev/null
+++ b/drivers/webpold/dec/idec.c
@@ -0,0 +1,785 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Incremental decoding
+//
+// Author: somnath@google.com (Somnath Banerjee)
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "./webpi.h"
+#include "./vp8i.h"
+#include "../utils/utils.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+// In append mode, buffer allocations increase as multiples of this value.
+// Needs to be a power of 2.
+#define CHUNK_SIZE 4096
+#define MAX_MB_SIZE 4096
+
+//------------------------------------------------------------------------------
+// Data structures for memory and states
+
+// Decoding states. State normally flows like HEADER->PARTS0->DATA->DONE.
+// If there is any error the decoder goes into state ERROR.
+typedef enum {
+ STATE_PRE_VP8, // All data before that of the first VP8 chunk.
+ STATE_VP8_FRAME_HEADER, // For VP8 Frame header (within VP8 chunk).
+ STATE_VP8_PARTS0,
+ STATE_VP8_DATA,
+ STATE_VP8L_HEADER,
+ STATE_VP8L_DATA,
+ STATE_DONE,
+ STATE_ERROR
+} DecState;
+
+// Operating state for the MemBuffer
+typedef enum {
+ MEM_MODE_NONE = 0,
+ MEM_MODE_APPEND,
+ MEM_MODE_MAP
+} MemBufferMode;
+
+// storage for partition #0 and partial data (in a rolling fashion)
+typedef struct {
+ MemBufferMode mode_; // Operation mode
+ size_t start_; // start location of the data to be decoded
+ size_t end_; // end location
+ size_t buf_size_; // size of the allocated buffer
+ uint8_t* buf_; // We don't own this buffer in case WebPIUpdate()
+
+ size_t part0_size_; // size of partition #0
+ const uint8_t* part0_buf_; // buffer to store partition #0
+} MemBuffer;
+
+struct WebPIDecoder {
+ DecState state_; // current decoding state
+ WebPDecParams params_; // Params to store output info
+ int is_lossless_; // for down-casting 'dec_'.
+ void* dec_; // either a VP8Decoder or a VP8LDecoder instance
+ VP8Io io_;
+
+ MemBuffer mem_; // input memory buffer.
+ WebPDecBuffer output_; // output buffer (when no external one is supplied)
+ size_t chunk_size_; // Compressed VP8/VP8L size extracted from Header.
+};
+
+// MB context to restore in case VP8DecodeMB() fails
+typedef struct {
+ VP8MB left_;
+ VP8MB info_;
+ uint8_t intra_t_[4];
+ uint8_t intra_l_[4];
+ VP8BitReader br_;
+ VP8BitReader token_br_;
+} MBContext;
+
+//------------------------------------------------------------------------------
+// MemBuffer: incoming data handling
+
+static void RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) {
+ if (br->buf_ != NULL) {
+ br->buf_ += offset;
+ br->buf_end_ += offset;
+ }
+}
+
+static WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) {
+ return (mem->end_ - mem->start_);
+}
+
+static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) {
+ MemBuffer* const mem = &idec->mem_;
+ const uint8_t* const new_base = mem->buf_ + mem->start_;
+ // note: for VP8, setting up idec->io_ is only really needed at the beginning
+ // of the decoding, till partition #0 is complete.
+ idec->io_.data = new_base;
+ idec->io_.data_size = MemDataSize(mem);
+
+ if (idec->dec_ != NULL) {
+ if (!idec->is_lossless_) {
+ VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
+ const int last_part = dec->num_parts_ - 1;
+ if (offset != 0) {
+ int p;
+ for (p = 0; p <= last_part; ++p) {
+ RemapBitReader(dec->parts_ + p, offset);
+ }
+ // Remap partition #0 data pointer to new offset, but only in MAP
+ // mode (in APPEND mode, partition #0 is copied into a fixed memory).
+ if (mem->mode_ == MEM_MODE_MAP) {
+ RemapBitReader(&dec->br_, offset);
+ }
+ }
+ assert(last_part >= 0);
+ dec->parts_[last_part].buf_end_ = mem->buf_ + mem->end_;
+ } else { // Resize lossless bitreader
+ VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_;
+ VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem));
+ }
+ }
+}
+
+// Appends data to the end of MemBuffer->buf_. It expands the allocated memory
+// size if required and also updates VP8BitReader's if new memory is allocated.
+static int AppendToMemBuffer(WebPIDecoder* const idec,
+ const uint8_t* const data, size_t data_size) {
+ MemBuffer* const mem = &idec->mem_;
+ const uint8_t* const old_base = mem->buf_ + mem->start_;
+ assert(mem->mode_ == MEM_MODE_APPEND);
+ if (data_size > MAX_CHUNK_PAYLOAD) {
+ // security safeguard: trying to allocate more than what the format
+ // allows for a chunk should be considered a smoke smell.
+ return 0;
+ }
+
+ if (mem->end_ + data_size > mem->buf_size_) { // Need some free memory
+ const size_t current_size = MemDataSize(mem);
+ const uint64_t new_size = (uint64_t)current_size + data_size;
+ const uint64_t extra_size = (new_size + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1);
+ uint8_t* const new_buf =
+ (uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf));
+ if (new_buf == NULL) return 0;
+ memcpy(new_buf, old_base, current_size);
+ free(mem->buf_);
+ mem->buf_ = new_buf;
+ mem->buf_size_ = (size_t)extra_size;
+ mem->start_ = 0;
+ mem->end_ = current_size;
+ }
+
+ memcpy(mem->buf_ + mem->end_, data, data_size);
+ mem->end_ += data_size;
+ assert(mem->end_ <= mem->buf_size_);
+
+ DoRemap(idec, mem->buf_ + mem->start_ - old_base);
+ return 1;
+}
+
+static int RemapMemBuffer(WebPIDecoder* const idec,
+ const uint8_t* const data, size_t data_size) {
+ MemBuffer* const mem = &idec->mem_;
+ const uint8_t* const old_base = mem->buf_ + mem->start_;
+ assert(mem->mode_ == MEM_MODE_MAP);
+
+ if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer!
+
+ mem->buf_ = (uint8_t*)data;
+ mem->end_ = mem->buf_size_ = data_size;
+
+ DoRemap(idec, mem->buf_ + mem->start_ - old_base);
+ return 1;
+}
+
+static void InitMemBuffer(MemBuffer* const mem) {
+ mem->mode_ = MEM_MODE_NONE;
+ mem->buf_ = NULL;
+ mem->buf_size_ = 0;
+ mem->part0_buf_ = NULL;
+ mem->part0_size_ = 0;
+}
+
+static void ClearMemBuffer(MemBuffer* const mem) {
+ assert(mem);
+ if (mem->mode_ == MEM_MODE_APPEND) {
+ free(mem->buf_);
+ free((void*)mem->part0_buf_);
+ }
+}
+
+static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) {
+ if (mem->mode_ == MEM_MODE_NONE) {
+ mem->mode_ = expected; // switch to the expected mode
+ } else if (mem->mode_ != expected) {
+ return 0; // we mixed the modes => error
+ }
+ assert(mem->mode_ == expected); // mode is ok
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Macroblock-decoding contexts
+
+static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br,
+ MBContext* const context) {
+ const VP8BitReader* const br = &dec->br_;
+ const VP8MB* const left = dec->mb_info_ - 1;
+ const VP8MB* const info = dec->mb_info_ + dec->mb_x_;
+
+ context->left_ = *left;
+ context->info_ = *info;
+ context->br_ = *br;
+ context->token_br_ = *token_br;
+ memcpy(context->intra_t_, dec->intra_t_ + 4 * dec->mb_x_, 4);
+ memcpy(context->intra_l_, dec->intra_l_, 4);
+}
+
+static void RestoreContext(const MBContext* context, VP8Decoder* const dec,
+ VP8BitReader* const token_br) {
+ VP8BitReader* const br = &dec->br_;
+ VP8MB* const left = dec->mb_info_ - 1;
+ VP8MB* const info = dec->mb_info_ + dec->mb_x_;
+
+ *left = context->left_;
+ *info = context->info_;
+ *br = context->br_;
+ *token_br = context->token_br_;
+ memcpy(dec->intra_t_ + 4 * dec->mb_x_, context->intra_t_, 4);
+ memcpy(dec->intra_l_, context->intra_l_, 4);
+}
+
+//------------------------------------------------------------------------------
+
+static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) {
+ if (idec->state_ == STATE_VP8_DATA) {
+ VP8Io* const io = &idec->io_;
+ if (io->teardown) {
+ io->teardown(io);
+ }
+ }
+ idec->state_ = STATE_ERROR;
+ return error;
+}
+
+static void ChangeState(WebPIDecoder* const idec, DecState new_state,
+ size_t consumed_bytes) {
+ MemBuffer* const mem = &idec->mem_;
+ idec->state_ = new_state;
+ mem->start_ += consumed_bytes;
+ assert(mem->start_ <= mem->end_);
+ idec->io_.data = mem->buf_ + mem->start_;
+ idec->io_.data_size = MemDataSize(mem);
+}
+
+// Headers
+static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) {
+ MemBuffer* const mem = &idec->mem_;
+ const uint8_t* data = mem->buf_ + mem->start_;
+ size_t curr_size = MemDataSize(mem);
+ VP8StatusCode status;
+ WebPHeaderStructure headers;
+
+ headers.data = data;
+ headers.data_size = curr_size;
+ status = WebPParseHeaders(&headers);
+ if (status == VP8_STATUS_NOT_ENOUGH_DATA) {
+ return VP8_STATUS_SUSPENDED; // We haven't found a VP8 chunk yet.
+ } else if (status != VP8_STATUS_OK) {
+ return IDecError(idec, status);
+ }
+
+ idec->chunk_size_ = headers.compressed_size;
+ idec->is_lossless_ = headers.is_lossless;
+ if (!idec->is_lossless_) {
+ VP8Decoder* const dec = VP8New();
+ if (dec == NULL) {
+ return VP8_STATUS_OUT_OF_MEMORY;
+ }
+ idec->dec_ = dec;
+#ifdef WEBP_USE_THREAD
+ dec->use_threads_ = (idec->params_.options != NULL) &&
+ (idec->params_.options->use_threads > 0);
+#else
+ dec->use_threads_ = 0;
+#endif
+ dec->alpha_data_ = headers.alpha_data;
+ dec->alpha_data_size_ = headers.alpha_data_size;
+ ChangeState(idec, STATE_VP8_FRAME_HEADER, headers.offset);
+ } else {
+ VP8LDecoder* const dec = VP8LNew();
+ if (dec == NULL) {
+ return VP8_STATUS_OUT_OF_MEMORY;
+ }
+ idec->dec_ = dec;
+ ChangeState(idec, STATE_VP8L_HEADER, headers.offset);
+ }
+ return VP8_STATUS_OK;
+}
+
+static VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) {
+ const uint8_t* data = idec->mem_.buf_ + idec->mem_.start_;
+ const size_t curr_size = MemDataSize(&idec->mem_);
+ uint32_t bits;
+
+ if (curr_size < VP8_FRAME_HEADER_SIZE) {
+ // Not enough data bytes to extract VP8 Frame Header.
+ return VP8_STATUS_SUSPENDED;
+ }
+ if (!VP8GetInfo(data, curr_size, idec->chunk_size_, NULL, NULL)) {
+ return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
+ }
+
+ bits = data[0] | (data[1] << 8) | (data[2] << 16);
+ idec->mem_.part0_size_ = (bits >> 5) + VP8_FRAME_HEADER_SIZE;
+
+ idec->io_.data = data;
+ idec->io_.data_size = curr_size;
+ idec->state_ = STATE_VP8_PARTS0;
+ return VP8_STATUS_OK;
+}
+
+// Partition #0
+static int CopyParts0Data(WebPIDecoder* const idec) {
+ VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
+ VP8BitReader* const br = &dec->br_;
+ const size_t psize = br->buf_end_ - br->buf_;
+ MemBuffer* const mem = &idec->mem_;
+ assert(!idec->is_lossless_);
+ assert(mem->part0_buf_ == NULL);
+ assert(psize > 0);
+ assert(psize <= mem->part0_size_); // Format limit: no need for runtime check
+ if (mem->mode_ == MEM_MODE_APPEND) {
+ // We copy and grab ownership of the partition #0 data.
+ uint8_t* const part0_buf = (uint8_t*)malloc(psize);
+ if (part0_buf == NULL) {
+ return 0;
+ }
+ memcpy(part0_buf, br->buf_, psize);
+ mem->part0_buf_ = part0_buf;
+ br->buf_ = part0_buf;
+ br->buf_end_ = part0_buf + psize;
+ } else {
+ // Else: just keep pointers to the partition #0's data in dec_->br_.
+ }
+ mem->start_ += psize;
+ return 1;
+}
+
+static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) {
+ VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
+ VP8Io* const io = &idec->io_;
+ const WebPDecParams* const params = &idec->params_;
+ WebPDecBuffer* const output = params->output;
+
+ // Wait till we have enough data for the whole partition #0
+ if (MemDataSize(&idec->mem_) < idec->mem_.part0_size_) {
+ return VP8_STATUS_SUSPENDED;
+ }
+
+ if (!VP8GetHeaders(dec, io)) {
+ const VP8StatusCode status = dec->status_;
+ if (status == VP8_STATUS_SUSPENDED ||
+ status == VP8_STATUS_NOT_ENOUGH_DATA) {
+ // treating NOT_ENOUGH_DATA as SUSPENDED state
+ return VP8_STATUS_SUSPENDED;
+ }
+ return IDecError(idec, status);
+ }
+
+ // Allocate/Verify output buffer now
+ dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options,
+ output);
+ if (dec->status_ != VP8_STATUS_OK) {
+ return IDecError(idec, dec->status_);
+ }
+
+ if (!CopyParts0Data(idec)) {
+ return IDecError(idec, VP8_STATUS_OUT_OF_MEMORY);
+ }
+
+ // Finish setting up the decoding parameters. Will call io->setup().
+ if (VP8EnterCritical(dec, io) != VP8_STATUS_OK) {
+ return IDecError(idec, dec->status_);
+ }
+
+ // Note: past this point, teardown() must always be called
+ // in case of error.
+ idec->state_ = STATE_VP8_DATA;
+ // Allocate memory and prepare everything.
+ if (!VP8InitFrame(dec, io)) {
+ return IDecError(idec, dec->status_);
+ }
+ return VP8_STATUS_OK;
+}
+
+// Remaining partitions
+static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
+ VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
+ VP8Io* const io = &idec->io_;
+
+ assert(dec->ready_);
+
+ for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) {
+ VP8BitReader* token_br = &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)];
+ if (dec->mb_x_ == 0) {
+ VP8InitScanline(dec);
+ }
+ for (; dec->mb_x_ < dec->mb_w_; dec->mb_x_++) {
+ MBContext context;
+ SaveContext(dec, token_br, &context);
+
+ if (!VP8DecodeMB(dec, token_br)) {
+ RestoreContext(&context, dec, token_br);
+ // We shouldn't fail when MAX_MB data was available
+ if (dec->num_parts_ == 1 && MemDataSize(&idec->mem_) > MAX_MB_SIZE) {
+ return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
+ }
+ return VP8_STATUS_SUSPENDED;
+ }
+ VP8ReconstructBlock(dec);
+ // Store data and save block's filtering params
+ VP8StoreBlock(dec);
+
+ // Release buffer only if there is only one partition
+ if (dec->num_parts_ == 1) {
+ idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_;
+ assert(idec->mem_.start_ <= idec->mem_.end_);
+ }
+ }
+ if (!VP8ProcessRow(dec, io)) {
+ return IDecError(idec, VP8_STATUS_USER_ABORT);
+ }
+ dec->mb_x_ = 0;
+ }
+ // Synchronize the thread and check for errors.
+ if (!VP8ExitCritical(dec, io)) {
+ return IDecError(idec, VP8_STATUS_USER_ABORT);
+ }
+ dec->ready_ = 0;
+ idec->state_ = STATE_DONE;
+
+ return VP8_STATUS_OK;
+}
+
+static int ErrorStatusLossless(WebPIDecoder* const idec, VP8StatusCode status) {
+ if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) {
+ return VP8_STATUS_SUSPENDED;
+ }
+ return IDecError(idec, status);
+}
+
+static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) {
+ VP8Io* const io = &idec->io_;
+ VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_;
+ const WebPDecParams* const params = &idec->params_;
+ WebPDecBuffer* const output = params->output;
+ size_t curr_size = MemDataSize(&idec->mem_);
+ assert(idec->is_lossless_);
+
+ // Wait until there's enough data for decoding header.
+ if (curr_size < (idec->chunk_size_ >> 3)) {
+ return VP8_STATUS_SUSPENDED;
+ }
+ if (!VP8LDecodeHeader(dec, io)) {
+ return ErrorStatusLossless(idec, dec->status_);
+ }
+ // Allocate/verify output buffer now.
+ dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options,
+ output);
+ if (dec->status_ != VP8_STATUS_OK) {
+ return IDecError(idec, dec->status_);
+ }
+
+ idec->state_ = STATE_VP8L_DATA;
+ return VP8_STATUS_OK;
+}
+
+static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) {
+ VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_;
+ const size_t curr_size = MemDataSize(&idec->mem_);
+ assert(idec->is_lossless_);
+
+ // At present Lossless decoder can't decode image incrementally. So wait till
+ // all the image data is aggregated before image can be decoded.
+ if (curr_size < idec->chunk_size_) {
+ return VP8_STATUS_SUSPENDED;
+ }
+
+ if (!VP8LDecodeImage(dec)) {
+ return ErrorStatusLossless(idec, dec->status_);
+ }
+
+ idec->state_ = STATE_DONE;
+
+ return VP8_STATUS_OK;
+}
+
+ // Main decoding loop
+static VP8StatusCode IDecode(WebPIDecoder* idec) {
+ VP8StatusCode status = VP8_STATUS_SUSPENDED;
+
+ if (idec->state_ == STATE_PRE_VP8) {
+ status = DecodeWebPHeaders(idec);
+ } else {
+ if (idec->dec_ == NULL) {
+ return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder.
+ }
+ }
+ if (idec->state_ == STATE_VP8_FRAME_HEADER) {
+ status = DecodeVP8FrameHeader(idec);
+ }
+ if (idec->state_ == STATE_VP8_PARTS0) {
+ status = DecodePartition0(idec);
+ }
+ if (idec->state_ == STATE_VP8_DATA) {
+ status = DecodeRemaining(idec);
+ }
+ if (idec->state_ == STATE_VP8L_HEADER) {
+ status = DecodeVP8LHeader(idec);
+ }
+ if (idec->state_ == STATE_VP8L_DATA) {
+ status = DecodeVP8LData(idec);
+ }
+ return status;
+}
+
+//------------------------------------------------------------------------------
+// Public functions
+
+WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) {
+ WebPIDecoder* idec = (WebPIDecoder*)calloc(1, sizeof(*idec));
+ if (idec == NULL) {
+ return NULL;
+ }
+
+ idec->state_ = STATE_PRE_VP8;
+ idec->chunk_size_ = 0;
+
+ InitMemBuffer(&idec->mem_);
+ WebPInitDecBuffer(&idec->output_);
+ VP8InitIo(&idec->io_);
+
+ WebPResetDecParams(&idec->params_);
+ idec->params_.output = output_buffer ? output_buffer : &idec->output_;
+ WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions.
+
+ return idec;
+}
+
+WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size,
+ WebPDecoderConfig* config) {
+ WebPIDecoder* idec;
+
+ // Parse the bitstream's features, if requested:
+ if (data != NULL && data_size > 0 && config != NULL) {
+ if (WebPGetFeatures(data, data_size, &config->input) != VP8_STATUS_OK) {
+ return NULL;
+ }
+ }
+ // Create an instance of the incremental decoder
+ idec = WebPINewDecoder(config ? &config->output : NULL);
+ if (idec == NULL) {
+ return NULL;
+ }
+ // Finish initialization
+ if (config != NULL) {
+ idec->params_.options = &config->options;
+ }
+ return idec;
+}
+
+void WebPIDelete(WebPIDecoder* idec) {
+ if (idec == NULL) return;
+ if (idec->dec_ != NULL) {
+ if (!idec->is_lossless_) {
+ VP8Delete(idec->dec_);
+ } else {
+ VP8LDelete(idec->dec_);
+ }
+ }
+ ClearMemBuffer(&idec->mem_);
+ WebPFreeDecBuffer(&idec->output_);
+ free(idec);
+}
+
+//------------------------------------------------------------------------------
+// Wrapper toward WebPINewDecoder
+
+WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer,
+ size_t output_buffer_size, int output_stride) {
+ WebPIDecoder* idec;
+ if (mode >= MODE_YUV) return NULL;
+ idec = WebPINewDecoder(NULL);
+ if (idec == NULL) return NULL;
+ idec->output_.colorspace = mode;
+ idec->output_.is_external_memory = 1;
+ idec->output_.u.RGBA.rgba = output_buffer;
+ idec->output_.u.RGBA.stride = output_stride;
+ idec->output_.u.RGBA.size = output_buffer_size;
+ return idec;
+}
+
+WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride,
+ uint8_t* u, size_t u_size, int u_stride,
+ uint8_t* v, size_t v_size, int v_stride,
+ uint8_t* a, size_t a_size, int a_stride) {
+ WebPIDecoder* const idec = WebPINewDecoder(NULL);
+ if (idec == NULL) return NULL;
+ idec->output_.colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA;
+ idec->output_.is_external_memory = 1;
+ idec->output_.u.YUVA.y = luma;
+ idec->output_.u.YUVA.y_stride = luma_stride;
+ idec->output_.u.YUVA.y_size = luma_size;
+ idec->output_.u.YUVA.u = u;
+ idec->output_.u.YUVA.u_stride = u_stride;
+ idec->output_.u.YUVA.u_size = u_size;
+ idec->output_.u.YUVA.v = v;
+ idec->output_.u.YUVA.v_stride = v_stride;
+ idec->output_.u.YUVA.v_size = v_size;
+ idec->output_.u.YUVA.a = a;
+ idec->output_.u.YUVA.a_stride = a_stride;
+ idec->output_.u.YUVA.a_size = a_size;
+ return idec;
+}
+
+WebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride,
+ uint8_t* u, size_t u_size, int u_stride,
+ uint8_t* v, size_t v_size, int v_stride) {
+ return WebPINewYUVA(luma, luma_size, luma_stride,
+ u, u_size, u_stride,
+ v, v_size, v_stride,
+ NULL, 0, 0);
+}
+
+//------------------------------------------------------------------------------
+
+static VP8StatusCode IDecCheckStatus(const WebPIDecoder* const idec) {
+ assert(idec);
+ if (idec->state_ == STATE_ERROR) {
+ return VP8_STATUS_BITSTREAM_ERROR;
+ }
+ if (idec->state_ == STATE_DONE) {
+ return VP8_STATUS_OK;
+ }
+ return VP8_STATUS_SUSPENDED;
+}
+
+VP8StatusCode WebPIAppend(WebPIDecoder* idec,
+ const uint8_t* data, size_t data_size) {
+ VP8StatusCode status;
+ if (idec == NULL || data == NULL) {
+ return VP8_STATUS_INVALID_PARAM;
+ }
+ status = IDecCheckStatus(idec);
+ if (status != VP8_STATUS_SUSPENDED) {
+ return status;
+ }
+ // Check mixed calls between RemapMemBuffer and AppendToMemBuffer.
+ if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_APPEND)) {
+ return VP8_STATUS_INVALID_PARAM;
+ }
+ // Append data to memory buffer
+ if (!AppendToMemBuffer(idec, data, data_size)) {
+ return VP8_STATUS_OUT_OF_MEMORY;
+ }
+ return IDecode(idec);
+}
+
+VP8StatusCode WebPIUpdate(WebPIDecoder* idec,
+ const uint8_t* data, size_t data_size) {
+ VP8StatusCode status;
+ if (idec == NULL || data == NULL) {
+ return VP8_STATUS_INVALID_PARAM;
+ }
+ status = IDecCheckStatus(idec);
+ if (status != VP8_STATUS_SUSPENDED) {
+ return status;
+ }
+ // Check mixed calls between RemapMemBuffer and AppendToMemBuffer.
+ if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_MAP)) {
+ return VP8_STATUS_INVALID_PARAM;
+ }
+ // Make the memory buffer point to the new buffer
+ if (!RemapMemBuffer(idec, data, data_size)) {
+ return VP8_STATUS_INVALID_PARAM;
+ }
+ return IDecode(idec);
+}
+
+//------------------------------------------------------------------------------
+
+static const WebPDecBuffer* GetOutputBuffer(const WebPIDecoder* const idec) {
+ if (idec == NULL || idec->dec_ == NULL) {
+ return NULL;
+ }
+ if (idec->state_ <= STATE_VP8_PARTS0) {
+ return NULL;
+ }
+ return idec->params_.output;
+}
+
+const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec,
+ int* left, int* top,
+ int* width, int* height) {
+ const WebPDecBuffer* const src = GetOutputBuffer(idec);
+ if (left != NULL) *left = 0;
+ if (top != NULL) *top = 0;
+ // TODO(skal): later include handling of rotations.
+ if (src) {
+ if (width != NULL) *width = src->width;
+ if (height != NULL) *height = idec->params_.last_y;
+ } else {
+ if (width != NULL) *width = 0;
+ if (height != NULL) *height = 0;
+ }
+ return src;
+}
+
+uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y,
+ int* width, int* height, int* stride) {
+ const WebPDecBuffer* const src = GetOutputBuffer(idec);
+ if (src == NULL) return NULL;
+ if (src->colorspace >= MODE_YUV) {
+ return NULL;
+ }
+
+ if (last_y != NULL) *last_y = idec->params_.last_y;
+ if (width != NULL) *width = src->width;
+ if (height != NULL) *height = src->height;
+ if (stride != NULL) *stride = src->u.RGBA.stride;
+
+ return src->u.RGBA.rgba;
+}
+
+uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y,
+ uint8_t** u, uint8_t** v, uint8_t** a,
+ int* width, int* height,
+ int* stride, int* uv_stride, int* a_stride) {
+ const WebPDecBuffer* const src = GetOutputBuffer(idec);
+ if (src == NULL) return NULL;
+ if (src->colorspace < MODE_YUV) {
+ return NULL;
+ }
+
+ if (last_y != NULL) *last_y = idec->params_.last_y;
+ if (u != NULL) *u = src->u.YUVA.u;
+ if (v != NULL) *v = src->u.YUVA.v;
+ if (a != NULL) *a = src->u.YUVA.a;
+ if (width != NULL) *width = src->width;
+ if (height != NULL) *height = src->height;
+ if (stride != NULL) *stride = src->u.YUVA.y_stride;
+ if (uv_stride != NULL) *uv_stride = src->u.YUVA.u_stride;
+ if (a_stride != NULL) *a_stride = src->u.YUVA.a_stride;
+
+ return src->u.YUVA.y;
+}
+
+int WebPISetIOHooks(WebPIDecoder* const idec,
+ VP8IoPutHook put,
+ VP8IoSetupHook setup,
+ VP8IoTeardownHook teardown,
+ void* user_data) {
+ if (idec == NULL || idec->state_ > STATE_PRE_VP8) {
+ return 0;
+ }
+
+ idec->io_.put = put;
+ idec->io_.setup = setup;
+ idec->io_.teardown = teardown;
+ idec->io_.opaque = user_data;
+
+ return 1;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dec/io.c b/drivers/webpold/dec/io.c
new file mode 100644
index 0000000000..594804c2e6
--- /dev/null
+++ b/drivers/webpold/dec/io.c
@@ -0,0 +1,633 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// functions for sample output.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <stdlib.h>
+#include "../dec/vp8i.h"
+#include "./webpi.h"
+#include "../dsp/dsp.h"
+#include "../dsp/yuv.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Main YUV<->RGB conversion functions
+
+static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) {
+ WebPDecBuffer* output = p->output;
+ const WebPYUVABuffer* const buf = &output->u.YUVA;
+ uint8_t* const y_dst = buf->y + io->mb_y * buf->y_stride;
+ uint8_t* const u_dst = buf->u + (io->mb_y >> 1) * buf->u_stride;
+ uint8_t* const v_dst = buf->v + (io->mb_y >> 1) * buf->v_stride;
+ const int mb_w = io->mb_w;
+ const int mb_h = io->mb_h;
+ const int uv_w = (mb_w + 1) / 2;
+ const int uv_h = (mb_h + 1) / 2;
+ int j;
+ for (j = 0; j < mb_h; ++j) {
+ memcpy(y_dst + j * buf->y_stride, io->y + j * io->y_stride, mb_w);
+ }
+ for (j = 0; j < uv_h; ++j) {
+ memcpy(u_dst + j * buf->u_stride, io->u + j * io->uv_stride, uv_w);
+ memcpy(v_dst + j * buf->v_stride, io->v + j * io->uv_stride, uv_w);
+ }
+ return io->mb_h;
+}
+
+// Point-sampling U/V sampler.
+static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) {
+ WebPDecBuffer* output = p->output;
+ const WebPRGBABuffer* const buf = &output->u.RGBA;
+ uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
+ const uint8_t* y_src = io->y;
+ const uint8_t* u_src = io->u;
+ const uint8_t* v_src = io->v;
+ const WebPSampleLinePairFunc sample = WebPSamplers[output->colorspace];
+ const int mb_w = io->mb_w;
+ const int last = io->mb_h - 1;
+ int j;
+ for (j = 0; j < last; j += 2) {
+ sample(y_src, y_src + io->y_stride, u_src, v_src,
+ dst, dst + buf->stride, mb_w);
+ y_src += 2 * io->y_stride;
+ u_src += io->uv_stride;
+ v_src += io->uv_stride;
+ dst += 2 * buf->stride;
+ }
+ if (j == last) { // Just do the last line twice
+ sample(y_src, y_src, u_src, v_src, dst, dst, mb_w);
+ }
+ return io->mb_h;
+}
+
+//------------------------------------------------------------------------------
+// YUV444 -> RGB conversion
+
+#if 0 // TODO(skal): this is for future rescaling.
+static int EmitRGB(const VP8Io* const io, WebPDecParams* const p) {
+ WebPDecBuffer* output = p->output;
+ const WebPRGBABuffer* const buf = &output->u.RGBA;
+ uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
+ const uint8_t* y_src = io->y;
+ const uint8_t* u_src = io->u;
+ const uint8_t* v_src = io->v;
+ const WebPYUV444Converter convert = WebPYUV444Converters[output->colorspace];
+ const int mb_w = io->mb_w;
+ const int last = io->mb_h;
+ int j;
+ for (j = 0; j < last; ++j) {
+ convert(y_src, u_src, v_src, dst, mb_w);
+ y_src += io->y_stride;
+ u_src += io->uv_stride;
+ v_src += io->uv_stride;
+ dst += buf->stride;
+ }
+ return io->mb_h;
+}
+#endif
+
+//------------------------------------------------------------------------------
+// Fancy upsampling
+
+#ifdef FANCY_UPSAMPLING
+static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
+ int num_lines_out = io->mb_h; // a priori guess
+ const WebPRGBABuffer* const buf = &p->output->u.RGBA;
+ uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
+ WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace];
+ const uint8_t* cur_y = io->y;
+ const uint8_t* cur_u = io->u;
+ const uint8_t* cur_v = io->v;
+ const uint8_t* top_u = p->tmp_u;
+ const uint8_t* top_v = p->tmp_v;
+ int y = io->mb_y;
+ const int y_end = io->mb_y + io->mb_h;
+ const int mb_w = io->mb_w;
+ const int uv_w = (mb_w + 1) / 2;
+
+ if (y == 0) {
+ // First line is special cased. We mirror the u/v samples at boundary.
+ upsample(NULL, cur_y, cur_u, cur_v, cur_u, cur_v, NULL, dst, mb_w);
+ } else {
+ // We can finish the left-over line from previous call.
+ upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v,
+ dst - buf->stride, dst, mb_w);
+ ++num_lines_out;
+ }
+ // Loop over each output pairs of row.
+ for (; y + 2 < y_end; y += 2) {
+ top_u = cur_u;
+ top_v = cur_v;
+ cur_u += io->uv_stride;
+ cur_v += io->uv_stride;
+ dst += 2 * buf->stride;
+ cur_y += 2 * io->y_stride;
+ upsample(cur_y - io->y_stride, cur_y,
+ top_u, top_v, cur_u, cur_v,
+ dst - buf->stride, dst, mb_w);
+ }
+ // move to last row
+ cur_y += io->y_stride;
+ if (io->crop_top + y_end < io->crop_bottom) {
+ // Save the unfinished samples for next call (as we're not done yet).
+ memcpy(p->tmp_y, cur_y, mb_w * sizeof(*p->tmp_y));
+ memcpy(p->tmp_u, cur_u, uv_w * sizeof(*p->tmp_u));
+ memcpy(p->tmp_v, cur_v, uv_w * sizeof(*p->tmp_v));
+ // The fancy upsampler leaves a row unfinished behind
+ // (except for the very last row)
+ num_lines_out--;
+ } else {
+ // Process the very last row of even-sized picture
+ if (!(y_end & 1)) {
+ upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v,
+ dst + buf->stride, NULL, mb_w);
+ }
+ }
+ return num_lines_out;
+}
+
+#endif /* FANCY_UPSAMPLING */
+
+//------------------------------------------------------------------------------
+
+static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p) {
+ const uint8_t* alpha = io->a;
+ const WebPYUVABuffer* const buf = &p->output->u.YUVA;
+ const int mb_w = io->mb_w;
+ const int mb_h = io->mb_h;
+ uint8_t* dst = buf->a + io->mb_y * buf->a_stride;
+ int j;
+
+ if (alpha != NULL) {
+ for (j = 0; j < mb_h; ++j) {
+ memcpy(dst, alpha, mb_w * sizeof(*dst));
+ alpha += io->width;
+ dst += buf->a_stride;
+ }
+ } else if (buf->a != NULL) {
+ // the user requested alpha, but there is none, set it to opaque.
+ for (j = 0; j < mb_h; ++j) {
+ memset(dst, 0xff, mb_w * sizeof(*dst));
+ dst += buf->a_stride;
+ }
+ }
+ return 0;
+}
+
+static int GetAlphaSourceRow(const VP8Io* const io,
+ const uint8_t** alpha, int* const num_rows) {
+ int start_y = io->mb_y;
+ *num_rows = io->mb_h;
+
+ // Compensate for the 1-line delay of the fancy upscaler.
+ // This is similar to EmitFancyRGB().
+ if (io->fancy_upsampling) {
+ if (start_y == 0) {
+ // We don't process the last row yet. It'll be done during the next call.
+ --*num_rows;
+ } else {
+ --start_y;
+ // Fortunately, *alpha data is persistent, so we can go back
+ // one row and finish alpha blending, now that the fancy upscaler
+ // completed the YUV->RGB interpolation.
+ *alpha -= io->width;
+ }
+ if (io->crop_top + io->mb_y + io->mb_h == io->crop_bottom) {
+ // If it's the very last call, we process all the remaining rows!
+ *num_rows = io->crop_bottom - io->crop_top - start_y;
+ }
+ }
+ return start_y;
+}
+
+static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
+ const uint8_t* alpha = io->a;
+ if (alpha != NULL) {
+ const int mb_w = io->mb_w;
+ const WEBP_CSP_MODE colorspace = p->output->colorspace;
+ const int alpha_first =
+ (colorspace == MODE_ARGB || colorspace == MODE_Argb);
+ const WebPRGBABuffer* const buf = &p->output->u.RGBA;
+ int num_rows;
+ const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
+ uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
+ uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
+ uint32_t alpha_mask = 0xff;
+ int i, j;
+
+ for (j = 0; j < num_rows; ++j) {
+ for (i = 0; i < mb_w; ++i) {
+ const uint32_t alpha_value = alpha[i];
+ dst[4 * i] = alpha_value;
+ alpha_mask &= alpha_value;
+ }
+ alpha += io->width;
+ dst += buf->stride;
+ }
+ // alpha_mask is < 0xff if there's non-trivial alpha to premultiply with.
+ if (alpha_mask != 0xff && WebPIsPremultipliedMode(colorspace)) {
+ WebPApplyAlphaMultiply(base_rgba, alpha_first,
+ mb_w, num_rows, buf->stride);
+ }
+ }
+ return 0;
+}
+
+static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p) {
+ const uint8_t* alpha = io->a;
+ if (alpha != NULL) {
+ const int mb_w = io->mb_w;
+ const WEBP_CSP_MODE colorspace = p->output->colorspace;
+ const WebPRGBABuffer* const buf = &p->output->u.RGBA;
+ int num_rows;
+ const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
+ uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
+ uint8_t* alpha_dst = base_rgba + 1;
+ uint32_t alpha_mask = 0x0f;
+ int i, j;
+
+ for (j = 0; j < num_rows; ++j) {
+ for (i = 0; i < mb_w; ++i) {
+ // Fill in the alpha value (converted to 4 bits).
+ const uint32_t alpha_value = alpha[i] >> 4;
+ alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value;
+ alpha_mask &= alpha_value;
+ }
+ alpha += io->width;
+ alpha_dst += buf->stride;
+ }
+ if (alpha_mask != 0x0f && WebPIsPremultipliedMode(colorspace)) {
+ WebPApplyAlphaMultiply4444(base_rgba, mb_w, num_rows, buf->stride);
+ }
+ }
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+// YUV rescaling (no final RGB conversion needed)
+
+static int Rescale(const uint8_t* src, int src_stride,
+ int new_lines, WebPRescaler* const wrk) {
+ int num_lines_out = 0;
+ while (new_lines > 0) { // import new contributions of source rows.
+ const int lines_in = WebPRescalerImport(wrk, new_lines, src, src_stride);
+ src += lines_in * src_stride;
+ new_lines -= lines_in;
+ num_lines_out += WebPRescalerExport(wrk); // emit output row(s)
+ }
+ return num_lines_out;
+}
+
+static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
+ const int mb_h = io->mb_h;
+ const int uv_mb_h = (mb_h + 1) >> 1;
+ const int num_lines_out = Rescale(io->y, io->y_stride, mb_h, &p->scaler_y);
+ Rescale(io->u, io->uv_stride, uv_mb_h, &p->scaler_u);
+ Rescale(io->v, io->uv_stride, uv_mb_h, &p->scaler_v);
+ return num_lines_out;
+}
+
+static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p) {
+ if (io->a != NULL) {
+ Rescale(io->a, io->width, io->mb_h, &p->scaler_a);
+ }
+ return 0;
+}
+
+static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
+ const int has_alpha = WebPIsAlphaMode(p->output->colorspace);
+ const WebPYUVABuffer* const buf = &p->output->u.YUVA;
+ const int out_width = io->scaled_width;
+ const int out_height = io->scaled_height;
+ const int uv_out_width = (out_width + 1) >> 1;
+ const int uv_out_height = (out_height + 1) >> 1;
+ const int uv_in_width = (io->mb_w + 1) >> 1;
+ const int uv_in_height = (io->mb_h + 1) >> 1;
+ const size_t work_size = 2 * out_width; // scratch memory for luma rescaler
+ const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones
+ size_t tmp_size;
+ int32_t* work;
+
+ tmp_size = work_size + 2 * uv_work_size;
+ if (has_alpha) {
+ tmp_size += work_size;
+ }
+ p->memory = calloc(1, tmp_size * sizeof(*work));
+ if (p->memory == NULL) {
+ return 0; // memory error
+ }
+ work = (int32_t*)p->memory;
+ WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h,
+ buf->y, out_width, out_height, buf->y_stride, 1,
+ io->mb_w, out_width, io->mb_h, out_height,
+ work);
+ WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
+ buf->u, uv_out_width, uv_out_height, buf->u_stride, 1,
+ uv_in_width, uv_out_width,
+ uv_in_height, uv_out_height,
+ work + work_size);
+ WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height,
+ buf->v, uv_out_width, uv_out_height, buf->v_stride, 1,
+ uv_in_width, uv_out_width,
+ uv_in_height, uv_out_height,
+ work + work_size + uv_work_size);
+ p->emit = EmitRescaledYUV;
+
+ if (has_alpha) {
+ WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h,
+ buf->a, out_width, out_height, buf->a_stride, 1,
+ io->mb_w, out_width, io->mb_h, out_height,
+ work + work_size + 2 * uv_work_size);
+ p->emit_alpha = EmitRescaledAlphaYUV;
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// RGBA rescaling
+
+static int ExportRGB(WebPDecParams* const p, int y_pos) {
+ const WebPYUV444Converter convert =
+ WebPYUV444Converters[p->output->colorspace];
+ const WebPRGBABuffer* const buf = &p->output->u.RGBA;
+ uint8_t* dst = buf->rgba + (p->last_y + y_pos) * buf->stride;
+ int num_lines_out = 0;
+ // For RGB rescaling, because of the YUV420, current scan position
+ // U/V can be +1/-1 line from the Y one. Hence the double test.
+ while (WebPRescalerHasPendingOutput(&p->scaler_y) &&
+ WebPRescalerHasPendingOutput(&p->scaler_u)) {
+ assert(p->last_y + y_pos + num_lines_out < p->output->height);
+ assert(p->scaler_u.y_accum == p->scaler_v.y_accum);
+ WebPRescalerExportRow(&p->scaler_y);
+ WebPRescalerExportRow(&p->scaler_u);
+ WebPRescalerExportRow(&p->scaler_v);
+ convert(p->scaler_y.dst, p->scaler_u.dst, p->scaler_v.dst,
+ dst, p->scaler_y.dst_width);
+ dst += buf->stride;
+ ++num_lines_out;
+ }
+ return num_lines_out;
+}
+
+static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
+ const int mb_h = io->mb_h;
+ const int uv_mb_h = (mb_h + 1) >> 1;
+ int j = 0, uv_j = 0;
+ int num_lines_out = 0;
+ while (j < mb_h) {
+ const int y_lines_in =
+ WebPRescalerImport(&p->scaler_y, mb_h - j,
+ io->y + j * io->y_stride, io->y_stride);
+ const int u_lines_in =
+ WebPRescalerImport(&p->scaler_u, uv_mb_h - uv_j,
+ io->u + uv_j * io->uv_stride, io->uv_stride);
+ const int v_lines_in =
+ WebPRescalerImport(&p->scaler_v, uv_mb_h - uv_j,
+ io->v + uv_j * io->uv_stride, io->uv_stride);
+ (void)v_lines_in; // remove a gcc warning
+ assert(u_lines_in == v_lines_in);
+ j += y_lines_in;
+ uv_j += u_lines_in;
+ num_lines_out += ExportRGB(p, num_lines_out);
+ }
+ return num_lines_out;
+}
+
+static int ExportAlpha(WebPDecParams* const p, int y_pos) {
+ const WebPRGBABuffer* const buf = &p->output->u.RGBA;
+ uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride;
+ const WEBP_CSP_MODE colorspace = p->output->colorspace;
+ const int alpha_first =
+ (colorspace == MODE_ARGB || colorspace == MODE_Argb);
+ uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
+ int num_lines_out = 0;
+ const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
+ uint32_t alpha_mask = 0xff;
+ const int width = p->scaler_a.dst_width;
+
+ while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
+ int i;
+ assert(p->last_y + y_pos + num_lines_out < p->output->height);
+ WebPRescalerExportRow(&p->scaler_a);
+ for (i = 0; i < width; ++i) {
+ const uint32_t alpha_value = p->scaler_a.dst[i];
+ dst[4 * i] = alpha_value;
+ alpha_mask &= alpha_value;
+ }
+ dst += buf->stride;
+ ++num_lines_out;
+ }
+ if (is_premult_alpha && alpha_mask != 0xff) {
+ WebPApplyAlphaMultiply(base_rgba, alpha_first,
+ width, num_lines_out, buf->stride);
+ }
+ return num_lines_out;
+}
+
+static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos) {
+ const WebPRGBABuffer* const buf = &p->output->u.RGBA;
+ uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride;
+ uint8_t* alpha_dst = base_rgba + 1;
+ int num_lines_out = 0;
+ const WEBP_CSP_MODE colorspace = p->output->colorspace;
+ const int width = p->scaler_a.dst_width;
+ const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
+ uint32_t alpha_mask = 0x0f;
+
+ while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
+ int i;
+ assert(p->last_y + y_pos + num_lines_out < p->output->height);
+ WebPRescalerExportRow(&p->scaler_a);
+ for (i = 0; i < width; ++i) {
+ // Fill in the alpha value (converted to 4 bits).
+ const uint32_t alpha_value = p->scaler_a.dst[i] >> 4;
+ alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value;
+ alpha_mask &= alpha_value;
+ }
+ alpha_dst += buf->stride;
+ ++num_lines_out;
+ }
+ if (is_premult_alpha && alpha_mask != 0x0f) {
+ WebPApplyAlphaMultiply4444(base_rgba, width, num_lines_out, buf->stride);
+ }
+ return num_lines_out;
+}
+
+static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
+ if (io->a != NULL) {
+ WebPRescaler* const scaler = &p->scaler_a;
+ int j = 0;
+ int pos = 0;
+ while (j < io->mb_h) {
+ j += WebPRescalerImport(scaler, io->mb_h - j,
+ io->a + j * io->width, io->width);
+ pos += p->emit_alpha_row(p, pos);
+ }
+ }
+ return 0;
+}
+
+static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
+ const int has_alpha = WebPIsAlphaMode(p->output->colorspace);
+ const int out_width = io->scaled_width;
+ const int out_height = io->scaled_height;
+ const int uv_in_width = (io->mb_w + 1) >> 1;
+ const int uv_in_height = (io->mb_h + 1) >> 1;
+ const size_t work_size = 2 * out_width; // scratch memory for one rescaler
+ int32_t* work; // rescalers work area
+ uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion
+ size_t tmp_size1, tmp_size2;
+
+ tmp_size1 = 3 * work_size;
+ tmp_size2 = 3 * out_width;
+ if (has_alpha) {
+ tmp_size1 += work_size;
+ tmp_size2 += out_width;
+ }
+ p->memory = calloc(1, tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp));
+ if (p->memory == NULL) {
+ return 0; // memory error
+ }
+ work = (int32_t*)p->memory;
+ tmp = (uint8_t*)(work + tmp_size1);
+ WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h,
+ tmp + 0 * out_width, out_width, out_height, 0, 1,
+ io->mb_w, out_width, io->mb_h, out_height,
+ work + 0 * work_size);
+ WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
+ tmp + 1 * out_width, out_width, out_height, 0, 1,
+ io->mb_w, 2 * out_width, io->mb_h, 2 * out_height,
+ work + 1 * work_size);
+ WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height,
+ tmp + 2 * out_width, out_width, out_height, 0, 1,
+ io->mb_w, 2 * out_width, io->mb_h, 2 * out_height,
+ work + 2 * work_size);
+ p->emit = EmitRescaledRGB;
+
+ if (has_alpha) {
+ WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h,
+ tmp + 3 * out_width, out_width, out_height, 0, 1,
+ io->mb_w, out_width, io->mb_h, out_height,
+ work + 3 * work_size);
+ p->emit_alpha = EmitRescaledAlphaRGB;
+ if (p->output->colorspace == MODE_RGBA_4444 ||
+ p->output->colorspace == MODE_rgbA_4444) {
+ p->emit_alpha_row = ExportAlphaRGBA4444;
+ } else {
+ p->emit_alpha_row = ExportAlpha;
+ }
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Default custom functions
+
+static int CustomSetup(VP8Io* io) {
+ WebPDecParams* const p = (WebPDecParams*)io->opaque;
+ const WEBP_CSP_MODE colorspace = p->output->colorspace;
+ const int is_rgb = WebPIsRGBMode(colorspace);
+ const int is_alpha = WebPIsAlphaMode(colorspace);
+
+ p->memory = NULL;
+ p->emit = NULL;
+ p->emit_alpha = NULL;
+ p->emit_alpha_row = NULL;
+ if (!WebPIoInitFromOptions(p->options, io, is_alpha ? MODE_YUV : MODE_YUVA)) {
+ return 0;
+ }
+
+ if (io->use_scaling) {
+ const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p);
+ if (!ok) {
+ return 0; // memory error
+ }
+ } else {
+ if (is_rgb) {
+ p->emit = EmitSampledRGB; // default
+#ifdef FANCY_UPSAMPLING
+ if (io->fancy_upsampling) {
+ const int uv_width = (io->mb_w + 1) >> 1;
+ p->memory = malloc(io->mb_w + 2 * uv_width);
+ if (p->memory == NULL) {
+ return 0; // memory error.
+ }
+ p->tmp_y = (uint8_t*)p->memory;
+ p->tmp_u = p->tmp_y + io->mb_w;
+ p->tmp_v = p->tmp_u + uv_width;
+ p->emit = EmitFancyRGB;
+ WebPInitUpsamplers();
+ }
+#endif
+ } else {
+ p->emit = EmitYUV;
+ }
+ if (is_alpha) { // need transparency output
+ if (WebPIsPremultipliedMode(colorspace)) WebPInitPremultiply();
+ p->emit_alpha =
+ (colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444) ?
+ EmitAlphaRGBA4444
+ : is_rgb ? EmitAlphaRGB
+ : EmitAlphaYUV;
+ }
+ }
+
+ if (is_rgb) {
+ VP8YUVInit();
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+
+static int CustomPut(const VP8Io* io) {
+ WebPDecParams* const p = (WebPDecParams*)io->opaque;
+ const int mb_w = io->mb_w;
+ const int mb_h = io->mb_h;
+ int num_lines_out;
+ assert(!(io->mb_y & 1));
+
+ if (mb_w <= 0 || mb_h <= 0) {
+ return 0;
+ }
+ num_lines_out = p->emit(io, p);
+ if (p->emit_alpha) {
+ p->emit_alpha(io, p);
+ }
+ p->last_y += num_lines_out;
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+
+static void CustomTeardown(const VP8Io* io) {
+ WebPDecParams* const p = (WebPDecParams*)io->opaque;
+ free(p->memory);
+ p->memory = NULL;
+}
+
+//------------------------------------------------------------------------------
+// Main entry point
+
+void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) {
+ io->put = CustomPut;
+ io->setup = CustomSetup;
+ io->teardown = CustomTeardown;
+ io->opaque = params;
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webp/dec/layer.c b/drivers/webpold/dec/layer.c
index a3a5bdcfe8..a3a5bdcfe8 100644
--- a/drivers/webp/dec/layer.c
+++ b/drivers/webpold/dec/layer.c
diff --git a/drivers/webpold/dec/quant.c b/drivers/webpold/dec/quant.c
new file mode 100644
index 0000000000..d54097af0d
--- /dev/null
+++ b/drivers/webpold/dec/quant.c
@@ -0,0 +1,113 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Quantizer initialization
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./vp8i.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+static WEBP_INLINE int clip(int v, int M) {
+ return v < 0 ? 0 : v > M ? M : v;
+}
+
+// Paragraph 14.1
+static const uint8_t kDcTable[128] = {
+ 4, 5, 6, 7, 8, 9, 10, 10,
+ 11, 12, 13, 14, 15, 16, 17, 17,
+ 18, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 25, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89,
+ 91, 93, 95, 96, 98, 100, 101, 102,
+ 104, 106, 108, 110, 112, 114, 116, 118,
+ 122, 124, 126, 128, 130, 132, 134, 136,
+ 138, 140, 143, 145, 148, 151, 154, 157
+};
+
+static const uint16_t kAcTable[128] = {
+ 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 60,
+ 62, 64, 66, 68, 70, 72, 74, 76,
+ 78, 80, 82, 84, 86, 88, 90, 92,
+ 94, 96, 98, 100, 102, 104, 106, 108,
+ 110, 112, 114, 116, 119, 122, 125, 128,
+ 131, 134, 137, 140, 143, 146, 149, 152,
+ 155, 158, 161, 164, 167, 170, 173, 177,
+ 181, 185, 189, 193, 197, 201, 205, 209,
+ 213, 217, 221, 225, 229, 234, 239, 245,
+ 249, 254, 259, 264, 269, 274, 279, 284
+};
+
+//------------------------------------------------------------------------------
+// Paragraph 9.6
+
+void VP8ParseQuant(VP8Decoder* const dec) {
+ VP8BitReader* const br = &dec->br_;
+ const int base_q0 = VP8GetValue(br, 7);
+ const int dqy1_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
+ const int dqy2_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
+ const int dqy2_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
+ const int dquv_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
+ const int dquv_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
+
+ const VP8SegmentHeader* const hdr = &dec->segment_hdr_;
+ int i;
+
+ for (i = 0; i < NUM_MB_SEGMENTS; ++i) {
+ int q;
+ if (hdr->use_segment_) {
+ q = hdr->quantizer_[i];
+ if (!hdr->absolute_delta_) {
+ q += base_q0;
+ }
+ } else {
+ if (i > 0) {
+ dec->dqm_[i] = dec->dqm_[0];
+ continue;
+ } else {
+ q = base_q0;
+ }
+ }
+ {
+ VP8QuantMatrix* const m = &dec->dqm_[i];
+ m->y1_mat_[0] = kDcTable[clip(q + dqy1_dc, 127)];
+ m->y1_mat_[1] = kAcTable[clip(q + 0, 127)];
+
+ m->y2_mat_[0] = kDcTable[clip(q + dqy2_dc, 127)] * 2;
+ // For all x in [0..284], x*155/100 is bitwise equal to (x*101581) >> 16.
+ // The smallest precision for that is '(x*6349) >> 12' but 16 is a good
+ // word size.
+ m->y2_mat_[1] = (kAcTable[clip(q + dqy2_ac, 127)] * 101581) >> 16;
+ if (m->y2_mat_[1] < 8) m->y2_mat_[1] = 8;
+
+ m->uv_mat_[0] = kDcTable[clip(q + dquv_dc, 117)];
+ m->uv_mat_[1] = kAcTable[clip(q + dquv_ac, 127)];
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dec/tree.c b/drivers/webpold/dec/tree.c
new file mode 100644
index 0000000000..82484e4c55
--- /dev/null
+++ b/drivers/webpold/dec/tree.c
@@ -0,0 +1,589 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Coding trees and probas
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "vp8i.h"
+
+#define USE_GENERIC_TREE
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#ifdef USE_GENERIC_TREE
+static const int8_t kYModesIntra4[18] = {
+ -B_DC_PRED, 1,
+ -B_TM_PRED, 2,
+ -B_VE_PRED, 3,
+ 4, 6,
+ -B_HE_PRED, 5,
+ -B_RD_PRED, -B_VR_PRED,
+ -B_LD_PRED, 7,
+ -B_VL_PRED, 8,
+ -B_HD_PRED, -B_HU_PRED
+};
+#endif
+
+#ifndef ONLY_KEYFRAME_CODE
+
+// inter prediction modes
+enum {
+ LEFT4 = 0, ABOVE4 = 1, ZERO4 = 2, NEW4 = 3,
+ NEARESTMV, NEARMV, ZEROMV, NEWMV, SPLITMV };
+
+static const int8_t kYModesInter[8] = {
+ -DC_PRED, 1,
+ 2, 3,
+ -V_PRED, -H_PRED,
+ -TM_PRED, -B_PRED
+};
+
+static const int8_t kMBSplit[6] = {
+ -3, 1,
+ -2, 2,
+ -0, -1
+};
+
+static const int8_t kMVRef[8] = {
+ -ZEROMV, 1,
+ -NEARESTMV, 2,
+ -NEARMV, 3,
+ -NEWMV, -SPLITMV
+};
+
+static const int8_t kMVRef4[6] = {
+ -LEFT4, 1,
+ -ABOVE4, 2,
+ -ZERO4, -NEW4
+};
+#endif
+
+//------------------------------------------------------------------------------
+// Default probabilities
+
+// Inter
+#ifndef ONLY_KEYFRAME_CODE
+static const uint8_t kYModeProbaInter0[4] = { 112, 86, 140, 37 };
+static const uint8_t kUVModeProbaInter0[3] = { 162, 101, 204 };
+static const uint8_t kMVProba0[2][NUM_MV_PROBAS] = {
+ { 162, 128, 225, 146, 172, 147, 214, 39,
+ 156, 128, 129, 132, 75, 145, 178, 206,
+ 239, 254, 254 },
+ { 164, 128, 204, 170, 119, 235, 140, 230,
+ 228, 128, 130, 130, 74, 148, 180, 203,
+ 236, 254, 254 }
+};
+#endif
+
+// Paragraph 13.5
+static const uint8_t
+ CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
+ // genereated using vp8_default_coef_probs() in entropy.c:129
+ { { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
+ },
+ { { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 },
+ { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 },
+ { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 }
+ },
+ { { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 },
+ { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 },
+ { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 },
+ },
+ { { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 },
+ { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 },
+ { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 },
+ },
+ { { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 },
+ { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 },
+ { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 }
+ },
+ { { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 },
+ { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 },
+ { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 }
+ },
+ { { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 },
+ { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 },
+ { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 }
+ },
+ { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
+ }
+ },
+ { { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 },
+ { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 },
+ { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 }
+ },
+ { { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 },
+ { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 },
+ { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 }
+ },
+ { { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 },
+ { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 },
+ { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 }
+ },
+ { { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 },
+ { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 },
+ { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 }
+ },
+ { { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 },
+ { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 },
+ { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 }
+ },
+ { { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 },
+ { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 },
+ { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 }
+ },
+ { { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 },
+ { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 },
+ { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 }
+ },
+ { { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 },
+ { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 },
+ { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 }
+ }
+ },
+ { { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 },
+ { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 },
+ { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 }
+ },
+ { { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 },
+ { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 },
+ { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 }
+ },
+ { { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 },
+ { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 },
+ { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 }
+ },
+ { { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 },
+ { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 },
+ { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 }
+ },
+ { { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 },
+ { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 },
+ { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
+ },
+ { { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
+ },
+ { { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 },
+ { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 },
+ { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
+ },
+ { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
+ }
+ },
+ { { { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 },
+ { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 },
+ { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 }
+ },
+ { { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 },
+ { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 },
+ { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 }
+ },
+ { { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 },
+ { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 },
+ { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 }
+ },
+ { { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 },
+ { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 },
+ { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 }
+ },
+ { { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 },
+ { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 },
+ { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 }
+ },
+ { { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 },
+ { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 },
+ { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 }
+ },
+ { { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 },
+ { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 },
+ { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 }
+ },
+ { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
+ }
+ }
+};
+
+// Paragraph 11.5
+static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = {
+ { { 231, 120, 48, 89, 115, 113, 120, 152, 112 },
+ { 152, 179, 64, 126, 170, 118, 46, 70, 95 },
+ { 175, 69, 143, 80, 85, 82, 72, 155, 103 },
+ { 56, 58, 10, 171, 218, 189, 17, 13, 152 },
+ { 114, 26, 17, 163, 44, 195, 21, 10, 173 },
+ { 121, 24, 80, 195, 26, 62, 44, 64, 85 },
+ { 144, 71, 10, 38, 171, 213, 144, 34, 26 },
+ { 170, 46, 55, 19, 136, 160, 33, 206, 71 },
+ { 63, 20, 8, 114, 114, 208, 12, 9, 226 },
+ { 81, 40, 11, 96, 182, 84, 29, 16, 36 } },
+ { { 134, 183, 89, 137, 98, 101, 106, 165, 148 },
+ { 72, 187, 100, 130, 157, 111, 32, 75, 80 },
+ { 66, 102, 167, 99, 74, 62, 40, 234, 128 },
+ { 41, 53, 9, 178, 241, 141, 26, 8, 107 },
+ { 74, 43, 26, 146, 73, 166, 49, 23, 157 },
+ { 65, 38, 105, 160, 51, 52, 31, 115, 128 },
+ { 104, 79, 12, 27, 217, 255, 87, 17, 7 },
+ { 87, 68, 71, 44, 114, 51, 15, 186, 23 },
+ { 47, 41, 14, 110, 182, 183, 21, 17, 194 },
+ { 66, 45, 25, 102, 197, 189, 23, 18, 22 } },
+ { { 88, 88, 147, 150, 42, 46, 45, 196, 205 },
+ { 43, 97, 183, 117, 85, 38, 35, 179, 61 },
+ { 39, 53, 200, 87, 26, 21, 43, 232, 171 },
+ { 56, 34, 51, 104, 114, 102, 29, 93, 77 },
+ { 39, 28, 85, 171, 58, 165, 90, 98, 64 },
+ { 34, 22, 116, 206, 23, 34, 43, 166, 73 },
+ { 107, 54, 32, 26, 51, 1, 81, 43, 31 },
+ { 68, 25, 106, 22, 64, 171, 36, 225, 114 },
+ { 34, 19, 21, 102, 132, 188, 16, 76, 124 },
+ { 62, 18, 78, 95, 85, 57, 50, 48, 51 } },
+ { { 193, 101, 35, 159, 215, 111, 89, 46, 111 },
+ { 60, 148, 31, 172, 219, 228, 21, 18, 111 },
+ { 112, 113, 77, 85, 179, 255, 38, 120, 114 },
+ { 40, 42, 1, 196, 245, 209, 10, 25, 109 },
+ { 88, 43, 29, 140, 166, 213, 37, 43, 154 },
+ { 61, 63, 30, 155, 67, 45, 68, 1, 209 },
+ { 100, 80, 8, 43, 154, 1, 51, 26, 71 },
+ { 142, 78, 78, 16, 255, 128, 34, 197, 171 },
+ { 41, 40, 5, 102, 211, 183, 4, 1, 221 },
+ { 51, 50, 17, 168, 209, 192, 23, 25, 82 } },
+ { { 138, 31, 36, 171, 27, 166, 38, 44, 229 },
+ { 67, 87, 58, 169, 82, 115, 26, 59, 179 },
+ { 63, 59, 90, 180, 59, 166, 93, 73, 154 },
+ { 40, 40, 21, 116, 143, 209, 34, 39, 175 },
+ { 47, 15, 16, 183, 34, 223, 49, 45, 183 },
+ { 46, 17, 33, 183, 6, 98, 15, 32, 183 },
+ { 57, 46, 22, 24, 128, 1, 54, 17, 37 },
+ { 65, 32, 73, 115, 28, 128, 23, 128, 205 },
+ { 40, 3, 9, 115, 51, 192, 18, 6, 223 },
+ { 87, 37, 9, 115, 59, 77, 64, 21, 47 } },
+ { { 104, 55, 44, 218, 9, 54, 53, 130, 226 },
+ { 64, 90, 70, 205, 40, 41, 23, 26, 57 },
+ { 54, 57, 112, 184, 5, 41, 38, 166, 213 },
+ { 30, 34, 26, 133, 152, 116, 10, 32, 134 },
+ { 39, 19, 53, 221, 26, 114, 32, 73, 255 },
+ { 31, 9, 65, 234, 2, 15, 1, 118, 73 },
+ { 75, 32, 12, 51, 192, 255, 160, 43, 51 },
+ { 88, 31, 35, 67, 102, 85, 55, 186, 85 },
+ { 56, 21, 23, 111, 59, 205, 45, 37, 192 },
+ { 55, 38, 70, 124, 73, 102, 1, 34, 98 } },
+ { { 125, 98, 42, 88, 104, 85, 117, 175, 82 },
+ { 95, 84, 53, 89, 128, 100, 113, 101, 45 },
+ { 75, 79, 123, 47, 51, 128, 81, 171, 1 },
+ { 57, 17, 5, 71, 102, 57, 53, 41, 49 },
+ { 38, 33, 13, 121, 57, 73, 26, 1, 85 },
+ { 41, 10, 67, 138, 77, 110, 90, 47, 114 },
+ { 115, 21, 2, 10, 102, 255, 166, 23, 6 },
+ { 101, 29, 16, 10, 85, 128, 101, 196, 26 },
+ { 57, 18, 10, 102, 102, 213, 34, 20, 43 },
+ { 117, 20, 15, 36, 163, 128, 68, 1, 26 } },
+ { { 102, 61, 71, 37, 34, 53, 31, 243, 192 },
+ { 69, 60, 71, 38, 73, 119, 28, 222, 37 },
+ { 68, 45, 128, 34, 1, 47, 11, 245, 171 },
+ { 62, 17, 19, 70, 146, 85, 55, 62, 70 },
+ { 37, 43, 37, 154, 100, 163, 85, 160, 1 },
+ { 63, 9, 92, 136, 28, 64, 32, 201, 85 },
+ { 75, 15, 9, 9, 64, 255, 184, 119, 16 },
+ { 86, 6, 28, 5, 64, 255, 25, 248, 1 },
+ { 56, 8, 17, 132, 137, 255, 55, 116, 128 },
+ { 58, 15, 20, 82, 135, 57, 26, 121, 40 } },
+ { { 164, 50, 31, 137, 154, 133, 25, 35, 218 },
+ { 51, 103, 44, 131, 131, 123, 31, 6, 158 },
+ { 86, 40, 64, 135, 148, 224, 45, 183, 128 },
+ { 22, 26, 17, 131, 240, 154, 14, 1, 209 },
+ { 45, 16, 21, 91, 64, 222, 7, 1, 197 },
+ { 56, 21, 39, 155, 60, 138, 23, 102, 213 },
+ { 83, 12, 13, 54, 192, 255, 68, 47, 28 },
+ { 85, 26, 85, 85, 128, 128, 32, 146, 171 },
+ { 18, 11, 7, 63, 144, 171, 4, 4, 246 },
+ { 35, 27, 10, 146, 174, 171, 12, 26, 128 } },
+ { { 190, 80, 35, 99, 180, 80, 126, 54, 45 },
+ { 85, 126, 47, 87, 176, 51, 41, 20, 32 },
+ { 101, 75, 128, 139, 118, 146, 116, 128, 85 },
+ { 56, 41, 15, 176, 236, 85, 37, 9, 62 },
+ { 71, 30, 17, 119, 118, 255, 17, 18, 138 },
+ { 101, 38, 60, 138, 55, 70, 43, 26, 142 },
+ { 146, 36, 19, 30, 171, 255, 97, 27, 20 },
+ { 138, 45, 61, 62, 219, 1, 81, 188, 64 },
+ { 32, 41, 20, 117, 151, 142, 20, 21, 163 },
+ { 112, 19, 12, 61, 195, 128, 48, 4, 24 } }
+};
+
+void VP8ResetProba(VP8Proba* const proba) {
+ memset(proba->segments_, 255u, sizeof(proba->segments_));
+ memcpy(proba->coeffs_, CoeffsProba0, sizeof(CoeffsProba0));
+#ifndef ONLY_KEYFRAME_CODE
+ memcpy(proba->mv_, kMVProba0, sizeof(kMVProba0));
+ memcpy(proba->ymode_, kYModeProbaInter0, sizeof(kYModeProbaInter0));
+ memcpy(proba->uvmode_, kUVModeProbaInter0, sizeof(kUVModeProbaInter0));
+#endif
+}
+
+void VP8ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec) {
+ uint8_t* const top = dec->intra_t_ + 4 * dec->mb_x_;
+ uint8_t* const left = dec->intra_l_;
+ // Hardcoded 16x16 intra-mode decision tree.
+ dec->is_i4x4_ = !VP8GetBit(br, 145); // decide for B_PRED first
+ if (!dec->is_i4x4_) {
+ const int ymode =
+ VP8GetBit(br, 156) ? (VP8GetBit(br, 128) ? TM_PRED : H_PRED)
+ : (VP8GetBit(br, 163) ? V_PRED : DC_PRED);
+ dec->imodes_[0] = ymode;
+ memset(top, ymode, 4 * sizeof(top[0]));
+ memset(left, ymode, 4 * sizeof(left[0]));
+ } else {
+ uint8_t* modes = dec->imodes_;
+ int y;
+ for (y = 0; y < 4; ++y) {
+ int ymode = left[y];
+ int x;
+ for (x = 0; x < 4; ++x) {
+ const uint8_t* const prob = kBModesProba[top[x]][ymode];
+#ifdef USE_GENERIC_TREE
+ // Generic tree-parsing
+ int i = 0;
+ do {
+ i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])];
+ } while (i > 0);
+ ymode = -i;
+#else
+ // Hardcoded tree parsing
+ ymode = !VP8GetBit(br, prob[0]) ? B_DC_PRED :
+ !VP8GetBit(br, prob[1]) ? B_TM_PRED :
+ !VP8GetBit(br, prob[2]) ? B_VE_PRED :
+ !VP8GetBit(br, prob[3]) ?
+ (!VP8GetBit(br, prob[4]) ? B_HE_PRED :
+ (!VP8GetBit(br, prob[5]) ? B_RD_PRED : B_VR_PRED)) :
+ (!VP8GetBit(br, prob[6]) ? B_LD_PRED :
+ (!VP8GetBit(br, prob[7]) ? B_VL_PRED :
+ (!VP8GetBit(br, prob[8]) ? B_HD_PRED : B_HU_PRED)));
+#endif // USE_GENERIC_TREE
+ top[x] = ymode;
+ *modes++ = ymode;
+ }
+ left[y] = ymode;
+ }
+ }
+ // Hardcoded UVMode decision tree
+ dec->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED
+ : !VP8GetBit(br, 114) ? V_PRED
+ : VP8GetBit(br, 183) ? TM_PRED : H_PRED;
+}
+
+//------------------------------------------------------------------------------
+// Paragraph 13
+
+static const uint8_t
+ CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
+ { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 },
+ { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 },
+ { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ }
+ },
+ { { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 },
+ { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 }
+ },
+ { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ }
+ },
+ { { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 },
+ { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 }
+ },
+ { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ }
+ },
+ { { { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 },
+ { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ }
+ }
+};
+
+#ifndef ONLY_KEYFRAME_CODE
+static const uint8_t MVUpdateProba[2][NUM_MV_PROBAS] = {
+ { 237, 246, 253, 253, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 250, 250,
+ 252, 254, 254 },
+ { 231, 243, 245, 253, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 251, 251,
+ 254, 254, 254 }
+};
+#endif
+
+// Paragraph 9.9
+void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
+ VP8Proba* const proba = &dec->proba_;
+ int t, b, c, p;
+ for (t = 0; t < NUM_TYPES; ++t) {
+ for (b = 0; b < NUM_BANDS; ++b) {
+ for (c = 0; c < NUM_CTX; ++c) {
+ for (p = 0; p < NUM_PROBAS; ++p) {
+ if (VP8GetBit(br, CoeffsUpdateProba[t][b][c][p])) {
+ proba->coeffs_[t][b][c][p] = VP8GetValue(br, 8);
+ }
+ }
+ }
+ }
+ }
+ dec->use_skip_proba_ = VP8Get(br);
+ if (dec->use_skip_proba_) {
+ dec->skip_p_ = VP8GetValue(br, 8);
+ }
+#ifndef ONLY_KEYFRAME_CODE
+ if (!dec->frm_hdr_.key_frame_) {
+ int i;
+ dec->intra_p_ = VP8GetValue(br, 8);
+ dec->last_p_ = VP8GetValue(br, 8);
+ dec->golden_p_ = VP8GetValue(br, 8);
+ if (VP8Get(br)) { // update y-mode
+ for (i = 0; i < 4; ++i) {
+ proba->ymode_[i] = VP8GetValue(br, 8);
+ }
+ }
+ if (VP8Get(br)) { // update uv-mode
+ for (i = 0; i < 3; ++i) {
+ proba->uvmode_[i] = VP8GetValue(br, 8);
+ }
+ }
+ // update MV
+ for (i = 0; i < 2; ++i) {
+ int k;
+ for (k = 0; k < NUM_MV_PROBAS; ++k) {
+ if (VP8GetBit(br, MVUpdateProba[i][k])) {
+ const int v = VP8GetValue(br, 7);
+ proba->mv_[i][k] = v ? v << 1 : 1;
+ }
+ }
+ }
+ }
+#endif
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dec/vp8.c b/drivers/webpold/dec/vp8.c
new file mode 100644
index 0000000000..b0ccfa2a06
--- /dev/null
+++ b/drivers/webpold/dec/vp8.c
@@ -0,0 +1,787 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// main entry for the decoder
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <stdlib.h>
+
+#include "./vp8i.h"
+#include "./vp8li.h"
+#include "./webpi.h"
+#include "../utils/bit_reader.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+
+int WebPGetDecoderVersion(void) {
+ return (DEC_MAJ_VERSION << 16) | (DEC_MIN_VERSION << 8) | DEC_REV_VERSION;
+}
+
+//------------------------------------------------------------------------------
+// VP8Decoder
+
+static void SetOk(VP8Decoder* const dec) {
+ dec->status_ = VP8_STATUS_OK;
+ dec->error_msg_ = "OK";
+}
+
+int VP8InitIoInternal(VP8Io* const io, int version) {
+ if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
+ return 0; // mismatch error
+ }
+ if (io != NULL) {
+ memset(io, 0, sizeof(*io));
+ }
+ return 1;
+}
+
+VP8Decoder* VP8New(void) {
+ VP8Decoder* const dec = (VP8Decoder*)calloc(1, sizeof(*dec));
+ if (dec != NULL) {
+ SetOk(dec);
+ WebPWorkerInit(&dec->worker_);
+ dec->ready_ = 0;
+ dec->num_parts_ = 1;
+ }
+ return dec;
+}
+
+VP8StatusCode VP8Status(VP8Decoder* const dec) {
+ if (!dec) return VP8_STATUS_INVALID_PARAM;
+ return dec->status_;
+}
+
+const char* VP8StatusMessage(VP8Decoder* const dec) {
+ if (dec == NULL) return "no object";
+ if (!dec->error_msg_) return "OK";
+ return dec->error_msg_;
+}
+
+void VP8Delete(VP8Decoder* const dec) {
+ if (dec != NULL) {
+ VP8Clear(dec);
+ free(dec);
+ }
+}
+
+int VP8SetError(VP8Decoder* const dec,
+ VP8StatusCode error, const char* const msg) {
+ // TODO This check would be unnecessary if alpha decompression was separated
+ // from VP8ProcessRow/FinishRow. This avoids setting 'dec->status_' to
+ // something other than VP8_STATUS_BITSTREAM_ERROR on alpha decompression
+ // failure.
+ if (dec->status_ == VP8_STATUS_OK) {
+ dec->status_ = error;
+ dec->error_msg_ = msg;
+ dec->ready_ = 0;
+ }
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+
+int VP8CheckSignature(const uint8_t* const data, size_t data_size) {
+ return (data_size >= 3 &&
+ data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a);
+}
+
+int VP8GetInfo(const uint8_t* data, size_t data_size, size_t chunk_size,
+ int* const width, int* const height) {
+ if (data == NULL || data_size < VP8_FRAME_HEADER_SIZE) {
+ return 0; // not enough data
+ }
+ // check signature
+ if (!VP8CheckSignature(data + 3, data_size - 3)) {
+ return 0; // Wrong signature.
+ } else {
+ const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16);
+ const int key_frame = !(bits & 1);
+ const int w = ((data[7] << 8) | data[6]) & 0x3fff;
+ const int h = ((data[9] << 8) | data[8]) & 0x3fff;
+
+ if (!key_frame) { // Not a keyframe.
+ return 0;
+ }
+
+ if (((bits >> 1) & 7) > 3) {
+ return 0; // unknown profile
+ }
+ if (!((bits >> 4) & 1)) {
+ return 0; // first frame is invisible!
+ }
+ if (((bits >> 5)) >= chunk_size) { // partition_length
+ return 0; // inconsistent size information.
+ }
+
+ if (width) {
+ *width = w;
+ }
+ if (height) {
+ *height = h;
+ }
+
+ return 1;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Header parsing
+
+static void ResetSegmentHeader(VP8SegmentHeader* const hdr) {
+ assert(hdr != NULL);
+ hdr->use_segment_ = 0;
+ hdr->update_map_ = 0;
+ hdr->absolute_delta_ = 1;
+ memset(hdr->quantizer_, 0, sizeof(hdr->quantizer_));
+ memset(hdr->filter_strength_, 0, sizeof(hdr->filter_strength_));
+}
+
+// Paragraph 9.3
+static int ParseSegmentHeader(VP8BitReader* br,
+ VP8SegmentHeader* hdr, VP8Proba* proba) {
+ assert(br != NULL);
+ assert(hdr != NULL);
+ hdr->use_segment_ = VP8Get(br);
+ if (hdr->use_segment_) {
+ hdr->update_map_ = VP8Get(br);
+ if (VP8Get(br)) { // update data
+ int s;
+ hdr->absolute_delta_ = VP8Get(br);
+ for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
+ hdr->quantizer_[s] = VP8Get(br) ? VP8GetSignedValue(br, 7) : 0;
+ }
+ for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
+ hdr->filter_strength_[s] = VP8Get(br) ? VP8GetSignedValue(br, 6) : 0;
+ }
+ }
+ if (hdr->update_map_) {
+ int s;
+ for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) {
+ proba->segments_[s] = VP8Get(br) ? VP8GetValue(br, 8) : 255u;
+ }
+ }
+ } else {
+ hdr->update_map_ = 0;
+ }
+ return !br->eof_;
+}
+
+// Paragraph 9.5
+// This function returns VP8_STATUS_SUSPENDED if we don't have all the
+// necessary data in 'buf'.
+// This case is not necessarily an error (for incremental decoding).
+// Still, no bitreader is ever initialized to make it possible to read
+// unavailable memory.
+// If we don't even have the partitions' sizes, than VP8_STATUS_NOT_ENOUGH_DATA
+// is returned, and this is an unrecoverable error.
+// If the partitions were positioned ok, VP8_STATUS_OK is returned.
+static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
+ const uint8_t* buf, size_t size) {
+ VP8BitReader* const br = &dec->br_;
+ const uint8_t* sz = buf;
+ const uint8_t* buf_end = buf + size;
+ const uint8_t* part_start;
+ int last_part;
+ int p;
+
+ dec->num_parts_ = 1 << VP8GetValue(br, 2);
+ last_part = dec->num_parts_ - 1;
+ part_start = buf + last_part * 3;
+ if (buf_end < part_start) {
+ // we can't even read the sizes with sz[]! That's a failure.
+ return VP8_STATUS_NOT_ENOUGH_DATA;
+ }
+ for (p = 0; p < last_part; ++p) {
+ const uint32_t psize = sz[0] | (sz[1] << 8) | (sz[2] << 16);
+ const uint8_t* part_end = part_start + psize;
+ if (part_end > buf_end) part_end = buf_end;
+ VP8InitBitReader(dec->parts_ + p, part_start, part_end);
+ part_start = part_end;
+ sz += 3;
+ }
+ VP8InitBitReader(dec->parts_ + last_part, part_start, buf_end);
+ return (part_start < buf_end) ? VP8_STATUS_OK :
+ VP8_STATUS_SUSPENDED; // Init is ok, but there's not enough data
+}
+
+// Paragraph 9.4
+static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) {
+ VP8FilterHeader* const hdr = &dec->filter_hdr_;
+ hdr->simple_ = VP8Get(br);
+ hdr->level_ = VP8GetValue(br, 6);
+ hdr->sharpness_ = VP8GetValue(br, 3);
+ hdr->use_lf_delta_ = VP8Get(br);
+ if (hdr->use_lf_delta_) {
+ if (VP8Get(br)) { // update lf-delta?
+ int i;
+ for (i = 0; i < NUM_REF_LF_DELTAS; ++i) {
+ if (VP8Get(br)) {
+ hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6);
+ }
+ }
+ for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) {
+ if (VP8Get(br)) {
+ hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6);
+ }
+ }
+ }
+ }
+ dec->filter_type_ = (hdr->level_ == 0) ? 0 : hdr->simple_ ? 1 : 2;
+ if (dec->filter_type_ > 0) { // precompute filter levels per segment
+ if (dec->segment_hdr_.use_segment_) {
+ int s;
+ for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
+ int strength = dec->segment_hdr_.filter_strength_[s];
+ if (!dec->segment_hdr_.absolute_delta_) {
+ strength += hdr->level_;
+ }
+ dec->filter_levels_[s] = strength;
+ }
+ } else {
+ dec->filter_levels_[0] = hdr->level_;
+ }
+ }
+ return !br->eof_;
+}
+
+// Topmost call
+int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
+ const uint8_t* buf;
+ size_t buf_size;
+ VP8FrameHeader* frm_hdr;
+ VP8PictureHeader* pic_hdr;
+ VP8BitReader* br;
+ VP8StatusCode status;
+ WebPHeaderStructure headers;
+
+ if (dec == NULL) {
+ return 0;
+ }
+ SetOk(dec);
+ if (io == NULL) {
+ return VP8SetError(dec, VP8_STATUS_INVALID_PARAM,
+ "null VP8Io passed to VP8GetHeaders()");
+ }
+
+ // Process Pre-VP8 chunks.
+ headers.data = io->data;
+ headers.data_size = io->data_size;
+ status = WebPParseHeaders(&headers);
+ if (status != VP8_STATUS_OK) {
+ return VP8SetError(dec, status, "Incorrect/incomplete header.");
+ }
+ if (headers.is_lossless) {
+ return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
+ "Unexpected lossless format encountered.");
+ }
+
+ if (dec->alpha_data_ == NULL) {
+ assert(dec->alpha_data_size_ == 0);
+ // We have NOT set alpha data yet. Set it now.
+ // (This is to ensure that dec->alpha_data_ is NOT reset to NULL if
+ // WebPParseHeaders() is called more than once, as in incremental decoding
+ // case.)
+ dec->alpha_data_ = headers.alpha_data;
+ dec->alpha_data_size_ = headers.alpha_data_size;
+ }
+
+ // Process the VP8 frame header.
+ buf = headers.data + headers.offset;
+ buf_size = headers.data_size - headers.offset;
+ assert(headers.data_size >= headers.offset); // WebPParseHeaders' guarantee
+ if (buf_size < 4) {
+ return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
+ "Truncated header.");
+ }
+
+ // Paragraph 9.1
+ {
+ const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16);
+ frm_hdr = &dec->frm_hdr_;
+ frm_hdr->key_frame_ = !(bits & 1);
+ frm_hdr->profile_ = (bits >> 1) & 7;
+ frm_hdr->show_ = (bits >> 4) & 1;
+ frm_hdr->partition_length_ = (bits >> 5);
+ if (frm_hdr->profile_ > 3)
+ return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
+ "Incorrect keyframe parameters.");
+ if (!frm_hdr->show_)
+ return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE,
+ "Frame not displayable.");
+ buf += 3;
+ buf_size -= 3;
+ }
+
+ pic_hdr = &dec->pic_hdr_;
+ if (frm_hdr->key_frame_) {
+ // Paragraph 9.2
+ if (buf_size < 7) {
+ return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
+ "cannot parse picture header");
+ }
+ if (!VP8CheckSignature(buf, buf_size)) {
+ return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
+ "Bad code word");
+ }
+ pic_hdr->width_ = ((buf[4] << 8) | buf[3]) & 0x3fff;
+ pic_hdr->xscale_ = buf[4] >> 6; // ratio: 1, 5/4 5/3 or 2
+ pic_hdr->height_ = ((buf[6] << 8) | buf[5]) & 0x3fff;
+ pic_hdr->yscale_ = buf[6] >> 6;
+ buf += 7;
+ buf_size -= 7;
+
+ dec->mb_w_ = (pic_hdr->width_ + 15) >> 4;
+ dec->mb_h_ = (pic_hdr->height_ + 15) >> 4;
+ // Setup default output area (can be later modified during io->setup())
+ io->width = pic_hdr->width_;
+ io->height = pic_hdr->height_;
+ io->use_scaling = 0;
+ io->use_cropping = 0;
+ io->crop_top = 0;
+ io->crop_left = 0;
+ io->crop_right = io->width;
+ io->crop_bottom = io->height;
+ io->mb_w = io->width; // sanity check
+ io->mb_h = io->height; // ditto
+
+ VP8ResetProba(&dec->proba_);
+ ResetSegmentHeader(&dec->segment_hdr_);
+ dec->segment_ = 0; // default for intra
+ }
+
+ // Check if we have all the partition #0 available, and initialize dec->br_
+ // to read this partition (and this partition only).
+ if (frm_hdr->partition_length_ > buf_size) {
+ return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
+ "bad partition length");
+ }
+
+ br = &dec->br_;
+ VP8InitBitReader(br, buf, buf + frm_hdr->partition_length_);
+ buf += frm_hdr->partition_length_;
+ buf_size -= frm_hdr->partition_length_;
+
+ if (frm_hdr->key_frame_) {
+ pic_hdr->colorspace_ = VP8Get(br);
+ pic_hdr->clamp_type_ = VP8Get(br);
+ }
+ if (!ParseSegmentHeader(br, &dec->segment_hdr_, &dec->proba_)) {
+ return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
+ "cannot parse segment header");
+ }
+ // Filter specs
+ if (!ParseFilterHeader(br, dec)) {
+ return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
+ "cannot parse filter header");
+ }
+ status = ParsePartitions(dec, buf, buf_size);
+ if (status != VP8_STATUS_OK) {
+ return VP8SetError(dec, status, "cannot parse partitions");
+ }
+
+ // quantizer change
+ VP8ParseQuant(dec);
+
+ // Frame buffer marking
+ if (!frm_hdr->key_frame_) {
+ // Paragraph 9.7
+#ifndef ONLY_KEYFRAME_CODE
+ dec->buffer_flags_ = VP8Get(br) << 0; // update golden
+ dec->buffer_flags_ |= VP8Get(br) << 1; // update alt ref
+ if (!(dec->buffer_flags_ & 1)) {
+ dec->buffer_flags_ |= VP8GetValue(br, 2) << 2;
+ }
+ if (!(dec->buffer_flags_ & 2)) {
+ dec->buffer_flags_ |= VP8GetValue(br, 2) << 4;
+ }
+ dec->buffer_flags_ |= VP8Get(br) << 6; // sign bias golden
+ dec->buffer_flags_ |= VP8Get(br) << 7; // sign bias alt ref
+#else
+ return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE,
+ "Not a key frame.");
+#endif
+ } else {
+ dec->buffer_flags_ = 0x003 | 0x100;
+ }
+
+ // Paragraph 9.8
+#ifndef ONLY_KEYFRAME_CODE
+ dec->update_proba_ = VP8Get(br);
+ if (!dec->update_proba_) { // save for later restore
+ dec->proba_saved_ = dec->proba_;
+ }
+ dec->buffer_flags_ &= 1 << 8;
+ dec->buffer_flags_ |=
+ (frm_hdr->key_frame_ || VP8Get(br)) << 8; // refresh last frame
+#else
+ VP8Get(br); // just ignore the value of update_proba_
+#endif
+
+ VP8ParseProba(br, dec);
+
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ // Extensions
+ if (dec->pic_hdr_.colorspace_) {
+ const size_t kTrailerSize = 8;
+ const uint8_t kTrailerMarker = 0x01;
+ const uint8_t* ext_buf = buf - kTrailerSize;
+ size_t size;
+
+ if (frm_hdr->partition_length_ < kTrailerSize ||
+ ext_buf[kTrailerSize - 1] != kTrailerMarker) {
+ return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
+ "RIFF: Inconsistent extra information.");
+ }
+
+ // Layer
+ size = (ext_buf[0] << 0) | (ext_buf[1] << 8) | (ext_buf[2] << 16);
+ dec->layer_data_size_ = size;
+ dec->layer_data_ = NULL; // will be set later
+ dec->layer_colorspace_ = ext_buf[3];
+ }
+#endif
+
+ // sanitized state
+ dec->ready_ = 1;
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Residual decoding (Paragraph 13.2 / 13.3)
+
+static const uint8_t kBands[16 + 1] = {
+ 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
+ 0 // extra entry as sentinel
+};
+
+static const uint8_t kCat3[] = { 173, 148, 140, 0 };
+static const uint8_t kCat4[] = { 176, 155, 140, 135, 0 };
+static const uint8_t kCat5[] = { 180, 157, 141, 134, 130, 0 };
+static const uint8_t kCat6[] =
+ { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 };
+static const uint8_t* const kCat3456[] = { kCat3, kCat4, kCat5, kCat6 };
+static const uint8_t kZigzag[16] = {
+ 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
+};
+
+typedef const uint8_t (*ProbaArray)[NUM_CTX][NUM_PROBAS]; // for const-casting
+
+// Returns the position of the last non-zero coeff plus one
+// (and 0 if there's no coeff at all)
+static int GetCoeffs(VP8BitReader* const br, ProbaArray prob,
+ int ctx, const quant_t dq, int n, int16_t* out) {
+ // n is either 0 or 1 here. kBands[n] is not necessary for extracting '*p'.
+ const uint8_t* p = prob[n][ctx];
+ if (!VP8GetBit(br, p[0])) { // first EOB is more a 'CBP' bit.
+ return 0;
+ }
+ while (1) {
+ ++n;
+ if (!VP8GetBit(br, p[1])) {
+ p = prob[kBands[n]][0];
+ } else { // non zero coeff
+ int v, j;
+ if (!VP8GetBit(br, p[2])) {
+ p = prob[kBands[n]][1];
+ v = 1;
+ } else {
+ if (!VP8GetBit(br, p[3])) {
+ if (!VP8GetBit(br, p[4])) {
+ v = 2;
+ } else {
+ v = 3 + VP8GetBit(br, p[5]);
+ }
+ } else {
+ if (!VP8GetBit(br, p[6])) {
+ if (!VP8GetBit(br, p[7])) {
+ v = 5 + VP8GetBit(br, 159);
+ } else {
+ v = 7 + 2 * VP8GetBit(br, 165);
+ v += VP8GetBit(br, 145);
+ }
+ } else {
+ const uint8_t* tab;
+ const int bit1 = VP8GetBit(br, p[8]);
+ const int bit0 = VP8GetBit(br, p[9 + bit1]);
+ const int cat = 2 * bit1 + bit0;
+ v = 0;
+ for (tab = kCat3456[cat]; *tab; ++tab) {
+ v += v + VP8GetBit(br, *tab);
+ }
+ v += 3 + (8 << cat);
+ }
+ }
+ p = prob[kBands[n]][2];
+ }
+ j = kZigzag[n - 1];
+ out[j] = VP8GetSigned(br, v) * dq[j > 0];
+ if (n == 16 || !VP8GetBit(br, p[0])) { // EOB
+ return n;
+ }
+ }
+ if (n == 16) {
+ return 16;
+ }
+ }
+}
+
+// Alias-safe way of converting 4bytes to 32bits.
+typedef union {
+ uint8_t i8[4];
+ uint32_t i32;
+} PackedNz;
+
+// Table to unpack four bits into four bytes
+static const PackedNz kUnpackTab[16] = {
+ {{0, 0, 0, 0}}, {{1, 0, 0, 0}}, {{0, 1, 0, 0}}, {{1, 1, 0, 0}},
+ {{0, 0, 1, 0}}, {{1, 0, 1, 0}}, {{0, 1, 1, 0}}, {{1, 1, 1, 0}},
+ {{0, 0, 0, 1}}, {{1, 0, 0, 1}}, {{0, 1, 0, 1}}, {{1, 1, 0, 1}},
+ {{0, 0, 1, 1}}, {{1, 0, 1, 1}}, {{0, 1, 1, 1}}, {{1, 1, 1, 1}} };
+
+// Macro to pack four LSB of four bytes into four bits.
+#if defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || \
+ defined(__BIG_ENDIAN__)
+#define PACK_CST 0x08040201U
+#else
+#define PACK_CST 0x01020408U
+#endif
+#define PACK(X, S) ((((X).i32 * PACK_CST) & 0xff000000) >> (S))
+
+static void ParseResiduals(VP8Decoder* const dec,
+ VP8MB* const mb, VP8BitReader* const token_br) {
+ int out_t_nz, out_l_nz, first;
+ ProbaArray ac_prob;
+ const VP8QuantMatrix* q = &dec->dqm_[dec->segment_];
+ int16_t* dst = dec->coeffs_;
+ VP8MB* const left_mb = dec->mb_info_ - 1;
+ PackedNz nz_ac, nz_dc;
+ PackedNz tnz, lnz;
+ uint32_t non_zero_ac = 0;
+ uint32_t non_zero_dc = 0;
+ int x, y, ch;
+
+ nz_dc.i32 = nz_ac.i32 = 0;
+ memset(dst, 0, 384 * sizeof(*dst));
+ if (!dec->is_i4x4_) { // parse DC
+ int16_t dc[16] = { 0 };
+ const int ctx = mb->dc_nz_ + left_mb->dc_nz_;
+ mb->dc_nz_ = left_mb->dc_nz_ =
+ (GetCoeffs(token_br, (ProbaArray)dec->proba_.coeffs_[1],
+ ctx, q->y2_mat_, 0, dc) > 0);
+ first = 1;
+ ac_prob = (ProbaArray)dec->proba_.coeffs_[0];
+ VP8TransformWHT(dc, dst);
+ } else {
+ first = 0;
+ ac_prob = (ProbaArray)dec->proba_.coeffs_[3];
+ }
+
+ tnz = kUnpackTab[mb->nz_ & 0xf];
+ lnz = kUnpackTab[left_mb->nz_ & 0xf];
+ for (y = 0; y < 4; ++y) {
+ int l = lnz.i8[y];
+ for (x = 0; x < 4; ++x) {
+ const int ctx = l + tnz.i8[x];
+ const int nz = GetCoeffs(token_br, ac_prob, ctx,
+ q->y1_mat_, first, dst);
+ tnz.i8[x] = l = (nz > 0);
+ nz_dc.i8[x] = (dst[0] != 0);
+ nz_ac.i8[x] = (nz > 1);
+ dst += 16;
+ }
+ lnz.i8[y] = l;
+ non_zero_dc |= PACK(nz_dc, 24 - y * 4);
+ non_zero_ac |= PACK(nz_ac, 24 - y * 4);
+ }
+ out_t_nz = PACK(tnz, 24);
+ out_l_nz = PACK(lnz, 24);
+
+ tnz = kUnpackTab[mb->nz_ >> 4];
+ lnz = kUnpackTab[left_mb->nz_ >> 4];
+ for (ch = 0; ch < 4; ch += 2) {
+ for (y = 0; y < 2; ++y) {
+ int l = lnz.i8[ch + y];
+ for (x = 0; x < 2; ++x) {
+ const int ctx = l + tnz.i8[ch + x];
+ const int nz =
+ GetCoeffs(token_br, (ProbaArray)dec->proba_.coeffs_[2],
+ ctx, q->uv_mat_, 0, dst);
+ tnz.i8[ch + x] = l = (nz > 0);
+ nz_dc.i8[y * 2 + x] = (dst[0] != 0);
+ nz_ac.i8[y * 2 + x] = (nz > 1);
+ dst += 16;
+ }
+ lnz.i8[ch + y] = l;
+ }
+ non_zero_dc |= PACK(nz_dc, 8 - ch * 2);
+ non_zero_ac |= PACK(nz_ac, 8 - ch * 2);
+ }
+ out_t_nz |= PACK(tnz, 20);
+ out_l_nz |= PACK(lnz, 20);
+ mb->nz_ = out_t_nz;
+ left_mb->nz_ = out_l_nz;
+
+ dec->non_zero_ac_ = non_zero_ac;
+ dec->non_zero_ = non_zero_ac | non_zero_dc;
+ mb->skip_ = !dec->non_zero_;
+}
+#undef PACK
+
+//------------------------------------------------------------------------------
+// Main loop
+
+int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) {
+ VP8BitReader* const br = &dec->br_;
+ VP8MB* const left = dec->mb_info_ - 1;
+ VP8MB* const info = dec->mb_info_ + dec->mb_x_;
+
+ // Note: we don't save segment map (yet), as we don't expect
+ // to decode more than 1 keyframe.
+ if (dec->segment_hdr_.update_map_) {
+ // Hardcoded tree parsing
+ dec->segment_ = !VP8GetBit(br, dec->proba_.segments_[0]) ?
+ VP8GetBit(br, dec->proba_.segments_[1]) :
+ 2 + VP8GetBit(br, dec->proba_.segments_[2]);
+ }
+ info->skip_ = dec->use_skip_proba_ ? VP8GetBit(br, dec->skip_p_) : 0;
+
+ VP8ParseIntraMode(br, dec);
+ if (br->eof_) {
+ return 0;
+ }
+
+ if (!info->skip_) {
+ ParseResiduals(dec, info, token_br);
+ } else {
+ left->nz_ = info->nz_ = 0;
+ if (!dec->is_i4x4_) {
+ left->dc_nz_ = info->dc_nz_ = 0;
+ }
+ dec->non_zero_ = 0;
+ dec->non_zero_ac_ = 0;
+ }
+
+ return (!token_br->eof_);
+}
+
+void VP8InitScanline(VP8Decoder* const dec) {
+ VP8MB* const left = dec->mb_info_ - 1;
+ left->nz_ = 0;
+ left->dc_nz_ = 0;
+ memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_));
+ dec->filter_row_ =
+ (dec->filter_type_ > 0) &&
+ (dec->mb_y_ >= dec->tl_mb_y_) && (dec->mb_y_ <= dec->br_mb_y_);
+}
+
+static int ParseFrame(VP8Decoder* const dec, VP8Io* io) {
+ for (dec->mb_y_ = 0; dec->mb_y_ < dec->br_mb_y_; ++dec->mb_y_) {
+ VP8BitReader* const token_br =
+ &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)];
+ VP8InitScanline(dec);
+ for (dec->mb_x_ = 0; dec->mb_x_ < dec->mb_w_; dec->mb_x_++) {
+ if (!VP8DecodeMB(dec, token_br)) {
+ return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
+ "Premature end-of-file encountered.");
+ }
+ VP8ReconstructBlock(dec);
+
+ // Store data and save block's filtering params
+ VP8StoreBlock(dec);
+ }
+ if (!VP8ProcessRow(dec, io)) {
+ return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted.");
+ }
+ }
+ if (dec->use_threads_ && !WebPWorkerSync(&dec->worker_)) {
+ return 0;
+ }
+
+ // Finish
+#ifndef ONLY_KEYFRAME_CODE
+ if (!dec->update_proba_) {
+ dec->proba_ = dec->proba_saved_;
+ }
+#endif
+
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ if (dec->layer_data_size_ > 0) {
+ if (!VP8DecodeLayer(dec)) {
+ return 0;
+ }
+ }
+#endif
+
+ return 1;
+}
+
+// Main entry point
+int VP8Decode(VP8Decoder* const dec, VP8Io* const io) {
+ int ok = 0;
+ if (dec == NULL) {
+ return 0;
+ }
+ if (io == NULL) {
+ return VP8SetError(dec, VP8_STATUS_INVALID_PARAM,
+ "NULL VP8Io parameter in VP8Decode().");
+ }
+
+ if (!dec->ready_) {
+ if (!VP8GetHeaders(dec, io)) {
+ return 0;
+ }
+ }
+ assert(dec->ready_);
+
+ // Finish setting up the decoding parameter. Will call io->setup().
+ ok = (VP8EnterCritical(dec, io) == VP8_STATUS_OK);
+ if (ok) { // good to go.
+ // Will allocate memory and prepare everything.
+ if (ok) ok = VP8InitFrame(dec, io);
+
+ // Main decoding loop
+ if (ok) ok = ParseFrame(dec, io);
+
+ // Exit.
+ ok &= VP8ExitCritical(dec, io);
+ }
+
+ if (!ok) {
+ VP8Clear(dec);
+ return 0;
+ }
+
+ dec->ready_ = 0;
+ return ok;
+}
+
+void VP8Clear(VP8Decoder* const dec) {
+ if (dec == NULL) {
+ return;
+ }
+ if (dec->use_threads_) {
+ WebPWorkerEnd(&dec->worker_);
+ }
+ if (dec->mem_) {
+ free(dec->mem_);
+ }
+ dec->mem_ = NULL;
+ dec->mem_size_ = 0;
+ memset(&dec->br_, 0, sizeof(dec->br_));
+ dec->ready_ = 0;
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dec/vp8i.h b/drivers/webpold/dec/vp8i.h
new file mode 100644
index 0000000000..4382edfd8e
--- /dev/null
+++ b/drivers/webpold/dec/vp8i.h
@@ -0,0 +1,335 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// VP8 decoder: internal header.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_DEC_VP8I_H_
+#define WEBP_DEC_VP8I_H_
+
+#include <string.h> // for memcpy()
+#include "./vp8li.h"
+#include "../utils/bit_reader.h"
+#include "../utils/thread.h"
+#include "../dsp/dsp.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Various defines and enums
+
+// version numbers
+#define DEC_MAJ_VERSION 0
+#define DEC_MIN_VERSION 2
+#define DEC_REV_VERSION 0
+
+#define ONLY_KEYFRAME_CODE // to remove any code related to P-Frames
+
+// intra prediction modes
+enum { B_DC_PRED = 0, // 4x4 modes
+ B_TM_PRED,
+ B_VE_PRED,
+ B_HE_PRED,
+ B_RD_PRED,
+ B_VR_PRED,
+ B_LD_PRED,
+ B_VL_PRED,
+ B_HD_PRED,
+ B_HU_PRED,
+ NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10
+
+ // Luma16 or UV modes
+ DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED,
+ H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED,
+ B_PRED = NUM_BMODES, // refined I4x4 mode
+
+ // special modes
+ B_DC_PRED_NOTOP = 4,
+ B_DC_PRED_NOLEFT = 5,
+ B_DC_PRED_NOTOPLEFT = 6,
+ NUM_B_DC_MODES = 7 };
+
+enum { MB_FEATURE_TREE_PROBS = 3,
+ NUM_MB_SEGMENTS = 4,
+ NUM_REF_LF_DELTAS = 4,
+ NUM_MODE_LF_DELTAS = 4, // I4x4, ZERO, *, SPLIT
+ MAX_NUM_PARTITIONS = 8,
+ // Probabilities
+ NUM_TYPES = 4,
+ NUM_BANDS = 8,
+ NUM_CTX = 3,
+ NUM_PROBAS = 11,
+ NUM_MV_PROBAS = 19 };
+
+// YUV-cache parameters.
+// Constraints are: We need to store one 16x16 block of luma samples (y),
+// and two 8x8 chroma blocks (u/v). These are better be 16-bytes aligned,
+// in order to be SIMD-friendly. We also need to store the top, left and
+// top-left samples (from previously decoded blocks), along with four
+// extra top-right samples for luma (intra4x4 prediction only).
+// One possible layout is, using 32 * (17 + 9) bytes:
+//
+// .+------ <- only 1 pixel high
+// .|yyyyt.
+// .|yyyyt.
+// .|yyyyt.
+// .|yyyy..
+// .+--.+-- <- only 1 pixel high
+// .|uu.|vv
+// .|uu.|vv
+//
+// Every character is a 4x4 block, with legend:
+// '.' = unused
+// 'y' = y-samples 'u' = u-samples 'v' = u-samples
+// '|' = left sample, '-' = top sample, '+' = top-left sample
+// 't' = extra top-right sample for 4x4 modes
+// With this layout, BPS (=Bytes Per Scan-line) is one cacheline size.
+#define BPS 32 // this is the common stride used by yuv[]
+#define YUV_SIZE (BPS * 17 + BPS * 9)
+#define Y_SIZE (BPS * 17)
+#define Y_OFF (BPS * 1 + 8)
+#define U_OFF (Y_OFF + BPS * 16 + BPS)
+#define V_OFF (U_OFF + 16)
+
+//------------------------------------------------------------------------------
+// Headers
+
+typedef struct {
+ uint8_t key_frame_;
+ uint8_t profile_;
+ uint8_t show_;
+ uint32_t partition_length_;
+} VP8FrameHeader;
+
+typedef struct {
+ uint16_t width_;
+ uint16_t height_;
+ uint8_t xscale_;
+ uint8_t yscale_;
+ uint8_t colorspace_; // 0 = YCbCr
+ uint8_t clamp_type_;
+} VP8PictureHeader;
+
+// segment features
+typedef struct {
+ int use_segment_;
+ int update_map_; // whether to update the segment map or not
+ int absolute_delta_; // absolute or delta values for quantizer and filter
+ int8_t quantizer_[NUM_MB_SEGMENTS]; // quantization changes
+ int8_t filter_strength_[NUM_MB_SEGMENTS]; // filter strength for segments
+} VP8SegmentHeader;
+
+// Struct collecting all frame-persistent probabilities.
+typedef struct {
+ uint8_t segments_[MB_FEATURE_TREE_PROBS];
+ // Type: 0:Intra16-AC 1:Intra16-DC 2:Chroma 3:Intra4
+ uint8_t coeffs_[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS];
+#ifndef ONLY_KEYFRAME_CODE
+ uint8_t ymode_[4], uvmode_[3];
+ uint8_t mv_[2][NUM_MV_PROBAS];
+#endif
+} VP8Proba;
+
+// Filter parameters
+typedef struct {
+ int simple_; // 0=complex, 1=simple
+ int level_; // [0..63]
+ int sharpness_; // [0..7]
+ int use_lf_delta_;
+ int ref_lf_delta_[NUM_REF_LF_DELTAS];
+ int mode_lf_delta_[NUM_MODE_LF_DELTAS];
+} VP8FilterHeader;
+
+//------------------------------------------------------------------------------
+// Informations about the macroblocks.
+
+typedef struct { // filter specs
+ unsigned int f_level_:6; // filter strength: 0..63
+ unsigned int f_ilevel_:6; // inner limit: 1..63
+ unsigned int f_inner_:1; // do inner filtering?
+} VP8FInfo;
+
+typedef struct { // used for syntax-parsing
+ unsigned int nz_; // non-zero AC/DC coeffs
+ unsigned int dc_nz_:1; // non-zero DC coeffs
+ unsigned int skip_:1; // block type
+} VP8MB;
+
+// Dequantization matrices
+typedef int quant_t[2]; // [DC / AC]. Can be 'uint16_t[2]' too (~slower).
+typedef struct {
+ quant_t y1_mat_, y2_mat_, uv_mat_;
+} VP8QuantMatrix;
+
+// Persistent information needed by the parallel processing
+typedef struct {
+ int id_; // cache row to process (in [0..2])
+ int mb_y_; // macroblock position of the row
+ int filter_row_; // true if row-filtering is needed
+ VP8FInfo* f_info_; // filter strengths
+ VP8Io io_; // copy of the VP8Io to pass to put()
+} VP8ThreadContext;
+
+//------------------------------------------------------------------------------
+// VP8Decoder: the main opaque structure handed over to user
+
+struct VP8Decoder {
+ VP8StatusCode status_;
+ int ready_; // true if ready to decode a picture with VP8Decode()
+ const char* error_msg_; // set when status_ is not OK.
+
+ // Main data source
+ VP8BitReader br_;
+
+ // headers
+ VP8FrameHeader frm_hdr_;
+ VP8PictureHeader pic_hdr_;
+ VP8FilterHeader filter_hdr_;
+ VP8SegmentHeader segment_hdr_;
+
+ // Worker
+ WebPWorker worker_;
+ int use_threads_; // use multi-thread
+ int cache_id_; // current cache row
+ int num_caches_; // number of cached rows of 16 pixels (1, 2 or 3)
+ VP8ThreadContext thread_ctx_; // Thread context
+
+ // dimension, in macroblock units.
+ int mb_w_, mb_h_;
+
+ // Macroblock to process/filter, depending on cropping and filter_type.
+ int tl_mb_x_, tl_mb_y_; // top-left MB that must be in-loop filtered
+ int br_mb_x_, br_mb_y_; // last bottom-right MB that must be decoded
+
+ // number of partitions.
+ int num_parts_;
+ // per-partition boolean decoders.
+ VP8BitReader parts_[MAX_NUM_PARTITIONS];
+
+ // buffer refresh flags
+ // bit 0: refresh Gold, bit 1: refresh Alt
+ // bit 2-3: copy to Gold, bit 4-5: copy to Alt
+ // bit 6: Gold sign bias, bit 7: Alt sign bias
+ // bit 8: refresh last frame
+ uint32_t buffer_flags_;
+
+ // dequantization (one set of DC/AC dequant factor per segment)
+ VP8QuantMatrix dqm_[NUM_MB_SEGMENTS];
+
+ // probabilities
+ VP8Proba proba_;
+ int use_skip_proba_;
+ uint8_t skip_p_;
+#ifndef ONLY_KEYFRAME_CODE
+ uint8_t intra_p_, last_p_, golden_p_;
+ VP8Proba proba_saved_;
+ int update_proba_;
+#endif
+
+ // Boundary data cache and persistent buffers.
+ uint8_t* intra_t_; // top intra modes values: 4 * mb_w_
+ uint8_t intra_l_[4]; // left intra modes values
+ uint8_t* y_t_; // top luma samples: 16 * mb_w_
+ uint8_t* u_t_, *v_t_; // top u/v samples: 8 * mb_w_ each
+
+ VP8MB* mb_info_; // contextual macroblock info (mb_w_ + 1)
+ VP8FInfo* f_info_; // filter strength info
+ uint8_t* yuv_b_; // main block for Y/U/V (size = YUV_SIZE)
+ int16_t* coeffs_; // 384 coeffs = (16+8+8) * 4*4
+
+ uint8_t* cache_y_; // macroblock row for storing unfiltered samples
+ uint8_t* cache_u_;
+ uint8_t* cache_v_;
+ int cache_y_stride_;
+ int cache_uv_stride_;
+
+ // main memory chunk for the above data. Persistent.
+ void* mem_;
+ size_t mem_size_;
+
+ // Per macroblock non-persistent infos.
+ int mb_x_, mb_y_; // current position, in macroblock units
+ uint8_t is_i4x4_; // true if intra4x4
+ uint8_t imodes_[16]; // one 16x16 mode (#0) or sixteen 4x4 modes
+ uint8_t uvmode_; // chroma prediction mode
+ uint8_t segment_; // block's segment
+
+ // bit-wise info about the content of each sub-4x4 blocks: there are 16 bits
+ // for luma (bits #0->#15), then 4 bits for chroma-u (#16->#19) and 4 bits for
+ // chroma-v (#20->#23), each corresponding to one 4x4 block in decoding order.
+ // If the bit is set, the 4x4 block contains some non-zero coefficients.
+ uint32_t non_zero_;
+ uint32_t non_zero_ac_;
+
+ // Filtering side-info
+ int filter_type_; // 0=off, 1=simple, 2=complex
+ int filter_row_; // per-row flag
+ uint8_t filter_levels_[NUM_MB_SEGMENTS]; // precalculated per-segment
+
+ // extensions
+ const uint8_t* alpha_data_; // compressed alpha data (if present)
+ size_t alpha_data_size_;
+ uint8_t* alpha_plane_; // output. Persistent, contains the whole data.
+
+ int layer_colorspace_;
+ const uint8_t* layer_data_; // compressed layer data (if present)
+ size_t layer_data_size_;
+};
+
+//------------------------------------------------------------------------------
+// internal functions. Not public.
+
+// in vp8.c
+int VP8SetError(VP8Decoder* const dec,
+ VP8StatusCode error, const char* const msg);
+
+// in tree.c
+void VP8ResetProba(VP8Proba* const proba);
+void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec);
+void VP8ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec);
+
+// in quant.c
+void VP8ParseQuant(VP8Decoder* const dec);
+
+// in frame.c
+int VP8InitFrame(VP8Decoder* const dec, VP8Io* io);
+// Predict a block and add residual
+void VP8ReconstructBlock(VP8Decoder* const dec);
+// Call io->setup() and finish setting up scan parameters.
+// After this call returns, one must always call VP8ExitCritical() with the
+// same parameters. Both functions should be used in pair. Returns VP8_STATUS_OK
+// if ok, otherwise sets and returns the error status on *dec.
+VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io);
+// Must always be called in pair with VP8EnterCritical().
+// Returns false in case of error.
+int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io);
+// Process the last decoded row (filtering + output)
+int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io);
+// Store a block, along with filtering params
+void VP8StoreBlock(VP8Decoder* const dec);
+// To be called at the start of a new scanline, to initialize predictors.
+void VP8InitScanline(VP8Decoder* const dec);
+// Decode one macroblock. Returns false if there is not enough data.
+int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br);
+
+// in alpha.c
+const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
+ int row, int num_rows);
+
+// in layer.c
+int VP8DecodeLayer(VP8Decoder* const dec);
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_DEC_VP8I_H_ */
diff --git a/drivers/webpold/dec/vp8l.c b/drivers/webpold/dec/vp8l.c
new file mode 100644
index 0000000000..897e4395c7
--- /dev/null
+++ b/drivers/webpold/dec/vp8l.c
@@ -0,0 +1,1200 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// main entry for the decoder
+//
+// Authors: Vikas Arora (vikaas.arora@gmail.com)
+// Jyrki Alakuijala (jyrki@google.com)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "./vp8li.h"
+#include "../dsp/lossless.h"
+#include "../dsp/yuv.h"
+#include "../utils/huffman.h"
+#include "../utils/utils.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define NUM_ARGB_CACHE_ROWS 16
+
+static const int kCodeLengthLiterals = 16;
+static const int kCodeLengthRepeatCode = 16;
+static const int kCodeLengthExtraBits[3] = { 2, 3, 7 };
+static const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };
+
+// -----------------------------------------------------------------------------
+// Five Huffman codes are used at each meta code:
+// 1. green + length prefix codes + color cache codes,
+// 2. alpha,
+// 3. red,
+// 4. blue, and,
+// 5. distance prefix codes.
+typedef enum {
+ GREEN = 0,
+ RED = 1,
+ BLUE = 2,
+ ALPHA = 3,
+ DIST = 4
+} HuffIndex;
+
+static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = {
+ NUM_LITERAL_CODES + NUM_LENGTH_CODES,
+ NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,
+ NUM_DISTANCE_CODES
+};
+
+
+#define NUM_CODE_LENGTH_CODES 19
+static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = {
+ 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+#define CODE_TO_PLANE_CODES 120
+static const uint8_t code_to_plane_lut[CODE_TO_PLANE_CODES] = {
+ 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
+ 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
+ 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
+ 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
+ 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
+ 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
+ 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
+ 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
+ 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
+ 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
+ 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
+ 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70
+};
+
+static int DecodeImageStream(int xsize, int ysize,
+ int is_level0,
+ VP8LDecoder* const dec,
+ uint32_t** const decoded_data);
+
+//------------------------------------------------------------------------------
+
+int VP8LCheckSignature(const uint8_t* const data, size_t size) {
+ return (size >= 1) && (data[0] == VP8L_MAGIC_BYTE);
+}
+
+static int ReadImageInfo(VP8LBitReader* const br,
+ int* const width, int* const height,
+ int* const has_alpha) {
+ const uint8_t signature = VP8LReadBits(br, 8);
+ if (!VP8LCheckSignature(&signature, 1)) {
+ return 0;
+ }
+ *width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
+ *height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
+ *has_alpha = VP8LReadBits(br, 1);
+ VP8LReadBits(br, VP8L_VERSION_BITS); // Read/ignore the version number.
+ return 1;
+}
+
+int VP8LGetInfo(const uint8_t* data, size_t data_size,
+ int* const width, int* const height, int* const has_alpha) {
+ if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) {
+ return 0; // not enough data
+ } else {
+ int w, h, a;
+ VP8LBitReader br;
+ VP8LInitBitReader(&br, data, data_size);
+ if (!ReadImageInfo(&br, &w, &h, &a)) {
+ return 0;
+ }
+ if (width != NULL) *width = w;
+ if (height != NULL) *height = h;
+ if (has_alpha != NULL) *has_alpha = a;
+ return 1;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+static WEBP_INLINE int GetCopyDistance(int distance_symbol,
+ VP8LBitReader* const br) {
+ int extra_bits, offset;
+ if (distance_symbol < 4) {
+ return distance_symbol + 1;
+ }
+ extra_bits = (distance_symbol - 2) >> 1;
+ offset = (2 + (distance_symbol & 1)) << extra_bits;
+ return offset + VP8LReadBits(br, extra_bits) + 1;
+}
+
+static WEBP_INLINE int GetCopyLength(int length_symbol,
+ VP8LBitReader* const br) {
+ // Length and distance prefixes are encoded the same way.
+ return GetCopyDistance(length_symbol, br);
+}
+
+static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {
+ if (plane_code > CODE_TO_PLANE_CODES) {
+ return plane_code - CODE_TO_PLANE_CODES;
+ } else {
+ const int dist_code = code_to_plane_lut[plane_code - 1];
+ const int yoffset = dist_code >> 4;
+ const int xoffset = 8 - (dist_code & 0xf);
+ const int dist = yoffset * xsize + xoffset;
+ return (dist >= 1) ? dist : 1;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Decodes the next Huffman code from bit-stream.
+// FillBitWindow(br) needs to be called at minimum every second call
+// to ReadSymbolUnsafe.
+static int ReadSymbolUnsafe(const HuffmanTree* tree, VP8LBitReader* const br) {
+ const HuffmanTreeNode* node = tree->root_;
+ assert(node != NULL);
+ while (!HuffmanTreeNodeIsLeaf(node)) {
+ node = HuffmanTreeNextNode(node, VP8LReadOneBitUnsafe(br));
+ }
+ return node->symbol_;
+}
+
+static WEBP_INLINE int ReadSymbol(const HuffmanTree* tree,
+ VP8LBitReader* const br) {
+ const int read_safe = (br->pos_ + 8 > br->len_);
+ if (!read_safe) {
+ return ReadSymbolUnsafe(tree, br);
+ } else {
+ const HuffmanTreeNode* node = tree->root_;
+ assert(node != NULL);
+ while (!HuffmanTreeNodeIsLeaf(node)) {
+ node = HuffmanTreeNextNode(node, VP8LReadOneBit(br));
+ }
+ return node->symbol_;
+ }
+}
+
+static int ReadHuffmanCodeLengths(
+ VP8LDecoder* const dec, const int* const code_length_code_lengths,
+ int num_symbols, int* const code_lengths) {
+ int ok = 0;
+ VP8LBitReader* const br = &dec->br_;
+ int symbol;
+ int max_symbol;
+ int prev_code_len = DEFAULT_CODE_LENGTH;
+ HuffmanTree tree;
+
+ if (!HuffmanTreeBuildImplicit(&tree, code_length_code_lengths,
+ NUM_CODE_LENGTH_CODES)) {
+ dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
+ return 0;
+ }
+
+ if (VP8LReadBits(br, 1)) { // use length
+ const int length_nbits = 2 + 2 * VP8LReadBits(br, 3);
+ max_symbol = 2 + VP8LReadBits(br, length_nbits);
+ if (max_symbol > num_symbols) {
+ dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
+ goto End;
+ }
+ } else {
+ max_symbol = num_symbols;
+ }
+
+ symbol = 0;
+ while (symbol < num_symbols) {
+ int code_len;
+ if (max_symbol-- == 0) break;
+ VP8LFillBitWindow(br);
+ code_len = ReadSymbol(&tree, br);
+ if (code_len < kCodeLengthLiterals) {
+ code_lengths[symbol++] = code_len;
+ if (code_len != 0) prev_code_len = code_len;
+ } else {
+ const int use_prev = (code_len == kCodeLengthRepeatCode);
+ const int slot = code_len - kCodeLengthLiterals;
+ const int extra_bits = kCodeLengthExtraBits[slot];
+ const int repeat_offset = kCodeLengthRepeatOffsets[slot];
+ int repeat = VP8LReadBits(br, extra_bits) + repeat_offset;
+ if (symbol + repeat > num_symbols) {
+ dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
+ goto End;
+ } else {
+ const int length = use_prev ? prev_code_len : 0;
+ while (repeat-- > 0) code_lengths[symbol++] = length;
+ }
+ }
+ }
+ ok = 1;
+
+ End:
+ HuffmanTreeRelease(&tree);
+ return ok;
+}
+
+static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
+ HuffmanTree* const tree) {
+ int ok = 0;
+ VP8LBitReader* const br = &dec->br_;
+ const int simple_code = VP8LReadBits(br, 1);
+
+ if (simple_code) { // Read symbols, codes & code lengths directly.
+ int symbols[2];
+ int codes[2];
+ int code_lengths[2];
+ const int num_symbols = VP8LReadBits(br, 1) + 1;
+ const int first_symbol_len_code = VP8LReadBits(br, 1);
+ // The first code is either 1 bit or 8 bit code.
+ symbols[0] = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);
+ codes[0] = 0;
+ code_lengths[0] = num_symbols - 1;
+ // The second code (if present), is always 8 bit long.
+ if (num_symbols == 2) {
+ symbols[1] = VP8LReadBits(br, 8);
+ codes[1] = 1;
+ code_lengths[1] = num_symbols - 1;
+ }
+ ok = HuffmanTreeBuildExplicit(tree, code_lengths, codes, symbols,
+ alphabet_size, num_symbols);
+ } else { // Decode Huffman-coded code lengths.
+ int* code_lengths = NULL;
+ int i;
+ int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
+ const int num_codes = VP8LReadBits(br, 4) + 4;
+ if (num_codes > NUM_CODE_LENGTH_CODES) {
+ dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
+ return 0;
+ }
+
+ code_lengths =
+ (int*)WebPSafeCalloc((uint64_t)alphabet_size, sizeof(*code_lengths));
+ if (code_lengths == NULL) {
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ return 0;
+ }
+
+ for (i = 0; i < num_codes; ++i) {
+ code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3);
+ }
+ ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size,
+ code_lengths);
+ if (ok) {
+ ok = HuffmanTreeBuildImplicit(tree, code_lengths, alphabet_size);
+ }
+ free(code_lengths);
+ }
+ ok = ok && !br->error_;
+ if (!ok) {
+ dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
+ return 0;
+ }
+ return 1;
+}
+
+static void DeleteHtreeGroups(HTreeGroup* htree_groups, int num_htree_groups) {
+ if (htree_groups != NULL) {
+ int i, j;
+ for (i = 0; i < num_htree_groups; ++i) {
+ HuffmanTree* const htrees = htree_groups[i].htrees_;
+ for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
+ HuffmanTreeRelease(&htrees[j]);
+ }
+ }
+ free(htree_groups);
+ }
+}
+
+static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
+ int color_cache_bits, int allow_recursion) {
+ int i, j;
+ VP8LBitReader* const br = &dec->br_;
+ VP8LMetadata* const hdr = &dec->hdr_;
+ uint32_t* huffman_image = NULL;
+ HTreeGroup* htree_groups = NULL;
+ int num_htree_groups = 1;
+
+ if (allow_recursion && VP8LReadBits(br, 1)) {
+ // use meta Huffman codes.
+ const int huffman_precision = VP8LReadBits(br, 3) + 2;
+ const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);
+ const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
+ const int huffman_pixs = huffman_xsize * huffman_ysize;
+ if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,
+ &huffman_image)) {
+ dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
+ goto Error;
+ }
+ hdr->huffman_subsample_bits_ = huffman_precision;
+ for (i = 0; i < huffman_pixs; ++i) {
+ // The huffman data is stored in red and green bytes.
+ const int index = (huffman_image[i] >> 8) & 0xffff;
+ huffman_image[i] = index;
+ if (index >= num_htree_groups) {
+ num_htree_groups = index + 1;
+ }
+ }
+ }
+
+ if (br->error_) goto Error;
+
+ assert(num_htree_groups <= 0x10000);
+ htree_groups =
+ (HTreeGroup*)WebPSafeCalloc((uint64_t)num_htree_groups,
+ sizeof(*htree_groups));
+ if (htree_groups == NULL) {
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ goto Error;
+ }
+
+ for (i = 0; i < num_htree_groups; ++i) {
+ HuffmanTree* const htrees = htree_groups[i].htrees_;
+ for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
+ int alphabet_size = kAlphabetSize[j];
+ if (j == 0 && color_cache_bits > 0) {
+ alphabet_size += 1 << color_cache_bits;
+ }
+ if (!ReadHuffmanCode(alphabet_size, dec, htrees + j)) goto Error;
+ }
+ }
+
+ // All OK. Finalize pointers and return.
+ hdr->huffman_image_ = huffman_image;
+ hdr->num_htree_groups_ = num_htree_groups;
+ hdr->htree_groups_ = htree_groups;
+ return 1;
+
+ Error:
+ free(huffman_image);
+ DeleteHtreeGroups(htree_groups, num_htree_groups);
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+// Scaling.
+
+static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
+ const int num_channels = 4;
+ const int in_width = io->mb_w;
+ const int out_width = io->scaled_width;
+ const int in_height = io->mb_h;
+ const int out_height = io->scaled_height;
+ const uint64_t work_size = 2 * num_channels * (uint64_t)out_width;
+ int32_t* work; // Rescaler work area.
+ const uint64_t scaled_data_size = num_channels * (uint64_t)out_width;
+ uint32_t* scaled_data; // Temporary storage for scaled BGRA data.
+ const uint64_t memory_size = sizeof(*dec->rescaler) +
+ work_size * sizeof(*work) +
+ scaled_data_size * sizeof(*scaled_data);
+ uint8_t* memory = (uint8_t*)WebPSafeCalloc(memory_size, sizeof(*memory));
+ if (memory == NULL) {
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ return 0;
+ }
+ assert(dec->rescaler_memory == NULL);
+ dec->rescaler_memory = memory;
+
+ dec->rescaler = (WebPRescaler*)memory;
+ memory += sizeof(*dec->rescaler);
+ work = (int32_t*)memory;
+ memory += work_size * sizeof(*work);
+ scaled_data = (uint32_t*)memory;
+
+ WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data,
+ out_width, out_height, 0, num_channels,
+ in_width, out_width, in_height, out_height, work);
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Export to ARGB
+
+// We have special "export" function since we need to convert from BGRA
+static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,
+ int rgba_stride, uint8_t* const rgba) {
+ const uint32_t* const src = (const uint32_t*)rescaler->dst;
+ const int dst_width = rescaler->dst_width;
+ int num_lines_out = 0;
+ while (WebPRescalerHasPendingOutput(rescaler)) {
+ uint8_t* const dst = rgba + num_lines_out * rgba_stride;
+ WebPRescalerExportRow(rescaler);
+ VP8LConvertFromBGRA(src, dst_width, colorspace, dst);
+ ++num_lines_out;
+ }
+ return num_lines_out;
+}
+
+// Emit scaled rows.
+static int EmitRescaledRows(const VP8LDecoder* const dec,
+ const uint32_t* const data, int in_stride, int mb_h,
+ uint8_t* const out, int out_stride) {
+ const WEBP_CSP_MODE colorspace = dec->output_->colorspace;
+ const uint8_t* const in = (const uint8_t*)data;
+ int num_lines_in = 0;
+ int num_lines_out = 0;
+ while (num_lines_in < mb_h) {
+ const uint8_t* const row_in = in + num_lines_in * in_stride;
+ uint8_t* const row_out = out + num_lines_out * out_stride;
+ num_lines_in += WebPRescalerImport(dec->rescaler, mb_h - num_lines_in,
+ row_in, in_stride);
+ num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out);
+ }
+ return num_lines_out;
+}
+
+// Emit rows without any scaling.
+static int EmitRows(WEBP_CSP_MODE colorspace,
+ const uint32_t* const data, int in_stride,
+ int mb_w, int mb_h,
+ uint8_t* const out, int out_stride) {
+ int lines = mb_h;
+ const uint8_t* row_in = (const uint8_t*)data;
+ uint8_t* row_out = out;
+ while (lines-- > 0) {
+ VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out);
+ row_in += in_stride;
+ row_out += out_stride;
+ }
+ return mb_h; // Num rows out == num rows in.
+}
+
+//------------------------------------------------------------------------------
+// Export to YUVA
+
+static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,
+ const WebPDecBuffer* const output) {
+ const WebPYUVABuffer* const buf = &output->u.YUVA;
+ // first, the luma plane
+ {
+ int i;
+ uint8_t* const y = buf->y + y_pos * buf->y_stride;
+ for (i = 0; i < width; ++i) {
+ const uint32_t p = src[i];
+ y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff);
+ }
+ }
+
+ // then U/V planes
+ {
+ uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride;
+ uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride;
+ const int uv_width = width >> 1;
+ int i;
+ for (i = 0; i < uv_width; ++i) {
+ const uint32_t v0 = src[2 * i + 0];
+ const uint32_t v1 = src[2 * i + 1];
+ // VP8RGBToU/V expects four accumulated pixels. Hence we need to
+ // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less.
+ const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe);
+ const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe);
+ const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe);
+ if (!(y_pos & 1)) { // even lines: store values
+ u[i] = VP8RGBToU(r, g, b);
+ v[i] = VP8RGBToV(r, g, b);
+ } else { // odd lines: average with previous values
+ const int tmp_u = VP8RGBToU(r, g, b);
+ const int tmp_v = VP8RGBToV(r, g, b);
+ // Approximated average-of-four. But it's an acceptable diff.
+ u[i] = (u[i] + tmp_u + 1) >> 1;
+ v[i] = (v[i] + tmp_v + 1) >> 1;
+ }
+ }
+ if (width & 1) { // last pixel
+ const uint32_t v0 = src[2 * i + 0];
+ const int r = (v0 >> 14) & 0x3fc;
+ const int g = (v0 >> 6) & 0x3fc;
+ const int b = (v0 << 2) & 0x3fc;
+ if (!(y_pos & 1)) { // even lines
+ u[i] = VP8RGBToU(r, g, b);
+ v[i] = VP8RGBToV(r, g, b);
+ } else { // odd lines (note: we could just skip this)
+ const int tmp_u = VP8RGBToU(r, g, b);
+ const int tmp_v = VP8RGBToV(r, g, b);
+ u[i] = (u[i] + tmp_u + 1) >> 1;
+ v[i] = (v[i] + tmp_v + 1) >> 1;
+ }
+ }
+ }
+ // Lastly, store alpha if needed.
+ if (buf->a != NULL) {
+ int i;
+ uint8_t* const a = buf->a + y_pos * buf->a_stride;
+ for (i = 0; i < width; ++i) a[i] = (src[i] >> 24);
+ }
+}
+
+static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {
+ WebPRescaler* const rescaler = dec->rescaler;
+ const uint32_t* const src = (const uint32_t*)rescaler->dst;
+ const int dst_width = rescaler->dst_width;
+ int num_lines_out = 0;
+ while (WebPRescalerHasPendingOutput(rescaler)) {
+ WebPRescalerExportRow(rescaler);
+ ConvertToYUVA(src, dst_width, y_pos, dec->output_);
+ ++y_pos;
+ ++num_lines_out;
+ }
+ return num_lines_out;
+}
+
+static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
+ const uint32_t* const data,
+ int in_stride, int mb_h) {
+ const uint8_t* const in = (const uint8_t*)data;
+ int num_lines_in = 0;
+ int y_pos = dec->last_out_row_;
+ while (num_lines_in < mb_h) {
+ const uint8_t* const row_in = in + num_lines_in * in_stride;
+ num_lines_in += WebPRescalerImport(dec->rescaler, mb_h - num_lines_in,
+ row_in, in_stride);
+ y_pos += ExportYUVA(dec, y_pos);
+ }
+ return y_pos;
+}
+
+static int EmitRowsYUVA(const VP8LDecoder* const dec,
+ const uint32_t* const data, int in_stride,
+ int mb_w, int num_rows) {
+ int y_pos = dec->last_out_row_;
+ const uint8_t* row_in = (const uint8_t*)data;
+ while (num_rows-- > 0) {
+ ConvertToYUVA((const uint32_t*)row_in, mb_w, y_pos, dec->output_);
+ row_in += in_stride;
+ ++y_pos;
+ }
+ return y_pos;
+}
+
+//------------------------------------------------------------------------------
+// Cropping.
+
+// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and
+// crop options. Also updates the input data pointer, so that it points to the
+// start of the cropped window.
+// Note that 'pixel_stride' is in units of 'uint32_t' (and not 'bytes).
+// Returns true if the crop window is not empty.
+static int SetCropWindow(VP8Io* const io, int y_start, int y_end,
+ const uint32_t** const in_data, int pixel_stride) {
+ assert(y_start < y_end);
+ assert(io->crop_left < io->crop_right);
+ if (y_end > io->crop_bottom) {
+ y_end = io->crop_bottom; // make sure we don't overflow on last row.
+ }
+ if (y_start < io->crop_top) {
+ const int delta = io->crop_top - y_start;
+ y_start = io->crop_top;
+ *in_data += pixel_stride * delta;
+ }
+ if (y_start >= y_end) return 0; // Crop window is empty.
+
+ *in_data += io->crop_left;
+
+ io->mb_y = y_start - io->crop_top;
+ io->mb_w = io->crop_right - io->crop_left;
+ io->mb_h = y_end - y_start;
+ return 1; // Non-empty crop window.
+}
+
+//------------------------------------------------------------------------------
+
+static WEBP_INLINE int GetMetaIndex(
+ const uint32_t* const image, int xsize, int bits, int x, int y) {
+ if (bits == 0) return 0;
+ return image[xsize * (y >> bits) + (x >> bits)];
+}
+
+static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
+ int x, int y) {
+ const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_,
+ hdr->huffman_subsample_bits_, x, y);
+ assert(meta_index < hdr->num_htree_groups_);
+ return hdr->htree_groups_ + meta_index;
+}
+
+//------------------------------------------------------------------------------
+// Main loop, with custom row-processing function
+
+typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
+
+static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,
+ const uint32_t* const rows) {
+ int n = dec->next_transform_;
+ const int cache_pixs = dec->width_ * num_rows;
+ const int start_row = dec->last_row_;
+ const int end_row = start_row + num_rows;
+ const uint32_t* rows_in = rows;
+ uint32_t* const rows_out = dec->argb_cache_;
+
+ // Inverse transforms.
+ // TODO: most transforms only need to operate on the cropped region only.
+ memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out));
+ while (n-- > 0) {
+ VP8LTransform* const transform = &dec->transforms_[n];
+ VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out);
+ rows_in = rows_out;
+ }
+}
+
+// Processes (transforms, scales & color-converts) the rows decoded after the
+// last call.
+static void ProcessRows(VP8LDecoder* const dec, int row) {
+ const uint32_t* const rows = dec->argb_ + dec->width_ * dec->last_row_;
+ const int num_rows = row - dec->last_row_;
+
+ if (num_rows <= 0) return; // Nothing to be done.
+ ApplyInverseTransforms(dec, num_rows, rows);
+
+ // Emit output.
+ {
+ VP8Io* const io = dec->io_;
+ const uint32_t* rows_data = dec->argb_cache_;
+ if (!SetCropWindow(io, dec->last_row_, row, &rows_data, io->width)) {
+ // Nothing to output (this time).
+ } else {
+ const WebPDecBuffer* const output = dec->output_;
+ const int in_stride = io->width * sizeof(*rows_data);
+ if (output->colorspace < MODE_YUV) { // convert to RGBA
+ const WebPRGBABuffer* const buf = &output->u.RGBA;
+ uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride;
+ const int num_rows_out = io->use_scaling ?
+ EmitRescaledRows(dec, rows_data, in_stride, io->mb_h,
+ rgba, buf->stride) :
+ EmitRows(output->colorspace, rows_data, in_stride,
+ io->mb_w, io->mb_h, rgba, buf->stride);
+ // Update 'last_out_row_'.
+ dec->last_out_row_ += num_rows_out;
+ } else { // convert to YUVA
+ dec->last_out_row_ = io->use_scaling ?
+ EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) :
+ EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h);
+ }
+ assert(dec->last_out_row_ <= output->height);
+ }
+ }
+
+ // Update 'last_row_'.
+ dec->last_row_ = row;
+ assert(dec->last_row_ <= dec->height_);
+}
+
+static int DecodeImageData(VP8LDecoder* const dec,
+ uint32_t* const data, int width, int height,
+ ProcessRowsFunc process_func) {
+ int ok = 1;
+ int col = 0, row = 0;
+ VP8LBitReader* const br = &dec->br_;
+ VP8LMetadata* const hdr = &dec->hdr_;
+ HTreeGroup* htree_group = hdr->htree_groups_;
+ uint32_t* src = data;
+ uint32_t* last_cached = data;
+ uint32_t* const src_end = data + width * height;
+ const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
+ const int color_cache_limit = len_code_limit + hdr->color_cache_size_;
+ VP8LColorCache* const color_cache =
+ (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL;
+ const int mask = hdr->huffman_mask_;
+
+ assert(htree_group != NULL);
+
+ while (!br->eos_ && src < src_end) {
+ int code;
+ // Only update when changing tile. Note we could use the following test:
+ // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed
+ // but that's actually slower and requires storing the previous col/row
+ if ((col & mask) == 0) {
+ htree_group = GetHtreeGroupForPos(hdr, col, row);
+ }
+ VP8LFillBitWindow(br);
+ code = ReadSymbol(&htree_group->htrees_[GREEN], br);
+ if (code < NUM_LITERAL_CODES) { // Literal.
+ int red, green, blue, alpha;
+ red = ReadSymbol(&htree_group->htrees_[RED], br);
+ green = code;
+ VP8LFillBitWindow(br);
+ blue = ReadSymbol(&htree_group->htrees_[BLUE], br);
+ alpha = ReadSymbol(&htree_group->htrees_[ALPHA], br);
+ *src = (alpha << 24) + (red << 16) + (green << 8) + blue;
+ AdvanceByOne:
+ ++src;
+ ++col;
+ if (col >= width) {
+ col = 0;
+ ++row;
+ if ((process_func != NULL) && (row % NUM_ARGB_CACHE_ROWS == 0)) {
+ process_func(dec, row);
+ }
+ if (color_cache != NULL) {
+ while (last_cached < src) {
+ VP8LColorCacheInsert(color_cache, *last_cached++);
+ }
+ }
+ }
+ } else if (code < len_code_limit) { // Backward reference
+ int dist_code, dist;
+ const int length_sym = code - NUM_LITERAL_CODES;
+ const int length = GetCopyLength(length_sym, br);
+ const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br);
+ VP8LFillBitWindow(br);
+ dist_code = GetCopyDistance(dist_symbol, br);
+ dist = PlaneCodeToDistance(width, dist_code);
+ if (src - data < dist || src_end - src < length) {
+ ok = 0;
+ goto End;
+ }
+ {
+ int i;
+ for (i = 0; i < length; ++i) src[i] = src[i - dist];
+ src += length;
+ }
+ col += length;
+ while (col >= width) {
+ col -= width;
+ ++row;
+ if ((process_func != NULL) && (row % NUM_ARGB_CACHE_ROWS == 0)) {
+ process_func(dec, row);
+ }
+ }
+ if (src < src_end) {
+ htree_group = GetHtreeGroupForPos(hdr, col, row);
+ if (color_cache != NULL) {
+ while (last_cached < src) {
+ VP8LColorCacheInsert(color_cache, *last_cached++);
+ }
+ }
+ }
+ } else if (code < color_cache_limit) { // Color cache.
+ const int key = code - len_code_limit;
+ assert(color_cache != NULL);
+ while (last_cached < src) {
+ VP8LColorCacheInsert(color_cache, *last_cached++);
+ }
+ *src = VP8LColorCacheLookup(color_cache, key);
+ goto AdvanceByOne;
+ } else { // Not reached.
+ ok = 0;
+ goto End;
+ }
+ ok = !br->error_;
+ if (!ok) goto End;
+ }
+ // Process the remaining rows corresponding to last row-block.
+ if (process_func != NULL) process_func(dec, row);
+
+ End:
+ if (br->error_ || !ok || (br->eos_ && src < src_end)) {
+ ok = 0;
+ dec->status_ = (!br->eos_) ?
+ VP8_STATUS_BITSTREAM_ERROR : VP8_STATUS_SUSPENDED;
+ } else if (src == src_end) {
+ dec->state_ = READ_DATA;
+ }
+
+ return ok;
+}
+
+// -----------------------------------------------------------------------------
+// VP8LTransform
+
+static void ClearTransform(VP8LTransform* const transform) {
+ free(transform->data_);
+ transform->data_ = NULL;
+}
+
+// For security reason, we need to remap the color map to span
+// the total possible bundled values, and not just the num_colors.
+static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {
+ int i;
+ const int final_num_colors = 1 << (8 >> transform->bits_);
+ uint32_t* const new_color_map =
+ (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors,
+ sizeof(*new_color_map));
+ if (new_color_map == NULL) {
+ return 0;
+ } else {
+ uint8_t* const data = (uint8_t*)transform->data_;
+ uint8_t* const new_data = (uint8_t*)new_color_map;
+ new_color_map[0] = transform->data_[0];
+ for (i = 4; i < 4 * num_colors; ++i) {
+ // Equivalent to AddPixelEq(), on a byte-basis.
+ new_data[i] = (data[i] + new_data[i - 4]) & 0xff;
+ }
+ for (; i < 4 * final_num_colors; ++i)
+ new_data[i] = 0; // black tail.
+ free(transform->data_);
+ transform->data_ = new_color_map;
+ }
+ return 1;
+}
+
+static int ReadTransform(int* const xsize, int const* ysize,
+ VP8LDecoder* const dec) {
+ int ok = 1;
+ VP8LBitReader* const br = &dec->br_;
+ VP8LTransform* transform = &dec->transforms_[dec->next_transform_];
+ const VP8LImageTransformType type =
+ (VP8LImageTransformType)VP8LReadBits(br, 2);
+
+ // Each transform type can only be present once in the stream.
+ if (dec->transforms_seen_ & (1U << type)) {
+ return 0; // Already there, let's not accept the second same transform.
+ }
+ dec->transforms_seen_ |= (1U << type);
+
+ transform->type_ = type;
+ transform->xsize_ = *xsize;
+ transform->ysize_ = *ysize;
+ transform->data_ = NULL;
+ ++dec->next_transform_;
+ assert(dec->next_transform_ <= NUM_TRANSFORMS);
+
+ switch (type) {
+ case PREDICTOR_TRANSFORM:
+ case CROSS_COLOR_TRANSFORM:
+ transform->bits_ = VP8LReadBits(br, 3) + 2;
+ ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_,
+ transform->bits_),
+ VP8LSubSampleSize(transform->ysize_,
+ transform->bits_),
+ 0, dec, &transform->data_);
+ break;
+ case COLOR_INDEXING_TRANSFORM: {
+ const int num_colors = VP8LReadBits(br, 8) + 1;
+ const int bits = (num_colors > 16) ? 0
+ : (num_colors > 4) ? 1
+ : (num_colors > 2) ? 2
+ : 3;
+ *xsize = VP8LSubSampleSize(transform->xsize_, bits);
+ transform->bits_ = bits;
+ ok = DecodeImageStream(num_colors, 1, 0, dec, &transform->data_);
+ ok = ok && ExpandColorMap(num_colors, transform);
+ break;
+ }
+ case SUBTRACT_GREEN:
+ break;
+ default:
+ assert(0); // can't happen
+ break;
+ }
+
+ return ok;
+}
+
+// -----------------------------------------------------------------------------
+// VP8LMetadata
+
+static void InitMetadata(VP8LMetadata* const hdr) {
+ assert(hdr);
+ memset(hdr, 0, sizeof(*hdr));
+}
+
+static void ClearMetadata(VP8LMetadata* const hdr) {
+ assert(hdr);
+
+ free(hdr->huffman_image_);
+ DeleteHtreeGroups(hdr->htree_groups_, hdr->num_htree_groups_);
+ VP8LColorCacheClear(&hdr->color_cache_);
+ InitMetadata(hdr);
+}
+
+// -----------------------------------------------------------------------------
+// VP8LDecoder
+
+VP8LDecoder* VP8LNew(void) {
+ VP8LDecoder* const dec = (VP8LDecoder*)calloc(1, sizeof(*dec));
+ if (dec == NULL) return NULL;
+ dec->status_ = VP8_STATUS_OK;
+ dec->action_ = READ_DIM;
+ dec->state_ = READ_DIM;
+ return dec;
+}
+
+void VP8LClear(VP8LDecoder* const dec) {
+ int i;
+ if (dec == NULL) return;
+ ClearMetadata(&dec->hdr_);
+
+ free(dec->argb_);
+ dec->argb_ = NULL;
+ for (i = 0; i < dec->next_transform_; ++i) {
+ ClearTransform(&dec->transforms_[i]);
+ }
+ dec->next_transform_ = 0;
+ dec->transforms_seen_ = 0;
+
+ free(dec->rescaler_memory);
+ dec->rescaler_memory = NULL;
+
+ dec->output_ = NULL; // leave no trace behind
+}
+
+void VP8LDelete(VP8LDecoder* const dec) {
+ if (dec != NULL) {
+ VP8LClear(dec);
+ free(dec);
+ }
+}
+
+static void UpdateDecoder(VP8LDecoder* const dec, int width, int height) {
+ VP8LMetadata* const hdr = &dec->hdr_;
+ const int num_bits = hdr->huffman_subsample_bits_;
+ dec->width_ = width;
+ dec->height_ = height;
+
+ hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits);
+ hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1;
+}
+
+static int DecodeImageStream(int xsize, int ysize,
+ int is_level0,
+ VP8LDecoder* const dec,
+ uint32_t** const decoded_data) {
+ int ok = 1;
+ int transform_xsize = xsize;
+ int transform_ysize = ysize;
+ VP8LBitReader* const br = &dec->br_;
+ VP8LMetadata* const hdr = &dec->hdr_;
+ uint32_t* data = NULL;
+ int color_cache_bits = 0;
+
+ // Read the transforms (may recurse).
+ if (is_level0) {
+ while (ok && VP8LReadBits(br, 1)) {
+ ok = ReadTransform(&transform_xsize, &transform_ysize, dec);
+ }
+ }
+
+ // Color cache
+ if (ok && VP8LReadBits(br, 1)) {
+ color_cache_bits = VP8LReadBits(br, 4);
+ ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);
+ if (!ok) {
+ dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
+ goto End;
+ }
+ }
+
+ // Read the Huffman codes (may recurse).
+ ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
+ color_cache_bits, is_level0);
+ if (!ok) {
+ dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
+ goto End;
+ }
+
+ // Finish setting up the color-cache
+ if (color_cache_bits > 0) {
+ hdr->color_cache_size_ = 1 << color_cache_bits;
+ if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) {
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ ok = 0;
+ goto End;
+ }
+ } else {
+ hdr->color_cache_size_ = 0;
+ }
+ UpdateDecoder(dec, transform_xsize, transform_ysize);
+
+ if (is_level0) { // level 0 complete
+ dec->state_ = READ_HDR;
+ goto End;
+ }
+
+ {
+ const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;
+ data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));
+ if (data == NULL) {
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ ok = 0;
+ goto End;
+ }
+ }
+
+ // Use the Huffman trees to decode the LZ77 encoded data.
+ ok = DecodeImageData(dec, data, transform_xsize, transform_ysize, NULL);
+ ok = ok && !br->error_;
+
+ End:
+
+ if (!ok) {
+ free(data);
+ ClearMetadata(hdr);
+ // If not enough data (br.eos_) resulted in BIT_STREAM_ERROR, update the
+ // status appropriately.
+ if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && dec->br_.eos_) {
+ dec->status_ = VP8_STATUS_SUSPENDED;
+ }
+ } else {
+ if (decoded_data != NULL) {
+ *decoded_data = data;
+ } else {
+ // We allocate image data in this function only for transforms. At level 0
+ // (that is: not the transforms), we shouldn't have allocated anything.
+ assert(data == NULL);
+ assert(is_level0);
+ }
+ if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind.
+ }
+ return ok;
+}
+
+//------------------------------------------------------------------------------
+// Allocate dec->argb_ and dec->argb_cache_ using dec->width_ and dec->height_
+
+static int AllocateARGBBuffers(VP8LDecoder* const dec, int final_width) {
+ const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_;
+ // Scratch buffer corresponding to top-prediction row for transforming the
+ // first row in the row-blocks.
+ const uint64_t cache_top_pixels = final_width;
+ // Scratch buffer for temporary BGRA storage.
+ const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS;
+ const uint64_t total_num_pixels =
+ num_pixels + cache_top_pixels + cache_pixels;
+
+ assert(dec->width_ <= final_width);
+ dec->argb_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(*dec->argb_));
+ if (dec->argb_ == NULL) {
+ dec->argb_cache_ = NULL; // for sanity check
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ return 0;
+ }
+ dec->argb_cache_ = dec->argb_ + num_pixels + cache_top_pixels;
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Special row-processing that only stores the alpha data.
+
+static void ExtractAlphaRows(VP8LDecoder* const dec, int row) {
+ const int num_rows = row - dec->last_row_;
+ const uint32_t* const in = dec->argb_ + dec->width_ * dec->last_row_;
+
+ if (num_rows <= 0) return; // Nothing to be done.
+ ApplyInverseTransforms(dec, num_rows, in);
+
+ // Extract alpha (which is stored in the green plane).
+ {
+ const int width = dec->io_->width; // the final width (!= dec->width_)
+ const int cache_pixs = width * num_rows;
+ uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_;
+ const uint32_t* const src = dec->argb_cache_;
+ int i;
+ for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff;
+ }
+
+ dec->last_row_ = dec->last_out_row_ = row;
+}
+
+int VP8LDecodeAlphaImageStream(int width, int height, const uint8_t* const data,
+ size_t data_size, uint8_t* const output) {
+ VP8Io io;
+ int ok = 0;
+ VP8LDecoder* const dec = VP8LNew();
+ if (dec == NULL) return 0;
+
+ dec->width_ = width;
+ dec->height_ = height;
+ dec->io_ = &io;
+
+ VP8InitIo(&io);
+ WebPInitCustomIo(NULL, &io); // Just a sanity Init. io won't be used.
+ io.opaque = output;
+ io.width = width;
+ io.height = height;
+
+ dec->status_ = VP8_STATUS_OK;
+ VP8LInitBitReader(&dec->br_, data, data_size);
+
+ dec->action_ = READ_HDR;
+ if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Err;
+
+ // Allocate output (note that dec->width_ may have changed here).
+ if (!AllocateARGBBuffers(dec, width)) goto Err;
+
+ // Decode (with special row processing).
+ dec->action_ = READ_DATA;
+ ok = DecodeImageData(dec, dec->argb_, dec->width_, dec->height_,
+ ExtractAlphaRows);
+
+ Err:
+ VP8LDelete(dec);
+ return ok;
+}
+
+//------------------------------------------------------------------------------
+
+int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {
+ int width, height, has_alpha;
+
+ if (dec == NULL) return 0;
+ if (io == NULL) {
+ dec->status_ = VP8_STATUS_INVALID_PARAM;
+ return 0;
+ }
+
+ dec->io_ = io;
+ dec->status_ = VP8_STATUS_OK;
+ VP8LInitBitReader(&dec->br_, io->data, io->data_size);
+ if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) {
+ dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
+ goto Error;
+ }
+ dec->state_ = READ_DIM;
+ io->width = width;
+ io->height = height;
+
+ dec->action_ = READ_HDR;
+ if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error;
+ return 1;
+
+ Error:
+ VP8LClear(dec);
+ assert(dec->status_ != VP8_STATUS_OK);
+ return 0;
+}
+
+int VP8LDecodeImage(VP8LDecoder* const dec) {
+ VP8Io* io = NULL;
+ WebPDecParams* params = NULL;
+
+ // Sanity checks.
+ if (dec == NULL) return 0;
+
+ io = dec->io_;
+ assert(io != NULL);
+ params = (WebPDecParams*)io->opaque;
+ assert(params != NULL);
+ dec->output_ = params->output;
+ assert(dec->output_ != NULL);
+
+ // Initialization.
+ if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {
+ dec->status_ = VP8_STATUS_INVALID_PARAM;
+ goto Err;
+ }
+
+ if (!AllocateARGBBuffers(dec, io->width)) goto Err;
+
+ if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
+
+ // Decode.
+ dec->action_ = READ_DATA;
+ if (!DecodeImageData(dec, dec->argb_, dec->width_, dec->height_,
+ ProcessRows)) {
+ goto Err;
+ }
+
+ // Cleanup.
+ params->last_y = dec->last_out_row_;
+ VP8LClear(dec);
+ return 1;
+
+ Err:
+ VP8LClear(dec);
+ assert(dec->status_ != VP8_STATUS_OK);
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dec/vp8li.h b/drivers/webpold/dec/vp8li.h
new file mode 100644
index 0000000000..5f6cd6a01c
--- /dev/null
+++ b/drivers/webpold/dec/vp8li.h
@@ -0,0 +1,121 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Lossless decoder: internal header.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+// Vikas Arora(vikaas.arora@gmail.com)
+
+#ifndef WEBP_DEC_VP8LI_H_
+#define WEBP_DEC_VP8LI_H_
+
+#include <string.h> // for memcpy()
+#include "./webpi.h"
+#include "../utils/bit_reader.h"
+#include "../utils/color_cache.h"
+#include "../utils/huffman.h"
+#include "../format_constants.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+typedef enum {
+ READ_DATA = 0,
+ READ_HDR = 1,
+ READ_DIM = 2
+} VP8LDecodeState;
+
+typedef struct VP8LTransform VP8LTransform;
+struct VP8LTransform {
+ VP8LImageTransformType type_; // transform type.
+ int bits_; // subsampling bits defining transform window.
+ int xsize_; // transform window X index.
+ int ysize_; // transform window Y index.
+ uint32_t *data_; // transform data.
+};
+
+typedef struct {
+ HuffmanTree htrees_[HUFFMAN_CODES_PER_META_CODE];
+} HTreeGroup;
+
+typedef struct {
+ int color_cache_size_;
+ VP8LColorCache color_cache_;
+
+ int huffman_mask_;
+ int huffman_subsample_bits_;
+ int huffman_xsize_;
+ uint32_t *huffman_image_;
+ int num_htree_groups_;
+ HTreeGroup *htree_groups_;
+} VP8LMetadata;
+
+typedef struct {
+ VP8StatusCode status_;
+ VP8LDecodeState action_;
+ VP8LDecodeState state_;
+ VP8Io *io_;
+
+ const WebPDecBuffer *output_; // shortcut to io->opaque->output
+
+ uint32_t *argb_; // Internal data: always in BGRA color mode.
+ uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage.
+
+ VP8LBitReader br_;
+
+ int width_;
+ int height_;
+ int last_row_; // last input row decoded so far.
+ int last_out_row_; // last row output so far.
+
+ VP8LMetadata hdr_;
+
+ int next_transform_;
+ VP8LTransform transforms_[NUM_TRANSFORMS];
+ // or'd bitset storing the transforms types.
+ uint32_t transforms_seen_;
+
+ uint8_t *rescaler_memory; // Working memory for rescaling work.
+ WebPRescaler *rescaler; // Common rescaler for all channels.
+} VP8LDecoder;
+
+//------------------------------------------------------------------------------
+// internal functions. Not public.
+
+// in vp8l.c
+
+// Decodes a raw image stream (without header) and store the alpha data
+// into *output, which must be of size width x height. Returns false in case
+// of error.
+int VP8LDecodeAlphaImageStream(int width, int height, const uint8_t* const data,
+ size_t data_size, uint8_t* const output);
+
+// Allocates and initialize a new lossless decoder instance.
+VP8LDecoder* VP8LNew(void);
+
+// Decodes the image header. Returns false in case of error.
+int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io);
+
+// Decodes an image. It's required to decode the lossless header before calling
+// this function. Returns false in case of error, with updated dec->status_.
+int VP8LDecodeImage(VP8LDecoder* const dec);
+
+// Resets the decoder in its initial state, reclaiming memory.
+// Preserves the dec->status_ value.
+void VP8LClear(VP8LDecoder* const dec);
+
+// Clears and deallocate a lossless decoder instance.
+void VP8LDelete(VP8LDecoder* const dec);
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_DEC_VP8LI_H_ */
diff --git a/drivers/webpold/dec/webp.c b/drivers/webpold/dec/webp.c
new file mode 100644
index 0000000000..f44bc2b8ae
--- /dev/null
+++ b/drivers/webpold/dec/webp.c
@@ -0,0 +1,771 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Main decoding functions for WEBP images.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <stdlib.h>
+
+#include "./vp8i.h"
+#include "./vp8li.h"
+#include "./webpi.h"
+#include "../format_constants.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// RIFF layout is:
+// Offset tag
+// 0...3 "RIFF" 4-byte tag
+// 4...7 size of image data (including metadata) starting at offset 8
+// 8...11 "WEBP" our form-type signature
+// The RIFF container (12 bytes) is followed by appropriate chunks:
+// 12..15 "VP8 ": 4-bytes tags, signaling the use of VP8 video format
+// 16..19 size of the raw VP8 image data, starting at offset 20
+// 20.... the VP8 bytes
+// Or,
+// 12..15 "VP8L": 4-bytes tags, signaling the use of VP8L lossless format
+// 16..19 size of the raw VP8L image data, starting at offset 20
+// 20.... the VP8L bytes
+// Or,
+// 12..15 "VP8X": 4-bytes tags, describing the extended-VP8 chunk.
+// 16..19 size of the VP8X chunk starting at offset 20.
+// 20..23 VP8X flags bit-map corresponding to the chunk-types present.
+// 24..26 Width of the Canvas Image.
+// 27..29 Height of the Canvas Image.
+// There can be extra chunks after the "VP8X" chunk (ICCP, TILE, FRM, VP8,
+// META ...)
+// All sizes are in little-endian order.
+// Note: chunk data size must be padded to multiple of 2 when written.
+
+static WEBP_INLINE uint32_t get_le24(const uint8_t* const data) {
+ return data[0] | (data[1] << 8) | (data[2] << 16);
+}
+
+static WEBP_INLINE uint32_t get_le32(const uint8_t* const data) {
+ return (uint32_t)get_le24(data) | (data[3] << 24);
+}
+
+// Validates the RIFF container (if detected) and skips over it.
+// If a RIFF container is detected,
+// Returns VP8_STATUS_BITSTREAM_ERROR for invalid header, and
+// VP8_STATUS_OK otherwise.
+// In case there are not enough bytes (partial RIFF container), return 0 for
+// *riff_size. Else return the RIFF size extracted from the header.
+static VP8StatusCode ParseRIFF(const uint8_t** const data,
+ size_t* const data_size,
+ size_t* const riff_size) {
+ assert(data != NULL);
+ assert(data_size != NULL);
+ assert(riff_size != NULL);
+
+ *riff_size = 0; // Default: no RIFF present.
+ if (*data_size >= RIFF_HEADER_SIZE && !memcmp(*data, "RIFF", TAG_SIZE)) {
+ if (memcmp(*data + 8, "WEBP", TAG_SIZE)) {
+ return VP8_STATUS_BITSTREAM_ERROR; // Wrong image file signature.
+ } else {
+ const uint32_t size = get_le32(*data + TAG_SIZE);
+ // Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn").
+ if (size < TAG_SIZE + CHUNK_HEADER_SIZE) {
+ return VP8_STATUS_BITSTREAM_ERROR;
+ }
+ // We have a RIFF container. Skip it.
+ *riff_size = size;
+ *data += RIFF_HEADER_SIZE;
+ *data_size -= RIFF_HEADER_SIZE;
+ }
+ }
+ return VP8_STATUS_OK;
+}
+
+// Validates the VP8X header and skips over it.
+// Returns VP8_STATUS_BITSTREAM_ERROR for invalid VP8X header,
+// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and
+// VP8_STATUS_OK otherwise.
+// If a VP8X chunk is found, found_vp8x is set to true and *width_ptr,
+// *height_ptr and *flags_ptr are set to the corresponding values extracted
+// from the VP8X chunk.
+static VP8StatusCode ParseVP8X(const uint8_t** const data,
+ size_t* const data_size,
+ int* const found_vp8x,
+ int* const width_ptr, int* const height_ptr,
+ uint32_t* const flags_ptr) {
+ const uint32_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE;
+ assert(data != NULL);
+ assert(data_size != NULL);
+ assert(found_vp8x != NULL);
+
+ *found_vp8x = 0;
+
+ if (*data_size < CHUNK_HEADER_SIZE) {
+ return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data.
+ }
+
+ if (!memcmp(*data, "VP8X", TAG_SIZE)) {
+ int width, height;
+ uint32_t flags;
+ const uint32_t chunk_size = get_le32(*data + TAG_SIZE);
+ if (chunk_size != VP8X_CHUNK_SIZE) {
+ return VP8_STATUS_BITSTREAM_ERROR; // Wrong chunk size.
+ }
+
+ // Verify if enough data is available to validate the VP8X chunk.
+ if (*data_size < vp8x_size) {
+ return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data.
+ }
+ flags = get_le32(*data + 8);
+ width = 1 + get_le24(*data + 12);
+ height = 1 + get_le24(*data + 15);
+ if (width * (uint64_t)height >= MAX_IMAGE_AREA) {
+ return VP8_STATUS_BITSTREAM_ERROR; // image is too large
+ }
+
+ if (flags_ptr != NULL) *flags_ptr = flags;
+ if (width_ptr != NULL) *width_ptr = width;
+ if (height_ptr != NULL) *height_ptr = height;
+ // Skip over VP8X header bytes.
+ *data += vp8x_size;
+ *data_size -= vp8x_size;
+ *found_vp8x = 1;
+ }
+ return VP8_STATUS_OK;
+}
+
+// Skips to the next VP8/VP8L chunk header in the data given the size of the
+// RIFF chunk 'riff_size'.
+// Returns VP8_STATUS_BITSTREAM_ERROR if any invalid chunk size is encountered,
+// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and
+// VP8_STATUS_OK otherwise.
+// If an alpha chunk is found, *alpha_data and *alpha_size are set
+// appropriately.
+static VP8StatusCode ParseOptionalChunks(const uint8_t** const data,
+ size_t* const data_size,
+ size_t const riff_size,
+ const uint8_t** const alpha_data,
+ size_t* const alpha_size) {
+ const uint8_t* buf;
+ size_t buf_size;
+ uint32_t total_size = TAG_SIZE + // "WEBP".
+ CHUNK_HEADER_SIZE + // "VP8Xnnnn".
+ VP8X_CHUNK_SIZE; // data.
+ assert(data != NULL);
+ assert(data_size != NULL);
+ buf = *data;
+ buf_size = *data_size;
+
+ assert(alpha_data != NULL);
+ assert(alpha_size != NULL);
+ *alpha_data = NULL;
+ *alpha_size = 0;
+
+ while (1) {
+ uint32_t chunk_size;
+ uint32_t disk_chunk_size; // chunk_size with padding
+
+ *data = buf;
+ *data_size = buf_size;
+
+ if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data.
+ return VP8_STATUS_NOT_ENOUGH_DATA;
+ }
+
+ chunk_size = get_le32(buf + TAG_SIZE);
+ // For odd-sized chunk-payload, there's one byte padding at the end.
+ disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1;
+ total_size += disk_chunk_size;
+
+ // Check that total bytes skipped so far does not exceed riff_size.
+ if (riff_size > 0 && (total_size > riff_size)) {
+ return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size.
+ }
+
+ if (buf_size < disk_chunk_size) { // Insufficient data.
+ return VP8_STATUS_NOT_ENOUGH_DATA;
+ }
+
+ if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header.
+ *alpha_data = buf + CHUNK_HEADER_SIZE;
+ *alpha_size = chunk_size;
+ } else if (!memcmp(buf, "VP8 ", TAG_SIZE) ||
+ !memcmp(buf, "VP8L", TAG_SIZE)) { // A valid VP8/VP8L header.
+ return VP8_STATUS_OK; // Found.
+ }
+
+ // We have a full and valid chunk; skip it.
+ buf += disk_chunk_size;
+ buf_size -= disk_chunk_size;
+ }
+}
+
+// Validates the VP8/VP8L Header ("VP8 nnnn" or "VP8L nnnn") and skips over it.
+// Returns VP8_STATUS_BITSTREAM_ERROR for invalid (chunk larger than
+// riff_size) VP8/VP8L header,
+// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and
+// VP8_STATUS_OK otherwise.
+// If a VP8/VP8L chunk is found, *chunk_size is set to the total number of bytes
+// extracted from the VP8/VP8L chunk header.
+// The flag '*is_lossless' is set to 1 in case of VP8L chunk / raw VP8L data.
+static VP8StatusCode ParseVP8Header(const uint8_t** const data_ptr,
+ size_t* const data_size,
+ size_t riff_size,
+ size_t* const chunk_size,
+ int* const is_lossless) {
+ const uint8_t* const data = *data_ptr;
+ const int is_vp8 = !memcmp(data, "VP8 ", TAG_SIZE);
+ const int is_vp8l = !memcmp(data, "VP8L", TAG_SIZE);
+ const uint32_t minimal_size =
+ TAG_SIZE + CHUNK_HEADER_SIZE; // "WEBP" + "VP8 nnnn" OR
+ // "WEBP" + "VP8Lnnnn"
+ assert(data != NULL);
+ assert(data_size != NULL);
+ assert(chunk_size != NULL);
+ assert(is_lossless != NULL);
+
+ if (*data_size < CHUNK_HEADER_SIZE) {
+ return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data.
+ }
+
+ if (is_vp8 || is_vp8l) {
+ // Bitstream contains VP8/VP8L header.
+ const uint32_t size = get_le32(data + TAG_SIZE);
+ if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) {
+ return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information.
+ }
+ // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header.
+ *chunk_size = size;
+ *data_ptr += CHUNK_HEADER_SIZE;
+ *data_size -= CHUNK_HEADER_SIZE;
+ *is_lossless = is_vp8l;
+ } else {
+ // Raw VP8/VP8L bitstream (no header).
+ *is_lossless = VP8LCheckSignature(data, *data_size);
+ *chunk_size = *data_size;
+ }
+
+ return VP8_STATUS_OK;
+}
+
+//------------------------------------------------------------------------------
+
+// Fetch '*width', '*height', '*has_alpha' and fill out 'headers' based on
+// 'data'. All the output parameters may be NULL. If 'headers' is NULL only the
+// minimal amount will be read to fetch the remaining parameters.
+// If 'headers' is non-NULL this function will attempt to locate both alpha
+// data (with or without a VP8X chunk) and the bitstream chunk (VP8/VP8L).
+// Note: The following chunk sequences (before the raw VP8/VP8L data) are
+// considered valid by this function:
+// RIFF + VP8(L)
+// RIFF + VP8X + (optional chunks) + VP8(L)
+// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose.
+// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose.
+static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
+ size_t data_size,
+ int* const width,
+ int* const height,
+ int* const has_alpha,
+ WebPHeaderStructure* const headers) {
+ int found_riff = 0;
+ int found_vp8x = 0;
+ VP8StatusCode status;
+ WebPHeaderStructure hdrs;
+
+ if (data == NULL || data_size < RIFF_HEADER_SIZE) {
+ return VP8_STATUS_NOT_ENOUGH_DATA;
+ }
+ memset(&hdrs, 0, sizeof(hdrs));
+ hdrs.data = data;
+ hdrs.data_size = data_size;
+
+ // Skip over RIFF header.
+ status = ParseRIFF(&data, &data_size, &hdrs.riff_size);
+ if (status != VP8_STATUS_OK) {
+ return status; // Wrong RIFF header / insufficient data.
+ }
+ found_riff = (hdrs.riff_size > 0);
+
+ // Skip over VP8X.
+ {
+ uint32_t flags = 0;
+ status = ParseVP8X(&data, &data_size, &found_vp8x, width, height, &flags);
+ if (status != VP8_STATUS_OK) {
+ return status; // Wrong VP8X / insufficient data.
+ }
+ if (!found_riff && found_vp8x) {
+ // Note: This restriction may be removed in the future, if it becomes
+ // necessary to send VP8X chunk to the decoder.
+ return VP8_STATUS_BITSTREAM_ERROR;
+ }
+ if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG_BIT);
+ if (found_vp8x && headers == NULL) {
+ return VP8_STATUS_OK; // Return features from VP8X header.
+ }
+ }
+
+ if (data_size < TAG_SIZE) return VP8_STATUS_NOT_ENOUGH_DATA;
+
+ // Skip over optional chunks if data started with "RIFF + VP8X" or "ALPH".
+ if ((found_riff && found_vp8x) ||
+ (!found_riff && !found_vp8x && !memcmp(data, "ALPH", TAG_SIZE))) {
+ status = ParseOptionalChunks(&data, &data_size, hdrs.riff_size,
+ &hdrs.alpha_data, &hdrs.alpha_data_size);
+ if (status != VP8_STATUS_OK) {
+ return status; // Found an invalid chunk size / insufficient data.
+ }
+ }
+
+ // Skip over VP8/VP8L header.
+ status = ParseVP8Header(&data, &data_size, hdrs.riff_size,
+ &hdrs.compressed_size, &hdrs.is_lossless);
+ if (status != VP8_STATUS_OK) {
+ return status; // Wrong VP8/VP8L chunk-header / insufficient data.
+ }
+ if (hdrs.compressed_size > MAX_CHUNK_PAYLOAD) {
+ return VP8_STATUS_BITSTREAM_ERROR;
+ }
+
+ if (!hdrs.is_lossless) {
+ if (data_size < VP8_FRAME_HEADER_SIZE) {
+ return VP8_STATUS_NOT_ENOUGH_DATA;
+ }
+ // Validates raw VP8 data.
+ if (!VP8GetInfo(data, data_size,
+ (uint32_t)hdrs.compressed_size, width, height)) {
+ return VP8_STATUS_BITSTREAM_ERROR;
+ }
+ } else {
+ if (data_size < VP8L_FRAME_HEADER_SIZE) {
+ return VP8_STATUS_NOT_ENOUGH_DATA;
+ }
+ // Validates raw VP8L data.
+ if (!VP8LGetInfo(data, data_size, width, height, has_alpha)) {
+ return VP8_STATUS_BITSTREAM_ERROR;
+ }
+ }
+
+ if (has_alpha != NULL) {
+ // If the data did not contain a VP8X/VP8L chunk the only definitive way
+ // to set this is by looking for alpha data (from an ALPH chunk).
+ *has_alpha |= (hdrs.alpha_data != NULL);
+ }
+ if (headers != NULL) {
+ *headers = hdrs;
+ headers->offset = data - headers->data;
+ assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD);
+ assert(headers->offset == headers->data_size - data_size);
+ }
+ return VP8_STATUS_OK; // Return features from VP8 header.
+}
+
+VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) {
+ assert(headers != NULL);
+ // fill out headers, ignore width/height/has_alpha.
+ return ParseHeadersInternal(headers->data, headers->data_size,
+ NULL, NULL, NULL, headers);
+}
+
+//------------------------------------------------------------------------------
+// WebPDecParams
+
+void WebPResetDecParams(WebPDecParams* const params) {
+ if (params) {
+ memset(params, 0, sizeof(*params));
+ }
+}
+
+//------------------------------------------------------------------------------
+// "Into" decoding variants
+
+// Main flow
+static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size,
+ WebPDecParams* const params) {
+ VP8StatusCode status;
+ VP8Io io;
+ WebPHeaderStructure headers;
+
+ headers.data = data;
+ headers.data_size = data_size;
+ status = WebPParseHeaders(&headers); // Process Pre-VP8 chunks.
+ if (status != VP8_STATUS_OK) {
+ return status;
+ }
+
+ assert(params != NULL);
+ VP8InitIo(&io);
+ io.data = headers.data + headers.offset;
+ io.data_size = headers.data_size - headers.offset;
+ WebPInitCustomIo(params, &io); // Plug the I/O functions.
+
+ if (!headers.is_lossless) {
+ VP8Decoder* const dec = VP8New();
+ if (dec == NULL) {
+ return VP8_STATUS_OUT_OF_MEMORY;
+ }
+#ifdef WEBP_USE_THREAD
+ dec->use_threads_ = params->options && (params->options->use_threads > 0);
+#else
+ dec->use_threads_ = 0;
+#endif
+ dec->alpha_data_ = headers.alpha_data;
+ dec->alpha_data_size_ = headers.alpha_data_size;
+
+ // Decode bitstream header, update io->width/io->height.
+ if (!VP8GetHeaders(dec, &io)) {
+ status = dec->status_; // An error occurred. Grab error status.
+ } else {
+ // Allocate/check output buffers.
+ status = WebPAllocateDecBuffer(io.width, io.height, params->options,
+ params->output);
+ if (status == VP8_STATUS_OK) { // Decode
+ if (!VP8Decode(dec, &io)) {
+ status = dec->status_;
+ }
+ }
+ }
+ VP8Delete(dec);
+ } else {
+ VP8LDecoder* const dec = VP8LNew();
+ if (dec == NULL) {
+ return VP8_STATUS_OUT_OF_MEMORY;
+ }
+ if (!VP8LDecodeHeader(dec, &io)) {
+ status = dec->status_; // An error occurred. Grab error status.
+ } else {
+ // Allocate/check output buffers.
+ status = WebPAllocateDecBuffer(io.width, io.height, params->options,
+ params->output);
+ if (status == VP8_STATUS_OK) { // Decode
+ if (!VP8LDecodeImage(dec)) {
+ status = dec->status_;
+ }
+ }
+ }
+ VP8LDelete(dec);
+ }
+
+ if (status != VP8_STATUS_OK) {
+ WebPFreeDecBuffer(params->output);
+ }
+ return status;
+}
+
+// Helpers
+static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace,
+ const uint8_t* const data,
+ size_t data_size,
+ uint8_t* const rgba,
+ int stride, size_t size) {
+ WebPDecParams params;
+ WebPDecBuffer buf;
+ if (rgba == NULL) {
+ return NULL;
+ }
+ WebPInitDecBuffer(&buf);
+ WebPResetDecParams(&params);
+ params.output = &buf;
+ buf.colorspace = colorspace;
+ buf.u.RGBA.rgba = rgba;
+ buf.u.RGBA.stride = stride;
+ buf.u.RGBA.size = size;
+ buf.is_external_memory = 1;
+ if (DecodeInto(data, data_size, &params) != VP8_STATUS_OK) {
+ return NULL;
+ }
+ return rgba;
+}
+
+uint8_t* WebPDecodeRGBInto(const uint8_t* data, size_t data_size,
+ uint8_t* output, size_t size, int stride) {
+ return DecodeIntoRGBABuffer(MODE_RGB, data, data_size, output, stride, size);
+}
+
+uint8_t* WebPDecodeRGBAInto(const uint8_t* data, size_t data_size,
+ uint8_t* output, size_t size, int stride) {
+ return DecodeIntoRGBABuffer(MODE_RGBA, data, data_size, output, stride, size);
+}
+
+uint8_t* WebPDecodeARGBInto(const uint8_t* data, size_t data_size,
+ uint8_t* output, size_t size, int stride) {
+ return DecodeIntoRGBABuffer(MODE_ARGB, data, data_size, output, stride, size);
+}
+
+uint8_t* WebPDecodeBGRInto(const uint8_t* data, size_t data_size,
+ uint8_t* output, size_t size, int stride) {
+ return DecodeIntoRGBABuffer(MODE_BGR, data, data_size, output, stride, size);
+}
+
+uint8_t* WebPDecodeBGRAInto(const uint8_t* data, size_t data_size,
+ uint8_t* output, size_t size, int stride) {
+ return DecodeIntoRGBABuffer(MODE_BGRA, data, data_size, output, stride, size);
+}
+
+uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size,
+ uint8_t* luma, size_t luma_size, int luma_stride,
+ uint8_t* u, size_t u_size, int u_stride,
+ uint8_t* v, size_t v_size, int v_stride) {
+ WebPDecParams params;
+ WebPDecBuffer output;
+ if (luma == NULL) return NULL;
+ WebPInitDecBuffer(&output);
+ WebPResetDecParams(&params);
+ params.output = &output;
+ output.colorspace = MODE_YUV;
+ output.u.YUVA.y = luma;
+ output.u.YUVA.y_stride = luma_stride;
+ output.u.YUVA.y_size = luma_size;
+ output.u.YUVA.u = u;
+ output.u.YUVA.u_stride = u_stride;
+ output.u.YUVA.u_size = u_size;
+ output.u.YUVA.v = v;
+ output.u.YUVA.v_stride = v_stride;
+ output.u.YUVA.v_size = v_size;
+ output.is_external_memory = 1;
+ if (DecodeInto(data, data_size, &params) != VP8_STATUS_OK) {
+ return NULL;
+ }
+ return luma;
+}
+
+//------------------------------------------------------------------------------
+
+static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data,
+ size_t data_size, int* const width, int* const height,
+ WebPDecBuffer* const keep_info) {
+ WebPDecParams params;
+ WebPDecBuffer output;
+
+ WebPInitDecBuffer(&output);
+ WebPResetDecParams(&params);
+ params.output = &output;
+ output.colorspace = mode;
+
+ // Retrieve (and report back) the required dimensions from bitstream.
+ if (!WebPGetInfo(data, data_size, &output.width, &output.height)) {
+ return NULL;
+ }
+ if (width != NULL) *width = output.width;
+ if (height != NULL) *height = output.height;
+
+ // Decode
+ if (DecodeInto(data, data_size, &params) != VP8_STATUS_OK) {
+ return NULL;
+ }
+ if (keep_info != NULL) { // keep track of the side-info
+ WebPCopyDecBuffer(&output, keep_info);
+ }
+ // return decoded samples (don't clear 'output'!)
+ return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y;
+}
+
+uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size,
+ int* width, int* height) {
+ return Decode(MODE_RGB, data, data_size, width, height, NULL);
+}
+
+uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size,
+ int* width, int* height) {
+ return Decode(MODE_RGBA, data, data_size, width, height, NULL);
+}
+
+uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size,
+ int* width, int* height) {
+ return Decode(MODE_ARGB, data, data_size, width, height, NULL);
+}
+
+uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size,
+ int* width, int* height) {
+ return Decode(MODE_BGR, data, data_size, width, height, NULL);
+}
+
+uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size,
+ int* width, int* height) {
+ return Decode(MODE_BGRA, data, data_size, width, height, NULL);
+}
+
+uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size,
+ int* width, int* height, uint8_t** u, uint8_t** v,
+ int* stride, int* uv_stride) {
+ WebPDecBuffer output; // only to preserve the side-infos
+ uint8_t* const out = Decode(MODE_YUV, data, data_size,
+ width, height, &output);
+
+ if (out != NULL) {
+ const WebPYUVABuffer* const buf = &output.u.YUVA;
+ *u = buf->u;
+ *v = buf->v;
+ *stride = buf->y_stride;
+ *uv_stride = buf->u_stride;
+ assert(buf->u_stride == buf->v_stride);
+ }
+ return out;
+}
+
+static void DefaultFeatures(WebPBitstreamFeatures* const features) {
+ assert(features != NULL);
+ memset(features, 0, sizeof(*features));
+ features->bitstream_version = 0;
+}
+
+static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size,
+ WebPBitstreamFeatures* const features) {
+ if (features == NULL || data == NULL) {
+ return VP8_STATUS_INVALID_PARAM;
+ }
+ DefaultFeatures(features);
+
+ // Only parse enough of the data to retrieve width/height/has_alpha.
+ return ParseHeadersInternal(data, data_size,
+ &features->width, &features->height,
+ &features->has_alpha, NULL);
+}
+
+//------------------------------------------------------------------------------
+// WebPGetInfo()
+
+int WebPGetInfo(const uint8_t* data, size_t data_size,
+ int* width, int* height) {
+ WebPBitstreamFeatures features;
+
+ if (GetFeatures(data, data_size, &features) != VP8_STATUS_OK) {
+ return 0;
+ }
+
+ if (width != NULL) {
+ *width = features.width;
+ }
+ if (height != NULL) {
+ *height = features.height;
+ }
+
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Advance decoding API
+
+int WebPInitDecoderConfigInternal(WebPDecoderConfig* config,
+ int version) {
+ if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
+ return 0; // version mismatch
+ }
+ if (config == NULL) {
+ return 0;
+ }
+ memset(config, 0, sizeof(*config));
+ DefaultFeatures(&config->input);
+ WebPInitDecBuffer(&config->output);
+ return 1;
+}
+
+VP8StatusCode WebPGetFeaturesInternal(const uint8_t* data, size_t data_size,
+ WebPBitstreamFeatures* features,
+ int version) {
+ VP8StatusCode status;
+ if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
+ return VP8_STATUS_INVALID_PARAM; // version mismatch
+ }
+ if (features == NULL) {
+ return VP8_STATUS_INVALID_PARAM;
+ }
+
+ status = GetFeatures(data, data_size, features);
+ if (status == VP8_STATUS_NOT_ENOUGH_DATA) {
+ return VP8_STATUS_BITSTREAM_ERROR; // Not-enough-data treated as error.
+ }
+ return status;
+}
+
+VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size,
+ WebPDecoderConfig* config) {
+ WebPDecParams params;
+ VP8StatusCode status;
+
+ if (config == NULL) {
+ return VP8_STATUS_INVALID_PARAM;
+ }
+
+ status = GetFeatures(data, data_size, &config->input);
+ if (status != VP8_STATUS_OK) {
+ if (status == VP8_STATUS_NOT_ENOUGH_DATA) {
+ return VP8_STATUS_BITSTREAM_ERROR; // Not-enough-data treated as error.
+ }
+ return status;
+ }
+
+ WebPResetDecParams(&params);
+ params.output = &config->output;
+ params.options = &config->options;
+ status = DecodeInto(data, data_size, &params);
+
+ return status;
+}
+
+//------------------------------------------------------------------------------
+// Cropping and rescaling.
+
+int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
+ VP8Io* const io, WEBP_CSP_MODE src_colorspace) {
+ const int W = io->width;
+ const int H = io->height;
+ int x = 0, y = 0, w = W, h = H;
+
+ // Cropping
+ io->use_cropping = (options != NULL) && (options->use_cropping > 0);
+ if (io->use_cropping) {
+ w = options->crop_width;
+ h = options->crop_height;
+ x = options->crop_left;
+ y = options->crop_top;
+ if (!WebPIsRGBMode(src_colorspace)) { // only snap for YUV420 or YUV422
+ x &= ~1;
+ y &= ~1; // TODO(later): only for YUV420, not YUV422.
+ }
+ if (x < 0 || y < 0 || w <= 0 || h <= 0 || x + w > W || y + h > H) {
+ return 0; // out of frame boundary error
+ }
+ }
+ io->crop_left = x;
+ io->crop_top = y;
+ io->crop_right = x + w;
+ io->crop_bottom = y + h;
+ io->mb_w = w;
+ io->mb_h = h;
+
+ // Scaling
+ io->use_scaling = (options != NULL) && (options->use_scaling > 0);
+ if (io->use_scaling) {
+ if (options->scaled_width <= 0 || options->scaled_height <= 0) {
+ return 0;
+ }
+ io->scaled_width = options->scaled_width;
+ io->scaled_height = options->scaled_height;
+ }
+
+ // Filter
+ io->bypass_filtering = options && options->bypass_filtering;
+
+ // Fancy upsampler
+#ifdef FANCY_UPSAMPLING
+ io->fancy_upsampling = (options == NULL) || (!options->no_fancy_upsampling);
+#endif
+
+ if (io->use_scaling) {
+ // disable filter (only for large downscaling ratio).
+ io->bypass_filtering = (io->scaled_width < W * 3 / 4) &&
+ (io->scaled_height < H * 3 / 4);
+ io->fancy_upsampling = 0;
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dec/webpi.h b/drivers/webpold/dec/webpi.h
new file mode 100644
index 0000000000..44e5744411
--- /dev/null
+++ b/drivers/webpold/dec/webpi.h
@@ -0,0 +1,114 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Internal header: WebP decoding parameters and custom IO on buffer
+//
+// Author: somnath@google.com (Somnath Banerjee)
+
+#ifndef WEBP_DEC_WEBPI_H_
+#define WEBP_DEC_WEBPI_H_
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include "../utils/rescaler.h"
+#include "./decode_vp8.h"
+
+//------------------------------------------------------------------------------
+// WebPDecParams: Decoding output parameters. Transient internal object.
+
+typedef struct WebPDecParams WebPDecParams;
+typedef int (*OutputFunc)(const VP8Io* const io, WebPDecParams* const p);
+typedef int (*OutputRowFunc)(WebPDecParams* const p, int y_pos);
+
+struct WebPDecParams {
+ WebPDecBuffer* output; // output buffer.
+ uint8_t* tmp_y, *tmp_u, *tmp_v; // cache for the fancy upsampler
+ // or used for tmp rescaling
+
+ int last_y; // coordinate of the line that was last output
+ const WebPDecoderOptions* options; // if not NULL, use alt decoding features
+ // rescalers
+ WebPRescaler scaler_y, scaler_u, scaler_v, scaler_a;
+ void* memory; // overall scratch memory for the output work.
+
+ OutputFunc emit; // output RGB or YUV samples
+ OutputFunc emit_alpha; // output alpha channel
+ OutputRowFunc emit_alpha_row; // output one line of rescaled alpha values
+};
+
+// Should be called first, before any use of the WebPDecParams object.
+void WebPResetDecParams(WebPDecParams* const params);
+
+//------------------------------------------------------------------------------
+// Header parsing helpers
+
+// Structure storing a description of the RIFF headers.
+typedef struct {
+ const uint8_t* data; // input buffer
+ size_t data_size; // input buffer size
+ size_t offset; // offset to main data chunk (VP8 or VP8L)
+ const uint8_t* alpha_data; // points to alpha chunk (if present)
+ size_t alpha_data_size; // alpha chunk size
+ size_t compressed_size; // VP8/VP8L compressed data size
+ size_t riff_size; // size of the riff payload (or 0 if absent)
+ int is_lossless; // true if a VP8L chunk is present
+} WebPHeaderStructure;
+
+// Skips over all valid chunks prior to the first VP8/VP8L frame header.
+// Returns VP8_STATUS_OK on success,
+// VP8_STATUS_BITSTREAM_ERROR if an invalid header/chunk is found, and
+// VP8_STATUS_NOT_ENOUGH_DATA if case of insufficient data.
+// In 'headers', compressed_size, offset, alpha_data, alpha_size and lossless
+// fields are updated appropriately upon success.
+VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers);
+
+//------------------------------------------------------------------------------
+// Misc utils
+
+// Initializes VP8Io with custom setup, io and teardown functions. The default
+// hooks will use the supplied 'params' as io->opaque handle.
+void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io);
+
+// Setup crop_xxx fields, mb_w and mb_h in io. 'src_colorspace' refers
+// to the *compressed* format, not the output one.
+int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
+ VP8Io* const io, WEBP_CSP_MODE src_colorspace);
+
+//------------------------------------------------------------------------------
+// Internal functions regarding WebPDecBuffer memory (in buffer.c).
+// Don't really need to be externally visible for now.
+
+// Prepare 'buffer' with the requested initial dimensions width/height.
+// If no external storage is supplied, initializes buffer by allocating output
+// memory and setting up the stride information. Validate the parameters. Return
+// an error code in case of problem (no memory, or invalid stride / size /
+// dimension / etc.). If *options is not NULL, also verify that the options'
+// parameters are valid and apply them to the width/height dimensions of the
+// output buffer. This takes cropping / scaling / rotation into account.
+VP8StatusCode WebPAllocateDecBuffer(int width, int height,
+ const WebPDecoderOptions* const options,
+ WebPDecBuffer* const buffer);
+
+// Copy 'src' into 'dst' buffer, making sure 'dst' is not marked as owner of the
+// memory (still held by 'src').
+void WebPCopyDecBuffer(const WebPDecBuffer* const src,
+ WebPDecBuffer* const dst);
+
+// Copy and transfer ownership from src to dst (beware of parameter order!)
+void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst);
+
+
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_DEC_WEBPI_H_ */
diff --git a/drivers/webpold/decode.h b/drivers/webpold/decode.h
new file mode 100644
index 0000000000..43b6c58f4f
--- /dev/null
+++ b/drivers/webpold/decode.h
@@ -0,0 +1,454 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Main decoding functions for WebP images.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_WEBP_DECODE_H_
+#define WEBP_WEBP_DECODE_H_
+
+#include "./types.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define WEBP_DECODER_ABI_VERSION 0x0200 // MAJOR(8b) + MINOR(8b)
+
+// Return the decoder's version number, packed in hexadecimal using 8bits for
+// each of major/minor/revision. E.g: v2.5.7 is 0x020507.
+WEBP_EXTERN(int) WebPGetDecoderVersion(void);
+
+// Retrieve basic header information: width, height.
+// This function will also validate the header and return 0 in
+// case of formatting error.
+// Pointers 'width' and 'height' can be passed NULL if deemed irrelevant.
+WEBP_EXTERN(int) WebPGetInfo(const uint8_t* data, size_t data_size,
+ int* width, int* height);
+
+// Decodes WebP images pointed to by 'data' and returns RGBA samples, along
+// with the dimensions in *width and *height. The ordering of samples in
+// memory is R, G, B, A, R, G, B, A... in scan order (endian-independent).
+// The returned pointer should be deleted calling free().
+// Returns NULL in case of error.
+WEBP_EXTERN(uint8_t*) WebPDecodeRGBA(const uint8_t* data, size_t data_size,
+ int* width, int* height);
+
+// Same as WebPDecodeRGBA, but returning A, R, G, B, A, R, G, B... ordered data.
+WEBP_EXTERN(uint8_t*) WebPDecodeARGB(const uint8_t* data, size_t data_size,
+ int* width, int* height);
+
+// Same as WebPDecodeRGBA, but returning B, G, R, A, B, G, R, A... ordered data.
+WEBP_EXTERN(uint8_t*) WebPDecodeBGRA(const uint8_t* data, size_t data_size,
+ int* width, int* height);
+
+// Same as WebPDecodeRGBA, but returning R, G, B, R, G, B... ordered data.
+// If the bitstream contains transparency, it is ignored.
+WEBP_EXTERN(uint8_t*) WebPDecodeRGB(const uint8_t* data, size_t data_size,
+ int* width, int* height);
+
+// Same as WebPDecodeRGB, but returning B, G, R, B, G, R... ordered data.
+WEBP_EXTERN(uint8_t*) WebPDecodeBGR(const uint8_t* data, size_t data_size,
+ int* width, int* height);
+
+
+// Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer
+// returned is the Y samples buffer. Upon return, *u and *v will point to
+// the U and V chroma data. These U and V buffers need NOT be free()'d,
+// unlike the returned Y luma one. The dimension of the U and V planes
+// are both (*width + 1) / 2 and (*height + 1)/ 2.
+// Upon return, the Y buffer has a stride returned as '*stride', while U and V
+// have a common stride returned as '*uv_stride'.
+// Return NULL in case of error.
+// (*) Also named Y'CbCr. See: http://en.wikipedia.org/wiki/YCbCr
+WEBP_EXTERN(uint8_t*) WebPDecodeYUV(const uint8_t* data, size_t data_size,
+ int* width, int* height,
+ uint8_t** u, uint8_t** v,
+ int* stride, int* uv_stride);
+
+// These five functions are variants of the above ones, that decode the image
+// directly into a pre-allocated buffer 'output_buffer'. The maximum storage
+// available in this buffer is indicated by 'output_buffer_size'. If this
+// storage is not sufficient (or an error occurred), NULL is returned.
+// Otherwise, output_buffer is returned, for convenience.
+// The parameter 'output_stride' specifies the distance (in bytes)
+// between scanlines. Hence, output_buffer_size is expected to be at least
+// output_stride x picture-height.
+WEBP_EXTERN(uint8_t*) WebPDecodeRGBAInto(
+ const uint8_t* data, size_t data_size,
+ uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
+WEBP_EXTERN(uint8_t*) WebPDecodeARGBInto(
+ const uint8_t* data, size_t data_size,
+ uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
+WEBP_EXTERN(uint8_t*) WebPDecodeBGRAInto(
+ const uint8_t* data, size_t data_size,
+ uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
+
+// RGB and BGR variants. Here too the transparency information, if present,
+// will be dropped and ignored.
+WEBP_EXTERN(uint8_t*) WebPDecodeRGBInto(
+ const uint8_t* data, size_t data_size,
+ uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
+WEBP_EXTERN(uint8_t*) WebPDecodeBGRInto(
+ const uint8_t* data, size_t data_size,
+ uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
+
+// WebPDecodeYUVInto() is a variant of WebPDecodeYUV() that operates directly
+// into pre-allocated luma/chroma plane buffers. This function requires the
+// strides to be passed: one for the luma plane and one for each of the
+// chroma ones. The size of each plane buffer is passed as 'luma_size',
+// 'u_size' and 'v_size' respectively.
+// Pointer to the luma plane ('*luma') is returned or NULL if an error occurred
+// during decoding (or because some buffers were found to be too small).
+WEBP_EXTERN(uint8_t*) WebPDecodeYUVInto(
+ const uint8_t* data, size_t data_size,
+ uint8_t* luma, size_t luma_size, int luma_stride,
+ uint8_t* u, size_t u_size, int u_stride,
+ uint8_t* v, size_t v_size, int v_stride);
+
+//------------------------------------------------------------------------------
+// Output colorspaces and buffer
+
+// Colorspaces
+// Note: the naming describes the byte-ordering of packed samples in memory.
+// For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,...
+// Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels.
+// RGB-565 and RGBA-4444 are also endian-agnostic and byte-oriented.
+typedef enum { MODE_RGB = 0, MODE_RGBA = 1,
+ MODE_BGR = 2, MODE_BGRA = 3,
+ MODE_ARGB = 4, MODE_RGBA_4444 = 5,
+ MODE_RGB_565 = 6,
+ // RGB-premultiplied transparent modes (alpha value is preserved)
+ MODE_rgbA = 7,
+ MODE_bgrA = 8,
+ MODE_Argb = 9,
+ MODE_rgbA_4444 = 10,
+ // YUV modes must come after RGB ones.
+ MODE_YUV = 11, MODE_YUVA = 12, // yuv 4:2:0
+ MODE_LAST = 13
+ } WEBP_CSP_MODE;
+
+// Some useful macros:
+static WEBP_INLINE int WebPIsPremultipliedMode(WEBP_CSP_MODE mode) {
+ return (mode == MODE_rgbA || mode == MODE_bgrA || mode == MODE_Argb ||
+ mode == MODE_rgbA_4444);
+}
+
+static WEBP_INLINE int WebPIsAlphaMode(WEBP_CSP_MODE mode) {
+ return (mode == MODE_RGBA || mode == MODE_BGRA || mode == MODE_ARGB ||
+ mode == MODE_RGBA_4444 || mode == MODE_YUVA ||
+ WebPIsPremultipliedMode(mode));
+}
+
+static WEBP_INLINE int WebPIsRGBMode(WEBP_CSP_MODE mode) {
+ return (mode < MODE_YUV);
+}
+
+//------------------------------------------------------------------------------
+// WebPDecBuffer: Generic structure for describing the output sample buffer.
+
+typedef struct { // view as RGBA
+ uint8_t* rgba; // pointer to RGBA samples
+ int stride; // stride in bytes from one scanline to the next.
+ size_t size; // total size of the *rgba buffer.
+} WebPRGBABuffer;
+
+typedef struct { // view as YUVA
+ uint8_t* y, *u, *v, *a; // pointer to luma, chroma U/V, alpha samples
+ int y_stride; // luma stride
+ int u_stride, v_stride; // chroma strides
+ int a_stride; // alpha stride
+ size_t y_size; // luma plane size
+ size_t u_size, v_size; // chroma planes size
+ size_t a_size; // alpha-plane size
+} WebPYUVABuffer;
+
+// Output buffer
+typedef struct {
+ WEBP_CSP_MODE colorspace; // Colorspace.
+ int width, height; // Dimensions.
+ int is_external_memory; // If true, 'internal_memory' pointer is not used.
+ union {
+ WebPRGBABuffer RGBA;
+ WebPYUVABuffer YUVA;
+ } u; // Nameless union of buffer parameters.
+ uint32_t pad[4]; // padding for later use
+
+ uint8_t* private_memory; // Internally allocated memory (only when
+ // is_external_memory is false). Should not be used
+ // externally, but accessed via the buffer union.
+} WebPDecBuffer;
+
+// Internal, version-checked, entry point
+WEBP_EXTERN(int) WebPInitDecBufferInternal(WebPDecBuffer*, int);
+
+// Initialize the structure as empty. Must be called before any other use.
+// Returns false in case of version mismatch
+static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) {
+ return WebPInitDecBufferInternal(buffer, WEBP_DECODER_ABI_VERSION);
+}
+
+// Free any memory associated with the buffer. Must always be called last.
+// Note: doesn't free the 'buffer' structure itself.
+WEBP_EXTERN(void) WebPFreeDecBuffer(WebPDecBuffer* buffer);
+
+//------------------------------------------------------------------------------
+// Enumeration of the status codes
+
+typedef enum {
+ VP8_STATUS_OK = 0,
+ VP8_STATUS_OUT_OF_MEMORY,
+ VP8_STATUS_INVALID_PARAM,
+ VP8_STATUS_BITSTREAM_ERROR,
+ VP8_STATUS_UNSUPPORTED_FEATURE,
+ VP8_STATUS_SUSPENDED,
+ VP8_STATUS_USER_ABORT,
+ VP8_STATUS_NOT_ENOUGH_DATA
+} VP8StatusCode;
+
+//------------------------------------------------------------------------------
+// Incremental decoding
+//
+// This API allows streamlined decoding of partial data.
+// Picture can be incrementally decoded as data become available thanks to the
+// WebPIDecoder object. This object can be left in a SUSPENDED state if the
+// picture is only partially decoded, pending additional input.
+// Code example:
+//
+// WebPInitDecBuffer(&buffer);
+// buffer.colorspace = mode;
+// ...
+// WebPIDecoder* idec = WebPINewDecoder(&buffer);
+// while (has_more_data) {
+// // ... (get additional data)
+// status = WebPIAppend(idec, new_data, new_data_size);
+// if (status != VP8_STATUS_SUSPENDED ||
+// break;
+// }
+//
+// // The above call decodes the current available buffer.
+// // Part of the image can now be refreshed by calling to
+// // WebPIDecGetRGB()/WebPIDecGetYUVA() etc.
+// }
+// WebPIDelete(idec);
+
+typedef struct WebPIDecoder WebPIDecoder;
+
+// Creates a new incremental decoder with the supplied buffer parameter.
+// This output_buffer can be passed NULL, in which case a default output buffer
+// is used (with MODE_RGB). Otherwise, an internal reference to 'output_buffer'
+// is kept, which means that the lifespan of 'output_buffer' must be larger than
+// that of the returned WebPIDecoder object.
+// Returns NULL if the allocation failed.
+WEBP_EXTERN(WebPIDecoder*) WebPINewDecoder(WebPDecBuffer* output_buffer);
+
+// This function allocates and initializes an incremental-decoder object, which
+// will output the RGB/A samples specified by 'csp' into a preallocated
+// buffer 'output_buffer'. The size of this buffer is at least
+// 'output_buffer_size' and the stride (distance in bytes between two scanlines)
+// is specified by 'output_stride'. Returns NULL if the allocation failed.
+WEBP_EXTERN(WebPIDecoder*) WebPINewRGB(
+ WEBP_CSP_MODE csp,
+ uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
+
+// This function allocates and initializes an incremental-decoder object, which
+// will output the raw luma/chroma samples into a preallocated planes. The luma
+// plane is specified by its pointer 'luma', its size 'luma_size' and its stride
+// 'luma_stride'. Similarly, the chroma-u plane is specified by the 'u',
+// 'u_size' and 'u_stride' parameters, and the chroma-v plane by 'v'
+// and 'v_size'. And same for the alpha-plane. The 'a' pointer can be pass
+// NULL in case one is not interested in the transparency plane.
+// Returns NULL if the allocation failed.
+WEBP_EXTERN(WebPIDecoder*) WebPINewYUVA(
+ uint8_t* luma, size_t luma_size, int luma_stride,
+ uint8_t* u, size_t u_size, int u_stride,
+ uint8_t* v, size_t v_size, int v_stride,
+ uint8_t* a, size_t a_size, int a_stride);
+
+// Deprecated version of the above, without the alpha plane.
+// Kept for backward compatibility.
+WEBP_EXTERN(WebPIDecoder*) WebPINewYUV(
+ uint8_t* luma, size_t luma_size, int luma_stride,
+ uint8_t* u, size_t u_size, int u_stride,
+ uint8_t* v, size_t v_size, int v_stride);
+
+// Deletes the WebPIDecoder object and associated memory. Must always be called
+// if WebPINewDecoder, WebPINewRGB or WebPINewYUV succeeded.
+WEBP_EXTERN(void) WebPIDelete(WebPIDecoder* idec);
+
+// Copies and decodes the next available data. Returns VP8_STATUS_OK when
+// the image is successfully decoded. Returns VP8_STATUS_SUSPENDED when more
+// data is expected. Returns error in other cases.
+WEBP_EXTERN(VP8StatusCode) WebPIAppend(
+ WebPIDecoder* idec, const uint8_t* data, size_t data_size);
+
+// A variant of the above function to be used when data buffer contains
+// partial data from the beginning. In this case data buffer is not copied
+// to the internal memory.
+// Note that the value of the 'data' pointer can change between calls to
+// WebPIUpdate, for instance when the data buffer is resized to fit larger data.
+WEBP_EXTERN(VP8StatusCode) WebPIUpdate(
+ WebPIDecoder* idec, const uint8_t* data, size_t data_size);
+
+// Returns the RGB/A image decoded so far. Returns NULL if output params
+// are not initialized yet. The RGB/A output type corresponds to the colorspace
+// specified during call to WebPINewDecoder() or WebPINewRGB().
+// *last_y is the index of last decoded row in raster scan order. Some pointers
+// (*last_y, *width etc.) can be NULL if corresponding information is not
+// needed.
+WEBP_EXTERN(uint8_t*) WebPIDecGetRGB(
+ const WebPIDecoder* idec, int* last_y,
+ int* width, int* height, int* stride);
+
+// Same as above function to get a YUVA image. Returns pointer to the luma
+// plane or NULL in case of error. If there is no alpha information
+// the alpha pointer '*a' will be returned NULL.
+WEBP_EXTERN(uint8_t*) WebPIDecGetYUVA(
+ const WebPIDecoder* idec, int* last_y,
+ uint8_t** u, uint8_t** v, uint8_t** a,
+ int* width, int* height, int* stride, int* uv_stride, int* a_stride);
+
+// Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the
+// alpha information (if present). Kept for backward compatibility.
+static WEBP_INLINE uint8_t* WebPIDecGetYUV(
+ const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v,
+ int* width, int* height, int* stride, int* uv_stride) {
+ return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height,
+ stride, uv_stride, NULL);
+}
+
+// Generic call to retrieve information about the displayable area.
+// If non NULL, the left/right/width/height pointers are filled with the visible
+// rectangular area so far.
+// Returns NULL in case the incremental decoder object is in an invalid state.
+// Otherwise returns the pointer to the internal representation. This structure
+// is read-only, tied to WebPIDecoder's lifespan and should not be modified.
+WEBP_EXTERN(const WebPDecBuffer*) WebPIDecodedArea(
+ const WebPIDecoder* idec, int* left, int* top, int* width, int* height);
+
+//------------------------------------------------------------------------------
+// Advanced decoding parametrization
+//
+// Code sample for using the advanced decoding API
+/*
+ // A) Init a configuration object
+ WebPDecoderConfig config;
+ CHECK(WebPInitDecoderConfig(&config));
+
+ // B) optional: retrieve the bitstream's features.
+ CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);
+
+ // C) Adjust 'config', if needed
+ config.no_fancy = 1;
+ config.output.colorspace = MODE_BGRA;
+ // etc.
+
+ // Note that you can also make config.output point to an externally
+ // supplied memory buffer, provided it's big enough to store the decoded
+ // picture. Otherwise, config.output will just be used to allocate memory
+ // and store the decoded picture.
+
+ // D) Decode!
+ CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK);
+
+ // E) Decoded image is now in config.output (and config.output.u.RGBA)
+
+ // F) Reclaim memory allocated in config's object. It's safe to call
+ // this function even if the memory is external and wasn't allocated
+ // by WebPDecode().
+ WebPFreeDecBuffer(&config.output);
+*/
+
+// Features gathered from the bitstream
+typedef struct {
+ int width; // Width in pixels, as read from the bitstream.
+ int height; // Height in pixels, as read from the bitstream.
+ int has_alpha; // True if the bitstream contains an alpha channel.
+
+ // Unused for now:
+ int bitstream_version; // should be 0 for now. TODO(later)
+ int no_incremental_decoding; // if true, using incremental decoding is not
+ // recommended.
+ int rotate; // TODO(later)
+ int uv_sampling; // should be 0 for now. TODO(later)
+ uint32_t pad[3]; // padding for later use
+} WebPBitstreamFeatures;
+
+// Internal, version-checked, entry point
+WEBP_EXTERN(VP8StatusCode) WebPGetFeaturesInternal(
+ const uint8_t*, size_t, WebPBitstreamFeatures*, int);
+
+// Retrieve features from the bitstream. The *features structure is filled
+// with information gathered from the bitstream.
+// Returns false in case of error or version mismatch.
+// In case of error, features->bitstream_status will reflect the error code.
+static WEBP_INLINE VP8StatusCode WebPGetFeatures(
+ const uint8_t* data, size_t data_size,
+ WebPBitstreamFeatures* features) {
+ return WebPGetFeaturesInternal(data, data_size, features,
+ WEBP_DECODER_ABI_VERSION);
+}
+
+// Decoding options
+typedef struct {
+ int bypass_filtering; // if true, skip the in-loop filtering
+ int no_fancy_upsampling; // if true, use faster pointwise upsampler
+ int use_cropping; // if true, cropping is applied _first_
+ int crop_left, crop_top; // top-left position for cropping.
+ // Will be snapped to even values.
+ int crop_width, crop_height; // dimension of the cropping area
+ int use_scaling; // if true, scaling is applied _afterward_
+ int scaled_width, scaled_height; // final resolution
+ int use_threads; // if true, use multi-threaded decoding
+
+ // Unused for now:
+ int force_rotation; // forced rotation (to be applied _last_)
+ int no_enhancement; // if true, discard enhancement layer
+ uint32_t pad[6]; // padding for later use
+} WebPDecoderOptions;
+
+// Main object storing the configuration for advanced decoding.
+typedef struct {
+ WebPBitstreamFeatures input; // Immutable bitstream features (optional)
+ WebPDecBuffer output; // Output buffer (can point to external mem)
+ WebPDecoderOptions options; // Decoding options
+} WebPDecoderConfig;
+
+// Internal, version-checked, entry point
+WEBP_EXTERN(int) WebPInitDecoderConfigInternal(WebPDecoderConfig*, int);
+
+// Initialize the configuration as empty. This function must always be
+// called first, unless WebPGetFeatures() is to be called.
+// Returns false in case of mismatched version.
+static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) {
+ return WebPInitDecoderConfigInternal(config, WEBP_DECODER_ABI_VERSION);
+}
+
+// Instantiate a new incremental decoder object with the requested
+// configuration. The bitstream can be passed using 'data' and 'data_size'
+// parameter, in which case the features will be parsed and stored into
+// config->input. Otherwise, 'data' can be NULL and no parsing will occur.
+// Note that 'config' can be NULL too, in which case a default configuration
+// is used.
+// The return WebPIDecoder object must always be deleted calling WebPIDelete().
+// Returns NULL in case of error (and config->status will then reflect
+// the error condition).
+WEBP_EXTERN(WebPIDecoder*) WebPIDecode(const uint8_t* data, size_t data_size,
+ WebPDecoderConfig* config);
+
+// Non-incremental version. This version decodes the full data at once, taking
+// 'config' into account. Returns decoding status (which should be VP8_STATUS_OK
+// if the decoding was successful).
+WEBP_EXTERN(VP8StatusCode) WebPDecode(const uint8_t* data, size_t data_size,
+ WebPDecoderConfig* config);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_WEBP_DECODE_H_ */
diff --git a/drivers/webpold/dsp/cpu.c b/drivers/webpold/dsp/cpu.c
new file mode 100644
index 0000000000..0228734457
--- /dev/null
+++ b/drivers/webpold/dsp/cpu.c
@@ -0,0 +1,85 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// CPU detection
+//
+// Author: Christian Duvivier (cduvivier@google.com)
+
+#include "./dsp.h"
+
+#if defined(__ANDROID__)
+#include <cpu-features.h>
+#endif
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// SSE2 detection.
+//
+
+// apple/darwin gcc-4.0.1 defines __PIC__, but not __pic__ with -fPIC.
+#if (defined(__pic__) || defined(__PIC__)) && defined(__i386__)
+static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
+ __asm__ volatile (
+ "mov %%ebx, %%edi\n"
+ "cpuid\n"
+ "xchg %%edi, %%ebx\n"
+ : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
+ : "a"(info_type));
+}
+#elif defined(__i386__) || defined(__x86_64__)
+static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
+ __asm__ volatile (
+ "cpuid\n"
+ : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
+ : "a"(info_type));
+}
+#elif defined(WEBP_MSC_SSE2)
+#define GetCPUInfo __cpuid
+#endif
+
+#if defined(__i386__) || defined(__x86_64__) || defined(WEBP_MSC_SSE2)
+static int x86CPUInfo(CPUFeature feature) {
+ int cpu_info[4];
+ GetCPUInfo(cpu_info, 1);
+ if (feature == kSSE2) {
+ return 0 != (cpu_info[3] & 0x04000000);
+ }
+ if (feature == kSSE3) {
+ return 0 != (cpu_info[2] & 0x00000001);
+ }
+ return 0;
+}
+VP8CPUInfo VP8GetCPUInfo = x86CPUInfo;
+#elif defined(WEBP_ANDROID_NEON)
+static int AndroidCPUInfo(CPUFeature feature) {
+ const AndroidCpuFamily cpu_family = android_getCpuFamily();
+ const uint64_t cpu_features = android_getCpuFeatures();
+ if (feature == kNEON) {
+ return (cpu_family == ANDROID_CPU_FAMILY_ARM &&
+ 0 != (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON));
+ }
+ return 0;
+}
+VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo;
+#elif defined(__ARM_NEON__)
+// define a dummy function to enable turning off NEON at runtime by setting
+// VP8DecGetCPUInfo = NULL
+static int armCPUInfo(CPUFeature feature) {
+ (void)feature;
+ return 1;
+}
+VP8CPUInfo VP8GetCPUInfo = armCPUInfo;
+#else
+VP8CPUInfo VP8GetCPUInfo = NULL;
+#endif
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dsp/dec.c b/drivers/webpold/dsp/dec.c
new file mode 100644
index 0000000000..9ae7b6fa76
--- /dev/null
+++ b/drivers/webpold/dsp/dec.c
@@ -0,0 +1,732 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Speed-critical decoding functions.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+#include "../dec/vp8i.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// run-time tables (~4k)
+
+static uint8_t abs0[255 + 255 + 1]; // abs(i)
+static uint8_t abs1[255 + 255 + 1]; // abs(i)>>1
+static int8_t sclip1[1020 + 1020 + 1]; // clips [-1020, 1020] to [-128, 127]
+static int8_t sclip2[112 + 112 + 1]; // clips [-112, 112] to [-16, 15]
+static uint8_t clip1[255 + 510 + 1]; // clips [-255,510] to [0,255]
+
+// We declare this variable 'volatile' to prevent instruction reordering
+// and make sure it's set to true _last_ (so as to be thread-safe)
+static volatile int tables_ok = 0;
+
+static void DspInitTables(void) {
+ if (!tables_ok) {
+ int i;
+ for (i = -255; i <= 255; ++i) {
+ abs0[255 + i] = (i < 0) ? -i : i;
+ abs1[255 + i] = abs0[255 + i] >> 1;
+ }
+ for (i = -1020; i <= 1020; ++i) {
+ sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i;
+ }
+ for (i = -112; i <= 112; ++i) {
+ sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i;
+ }
+ for (i = -255; i <= 255 + 255; ++i) {
+ clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i;
+ }
+ tables_ok = 1;
+ }
+}
+
+static WEBP_INLINE uint8_t clip_8b(int v) {
+ return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255;
+}
+
+//------------------------------------------------------------------------------
+// Transforms (Paragraph 14.4)
+
+#define STORE(x, y, v) \
+ dst[x + y * BPS] = clip_8b(dst[x + y * BPS] + ((v) >> 3))
+
+static const int kC1 = 20091 + (1 << 16);
+static const int kC2 = 35468;
+#define MUL(a, b) (((a) * (b)) >> 16)
+
+static void TransformOne(const int16_t* in, uint8_t* dst) {
+ int C[4 * 4], *tmp;
+ int i;
+ tmp = C;
+ for (i = 0; i < 4; ++i) { // vertical pass
+ const int a = in[0] + in[8]; // [-4096, 4094]
+ const int b = in[0] - in[8]; // [-4095, 4095]
+ const int c = MUL(in[4], kC2) - MUL(in[12], kC1); // [-3783, 3783]
+ const int d = MUL(in[4], kC1) + MUL(in[12], kC2); // [-3785, 3781]
+ tmp[0] = a + d; // [-7881, 7875]
+ tmp[1] = b + c; // [-7878, 7878]
+ tmp[2] = b - c; // [-7878, 7878]
+ tmp[3] = a - d; // [-7877, 7879]
+ tmp += 4;
+ in++;
+ }
+ // Each pass is expanding the dynamic range by ~3.85 (upper bound).
+ // The exact value is (2. + (kC1 + kC2) / 65536).
+ // After the second pass, maximum interval is [-3794, 3794], assuming
+ // an input in [-2048, 2047] interval. We then need to add a dst value
+ // in the [0, 255] range.
+ // In the worst case scenario, the input to clip_8b() can be as large as
+ // [-60713, 60968].
+ tmp = C;
+ for (i = 0; i < 4; ++i) { // horizontal pass
+ const int dc = tmp[0] + 4;
+ const int a = dc + tmp[8];
+ const int b = dc - tmp[8];
+ const int c = MUL(tmp[4], kC2) - MUL(tmp[12], kC1);
+ const int d = MUL(tmp[4], kC1) + MUL(tmp[12], kC2);
+ STORE(0, 0, a + d);
+ STORE(1, 0, b + c);
+ STORE(2, 0, b - c);
+ STORE(3, 0, a - d);
+ tmp++;
+ dst += BPS;
+ }
+}
+#undef MUL
+
+static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
+ TransformOne(in, dst);
+ if (do_two) {
+ TransformOne(in + 16, dst + 4);
+ }
+}
+
+static void TransformUV(const int16_t* in, uint8_t* dst) {
+ VP8Transform(in + 0 * 16, dst, 1);
+ VP8Transform(in + 2 * 16, dst + 4 * BPS, 1);
+}
+
+static void TransformDC(const int16_t *in, uint8_t* dst) {
+ const int DC = in[0] + 4;
+ int i, j;
+ for (j = 0; j < 4; ++j) {
+ for (i = 0; i < 4; ++i) {
+ STORE(i, j, DC);
+ }
+ }
+}
+
+static void TransformDCUV(const int16_t* in, uint8_t* dst) {
+ if (in[0 * 16]) TransformDC(in + 0 * 16, dst);
+ if (in[1 * 16]) TransformDC(in + 1 * 16, dst + 4);
+ if (in[2 * 16]) TransformDC(in + 2 * 16, dst + 4 * BPS);
+ if (in[3 * 16]) TransformDC(in + 3 * 16, dst + 4 * BPS + 4);
+}
+
+#undef STORE
+
+//------------------------------------------------------------------------------
+// Paragraph 14.3
+
+static void TransformWHT(const int16_t* in, int16_t* out) {
+ int tmp[16];
+ int i;
+ for (i = 0; i < 4; ++i) {
+ const int a0 = in[0 + i] + in[12 + i];
+ const int a1 = in[4 + i] + in[ 8 + i];
+ const int a2 = in[4 + i] - in[ 8 + i];
+ const int a3 = in[0 + i] - in[12 + i];
+ tmp[0 + i] = a0 + a1;
+ tmp[8 + i] = a0 - a1;
+ tmp[4 + i] = a3 + a2;
+ tmp[12 + i] = a3 - a2;
+ }
+ for (i = 0; i < 4; ++i) {
+ const int dc = tmp[0 + i * 4] + 3; // w/ rounder
+ const int a0 = dc + tmp[3 + i * 4];
+ const int a1 = tmp[1 + i * 4] + tmp[2 + i * 4];
+ const int a2 = tmp[1 + i * 4] - tmp[2 + i * 4];
+ const int a3 = dc - tmp[3 + i * 4];
+ out[ 0] = (a0 + a1) >> 3;
+ out[16] = (a3 + a2) >> 3;
+ out[32] = (a0 - a1) >> 3;
+ out[48] = (a3 - a2) >> 3;
+ out += 64;
+ }
+}
+
+void (*VP8TransformWHT)(const int16_t* in, int16_t* out) = TransformWHT;
+
+//------------------------------------------------------------------------------
+// Intra predictions
+
+#define DST(x, y) dst[(x) + (y) * BPS]
+
+static WEBP_INLINE void TrueMotion(uint8_t *dst, int size) {
+ const uint8_t* top = dst - BPS;
+ const uint8_t* const clip0 = clip1 + 255 - top[-1];
+ int y;
+ for (y = 0; y < size; ++y) {
+ const uint8_t* const clip = clip0 + dst[-1];
+ int x;
+ for (x = 0; x < size; ++x) {
+ dst[x] = clip[top[x]];
+ }
+ dst += BPS;
+ }
+}
+static void TM4(uint8_t *dst) { TrueMotion(dst, 4); }
+static void TM8uv(uint8_t *dst) { TrueMotion(dst, 8); }
+static void TM16(uint8_t *dst) { TrueMotion(dst, 16); }
+
+//------------------------------------------------------------------------------
+// 16x16
+
+static void VE16(uint8_t *dst) { // vertical
+ int j;
+ for (j = 0; j < 16; ++j) {
+ memcpy(dst + j * BPS, dst - BPS, 16);
+ }
+}
+
+static void HE16(uint8_t *dst) { // horizontal
+ int j;
+ for (j = 16; j > 0; --j) {
+ memset(dst, dst[-1], 16);
+ dst += BPS;
+ }
+}
+
+static WEBP_INLINE void Put16(int v, uint8_t* dst) {
+ int j;
+ for (j = 0; j < 16; ++j) {
+ memset(dst + j * BPS, v, 16);
+ }
+}
+
+static void DC16(uint8_t *dst) { // DC
+ int DC = 16;
+ int j;
+ for (j = 0; j < 16; ++j) {
+ DC += dst[-1 + j * BPS] + dst[j - BPS];
+ }
+ Put16(DC >> 5, dst);
+}
+
+static void DC16NoTop(uint8_t *dst) { // DC with top samples not available
+ int DC = 8;
+ int j;
+ for (j = 0; j < 16; ++j) {
+ DC += dst[-1 + j * BPS];
+ }
+ Put16(DC >> 4, dst);
+}
+
+static void DC16NoLeft(uint8_t *dst) { // DC with left samples not available
+ int DC = 8;
+ int i;
+ for (i = 0; i < 16; ++i) {
+ DC += dst[i - BPS];
+ }
+ Put16(DC >> 4, dst);
+}
+
+static void DC16NoTopLeft(uint8_t *dst) { // DC with no top and left samples
+ Put16(0x80, dst);
+}
+
+//------------------------------------------------------------------------------
+// 4x4
+
+#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2)
+#define AVG2(a, b) (((a) + (b) + 1) >> 1)
+
+static void VE4(uint8_t *dst) { // vertical
+ const uint8_t* top = dst - BPS;
+ const uint8_t vals[4] = {
+ AVG3(top[-1], top[0], top[1]),
+ AVG3(top[ 0], top[1], top[2]),
+ AVG3(top[ 1], top[2], top[3]),
+ AVG3(top[ 2], top[3], top[4])
+ };
+ int i;
+ for (i = 0; i < 4; ++i) {
+ memcpy(dst + i * BPS, vals, sizeof(vals));
+ }
+}
+
+static void HE4(uint8_t *dst) { // horizontal
+ const int A = dst[-1 - BPS];
+ const int B = dst[-1];
+ const int C = dst[-1 + BPS];
+ const int D = dst[-1 + 2 * BPS];
+ const int E = dst[-1 + 3 * BPS];
+ *(uint32_t*)(dst + 0 * BPS) = 0x01010101U * AVG3(A, B, C);
+ *(uint32_t*)(dst + 1 * BPS) = 0x01010101U * AVG3(B, C, D);
+ *(uint32_t*)(dst + 2 * BPS) = 0x01010101U * AVG3(C, D, E);
+ *(uint32_t*)(dst + 3 * BPS) = 0x01010101U * AVG3(D, E, E);
+}
+
+static void DC4(uint8_t *dst) { // DC
+ uint32_t dc = 4;
+ int i;
+ for (i = 0; i < 4; ++i) dc += dst[i - BPS] + dst[-1 + i * BPS];
+ dc >>= 3;
+ for (i = 0; i < 4; ++i) memset(dst + i * BPS, dc, 4);
+}
+
+static void RD4(uint8_t *dst) { // Down-right
+ const int I = dst[-1 + 0 * BPS];
+ const int J = dst[-1 + 1 * BPS];
+ const int K = dst[-1 + 2 * BPS];
+ const int L = dst[-1 + 3 * BPS];
+ const int X = dst[-1 - BPS];
+ const int A = dst[0 - BPS];
+ const int B = dst[1 - BPS];
+ const int C = dst[2 - BPS];
+ const int D = dst[3 - BPS];
+ DST(0, 3) = AVG3(J, K, L);
+ DST(0, 2) = DST(1, 3) = AVG3(I, J, K);
+ DST(0, 1) = DST(1, 2) = DST(2, 3) = AVG3(X, I, J);
+ DST(0, 0) = DST(1, 1) = DST(2, 2) = DST(3, 3) = AVG3(A, X, I);
+ DST(1, 0) = DST(2, 1) = DST(3, 2) = AVG3(B, A, X);
+ DST(2, 0) = DST(3, 1) = AVG3(C, B, A);
+ DST(3, 0) = AVG3(D, C, B);
+}
+
+static void LD4(uint8_t *dst) { // Down-Left
+ const int A = dst[0 - BPS];
+ const int B = dst[1 - BPS];
+ const int C = dst[2 - BPS];
+ const int D = dst[3 - BPS];
+ const int E = dst[4 - BPS];
+ const int F = dst[5 - BPS];
+ const int G = dst[6 - BPS];
+ const int H = dst[7 - BPS];
+ DST(0, 0) = AVG3(A, B, C);
+ DST(1, 0) = DST(0, 1) = AVG3(B, C, D);
+ DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E);
+ DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F);
+ DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G);
+ DST(3, 2) = DST(2, 3) = AVG3(F, G, H);
+ DST(3, 3) = AVG3(G, H, H);
+}
+
+static void VR4(uint8_t *dst) { // Vertical-Right
+ const int I = dst[-1 + 0 * BPS];
+ const int J = dst[-1 + 1 * BPS];
+ const int K = dst[-1 + 2 * BPS];
+ const int X = dst[-1 - BPS];
+ const int A = dst[0 - BPS];
+ const int B = dst[1 - BPS];
+ const int C = dst[2 - BPS];
+ const int D = dst[3 - BPS];
+ DST(0, 0) = DST(1, 2) = AVG2(X, A);
+ DST(1, 0) = DST(2, 2) = AVG2(A, B);
+ DST(2, 0) = DST(3, 2) = AVG2(B, C);
+ DST(3, 0) = AVG2(C, D);
+
+ DST(0, 3) = AVG3(K, J, I);
+ DST(0, 2) = AVG3(J, I, X);
+ DST(0, 1) = DST(1, 3) = AVG3(I, X, A);
+ DST(1, 1) = DST(2, 3) = AVG3(X, A, B);
+ DST(2, 1) = DST(3, 3) = AVG3(A, B, C);
+ DST(3, 1) = AVG3(B, C, D);
+}
+
+static void VL4(uint8_t *dst) { // Vertical-Left
+ const int A = dst[0 - BPS];
+ const int B = dst[1 - BPS];
+ const int C = dst[2 - BPS];
+ const int D = dst[3 - BPS];
+ const int E = dst[4 - BPS];
+ const int F = dst[5 - BPS];
+ const int G = dst[6 - BPS];
+ const int H = dst[7 - BPS];
+ DST(0, 0) = AVG2(A, B);
+ DST(1, 0) = DST(0, 2) = AVG2(B, C);
+ DST(2, 0) = DST(1, 2) = AVG2(C, D);
+ DST(3, 0) = DST(2, 2) = AVG2(D, E);
+
+ DST(0, 1) = AVG3(A, B, C);
+ DST(1, 1) = DST(0, 3) = AVG3(B, C, D);
+ DST(2, 1) = DST(1, 3) = AVG3(C, D, E);
+ DST(3, 1) = DST(2, 3) = AVG3(D, E, F);
+ DST(3, 2) = AVG3(E, F, G);
+ DST(3, 3) = AVG3(F, G, H);
+}
+
+static void HU4(uint8_t *dst) { // Horizontal-Up
+ const int I = dst[-1 + 0 * BPS];
+ const int J = dst[-1 + 1 * BPS];
+ const int K = dst[-1 + 2 * BPS];
+ const int L = dst[-1 + 3 * BPS];
+ DST(0, 0) = AVG2(I, J);
+ DST(2, 0) = DST(0, 1) = AVG2(J, K);
+ DST(2, 1) = DST(0, 2) = AVG2(K, L);
+ DST(1, 0) = AVG3(I, J, K);
+ DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
+ DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
+ DST(3, 2) = DST(2, 2) =
+ DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
+}
+
+static void HD4(uint8_t *dst) { // Horizontal-Down
+ const int I = dst[-1 + 0 * BPS];
+ const int J = dst[-1 + 1 * BPS];
+ const int K = dst[-1 + 2 * BPS];
+ const int L = dst[-1 + 3 * BPS];
+ const int X = dst[-1 - BPS];
+ const int A = dst[0 - BPS];
+ const int B = dst[1 - BPS];
+ const int C = dst[2 - BPS];
+
+ DST(0, 0) = DST(2, 1) = AVG2(I, X);
+ DST(0, 1) = DST(2, 2) = AVG2(J, I);
+ DST(0, 2) = DST(2, 3) = AVG2(K, J);
+ DST(0, 3) = AVG2(L, K);
+
+ DST(3, 0) = AVG3(A, B, C);
+ DST(2, 0) = AVG3(X, A, B);
+ DST(1, 0) = DST(3, 1) = AVG3(I, X, A);
+ DST(1, 1) = DST(3, 2) = AVG3(J, I, X);
+ DST(1, 2) = DST(3, 3) = AVG3(K, J, I);
+ DST(1, 3) = AVG3(L, K, J);
+}
+
+#undef DST
+#undef AVG3
+#undef AVG2
+
+//------------------------------------------------------------------------------
+// Chroma
+
+static void VE8uv(uint8_t *dst) { // vertical
+ int j;
+ for (j = 0; j < 8; ++j) {
+ memcpy(dst + j * BPS, dst - BPS, 8);
+ }
+}
+
+static void HE8uv(uint8_t *dst) { // horizontal
+ int j;
+ for (j = 0; j < 8; ++j) {
+ memset(dst, dst[-1], 8);
+ dst += BPS;
+ }
+}
+
+// helper for chroma-DC predictions
+static WEBP_INLINE void Put8x8uv(uint64_t v, uint8_t* dst) {
+ int j;
+ for (j = 0; j < 8; ++j) {
+ *(uint64_t*)(dst + j * BPS) = v;
+ }
+}
+
+static void DC8uv(uint8_t *dst) { // DC
+ int dc0 = 8;
+ int i;
+ for (i = 0; i < 8; ++i) {
+ dc0 += dst[i - BPS] + dst[-1 + i * BPS];
+ }
+ Put8x8uv((uint64_t)((dc0 >> 4) * 0x0101010101010101ULL), dst);
+}
+
+static void DC8uvNoLeft(uint8_t *dst) { // DC with no left samples
+ int dc0 = 4;
+ int i;
+ for (i = 0; i < 8; ++i) {
+ dc0 += dst[i - BPS];
+ }
+ Put8x8uv((uint64_t)((dc0 >> 3) * 0x0101010101010101ULL), dst);
+}
+
+static void DC8uvNoTop(uint8_t *dst) { // DC with no top samples
+ int dc0 = 4;
+ int i;
+ for (i = 0; i < 8; ++i) {
+ dc0 += dst[-1 + i * BPS];
+ }
+ Put8x8uv((uint64_t)((dc0 >> 3) * 0x0101010101010101ULL), dst);
+}
+
+static void DC8uvNoTopLeft(uint8_t *dst) { // DC with nothing
+ Put8x8uv(0x8080808080808080ULL, dst);
+}
+
+//------------------------------------------------------------------------------
+// default C implementations
+
+const VP8PredFunc VP8PredLuma4[NUM_BMODES] = {
+ DC4, TM4, VE4, HE4, RD4, VR4, LD4, VL4, HD4, HU4
+};
+
+const VP8PredFunc VP8PredLuma16[NUM_B_DC_MODES] = {
+ DC16, TM16, VE16, HE16,
+ DC16NoTop, DC16NoLeft, DC16NoTopLeft
+};
+
+const VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES] = {
+ DC8uv, TM8uv, VE8uv, HE8uv,
+ DC8uvNoTop, DC8uvNoLeft, DC8uvNoTopLeft
+};
+
+//------------------------------------------------------------------------------
+// Edge filtering functions
+
+// 4 pixels in, 2 pixels out
+static WEBP_INLINE void do_filter2(uint8_t* p, int step) {
+ const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
+ const int a = 3 * (q0 - p0) + sclip1[1020 + p1 - q1];
+ const int a1 = sclip2[112 + ((a + 4) >> 3)];
+ const int a2 = sclip2[112 + ((a + 3) >> 3)];
+ p[-step] = clip1[255 + p0 + a2];
+ p[ 0] = clip1[255 + q0 - a1];
+}
+
+// 4 pixels in, 4 pixels out
+static WEBP_INLINE void do_filter4(uint8_t* p, int step) {
+ const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
+ const int a = 3 * (q0 - p0);
+ const int a1 = sclip2[112 + ((a + 4) >> 3)];
+ const int a2 = sclip2[112 + ((a + 3) >> 3)];
+ const int a3 = (a1 + 1) >> 1;
+ p[-2*step] = clip1[255 + p1 + a3];
+ p[- step] = clip1[255 + p0 + a2];
+ p[ 0] = clip1[255 + q0 - a1];
+ p[ step] = clip1[255 + q1 - a3];
+}
+
+// 6 pixels in, 6 pixels out
+static WEBP_INLINE void do_filter6(uint8_t* p, int step) {
+ const int p2 = p[-3*step], p1 = p[-2*step], p0 = p[-step];
+ const int q0 = p[0], q1 = p[step], q2 = p[2*step];
+ const int a = sclip1[1020 + 3 * (q0 - p0) + sclip1[1020 + p1 - q1]];
+ const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7
+ const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7
+ const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7
+ p[-3*step] = clip1[255 + p2 + a3];
+ p[-2*step] = clip1[255 + p1 + a2];
+ p[- step] = clip1[255 + p0 + a1];
+ p[ 0] = clip1[255 + q0 - a1];
+ p[ step] = clip1[255 + q1 - a2];
+ p[ 2*step] = clip1[255 + q2 - a3];
+}
+
+static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) {
+ const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
+ return (abs0[255 + p1 - p0] > thresh) || (abs0[255 + q1 - q0] > thresh);
+}
+
+static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int thresh) {
+ const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
+ return (2 * abs0[255 + p0 - q0] + abs1[255 + p1 - q1]) <= thresh;
+}
+
+static WEBP_INLINE int needs_filter2(const uint8_t* p,
+ int step, int t, int it) {
+ const int p3 = p[-4*step], p2 = p[-3*step], p1 = p[-2*step], p0 = p[-step];
+ const int q0 = p[0], q1 = p[step], q2 = p[2*step], q3 = p[3*step];
+ if ((2 * abs0[255 + p0 - q0] + abs1[255 + p1 - q1]) > t)
+ return 0;
+ return abs0[255 + p3 - p2] <= it && abs0[255 + p2 - p1] <= it &&
+ abs0[255 + p1 - p0] <= it && abs0[255 + q3 - q2] <= it &&
+ abs0[255 + q2 - q1] <= it && abs0[255 + q1 - q0] <= it;
+}
+
+//------------------------------------------------------------------------------
+// Simple In-loop filtering (Paragraph 15.2)
+
+static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
+ int i;
+ for (i = 0; i < 16; ++i) {
+ if (needs_filter(p + i, stride, thresh)) {
+ do_filter2(p + i, stride);
+ }
+ }
+}
+
+static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
+ int i;
+ for (i = 0; i < 16; ++i) {
+ if (needs_filter(p + i * stride, 1, thresh)) {
+ do_filter2(p + i * stride, 1);
+ }
+ }
+}
+
+static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4 * stride;
+ SimpleVFilter16(p, stride, thresh);
+ }
+}
+
+static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4;
+ SimpleHFilter16(p, stride, thresh);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Complex In-loop filtering (Paragraph 15.3)
+
+static WEBP_INLINE void FilterLoop26(uint8_t* p,
+ int hstride, int vstride, int size,
+ int thresh, int ithresh, int hev_thresh) {
+ while (size-- > 0) {
+ if (needs_filter2(p, hstride, thresh, ithresh)) {
+ if (hev(p, hstride, hev_thresh)) {
+ do_filter2(p, hstride);
+ } else {
+ do_filter6(p, hstride);
+ }
+ }
+ p += vstride;
+ }
+}
+
+static WEBP_INLINE void FilterLoop24(uint8_t* p,
+ int hstride, int vstride, int size,
+ int thresh, int ithresh, int hev_thresh) {
+ while (size-- > 0) {
+ if (needs_filter2(p, hstride, thresh, ithresh)) {
+ if (hev(p, hstride, hev_thresh)) {
+ do_filter2(p, hstride);
+ } else {
+ do_filter4(p, hstride);
+ }
+ }
+ p += vstride;
+ }
+}
+
+// on macroblock edges
+static void VFilter16(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh);
+}
+
+static void HFilter16(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh);
+}
+
+// on three inner edges
+static void VFilter16i(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4 * stride;
+ FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh);
+ }
+}
+
+static void HFilter16i(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4;
+ FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh);
+ }
+}
+
+// 8-pixels wide variant, for chroma filtering
+static void VFilter8(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh);
+ FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh);
+}
+
+static void HFilter8(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh);
+ FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh);
+}
+
+static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
+ FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
+}
+
+static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
+ FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
+}
+
+//------------------------------------------------------------------------------
+
+VP8DecIdct2 VP8Transform;
+VP8DecIdct VP8TransformUV;
+VP8DecIdct VP8TransformDC;
+VP8DecIdct VP8TransformDCUV;
+
+VP8LumaFilterFunc VP8VFilter16;
+VP8LumaFilterFunc VP8HFilter16;
+VP8ChromaFilterFunc VP8VFilter8;
+VP8ChromaFilterFunc VP8HFilter8;
+VP8LumaFilterFunc VP8VFilter16i;
+VP8LumaFilterFunc VP8HFilter16i;
+VP8ChromaFilterFunc VP8VFilter8i;
+VP8ChromaFilterFunc VP8HFilter8i;
+VP8SimpleFilterFunc VP8SimpleVFilter16;
+VP8SimpleFilterFunc VP8SimpleHFilter16;
+VP8SimpleFilterFunc VP8SimpleVFilter16i;
+VP8SimpleFilterFunc VP8SimpleHFilter16i;
+
+extern void VP8DspInitSSE2(void);
+extern void VP8DspInitNEON(void);
+
+void VP8DspInit(void) {
+ DspInitTables();
+
+ VP8Transform = TransformTwo;
+ VP8TransformUV = TransformUV;
+ VP8TransformDC = TransformDC;
+ VP8TransformDCUV = TransformDCUV;
+
+ VP8VFilter16 = VFilter16;
+ VP8HFilter16 = HFilter16;
+ VP8VFilter8 = VFilter8;
+ VP8HFilter8 = HFilter8;
+ VP8VFilter16i = VFilter16i;
+ VP8HFilter16i = HFilter16i;
+ VP8VFilter8i = VFilter8i;
+ VP8HFilter8i = HFilter8i;
+ VP8SimpleVFilter16 = SimpleVFilter16;
+ VP8SimpleHFilter16 = SimpleHFilter16;
+ VP8SimpleVFilter16i = SimpleVFilter16i;
+ VP8SimpleHFilter16i = SimpleHFilter16i;
+
+ // If defined, use CPUInfo() to overwrite some pointers with faster versions.
+ if (VP8GetCPUInfo) {
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ VP8DspInitSSE2();
+ }
+#elif defined(WEBP_USE_NEON)
+ if (VP8GetCPUInfo(kNEON)) {
+ VP8DspInitNEON();
+ }
+#endif
+ }
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dsp/dec_neon.c b/drivers/webpold/dsp/dec_neon.c
new file mode 100644
index 0000000000..ec824b790b
--- /dev/null
+++ b/drivers/webpold/dsp/dec_neon.c
@@ -0,0 +1,329 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// ARM NEON version of dsp functions and loop filtering.
+//
+// Authors: Somnath Banerjee (somnath@google.com)
+// Johann Koenig (johannkoenig@google.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_NEON)
+
+#include "../dec/vp8i.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define QRegs "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", \
+ "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
+
+#define FLIP_SIGN_BIT2(a, b, s) \
+ "veor " #a "," #a "," #s " \n" \
+ "veor " #b "," #b "," #s " \n" \
+
+#define FLIP_SIGN_BIT4(a, b, c, d, s) \
+ FLIP_SIGN_BIT2(a, b, s) \
+ FLIP_SIGN_BIT2(c, d, s) \
+
+#define NEEDS_FILTER(p1, p0, q0, q1, thresh, mask) \
+ "vabd.u8 q15," #p0 "," #q0 " \n" /* abs(p0 - q0) */ \
+ "vabd.u8 q14," #p1 "," #q1 " \n" /* abs(p1 - q1) */ \
+ "vqadd.u8 q15, q15, q15 \n" /* abs(p0 - q0) * 2 */ \
+ "vshr.u8 q14, q14, #1 \n" /* abs(p1 - q1) / 2 */ \
+ "vqadd.u8 q15, q15, q14 \n" /* abs(p0 - q0) * 2 + abs(p1 - q1) / 2 */ \
+ "vdup.8 q14, " #thresh " \n" \
+ "vcge.u8 " #mask ", q14, q15 \n" /* mask <= thresh */
+
+#define GET_BASE_DELTA(p1, p0, q0, q1, o) \
+ "vqsub.s8 q15," #q0 "," #p0 " \n" /* (q0 - p0) */ \
+ "vqsub.s8 " #o "," #p1 "," #q1 " \n" /* (p1 - q1) */ \
+ "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 1 * (p0 - q0) */ \
+ "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 2 * (p0 - q0) */ \
+ "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 3 * (p0 - q0) */
+
+#define DO_SIMPLE_FILTER(p0, q0, fl) \
+ "vmov.i8 q15, #0x03 \n" \
+ "vqadd.s8 q15, q15, " #fl " \n" /* filter1 = filter + 3 */ \
+ "vshr.s8 q15, q15, #3 \n" /* filter1 >> 3 */ \
+ "vqadd.s8 " #p0 "," #p0 ", q15 \n" /* p0 += filter1 */ \
+ \
+ "vmov.i8 q15, #0x04 \n" \
+ "vqadd.s8 q15, q15, " #fl " \n" /* filter1 = filter + 4 */ \
+ "vshr.s8 q15, q15, #3 \n" /* filter2 >> 3 */ \
+ "vqsub.s8 " #q0 "," #q0 ", q15 \n" /* q0 -= filter2 */
+
+// Applies filter on 2 pixels (p0 and q0)
+#define DO_FILTER2(p1, p0, q0, q1, thresh) \
+ NEEDS_FILTER(p1, p0, q0, q1, thresh, q9) /* filter mask in q9 */ \
+ "vmov.i8 q10, #0x80 \n" /* sign bit */ \
+ FLIP_SIGN_BIT4(p1, p0, q0, q1, q10) /* convert to signed value */ \
+ GET_BASE_DELTA(p1, p0, q0, q1, q11) /* get filter level */ \
+ "vand q9, q9, q11 \n" /* apply filter mask */ \
+ DO_SIMPLE_FILTER(p0, q0, q9) /* apply filter */ \
+ FLIP_SIGN_BIT2(p0, q0, q10)
+
+// Load/Store vertical edge
+#define LOAD8x4(c1, c2, c3, c4, b1, b2, stride) \
+ "vld4.8 {" #c1"[0], " #c2"[0], " #c3"[0], " #c4"[0]}," #b1 "," #stride"\n" \
+ "vld4.8 {" #c1"[1], " #c2"[1], " #c3"[1], " #c4"[1]}," #b2 "," #stride"\n" \
+ "vld4.8 {" #c1"[2], " #c2"[2], " #c3"[2], " #c4"[2]}," #b1 "," #stride"\n" \
+ "vld4.8 {" #c1"[3], " #c2"[3], " #c3"[3], " #c4"[3]}," #b2 "," #stride"\n" \
+ "vld4.8 {" #c1"[4], " #c2"[4], " #c3"[4], " #c4"[4]}," #b1 "," #stride"\n" \
+ "vld4.8 {" #c1"[5], " #c2"[5], " #c3"[5], " #c4"[5]}," #b2 "," #stride"\n" \
+ "vld4.8 {" #c1"[6], " #c2"[6], " #c3"[6], " #c4"[6]}," #b1 "," #stride"\n" \
+ "vld4.8 {" #c1"[7], " #c2"[7], " #c3"[7], " #c4"[7]}," #b2 "," #stride"\n"
+
+#define STORE8x2(c1, c2, p,stride) \
+ "vst2.8 {" #c1"[0], " #c2"[0]}," #p "," #stride " \n" \
+ "vst2.8 {" #c1"[1], " #c2"[1]}," #p "," #stride " \n" \
+ "vst2.8 {" #c1"[2], " #c2"[2]}," #p "," #stride " \n" \
+ "vst2.8 {" #c1"[3], " #c2"[3]}," #p "," #stride " \n" \
+ "vst2.8 {" #c1"[4], " #c2"[4]}," #p "," #stride " \n" \
+ "vst2.8 {" #c1"[5], " #c2"[5]}," #p "," #stride " \n" \
+ "vst2.8 {" #c1"[6], " #c2"[6]}," #p "," #stride " \n" \
+ "vst2.8 {" #c1"[7], " #c2"[7]}," #p "," #stride " \n"
+
+//-----------------------------------------------------------------------------
+// Simple In-loop filtering (Paragraph 15.2)
+
+static void SimpleVFilter16NEON(uint8_t* p, int stride, int thresh) {
+ __asm__ volatile (
+ "sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride
+
+ "vld1.u8 {q1}, [%[p]], %[stride] \n" // p1
+ "vld1.u8 {q2}, [%[p]], %[stride] \n" // p0
+ "vld1.u8 {q3}, [%[p]], %[stride] \n" // q0
+ "vld1.u8 {q4}, [%[p]] \n" // q1
+
+ DO_FILTER2(q1, q2, q3, q4, %[thresh])
+
+ "sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride
+
+ "vst1.u8 {q2}, [%[p]], %[stride] \n" // store op0
+ "vst1.u8 {q3}, [%[p]] \n" // store oq0
+ : [p] "+r"(p)
+ : [stride] "r"(stride), [thresh] "r"(thresh)
+ : "memory", QRegs
+ );
+}
+
+static void SimpleHFilter16NEON(uint8_t* p, int stride, int thresh) {
+ __asm__ volatile (
+ "sub r4, %[p], #2 \n" // base1 = p - 2
+ "lsl r6, %[stride], #1 \n" // r6 = 2 * stride
+ "add r5, r4, %[stride] \n" // base2 = base1 + stride
+
+ LOAD8x4(d2, d3, d4, d5, [r4], [r5], r6)
+ LOAD8x4(d6, d7, d8, d9, [r4], [r5], r6)
+ "vswp d3, d6 \n" // p1:q1 p0:q3
+ "vswp d5, d8 \n" // q0:q2 q1:q4
+ "vswp q2, q3 \n" // p1:q1 p0:q2 q0:q3 q1:q4
+
+ DO_FILTER2(q1, q2, q3, q4, %[thresh])
+
+ "sub %[p], %[p], #1 \n" // p - 1
+
+ "vswp d5, d6 \n"
+ STORE8x2(d4, d5, [%[p]], %[stride])
+ STORE8x2(d6, d7, [%[p]], %[stride])
+
+ : [p] "+r"(p)
+ : [stride] "r"(stride), [thresh] "r"(thresh)
+ : "memory", "r4", "r5", "r6", QRegs
+ );
+}
+
+static void SimpleVFilter16iNEON(uint8_t* p, int stride, int thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4 * stride;
+ SimpleVFilter16NEON(p, stride, thresh);
+ }
+}
+
+static void SimpleHFilter16iNEON(uint8_t* p, int stride, int thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4;
+ SimpleHFilter16NEON(p, stride, thresh);
+ }
+}
+
+static void TransformOneNEON(const int16_t *in, uint8_t *dst) {
+ const int kBPS = BPS;
+ const int16_t constants[] = {20091, 17734, 0, 0};
+ /* kC1, kC2. Padded because vld1.16 loads 8 bytes
+ * Technically these are unsigned but vqdmulh is only available in signed.
+ * vqdmulh returns high half (effectively >> 16) but also doubles the value,
+ * changing the >> 16 to >> 15 and requiring an additional >> 1.
+ * We use this to our advantage with kC2. The canonical value is 35468.
+ * However, the high bit is set so treating it as signed will give incorrect
+ * results. We avoid this by down shifting by 1 here to clear the highest bit.
+ * Combined with the doubling effect of vqdmulh we get >> 16.
+ * This can not be applied to kC1 because the lowest bit is set. Down shifting
+ * the constant would reduce precision.
+ */
+
+ /* libwebp uses a trick to avoid some extra addition that libvpx does.
+ * Instead of:
+ * temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1) >> 16);
+ * libwebp adds 1 << 16 to cospi8sqrt2minus1 (kC1). However, this causes the
+ * same issue with kC1 and vqdmulh that we work around by down shifting kC2
+ */
+
+ /* Adapted from libvpx: vp8/common/arm/neon/shortidct4x4llm_neon.asm */
+ __asm__ volatile (
+ "vld1.16 {q1, q2}, [%[in]] \n"
+ "vld1.16 {d0}, [%[constants]] \n"
+
+ /* d2: in[0]
+ * d3: in[8]
+ * d4: in[4]
+ * d5: in[12]
+ */
+ "vswp d3, d4 \n"
+
+ /* q8 = {in[4], in[12]} * kC1 * 2 >> 16
+ * q9 = {in[4], in[12]} * kC2 >> 16
+ */
+ "vqdmulh.s16 q8, q2, d0[0] \n"
+ "vqdmulh.s16 q9, q2, d0[1] \n"
+
+ /* d22 = a = in[0] + in[8]
+ * d23 = b = in[0] - in[8]
+ */
+ "vqadd.s16 d22, d2, d3 \n"
+ "vqsub.s16 d23, d2, d3 \n"
+
+ /* The multiplication should be x * kC1 >> 16
+ * However, with vqdmulh we get x * kC1 * 2 >> 16
+ * (multiply, double, return high half)
+ * We avoided this in kC2 by pre-shifting the constant.
+ * q8 = in[4]/[12] * kC1 >> 16
+ */
+ "vshr.s16 q8, q8, #1 \n"
+
+ /* Add {in[4], in[12]} back after the multiplication. This is handled by
+ * adding 1 << 16 to kC1 in the libwebp C code.
+ */
+ "vqadd.s16 q8, q2, q8 \n"
+
+ /* d20 = c = in[4]*kC2 - in[12]*kC1
+ * d21 = d = in[4]*kC1 + in[12]*kC2
+ */
+ "vqsub.s16 d20, d18, d17 \n"
+ "vqadd.s16 d21, d19, d16 \n"
+
+ /* d2 = tmp[0] = a + d
+ * d3 = tmp[1] = b + c
+ * d4 = tmp[2] = b - c
+ * d5 = tmp[3] = a - d
+ */
+ "vqadd.s16 d2, d22, d21 \n"
+ "vqadd.s16 d3, d23, d20 \n"
+ "vqsub.s16 d4, d23, d20 \n"
+ "vqsub.s16 d5, d22, d21 \n"
+
+ "vzip.16 q1, q2 \n"
+ "vzip.16 q1, q2 \n"
+
+ "vswp d3, d4 \n"
+
+ /* q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16
+ * q9 = {tmp[4], tmp[12]} * kC2 >> 16
+ */
+ "vqdmulh.s16 q8, q2, d0[0] \n"
+ "vqdmulh.s16 q9, q2, d0[1] \n"
+
+ /* d22 = a = tmp[0] + tmp[8]
+ * d23 = b = tmp[0] - tmp[8]
+ */
+ "vqadd.s16 d22, d2, d3 \n"
+ "vqsub.s16 d23, d2, d3 \n"
+
+ /* See long winded explanations prior */
+ "vshr.s16 q8, q8, #1 \n"
+ "vqadd.s16 q8, q2, q8 \n"
+
+ /* d20 = c = in[4]*kC2 - in[12]*kC1
+ * d21 = d = in[4]*kC1 + in[12]*kC2
+ */
+ "vqsub.s16 d20, d18, d17 \n"
+ "vqadd.s16 d21, d19, d16 \n"
+
+ /* d2 = tmp[0] = a + d
+ * d3 = tmp[1] = b + c
+ * d4 = tmp[2] = b - c
+ * d5 = tmp[3] = a - d
+ */
+ "vqadd.s16 d2, d22, d21 \n"
+ "vqadd.s16 d3, d23, d20 \n"
+ "vqsub.s16 d4, d23, d20 \n"
+ "vqsub.s16 d5, d22, d21 \n"
+
+ "vld1.32 d6[0], [%[dst]], %[kBPS] \n"
+ "vld1.32 d6[1], [%[dst]], %[kBPS] \n"
+ "vld1.32 d7[0], [%[dst]], %[kBPS] \n"
+ "vld1.32 d7[1], [%[dst]], %[kBPS] \n"
+
+ "sub %[dst], %[dst], %[kBPS], lsl #2 \n"
+
+ /* (val) + 4 >> 3 */
+ "vrshr.s16 d2, d2, #3 \n"
+ "vrshr.s16 d3, d3, #3 \n"
+ "vrshr.s16 d4, d4, #3 \n"
+ "vrshr.s16 d5, d5, #3 \n"
+
+ "vzip.16 q1, q2 \n"
+ "vzip.16 q1, q2 \n"
+
+ /* Must accumulate before saturating */
+ "vmovl.u8 q8, d6 \n"
+ "vmovl.u8 q9, d7 \n"
+
+ "vqadd.s16 q1, q1, q8 \n"
+ "vqadd.s16 q2, q2, q9 \n"
+
+ "vqmovun.s16 d0, q1 \n"
+ "vqmovun.s16 d1, q2 \n"
+
+ "vst1.32 d0[0], [%[dst]], %[kBPS] \n"
+ "vst1.32 d0[1], [%[dst]], %[kBPS] \n"
+ "vst1.32 d1[0], [%[dst]], %[kBPS] \n"
+ "vst1.32 d1[1], [%[dst]] \n"
+
+ : [in] "+r"(in), [dst] "+r"(dst) /* modified registers */
+ : [kBPS] "r"(kBPS), [constants] "r"(constants) /* constants */
+ : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11" /* clobbered */
+ );
+}
+
+static void TransformTwoNEON(const int16_t* in, uint8_t* dst, int do_two) {
+ TransformOneNEON(in, dst);
+ if (do_two) {
+ TransformOneNEON(in + 16, dst + 4);
+ }
+}
+
+extern void VP8DspInitNEON(void);
+
+void VP8DspInitNEON(void) {
+ VP8Transform = TransformTwoNEON;
+
+ VP8SimpleVFilter16 = SimpleVFilter16NEON;
+ VP8SimpleHFilter16 = SimpleHFilter16NEON;
+ VP8SimpleVFilter16i = SimpleVFilter16iNEON;
+ VP8SimpleHFilter16i = SimpleHFilter16iNEON;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif // WEBP_USE_NEON
diff --git a/drivers/webpold/dsp/dec_sse2.c b/drivers/webpold/dsp/dec_sse2.c
new file mode 100644
index 0000000000..472b68ecb8
--- /dev/null
+++ b/drivers/webpold/dsp/dec_sse2.c
@@ -0,0 +1,903 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// SSE2 version of some decoding functions (idct, loop filtering).
+//
+// Author: somnath@google.com (Somnath Banerjee)
+// cduvivier@google.com (Christian Duvivier)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_SSE2)
+
+#include <emmintrin.h>
+#include "../dec/vp8i.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Transforms (Paragraph 14.4)
+
+static void TransformSSE2(const int16_t* in, uint8_t* dst, int do_two) {
+ // This implementation makes use of 16-bit fixed point versions of two
+ // multiply constants:
+ // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16
+ // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16
+ //
+ // To be able to use signed 16-bit integers, we use the following trick to
+ // have constants within range:
+ // - Associated constants are obtained by subtracting the 16-bit fixed point
+ // version of one:
+ // k = K - (1 << 16) => K = k + (1 << 16)
+ // K1 = 85267 => k1 = 20091
+ // K2 = 35468 => k2 = -30068
+ // - The multiplication of a variable by a constant become the sum of the
+ // variable and the multiplication of that variable by the associated
+ // constant:
+ // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x
+ const __m128i k1 = _mm_set1_epi16(20091);
+ const __m128i k2 = _mm_set1_epi16(-30068);
+ __m128i T0, T1, T2, T3;
+
+ // Load and concatenate the transform coefficients (we'll do two transforms
+ // in parallel). In the case of only one transform, the second half of the
+ // vectors will just contain random value we'll never use nor store.
+ __m128i in0, in1, in2, in3;
+ {
+ in0 = _mm_loadl_epi64((__m128i*)&in[0]);
+ in1 = _mm_loadl_epi64((__m128i*)&in[4]);
+ in2 = _mm_loadl_epi64((__m128i*)&in[8]);
+ in3 = _mm_loadl_epi64((__m128i*)&in[12]);
+ // a00 a10 a20 a30 x x x x
+ // a01 a11 a21 a31 x x x x
+ // a02 a12 a22 a32 x x x x
+ // a03 a13 a23 a33 x x x x
+ if (do_two) {
+ const __m128i inB0 = _mm_loadl_epi64((__m128i*)&in[16]);
+ const __m128i inB1 = _mm_loadl_epi64((__m128i*)&in[20]);
+ const __m128i inB2 = _mm_loadl_epi64((__m128i*)&in[24]);
+ const __m128i inB3 = _mm_loadl_epi64((__m128i*)&in[28]);
+ in0 = _mm_unpacklo_epi64(in0, inB0);
+ in1 = _mm_unpacklo_epi64(in1, inB1);
+ in2 = _mm_unpacklo_epi64(in2, inB2);
+ in3 = _mm_unpacklo_epi64(in3, inB3);
+ // a00 a10 a20 a30 b00 b10 b20 b30
+ // a01 a11 a21 a31 b01 b11 b21 b31
+ // a02 a12 a22 a32 b02 b12 b22 b32
+ // a03 a13 a23 a33 b03 b13 b23 b33
+ }
+ }
+
+ // Vertical pass and subsequent transpose.
+ {
+ // First pass, c and d calculations are longer because of the "trick"
+ // multiplications.
+ const __m128i a = _mm_add_epi16(in0, in2);
+ const __m128i b = _mm_sub_epi16(in0, in2);
+ // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3
+ const __m128i c1 = _mm_mulhi_epi16(in1, k2);
+ const __m128i c2 = _mm_mulhi_epi16(in3, k1);
+ const __m128i c3 = _mm_sub_epi16(in1, in3);
+ const __m128i c4 = _mm_sub_epi16(c1, c2);
+ const __m128i c = _mm_add_epi16(c3, c4);
+ // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3
+ const __m128i d1 = _mm_mulhi_epi16(in1, k1);
+ const __m128i d2 = _mm_mulhi_epi16(in3, k2);
+ const __m128i d3 = _mm_add_epi16(in1, in3);
+ const __m128i d4 = _mm_add_epi16(d1, d2);
+ const __m128i d = _mm_add_epi16(d3, d4);
+
+ // Second pass.
+ const __m128i tmp0 = _mm_add_epi16(a, d);
+ const __m128i tmp1 = _mm_add_epi16(b, c);
+ const __m128i tmp2 = _mm_sub_epi16(b, c);
+ const __m128i tmp3 = _mm_sub_epi16(a, d);
+
+ // Transpose the two 4x4.
+ // a00 a01 a02 a03 b00 b01 b02 b03
+ // a10 a11 a12 a13 b10 b11 b12 b13
+ // a20 a21 a22 a23 b20 b21 b22 b23
+ // a30 a31 a32 a33 b30 b31 b32 b33
+ const __m128i transpose0_0 = _mm_unpacklo_epi16(tmp0, tmp1);
+ const __m128i transpose0_1 = _mm_unpacklo_epi16(tmp2, tmp3);
+ const __m128i transpose0_2 = _mm_unpackhi_epi16(tmp0, tmp1);
+ const __m128i transpose0_3 = _mm_unpackhi_epi16(tmp2, tmp3);
+ // a00 a10 a01 a11 a02 a12 a03 a13
+ // a20 a30 a21 a31 a22 a32 a23 a33
+ // b00 b10 b01 b11 b02 b12 b03 b13
+ // b20 b30 b21 b31 b22 b32 b23 b33
+ const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
+ const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3);
+ const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
+ const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3);
+ // a00 a10 a20 a30 a01 a11 a21 a31
+ // b00 b10 b20 b30 b01 b11 b21 b31
+ // a02 a12 a22 a32 a03 a13 a23 a33
+ // b02 b12 a22 b32 b03 b13 b23 b33
+ T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1);
+ T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1);
+ T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3);
+ T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3);
+ // a00 a10 a20 a30 b00 b10 b20 b30
+ // a01 a11 a21 a31 b01 b11 b21 b31
+ // a02 a12 a22 a32 b02 b12 b22 b32
+ // a03 a13 a23 a33 b03 b13 b23 b33
+ }
+
+ // Horizontal pass and subsequent transpose.
+ {
+ // First pass, c and d calculations are longer because of the "trick"
+ // multiplications.
+ const __m128i four = _mm_set1_epi16(4);
+ const __m128i dc = _mm_add_epi16(T0, four);
+ const __m128i a = _mm_add_epi16(dc, T2);
+ const __m128i b = _mm_sub_epi16(dc, T2);
+ // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3
+ const __m128i c1 = _mm_mulhi_epi16(T1, k2);
+ const __m128i c2 = _mm_mulhi_epi16(T3, k1);
+ const __m128i c3 = _mm_sub_epi16(T1, T3);
+ const __m128i c4 = _mm_sub_epi16(c1, c2);
+ const __m128i c = _mm_add_epi16(c3, c4);
+ // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3
+ const __m128i d1 = _mm_mulhi_epi16(T1, k1);
+ const __m128i d2 = _mm_mulhi_epi16(T3, k2);
+ const __m128i d3 = _mm_add_epi16(T1, T3);
+ const __m128i d4 = _mm_add_epi16(d1, d2);
+ const __m128i d = _mm_add_epi16(d3, d4);
+
+ // Second pass.
+ const __m128i tmp0 = _mm_add_epi16(a, d);
+ const __m128i tmp1 = _mm_add_epi16(b, c);
+ const __m128i tmp2 = _mm_sub_epi16(b, c);
+ const __m128i tmp3 = _mm_sub_epi16(a, d);
+ const __m128i shifted0 = _mm_srai_epi16(tmp0, 3);
+ const __m128i shifted1 = _mm_srai_epi16(tmp1, 3);
+ const __m128i shifted2 = _mm_srai_epi16(tmp2, 3);
+ const __m128i shifted3 = _mm_srai_epi16(tmp3, 3);
+
+ // Transpose the two 4x4.
+ // a00 a01 a02 a03 b00 b01 b02 b03
+ // a10 a11 a12 a13 b10 b11 b12 b13
+ // a20 a21 a22 a23 b20 b21 b22 b23
+ // a30 a31 a32 a33 b30 b31 b32 b33
+ const __m128i transpose0_0 = _mm_unpacklo_epi16(shifted0, shifted1);
+ const __m128i transpose0_1 = _mm_unpacklo_epi16(shifted2, shifted3);
+ const __m128i transpose0_2 = _mm_unpackhi_epi16(shifted0, shifted1);
+ const __m128i transpose0_3 = _mm_unpackhi_epi16(shifted2, shifted3);
+ // a00 a10 a01 a11 a02 a12 a03 a13
+ // a20 a30 a21 a31 a22 a32 a23 a33
+ // b00 b10 b01 b11 b02 b12 b03 b13
+ // b20 b30 b21 b31 b22 b32 b23 b33
+ const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
+ const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3);
+ const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
+ const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3);
+ // a00 a10 a20 a30 a01 a11 a21 a31
+ // b00 b10 b20 b30 b01 b11 b21 b31
+ // a02 a12 a22 a32 a03 a13 a23 a33
+ // b02 b12 a22 b32 b03 b13 b23 b33
+ T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1);
+ T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1);
+ T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3);
+ T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3);
+ // a00 a10 a20 a30 b00 b10 b20 b30
+ // a01 a11 a21 a31 b01 b11 b21 b31
+ // a02 a12 a22 a32 b02 b12 b22 b32
+ // a03 a13 a23 a33 b03 b13 b23 b33
+ }
+
+ // Add inverse transform to 'dst' and store.
+ {
+ const __m128i zero = _mm_set1_epi16(0);
+ // Load the reference(s).
+ __m128i dst0, dst1, dst2, dst3;
+ if (do_two) {
+ // Load eight bytes/pixels per line.
+ dst0 = _mm_loadl_epi64((__m128i*)&dst[0 * BPS]);
+ dst1 = _mm_loadl_epi64((__m128i*)&dst[1 * BPS]);
+ dst2 = _mm_loadl_epi64((__m128i*)&dst[2 * BPS]);
+ dst3 = _mm_loadl_epi64((__m128i*)&dst[3 * BPS]);
+ } else {
+ // Load four bytes/pixels per line.
+ dst0 = _mm_cvtsi32_si128(*(int*)&dst[0 * BPS]);
+ dst1 = _mm_cvtsi32_si128(*(int*)&dst[1 * BPS]);
+ dst2 = _mm_cvtsi32_si128(*(int*)&dst[2 * BPS]);
+ dst3 = _mm_cvtsi32_si128(*(int*)&dst[3 * BPS]);
+ }
+ // Convert to 16b.
+ dst0 = _mm_unpacklo_epi8(dst0, zero);
+ dst1 = _mm_unpacklo_epi8(dst1, zero);
+ dst2 = _mm_unpacklo_epi8(dst2, zero);
+ dst3 = _mm_unpacklo_epi8(dst3, zero);
+ // Add the inverse transform(s).
+ dst0 = _mm_add_epi16(dst0, T0);
+ dst1 = _mm_add_epi16(dst1, T1);
+ dst2 = _mm_add_epi16(dst2, T2);
+ dst3 = _mm_add_epi16(dst3, T3);
+ // Unsigned saturate to 8b.
+ dst0 = _mm_packus_epi16(dst0, dst0);
+ dst1 = _mm_packus_epi16(dst1, dst1);
+ dst2 = _mm_packus_epi16(dst2, dst2);
+ dst3 = _mm_packus_epi16(dst3, dst3);
+ // Store the results.
+ if (do_two) {
+ // Store eight bytes/pixels per line.
+ _mm_storel_epi64((__m128i*)&dst[0 * BPS], dst0);
+ _mm_storel_epi64((__m128i*)&dst[1 * BPS], dst1);
+ _mm_storel_epi64((__m128i*)&dst[2 * BPS], dst2);
+ _mm_storel_epi64((__m128i*)&dst[3 * BPS], dst3);
+ } else {
+ // Store four bytes/pixels per line.
+ *((int32_t *)&dst[0 * BPS]) = _mm_cvtsi128_si32(dst0);
+ *((int32_t *)&dst[1 * BPS]) = _mm_cvtsi128_si32(dst1);
+ *((int32_t *)&dst[2 * BPS]) = _mm_cvtsi128_si32(dst2);
+ *((int32_t *)&dst[3 * BPS]) = _mm_cvtsi128_si32(dst3);
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// Loop Filter (Paragraph 15)
+
+// Compute abs(p - q) = subs(p - q) OR subs(q - p)
+#define MM_ABS(p, q) _mm_or_si128( \
+ _mm_subs_epu8((q), (p)), \
+ _mm_subs_epu8((p), (q)))
+
+// Shift each byte of "a" by N bits while preserving by the sign bit.
+//
+// It first shifts the lower bytes of the words and then the upper bytes and
+// then merges the results together.
+#define SIGNED_SHIFT_N(a, N) { \
+ __m128i t = a; \
+ t = _mm_slli_epi16(t, 8); \
+ t = _mm_srai_epi16(t, N); \
+ t = _mm_srli_epi16(t, 8); \
+ \
+ a = _mm_srai_epi16(a, N + 8); \
+ a = _mm_slli_epi16(a, 8); \
+ \
+ a = _mm_or_si128(t, a); \
+}
+
+#define FLIP_SIGN_BIT2(a, b) { \
+ a = _mm_xor_si128(a, sign_bit); \
+ b = _mm_xor_si128(b, sign_bit); \
+}
+
+#define FLIP_SIGN_BIT4(a, b, c, d) { \
+ FLIP_SIGN_BIT2(a, b); \
+ FLIP_SIGN_BIT2(c, d); \
+}
+
+#define GET_NOTHEV(p1, p0, q0, q1, hev_thresh, not_hev) { \
+ const __m128i zero = _mm_setzero_si128(); \
+ const __m128i t1 = MM_ABS(p1, p0); \
+ const __m128i t2 = MM_ABS(q1, q0); \
+ \
+ const __m128i h = _mm_set1_epi8(hev_thresh); \
+ const __m128i t3 = _mm_subs_epu8(t1, h); /* abs(p1 - p0) - hev_tresh */ \
+ const __m128i t4 = _mm_subs_epu8(t2, h); /* abs(q1 - q0) - hev_tresh */ \
+ \
+ not_hev = _mm_or_si128(t3, t4); \
+ not_hev = _mm_cmpeq_epi8(not_hev, zero); /* not_hev <= t1 && not_hev <= t2 */\
+}
+
+#define GET_BASE_DELTA(p1, p0, q0, q1, o) { \
+ const __m128i qp0 = _mm_subs_epi8(q0, p0); /* q0 - p0 */ \
+ o = _mm_subs_epi8(p1, q1); /* p1 - q1 */ \
+ o = _mm_adds_epi8(o, qp0); /* p1 - q1 + 1 * (q0 - p0) */ \
+ o = _mm_adds_epi8(o, qp0); /* p1 - q1 + 2 * (q0 - p0) */ \
+ o = _mm_adds_epi8(o, qp0); /* p1 - q1 + 3 * (q0 - p0) */ \
+}
+
+#define DO_SIMPLE_FILTER(p0, q0, fl) { \
+ const __m128i three = _mm_set1_epi8(3); \
+ const __m128i four = _mm_set1_epi8(4); \
+ __m128i v3 = _mm_adds_epi8(fl, three); \
+ __m128i v4 = _mm_adds_epi8(fl, four); \
+ \
+ /* Do +4 side */ \
+ SIGNED_SHIFT_N(v4, 3); /* v4 >> 3 */ \
+ q0 = _mm_subs_epi8(q0, v4); /* q0 -= v4 */ \
+ \
+ /* Now do +3 side */ \
+ SIGNED_SHIFT_N(v3, 3); /* v3 >> 3 */ \
+ p0 = _mm_adds_epi8(p0, v3); /* p0 += v3 */ \
+}
+
+// Updates values of 2 pixels at MB edge during complex filtering.
+// Update operations:
+// q = q - a and p = p + a; where a = [(a_hi >> 7), (a_lo >> 7)]
+#define UPDATE_2PIXELS(pi, qi, a_lo, a_hi) { \
+ const __m128i a_lo7 = _mm_srai_epi16(a_lo, 7); \
+ const __m128i a_hi7 = _mm_srai_epi16(a_hi, 7); \
+ const __m128i a = _mm_packs_epi16(a_lo7, a_hi7); \
+ pi = _mm_adds_epi8(pi, a); \
+ qi = _mm_subs_epi8(qi, a); \
+}
+
+static void NeedsFilter(const __m128i* p1, const __m128i* p0, const __m128i* q0,
+ const __m128i* q1, int thresh, __m128i *mask) {
+ __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1)
+ *mask = _mm_set1_epi8(0xFE);
+ t1 = _mm_and_si128(t1, *mask); // set lsb of each byte to zero
+ t1 = _mm_srli_epi16(t1, 1); // abs(p1 - q1) / 2
+
+ *mask = MM_ABS(*p0, *q0); // abs(p0 - q0)
+ *mask = _mm_adds_epu8(*mask, *mask); // abs(p0 - q0) * 2
+ *mask = _mm_adds_epu8(*mask, t1); // abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+
+ t1 = _mm_set1_epi8(thresh);
+ *mask = _mm_subs_epu8(*mask, t1); // mask <= thresh
+ *mask = _mm_cmpeq_epi8(*mask, _mm_setzero_si128());
+}
+
+//------------------------------------------------------------------------------
+// Edge filtering functions
+
+// Applies filter on 2 pixels (p0 and q0)
+static WEBP_INLINE void DoFilter2(const __m128i* p1, __m128i* p0, __m128i* q0,
+ const __m128i* q1, int thresh) {
+ __m128i a, mask;
+ const __m128i sign_bit = _mm_set1_epi8(0x80);
+ const __m128i p1s = _mm_xor_si128(*p1, sign_bit);
+ const __m128i q1s = _mm_xor_si128(*q1, sign_bit);
+
+ NeedsFilter(p1, p0, q0, q1, thresh, &mask);
+
+ // convert to signed values
+ FLIP_SIGN_BIT2(*p0, *q0);
+
+ GET_BASE_DELTA(p1s, *p0, *q0, q1s, a);
+ a = _mm_and_si128(a, mask); // mask filter values we don't care about
+ DO_SIMPLE_FILTER(*p0, *q0, a);
+
+ // unoffset
+ FLIP_SIGN_BIT2(*p0, *q0);
+}
+
+// Applies filter on 4 pixels (p1, p0, q0 and q1)
+static WEBP_INLINE void DoFilter4(__m128i* p1, __m128i *p0,
+ __m128i* q0, __m128i* q1,
+ const __m128i* mask, int hev_thresh) {
+ __m128i not_hev;
+ __m128i t1, t2, t3;
+ const __m128i sign_bit = _mm_set1_epi8(0x80);
+
+ // compute hev mask
+ GET_NOTHEV(*p1, *p0, *q0, *q1, hev_thresh, not_hev);
+
+ // convert to signed values
+ FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1);
+
+ t1 = _mm_subs_epi8(*p1, *q1); // p1 - q1
+ t1 = _mm_andnot_si128(not_hev, t1); // hev(p1 - q1)
+ t2 = _mm_subs_epi8(*q0, *p0); // q0 - p0
+ t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 1 * (q0 - p0)
+ t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 2 * (q0 - p0)
+ t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 3 * (q0 - p0)
+ t1 = _mm_and_si128(t1, *mask); // mask filter values we don't care about
+
+ // Do +4 side
+ t2 = _mm_set1_epi8(4);
+ t2 = _mm_adds_epi8(t1, t2); // 3 * (q0 - p0) + (p1 - q1) + 4
+ SIGNED_SHIFT_N(t2, 3); // (3 * (q0 - p0) + hev(p1 - q1) + 4) >> 3
+ t3 = t2; // save t2
+ *q0 = _mm_subs_epi8(*q0, t2); // q0 -= t2
+
+ // Now do +3 side
+ t2 = _mm_set1_epi8(3);
+ t2 = _mm_adds_epi8(t1, t2); // +3 instead of +4
+ SIGNED_SHIFT_N(t2, 3); // (3 * (q0 - p0) + hev(p1 - q1) + 3) >> 3
+ *p0 = _mm_adds_epi8(*p0, t2); // p0 += t2
+
+ t2 = _mm_set1_epi8(1);
+ t3 = _mm_adds_epi8(t3, t2);
+ SIGNED_SHIFT_N(t3, 1); // (3 * (q0 - p0) + hev(p1 - q1) + 4) >> 4
+
+ t3 = _mm_and_si128(not_hev, t3); // if !hev
+ *q1 = _mm_subs_epi8(*q1, t3); // q1 -= t3
+ *p1 = _mm_adds_epi8(*p1, t3); // p1 += t3
+
+ // unoffset
+ FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1);
+}
+
+// Applies filter on 6 pixels (p2, p1, p0, q0, q1 and q2)
+static WEBP_INLINE void DoFilter6(__m128i *p2, __m128i* p1, __m128i *p0,
+ __m128i* q0, __m128i* q1, __m128i *q2,
+ const __m128i* mask, int hev_thresh) {
+ __m128i a, not_hev;
+ const __m128i sign_bit = _mm_set1_epi8(0x80);
+
+ // compute hev mask
+ GET_NOTHEV(*p1, *p0, *q0, *q1, hev_thresh, not_hev);
+
+ // convert to signed values
+ FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1);
+ FLIP_SIGN_BIT2(*p2, *q2);
+
+ GET_BASE_DELTA(*p1, *p0, *q0, *q1, a);
+
+ { // do simple filter on pixels with hev
+ const __m128i m = _mm_andnot_si128(not_hev, *mask);
+ const __m128i f = _mm_and_si128(a, m);
+ DO_SIMPLE_FILTER(*p0, *q0, f);
+ }
+ { // do strong filter on pixels with not hev
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i nine = _mm_set1_epi16(0x0900);
+ const __m128i sixty_three = _mm_set1_epi16(63);
+
+ const __m128i m = _mm_and_si128(not_hev, *mask);
+ const __m128i f = _mm_and_si128(a, m);
+ const __m128i f_lo = _mm_unpacklo_epi8(zero, f);
+ const __m128i f_hi = _mm_unpackhi_epi8(zero, f);
+
+ const __m128i f9_lo = _mm_mulhi_epi16(f_lo, nine); // Filter (lo) * 9
+ const __m128i f9_hi = _mm_mulhi_epi16(f_hi, nine); // Filter (hi) * 9
+ const __m128i f18_lo = _mm_add_epi16(f9_lo, f9_lo); // Filter (lo) * 18
+ const __m128i f18_hi = _mm_add_epi16(f9_hi, f9_hi); // Filter (hi) * 18
+
+ const __m128i a2_lo = _mm_add_epi16(f9_lo, sixty_three); // Filter * 9 + 63
+ const __m128i a2_hi = _mm_add_epi16(f9_hi, sixty_three); // Filter * 9 + 63
+
+ const __m128i a1_lo = _mm_add_epi16(f18_lo, sixty_three); // F... * 18 + 63
+ const __m128i a1_hi = _mm_add_epi16(f18_hi, sixty_three); // F... * 18 + 63
+
+ const __m128i a0_lo = _mm_add_epi16(f18_lo, a2_lo); // Filter * 27 + 63
+ const __m128i a0_hi = _mm_add_epi16(f18_hi, a2_hi); // Filter * 27 + 63
+
+ UPDATE_2PIXELS(*p2, *q2, a2_lo, a2_hi);
+ UPDATE_2PIXELS(*p1, *q1, a1_lo, a1_hi);
+ UPDATE_2PIXELS(*p0, *q0, a0_lo, a0_hi);
+ }
+
+ // unoffset
+ FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1);
+ FLIP_SIGN_BIT2(*p2, *q2);
+}
+
+// reads 8 rows across a vertical edge.
+//
+// TODO(somnath): Investigate _mm_shuffle* also see if it can be broken into
+// two Load4x4() to avoid code duplication.
+static WEBP_INLINE void Load8x4(const uint8_t* b, int stride,
+ __m128i* p, __m128i* q) {
+ __m128i t1, t2;
+
+ // Load 0th, 1st, 4th and 5th rows
+ __m128i r0 = _mm_cvtsi32_si128(*((int*)&b[0 * stride])); // 03 02 01 00
+ __m128i r1 = _mm_cvtsi32_si128(*((int*)&b[1 * stride])); // 13 12 11 10
+ __m128i r4 = _mm_cvtsi32_si128(*((int*)&b[4 * stride])); // 43 42 41 40
+ __m128i r5 = _mm_cvtsi32_si128(*((int*)&b[5 * stride])); // 53 52 51 50
+
+ r0 = _mm_unpacklo_epi32(r0, r4); // 43 42 41 40 03 02 01 00
+ r1 = _mm_unpacklo_epi32(r1, r5); // 53 52 51 50 13 12 11 10
+
+ // t1 = 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00
+ t1 = _mm_unpacklo_epi8(r0, r1);
+
+ // Load 2nd, 3rd, 6th and 7th rows
+ r0 = _mm_cvtsi32_si128(*((int*)&b[2 * stride])); // 23 22 21 22
+ r1 = _mm_cvtsi32_si128(*((int*)&b[3 * stride])); // 33 32 31 30
+ r4 = _mm_cvtsi32_si128(*((int*)&b[6 * stride])); // 63 62 61 60
+ r5 = _mm_cvtsi32_si128(*((int*)&b[7 * stride])); // 73 72 71 70
+
+ r0 = _mm_unpacklo_epi32(r0, r4); // 63 62 61 60 23 22 21 20
+ r1 = _mm_unpacklo_epi32(r1, r5); // 73 72 71 70 33 32 31 30
+
+ // t2 = 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20
+ t2 = _mm_unpacklo_epi8(r0, r1);
+
+ // t1 = 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00
+ // t2 = 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40
+ r0 = t1;
+ t1 = _mm_unpacklo_epi16(t1, t2);
+ t2 = _mm_unpackhi_epi16(r0, t2);
+
+ // *p = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
+ // *q = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
+ *p = _mm_unpacklo_epi32(t1, t2);
+ *q = _mm_unpackhi_epi32(t1, t2);
+}
+
+static WEBP_INLINE void Load16x4(const uint8_t* r0, const uint8_t* r8,
+ int stride,
+ __m128i* p1, __m128i* p0,
+ __m128i* q0, __m128i* q1) {
+ __m128i t1, t2;
+ // Assume the pixels around the edge (|) are numbered as follows
+ // 00 01 | 02 03
+ // 10 11 | 12 13
+ // ... | ...
+ // e0 e1 | e2 e3
+ // f0 f1 | f2 f3
+ //
+ // r0 is pointing to the 0th row (00)
+ // r8 is pointing to the 8th row (80)
+
+ // Load
+ // p1 = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
+ // q0 = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
+ // p0 = f1 e1 d1 c1 b1 a1 91 81 f0 e0 d0 c0 b0 a0 90 80
+ // q1 = f3 e3 d3 c3 b3 a3 93 83 f2 e2 d2 c2 b2 a2 92 82
+ Load8x4(r0, stride, p1, q0);
+ Load8x4(r8, stride, p0, q1);
+
+ t1 = *p1;
+ t2 = *q0;
+ // p1 = f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
+ // p0 = f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01
+ // q0 = f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+ // q1 = f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
+ *p1 = _mm_unpacklo_epi64(t1, *p0);
+ *p0 = _mm_unpackhi_epi64(t1, *p0);
+ *q0 = _mm_unpacklo_epi64(t2, *q1);
+ *q1 = _mm_unpackhi_epi64(t2, *q1);
+}
+
+static WEBP_INLINE void Store4x4(__m128i* x, uint8_t* dst, int stride) {
+ int i;
+ for (i = 0; i < 4; ++i, dst += stride) {
+ *((int32_t*)dst) = _mm_cvtsi128_si32(*x);
+ *x = _mm_srli_si128(*x, 4);
+ }
+}
+
+// Transpose back and store
+static WEBP_INLINE void Store16x4(uint8_t* r0, uint8_t* r8, int stride,
+ __m128i* p1, __m128i* p0,
+ __m128i* q0, __m128i* q1) {
+ __m128i t1;
+
+ // p0 = 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00
+ // p1 = f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80
+ t1 = *p0;
+ *p0 = _mm_unpacklo_epi8(*p1, t1);
+ *p1 = _mm_unpackhi_epi8(*p1, t1);
+
+ // q0 = 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02
+ // q1 = f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82
+ t1 = *q0;
+ *q0 = _mm_unpacklo_epi8(t1, *q1);
+ *q1 = _mm_unpackhi_epi8(t1, *q1);
+
+ // p0 = 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00
+ // q0 = 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40
+ t1 = *p0;
+ *p0 = _mm_unpacklo_epi16(t1, *q0);
+ *q0 = _mm_unpackhi_epi16(t1, *q0);
+
+ // p1 = b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80
+ // q1 = f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0
+ t1 = *p1;
+ *p1 = _mm_unpacklo_epi16(t1, *q1);
+ *q1 = _mm_unpackhi_epi16(t1, *q1);
+
+ Store4x4(p0, r0, stride);
+ r0 += 4 * stride;
+ Store4x4(q0, r0, stride);
+
+ Store4x4(p1, r8, stride);
+ r8 += 4 * stride;
+ Store4x4(q1, r8, stride);
+}
+
+//------------------------------------------------------------------------------
+// Simple In-loop filtering (Paragraph 15.2)
+
+static void SimpleVFilter16SSE2(uint8_t* p, int stride, int thresh) {
+ // Load
+ __m128i p1 = _mm_loadu_si128((__m128i*)&p[-2 * stride]);
+ __m128i p0 = _mm_loadu_si128((__m128i*)&p[-stride]);
+ __m128i q0 = _mm_loadu_si128((__m128i*)&p[0]);
+ __m128i q1 = _mm_loadu_si128((__m128i*)&p[stride]);
+
+ DoFilter2(&p1, &p0, &q0, &q1, thresh);
+
+ // Store
+ _mm_storeu_si128((__m128i*)&p[-stride], p0);
+ _mm_storeu_si128((__m128i*)p, q0);
+}
+
+static void SimpleHFilter16SSE2(uint8_t* p, int stride, int thresh) {
+ __m128i p1, p0, q0, q1;
+
+ p -= 2; // beginning of p1
+
+ Load16x4(p, p + 8 * stride, stride, &p1, &p0, &q0, &q1);
+ DoFilter2(&p1, &p0, &q0, &q1, thresh);
+ Store16x4(p, p + 8 * stride, stride, &p1, &p0, &q0, &q1);
+}
+
+static void SimpleVFilter16iSSE2(uint8_t* p, int stride, int thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4 * stride;
+ SimpleVFilter16SSE2(p, stride, thresh);
+ }
+}
+
+static void SimpleHFilter16iSSE2(uint8_t* p, int stride, int thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4;
+ SimpleHFilter16SSE2(p, stride, thresh);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Complex In-loop filtering (Paragraph 15.3)
+
+#define MAX_DIFF1(p3, p2, p1, p0, m) { \
+ m = MM_ABS(p3, p2); \
+ m = _mm_max_epu8(m, MM_ABS(p2, p1)); \
+ m = _mm_max_epu8(m, MM_ABS(p1, p0)); \
+}
+
+#define MAX_DIFF2(p3, p2, p1, p0, m) { \
+ m = _mm_max_epu8(m, MM_ABS(p3, p2)); \
+ m = _mm_max_epu8(m, MM_ABS(p2, p1)); \
+ m = _mm_max_epu8(m, MM_ABS(p1, p0)); \
+}
+
+#define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) { \
+ e1 = _mm_loadu_si128((__m128i*)&(p)[0 * stride]); \
+ e2 = _mm_loadu_si128((__m128i*)&(p)[1 * stride]); \
+ e3 = _mm_loadu_si128((__m128i*)&(p)[2 * stride]); \
+ e4 = _mm_loadu_si128((__m128i*)&(p)[3 * stride]); \
+}
+
+#define LOADUV_H_EDGE(p, u, v, stride) { \
+ p = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \
+ p = _mm_unpacklo_epi64(p, _mm_loadl_epi64((__m128i*)&(v)[(stride)])); \
+}
+
+#define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) { \
+ LOADUV_H_EDGE(e1, u, v, 0 * stride); \
+ LOADUV_H_EDGE(e2, u, v, 1 * stride); \
+ LOADUV_H_EDGE(e3, u, v, 2 * stride); \
+ LOADUV_H_EDGE(e4, u, v, 3 * stride); \
+}
+
+#define STOREUV(p, u, v, stride) { \
+ _mm_storel_epi64((__m128i*)&u[(stride)], p); \
+ p = _mm_srli_si128(p, 8); \
+ _mm_storel_epi64((__m128i*)&v[(stride)], p); \
+}
+
+#define COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask) { \
+ __m128i fl_yes; \
+ const __m128i it = _mm_set1_epi8(ithresh); \
+ mask = _mm_subs_epu8(mask, it); \
+ mask = _mm_cmpeq_epi8(mask, _mm_setzero_si128()); \
+ NeedsFilter(&p1, &p0, &q0, &q1, thresh, &fl_yes); \
+ mask = _mm_and_si128(mask, fl_yes); \
+}
+
+// on macroblock edges
+static void VFilter16SSE2(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ __m128i t1;
+ __m128i mask;
+ __m128i p2, p1, p0, q0, q1, q2;
+
+ // Load p3, p2, p1, p0
+ LOAD_H_EDGES4(p - 4 * stride, stride, t1, p2, p1, p0);
+ MAX_DIFF1(t1, p2, p1, p0, mask);
+
+ // Load q0, q1, q2, q3
+ LOAD_H_EDGES4(p, stride, q0, q1, q2, t1);
+ MAX_DIFF2(t1, q2, q1, q0, mask);
+
+ COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
+ DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
+
+ // Store
+ _mm_storeu_si128((__m128i*)&p[-3 * stride], p2);
+ _mm_storeu_si128((__m128i*)&p[-2 * stride], p1);
+ _mm_storeu_si128((__m128i*)&p[-1 * stride], p0);
+ _mm_storeu_si128((__m128i*)&p[0 * stride], q0);
+ _mm_storeu_si128((__m128i*)&p[1 * stride], q1);
+ _mm_storeu_si128((__m128i*)&p[2 * stride], q2);
+}
+
+static void HFilter16SSE2(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ __m128i mask;
+ __m128i p3, p2, p1, p0, q0, q1, q2, q3;
+
+ uint8_t* const b = p - 4;
+ Load16x4(b, b + 8 * stride, stride, &p3, &p2, &p1, &p0); // p3, p2, p1, p0
+ MAX_DIFF1(p3, p2, p1, p0, mask);
+
+ Load16x4(p, p + 8 * stride, stride, &q0, &q1, &q2, &q3); // q0, q1, q2, q3
+ MAX_DIFF2(q3, q2, q1, q0, mask);
+
+ COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
+ DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
+
+ Store16x4(b, b + 8 * stride, stride, &p3, &p2, &p1, &p0);
+ Store16x4(p, p + 8 * stride, stride, &q0, &q1, &q2, &q3);
+}
+
+// on three inner edges
+static void VFilter16iSSE2(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ int k;
+ __m128i mask;
+ __m128i t1, t2, p1, p0, q0, q1;
+
+ for (k = 3; k > 0; --k) {
+ // Load p3, p2, p1, p0
+ LOAD_H_EDGES4(p, stride, t2, t1, p1, p0);
+ MAX_DIFF1(t2, t1, p1, p0, mask);
+
+ p += 4 * stride;
+
+ // Load q0, q1, q2, q3
+ LOAD_H_EDGES4(p, stride, q0, q1, t1, t2);
+ MAX_DIFF2(t2, t1, q1, q0, mask);
+
+ COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
+ DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh);
+
+ // Store
+ _mm_storeu_si128((__m128i*)&p[-2 * stride], p1);
+ _mm_storeu_si128((__m128i*)&p[-1 * stride], p0);
+ _mm_storeu_si128((__m128i*)&p[0 * stride], q0);
+ _mm_storeu_si128((__m128i*)&p[1 * stride], q1);
+ }
+}
+
+static void HFilter16iSSE2(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ int k;
+ uint8_t* b;
+ __m128i mask;
+ __m128i t1, t2, p1, p0, q0, q1;
+
+ for (k = 3; k > 0; --k) {
+ b = p;
+ Load16x4(b, b + 8 * stride, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0
+ MAX_DIFF1(t2, t1, p1, p0, mask);
+
+ b += 4; // beginning of q0
+ Load16x4(b, b + 8 * stride, stride, &q0, &q1, &t1, &t2); // q0, q1, q2, q3
+ MAX_DIFF2(t2, t1, q1, q0, mask);
+
+ COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
+ DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh);
+
+ b -= 2; // beginning of p1
+ Store16x4(b, b + 8 * stride, stride, &p1, &p0, &q0, &q1);
+
+ p += 4;
+ }
+}
+
+// 8-pixels wide variant, for chroma filtering
+static void VFilter8SSE2(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ __m128i mask;
+ __m128i t1, p2, p1, p0, q0, q1, q2;
+
+ // Load p3, p2, p1, p0
+ LOADUV_H_EDGES4(u - 4 * stride, v - 4 * stride, stride, t1, p2, p1, p0);
+ MAX_DIFF1(t1, p2, p1, p0, mask);
+
+ // Load q0, q1, q2, q3
+ LOADUV_H_EDGES4(u, v, stride, q0, q1, q2, t1);
+ MAX_DIFF2(t1, q2, q1, q0, mask);
+
+ COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
+ DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
+
+ // Store
+ STOREUV(p2, u, v, -3 * stride);
+ STOREUV(p1, u, v, -2 * stride);
+ STOREUV(p0, u, v, -1 * stride);
+ STOREUV(q0, u, v, 0 * stride);
+ STOREUV(q1, u, v, 1 * stride);
+ STOREUV(q2, u, v, 2 * stride);
+}
+
+static void HFilter8SSE2(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ __m128i mask;
+ __m128i p3, p2, p1, p0, q0, q1, q2, q3;
+
+ uint8_t* const tu = u - 4;
+ uint8_t* const tv = v - 4;
+ Load16x4(tu, tv, stride, &p3, &p2, &p1, &p0); // p3, p2, p1, p0
+ MAX_DIFF1(p3, p2, p1, p0, mask);
+
+ Load16x4(u, v, stride, &q0, &q1, &q2, &q3); // q0, q1, q2, q3
+ MAX_DIFF2(q3, q2, q1, q0, mask);
+
+ COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
+ DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
+
+ Store16x4(tu, tv, stride, &p3, &p2, &p1, &p0);
+ Store16x4(u, v, stride, &q0, &q1, &q2, &q3);
+}
+
+static void VFilter8iSSE2(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ __m128i mask;
+ __m128i t1, t2, p1, p0, q0, q1;
+
+ // Load p3, p2, p1, p0
+ LOADUV_H_EDGES4(u, v, stride, t2, t1, p1, p0);
+ MAX_DIFF1(t2, t1, p1, p0, mask);
+
+ u += 4 * stride;
+ v += 4 * stride;
+
+ // Load q0, q1, q2, q3
+ LOADUV_H_EDGES4(u, v, stride, q0, q1, t1, t2);
+ MAX_DIFF2(t2, t1, q1, q0, mask);
+
+ COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
+ DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh);
+
+ // Store
+ STOREUV(p1, u, v, -2 * stride);
+ STOREUV(p0, u, v, -1 * stride);
+ STOREUV(q0, u, v, 0 * stride);
+ STOREUV(q1, u, v, 1 * stride);
+}
+
+static void HFilter8iSSE2(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ __m128i mask;
+ __m128i t1, t2, p1, p0, q0, q1;
+ Load16x4(u, v, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0
+ MAX_DIFF1(t2, t1, p1, p0, mask);
+
+ u += 4; // beginning of q0
+ v += 4;
+ Load16x4(u, v, stride, &q0, &q1, &t1, &t2); // q0, q1, q2, q3
+ MAX_DIFF2(t2, t1, q1, q0, mask);
+
+ COMPLEX_FL_MASK(p1, p0, q0, q1, thresh, ithresh, mask);
+ DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh);
+
+ u -= 2; // beginning of p1
+ v -= 2;
+ Store16x4(u, v, stride, &p1, &p0, &q0, &q1);
+}
+
+extern void VP8DspInitSSE2(void);
+
+void VP8DspInitSSE2(void) {
+ VP8Transform = TransformSSE2;
+
+ VP8VFilter16 = VFilter16SSE2;
+ VP8HFilter16 = HFilter16SSE2;
+ VP8VFilter8 = VFilter8SSE2;
+ VP8HFilter8 = HFilter8SSE2;
+ VP8VFilter16i = VFilter16iSSE2;
+ VP8HFilter16i = HFilter16iSSE2;
+ VP8VFilter8i = VFilter8iSSE2;
+ VP8HFilter8i = HFilter8iSSE2;
+
+ VP8SimpleVFilter16 = SimpleVFilter16SSE2;
+ VP8SimpleHFilter16 = SimpleHFilter16SSE2;
+ VP8SimpleVFilter16i = SimpleVFilter16iSSE2;
+ VP8SimpleHFilter16i = SimpleHFilter16iSSE2;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif // WEBP_USE_SSE2
diff --git a/drivers/webpold/dsp/dsp.h b/drivers/webpold/dsp/dsp.h
new file mode 100644
index 0000000000..fd686a8532
--- /dev/null
+++ b/drivers/webpold/dsp/dsp.h
@@ -0,0 +1,210 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Speed-critical functions.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_DSP_DSP_H_
+#define WEBP_DSP_DSP_H_
+
+#include "../types.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// CPU detection
+
+#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
+#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets
+#endif
+
+#if defined(__SSE2__) || defined(WEBP_MSC_SSE2)
+#define WEBP_USE_SSE2
+#endif
+
+#if defined(__ANDROID__) && defined(__ARM_ARCH_7A__) && defined(__ARM_NEON__)
+#define WEBP_ANDROID_NEON // Android targets that might support NEON
+#endif
+
+#if ( (defined(__ARM_NEON__) && !defined(__aarch64__)) || defined(WEBP_ANDROID_NEON)) && !defined(PSP2_ENABLED)
+#define WEBP_USE_NEON
+#endif
+
+typedef enum {
+ kSSE2,
+ kSSE3,
+ kNEON
+} CPUFeature;
+// returns true if the CPU supports the feature.
+typedef int (*VP8CPUInfo)(CPUFeature feature);
+extern VP8CPUInfo VP8GetCPUInfo;
+
+//------------------------------------------------------------------------------
+// Encoding
+
+int VP8GetAlpha(const int histo[]);
+
+// Transforms
+// VP8Idct: Does one of two inverse transforms. If do_two is set, the transforms
+// will be done for (ref, in, dst) and (ref + 4, in + 16, dst + 4).
+typedef void (*VP8Idct)(const uint8_t* ref, const int16_t* in, uint8_t* dst,
+ int do_two);
+typedef void (*VP8Fdct)(const uint8_t* src, const uint8_t* ref, int16_t* out);
+typedef void (*VP8WHT)(const int16_t* in, int16_t* out);
+extern VP8Idct VP8ITransform;
+extern VP8Fdct VP8FTransform;
+extern VP8WHT VP8ITransformWHT;
+extern VP8WHT VP8FTransformWHT;
+// Predictions
+// *dst is the destination block. *top and *left can be NULL.
+typedef void (*VP8IntraPreds)(uint8_t *dst, const uint8_t* left,
+ const uint8_t* top);
+typedef void (*VP8Intra4Preds)(uint8_t *dst, const uint8_t* top);
+extern VP8Intra4Preds VP8EncPredLuma4;
+extern VP8IntraPreds VP8EncPredLuma16;
+extern VP8IntraPreds VP8EncPredChroma8;
+
+typedef int (*VP8Metric)(const uint8_t* pix, const uint8_t* ref);
+extern VP8Metric VP8SSE16x16, VP8SSE16x8, VP8SSE8x8, VP8SSE4x4;
+typedef int (*VP8WMetric)(const uint8_t* pix, const uint8_t* ref,
+ const uint16_t* const weights);
+extern VP8WMetric VP8TDisto4x4, VP8TDisto16x16;
+
+typedef void (*VP8BlockCopy)(const uint8_t* src, uint8_t* dst);
+extern VP8BlockCopy VP8Copy4x4;
+// Quantization
+struct VP8Matrix; // forward declaration
+typedef int (*VP8QuantizeBlock)(int16_t in[16], int16_t out[16],
+ int n, const struct VP8Matrix* const mtx);
+extern VP8QuantizeBlock VP8EncQuantizeBlock;
+
+// Compute susceptibility based on DCT-coeff histograms:
+// the higher, the "easier" the macroblock is to compress.
+typedef int (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred,
+ int start_block, int end_block);
+extern const int VP8DspScan[16 + 4 + 4];
+extern VP8CHisto VP8CollectHistogram;
+
+void VP8EncDspInit(void); // must be called before using any of the above
+
+//------------------------------------------------------------------------------
+// Decoding
+
+typedef void (*VP8DecIdct)(const int16_t* coeffs, uint8_t* dst);
+// when doing two transforms, coeffs is actually int16_t[2][16].
+typedef void (*VP8DecIdct2)(const int16_t* coeffs, uint8_t* dst, int do_two);
+extern VP8DecIdct2 VP8Transform;
+extern VP8DecIdct VP8TransformUV;
+extern VP8DecIdct VP8TransformDC;
+extern VP8DecIdct VP8TransformDCUV;
+extern void (*VP8TransformWHT)(const int16_t* in, int16_t* out);
+
+// *dst is the destination block, with stride BPS. Boundary samples are
+// assumed accessible when needed.
+typedef void (*VP8PredFunc)(uint8_t* dst);
+extern const VP8PredFunc VP8PredLuma16[/* NUM_B_DC_MODES */];
+extern const VP8PredFunc VP8PredChroma8[/* NUM_B_DC_MODES */];
+extern const VP8PredFunc VP8PredLuma4[/* NUM_BMODES */];
+
+// simple filter (only for luma)
+typedef void (*VP8SimpleFilterFunc)(uint8_t* p, int stride, int thresh);
+extern VP8SimpleFilterFunc VP8SimpleVFilter16;
+extern VP8SimpleFilterFunc VP8SimpleHFilter16;
+extern VP8SimpleFilterFunc VP8SimpleVFilter16i; // filter 3 inner edges
+extern VP8SimpleFilterFunc VP8SimpleHFilter16i;
+
+// regular filter (on both macroblock edges and inner edges)
+typedef void (*VP8LumaFilterFunc)(uint8_t* luma, int stride,
+ int thresh, int ithresh, int hev_t);
+typedef void (*VP8ChromaFilterFunc)(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_t);
+// on outer edge
+extern VP8LumaFilterFunc VP8VFilter16;
+extern VP8LumaFilterFunc VP8HFilter16;
+extern VP8ChromaFilterFunc VP8VFilter8;
+extern VP8ChromaFilterFunc VP8HFilter8;
+
+// on inner edge
+extern VP8LumaFilterFunc VP8VFilter16i; // filtering 3 inner edges altogether
+extern VP8LumaFilterFunc VP8HFilter16i;
+extern VP8ChromaFilterFunc VP8VFilter8i; // filtering u and v altogether
+extern VP8ChromaFilterFunc VP8HFilter8i;
+
+// must be called before anything using the above
+void VP8DspInit(void);
+
+//------------------------------------------------------------------------------
+// WebP I/O
+
+#define FANCY_UPSAMPLING // undefined to remove fancy upsampling support
+
+typedef void (*WebPUpsampleLinePairFunc)(
+ const uint8_t* top_y, const uint8_t* bottom_y,
+ const uint8_t* top_u, const uint8_t* top_v,
+ const uint8_t* cur_u, const uint8_t* cur_v,
+ uint8_t* top_dst, uint8_t* bottom_dst, int len);
+
+#ifdef FANCY_UPSAMPLING
+
+// Fancy upsampling functions to convert YUV to RGB(A) modes
+extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
+
+// Initializes SSE2 version of the fancy upsamplers.
+void WebPInitUpsamplersSSE2(void);
+
+#endif // FANCY_UPSAMPLING
+
+// Point-sampling methods.
+typedef void (*WebPSampleLinePairFunc)(
+ const uint8_t* top_y, const uint8_t* bottom_y,
+ const uint8_t* u, const uint8_t* v,
+ uint8_t* top_dst, uint8_t* bottom_dst, int len);
+
+extern const WebPSampleLinePairFunc WebPSamplers[/* MODE_LAST */];
+
+// General function for converting two lines of ARGB or RGBA.
+// 'alpha_is_last' should be true if 0xff000000 is stored in memory as
+// as 0x00, 0x00, 0x00, 0xff (little endian).
+WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last);
+
+// YUV444->RGB converters
+typedef void (*WebPYUV444Converter)(const uint8_t* y,
+ const uint8_t* u, const uint8_t* v,
+ uint8_t* dst, int len);
+
+extern const WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */];
+
+// Main function to be called
+void WebPInitUpsamplers(void);
+
+//------------------------------------------------------------------------------
+// Pre-multiply planes with alpha values
+
+// Apply alpha pre-multiply on an rgba, bgra or argb plane of size w * h.
+// alpha_first should be 0 for argb, 1 for rgba or bgra (where alpha is last).
+extern void (*WebPApplyAlphaMultiply)(
+ uint8_t* rgba, int alpha_first, int w, int h, int stride);
+
+// Same, buf specifically for RGBA4444 format
+extern void (*WebPApplyAlphaMultiply4444)(
+ uint8_t* rgba4444, int w, int h, int stride);
+
+// To be called first before using the above.
+void WebPInitPremultiply(void);
+
+void WebPInitPremultiplySSE2(void); // should not be called directly.
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_DSP_DSP_H_ */
diff --git a/drivers/webpold/dsp/enc.c b/drivers/webpold/dsp/enc.c
new file mode 100644
index 0000000000..02234564be
--- /dev/null
+++ b/drivers/webpold/dsp/enc.c
@@ -0,0 +1,743 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Speed-critical encoding functions.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <stdlib.h> // for abs()
+#include "./dsp.h"
+#include "../enc/vp8enci.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Compute susceptibility based on DCT-coeff histograms:
+// the higher, the "easier" the macroblock is to compress.
+
+static int ClipAlpha(int alpha) {
+ return alpha < 0 ? 0 : alpha > 255 ? 255 : alpha;
+}
+
+int VP8GetAlpha(const int histo[MAX_COEFF_THRESH + 1]) {
+ int num = 0, den = 0, val = 0;
+ int k;
+ int alpha;
+ // note: changing this loop to avoid the numerous "k + 1" slows things down.
+ for (k = 0; k < MAX_COEFF_THRESH; ++k) {
+ if (histo[k + 1]) {
+ val += histo[k + 1];
+ num += val * (k + 1);
+ den += (k + 1) * (k + 1);
+ }
+ }
+ // we scale the value to a usable [0..255] range
+ alpha = den ? 10 * num / den - 5 : 0;
+ return ClipAlpha(alpha);
+}
+
+const int VP8DspScan[16 + 4 + 4] = {
+ // Luma
+ 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS,
+ 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS,
+ 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS,
+ 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS,
+
+ 0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U
+ 8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V
+};
+
+static int CollectHistogram(const uint8_t* ref, const uint8_t* pred,
+ int start_block, int end_block) {
+ int histo[MAX_COEFF_THRESH + 1] = { 0 };
+ int16_t out[16];
+ int j, k;
+ for (j = start_block; j < end_block; ++j) {
+ VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
+
+ // Convert coefficients to bin (within out[]).
+ for (k = 0; k < 16; ++k) {
+ const int v = abs(out[k]) >> 2;
+ out[k] = (v > MAX_COEFF_THRESH) ? MAX_COEFF_THRESH : v;
+ }
+
+ // Use bin to update histogram.
+ for (k = 0; k < 16; ++k) {
+ histo[out[k]]++;
+ }
+ }
+
+ return VP8GetAlpha(histo);
+}
+
+//------------------------------------------------------------------------------
+// run-time tables (~4k)
+
+static uint8_t clip1[255 + 510 + 1]; // clips [-255,510] to [0,255]
+
+// We declare this variable 'volatile' to prevent instruction reordering
+// and make sure it's set to true _last_ (so as to be thread-safe)
+static volatile int tables_ok = 0;
+
+static void InitTables(void) {
+ if (!tables_ok) {
+ int i;
+ for (i = -255; i <= 255 + 255; ++i) {
+ clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i;
+ }
+ tables_ok = 1;
+ }
+}
+
+static WEBP_INLINE uint8_t clip_8b(int v) {
+ return (!(v & ~0xff)) ? v : v < 0 ? 0 : 255;
+}
+
+//------------------------------------------------------------------------------
+// Transforms (Paragraph 14.4)
+
+#define STORE(x, y, v) \
+ dst[(x) + (y) * BPS] = clip_8b(ref[(x) + (y) * BPS] + ((v) >> 3))
+
+static const int kC1 = 20091 + (1 << 16);
+static const int kC2 = 35468;
+#define MUL(a, b) (((a) * (b)) >> 16)
+
+static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in,
+ uint8_t* dst) {
+ int C[4 * 4], *tmp;
+ int i;
+ tmp = C;
+ for (i = 0; i < 4; ++i) { // vertical pass
+ const int a = in[0] + in[8];
+ const int b = in[0] - in[8];
+ const int c = MUL(in[4], kC2) - MUL(in[12], kC1);
+ const int d = MUL(in[4], kC1) + MUL(in[12], kC2);
+ tmp[0] = a + d;
+ tmp[1] = b + c;
+ tmp[2] = b - c;
+ tmp[3] = a - d;
+ tmp += 4;
+ in++;
+ }
+
+ tmp = C;
+ for (i = 0; i < 4; ++i) { // horizontal pass
+ const int dc = tmp[0] + 4;
+ const int a = dc + tmp[8];
+ const int b = dc - tmp[8];
+ const int c = MUL(tmp[4], kC2) - MUL(tmp[12], kC1);
+ const int d = MUL(tmp[4], kC1) + MUL(tmp[12], kC2);
+ STORE(0, i, a + d);
+ STORE(1, i, b + c);
+ STORE(2, i, b - c);
+ STORE(3, i, a - d);
+ tmp++;
+ }
+}
+
+static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst,
+ int do_two) {
+ ITransformOne(ref, in, dst);
+ if (do_two) {
+ ITransformOne(ref + 4, in + 16, dst + 4);
+ }
+}
+
+static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) {
+ int i;
+ int tmp[16];
+ for (i = 0; i < 4; ++i, src += BPS, ref += BPS) {
+ const int d0 = src[0] - ref[0];
+ const int d1 = src[1] - ref[1];
+ const int d2 = src[2] - ref[2];
+ const int d3 = src[3] - ref[3];
+ const int a0 = (d0 + d3) << 3;
+ const int a1 = (d1 + d2) << 3;
+ const int a2 = (d1 - d2) << 3;
+ const int a3 = (d0 - d3) << 3;
+ tmp[0 + i * 4] = (a0 + a1);
+ tmp[1 + i * 4] = (a2 * 2217 + a3 * 5352 + 14500) >> 12;
+ tmp[2 + i * 4] = (a0 - a1);
+ tmp[3 + i * 4] = (a3 * 2217 - a2 * 5352 + 7500) >> 12;
+ }
+ for (i = 0; i < 4; ++i) {
+ const int a0 = (tmp[0 + i] + tmp[12 + i]);
+ const int a1 = (tmp[4 + i] + tmp[ 8 + i]);
+ const int a2 = (tmp[4 + i] - tmp[ 8 + i]);
+ const int a3 = (tmp[0 + i] - tmp[12 + i]);
+ out[0 + i] = (a0 + a1 + 7) >> 4;
+ out[4 + i] = ((a2 * 2217 + a3 * 5352 + 12000) >> 16) + (a3 != 0);
+ out[8 + i] = (a0 - a1 + 7) >> 4;
+ out[12+ i] = ((a3 * 2217 - a2 * 5352 + 51000) >> 16);
+ }
+}
+
+static void ITransformWHT(const int16_t* in, int16_t* out) {
+ int tmp[16];
+ int i;
+ for (i = 0; i < 4; ++i) {
+ const int a0 = in[0 + i] + in[12 + i];
+ const int a1 = in[4 + i] + in[ 8 + i];
+ const int a2 = in[4 + i] - in[ 8 + i];
+ const int a3 = in[0 + i] - in[12 + i];
+ tmp[0 + i] = a0 + a1;
+ tmp[8 + i] = a0 - a1;
+ tmp[4 + i] = a3 + a2;
+ tmp[12 + i] = a3 - a2;
+ }
+ for (i = 0; i < 4; ++i) {
+ const int dc = tmp[0 + i * 4] + 3; // w/ rounder
+ const int a0 = dc + tmp[3 + i * 4];
+ const int a1 = tmp[1 + i * 4] + tmp[2 + i * 4];
+ const int a2 = tmp[1 + i * 4] - tmp[2 + i * 4];
+ const int a3 = dc - tmp[3 + i * 4];
+ out[ 0] = (a0 + a1) >> 3;
+ out[16] = (a3 + a2) >> 3;
+ out[32] = (a0 - a1) >> 3;
+ out[48] = (a3 - a2) >> 3;
+ out += 64;
+ }
+}
+
+static void FTransformWHT(const int16_t* in, int16_t* out) {
+ int tmp[16];
+ int i;
+ for (i = 0; i < 4; ++i, in += 64) {
+ const int a0 = (in[0 * 16] + in[2 * 16]) << 2;
+ const int a1 = (in[1 * 16] + in[3 * 16]) << 2;
+ const int a2 = (in[1 * 16] - in[3 * 16]) << 2;
+ const int a3 = (in[0 * 16] - in[2 * 16]) << 2;
+ tmp[0 + i * 4] = (a0 + a1) + (a0 != 0);
+ tmp[1 + i * 4] = a3 + a2;
+ tmp[2 + i * 4] = a3 - a2;
+ tmp[3 + i * 4] = a0 - a1;
+ }
+ for (i = 0; i < 4; ++i) {
+ const int a0 = (tmp[0 + i] + tmp[8 + i]);
+ const int a1 = (tmp[4 + i] + tmp[12+ i]);
+ const int a2 = (tmp[4 + i] - tmp[12+ i]);
+ const int a3 = (tmp[0 + i] - tmp[8 + i]);
+ const int b0 = a0 + a1;
+ const int b1 = a3 + a2;
+ const int b2 = a3 - a2;
+ const int b3 = a0 - a1;
+ out[ 0 + i] = (b0 + (b0 > 0) + 3) >> 3;
+ out[ 4 + i] = (b1 + (b1 > 0) + 3) >> 3;
+ out[ 8 + i] = (b2 + (b2 > 0) + 3) >> 3;
+ out[12 + i] = (b3 + (b3 > 0) + 3) >> 3;
+ }
+}
+
+#undef MUL
+#undef STORE
+
+//------------------------------------------------------------------------------
+// Intra predictions
+
+#define DST(x, y) dst[(x) + (y) * BPS]
+
+static WEBP_INLINE void Fill(uint8_t* dst, int value, int size) {
+ int j;
+ for (j = 0; j < size; ++j) {
+ memset(dst + j * BPS, value, size);
+ }
+}
+
+static WEBP_INLINE void VerticalPred(uint8_t* dst,
+ const uint8_t* top, int size) {
+ int j;
+ if (top) {
+ for (j = 0; j < size; ++j) memcpy(dst + j * BPS, top, size);
+ } else {
+ Fill(dst, 127, size);
+ }
+}
+
+static WEBP_INLINE void HorizontalPred(uint8_t* dst,
+ const uint8_t* left, int size) {
+ if (left) {
+ int j;
+ for (j = 0; j < size; ++j) {
+ memset(dst + j * BPS, left[j], size);
+ }
+ } else {
+ Fill(dst, 129, size);
+ }
+}
+
+static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top, int size) {
+ int y;
+ if (left) {
+ if (top) {
+ const uint8_t* const clip = clip1 + 255 - left[-1];
+ for (y = 0; y < size; ++y) {
+ const uint8_t* const clip_table = clip + left[y];
+ int x;
+ for (x = 0; x < size; ++x) {
+ dst[x] = clip_table[top[x]];
+ }
+ dst += BPS;
+ }
+ } else {
+ HorizontalPred(dst, left, size);
+ }
+ } else {
+ // true motion without left samples (hence: with default 129 value)
+ // is equivalent to VE prediction where you just copy the top samples.
+ // Note that if top samples are not available, the default value is
+ // then 129, and not 127 as in the VerticalPred case.
+ if (top) {
+ VerticalPred(dst, top, size);
+ } else {
+ Fill(dst, 129, size);
+ }
+ }
+}
+
+static WEBP_INLINE void DCMode(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top,
+ int size, int round, int shift) {
+ int DC = 0;
+ int j;
+ if (top) {
+ for (j = 0; j < size; ++j) DC += top[j];
+ if (left) { // top and left present
+ for (j = 0; j < size; ++j) DC += left[j];
+ } else { // top, but no left
+ DC += DC;
+ }
+ DC = (DC + round) >> shift;
+ } else if (left) { // left but no top
+ for (j = 0; j < size; ++j) DC += left[j];
+ DC += DC;
+ DC = (DC + round) >> shift;
+ } else { // no top, no left, nothing.
+ DC = 0x80;
+ }
+ Fill(dst, DC, size);
+}
+
+//------------------------------------------------------------------------------
+// Chroma 8x8 prediction (paragraph 12.2)
+
+static void IntraChromaPreds(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top) {
+ // U block
+ DCMode(C8DC8 + dst, left, top, 8, 8, 4);
+ VerticalPred(C8VE8 + dst, top, 8);
+ HorizontalPred(C8HE8 + dst, left, 8);
+ TrueMotion(C8TM8 + dst, left, top, 8);
+ // V block
+ dst += 8;
+ if (top) top += 8;
+ if (left) left += 16;
+ DCMode(C8DC8 + dst, left, top, 8, 8, 4);
+ VerticalPred(C8VE8 + dst, top, 8);
+ HorizontalPred(C8HE8 + dst, left, 8);
+ TrueMotion(C8TM8 + dst, left, top, 8);
+}
+
+//------------------------------------------------------------------------------
+// luma 16x16 prediction (paragraph 12.3)
+
+static void Intra16Preds(uint8_t* dst,
+ const uint8_t* left, const uint8_t* top) {
+ DCMode(I16DC16 + dst, left, top, 16, 16, 5);
+ VerticalPred(I16VE16 + dst, top, 16);
+ HorizontalPred(I16HE16 + dst, left, 16);
+ TrueMotion(I16TM16 + dst, left, top, 16);
+}
+
+//------------------------------------------------------------------------------
+// luma 4x4 prediction
+
+#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2)
+#define AVG2(a, b) (((a) + (b) + 1) >> 1)
+
+static void VE4(uint8_t* dst, const uint8_t* top) { // vertical
+ const uint8_t vals[4] = {
+ AVG3(top[-1], top[0], top[1]),
+ AVG3(top[ 0], top[1], top[2]),
+ AVG3(top[ 1], top[2], top[3]),
+ AVG3(top[ 2], top[3], top[4])
+ };
+ int i;
+ for (i = 0; i < 4; ++i) {
+ memcpy(dst + i * BPS, vals, 4);
+ }
+}
+
+static void HE4(uint8_t* dst, const uint8_t* top) { // horizontal
+ const int X = top[-1];
+ const int I = top[-2];
+ const int J = top[-3];
+ const int K = top[-4];
+ const int L = top[-5];
+ *(uint32_t*)(dst + 0 * BPS) = 0x01010101U * AVG3(X, I, J);
+ *(uint32_t*)(dst + 1 * BPS) = 0x01010101U * AVG3(I, J, K);
+ *(uint32_t*)(dst + 2 * BPS) = 0x01010101U * AVG3(J, K, L);
+ *(uint32_t*)(dst + 3 * BPS) = 0x01010101U * AVG3(K, L, L);
+}
+
+static void DC4(uint8_t* dst, const uint8_t* top) {
+ uint32_t dc = 4;
+ int i;
+ for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i];
+ Fill(dst, dc >> 3, 4);
+}
+
+static void RD4(uint8_t* dst, const uint8_t* top) {
+ const int X = top[-1];
+ const int I = top[-2];
+ const int J = top[-3];
+ const int K = top[-4];
+ const int L = top[-5];
+ const int A = top[0];
+ const int B = top[1];
+ const int C = top[2];
+ const int D = top[3];
+ DST(0, 3) = AVG3(J, K, L);
+ DST(0, 2) = DST(1, 3) = AVG3(I, J, K);
+ DST(0, 1) = DST(1, 2) = DST(2, 3) = AVG3(X, I, J);
+ DST(0, 0) = DST(1, 1) = DST(2, 2) = DST(3, 3) = AVG3(A, X, I);
+ DST(1, 0) = DST(2, 1) = DST(3, 2) = AVG3(B, A, X);
+ DST(2, 0) = DST(3, 1) = AVG3(C, B, A);
+ DST(3, 0) = AVG3(D, C, B);
+}
+
+static void LD4(uint8_t* dst, const uint8_t* top) {
+ const int A = top[0];
+ const int B = top[1];
+ const int C = top[2];
+ const int D = top[3];
+ const int E = top[4];
+ const int F = top[5];
+ const int G = top[6];
+ const int H = top[7];
+ DST(0, 0) = AVG3(A, B, C);
+ DST(1, 0) = DST(0, 1) = AVG3(B, C, D);
+ DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E);
+ DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F);
+ DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G);
+ DST(3, 2) = DST(2, 3) = AVG3(F, G, H);
+ DST(3, 3) = AVG3(G, H, H);
+}
+
+static void VR4(uint8_t* dst, const uint8_t* top) {
+ const int X = top[-1];
+ const int I = top[-2];
+ const int J = top[-3];
+ const int K = top[-4];
+ const int A = top[0];
+ const int B = top[1];
+ const int C = top[2];
+ const int D = top[3];
+ DST(0, 0) = DST(1, 2) = AVG2(X, A);
+ DST(1, 0) = DST(2, 2) = AVG2(A, B);
+ DST(2, 0) = DST(3, 2) = AVG2(B, C);
+ DST(3, 0) = AVG2(C, D);
+
+ DST(0, 3) = AVG3(K, J, I);
+ DST(0, 2) = AVG3(J, I, X);
+ DST(0, 1) = DST(1, 3) = AVG3(I, X, A);
+ DST(1, 1) = DST(2, 3) = AVG3(X, A, B);
+ DST(2, 1) = DST(3, 3) = AVG3(A, B, C);
+ DST(3, 1) = AVG3(B, C, D);
+}
+
+static void VL4(uint8_t* dst, const uint8_t* top) {
+ const int A = top[0];
+ const int B = top[1];
+ const int C = top[2];
+ const int D = top[3];
+ const int E = top[4];
+ const int F = top[5];
+ const int G = top[6];
+ const int H = top[7];
+ DST(0, 0) = AVG2(A, B);
+ DST(1, 0) = DST(0, 2) = AVG2(B, C);
+ DST(2, 0) = DST(1, 2) = AVG2(C, D);
+ DST(3, 0) = DST(2, 2) = AVG2(D, E);
+
+ DST(0, 1) = AVG3(A, B, C);
+ DST(1, 1) = DST(0, 3) = AVG3(B, C, D);
+ DST(2, 1) = DST(1, 3) = AVG3(C, D, E);
+ DST(3, 1) = DST(2, 3) = AVG3(D, E, F);
+ DST(3, 2) = AVG3(E, F, G);
+ DST(3, 3) = AVG3(F, G, H);
+}
+
+static void HU4(uint8_t* dst, const uint8_t* top) {
+ const int I = top[-2];
+ const int J = top[-3];
+ const int K = top[-4];
+ const int L = top[-5];
+ DST(0, 0) = AVG2(I, J);
+ DST(2, 0) = DST(0, 1) = AVG2(J, K);
+ DST(2, 1) = DST(0, 2) = AVG2(K, L);
+ DST(1, 0) = AVG3(I, J, K);
+ DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
+ DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
+ DST(3, 2) = DST(2, 2) =
+ DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
+}
+
+static void HD4(uint8_t* dst, const uint8_t* top) {
+ const int X = top[-1];
+ const int I = top[-2];
+ const int J = top[-3];
+ const int K = top[-4];
+ const int L = top[-5];
+ const int A = top[0];
+ const int B = top[1];
+ const int C = top[2];
+
+ DST(0, 0) = DST(2, 1) = AVG2(I, X);
+ DST(0, 1) = DST(2, 2) = AVG2(J, I);
+ DST(0, 2) = DST(2, 3) = AVG2(K, J);
+ DST(0, 3) = AVG2(L, K);
+
+ DST(3, 0) = AVG3(A, B, C);
+ DST(2, 0) = AVG3(X, A, B);
+ DST(1, 0) = DST(3, 1) = AVG3(I, X, A);
+ DST(1, 1) = DST(3, 2) = AVG3(J, I, X);
+ DST(1, 2) = DST(3, 3) = AVG3(K, J, I);
+ DST(1, 3) = AVG3(L, K, J);
+}
+
+static void TM4(uint8_t* dst, const uint8_t* top) {
+ int x, y;
+ const uint8_t* const clip = clip1 + 255 - top[-1];
+ for (y = 0; y < 4; ++y) {
+ const uint8_t* const clip_table = clip + top[-2 - y];
+ for (x = 0; x < 4; ++x) {
+ dst[x] = clip_table[top[x]];
+ }
+ dst += BPS;
+ }
+}
+
+#undef DST
+#undef AVG3
+#undef AVG2
+
+// Left samples are top[-5 .. -2], top_left is top[-1], top are
+// located at top[0..3], and top right is top[4..7]
+static void Intra4Preds(uint8_t* dst, const uint8_t* top) {
+ DC4(I4DC4 + dst, top);
+ TM4(I4TM4 + dst, top);
+ VE4(I4VE4 + dst, top);
+ HE4(I4HE4 + dst, top);
+ RD4(I4RD4 + dst, top);
+ VR4(I4VR4 + dst, top);
+ LD4(I4LD4 + dst, top);
+ VL4(I4VL4 + dst, top);
+ HD4(I4HD4 + dst, top);
+ HU4(I4HU4 + dst, top);
+}
+
+//------------------------------------------------------------------------------
+// Metric
+
+static WEBP_INLINE int GetSSE(const uint8_t* a, const uint8_t* b,
+ int w, int h) {
+ int count = 0;
+ int y, x;
+ for (y = 0; y < h; ++y) {
+ for (x = 0; x < w; ++x) {
+ const int diff = (int)a[x] - b[x];
+ count += diff * diff;
+ }
+ a += BPS;
+ b += BPS;
+ }
+ return count;
+}
+
+static int SSE16x16(const uint8_t* a, const uint8_t* b) {
+ return GetSSE(a, b, 16, 16);
+}
+static int SSE16x8(const uint8_t* a, const uint8_t* b) {
+ return GetSSE(a, b, 16, 8);
+}
+static int SSE8x8(const uint8_t* a, const uint8_t* b) {
+ return GetSSE(a, b, 8, 8);
+}
+static int SSE4x4(const uint8_t* a, const uint8_t* b) {
+ return GetSSE(a, b, 4, 4);
+}
+
+//------------------------------------------------------------------------------
+// Texture distortion
+//
+// We try to match the spectral content (weighted) between source and
+// reconstructed samples.
+
+// Hadamard transform
+// Returns the weighted sum of the absolute value of transformed coefficients.
+static int TTransform(const uint8_t* in, const uint16_t* w) {
+ int sum = 0;
+ int tmp[16];
+ int i;
+ // horizontal pass
+ for (i = 0; i < 4; ++i, in += BPS) {
+ const int a0 = (in[0] + in[2]) << 2;
+ const int a1 = (in[1] + in[3]) << 2;
+ const int a2 = (in[1] - in[3]) << 2;
+ const int a3 = (in[0] - in[2]) << 2;
+ tmp[0 + i * 4] = a0 + a1 + (a0 != 0);
+ tmp[1 + i * 4] = a3 + a2;
+ tmp[2 + i * 4] = a3 - a2;
+ tmp[3 + i * 4] = a0 - a1;
+ }
+ // vertical pass
+ for (i = 0; i < 4; ++i, ++w) {
+ const int a0 = (tmp[0 + i] + tmp[8 + i]);
+ const int a1 = (tmp[4 + i] + tmp[12+ i]);
+ const int a2 = (tmp[4 + i] - tmp[12+ i]);
+ const int a3 = (tmp[0 + i] - tmp[8 + i]);
+ const int b0 = a0 + a1;
+ const int b1 = a3 + a2;
+ const int b2 = a3 - a2;
+ const int b3 = a0 - a1;
+ // abs((b + (b<0) + 3) >> 3) = (abs(b) + 3) >> 3
+ sum += w[ 0] * ((abs(b0) + 3) >> 3);
+ sum += w[ 4] * ((abs(b1) + 3) >> 3);
+ sum += w[ 8] * ((abs(b2) + 3) >> 3);
+ sum += w[12] * ((abs(b3) + 3) >> 3);
+ }
+ return sum;
+}
+
+static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
+ const uint16_t* const w) {
+ const int sum1 = TTransform(a, w);
+ const int sum2 = TTransform(b, w);
+ return (abs(sum2 - sum1) + 8) >> 4;
+}
+
+static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
+ const uint16_t* const w) {
+ int D = 0;
+ int x, y;
+ for (y = 0; y < 16 * BPS; y += 4 * BPS) {
+ for (x = 0; x < 16; x += 4) {
+ D += Disto4x4(a + x + y, b + x + y, w);
+ }
+ }
+ return D;
+}
+
+//------------------------------------------------------------------------------
+// Quantization
+//
+
+static const uint8_t kZigzag[16] = {
+ 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
+};
+
+// Simple quantization
+static int QuantizeBlock(int16_t in[16], int16_t out[16],
+ int n, const VP8Matrix* const mtx) {
+ int last = -1;
+ for (; n < 16; ++n) {
+ const int j = kZigzag[n];
+ const int sign = (in[j] < 0);
+ int coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
+ if (coeff > 2047) coeff = 2047;
+ if (coeff > mtx->zthresh_[j]) {
+ const int Q = mtx->q_[j];
+ const int iQ = mtx->iq_[j];
+ const int B = mtx->bias_[j];
+ out[n] = QUANTDIV(coeff, iQ, B);
+ if (sign) out[n] = -out[n];
+ in[j] = out[n] * Q;
+ if (out[n]) last = n;
+ } else {
+ out[n] = 0;
+ in[j] = 0;
+ }
+ }
+ return (last >= 0);
+}
+
+//------------------------------------------------------------------------------
+// Block copy
+
+static WEBP_INLINE void Copy(const uint8_t* src, uint8_t* dst, int size) {
+ int y;
+ for (y = 0; y < size; ++y) {
+ memcpy(dst, src, size);
+ src += BPS;
+ dst += BPS;
+ }
+}
+
+static void Copy4x4(const uint8_t* src, uint8_t* dst) { Copy(src, dst, 4); }
+
+//------------------------------------------------------------------------------
+// Initialization
+
+// Speed-critical function pointers. We have to initialize them to the default
+// implementations within VP8EncDspInit().
+VP8CHisto VP8CollectHistogram;
+VP8Idct VP8ITransform;
+VP8Fdct VP8FTransform;
+VP8WHT VP8ITransformWHT;
+VP8WHT VP8FTransformWHT;
+VP8Intra4Preds VP8EncPredLuma4;
+VP8IntraPreds VP8EncPredLuma16;
+VP8IntraPreds VP8EncPredChroma8;
+VP8Metric VP8SSE16x16;
+VP8Metric VP8SSE8x8;
+VP8Metric VP8SSE16x8;
+VP8Metric VP8SSE4x4;
+VP8WMetric VP8TDisto4x4;
+VP8WMetric VP8TDisto16x16;
+VP8QuantizeBlock VP8EncQuantizeBlock;
+VP8BlockCopy VP8Copy4x4;
+
+extern void VP8EncDspInitSSE2(void);
+
+void VP8EncDspInit(void) {
+ InitTables();
+
+ // default C implementations
+ VP8CollectHistogram = CollectHistogram;
+ VP8ITransform = ITransform;
+ VP8FTransform = FTransform;
+ VP8ITransformWHT = ITransformWHT;
+ VP8FTransformWHT = FTransformWHT;
+ VP8EncPredLuma4 = Intra4Preds;
+ VP8EncPredLuma16 = Intra16Preds;
+ VP8EncPredChroma8 = IntraChromaPreds;
+ VP8SSE16x16 = SSE16x16;
+ VP8SSE8x8 = SSE8x8;
+ VP8SSE16x8 = SSE16x8;
+ VP8SSE4x4 = SSE4x4;
+ VP8TDisto4x4 = Disto4x4;
+ VP8TDisto16x16 = Disto16x16;
+ VP8EncQuantizeBlock = QuantizeBlock;
+ VP8Copy4x4 = Copy4x4;
+
+ // If defined, use CPUInfo() to overwrite some pointers with faster versions.
+ if (VP8GetCPUInfo) {
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ VP8EncDspInitSSE2();
+ }
+#endif
+ }
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dsp/enc_sse2.c b/drivers/webpold/dsp/enc_sse2.c
new file mode 100644
index 0000000000..b046761dc1
--- /dev/null
+++ b/drivers/webpold/dsp/enc_sse2.c
@@ -0,0 +1,837 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// SSE2 version of speed-critical encoding functions.
+//
+// Author: Christian Duvivier (cduvivier@google.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_SSE2)
+#include <stdlib.h> // for abs()
+#include <emmintrin.h>
+
+#include "../enc/vp8enci.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Compute susceptibility based on DCT-coeff histograms:
+// the higher, the "easier" the macroblock is to compress.
+
+static int CollectHistogramSSE2(const uint8_t* ref, const uint8_t* pred,
+ int start_block, int end_block) {
+ int histo[MAX_COEFF_THRESH + 1] = { 0 };
+ int16_t out[16];
+ int j, k;
+ const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH);
+ for (j = start_block; j < end_block; ++j) {
+ VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
+
+ // Convert coefficients to bin (within out[]).
+ {
+ // Load.
+ const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]);
+ const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]);
+ // sign(out) = out >> 15 (0x0000 if positive, 0xffff if negative)
+ const __m128i sign0 = _mm_srai_epi16(out0, 15);
+ const __m128i sign1 = _mm_srai_epi16(out1, 15);
+ // abs(out) = (out ^ sign) - sign
+ const __m128i xor0 = _mm_xor_si128(out0, sign0);
+ const __m128i xor1 = _mm_xor_si128(out1, sign1);
+ const __m128i abs0 = _mm_sub_epi16(xor0, sign0);
+ const __m128i abs1 = _mm_sub_epi16(xor1, sign1);
+ // v = abs(out) >> 2
+ const __m128i v0 = _mm_srai_epi16(abs0, 2);
+ const __m128i v1 = _mm_srai_epi16(abs1, 2);
+ // bin = min(v, MAX_COEFF_THRESH)
+ const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh);
+ const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh);
+ // Store.
+ _mm_storeu_si128((__m128i*)&out[0], bin0);
+ _mm_storeu_si128((__m128i*)&out[8], bin1);
+ }
+
+ // Use bin to update histogram.
+ for (k = 0; k < 16; ++k) {
+ histo[out[k]]++;
+ }
+ }
+
+ return VP8GetAlpha(histo);
+}
+
+//------------------------------------------------------------------------------
+// Transforms (Paragraph 14.4)
+
+// Does one or two inverse transforms.
+static void ITransformSSE2(const uint8_t* ref, const int16_t* in, uint8_t* dst,
+ int do_two) {
+ // This implementation makes use of 16-bit fixed point versions of two
+ // multiply constants:
+ // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16
+ // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16
+ //
+ // To be able to use signed 16-bit integers, we use the following trick to
+ // have constants within range:
+ // - Associated constants are obtained by subtracting the 16-bit fixed point
+ // version of one:
+ // k = K - (1 << 16) => K = k + (1 << 16)
+ // K1 = 85267 => k1 = 20091
+ // K2 = 35468 => k2 = -30068
+ // - The multiplication of a variable by a constant become the sum of the
+ // variable and the multiplication of that variable by the associated
+ // constant:
+ // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x
+ const __m128i k1 = _mm_set1_epi16(20091);
+ const __m128i k2 = _mm_set1_epi16(-30068);
+ __m128i T0, T1, T2, T3;
+
+ // Load and concatenate the transform coefficients (we'll do two inverse
+ // transforms in parallel). In the case of only one inverse transform, the
+ // second half of the vectors will just contain random value we'll never
+ // use nor store.
+ __m128i in0, in1, in2, in3;
+ {
+ in0 = _mm_loadl_epi64((__m128i*)&in[0]);
+ in1 = _mm_loadl_epi64((__m128i*)&in[4]);
+ in2 = _mm_loadl_epi64((__m128i*)&in[8]);
+ in3 = _mm_loadl_epi64((__m128i*)&in[12]);
+ // a00 a10 a20 a30 x x x x
+ // a01 a11 a21 a31 x x x x
+ // a02 a12 a22 a32 x x x x
+ // a03 a13 a23 a33 x x x x
+ if (do_two) {
+ const __m128i inB0 = _mm_loadl_epi64((__m128i*)&in[16]);
+ const __m128i inB1 = _mm_loadl_epi64((__m128i*)&in[20]);
+ const __m128i inB2 = _mm_loadl_epi64((__m128i*)&in[24]);
+ const __m128i inB3 = _mm_loadl_epi64((__m128i*)&in[28]);
+ in0 = _mm_unpacklo_epi64(in0, inB0);
+ in1 = _mm_unpacklo_epi64(in1, inB1);
+ in2 = _mm_unpacklo_epi64(in2, inB2);
+ in3 = _mm_unpacklo_epi64(in3, inB3);
+ // a00 a10 a20 a30 b00 b10 b20 b30
+ // a01 a11 a21 a31 b01 b11 b21 b31
+ // a02 a12 a22 a32 b02 b12 b22 b32
+ // a03 a13 a23 a33 b03 b13 b23 b33
+ }
+ }
+
+ // Vertical pass and subsequent transpose.
+ {
+ // First pass, c and d calculations are longer because of the "trick"
+ // multiplications.
+ const __m128i a = _mm_add_epi16(in0, in2);
+ const __m128i b = _mm_sub_epi16(in0, in2);
+ // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3
+ const __m128i c1 = _mm_mulhi_epi16(in1, k2);
+ const __m128i c2 = _mm_mulhi_epi16(in3, k1);
+ const __m128i c3 = _mm_sub_epi16(in1, in3);
+ const __m128i c4 = _mm_sub_epi16(c1, c2);
+ const __m128i c = _mm_add_epi16(c3, c4);
+ // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3
+ const __m128i d1 = _mm_mulhi_epi16(in1, k1);
+ const __m128i d2 = _mm_mulhi_epi16(in3, k2);
+ const __m128i d3 = _mm_add_epi16(in1, in3);
+ const __m128i d4 = _mm_add_epi16(d1, d2);
+ const __m128i d = _mm_add_epi16(d3, d4);
+
+ // Second pass.
+ const __m128i tmp0 = _mm_add_epi16(a, d);
+ const __m128i tmp1 = _mm_add_epi16(b, c);
+ const __m128i tmp2 = _mm_sub_epi16(b, c);
+ const __m128i tmp3 = _mm_sub_epi16(a, d);
+
+ // Transpose the two 4x4.
+ // a00 a01 a02 a03 b00 b01 b02 b03
+ // a10 a11 a12 a13 b10 b11 b12 b13
+ // a20 a21 a22 a23 b20 b21 b22 b23
+ // a30 a31 a32 a33 b30 b31 b32 b33
+ const __m128i transpose0_0 = _mm_unpacklo_epi16(tmp0, tmp1);
+ const __m128i transpose0_1 = _mm_unpacklo_epi16(tmp2, tmp3);
+ const __m128i transpose0_2 = _mm_unpackhi_epi16(tmp0, tmp1);
+ const __m128i transpose0_3 = _mm_unpackhi_epi16(tmp2, tmp3);
+ // a00 a10 a01 a11 a02 a12 a03 a13
+ // a20 a30 a21 a31 a22 a32 a23 a33
+ // b00 b10 b01 b11 b02 b12 b03 b13
+ // b20 b30 b21 b31 b22 b32 b23 b33
+ const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
+ const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3);
+ const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
+ const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3);
+ // a00 a10 a20 a30 a01 a11 a21 a31
+ // b00 b10 b20 b30 b01 b11 b21 b31
+ // a02 a12 a22 a32 a03 a13 a23 a33
+ // b02 b12 a22 b32 b03 b13 b23 b33
+ T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1);
+ T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1);
+ T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3);
+ T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3);
+ // a00 a10 a20 a30 b00 b10 b20 b30
+ // a01 a11 a21 a31 b01 b11 b21 b31
+ // a02 a12 a22 a32 b02 b12 b22 b32
+ // a03 a13 a23 a33 b03 b13 b23 b33
+ }
+
+ // Horizontal pass and subsequent transpose.
+ {
+ // First pass, c and d calculations are longer because of the "trick"
+ // multiplications.
+ const __m128i four = _mm_set1_epi16(4);
+ const __m128i dc = _mm_add_epi16(T0, four);
+ const __m128i a = _mm_add_epi16(dc, T2);
+ const __m128i b = _mm_sub_epi16(dc, T2);
+ // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3
+ const __m128i c1 = _mm_mulhi_epi16(T1, k2);
+ const __m128i c2 = _mm_mulhi_epi16(T3, k1);
+ const __m128i c3 = _mm_sub_epi16(T1, T3);
+ const __m128i c4 = _mm_sub_epi16(c1, c2);
+ const __m128i c = _mm_add_epi16(c3, c4);
+ // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3
+ const __m128i d1 = _mm_mulhi_epi16(T1, k1);
+ const __m128i d2 = _mm_mulhi_epi16(T3, k2);
+ const __m128i d3 = _mm_add_epi16(T1, T3);
+ const __m128i d4 = _mm_add_epi16(d1, d2);
+ const __m128i d = _mm_add_epi16(d3, d4);
+
+ // Second pass.
+ const __m128i tmp0 = _mm_add_epi16(a, d);
+ const __m128i tmp1 = _mm_add_epi16(b, c);
+ const __m128i tmp2 = _mm_sub_epi16(b, c);
+ const __m128i tmp3 = _mm_sub_epi16(a, d);
+ const __m128i shifted0 = _mm_srai_epi16(tmp0, 3);
+ const __m128i shifted1 = _mm_srai_epi16(tmp1, 3);
+ const __m128i shifted2 = _mm_srai_epi16(tmp2, 3);
+ const __m128i shifted3 = _mm_srai_epi16(tmp3, 3);
+
+ // Transpose the two 4x4.
+ // a00 a01 a02 a03 b00 b01 b02 b03
+ // a10 a11 a12 a13 b10 b11 b12 b13
+ // a20 a21 a22 a23 b20 b21 b22 b23
+ // a30 a31 a32 a33 b30 b31 b32 b33
+ const __m128i transpose0_0 = _mm_unpacklo_epi16(shifted0, shifted1);
+ const __m128i transpose0_1 = _mm_unpacklo_epi16(shifted2, shifted3);
+ const __m128i transpose0_2 = _mm_unpackhi_epi16(shifted0, shifted1);
+ const __m128i transpose0_3 = _mm_unpackhi_epi16(shifted2, shifted3);
+ // a00 a10 a01 a11 a02 a12 a03 a13
+ // a20 a30 a21 a31 a22 a32 a23 a33
+ // b00 b10 b01 b11 b02 b12 b03 b13
+ // b20 b30 b21 b31 b22 b32 b23 b33
+ const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
+ const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3);
+ const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
+ const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3);
+ // a00 a10 a20 a30 a01 a11 a21 a31
+ // b00 b10 b20 b30 b01 b11 b21 b31
+ // a02 a12 a22 a32 a03 a13 a23 a33
+ // b02 b12 a22 b32 b03 b13 b23 b33
+ T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1);
+ T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1);
+ T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3);
+ T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3);
+ // a00 a10 a20 a30 b00 b10 b20 b30
+ // a01 a11 a21 a31 b01 b11 b21 b31
+ // a02 a12 a22 a32 b02 b12 b22 b32
+ // a03 a13 a23 a33 b03 b13 b23 b33
+ }
+
+ // Add inverse transform to 'ref' and store.
+ {
+ const __m128i zero = _mm_set1_epi16(0);
+ // Load the reference(s).
+ __m128i ref0, ref1, ref2, ref3;
+ if (do_two) {
+ // Load eight bytes/pixels per line.
+ ref0 = _mm_loadl_epi64((__m128i*)&ref[0 * BPS]);
+ ref1 = _mm_loadl_epi64((__m128i*)&ref[1 * BPS]);
+ ref2 = _mm_loadl_epi64((__m128i*)&ref[2 * BPS]);
+ ref3 = _mm_loadl_epi64((__m128i*)&ref[3 * BPS]);
+ } else {
+ // Load four bytes/pixels per line.
+ ref0 = _mm_cvtsi32_si128(*(int*)&ref[0 * BPS]);
+ ref1 = _mm_cvtsi32_si128(*(int*)&ref[1 * BPS]);
+ ref2 = _mm_cvtsi32_si128(*(int*)&ref[2 * BPS]);
+ ref3 = _mm_cvtsi32_si128(*(int*)&ref[3 * BPS]);
+ }
+ // Convert to 16b.
+ ref0 = _mm_unpacklo_epi8(ref0, zero);
+ ref1 = _mm_unpacklo_epi8(ref1, zero);
+ ref2 = _mm_unpacklo_epi8(ref2, zero);
+ ref3 = _mm_unpacklo_epi8(ref3, zero);
+ // Add the inverse transform(s).
+ ref0 = _mm_add_epi16(ref0, T0);
+ ref1 = _mm_add_epi16(ref1, T1);
+ ref2 = _mm_add_epi16(ref2, T2);
+ ref3 = _mm_add_epi16(ref3, T3);
+ // Unsigned saturate to 8b.
+ ref0 = _mm_packus_epi16(ref0, ref0);
+ ref1 = _mm_packus_epi16(ref1, ref1);
+ ref2 = _mm_packus_epi16(ref2, ref2);
+ ref3 = _mm_packus_epi16(ref3, ref3);
+ // Store the results.
+ if (do_two) {
+ // Store eight bytes/pixels per line.
+ _mm_storel_epi64((__m128i*)&dst[0 * BPS], ref0);
+ _mm_storel_epi64((__m128i*)&dst[1 * BPS], ref1);
+ _mm_storel_epi64((__m128i*)&dst[2 * BPS], ref2);
+ _mm_storel_epi64((__m128i*)&dst[3 * BPS], ref3);
+ } else {
+ // Store four bytes/pixels per line.
+ *((int32_t *)&dst[0 * BPS]) = _mm_cvtsi128_si32(ref0);
+ *((int32_t *)&dst[1 * BPS]) = _mm_cvtsi128_si32(ref1);
+ *((int32_t *)&dst[2 * BPS]) = _mm_cvtsi128_si32(ref2);
+ *((int32_t *)&dst[3 * BPS]) = _mm_cvtsi128_si32(ref3);
+ }
+ }
+}
+
+static void FTransformSSE2(const uint8_t* src, const uint8_t* ref,
+ int16_t* out) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i seven = _mm_set1_epi16(7);
+ const __m128i k7500 = _mm_set1_epi32(7500);
+ const __m128i k14500 = _mm_set1_epi32(14500);
+ const __m128i k51000 = _mm_set1_epi32(51000);
+ const __m128i k12000_plus_one = _mm_set1_epi32(12000 + (1 << 16));
+ const __m128i k5352_2217 = _mm_set_epi16(5352, 2217, 5352, 2217,
+ 5352, 2217, 5352, 2217);
+ const __m128i k2217_5352 = _mm_set_epi16(2217, -5352, 2217, -5352,
+ 2217, -5352, 2217, -5352);
+
+ __m128i v01, v32;
+
+ // Difference between src and ref and initial transpose.
+ {
+ // Load src and convert to 16b.
+ const __m128i src0 = _mm_loadl_epi64((__m128i*)&src[0 * BPS]);
+ const __m128i src1 = _mm_loadl_epi64((__m128i*)&src[1 * BPS]);
+ const __m128i src2 = _mm_loadl_epi64((__m128i*)&src[2 * BPS]);
+ const __m128i src3 = _mm_loadl_epi64((__m128i*)&src[3 * BPS]);
+ const __m128i src_0 = _mm_unpacklo_epi8(src0, zero);
+ const __m128i src_1 = _mm_unpacklo_epi8(src1, zero);
+ const __m128i src_2 = _mm_unpacklo_epi8(src2, zero);
+ const __m128i src_3 = _mm_unpacklo_epi8(src3, zero);
+ // Load ref and convert to 16b.
+ const __m128i ref0 = _mm_loadl_epi64((__m128i*)&ref[0 * BPS]);
+ const __m128i ref1 = _mm_loadl_epi64((__m128i*)&ref[1 * BPS]);
+ const __m128i ref2 = _mm_loadl_epi64((__m128i*)&ref[2 * BPS]);
+ const __m128i ref3 = _mm_loadl_epi64((__m128i*)&ref[3 * BPS]);
+ const __m128i ref_0 = _mm_unpacklo_epi8(ref0, zero);
+ const __m128i ref_1 = _mm_unpacklo_epi8(ref1, zero);
+ const __m128i ref_2 = _mm_unpacklo_epi8(ref2, zero);
+ const __m128i ref_3 = _mm_unpacklo_epi8(ref3, zero);
+ // Compute difference.
+ const __m128i diff0 = _mm_sub_epi16(src_0, ref_0);
+ const __m128i diff1 = _mm_sub_epi16(src_1, ref_1);
+ const __m128i diff2 = _mm_sub_epi16(src_2, ref_2);
+ const __m128i diff3 = _mm_sub_epi16(src_3, ref_3);
+
+ // Transpose.
+ // 00 01 02 03 0 0 0 0
+ // 10 11 12 13 0 0 0 0
+ // 20 21 22 23 0 0 0 0
+ // 30 31 32 33 0 0 0 0
+ const __m128i transpose0_0 = _mm_unpacklo_epi16(diff0, diff1);
+ const __m128i transpose0_1 = _mm_unpacklo_epi16(diff2, diff3);
+ // 00 10 01 11 02 12 03 13
+ // 20 30 21 31 22 32 23 33
+ const __m128i v23 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
+ v01 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
+ v32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2));
+ // a02 a12 a22 a32 a03 a13 a23 a33
+ // a00 a10 a20 a30 a01 a11 a21 a31
+ // a03 a13 a23 a33 a02 a12 a22 a32
+ }
+
+ // First pass and subsequent transpose.
+ {
+ // Same operations are done on the (0,3) and (1,2) pairs.
+ // b0 = (a0 + a3) << 3
+ // b1 = (a1 + a2) << 3
+ // b3 = (a0 - a3) << 3
+ // b2 = (a1 - a2) << 3
+ const __m128i a01 = _mm_add_epi16(v01, v32);
+ const __m128i a32 = _mm_sub_epi16(v01, v32);
+ const __m128i b01 = _mm_slli_epi16(a01, 3);
+ const __m128i b32 = _mm_slli_epi16(a32, 3);
+ const __m128i b11 = _mm_unpackhi_epi64(b01, b01);
+ const __m128i b22 = _mm_unpackhi_epi64(b32, b32);
+
+ // e0 = b0 + b1
+ // e2 = b0 - b1
+ const __m128i e0 = _mm_add_epi16(b01, b11);
+ const __m128i e2 = _mm_sub_epi16(b01, b11);
+ const __m128i e02 = _mm_unpacklo_epi64(e0, e2);
+
+ // e1 = (b3 * 5352 + b2 * 2217 + 14500) >> 12
+ // e3 = (b3 * 2217 - b2 * 5352 + 7500) >> 12
+ const __m128i b23 = _mm_unpacklo_epi16(b22, b32);
+ const __m128i c1 = _mm_madd_epi16(b23, k5352_2217);
+ const __m128i c3 = _mm_madd_epi16(b23, k2217_5352);
+ const __m128i d1 = _mm_add_epi32(c1, k14500);
+ const __m128i d3 = _mm_add_epi32(c3, k7500);
+ const __m128i e1 = _mm_srai_epi32(d1, 12);
+ const __m128i e3 = _mm_srai_epi32(d3, 12);
+ const __m128i e13 = _mm_packs_epi32(e1, e3);
+
+ // Transpose.
+ // 00 01 02 03 20 21 22 23
+ // 10 11 12 13 30 31 32 33
+ const __m128i transpose0_0 = _mm_unpacklo_epi16(e02, e13);
+ const __m128i transpose0_1 = _mm_unpackhi_epi16(e02, e13);
+ // 00 10 01 11 02 12 03 13
+ // 20 30 21 31 22 32 23 33
+ const __m128i v23 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
+ v01 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
+ v32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2));
+ // 02 12 22 32 03 13 23 33
+ // 00 10 20 30 01 11 21 31
+ // 03 13 23 33 02 12 22 32
+ }
+
+ // Second pass
+ {
+ // Same operations are done on the (0,3) and (1,2) pairs.
+ // a0 = v0 + v3
+ // a1 = v1 + v2
+ // a3 = v0 - v3
+ // a2 = v1 - v2
+ const __m128i a01 = _mm_add_epi16(v01, v32);
+ const __m128i a32 = _mm_sub_epi16(v01, v32);
+ const __m128i a11 = _mm_unpackhi_epi64(a01, a01);
+ const __m128i a22 = _mm_unpackhi_epi64(a32, a32);
+
+ // d0 = (a0 + a1 + 7) >> 4;
+ // d2 = (a0 - a1 + 7) >> 4;
+ const __m128i b0 = _mm_add_epi16(a01, a11);
+ const __m128i b2 = _mm_sub_epi16(a01, a11);
+ const __m128i c0 = _mm_add_epi16(b0, seven);
+ const __m128i c2 = _mm_add_epi16(b2, seven);
+ const __m128i d0 = _mm_srai_epi16(c0, 4);
+ const __m128i d2 = _mm_srai_epi16(c2, 4);
+
+ // f1 = ((b3 * 5352 + b2 * 2217 + 12000) >> 16)
+ // f3 = ((b3 * 2217 - b2 * 5352 + 51000) >> 16)
+ const __m128i b23 = _mm_unpacklo_epi16(a22, a32);
+ const __m128i c1 = _mm_madd_epi16(b23, k5352_2217);
+ const __m128i c3 = _mm_madd_epi16(b23, k2217_5352);
+ const __m128i d1 = _mm_add_epi32(c1, k12000_plus_one);
+ const __m128i d3 = _mm_add_epi32(c3, k51000);
+ const __m128i e1 = _mm_srai_epi32(d1, 16);
+ const __m128i e3 = _mm_srai_epi32(d3, 16);
+ const __m128i f1 = _mm_packs_epi32(e1, e1);
+ const __m128i f3 = _mm_packs_epi32(e3, e3);
+ // f1 = f1 + (a3 != 0);
+ // The compare will return (0xffff, 0) for (==0, !=0). To turn that into the
+ // desired (0, 1), we add one earlier through k12000_plus_one.
+ const __m128i g1 = _mm_add_epi16(f1, _mm_cmpeq_epi16(a32, zero));
+
+ _mm_storel_epi64((__m128i*)&out[ 0], d0);
+ _mm_storel_epi64((__m128i*)&out[ 4], g1);
+ _mm_storel_epi64((__m128i*)&out[ 8], d2);
+ _mm_storel_epi64((__m128i*)&out[12], f3);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Metric
+
+static int SSE4x4SSE2(const uint8_t* a, const uint8_t* b) {
+ const __m128i zero = _mm_set1_epi16(0);
+
+ // Load values.
+ const __m128i a0 = _mm_loadl_epi64((__m128i*)&a[BPS * 0]);
+ const __m128i a1 = _mm_loadl_epi64((__m128i*)&a[BPS * 1]);
+ const __m128i a2 = _mm_loadl_epi64((__m128i*)&a[BPS * 2]);
+ const __m128i a3 = _mm_loadl_epi64((__m128i*)&a[BPS * 3]);
+ const __m128i b0 = _mm_loadl_epi64((__m128i*)&b[BPS * 0]);
+ const __m128i b1 = _mm_loadl_epi64((__m128i*)&b[BPS * 1]);
+ const __m128i b2 = _mm_loadl_epi64((__m128i*)&b[BPS * 2]);
+ const __m128i b3 = _mm_loadl_epi64((__m128i*)&b[BPS * 3]);
+
+ // Combine pair of lines and convert to 16b.
+ const __m128i a01 = _mm_unpacklo_epi32(a0, a1);
+ const __m128i a23 = _mm_unpacklo_epi32(a2, a3);
+ const __m128i b01 = _mm_unpacklo_epi32(b0, b1);
+ const __m128i b23 = _mm_unpacklo_epi32(b2, b3);
+ const __m128i a01s = _mm_unpacklo_epi8(a01, zero);
+ const __m128i a23s = _mm_unpacklo_epi8(a23, zero);
+ const __m128i b01s = _mm_unpacklo_epi8(b01, zero);
+ const __m128i b23s = _mm_unpacklo_epi8(b23, zero);
+
+ // Compute differences; (a-b)^2 = (abs(a-b))^2 = (sat8(a-b) + sat8(b-a))^2
+ // TODO(cduvivier): Dissassemble and figure out why this is fastest. We don't
+ // need absolute values, there is no need to do calculation
+ // in 8bit as we are already in 16bit, ... Yet this is what
+ // benchmarks the fastest!
+ const __m128i d0 = _mm_subs_epu8(a01s, b01s);
+ const __m128i d1 = _mm_subs_epu8(b01s, a01s);
+ const __m128i d2 = _mm_subs_epu8(a23s, b23s);
+ const __m128i d3 = _mm_subs_epu8(b23s, a23s);
+
+ // Square and add them all together.
+ const __m128i madd0 = _mm_madd_epi16(d0, d0);
+ const __m128i madd1 = _mm_madd_epi16(d1, d1);
+ const __m128i madd2 = _mm_madd_epi16(d2, d2);
+ const __m128i madd3 = _mm_madd_epi16(d3, d3);
+ const __m128i sum0 = _mm_add_epi32(madd0, madd1);
+ const __m128i sum1 = _mm_add_epi32(madd2, madd3);
+ const __m128i sum2 = _mm_add_epi32(sum0, sum1);
+ int32_t tmp[4];
+ _mm_storeu_si128((__m128i*)tmp, sum2);
+ return (tmp[3] + tmp[2] + tmp[1] + tmp[0]);
+}
+
+//------------------------------------------------------------------------------
+// Texture distortion
+//
+// We try to match the spectral content (weighted) between source and
+// reconstructed samples.
+
+// Hadamard transform
+// Returns the difference between the weighted sum of the absolute value of
+// transformed coefficients.
+static int TTransformSSE2(const uint8_t* inA, const uint8_t* inB,
+ const uint16_t* const w) {
+ int32_t sum[4];
+ __m128i tmp_0, tmp_1, tmp_2, tmp_3;
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i one = _mm_set1_epi16(1);
+ const __m128i three = _mm_set1_epi16(3);
+
+ // Load, combine and tranpose inputs.
+ {
+ const __m128i inA_0 = _mm_loadl_epi64((__m128i*)&inA[BPS * 0]);
+ const __m128i inA_1 = _mm_loadl_epi64((__m128i*)&inA[BPS * 1]);
+ const __m128i inA_2 = _mm_loadl_epi64((__m128i*)&inA[BPS * 2]);
+ const __m128i inA_3 = _mm_loadl_epi64((__m128i*)&inA[BPS * 3]);
+ const __m128i inB_0 = _mm_loadl_epi64((__m128i*)&inB[BPS * 0]);
+ const __m128i inB_1 = _mm_loadl_epi64((__m128i*)&inB[BPS * 1]);
+ const __m128i inB_2 = _mm_loadl_epi64((__m128i*)&inB[BPS * 2]);
+ const __m128i inB_3 = _mm_loadl_epi64((__m128i*)&inB[BPS * 3]);
+
+ // Combine inA and inB (we'll do two transforms in parallel).
+ const __m128i inAB_0 = _mm_unpacklo_epi8(inA_0, inB_0);
+ const __m128i inAB_1 = _mm_unpacklo_epi8(inA_1, inB_1);
+ const __m128i inAB_2 = _mm_unpacklo_epi8(inA_2, inB_2);
+ const __m128i inAB_3 = _mm_unpacklo_epi8(inA_3, inB_3);
+ // a00 b00 a01 b01 a02 b03 a03 b03 0 0 0 0 0 0 0 0
+ // a10 b10 a11 b11 a12 b12 a13 b13 0 0 0 0 0 0 0 0
+ // a20 b20 a21 b21 a22 b22 a23 b23 0 0 0 0 0 0 0 0
+ // a30 b30 a31 b31 a32 b32 a33 b33 0 0 0 0 0 0 0 0
+
+ // Transpose the two 4x4, discarding the filling zeroes.
+ const __m128i transpose0_0 = _mm_unpacklo_epi8(inAB_0, inAB_2);
+ const __m128i transpose0_1 = _mm_unpacklo_epi8(inAB_1, inAB_3);
+ // a00 a20 b00 b20 a01 a21 b01 b21 a02 a22 b02 b22 a03 a23 b03 b23
+ // a10 a30 b10 b30 a11 a31 b11 b31 a12 a32 b12 b32 a13 a33 b13 b33
+ const __m128i transpose1_0 = _mm_unpacklo_epi8(transpose0_0, transpose0_1);
+ const __m128i transpose1_1 = _mm_unpackhi_epi8(transpose0_0, transpose0_1);
+ // a00 a10 a20 a30 b00 b10 b20 b30 a01 a11 a21 a31 b01 b11 b21 b31
+ // a02 a12 a22 a32 b02 b12 b22 b32 a03 a13 a23 a33 b03 b13 b23 b33
+
+ // Convert to 16b.
+ tmp_0 = _mm_unpacklo_epi8(transpose1_0, zero);
+ tmp_1 = _mm_unpackhi_epi8(transpose1_0, zero);
+ tmp_2 = _mm_unpacklo_epi8(transpose1_1, zero);
+ tmp_3 = _mm_unpackhi_epi8(transpose1_1, zero);
+ // a00 a10 a20 a30 b00 b10 b20 b30
+ // a01 a11 a21 a31 b01 b11 b21 b31
+ // a02 a12 a22 a32 b02 b12 b22 b32
+ // a03 a13 a23 a33 b03 b13 b23 b33
+ }
+
+ // Horizontal pass and subsequent transpose.
+ {
+ // Calculate a and b (two 4x4 at once).
+ const __m128i a0 = _mm_slli_epi16(_mm_add_epi16(tmp_0, tmp_2), 2);
+ const __m128i a1 = _mm_slli_epi16(_mm_add_epi16(tmp_1, tmp_3), 2);
+ const __m128i a2 = _mm_slli_epi16(_mm_sub_epi16(tmp_1, tmp_3), 2);
+ const __m128i a3 = _mm_slli_epi16(_mm_sub_epi16(tmp_0, tmp_2), 2);
+ // b0_extra = (a0 != 0);
+ const __m128i b0_extra = _mm_andnot_si128(_mm_cmpeq_epi16 (a0, zero), one);
+ const __m128i b0_base = _mm_add_epi16(a0, a1);
+ const __m128i b1 = _mm_add_epi16(a3, a2);
+ const __m128i b2 = _mm_sub_epi16(a3, a2);
+ const __m128i b3 = _mm_sub_epi16(a0, a1);
+ const __m128i b0 = _mm_add_epi16(b0_base, b0_extra);
+ // a00 a01 a02 a03 b00 b01 b02 b03
+ // a10 a11 a12 a13 b10 b11 b12 b13
+ // a20 a21 a22 a23 b20 b21 b22 b23
+ // a30 a31 a32 a33 b30 b31 b32 b33
+
+ // Transpose the two 4x4.
+ const __m128i transpose0_0 = _mm_unpacklo_epi16(b0, b1);
+ const __m128i transpose0_1 = _mm_unpacklo_epi16(b2, b3);
+ const __m128i transpose0_2 = _mm_unpackhi_epi16(b0, b1);
+ const __m128i transpose0_3 = _mm_unpackhi_epi16(b2, b3);
+ // a00 a10 a01 a11 a02 a12 a03 a13
+ // a20 a30 a21 a31 a22 a32 a23 a33
+ // b00 b10 b01 b11 b02 b12 b03 b13
+ // b20 b30 b21 b31 b22 b32 b23 b33
+ const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
+ const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3);
+ const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
+ const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3);
+ // a00 a10 a20 a30 a01 a11 a21 a31
+ // b00 b10 b20 b30 b01 b11 b21 b31
+ // a02 a12 a22 a32 a03 a13 a23 a33
+ // b02 b12 a22 b32 b03 b13 b23 b33
+ tmp_0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1);
+ tmp_1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1);
+ tmp_2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3);
+ tmp_3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3);
+ // a00 a10 a20 a30 b00 b10 b20 b30
+ // a01 a11 a21 a31 b01 b11 b21 b31
+ // a02 a12 a22 a32 b02 b12 b22 b32
+ // a03 a13 a23 a33 b03 b13 b23 b33
+ }
+
+ // Vertical pass and difference of weighted sums.
+ {
+ // Load all inputs.
+ // TODO(cduvivier): Make variable declarations and allocations aligned so
+ // we can use _mm_load_si128 instead of _mm_loadu_si128.
+ const __m128i w_0 = _mm_loadu_si128((__m128i*)&w[0]);
+ const __m128i w_8 = _mm_loadu_si128((__m128i*)&w[8]);
+
+ // Calculate a and b (two 4x4 at once).
+ const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2);
+ const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3);
+ const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3);
+ const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2);
+ const __m128i b0 = _mm_add_epi16(a0, a1);
+ const __m128i b1 = _mm_add_epi16(a3, a2);
+ const __m128i b2 = _mm_sub_epi16(a3, a2);
+ const __m128i b3 = _mm_sub_epi16(a0, a1);
+
+ // Separate the transforms of inA and inB.
+ __m128i A_b0 = _mm_unpacklo_epi64(b0, b1);
+ __m128i A_b2 = _mm_unpacklo_epi64(b2, b3);
+ __m128i B_b0 = _mm_unpackhi_epi64(b0, b1);
+ __m128i B_b2 = _mm_unpackhi_epi64(b2, b3);
+
+ {
+ // sign(b) = b >> 15 (0x0000 if positive, 0xffff if negative)
+ const __m128i sign_A_b0 = _mm_srai_epi16(A_b0, 15);
+ const __m128i sign_A_b2 = _mm_srai_epi16(A_b2, 15);
+ const __m128i sign_B_b0 = _mm_srai_epi16(B_b0, 15);
+ const __m128i sign_B_b2 = _mm_srai_epi16(B_b2, 15);
+
+ // b = abs(b) = (b ^ sign) - sign
+ A_b0 = _mm_xor_si128(A_b0, sign_A_b0);
+ A_b2 = _mm_xor_si128(A_b2, sign_A_b2);
+ B_b0 = _mm_xor_si128(B_b0, sign_B_b0);
+ B_b2 = _mm_xor_si128(B_b2, sign_B_b2);
+ A_b0 = _mm_sub_epi16(A_b0, sign_A_b0);
+ A_b2 = _mm_sub_epi16(A_b2, sign_A_b2);
+ B_b0 = _mm_sub_epi16(B_b0, sign_B_b0);
+ B_b2 = _mm_sub_epi16(B_b2, sign_B_b2);
+ }
+
+ // b = abs(b) + 3
+ A_b0 = _mm_add_epi16(A_b0, three);
+ A_b2 = _mm_add_epi16(A_b2, three);
+ B_b0 = _mm_add_epi16(B_b0, three);
+ B_b2 = _mm_add_epi16(B_b2, three);
+
+ // abs((b + (b<0) + 3) >> 3) = (abs(b) + 3) >> 3
+ // b = (abs(b) + 3) >> 3
+ A_b0 = _mm_srai_epi16(A_b0, 3);
+ A_b2 = _mm_srai_epi16(A_b2, 3);
+ B_b0 = _mm_srai_epi16(B_b0, 3);
+ B_b2 = _mm_srai_epi16(B_b2, 3);
+
+ // weighted sums
+ A_b0 = _mm_madd_epi16(A_b0, w_0);
+ A_b2 = _mm_madd_epi16(A_b2, w_8);
+ B_b0 = _mm_madd_epi16(B_b0, w_0);
+ B_b2 = _mm_madd_epi16(B_b2, w_8);
+ A_b0 = _mm_add_epi32(A_b0, A_b2);
+ B_b0 = _mm_add_epi32(B_b0, B_b2);
+
+ // difference of weighted sums
+ A_b0 = _mm_sub_epi32(A_b0, B_b0);
+ _mm_storeu_si128((__m128i*)&sum[0], A_b0);
+ }
+ return sum[0] + sum[1] + sum[2] + sum[3];
+}
+
+static int Disto4x4SSE2(const uint8_t* const a, const uint8_t* const b,
+ const uint16_t* const w) {
+ const int diff_sum = TTransformSSE2(a, b, w);
+ return (abs(diff_sum) + 8) >> 4;
+}
+
+static int Disto16x16SSE2(const uint8_t* const a, const uint8_t* const b,
+ const uint16_t* const w) {
+ int D = 0;
+ int x, y;
+ for (y = 0; y < 16 * BPS; y += 4 * BPS) {
+ for (x = 0; x < 16; x += 4) {
+ D += Disto4x4SSE2(a + x + y, b + x + y, w);
+ }
+ }
+ return D;
+}
+
+
+//------------------------------------------------------------------------------
+// Quantization
+//
+
+// Simple quantization
+static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
+ int n, const VP8Matrix* const mtx) {
+ const __m128i max_coeff_2047 = _mm_set1_epi16(2047);
+ const __m128i zero = _mm_set1_epi16(0);
+ __m128i sign0, sign8;
+ __m128i coeff0, coeff8;
+ __m128i out0, out8;
+ __m128i packed_out;
+
+ // Load all inputs.
+ // TODO(cduvivier): Make variable declarations and allocations aligned so that
+ // we can use _mm_load_si128 instead of _mm_loadu_si128.
+ __m128i in0 = _mm_loadu_si128((__m128i*)&in[0]);
+ __m128i in8 = _mm_loadu_si128((__m128i*)&in[8]);
+ const __m128i sharpen0 = _mm_loadu_si128((__m128i*)&mtx->sharpen_[0]);
+ const __m128i sharpen8 = _mm_loadu_si128((__m128i*)&mtx->sharpen_[8]);
+ const __m128i iq0 = _mm_loadu_si128((__m128i*)&mtx->iq_[0]);
+ const __m128i iq8 = _mm_loadu_si128((__m128i*)&mtx->iq_[8]);
+ const __m128i bias0 = _mm_loadu_si128((__m128i*)&mtx->bias_[0]);
+ const __m128i bias8 = _mm_loadu_si128((__m128i*)&mtx->bias_[8]);
+ const __m128i q0 = _mm_loadu_si128((__m128i*)&mtx->q_[0]);
+ const __m128i q8 = _mm_loadu_si128((__m128i*)&mtx->q_[8]);
+ const __m128i zthresh0 = _mm_loadu_si128((__m128i*)&mtx->zthresh_[0]);
+ const __m128i zthresh8 = _mm_loadu_si128((__m128i*)&mtx->zthresh_[8]);
+
+ // sign(in) = in >> 15 (0x0000 if positive, 0xffff if negative)
+ sign0 = _mm_srai_epi16(in0, 15);
+ sign8 = _mm_srai_epi16(in8, 15);
+
+ // coeff = abs(in) = (in ^ sign) - sign
+ coeff0 = _mm_xor_si128(in0, sign0);
+ coeff8 = _mm_xor_si128(in8, sign8);
+ coeff0 = _mm_sub_epi16(coeff0, sign0);
+ coeff8 = _mm_sub_epi16(coeff8, sign8);
+
+ // coeff = abs(in) + sharpen
+ coeff0 = _mm_add_epi16(coeff0, sharpen0);
+ coeff8 = _mm_add_epi16(coeff8, sharpen8);
+
+ // if (coeff > 2047) coeff = 2047
+ coeff0 = _mm_min_epi16(coeff0, max_coeff_2047);
+ coeff8 = _mm_min_epi16(coeff8, max_coeff_2047);
+
+ // out = (coeff * iQ + B) >> QFIX;
+ {
+ // doing calculations with 32b precision (QFIX=17)
+ // out = (coeff * iQ)
+ __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0);
+ __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0);
+ __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8);
+ __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8);
+ __m128i out_00 = _mm_unpacklo_epi16(coeff_iQ0L, coeff_iQ0H);
+ __m128i out_04 = _mm_unpackhi_epi16(coeff_iQ0L, coeff_iQ0H);
+ __m128i out_08 = _mm_unpacklo_epi16(coeff_iQ8L, coeff_iQ8H);
+ __m128i out_12 = _mm_unpackhi_epi16(coeff_iQ8L, coeff_iQ8H);
+ // expand bias from 16b to 32b
+ __m128i bias_00 = _mm_unpacklo_epi16(bias0, zero);
+ __m128i bias_04 = _mm_unpackhi_epi16(bias0, zero);
+ __m128i bias_08 = _mm_unpacklo_epi16(bias8, zero);
+ __m128i bias_12 = _mm_unpackhi_epi16(bias8, zero);
+ // out = (coeff * iQ + B)
+ out_00 = _mm_add_epi32(out_00, bias_00);
+ out_04 = _mm_add_epi32(out_04, bias_04);
+ out_08 = _mm_add_epi32(out_08, bias_08);
+ out_12 = _mm_add_epi32(out_12, bias_12);
+ // out = (coeff * iQ + B) >> QFIX;
+ out_00 = _mm_srai_epi32(out_00, QFIX);
+ out_04 = _mm_srai_epi32(out_04, QFIX);
+ out_08 = _mm_srai_epi32(out_08, QFIX);
+ out_12 = _mm_srai_epi32(out_12, QFIX);
+ // pack result as 16b
+ out0 = _mm_packs_epi32(out_00, out_04);
+ out8 = _mm_packs_epi32(out_08, out_12);
+ }
+
+ // get sign back (if (sign[j]) out_n = -out_n)
+ out0 = _mm_xor_si128(out0, sign0);
+ out8 = _mm_xor_si128(out8, sign8);
+ out0 = _mm_sub_epi16(out0, sign0);
+ out8 = _mm_sub_epi16(out8, sign8);
+
+ // in = out * Q
+ in0 = _mm_mullo_epi16(out0, q0);
+ in8 = _mm_mullo_epi16(out8, q8);
+
+ // if (coeff <= mtx->zthresh_) {in=0; out=0;}
+ {
+ __m128i cmp0 = _mm_cmpgt_epi16(coeff0, zthresh0);
+ __m128i cmp8 = _mm_cmpgt_epi16(coeff8, zthresh8);
+ in0 = _mm_and_si128(in0, cmp0);
+ in8 = _mm_and_si128(in8, cmp8);
+ _mm_storeu_si128((__m128i*)&in[0], in0);
+ _mm_storeu_si128((__m128i*)&in[8], in8);
+ out0 = _mm_and_si128(out0, cmp0);
+ out8 = _mm_and_si128(out8, cmp8);
+ }
+
+ // zigzag the output before storing it.
+ //
+ // The zigzag pattern can almost be reproduced with a small sequence of
+ // shuffles. After it, we only need to swap the 7th (ending up in third
+ // position instead of twelfth) and 8th values.
+ {
+ __m128i outZ0, outZ8;
+ outZ0 = _mm_shufflehi_epi16(out0, _MM_SHUFFLE(2, 1, 3, 0));
+ outZ0 = _mm_shuffle_epi32 (outZ0, _MM_SHUFFLE(3, 1, 2, 0));
+ outZ0 = _mm_shufflehi_epi16(outZ0, _MM_SHUFFLE(3, 1, 0, 2));
+ outZ8 = _mm_shufflelo_epi16(out8, _MM_SHUFFLE(3, 0, 2, 1));
+ outZ8 = _mm_shuffle_epi32 (outZ8, _MM_SHUFFLE(3, 1, 2, 0));
+ outZ8 = _mm_shufflelo_epi16(outZ8, _MM_SHUFFLE(1, 3, 2, 0));
+ _mm_storeu_si128((__m128i*)&out[0], outZ0);
+ _mm_storeu_si128((__m128i*)&out[8], outZ8);
+ packed_out = _mm_packs_epi16(outZ0, outZ8);
+ }
+ {
+ const int16_t outZ_12 = out[12];
+ const int16_t outZ_3 = out[3];
+ out[3] = outZ_12;
+ out[12] = outZ_3;
+ }
+
+ // detect if all 'out' values are zeroes or not
+ {
+ int32_t tmp[4];
+ _mm_storeu_si128((__m128i*)tmp, packed_out);
+ if (n) {
+ tmp[0] &= ~0xff;
+ }
+ return (tmp[3] || tmp[2] || tmp[1] || tmp[0]);
+ }
+}
+
+extern void VP8EncDspInitSSE2(void);
+void VP8EncDspInitSSE2(void) {
+ VP8CollectHistogram = CollectHistogramSSE2;
+ VP8EncQuantizeBlock = QuantizeBlockSSE2;
+ VP8ITransform = ITransformSSE2;
+ VP8FTransform = FTransformSSE2;
+ VP8SSE4x4 = SSE4x4SSE2;
+ VP8TDisto4x4 = Disto4x4SSE2;
+ VP8TDisto16x16 = Disto16x16SSE2;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif // WEBP_USE_SSE2
diff --git a/drivers/webpold/dsp/lossless.c b/drivers/webpold/dsp/lossless.c
new file mode 100644
index 0000000000..62a6b7b15a
--- /dev/null
+++ b/drivers/webpold/dsp/lossless.c
@@ -0,0 +1,1138 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Image transforms and color space conversion methods for lossless decoder.
+//
+// Authors: Vikas Arora (vikaas.arora@gmail.com)
+// Jyrki Alakuijala (jyrki@google.com)
+// Urvang Joshi (urvang@google.com)
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include <math.h>
+#include <stdlib.h>
+#include "./lossless.h"
+#include "../dec/vp8li.h"
+#include "../dsp/yuv.h"
+#include "../dsp/dsp.h"
+#include "../enc/histogram.h"
+
+#define MAX_DIFF_COST (1e30f)
+
+// lookup table for small values of log2(int)
+#define APPROX_LOG_MAX 4096
+#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086
+#define LOG_LOOKUP_IDX_MAX 256
+static const float kLog2Table[LOG_LOOKUP_IDX_MAX] = {
+ 0.0000000000000000f, 0.0000000000000000f,
+ 1.0000000000000000f, 1.5849625007211560f,
+ 2.0000000000000000f, 2.3219280948873621f,
+ 2.5849625007211560f, 2.8073549220576041f,
+ 3.0000000000000000f, 3.1699250014423121f,
+ 3.3219280948873621f, 3.4594316186372973f,
+ 3.5849625007211560f, 3.7004397181410921f,
+ 3.8073549220576041f, 3.9068905956085187f,
+ 4.0000000000000000f, 4.0874628412503390f,
+ 4.1699250014423121f, 4.2479275134435852f,
+ 4.3219280948873626f, 4.3923174227787606f,
+ 4.4594316186372973f, 4.5235619560570130f,
+ 4.5849625007211560f, 4.6438561897747243f,
+ 4.7004397181410917f, 4.7548875021634682f,
+ 4.8073549220576037f, 4.8579809951275718f,
+ 4.9068905956085187f, 4.9541963103868749f,
+ 5.0000000000000000f, 5.0443941193584533f,
+ 5.0874628412503390f, 5.1292830169449663f,
+ 5.1699250014423121f, 5.2094533656289501f,
+ 5.2479275134435852f, 5.2854022188622487f,
+ 5.3219280948873626f, 5.3575520046180837f,
+ 5.3923174227787606f, 5.4262647547020979f,
+ 5.4594316186372973f, 5.4918530963296747f,
+ 5.5235619560570130f, 5.5545888516776376f,
+ 5.5849625007211560f, 5.6147098441152083f,
+ 5.6438561897747243f, 5.6724253419714951f,
+ 5.7004397181410917f, 5.7279204545631987f,
+ 5.7548875021634682f, 5.7813597135246599f,
+ 5.8073549220576037f, 5.8328900141647412f,
+ 5.8579809951275718f, 5.8826430493618415f,
+ 5.9068905956085187f, 5.9307373375628866f,
+ 5.9541963103868749f, 5.9772799234999167f,
+ 6.0000000000000000f, 6.0223678130284543f,
+ 6.0443941193584533f, 6.0660891904577720f,
+ 6.0874628412503390f, 6.1085244567781691f,
+ 6.1292830169449663f, 6.1497471195046822f,
+ 6.1699250014423121f, 6.1898245588800175f,
+ 6.2094533656289501f, 6.2288186904958804f,
+ 6.2479275134435852f, 6.2667865406949010f,
+ 6.2854022188622487f, 6.3037807481771030f,
+ 6.3219280948873626f, 6.3398500028846243f,
+ 6.3575520046180837f, 6.3750394313469245f,
+ 6.3923174227787606f, 6.4093909361377017f,
+ 6.4262647547020979f, 6.4429434958487279f,
+ 6.4594316186372973f, 6.4757334309663976f,
+ 6.4918530963296747f, 6.5077946401986963f,
+ 6.5235619560570130f, 6.5391588111080309f,
+ 6.5545888516776376f, 6.5698556083309478f,
+ 6.5849625007211560f, 6.5999128421871278f,
+ 6.6147098441152083f, 6.6293566200796094f,
+ 6.6438561897747243f, 6.6582114827517946f,
+ 6.6724253419714951f, 6.6865005271832185f,
+ 6.7004397181410917f, 6.7142455176661224f,
+ 6.7279204545631987f, 6.7414669864011464f,
+ 6.7548875021634682f, 6.7681843247769259f,
+ 6.7813597135246599f, 6.7944158663501061f,
+ 6.8073549220576037f, 6.8201789624151878f,
+ 6.8328900141647412f, 6.8454900509443747f,
+ 6.8579809951275718f, 6.8703647195834047f,
+ 6.8826430493618415f, 6.8948177633079437f,
+ 6.9068905956085187f, 6.9188632372745946f,
+ 6.9307373375628866f, 6.9425145053392398f,
+ 6.9541963103868749f, 6.9657842846620869f,
+ 6.9772799234999167f, 6.9886846867721654f,
+ 7.0000000000000000f, 7.0112272554232539f,
+ 7.0223678130284543f, 7.0334230015374501f,
+ 7.0443941193584533f, 7.0552824355011898f,
+ 7.0660891904577720f, 7.0768155970508308f,
+ 7.0874628412503390f, 7.0980320829605263f,
+ 7.1085244567781691f, 7.1189410727235076f,
+ 7.1292830169449663f, 7.1395513523987936f,
+ 7.1497471195046822f, 7.1598713367783890f,
+ 7.1699250014423121f, 7.1799090900149344f,
+ 7.1898245588800175f, 7.1996723448363644f,
+ 7.2094533656289501f, 7.2191685204621611f,
+ 7.2288186904958804f, 7.2384047393250785f,
+ 7.2479275134435852f, 7.2573878426926521f,
+ 7.2667865406949010f, 7.2761244052742375f,
+ 7.2854022188622487f, 7.2946207488916270f,
+ 7.3037807481771030f, 7.3128829552843557f,
+ 7.3219280948873626f, 7.3309168781146167f,
+ 7.3398500028846243f, 7.3487281542310771f,
+ 7.3575520046180837f, 7.3663222142458160f,
+ 7.3750394313469245f, 7.3837042924740519f,
+ 7.3923174227787606f, 7.4008794362821843f,
+ 7.4093909361377017f, 7.4178525148858982f,
+ 7.4262647547020979f, 7.4346282276367245f,
+ 7.4429434958487279f, 7.4512111118323289f,
+ 7.4594316186372973f, 7.4676055500829976f,
+ 7.4757334309663976f, 7.4838157772642563f,
+ 7.4918530963296747f, 7.4998458870832056f,
+ 7.5077946401986963f, 7.5156998382840427f,
+ 7.5235619560570130f, 7.5313814605163118f,
+ 7.5391588111080309f, 7.5468944598876364f,
+ 7.5545888516776376f, 7.5622424242210728f,
+ 7.5698556083309478f, 7.5774288280357486f,
+ 7.5849625007211560f, 7.5924570372680806f,
+ 7.5999128421871278f, 7.6073303137496104f,
+ 7.6147098441152083f, 7.6220518194563764f,
+ 7.6293566200796094f, 7.6366246205436487f,
+ 7.6438561897747243f, 7.6510516911789281f,
+ 7.6582114827517946f, 7.6653359171851764f,
+ 7.6724253419714951f, 7.6794800995054464f,
+ 7.6865005271832185f, 7.6934869574993252f,
+ 7.7004397181410917f, 7.7073591320808825f,
+ 7.7142455176661224f, 7.7210991887071855f,
+ 7.7279204545631987f, 7.7347096202258383f,
+ 7.7414669864011464f, 7.7481928495894605f,
+ 7.7548875021634682f, 7.7615512324444795f,
+ 7.7681843247769259f, 7.7747870596011736f,
+ 7.7813597135246599f, 7.7879025593914317f,
+ 7.7944158663501061f, 7.8008998999203047f,
+ 7.8073549220576037f, 7.8137811912170374f,
+ 7.8201789624151878f, 7.8265484872909150f,
+ 7.8328900141647412f, 7.8392037880969436f,
+ 7.8454900509443747f, 7.8517490414160571f,
+ 7.8579809951275718f, 7.8641861446542797f,
+ 7.8703647195834047f, 7.8765169465649993f,
+ 7.8826430493618415f, 7.8887432488982591f,
+ 7.8948177633079437f, 7.9008668079807486f,
+ 7.9068905956085187f, 7.9128893362299619f,
+ 7.9188632372745946f, 7.9248125036057812f,
+ 7.9307373375628866f, 7.9366379390025709f,
+ 7.9425145053392398f, 7.9483672315846778f,
+ 7.9541963103868749f, 7.9600019320680805f,
+ 7.9657842846620869f, 7.9715435539507719f,
+ 7.9772799234999167f, 7.9829935746943103f,
+ 7.9886846867721654f, 7.9943534368588577f
+};
+
+float VP8LFastLog2(int v) {
+ if (v < LOG_LOOKUP_IDX_MAX) {
+ return kLog2Table[v];
+ } else if (v < APPROX_LOG_MAX) {
+ int log_cnt = 0;
+ while (v >= LOG_LOOKUP_IDX_MAX) {
+ ++log_cnt;
+ v = v >> 1;
+ }
+ return kLog2Table[v] + (float)log_cnt;
+ } else {
+ return (float)(LOG_2_RECIPROCAL * log((double)v));
+ }
+}
+
+//------------------------------------------------------------------------------
+// Image transforms.
+
+// In-place sum of each component with mod 256.
+static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) {
+ const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u);
+ const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu);
+ *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
+}
+
+static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
+ return (((a0 ^ a1) & 0xfefefefeL) >> 1) + (a0 & a1);
+}
+
+static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
+ return Average2(Average2(a0, a2), a1);
+}
+
+static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
+ uint32_t a2, uint32_t a3) {
+ return Average2(Average2(a0, a1), Average2(a2, a3));
+}
+
+static WEBP_INLINE uint32_t Clip255(uint32_t a) {
+ if (a < 256) {
+ return a;
+ }
+ // return 0, when a is a negative integer.
+ // return 255, when a is positive.
+ return ~a >> 24;
+}
+
+static WEBP_INLINE int AddSubtractComponentFull(int a, int b, int c) {
+ return Clip255(a + b - c);
+}
+
+static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
+ uint32_t c2) {
+ const int a = AddSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24);
+ const int r = AddSubtractComponentFull((c0 >> 16) & 0xff,
+ (c1 >> 16) & 0xff,
+ (c2 >> 16) & 0xff);
+ const int g = AddSubtractComponentFull((c0 >> 8) & 0xff,
+ (c1 >> 8) & 0xff,
+ (c2 >> 8) & 0xff);
+ const int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff);
+ return (a << 24) | (r << 16) | (g << 8) | b;
+}
+
+static WEBP_INLINE int AddSubtractComponentHalf(int a, int b) {
+ return Clip255(a + (a - b) / 2);
+}
+
+static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
+ uint32_t c2) {
+ const uint32_t ave = Average2(c0, c1);
+ const int a = AddSubtractComponentHalf(ave >> 24, c2 >> 24);
+ const int r = AddSubtractComponentHalf((ave >> 16) & 0xff, (c2 >> 16) & 0xff);
+ const int g = AddSubtractComponentHalf((ave >> 8) & 0xff, (c2 >> 8) & 0xff);
+ const int b = AddSubtractComponentHalf((ave >> 0) & 0xff, (c2 >> 0) & 0xff);
+ return (a << 24) | (r << 16) | (g << 8) | b;
+}
+
+static WEBP_INLINE int Sub3(int a, int b, int c) {
+ const int pa = b - c;
+ const int pb = a - c;
+ return abs(pa) - abs(pb);
+}
+
+static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
+ const int pa_minus_pb =
+ Sub3((a >> 24) , (b >> 24) , (c >> 24) ) +
+ Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) +
+ Sub3((a >> 8) & 0xff, (b >> 8) & 0xff, (c >> 8) & 0xff) +
+ Sub3((a ) & 0xff, (b ) & 0xff, (c ) & 0xff);
+
+ return (pa_minus_pb <= 0) ? a : b;
+}
+
+//------------------------------------------------------------------------------
+// Predictors
+
+static uint32_t Predictor0(uint32_t left, const uint32_t* const top) {
+ (void)top;
+ (void)left;
+ return ARGB_BLACK;
+}
+static uint32_t Predictor1(uint32_t left, const uint32_t* const top) {
+ (void)top;
+ return left;
+}
+static uint32_t Predictor2(uint32_t left, const uint32_t* const top) {
+ (void)left;
+ return top[0];
+}
+static uint32_t Predictor3(uint32_t left, const uint32_t* const top) {
+ (void)left;
+ return top[1];
+}
+static uint32_t Predictor4(uint32_t left, const uint32_t* const top) {
+ (void)left;
+ return top[-1];
+}
+static uint32_t Predictor5(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = Average3(left, top[0], top[1]);
+ return pred;
+}
+static uint32_t Predictor6(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = Average2(left, top[-1]);
+ return pred;
+}
+static uint32_t Predictor7(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = Average2(left, top[0]);
+ return pred;
+}
+static uint32_t Predictor8(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = Average2(top[-1], top[0]);
+ (void)left;
+ return pred;
+}
+static uint32_t Predictor9(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = Average2(top[0], top[1]);
+ (void)left;
+ return pred;
+}
+static uint32_t Predictor10(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = Average4(left, top[-1], top[0], top[1]);
+ return pred;
+}
+static uint32_t Predictor11(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = Select(top[0], left, top[-1]);
+ return pred;
+}
+static uint32_t Predictor12(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]);
+ return pred;
+}
+static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
+ const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]);
+ return pred;
+}
+
+typedef uint32_t (*PredictorFunc)(uint32_t left, const uint32_t* const top);
+static const PredictorFunc kPredictors[16] = {
+ Predictor0, Predictor1, Predictor2, Predictor3,
+ Predictor4, Predictor5, Predictor6, Predictor7,
+ Predictor8, Predictor9, Predictor10, Predictor11,
+ Predictor12, Predictor13,
+ Predictor0, Predictor0 // <- padding security sentinels
+};
+
+// TODO(vikasa): Replace 256 etc with defines.
+static float PredictionCostSpatial(const int* counts,
+ int weight_0, double exp_val) {
+ const int significant_symbols = 16;
+ const double exp_decay_factor = 0.6;
+ double bits = weight_0 * counts[0];
+ int i;
+ for (i = 1; i < significant_symbols; ++i) {
+ bits += exp_val * (counts[i] + counts[256 - i]);
+ exp_val *= exp_decay_factor;
+ }
+ return (float)(-0.1 * bits);
+}
+
+// Compute the Shanon's entropy: Sum(p*log2(p))
+static float ShannonEntropy(const int* const array, int n) {
+ int i;
+ float retval = 0.f;
+ int sum = 0;
+ for (i = 0; i < n; ++i) {
+ if (array[i] != 0) {
+ sum += array[i];
+ retval -= VP8LFastSLog2(array[i]);
+ }
+ }
+ retval += VP8LFastSLog2(sum);
+ return retval;
+}
+
+static float PredictionCostSpatialHistogram(int accumulated[4][256],
+ int tile[4][256]) {
+ int i;
+ int k;
+ int combo[256];
+ double retval = 0;
+ for (i = 0; i < 4; ++i) {
+ const double exp_val = 0.94;
+ retval += PredictionCostSpatial(&tile[i][0], 1, exp_val);
+ retval += ShannonEntropy(&tile[i][0], 256);
+ for (k = 0; k < 256; ++k) {
+ combo[k] = accumulated[i][k] + tile[i][k];
+ }
+ retval += ShannonEntropy(&combo[0], 256);
+ }
+ return (float)retval;
+}
+
+static int GetBestPredictorForTile(int width, int height,
+ int tile_x, int tile_y, int bits,
+ int accumulated[4][256],
+ const uint32_t* const argb_scratch) {
+ const int kNumPredModes = 14;
+ const int col_start = tile_x << bits;
+ const int row_start = tile_y << bits;
+ const int tile_size = 1 << bits;
+ const int ymax = (tile_size <= height - row_start) ?
+ tile_size : height - row_start;
+ const int xmax = (tile_size <= width - col_start) ?
+ tile_size : width - col_start;
+ int histo[4][256];
+ float best_diff = MAX_DIFF_COST;
+ int best_mode = 0;
+
+ int mode;
+ for (mode = 0; mode < kNumPredModes; ++mode) {
+ const uint32_t* current_row = argb_scratch;
+ const PredictorFunc pred_func = kPredictors[mode];
+ float cur_diff;
+ int y;
+ memset(&histo[0][0], 0, sizeof(histo));
+ for (y = 0; y < ymax; ++y) {
+ int x;
+ const int row = row_start + y;
+ const uint32_t* const upper_row = current_row;
+ current_row = upper_row + width;
+ for (x = 0; x < xmax; ++x) {
+ const int col = col_start + x;
+ uint32_t predict;
+ uint32_t predict_diff;
+ if (row == 0) {
+ predict = (col == 0) ? ARGB_BLACK : current_row[col - 1]; // Left.
+ } else if (col == 0) {
+ predict = upper_row[col]; // Top.
+ } else {
+ predict = pred_func(current_row[col - 1], upper_row + col);
+ }
+ predict_diff = VP8LSubPixels(current_row[col], predict);
+ ++histo[0][predict_diff >> 24];
+ ++histo[1][((predict_diff >> 16) & 0xff)];
+ ++histo[2][((predict_diff >> 8) & 0xff)];
+ ++histo[3][(predict_diff & 0xff)];
+ }
+ }
+ cur_diff = PredictionCostSpatialHistogram(accumulated, histo);
+ if (cur_diff < best_diff) {
+ best_diff = cur_diff;
+ best_mode = mode;
+ }
+ }
+
+ return best_mode;
+}
+
+static void CopyTileWithPrediction(int width, int height,
+ int tile_x, int tile_y, int bits, int mode,
+ const uint32_t* const argb_scratch,
+ uint32_t* const argb) {
+ const int col_start = tile_x << bits;
+ const int row_start = tile_y << bits;
+ const int tile_size = 1 << bits;
+ const int ymax = (tile_size <= height - row_start) ?
+ tile_size : height - row_start;
+ const int xmax = (tile_size <= width - col_start) ?
+ tile_size : width - col_start;
+ const PredictorFunc pred_func = kPredictors[mode];
+ const uint32_t* current_row = argb_scratch;
+
+ int y;
+ for (y = 0; y < ymax; ++y) {
+ int x;
+ const int row = row_start + y;
+ const uint32_t* const upper_row = current_row;
+ current_row = upper_row + width;
+ for (x = 0; x < xmax; ++x) {
+ const int col = col_start + x;
+ const int pix = row * width + col;
+ uint32_t predict;
+ if (row == 0) {
+ predict = (col == 0) ? ARGB_BLACK : current_row[col - 1]; // Left.
+ } else if (col == 0) {
+ predict = upper_row[col]; // Top.
+ } else {
+ predict = pred_func(current_row[col - 1], upper_row + col);
+ }
+ argb[pix] = VP8LSubPixels(current_row[col], predict);
+ }
+ }
+}
+
+void VP8LResidualImage(int width, int height, int bits,
+ uint32_t* const argb, uint32_t* const argb_scratch,
+ uint32_t* const image) {
+ const int max_tile_size = 1 << bits;
+ const int tiles_per_row = VP8LSubSampleSize(width, bits);
+ const int tiles_per_col = VP8LSubSampleSize(height, bits);
+ uint32_t* const upper_row = argb_scratch;
+ uint32_t* const current_tile_rows = argb_scratch + width;
+ int tile_y;
+ int histo[4][256];
+ memset(histo, 0, sizeof(histo));
+ for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) {
+ const int tile_y_offset = tile_y * max_tile_size;
+ const int this_tile_height =
+ (tile_y < tiles_per_col - 1) ? max_tile_size : height - tile_y_offset;
+ int tile_x;
+ if (tile_y > 0) {
+ memcpy(upper_row, current_tile_rows + (max_tile_size - 1) * width,
+ width * sizeof(*upper_row));
+ }
+ memcpy(current_tile_rows, &argb[tile_y_offset * width],
+ this_tile_height * width * sizeof(*current_tile_rows));
+ for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) {
+ int pred;
+ int y;
+ const int tile_x_offset = tile_x * max_tile_size;
+ int all_x_max = tile_x_offset + max_tile_size;
+ if (all_x_max > width) {
+ all_x_max = width;
+ }
+ pred = GetBestPredictorForTile(width, height, tile_x, tile_y, bits, histo,
+ argb_scratch);
+ image[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8);
+ CopyTileWithPrediction(width, height, tile_x, tile_y, bits, pred,
+ argb_scratch, argb);
+ for (y = 0; y < max_tile_size; ++y) {
+ int ix;
+ int all_x;
+ int all_y = tile_y_offset + y;
+ if (all_y >= height) {
+ break;
+ }
+ ix = all_y * width + tile_x_offset;
+ for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
+ const uint32_t a = argb[ix];
+ ++histo[0][a >> 24];
+ ++histo[1][((a >> 16) & 0xff)];
+ ++histo[2][((a >> 8) & 0xff)];
+ ++histo[3][(a & 0xff)];
+ }
+ }
+ }
+ }
+}
+
+// Inverse prediction.
+static void PredictorInverseTransform(const VP8LTransform* const transform,
+ int y_start, int y_end, uint32_t* data) {
+ const int width = transform->xsize_;
+ if (y_start == 0) { // First Row follows the L (mode=1) mode.
+ int x;
+ const uint32_t pred0 = Predictor0(data[-1], NULL);
+ AddPixelsEq(data, pred0);
+ for (x = 1; x < width; ++x) {
+ const uint32_t pred1 = Predictor1(data[x - 1], NULL);
+ AddPixelsEq(data + x, pred1);
+ }
+ data += width;
+ ++y_start;
+ }
+
+ {
+ int y = y_start;
+ const int mask = (1 << transform->bits_) - 1;
+ const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_);
+ const uint32_t* pred_mode_base =
+ transform->data_ + (y >> transform->bits_) * tiles_per_row;
+
+ while (y < y_end) {
+ int x;
+ const uint32_t pred2 = Predictor2(data[-1], data - width);
+ const uint32_t* pred_mode_src = pred_mode_base;
+ PredictorFunc pred_func;
+
+ // First pixel follows the T (mode=2) mode.
+ AddPixelsEq(data, pred2);
+
+ // .. the rest:
+ pred_func = kPredictors[((*pred_mode_src++) >> 8) & 0xf];
+ for (x = 1; x < width; ++x) {
+ uint32_t pred;
+ if ((x & mask) == 0) { // start of tile. Read predictor function.
+ pred_func = kPredictors[((*pred_mode_src++) >> 8) & 0xf];
+ }
+ pred = pred_func(data[x - 1], data + x - width);
+ AddPixelsEq(data + x, pred);
+ }
+ data += width;
+ ++y;
+ if ((y & mask) == 0) { // Use the same mask, since tiles are squares.
+ pred_mode_base += tiles_per_row;
+ }
+ }
+ }
+}
+
+void VP8LSubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixs) {
+ int i;
+ for (i = 0; i < num_pixs; ++i) {
+ const uint32_t argb = argb_data[i];
+ const uint32_t green = (argb >> 8) & 0xff;
+ const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff;
+ const uint32_t new_b = ((argb & 0xff) - green) & 0xff;
+ argb_data[i] = (argb & 0xff00ff00) | (new_r << 16) | new_b;
+ }
+}
+
+// Add green to blue and red channels (i.e. perform the inverse transform of
+// 'subtract green').
+static void AddGreenToBlueAndRed(const VP8LTransform* const transform,
+ int y_start, int y_end, uint32_t* data) {
+ const int width = transform->xsize_;
+ const uint32_t* const data_end = data + (y_end - y_start) * width;
+ while (data < data_end) {
+ const uint32_t argb = *data;
+ // "* 0001001u" is equivalent to "(green << 16) + green)"
+ const uint32_t green = ((argb >> 8) & 0xff);
+ uint32_t red_blue = (argb & 0x00ff00ffu);
+ red_blue += (green << 16) | green;
+ red_blue &= 0x00ff00ffu;
+ *data++ = (argb & 0xff00ff00u) | red_blue;
+ }
+}
+
+typedef struct {
+ // Note: the members are uint8_t, so that any negative values are
+ // automatically converted to "mod 256" values.
+ uint8_t green_to_red_;
+ uint8_t green_to_blue_;
+ uint8_t red_to_blue_;
+} Multipliers;
+
+static WEBP_INLINE void MultipliersClear(Multipliers* m) {
+ m->green_to_red_ = 0;
+ m->green_to_blue_ = 0;
+ m->red_to_blue_ = 0;
+}
+
+static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred,
+ int8_t color) {
+ return (uint32_t)((int)(color_pred) * color) >> 5;
+}
+
+static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code,
+ Multipliers* const m) {
+ m->green_to_red_ = (color_code >> 0) & 0xff;
+ m->green_to_blue_ = (color_code >> 8) & 0xff;
+ m->red_to_blue_ = (color_code >> 16) & 0xff;
+}
+
+static WEBP_INLINE uint32_t MultipliersToColorCode(Multipliers* const m) {
+ return 0xff000000u |
+ ((uint32_t)(m->red_to_blue_) << 16) |
+ ((uint32_t)(m->green_to_blue_) << 8) |
+ m->green_to_red_;
+}
+
+static WEBP_INLINE uint32_t TransformColor(const Multipliers* const m,
+ uint32_t argb, int inverse) {
+ const uint32_t green = argb >> 8;
+ const uint32_t red = argb >> 16;
+ uint32_t new_red = red;
+ uint32_t new_blue = argb;
+
+ if (inverse) {
+ new_red += ColorTransformDelta(m->green_to_red_, green);
+ new_red &= 0xff;
+ new_blue += ColorTransformDelta(m->green_to_blue_, green);
+ new_blue += ColorTransformDelta(m->red_to_blue_, new_red);
+ new_blue &= 0xff;
+ } else {
+ new_red -= ColorTransformDelta(m->green_to_red_, green);
+ new_red &= 0xff;
+ new_blue -= ColorTransformDelta(m->green_to_blue_, green);
+ new_blue -= ColorTransformDelta(m->red_to_blue_, red);
+ new_blue &= 0xff;
+ }
+ return (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
+}
+
+static WEBP_INLINE int SkipRepeatedPixels(const uint32_t* const argb,
+ int ix, int xsize) {
+ const uint32_t v = argb[ix];
+ if (ix >= xsize + 3) {
+ if (v == argb[ix - xsize] &&
+ argb[ix - 1] == argb[ix - xsize - 1] &&
+ argb[ix - 2] == argb[ix - xsize - 2] &&
+ argb[ix - 3] == argb[ix - xsize - 3]) {
+ return 1;
+ }
+ return v == argb[ix - 3] && v == argb[ix - 2] && v == argb[ix - 1];
+ } else if (ix >= 3) {
+ return v == argb[ix - 3] && v == argb[ix - 2] && v == argb[ix - 1];
+ }
+ return 0;
+}
+
+static float PredictionCostCrossColor(const int accumulated[256],
+ const int counts[256]) {
+ // Favor low entropy, locally and globally.
+ int i;
+ int combo[256];
+ for (i = 0; i < 256; ++i) {
+ combo[i] = accumulated[i] + counts[i];
+ }
+ return ShannonEntropy(combo, 256) +
+ ShannonEntropy(counts, 256) +
+ PredictionCostSpatial(counts, 3, 2.4); // Favor small absolute values.
+}
+
+static Multipliers GetBestColorTransformForTile(
+ int tile_x, int tile_y, int bits,
+ Multipliers prevX,
+ Multipliers prevY,
+ int step, int xsize, int ysize,
+ int* accumulated_red_histo,
+ int* accumulated_blue_histo,
+ const uint32_t* const argb) {
+ float best_diff = MAX_DIFF_COST;
+ float cur_diff;
+ const int halfstep = step / 2;
+ const int max_tile_size = 1 << bits;
+ const int tile_y_offset = tile_y * max_tile_size;
+ const int tile_x_offset = tile_x * max_tile_size;
+ int green_to_red;
+ int green_to_blue;
+ int red_to_blue;
+ int all_x_max = tile_x_offset + max_tile_size;
+ int all_y_max = tile_y_offset + max_tile_size;
+ Multipliers best_tx;
+ MultipliersClear(&best_tx);
+ if (all_x_max > xsize) {
+ all_x_max = xsize;
+ }
+ if (all_y_max > ysize) {
+ all_y_max = ysize;
+ }
+ for (green_to_red = -64; green_to_red <= 64; green_to_red += halfstep) {
+ int histo[256] = { 0 };
+ int all_y;
+ Multipliers tx;
+ MultipliersClear(&tx);
+ tx.green_to_red_ = green_to_red & 0xff;
+
+ for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) {
+ uint32_t predict;
+ int ix = all_y * xsize + tile_x_offset;
+ int all_x;
+ for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
+ if (SkipRepeatedPixels(argb, ix, xsize)) {
+ continue;
+ }
+ predict = TransformColor(&tx, argb[ix], 0);
+ ++histo[(predict >> 16) & 0xff]; // red.
+ }
+ }
+ cur_diff = PredictionCostCrossColor(&accumulated_red_histo[0], &histo[0]);
+ if (tx.green_to_red_ == prevX.green_to_red_) {
+ cur_diff -= 3; // favor keeping the areas locally similar
+ }
+ if (tx.green_to_red_ == prevY.green_to_red_) {
+ cur_diff -= 3; // favor keeping the areas locally similar
+ }
+ if (tx.green_to_red_ == 0) {
+ cur_diff -= 3;
+ }
+ if (cur_diff < best_diff) {
+ best_diff = cur_diff;
+ best_tx = tx;
+ }
+ }
+ best_diff = MAX_DIFF_COST;
+ green_to_red = best_tx.green_to_red_;
+ for (green_to_blue = -32; green_to_blue <= 32; green_to_blue += step) {
+ for (red_to_blue = -32; red_to_blue <= 32; red_to_blue += step) {
+ int all_y;
+ int histo[256] = { 0 };
+ Multipliers tx;
+ tx.green_to_red_ = green_to_red;
+ tx.green_to_blue_ = green_to_blue;
+ tx.red_to_blue_ = red_to_blue;
+ for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) {
+ uint32_t predict;
+ int all_x;
+ int ix = all_y * xsize + tile_x_offset;
+ for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
+ if (SkipRepeatedPixels(argb, ix, xsize)) {
+ continue;
+ }
+ predict = TransformColor(&tx, argb[ix], 0);
+ ++histo[predict & 0xff]; // blue.
+ }
+ }
+ cur_diff =
+ PredictionCostCrossColor(&accumulated_blue_histo[0], &histo[0]);
+ if (tx.green_to_blue_ == prevX.green_to_blue_) {
+ cur_diff -= 3; // favor keeping the areas locally similar
+ }
+ if (tx.green_to_blue_ == prevY.green_to_blue_) {
+ cur_diff -= 3; // favor keeping the areas locally similar
+ }
+ if (tx.red_to_blue_ == prevX.red_to_blue_) {
+ cur_diff -= 3; // favor keeping the areas locally similar
+ }
+ if (tx.red_to_blue_ == prevY.red_to_blue_) {
+ cur_diff -= 3; // favor keeping the areas locally similar
+ }
+ if (tx.green_to_blue_ == 0) {
+ cur_diff -= 3;
+ }
+ if (tx.red_to_blue_ == 0) {
+ cur_diff -= 3;
+ }
+ if (cur_diff < best_diff) {
+ best_diff = cur_diff;
+ best_tx = tx;
+ }
+ }
+ }
+ return best_tx;
+}
+
+static void CopyTileWithColorTransform(int xsize, int ysize,
+ int tile_x, int tile_y, int bits,
+ Multipliers color_transform,
+ uint32_t* const argb) {
+ int y;
+ int xscan = 1 << bits;
+ int yscan = 1 << bits;
+ tile_x <<= bits;
+ tile_y <<= bits;
+ if (xscan > xsize - tile_x) {
+ xscan = xsize - tile_x;
+ }
+ if (yscan > ysize - tile_y) {
+ yscan = ysize - tile_y;
+ }
+ yscan += tile_y;
+ for (y = tile_y; y < yscan; ++y) {
+ int ix = y * xsize + tile_x;
+ const int end_ix = ix + xscan;
+ for (; ix < end_ix; ++ix) {
+ argb[ix] = TransformColor(&color_transform, argb[ix], 0);
+ }
+ }
+}
+
+void VP8LColorSpaceTransform(int width, int height, int bits, int step,
+ uint32_t* const argb, uint32_t* image) {
+ const int max_tile_size = 1 << bits;
+ int tile_xsize = VP8LSubSampleSize(width, bits);
+ int tile_ysize = VP8LSubSampleSize(height, bits);
+ int accumulated_red_histo[256] = { 0 };
+ int accumulated_blue_histo[256] = { 0 };
+ int tile_y;
+ int tile_x;
+ Multipliers prevX;
+ Multipliers prevY;
+ MultipliersClear(&prevY);
+ MultipliersClear(&prevX);
+ for (tile_y = 0; tile_y < tile_ysize; ++tile_y) {
+ for (tile_x = 0; tile_x < tile_xsize; ++tile_x) {
+ Multipliers color_transform;
+ int all_x_max;
+ int y;
+ const int tile_y_offset = tile_y * max_tile_size;
+ const int tile_x_offset = tile_x * max_tile_size;
+ if (tile_y != 0) {
+ ColorCodeToMultipliers(image[tile_y * tile_xsize + tile_x - 1], &prevX);
+ ColorCodeToMultipliers(image[(tile_y - 1) * tile_xsize + tile_x],
+ &prevY);
+ } else if (tile_x != 0) {
+ ColorCodeToMultipliers(image[tile_y * tile_xsize + tile_x - 1], &prevX);
+ }
+ color_transform =
+ GetBestColorTransformForTile(tile_x, tile_y, bits,
+ prevX, prevY,
+ step, width, height,
+ &accumulated_red_histo[0],
+ &accumulated_blue_histo[0],
+ argb);
+ image[tile_y * tile_xsize + tile_x] =
+ MultipliersToColorCode(&color_transform);
+ CopyTileWithColorTransform(width, height, tile_x, tile_y, bits,
+ color_transform, argb);
+
+ // Gather accumulated histogram data.
+ all_x_max = tile_x_offset + max_tile_size;
+ if (all_x_max > width) {
+ all_x_max = width;
+ }
+ for (y = 0; y < max_tile_size; ++y) {
+ int ix;
+ int all_x;
+ int all_y = tile_y_offset + y;
+ if (all_y >= height) {
+ break;
+ }
+ ix = all_y * width + tile_x_offset;
+ for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
+ if (ix >= 2 &&
+ argb[ix] == argb[ix - 2] &&
+ argb[ix] == argb[ix - 1]) {
+ continue; // repeated pixels are handled by backward references
+ }
+ if (ix >= width + 2 &&
+ argb[ix - 2] == argb[ix - width - 2] &&
+ argb[ix - 1] == argb[ix - width - 1] &&
+ argb[ix] == argb[ix - width]) {
+ continue; // repeated pixels are handled by backward references
+ }
+ ++accumulated_red_histo[(argb[ix] >> 16) & 0xff];
+ ++accumulated_blue_histo[argb[ix] & 0xff];
+ }
+ }
+ }
+ }
+}
+
+// Color space inverse transform.
+static void ColorSpaceInverseTransform(const VP8LTransform* const transform,
+ int y_start, int y_end, uint32_t* data) {
+ const int width = transform->xsize_;
+ const int mask = (1 << transform->bits_) - 1;
+ const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_);
+ int y = y_start;
+ const uint32_t* pred_row =
+ transform->data_ + (y >> transform->bits_) * tiles_per_row;
+
+ while (y < y_end) {
+ const uint32_t* pred = pred_row;
+ Multipliers m = { 0, 0, 0 };
+ int x;
+
+ for (x = 0; x < width; ++x) {
+ if ((x & mask) == 0) ColorCodeToMultipliers(*pred++, &m);
+ data[x] = TransformColor(&m, data[x], 1);
+ }
+ data += width;
+ ++y;
+ if ((y & mask) == 0) pred_row += tiles_per_row;;
+ }
+}
+
+// Separate out pixels packed together using pixel-bundling.
+static void ColorIndexInverseTransform(
+ const VP8LTransform* const transform,
+ int y_start, int y_end, const uint32_t* src, uint32_t* dst) {
+ int y;
+ const int bits_per_pixel = 8 >> transform->bits_;
+ const int width = transform->xsize_;
+ const uint32_t* const color_map = transform->data_;
+ if (bits_per_pixel < 8) {
+ const int pixels_per_byte = 1 << transform->bits_;
+ const int count_mask = pixels_per_byte - 1;
+ const uint32_t bit_mask = (1 << bits_per_pixel) - 1;
+ for (y = y_start; y < y_end; ++y) {
+ uint32_t packed_pixels = 0;
+ int x;
+ for (x = 0; x < width; ++x) {
+ // We need to load fresh 'packed_pixels' once every 'pixels_per_byte'
+ // increments of x. Fortunately, pixels_per_byte is a power of 2, so
+ // can just use a mask for that, instead of decrementing a counter.
+ if ((x & count_mask) == 0) packed_pixels = ((*src++) >> 8) & 0xff;
+ *dst++ = color_map[packed_pixels & bit_mask];
+ packed_pixels >>= bits_per_pixel;
+ }
+ }
+ } else {
+ for (y = y_start; y < y_end; ++y) {
+ int x;
+ for (x = 0; x < width; ++x) {
+ *dst++ = color_map[((*src++) >> 8) & 0xff];
+ }
+ }
+ }
+}
+
+void VP8LInverseTransform(const VP8LTransform* const transform,
+ int row_start, int row_end,
+ const uint32_t* const in, uint32_t* const out) {
+ assert(row_start < row_end);
+ assert(row_end <= transform->ysize_);
+ switch (transform->type_) {
+ case SUBTRACT_GREEN:
+ AddGreenToBlueAndRed(transform, row_start, row_end, out);
+ break;
+ case PREDICTOR_TRANSFORM:
+ PredictorInverseTransform(transform, row_start, row_end, out);
+ if (row_end != transform->ysize_) {
+ // The last predicted row in this iteration will be the top-pred row
+ // for the first row in next iteration.
+ const int width = transform->xsize_;
+ memcpy(out - width, out + (row_end - row_start - 1) * width,
+ width * sizeof(*out));
+ }
+ break;
+ case CROSS_COLOR_TRANSFORM:
+ ColorSpaceInverseTransform(transform, row_start, row_end, out);
+ break;
+ case COLOR_INDEXING_TRANSFORM:
+ if (in == out && transform->bits_ > 0) {
+ // Move packed pixels to the end of unpacked region, so that unpacking
+ // can occur seamlessly.
+ // Also, note that this is the only transform that applies on
+ // the effective width of VP8LSubSampleSize(xsize_, bits_). All other
+ // transforms work on effective width of xsize_.
+ const int out_stride = (row_end - row_start) * transform->xsize_;
+ const int in_stride = (row_end - row_start) *
+ VP8LSubSampleSize(transform->xsize_, transform->bits_);
+ uint32_t* const src = out + out_stride - in_stride;
+ memmove(src, out, in_stride * sizeof(*src));
+ ColorIndexInverseTransform(transform, row_start, row_end, src, out);
+ } else {
+ ColorIndexInverseTransform(transform, row_start, row_end, in, out);
+ }
+ break;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Color space conversion.
+
+static int is_big_endian(void) {
+ static const union {
+ uint16_t w;
+ uint8_t b[2];
+ } tmp = { 1 };
+ return (tmp.b[0] != 1);
+}
+
+static void ConvertBGRAToRGB(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const uint32_t* const src_end = src + num_pixels;
+ while (src < src_end) {
+ const uint32_t argb = *src++;
+ *dst++ = (argb >> 16) & 0xff;
+ *dst++ = (argb >> 8) & 0xff;
+ *dst++ = (argb >> 0) & 0xff;
+ }
+}
+
+static void ConvertBGRAToRGBA(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const uint32_t* const src_end = src + num_pixels;
+ while (src < src_end) {
+ const uint32_t argb = *src++;
+ *dst++ = (argb >> 16) & 0xff;
+ *dst++ = (argb >> 8) & 0xff;
+ *dst++ = (argb >> 0) & 0xff;
+ *dst++ = (argb >> 24) & 0xff;
+ }
+}
+
+static void ConvertBGRAToRGBA4444(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const uint32_t* const src_end = src + num_pixels;
+ while (src < src_end) {
+ const uint32_t argb = *src++;
+ *dst++ = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf);
+ *dst++ = ((argb >> 0) & 0xf0) | ((argb >> 28) & 0xf);
+ }
+}
+
+static void ConvertBGRAToRGB565(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const uint32_t* const src_end = src + num_pixels;
+ while (src < src_end) {
+ const uint32_t argb = *src++;
+ *dst++ = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7);
+ *dst++ = ((argb >> 5) & 0xe0) | ((argb >> 3) & 0x1f);
+ }
+}
+
+static void ConvertBGRAToBGR(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const uint32_t* const src_end = src + num_pixels;
+ while (src < src_end) {
+ const uint32_t argb = *src++;
+ *dst++ = (argb >> 0) & 0xff;
+ *dst++ = (argb >> 8) & 0xff;
+ *dst++ = (argb >> 16) & 0xff;
+ }
+}
+
+static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst,
+ int swap_on_big_endian) {
+ if (is_big_endian() == swap_on_big_endian) {
+ const uint32_t* const src_end = src + num_pixels;
+ while (src < src_end) {
+ uint32_t argb = *src++;
+#if !defined(__BIG_ENDIAN__) && (defined(__i386__) || defined(__x86_64__))
+ __asm__ volatile("bswap %0" : "=r"(argb) : "0"(argb));
+ *(uint32_t*)dst = argb;
+ dst += sizeof(argb);
+#elif !defined(__BIG_ENDIAN__) && defined(_MSC_VER)
+ argb = _byteswap_ulong(argb);
+ *(uint32_t*)dst = argb;
+ dst += sizeof(argb);
+#else
+ *dst++ = (argb >> 24) & 0xff;
+ *dst++ = (argb >> 16) & 0xff;
+ *dst++ = (argb >> 8) & 0xff;
+ *dst++ = (argb >> 0) & 0xff;
+#endif
+ }
+ } else {
+ memcpy(dst, src, num_pixels * sizeof(*src));
+ }
+}
+
+void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels,
+ WEBP_CSP_MODE out_colorspace, uint8_t* const rgba) {
+ switch (out_colorspace) {
+ case MODE_RGB:
+ ConvertBGRAToRGB(in_data, num_pixels, rgba);
+ break;
+ case MODE_RGBA:
+ ConvertBGRAToRGBA(in_data, num_pixels, rgba);
+ break;
+ case MODE_rgbA:
+ ConvertBGRAToRGBA(in_data, num_pixels, rgba);
+ WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0);
+ break;
+ case MODE_BGR:
+ ConvertBGRAToBGR(in_data, num_pixels, rgba);
+ break;
+ case MODE_BGRA:
+ CopyOrSwap(in_data, num_pixels, rgba, 1);
+ break;
+ case MODE_bgrA:
+ CopyOrSwap(in_data, num_pixels, rgba, 1);
+ WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0);
+ break;
+ case MODE_ARGB:
+ CopyOrSwap(in_data, num_pixels, rgba, 0);
+ break;
+ case MODE_Argb:
+ CopyOrSwap(in_data, num_pixels, rgba, 0);
+ WebPApplyAlphaMultiply(rgba, 1, num_pixels, 1, 0);
+ break;
+ case MODE_RGBA_4444:
+ ConvertBGRAToRGBA4444(in_data, num_pixels, rgba);
+ break;
+ case MODE_rgbA_4444:
+ ConvertBGRAToRGBA4444(in_data, num_pixels, rgba);
+ WebPApplyAlphaMultiply4444(rgba, num_pixels, 1, 0);
+ break;
+ case MODE_RGB_565:
+ ConvertBGRAToRGB565(in_data, num_pixels, rgba);
+ break;
+ default:
+ assert(0); // Code flow should not reach here.
+ }
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dsp/lossless.h b/drivers/webpold/dsp/lossless.h
new file mode 100644
index 0000000000..7c7d5555ed
--- /dev/null
+++ b/drivers/webpold/dsp/lossless.h
@@ -0,0 +1,82 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Image transforms and color space conversion methods for lossless decoder.
+//
+// Authors: Vikas Arora (vikaas.arora@gmail.com)
+// Jyrki Alakuijala (jyrki@google.com)
+
+#ifndef WEBP_DSP_LOSSLESS_H_
+#define WEBP_DSP_LOSSLESS_H_
+
+#include "../types.h"
+#include "../decode.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Image transforms.
+
+struct VP8LTransform; // Defined in dec/vp8li.h.
+
+// Performs inverse transform of data given transform information, start and end
+// rows. Transform will be applied to rows [row_start, row_end[.
+// The *in and *out pointers refer to source and destination data respectively
+// corresponding to the intermediate row (row_start).
+void VP8LInverseTransform(const struct VP8LTransform* const transform,
+ int row_start, int row_end,
+ const uint32_t* const in, uint32_t* const out);
+
+// Subtracts green from blue and red channels.
+void VP8LSubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixs);
+
+void VP8LResidualImage(int width, int height, int bits,
+ uint32_t* const argb, uint32_t* const argb_scratch,
+ uint32_t* const image);
+
+void VP8LColorSpaceTransform(int width, int height, int bits, int step,
+ uint32_t* const argb, uint32_t* image);
+
+//------------------------------------------------------------------------------
+// Color space conversion.
+
+// Converts from BGRA to other color spaces.
+void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels,
+ WEBP_CSP_MODE out_colorspace, uint8_t* const rgba);
+
+//------------------------------------------------------------------------------
+// Misc methods.
+
+// Computes sampled size of 'size' when sampling using 'sampling bits'.
+static WEBP_INLINE uint32_t VP8LSubSampleSize(uint32_t size,
+ uint32_t sampling_bits) {
+ return (size + (1 << sampling_bits) - 1) >> sampling_bits;
+}
+
+// Faster logarithm for integers, with the property of log2(0) == 0.
+float VP8LFastLog2(int v);
+// Fast calculation of v * log2(v) for integer input.
+static WEBP_INLINE float VP8LFastSLog2(int v) { return VP8LFastLog2(v) * v; }
+
+// In-place difference of each component with mod 256.
+static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
+ const uint32_t alpha_and_green =
+ 0x00ff00ffu + (a & 0xff00ff00u) - (b & 0xff00ff00u);
+ const uint32_t red_and_blue =
+ 0xff00ff00u + (a & 0x00ff00ffu) - (b & 0x00ff00ffu);
+ return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif // WEBP_DSP_LOSSLESS_H_
diff --git a/drivers/webpold/dsp/upsampling.c b/drivers/webpold/dsp/upsampling.c
new file mode 100644
index 0000000000..4855eb1432
--- /dev/null
+++ b/drivers/webpold/dsp/upsampling.c
@@ -0,0 +1,357 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// YUV to RGB upsampling functions.
+//
+// Author: somnath@google.com (Somnath Banerjee)
+
+#include "./dsp.h"
+#include "./yuv.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Fancy upsampler
+
+#ifdef FANCY_UPSAMPLING
+
+// Fancy upsampling functions to convert YUV to RGB
+WebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST];
+
+// Given samples laid out in a square as:
+// [a b]
+// [c d]
+// we interpolate u/v as:
+// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16
+// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16
+
+// We process u and v together stashed into 32bit (16bit each).
+#define LOAD_UV(u,v) ((u) | ((v) << 16))
+
+#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \
+static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
+ const uint8_t* top_u, const uint8_t* top_v, \
+ const uint8_t* cur_u, const uint8_t* cur_v, \
+ uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
+ int x; \
+ const int last_pixel_pair = (len - 1) >> 1; \
+ uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \
+ uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \
+ if (top_y) { \
+ const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
+ FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \
+ } \
+ if (bottom_y) { \
+ const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
+ FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \
+ } \
+ for (x = 1; x <= last_pixel_pair; ++x) { \
+ const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \
+ const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \
+ /* precompute invariant values associated with first and second diagonals*/\
+ const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \
+ const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \
+ const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \
+ if (top_y) { \
+ const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \
+ const uint32_t uv1 = (diag_03 + t_uv) >> 1; \
+ FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \
+ top_dst + (2 * x - 1) * XSTEP); \
+ FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \
+ top_dst + (2 * x - 0) * XSTEP); \
+ } \
+ if (bottom_y) { \
+ const uint32_t uv0 = (diag_03 + l_uv) >> 1; \
+ const uint32_t uv1 = (diag_12 + uv) >> 1; \
+ FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \
+ bottom_dst + (2 * x - 1) * XSTEP); \
+ FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \
+ bottom_dst + (2 * x + 0) * XSTEP); \
+ } \
+ tl_uv = t_uv; \
+ l_uv = uv; \
+ } \
+ if (!(len & 1)) { \
+ if (top_y) { \
+ const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
+ FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \
+ top_dst + (len - 1) * XSTEP); \
+ } \
+ if (bottom_y) { \
+ const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
+ FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \
+ bottom_dst + (len - 1) * XSTEP); \
+ } \
+ } \
+}
+
+// All variants implemented.
+UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3)
+UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3)
+UPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4)
+UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4)
+UPSAMPLE_FUNC(UpsampleArgbLinePair, VP8YuvToArgb, 4)
+UPSAMPLE_FUNC(UpsampleRgba4444LinePair, VP8YuvToRgba4444, 2)
+UPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2)
+
+#undef LOAD_UV
+#undef UPSAMPLE_FUNC
+
+#endif // FANCY_UPSAMPLING
+
+//------------------------------------------------------------------------------
+// simple point-sampling
+
+#define SAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \
+static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
+ const uint8_t* u, const uint8_t* v, \
+ uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
+ int i; \
+ for (i = 0; i < len - 1; i += 2) { \
+ FUNC(top_y[0], u[0], v[0], top_dst); \
+ FUNC(top_y[1], u[0], v[0], top_dst + XSTEP); \
+ FUNC(bottom_y[0], u[0], v[0], bottom_dst); \
+ FUNC(bottom_y[1], u[0], v[0], bottom_dst + XSTEP); \
+ top_y += 2; \
+ bottom_y += 2; \
+ u++; \
+ v++; \
+ top_dst += 2 * XSTEP; \
+ bottom_dst += 2 * XSTEP; \
+ } \
+ if (i == len - 1) { /* last one */ \
+ FUNC(top_y[0], u[0], v[0], top_dst); \
+ FUNC(bottom_y[0], u[0], v[0], bottom_dst); \
+ } \
+}
+
+// All variants implemented.
+SAMPLE_FUNC(SampleRgbLinePair, VP8YuvToRgb, 3)
+SAMPLE_FUNC(SampleBgrLinePair, VP8YuvToBgr, 3)
+SAMPLE_FUNC(SampleRgbaLinePair, VP8YuvToRgba, 4)
+SAMPLE_FUNC(SampleBgraLinePair, VP8YuvToBgra, 4)
+SAMPLE_FUNC(SampleArgbLinePair, VP8YuvToArgb, 4)
+SAMPLE_FUNC(SampleRgba4444LinePair, VP8YuvToRgba4444, 2)
+SAMPLE_FUNC(SampleRgb565LinePair, VP8YuvToRgb565, 2)
+
+#undef SAMPLE_FUNC
+
+const WebPSampleLinePairFunc WebPSamplers[MODE_LAST] = {
+ SampleRgbLinePair, // MODE_RGB
+ SampleRgbaLinePair, // MODE_RGBA
+ SampleBgrLinePair, // MODE_BGR
+ SampleBgraLinePair, // MODE_BGRA
+ SampleArgbLinePair, // MODE_ARGB
+ SampleRgba4444LinePair, // MODE_RGBA_4444
+ SampleRgb565LinePair, // MODE_RGB_565
+ SampleRgbaLinePair, // MODE_rgbA
+ SampleBgraLinePair, // MODE_bgrA
+ SampleArgbLinePair, // MODE_Argb
+ SampleRgba4444LinePair // MODE_rgbA_4444
+};
+
+//------------------------------------------------------------------------------
+
+#if !defined(FANCY_UPSAMPLING)
+#define DUAL_SAMPLE_FUNC(FUNC_NAME, FUNC) \
+static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \
+ const uint8_t* top_u, const uint8_t* top_v, \
+ const uint8_t* bot_u, const uint8_t* bot_v, \
+ uint8_t* top_dst, uint8_t* bot_dst, int len) { \
+ const int half_len = len >> 1; \
+ int x; \
+ if (top_dst != NULL) { \
+ for (x = 0; x < half_len; ++x) { \
+ FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \
+ FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \
+ } \
+ if (len & 1) FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x); \
+ } \
+ if (bot_dst != NULL) { \
+ for (x = 0; x < half_len; ++x) { \
+ FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x + 0); \
+ FUNC(bot_y[2 * x + 1], bot_u[x], bot_v[x], bot_dst + 8 * x + 4); \
+ } \
+ if (len & 1) FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x); \
+ } \
+}
+
+DUAL_SAMPLE_FUNC(DualLineSamplerBGRA, VP8YuvToBgra)
+DUAL_SAMPLE_FUNC(DualLineSamplerARGB, VP8YuvToArgb)
+#undef DUAL_SAMPLE_FUNC
+
+#endif // !FANCY_UPSAMPLING
+
+WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last) {
+ WebPInitUpsamplers();
+ VP8YUVInit();
+#ifdef FANCY_UPSAMPLING
+ return WebPUpsamplers[alpha_is_last ? MODE_BGRA : MODE_ARGB];
+#else
+ return (alpha_is_last ? DualLineSamplerBGRA : DualLineSamplerARGB);
+#endif
+}
+
+//------------------------------------------------------------------------------
+// YUV444 converter
+
+#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \
+static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
+ uint8_t* dst, int len) { \
+ int i; \
+ for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \
+}
+
+YUV444_FUNC(Yuv444ToRgb, VP8YuvToRgb, 3)
+YUV444_FUNC(Yuv444ToBgr, VP8YuvToBgr, 3)
+YUV444_FUNC(Yuv444ToRgba, VP8YuvToRgba, 4)
+YUV444_FUNC(Yuv444ToBgra, VP8YuvToBgra, 4)
+YUV444_FUNC(Yuv444ToArgb, VP8YuvToArgb, 4)
+YUV444_FUNC(Yuv444ToRgba4444, VP8YuvToRgba4444, 2)
+YUV444_FUNC(Yuv444ToRgb565, VP8YuvToRgb565, 2)
+
+#undef YUV444_FUNC
+
+const WebPYUV444Converter WebPYUV444Converters[MODE_LAST] = {
+ Yuv444ToRgb, // MODE_RGB
+ Yuv444ToRgba, // MODE_RGBA
+ Yuv444ToBgr, // MODE_BGR
+ Yuv444ToBgra, // MODE_BGRA
+ Yuv444ToArgb, // MODE_ARGB
+ Yuv444ToRgba4444, // MODE_RGBA_4444
+ Yuv444ToRgb565, // MODE_RGB_565
+ Yuv444ToRgba, // MODE_rgbA
+ Yuv444ToBgra, // MODE_bgrA
+ Yuv444ToArgb, // MODE_Argb
+ Yuv444ToRgba4444 // MODE_rgbA_4444
+};
+
+//------------------------------------------------------------------------------
+// Premultiplied modes
+
+// non dithered-modes
+
+// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.)
+// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5),
+// one can use instead: (x * a * 65793 + (1 << 23)) >> 24
+#if 1 // (int)(x * a / 255.)
+#define MULTIPLIER(a) ((a) * 32897UL)
+#define PREMULTIPLY(x, m) (((x) * (m)) >> 23)
+#else // (int)(x * a / 255. + .5)
+#define MULTIPLIER(a) ((a) * 65793UL)
+#define PREMULTIPLY(x, m) (((x) * (m) + (1UL << 23)) >> 24)
+#endif
+
+static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first,
+ int w, int h, int stride) {
+ while (h-- > 0) {
+ uint8_t* const rgb = rgba + (alpha_first ? 1 : 0);
+ const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3);
+ int i;
+ for (i = 0; i < w; ++i) {
+ const uint32_t a = alpha[4 * i];
+ if (a != 0xff) {
+ const uint32_t mult = MULTIPLIER(a);
+ rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult);
+ rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult);
+ rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult);
+ }
+ }
+ rgba += stride;
+ }
+}
+#undef MULTIPLIER
+#undef PREMULTIPLY
+
+// rgbA4444
+
+#define MULTIPLIER(a) ((a) * 0x1111) // 0x1111 ~= (1 << 16) / 15
+
+static WEBP_INLINE uint8_t dither_hi(uint8_t x) {
+ return (x & 0xf0) | (x >> 4);
+}
+
+static WEBP_INLINE uint8_t dither_lo(uint8_t x) {
+ return (x & 0x0f) | (x << 4);
+}
+
+static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) {
+ return (x * m) >> 16;
+}
+
+static void ApplyAlphaMultiply4444(uint8_t* rgba4444,
+ int w, int h, int stride) {
+ while (h-- > 0) {
+ int i;
+ for (i = 0; i < w; ++i) {
+ const uint8_t a = (rgba4444[2 * i + 1] & 0x0f);
+ const uint32_t mult = MULTIPLIER(a);
+ const uint8_t r = multiply(dither_hi(rgba4444[2 * i + 0]), mult);
+ const uint8_t g = multiply(dither_lo(rgba4444[2 * i + 0]), mult);
+ const uint8_t b = multiply(dither_hi(rgba4444[2 * i + 1]), mult);
+ rgba4444[2 * i + 0] = (r & 0xf0) | ((g >> 4) & 0x0f);
+ rgba4444[2 * i + 1] = (b & 0xf0) | a;
+ }
+ rgba4444 += stride;
+ }
+}
+#undef MULTIPLIER
+
+void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int)
+ = ApplyAlphaMultiply;
+void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int)
+ = ApplyAlphaMultiply4444;
+
+//------------------------------------------------------------------------------
+// Main call
+
+void WebPInitUpsamplers(void) {
+#ifdef FANCY_UPSAMPLING
+ WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
+ WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
+ WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair;
+ WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair;
+ WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair;
+ WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair;
+ WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair;
+
+ // If defined, use CPUInfo() to overwrite some pointers with faster versions.
+ if (VP8GetCPUInfo != NULL) {
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ WebPInitUpsamplersSSE2();
+ }
+#endif
+ }
+#endif // FANCY_UPSAMPLING
+}
+
+void WebPInitPremultiply(void) {
+ WebPApplyAlphaMultiply = ApplyAlphaMultiply;
+ WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply4444;
+
+#ifdef FANCY_UPSAMPLING
+ WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair;
+ WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair;
+ WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair;
+ WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair;
+
+ if (VP8GetCPUInfo != NULL) {
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ WebPInitPremultiplySSE2();
+ }
+#endif
+ }
+#endif // FANCY_UPSAMPLING
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dsp/upsampling_sse2.c b/drivers/webpold/dsp/upsampling_sse2.c
new file mode 100644
index 0000000000..8cb275a02b
--- /dev/null
+++ b/drivers/webpold/dsp/upsampling_sse2.c
@@ -0,0 +1,209 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// SSE2 version of YUV to RGB upsampling functions.
+//
+// Author: somnath@google.com (Somnath Banerjee)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_SSE2)
+
+#include <assert.h>
+#include <emmintrin.h>
+#include <string.h>
+#include "./yuv.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#ifdef FANCY_UPSAMPLING
+
+// We compute (9*a + 3*b + 3*c + d + 8) / 16 as follows
+// u = (9*a + 3*b + 3*c + d + 8) / 16
+// = (a + (a + 3*b + 3*c + d) / 8 + 1) / 2
+// = (a + m + 1) / 2
+// where m = (a + 3*b + 3*c + d) / 8
+// = ((a + b + c + d) / 2 + b + c) / 4
+//
+// Let's say k = (a + b + c + d) / 4.
+// We can compute k as
+// k = (s + t + 1) / 2 - ((a^d) | (b^c) | (s^t)) & 1
+// where s = (a + d + 1) / 2 and t = (b + c + 1) / 2
+//
+// Then m can be written as
+// m = (k + t + 1) / 2 - (((b^c) & (s^t)) | (k^t)) & 1
+
+// Computes out = (k + in + 1) / 2 - ((ij & (s^t)) | (k^in)) & 1
+#define GET_M(ij, in, out) do { \
+ const __m128i tmp0 = _mm_avg_epu8(k, (in)); /* (k + in + 1) / 2 */ \
+ const __m128i tmp1 = _mm_and_si128((ij), st); /* (ij) & (s^t) */ \
+ const __m128i tmp2 = _mm_xor_si128(k, (in)); /* (k^in) */ \
+ const __m128i tmp3 = _mm_or_si128(tmp1, tmp2); /* ((ij) & (s^t)) | (k^in) */\
+ const __m128i tmp4 = _mm_and_si128(tmp3, one); /* & 1 -> lsb_correction */ \
+ (out) = _mm_sub_epi8(tmp0, tmp4); /* (k + in + 1) / 2 - lsb_correction */ \
+} while (0)
+
+// pack and store two alterning pixel rows
+#define PACK_AND_STORE(a, b, da, db, out) do { \
+ const __m128i ta = _mm_avg_epu8(a, da); /* (9a + 3b + 3c + d + 8) / 16 */ \
+ const __m128i tb = _mm_avg_epu8(b, db); /* (3a + 9b + c + 3d + 8) / 16 */ \
+ const __m128i t1 = _mm_unpacklo_epi8(ta, tb); \
+ const __m128i t2 = _mm_unpackhi_epi8(ta, tb); \
+ _mm_store_si128(((__m128i*)(out)) + 0, t1); \
+ _mm_store_si128(((__m128i*)(out)) + 1, t2); \
+} while (0)
+
+// Loads 17 pixels each from rows r1 and r2 and generates 32 pixels.
+#define UPSAMPLE_32PIXELS(r1, r2, out) { \
+ const __m128i one = _mm_set1_epi8(1); \
+ const __m128i a = _mm_loadu_si128((__m128i*)&(r1)[0]); \
+ const __m128i b = _mm_loadu_si128((__m128i*)&(r1)[1]); \
+ const __m128i c = _mm_loadu_si128((__m128i*)&(r2)[0]); \
+ const __m128i d = _mm_loadu_si128((__m128i*)&(r2)[1]); \
+ \
+ const __m128i s = _mm_avg_epu8(a, d); /* s = (a + d + 1) / 2 */ \
+ const __m128i t = _mm_avg_epu8(b, c); /* t = (b + c + 1) / 2 */ \
+ const __m128i st = _mm_xor_si128(s, t); /* st = s^t */ \
+ \
+ const __m128i ad = _mm_xor_si128(a, d); /* ad = a^d */ \
+ const __m128i bc = _mm_xor_si128(b, c); /* bc = b^c */ \
+ \
+ const __m128i t1 = _mm_or_si128(ad, bc); /* (a^d) | (b^c) */ \
+ const __m128i t2 = _mm_or_si128(t1, st); /* (a^d) | (b^c) | (s^t) */ \
+ const __m128i t3 = _mm_and_si128(t2, one); /* (a^d) | (b^c) | (s^t) & 1 */ \
+ const __m128i t4 = _mm_avg_epu8(s, t); \
+ const __m128i k = _mm_sub_epi8(t4, t3); /* k = (a + b + c + d) / 4 */ \
+ __m128i diag1, diag2; \
+ \
+ GET_M(bc, t, diag1); /* diag1 = (a + 3b + 3c + d) / 8 */ \
+ GET_M(ad, s, diag2); /* diag2 = (3a + b + c + 3d) / 8 */ \
+ \
+ /* pack the alternate pixels */ \
+ PACK_AND_STORE(a, b, diag1, diag2, &(out)[0 * 32]); \
+ PACK_AND_STORE(c, d, diag2, diag1, &(out)[2 * 32]); \
+}
+
+// Turn the macro into a function for reducing code-size when non-critical
+static void Upsample32Pixels(const uint8_t r1[], const uint8_t r2[],
+ uint8_t* const out) {
+ UPSAMPLE_32PIXELS(r1, r2, out);
+}
+
+#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \
+ uint8_t r1[17], r2[17]; \
+ memcpy(r1, (tb), (num_pixels)); \
+ memcpy(r2, (bb), (num_pixels)); \
+ /* replicate last byte */ \
+ memset(r1 + (num_pixels), r1[(num_pixels) - 1], 17 - (num_pixels)); \
+ memset(r2 + (num_pixels), r2[(num_pixels) - 1], 17 - (num_pixels)); \
+ /* using the shared function instead of the macro saves ~3k code size */ \
+ Upsample32Pixels(r1, r2, out); \
+}
+
+#define CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, uv, \
+ top_dst, bottom_dst, cur_x, num_pixels) { \
+ int n; \
+ if (top_y) { \
+ for (n = 0; n < (num_pixels); ++n) { \
+ FUNC(top_y[(cur_x) + n], (uv)[n], (uv)[32 + n], \
+ top_dst + ((cur_x) + n) * XSTEP); \
+ } \
+ } \
+ if (bottom_y) { \
+ for (n = 0; n < (num_pixels); ++n) { \
+ FUNC(bottom_y[(cur_x) + n], (uv)[64 + n], (uv)[64 + 32 + n], \
+ bottom_dst + ((cur_x) + n) * XSTEP); \
+ } \
+ } \
+}
+
+#define SSE2_UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \
+static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
+ const uint8_t* top_u, const uint8_t* top_v, \
+ const uint8_t* cur_u, const uint8_t* cur_v, \
+ uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
+ int b; \
+ /* 16 byte aligned array to cache reconstructed u and v */ \
+ uint8_t uv_buf[4 * 32 + 15]; \
+ uint8_t* const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
+ const int uv_len = (len + 1) >> 1; \
+ /* 17 pixels must be read-able for each block */ \
+ const int num_blocks = (uv_len - 1) >> 4; \
+ const int leftover = uv_len - num_blocks * 16; \
+ const int last_pos = 1 + 32 * num_blocks; \
+ \
+ const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \
+ const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \
+ \
+ assert(len > 0); \
+ /* Treat the first pixel in regular way */ \
+ if (top_y) { \
+ const int u0 = (top_u[0] + u_diag) >> 1; \
+ const int v0 = (top_v[0] + v_diag) >> 1; \
+ FUNC(top_y[0], u0, v0, top_dst); \
+ } \
+ if (bottom_y) { \
+ const int u0 = (cur_u[0] + u_diag) >> 1; \
+ const int v0 = (cur_v[0] + v_diag) >> 1; \
+ FUNC(bottom_y[0], u0, v0, bottom_dst); \
+ } \
+ \
+ for (b = 0; b < num_blocks; ++b) { \
+ UPSAMPLE_32PIXELS(top_u, cur_u, r_uv + 0 * 32); \
+ UPSAMPLE_32PIXELS(top_v, cur_v, r_uv + 1 * 32); \
+ CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, r_uv, top_dst, bottom_dst, \
+ 32 * b + 1, 32) \
+ top_u += 16; \
+ cur_u += 16; \
+ top_v += 16; \
+ cur_v += 16; \
+ } \
+ \
+ UPSAMPLE_LAST_BLOCK(top_u, cur_u, leftover, r_uv + 0 * 32); \
+ UPSAMPLE_LAST_BLOCK(top_v, cur_v, leftover, r_uv + 1 * 32); \
+ CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, r_uv, top_dst, bottom_dst, \
+ last_pos, len - last_pos); \
+}
+
+// SSE2 variants of the fancy upsampler.
+SSE2_UPSAMPLE_FUNC(UpsampleRgbLinePairSSE2, VP8YuvToRgb, 3)
+SSE2_UPSAMPLE_FUNC(UpsampleBgrLinePairSSE2, VP8YuvToBgr, 3)
+SSE2_UPSAMPLE_FUNC(UpsampleRgbaLinePairSSE2, VP8YuvToRgba, 4)
+SSE2_UPSAMPLE_FUNC(UpsampleBgraLinePairSSE2, VP8YuvToBgra, 4)
+
+#undef GET_M
+#undef PACK_AND_STORE
+#undef UPSAMPLE_32PIXELS
+#undef UPSAMPLE_LAST_BLOCK
+#undef CONVERT2RGB
+#undef SSE2_UPSAMPLE_FUNC
+
+//------------------------------------------------------------------------------
+
+extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
+
+void WebPInitUpsamplersSSE2(void) {
+ WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePairSSE2;
+ WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePairSSE2;
+ WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePairSSE2;
+ WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePairSSE2;
+}
+
+void WebPInitPremultiplySSE2(void) {
+ WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePairSSE2;
+ WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePairSSE2;
+}
+
+#endif // FANCY_UPSAMPLING
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif // WEBP_USE_SSE2
diff --git a/drivers/webpold/dsp/yuv.c b/drivers/webpold/dsp/yuv.c
new file mode 100644
index 0000000000..7f05f9a3aa
--- /dev/null
+++ b/drivers/webpold/dsp/yuv.c
@@ -0,0 +1,52 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// YUV->RGB conversion function
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./yuv.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+enum { YUV_HALF = 1 << (YUV_FIX - 1) };
+
+int16_t VP8kVToR[256], VP8kUToB[256];
+int32_t VP8kVToG[256], VP8kUToG[256];
+uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN];
+uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN];
+
+static int done = 0;
+
+static WEBP_INLINE uint8_t clip(int v, int max_value) {
+ return v < 0 ? 0 : v > max_value ? max_value : v;
+}
+
+void VP8YUVInit(void) {
+ int i;
+ if (done) {
+ return;
+ }
+ for (i = 0; i < 256; ++i) {
+ VP8kVToR[i] = (89858 * (i - 128) + YUV_HALF) >> YUV_FIX;
+ VP8kUToG[i] = -22014 * (i - 128) + YUV_HALF;
+ VP8kVToG[i] = -45773 * (i - 128);
+ VP8kUToB[i] = (113618 * (i - 128) + YUV_HALF) >> YUV_FIX;
+ }
+ for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) {
+ const int k = ((i - 16) * 76283 + YUV_HALF) >> YUV_FIX;
+ VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255);
+ VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15);
+ }
+ done = 1;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/dsp/yuv.h b/drivers/webpold/dsp/yuv.h
new file mode 100644
index 0000000000..a569109c54
--- /dev/null
+++ b/drivers/webpold/dsp/yuv.h
@@ -0,0 +1,128 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// inline YUV<->RGB conversion function
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_DSP_YUV_H_
+#define WEBP_DSP_YUV_H_
+
+#include "../dec/decode_vp8.h"
+
+//------------------------------------------------------------------------------
+// YUV -> RGB conversion
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+enum { YUV_FIX = 16, // fixed-point precision
+ YUV_RANGE_MIN = -227, // min value of r/g/b output
+ YUV_RANGE_MAX = 256 + 226 // max value of r/g/b output
+};
+extern int16_t VP8kVToR[256], VP8kUToB[256];
+extern int32_t VP8kVToG[256], VP8kUToG[256];
+extern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN];
+extern uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN];
+
+static WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v,
+ uint8_t* const rgb) {
+ const int r_off = VP8kVToR[v];
+ const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
+ const int b_off = VP8kUToB[u];
+ rgb[0] = VP8kClip[y + r_off - YUV_RANGE_MIN];
+ rgb[1] = VP8kClip[y + g_off - YUV_RANGE_MIN];
+ rgb[2] = VP8kClip[y + b_off - YUV_RANGE_MIN];
+}
+
+static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v,
+ uint8_t* const rgb) {
+ const int r_off = VP8kVToR[v];
+ const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
+ const int b_off = VP8kUToB[u];
+ rgb[0] = ((VP8kClip[y + r_off - YUV_RANGE_MIN] & 0xf8) |
+ (VP8kClip[y + g_off - YUV_RANGE_MIN] >> 5));
+ rgb[1] = (((VP8kClip[y + g_off - YUV_RANGE_MIN] << 3) & 0xe0) |
+ (VP8kClip[y + b_off - YUV_RANGE_MIN] >> 3));
+}
+
+static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v,
+ uint8_t* const argb) {
+ argb[0] = 0xff;
+ VP8YuvToRgb(y, u, v, argb + 1);
+}
+
+static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v,
+ uint8_t* const argb) {
+ const int r_off = VP8kVToR[v];
+ const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
+ const int b_off = VP8kUToB[u];
+ // Don't update alpha (last 4 bits of argb[1])
+ argb[0] = ((VP8kClip4Bits[y + r_off - YUV_RANGE_MIN] << 4) |
+ VP8kClip4Bits[y + g_off - YUV_RANGE_MIN]);
+ argb[1] = 0x0f | (VP8kClip4Bits[y + b_off - YUV_RANGE_MIN] << 4);
+}
+
+static WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v,
+ uint8_t* const bgr) {
+ const int r_off = VP8kVToR[v];
+ const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
+ const int b_off = VP8kUToB[u];
+ bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN];
+ bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN];
+ bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN];
+}
+
+static WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v,
+ uint8_t* const bgra) {
+ VP8YuvToBgr(y, u, v, bgra);
+ bgra[3] = 0xff;
+}
+
+static WEBP_INLINE void VP8YuvToRgba(uint8_t y, uint8_t u, uint8_t v,
+ uint8_t* const rgba) {
+ VP8YuvToRgb(y, u, v, rgba);
+ rgba[3] = 0xff;
+}
+
+// Must be called before everything, to initialize the tables.
+void VP8YUVInit(void);
+
+//------------------------------------------------------------------------------
+// RGB -> YUV conversion
+// The exact naming is Y'CbCr, following the ITU-R BT.601 standard.
+// More information at: http://en.wikipedia.org/wiki/YCbCr
+// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16
+// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128
+// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128
+// We use 16bit fixed point operations.
+
+static WEBP_INLINE int VP8ClipUV(int v) {
+ v = (v + (257 << (YUV_FIX + 2 - 1))) >> (YUV_FIX + 2);
+ return ((v & ~0xff) == 0) ? v : (v < 0) ? 0 : 255;
+}
+
+static WEBP_INLINE int VP8RGBToY(int r, int g, int b) {
+ const int kRound = (1 << (YUV_FIX - 1)) + (16 << YUV_FIX);
+ const int luma = 16839 * r + 33059 * g + 6420 * b;
+ return (luma + kRound) >> YUV_FIX; // no need to clip
+}
+
+static WEBP_INLINE int VP8RGBToU(int r, int g, int b) {
+ return VP8ClipUV(-9719 * r - 19081 * g + 28800 * b);
+}
+
+static WEBP_INLINE int VP8RGBToV(int r, int g, int b) {
+ return VP8ClipUV(+28800 * r - 24116 * g - 4684 * b);
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_DSP_YUV_H_ */
diff --git a/drivers/webpold/enc/alpha.c b/drivers/webpold/enc/alpha.c
new file mode 100644
index 0000000000..e554eb7f30
--- /dev/null
+++ b/drivers/webpold/enc/alpha.c
@@ -0,0 +1,330 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Alpha-plane compression.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "./vp8enci.h"
+#include "../utils/filters.h"
+#include "../utils/quant_levels.h"
+#include "../format_constants.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+// -----------------------------------------------------------------------------
+// Encodes the given alpha data via specified compression method 'method'.
+// The pre-processing (quantization) is performed if 'quality' is less than 100.
+// For such cases, the encoding is lossy. The valid range is [0, 100] for
+// 'quality' and [0, 1] for 'method':
+// 'method = 0' - No compression;
+// 'method = 1' - Use lossless coder on the alpha plane only
+// 'filter' values [0, 4] correspond to prediction modes none, horizontal,
+// vertical & gradient filters. The prediction mode 4 will try all the
+// prediction modes 0 to 3 and pick the best one.
+// 'effort_level': specifies how much effort must be spent to try and reduce
+// the compressed output size. In range 0 (quick) to 6 (slow).
+//
+// 'output' corresponds to the buffer containing compressed alpha data.
+// This buffer is allocated by this method and caller should call
+// free(*output) when done.
+// 'output_size' corresponds to size of this compressed alpha buffer.
+//
+// Returns 1 on successfully encoding the alpha and
+// 0 if either:
+// invalid quality or method, or
+// memory allocation for the compressed data fails.
+
+#include "../enc/vp8li.h"
+
+static int EncodeLossless(const uint8_t* const data, int width, int height,
+ int effort_level, // in [0..6] range
+ VP8BitWriter* const bw,
+ WebPAuxStats* const stats) {
+ int ok = 0;
+ WebPConfig config;
+ WebPPicture picture;
+ VP8LBitWriter tmp_bw;
+
+ WebPPictureInit(&picture);
+ picture.width = width;
+ picture.height = height;
+ picture.use_argb = 1;
+ picture.stats = stats;
+ if (!WebPPictureAlloc(&picture)) return 0;
+
+ // Transfer the alpha values to the green channel.
+ {
+ int i, j;
+ uint32_t* dst = picture.argb;
+ const uint8_t* src = data;
+ for (j = 0; j < picture.height; ++j) {
+ for (i = 0; i < picture.width; ++i) {
+ dst[i] = (src[i] << 8) | 0xff000000u;
+ }
+ src += width;
+ dst += picture.argb_stride;
+ }
+ }
+
+ WebPConfigInit(&config);
+ config.lossless = 1;
+ config.method = effort_level; // impact is very small
+ // Set moderate default quality setting for alpha. Higher qualities (80 and
+ // above) could be very slow.
+ config.quality = 10.f + 15.f * effort_level;
+ if (config.quality > 100.f) config.quality = 100.f;
+
+ ok = VP8LBitWriterInit(&tmp_bw, (width * height) >> 3);
+ ok = ok && (VP8LEncodeStream(&config, &picture, &tmp_bw) == VP8_ENC_OK);
+ WebPPictureFree(&picture);
+ if (ok) {
+ const uint8_t* const data = VP8LBitWriterFinish(&tmp_bw);
+ const size_t data_size = VP8LBitWriterNumBytes(&tmp_bw);
+ VP8BitWriterAppend(bw, data, data_size);
+ }
+ VP8LBitWriterDestroy(&tmp_bw);
+ return ok && !bw->error_;
+}
+
+// -----------------------------------------------------------------------------
+
+static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
+ int method, int filter, int reduce_levels,
+ int effort_level, // in [0..6] range
+ uint8_t* const tmp_alpha,
+ VP8BitWriter* const bw,
+ WebPAuxStats* const stats) {
+ int ok = 0;
+ const uint8_t* alpha_src;
+ WebPFilterFunc filter_func;
+ uint8_t header;
+ size_t expected_size;
+ const size_t data_size = width * height;
+
+ assert((uint64_t)data_size == (uint64_t)width * height); // as per spec
+ assert(filter >= 0 && filter < WEBP_FILTER_LAST);
+ assert(method >= ALPHA_NO_COMPRESSION);
+ assert(method <= ALPHA_LOSSLESS_COMPRESSION);
+ assert(sizeof(header) == ALPHA_HEADER_LEN);
+ // TODO(skal): have a common function and #define's to validate alpha params.
+
+ expected_size =
+ (method == ALPHA_NO_COMPRESSION) ? (ALPHA_HEADER_LEN + data_size)
+ : (data_size >> 5);
+ header = method | (filter << 2);
+ if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4;
+
+ VP8BitWriterInit(bw, expected_size);
+ VP8BitWriterAppend(bw, &header, ALPHA_HEADER_LEN);
+
+ filter_func = WebPFilters[filter];
+ if (filter_func) {
+ filter_func(data, width, height, 1, width, tmp_alpha);
+ alpha_src = tmp_alpha;
+ } else {
+ alpha_src = data;
+ }
+
+ if (method == ALPHA_NO_COMPRESSION) {
+ ok = VP8BitWriterAppend(bw, alpha_src, width * height);
+ ok = ok && !bw->error_;
+ } else {
+ ok = EncodeLossless(alpha_src, width, height, effort_level, bw, stats);
+ VP8BitWriterFinish(bw);
+ }
+ return ok;
+}
+
+// -----------------------------------------------------------------------------
+
+// TODO(skal): move to dsp/ ?
+static void CopyPlane(const uint8_t* src, int src_stride,
+ uint8_t* dst, int dst_stride, int width, int height) {
+ while (height-- > 0) {
+ memcpy(dst, src, width);
+ src += src_stride;
+ dst += dst_stride;
+ }
+}
+
+static int EncodeAlpha(VP8Encoder* const enc,
+ int quality, int method, int filter,
+ int effort_level,
+ uint8_t** const output, size_t* const output_size) {
+ const WebPPicture* const pic = enc->pic_;
+ const int width = pic->width;
+ const int height = pic->height;
+
+ uint8_t* quant_alpha = NULL;
+ const size_t data_size = width * height;
+ uint64_t sse = 0;
+ int ok = 1;
+ const int reduce_levels = (quality < 100);
+
+ // quick sanity checks
+ assert((uint64_t)data_size == (uint64_t)width * height); // as per spec
+ assert(enc != NULL && pic != NULL && pic->a != NULL);
+ assert(output != NULL && output_size != NULL);
+ assert(width > 0 && height > 0);
+ assert(pic->a_stride >= width);
+ assert(filter >= WEBP_FILTER_NONE && filter <= WEBP_FILTER_FAST);
+
+ if (quality < 0 || quality > 100) {
+ return 0;
+ }
+
+ if (method < ALPHA_NO_COMPRESSION || method > ALPHA_LOSSLESS_COMPRESSION) {
+ return 0;
+ }
+
+ quant_alpha = (uint8_t*)malloc(data_size);
+ if (quant_alpha == NULL) {
+ return 0;
+ }
+
+ // Extract alpha data (width x height) from raw_data (stride x height).
+ CopyPlane(pic->a, pic->a_stride, quant_alpha, width, width, height);
+
+ if (reduce_levels) { // No Quantization required for 'quality = 100'.
+ // 16 alpha levels gives quite a low MSE w.r.t original alpha plane hence
+ // mapped to moderate quality 70. Hence Quality:[0, 70] -> Levels:[2, 16]
+ // and Quality:]70, 100] -> Levels:]16, 256].
+ const int alpha_levels = (quality <= 70) ? (2 + quality / 5)
+ : (16 + (quality - 70) * 8);
+ ok = QuantizeLevels(quant_alpha, width, height, alpha_levels, &sse);
+ }
+
+ if (ok) {
+ VP8BitWriter bw;
+ int test_filter;
+ uint8_t* filtered_alpha = NULL;
+
+ // We always test WEBP_FILTER_NONE first.
+ ok = EncodeAlphaInternal(quant_alpha, width, height,
+ method, WEBP_FILTER_NONE, reduce_levels,
+ effort_level, NULL, &bw, pic->stats);
+ if (!ok) {
+ VP8BitWriterWipeOut(&bw);
+ goto End;
+ }
+
+ if (filter == WEBP_FILTER_FAST) { // Quick estimate of a second candidate?
+ filter = EstimateBestFilter(quant_alpha, width, height, width);
+ }
+ // Stop?
+ if (filter == WEBP_FILTER_NONE) {
+ goto Ok;
+ }
+
+ filtered_alpha = (uint8_t*)malloc(data_size);
+ ok = (filtered_alpha != NULL);
+ if (!ok) {
+ goto End;
+ }
+
+ // Try the other mode(s).
+ {
+ WebPAuxStats best_stats;
+ size_t best_score = VP8BitWriterSize(&bw);
+
+ memset(&best_stats, 0, sizeof(best_stats)); // prevent spurious warning
+ if (pic->stats != NULL) best_stats = *pic->stats;
+ for (test_filter = WEBP_FILTER_HORIZONTAL;
+ ok && (test_filter <= WEBP_FILTER_GRADIENT);
+ ++test_filter) {
+ VP8BitWriter tmp_bw;
+ if (filter != WEBP_FILTER_BEST && test_filter != filter) {
+ continue;
+ }
+ ok = EncodeAlphaInternal(quant_alpha, width, height,
+ method, test_filter, reduce_levels,
+ effort_level, filtered_alpha, &tmp_bw,
+ pic->stats);
+ if (ok) {
+ const size_t score = VP8BitWriterSize(&tmp_bw);
+ if (score < best_score) {
+ // swap bitwriter objects.
+ VP8BitWriter tmp = tmp_bw;
+ tmp_bw = bw;
+ bw = tmp;
+ best_score = score;
+ if (pic->stats != NULL) best_stats = *pic->stats;
+ }
+ } else {
+ VP8BitWriterWipeOut(&bw);
+ }
+ VP8BitWriterWipeOut(&tmp_bw);
+ }
+ if (pic->stats != NULL) *pic->stats = best_stats;
+ }
+ Ok:
+ if (ok) {
+ *output_size = VP8BitWriterSize(&bw);
+ *output = VP8BitWriterBuf(&bw);
+ if (pic->stats != NULL) { // need stats?
+ pic->stats->coded_size += (int)(*output_size);
+ enc->sse_[3] = sse;
+ }
+ }
+ free(filtered_alpha);
+ }
+ End:
+ free(quant_alpha);
+ return ok;
+}
+
+
+//------------------------------------------------------------------------------
+// Main calls
+
+void VP8EncInitAlpha(VP8Encoder* const enc) {
+ enc->has_alpha_ = WebPPictureHasTransparency(enc->pic_);
+ enc->alpha_data_ = NULL;
+ enc->alpha_data_size_ = 0;
+}
+
+int VP8EncFinishAlpha(VP8Encoder* const enc) {
+ if (enc->has_alpha_) {
+ const WebPConfig* config = enc->config_;
+ uint8_t* tmp_data = NULL;
+ size_t tmp_size = 0;
+ const int effort_level = config->method; // maps to [0..6]
+ const WEBP_FILTER_TYPE filter =
+ (config->alpha_filtering == 0) ? WEBP_FILTER_NONE :
+ (config->alpha_filtering == 1) ? WEBP_FILTER_FAST :
+ WEBP_FILTER_BEST;
+
+ if (!EncodeAlpha(enc, config->alpha_quality, config->alpha_compression,
+ filter, effort_level, &tmp_data, &tmp_size)) {
+ return 0;
+ }
+ if (tmp_size != (uint32_t)tmp_size) { // Sanity check.
+ free(tmp_data);
+ return 0;
+ }
+ enc->alpha_data_size_ = (uint32_t)tmp_size;
+ enc->alpha_data_ = tmp_data;
+ }
+ return WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_);
+}
+
+void VP8EncDeleteAlpha(VP8Encoder* const enc) {
+ free(enc->alpha_data_);
+ enc->alpha_data_ = NULL;
+ enc->alpha_data_size_ = 0;
+ enc->has_alpha_ = 0;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/enc/analysis.c b/drivers/webpold/enc/analysis.c
new file mode 100644
index 0000000000..22cfb492e7
--- /dev/null
+++ b/drivers/webpold/enc/analysis.c
@@ -0,0 +1,364 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Macroblock analysis
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "./vp8enci.h"
+#include "./cost.h"
+#include "../utils/utils.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define MAX_ITERS_K_MEANS 6
+
+static int ClipAlpha(int alpha) {
+ return alpha < 0 ? 0 : alpha > 255 ? 255 : alpha;
+}
+
+//------------------------------------------------------------------------------
+// Smooth the segment map by replacing isolated block by the majority of its
+// neighbours.
+
+static void SmoothSegmentMap(VP8Encoder* const enc) {
+ int n, x, y;
+ const int w = enc->mb_w_;
+ const int h = enc->mb_h_;
+ const int majority_cnt_3_x_3_grid = 5;
+ uint8_t* const tmp = (uint8_t*)WebPSafeMalloc((uint64_t)w * h, sizeof(*tmp));
+ assert((uint64_t)(w * h) == (uint64_t)w * h); // no overflow, as per spec
+
+ if (tmp == NULL) return;
+ for (y = 1; y < h - 1; ++y) {
+ for (x = 1; x < w - 1; ++x) {
+ int cnt[NUM_MB_SEGMENTS] = { 0 };
+ const VP8MBInfo* const mb = &enc->mb_info_[x + w * y];
+ int majority_seg = mb->segment_;
+ // Check the 8 neighbouring segment values.
+ cnt[mb[-w - 1].segment_]++; // top-left
+ cnt[mb[-w + 0].segment_]++; // top
+ cnt[mb[-w + 1].segment_]++; // top-right
+ cnt[mb[ - 1].segment_]++; // left
+ cnt[mb[ + 1].segment_]++; // right
+ cnt[mb[ w - 1].segment_]++; // bottom-left
+ cnt[mb[ w + 0].segment_]++; // bottom
+ cnt[mb[ w + 1].segment_]++; // bottom-right
+ for (n = 0; n < NUM_MB_SEGMENTS; ++n) {
+ if (cnt[n] >= majority_cnt_3_x_3_grid) {
+ majority_seg = n;
+ }
+ }
+ tmp[x + y * w] = majority_seg;
+ }
+ }
+ for (y = 1; y < h - 1; ++y) {
+ for (x = 1; x < w - 1; ++x) {
+ VP8MBInfo* const mb = &enc->mb_info_[x + w * y];
+ mb->segment_ = tmp[x + y * w];
+ }
+ }
+ free(tmp);
+}
+
+//------------------------------------------------------------------------------
+// Finalize Segment probability based on the coding tree
+
+static int GetProba(int a, int b) {
+ int proba;
+ const int total = a + b;
+ if (total == 0) return 255; // that's the default probability.
+ proba = (255 * a + total / 2) / total;
+ return proba;
+}
+
+static void SetSegmentProbas(VP8Encoder* const enc) {
+ int p[NUM_MB_SEGMENTS] = { 0 };
+ int n;
+
+ for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) {
+ const VP8MBInfo* const mb = &enc->mb_info_[n];
+ p[mb->segment_]++;
+ }
+ if (enc->pic_->stats) {
+ for (n = 0; n < NUM_MB_SEGMENTS; ++n) {
+ enc->pic_->stats->segment_size[n] = p[n];
+ }
+ }
+ if (enc->segment_hdr_.num_segments_ > 1) {
+ uint8_t* const probas = enc->proba_.segments_;
+ probas[0] = GetProba(p[0] + p[1], p[2] + p[3]);
+ probas[1] = GetProba(p[0], p[1]);
+ probas[2] = GetProba(p[2], p[3]);
+
+ enc->segment_hdr_.update_map_ =
+ (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255);
+ enc->segment_hdr_.size_ =
+ p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) +
+ p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) +
+ p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) +
+ p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2]));
+ } else {
+ enc->segment_hdr_.update_map_ = 0;
+ enc->segment_hdr_.size_ = 0;
+ }
+}
+
+static WEBP_INLINE int clip(int v, int m, int M) {
+ return v < m ? m : v > M ? M : v;
+}
+
+static void SetSegmentAlphas(VP8Encoder* const enc,
+ const int centers[NUM_MB_SEGMENTS],
+ int mid) {
+ const int nb = enc->segment_hdr_.num_segments_;
+ int min = centers[0], max = centers[0];
+ int n;
+
+ if (nb > 1) {
+ for (n = 0; n < nb; ++n) {
+ if (min > centers[n]) min = centers[n];
+ if (max < centers[n]) max = centers[n];
+ }
+ }
+ if (max == min) max = min + 1;
+ assert(mid <= max && mid >= min);
+ for (n = 0; n < nb; ++n) {
+ const int alpha = 255 * (centers[n] - mid) / (max - min);
+ const int beta = 255 * (centers[n] - min) / (max - min);
+ enc->dqm_[n].alpha_ = clip(alpha, -127, 127);
+ enc->dqm_[n].beta_ = clip(beta, 0, 255);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Simplified k-Means, to assign Nb segments based on alpha-histogram
+
+static void AssignSegments(VP8Encoder* const enc, const int alphas[256]) {
+ const int nb = enc->segment_hdr_.num_segments_;
+ int centers[NUM_MB_SEGMENTS];
+ int weighted_average = 0;
+ int map[256];
+ int a, n, k;
+ int min_a = 0, max_a = 255, range_a;
+ // 'int' type is ok for histo, and won't overflow
+ int accum[NUM_MB_SEGMENTS], dist_accum[NUM_MB_SEGMENTS];
+
+ // bracket the input
+ for (n = 0; n < 256 && alphas[n] == 0; ++n) {}
+ min_a = n;
+ for (n = 255; n > min_a && alphas[n] == 0; --n) {}
+ max_a = n;
+ range_a = max_a - min_a;
+
+ // Spread initial centers evenly
+ for (n = 1, k = 0; n < 2 * nb; n += 2) {
+ centers[k++] = min_a + (n * range_a) / (2 * nb);
+ }
+
+ for (k = 0; k < MAX_ITERS_K_MEANS; ++k) { // few iters are enough
+ int total_weight;
+ int displaced;
+ // Reset stats
+ for (n = 0; n < nb; ++n) {
+ accum[n] = 0;
+ dist_accum[n] = 0;
+ }
+ // Assign nearest center for each 'a'
+ n = 0; // track the nearest center for current 'a'
+ for (a = min_a; a <= max_a; ++a) {
+ if (alphas[a]) {
+ while (n < nb - 1 && abs(a - centers[n + 1]) < abs(a - centers[n])) {
+ n++;
+ }
+ map[a] = n;
+ // accumulate contribution into best centroid
+ dist_accum[n] += a * alphas[a];
+ accum[n] += alphas[a];
+ }
+ }
+ // All point are classified. Move the centroids to the
+ // center of their respective cloud.
+ displaced = 0;
+ weighted_average = 0;
+ total_weight = 0;
+ for (n = 0; n < nb; ++n) {
+ if (accum[n]) {
+ const int new_center = (dist_accum[n] + accum[n] / 2) / accum[n];
+ displaced += abs(centers[n] - new_center);
+ centers[n] = new_center;
+ weighted_average += new_center * accum[n];
+ total_weight += accum[n];
+ }
+ }
+ weighted_average = (weighted_average + total_weight / 2) / total_weight;
+ if (displaced < 5) break; // no need to keep on looping...
+ }
+
+ // Map each original value to the closest centroid
+ for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) {
+ VP8MBInfo* const mb = &enc->mb_info_[n];
+ const int alpha = mb->alpha_;
+ mb->segment_ = map[alpha];
+ mb->alpha_ = centers[map[alpha]]; // just for the record.
+ }
+
+ if (nb > 1) {
+ const int smooth = (enc->config_->preprocessing & 1);
+ if (smooth) SmoothSegmentMap(enc);
+ }
+
+ SetSegmentProbas(enc); // Assign final proba
+ SetSegmentAlphas(enc, centers, weighted_average); // pick some alphas.
+}
+
+//------------------------------------------------------------------------------
+// Macroblock analysis: collect histogram for each mode, deduce the maximal
+// susceptibility and set best modes for this macroblock.
+// Segment assignment is done later.
+
+// Number of modes to inspect for alpha_ evaluation. For high-quality settings,
+// we don't need to test all the possible modes during the analysis phase.
+#define MAX_INTRA16_MODE 2
+#define MAX_INTRA4_MODE 2
+#define MAX_UV_MODE 2
+
+static int MBAnalyzeBestIntra16Mode(VP8EncIterator* const it) {
+ const int max_mode = (it->enc_->method_ >= 3) ? MAX_INTRA16_MODE : 4;
+ int mode;
+ int best_alpha = -1;
+ int best_mode = 0;
+
+ VP8MakeLuma16Preds(it);
+ for (mode = 0; mode < max_mode; ++mode) {
+ const int alpha = VP8CollectHistogram(it->yuv_in_ + Y_OFF,
+ it->yuv_p_ + VP8I16ModeOffsets[mode],
+ 0, 16);
+ if (alpha > best_alpha) {
+ best_alpha = alpha;
+ best_mode = mode;
+ }
+ }
+ VP8SetIntra16Mode(it, best_mode);
+ return best_alpha;
+}
+
+static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it,
+ int best_alpha) {
+ uint8_t modes[16];
+ const int max_mode = (it->enc_->method_ >= 3) ? MAX_INTRA4_MODE : NUM_BMODES;
+ int i4_alpha = 0;
+ VP8IteratorStartI4(it);
+ do {
+ int mode;
+ int best_mode_alpha = -1;
+ const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_];
+
+ VP8MakeIntra4Preds(it);
+ for (mode = 0; mode < max_mode; ++mode) {
+ const int alpha = VP8CollectHistogram(src,
+ it->yuv_p_ + VP8I4ModeOffsets[mode],
+ 0, 1);
+ if (alpha > best_mode_alpha) {
+ best_mode_alpha = alpha;
+ modes[it->i4_] = mode;
+ }
+ }
+ i4_alpha += best_mode_alpha;
+ // Note: we reuse the original samples for predictors
+ } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF));
+
+ if (i4_alpha > best_alpha) {
+ VP8SetIntra4Mode(it, modes);
+ best_alpha = ClipAlpha(i4_alpha);
+ }
+ return best_alpha;
+}
+
+static int MBAnalyzeBestUVMode(VP8EncIterator* const it) {
+ int best_alpha = -1;
+ int best_mode = 0;
+ const int max_mode = (it->enc_->method_ >= 3) ? MAX_UV_MODE : 4;
+ int mode;
+ VP8MakeChroma8Preds(it);
+ for (mode = 0; mode < max_mode; ++mode) {
+ const int alpha = VP8CollectHistogram(it->yuv_in_ + U_OFF,
+ it->yuv_p_ + VP8UVModeOffsets[mode],
+ 16, 16 + 4 + 4);
+ if (alpha > best_alpha) {
+ best_alpha = alpha;
+ best_mode = mode;
+ }
+ }
+ VP8SetIntraUVMode(it, best_mode);
+ return best_alpha;
+}
+
+static void MBAnalyze(VP8EncIterator* const it,
+ int alphas[256], int* const uv_alpha) {
+ const VP8Encoder* const enc = it->enc_;
+ int best_alpha, best_uv_alpha;
+
+ VP8SetIntra16Mode(it, 0); // default: Intra16, DC_PRED
+ VP8SetSkip(it, 0); // not skipped
+ VP8SetSegment(it, 0); // default segment, spec-wise.
+
+ best_alpha = MBAnalyzeBestIntra16Mode(it);
+ if (enc->method_ != 3) {
+ // We go and make a fast decision for intra4/intra16.
+ // It's usually not a good and definitive pick, but helps seeding the stats
+ // about level bit-cost.
+ // TODO(skal): improve criterion.
+ best_alpha = MBAnalyzeBestIntra4Mode(it, best_alpha);
+ }
+ best_uv_alpha = MBAnalyzeBestUVMode(it);
+
+ // Final susceptibility mix
+ best_alpha = (best_alpha + best_uv_alpha + 1) / 2;
+ alphas[best_alpha]++;
+ *uv_alpha += best_uv_alpha;
+ it->mb_->alpha_ = best_alpha; // Informative only.
+}
+
+//------------------------------------------------------------------------------
+// Main analysis loop:
+// Collect all susceptibilities for each macroblock and record their
+// distribution in alphas[]. Segments is assigned a-posteriori, based on
+// this histogram.
+// We also pick an intra16 prediction mode, which shouldn't be considered
+// final except for fast-encode settings. We can also pick some intra4 modes
+// and decide intra4/intra16, but that's usually almost always a bad choice at
+// this stage.
+
+int VP8EncAnalyze(VP8Encoder* const enc) {
+ int ok = 1;
+ int alphas[256] = { 0 };
+ VP8EncIterator it;
+
+ VP8IteratorInit(enc, &it);
+ enc->uv_alpha_ = 0;
+ do {
+ VP8IteratorImport(&it);
+ MBAnalyze(&it, alphas, &enc->uv_alpha_);
+ ok = VP8IteratorProgress(&it, 20);
+ // Let's pretend we have perfect lossless reconstruction.
+ } while (ok && VP8IteratorNext(&it, it.yuv_in_));
+ enc->uv_alpha_ /= enc->mb_w_ * enc->mb_h_;
+ if (ok) AssignSegments(enc, alphas);
+
+ return ok;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/enc/backward_references.c b/drivers/webpold/enc/backward_references.c
new file mode 100644
index 0000000000..b8c8ece806
--- /dev/null
+++ b/drivers/webpold/enc/backward_references.c
@@ -0,0 +1,874 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Author: Jyrki Alakuijala (jyrki@google.com)
+//
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+
+#include "./backward_references.h"
+#include "./histogram.h"
+#include "../dsp/lossless.h"
+#include "../utils/color_cache.h"
+#include "../utils/utils.h"
+
+#define VALUES_IN_BYTE 256
+
+#define HASH_BITS 18
+#define HASH_SIZE (1 << HASH_BITS)
+#define HASH_MULTIPLIER (0xc6a4a7935bd1e995ULL)
+
+// 1M window (4M bytes) minus 120 special codes for short distances.
+#define WINDOW_SIZE ((1 << 20) - 120)
+
+// Bounds for the match length.
+#define MIN_LENGTH 2
+#define MAX_LENGTH 4096
+
+typedef struct {
+ // Stores the most recently added position with the given hash value.
+ int32_t hash_to_first_index_[HASH_SIZE];
+ // chain_[pos] stores the previous position with the same hash value
+ // for every pixel in the image.
+ int32_t* chain_;
+} HashChain;
+
+// -----------------------------------------------------------------------------
+
+static const uint8_t plane_to_code_lut[128] = {
+ 96, 73, 55, 39, 23, 13, 5, 1, 255, 255, 255, 255, 255, 255, 255, 255,
+ 101, 78, 58, 42, 26, 16, 8, 2, 0, 3, 9, 17, 27, 43, 59, 79,
+ 102, 86, 62, 46, 32, 20, 10, 6, 4, 7, 11, 21, 33, 47, 63, 87,
+ 105, 90, 70, 52, 37, 28, 18, 14, 12, 15, 19, 29, 38, 53, 71, 91,
+ 110, 99, 82, 66, 48, 35, 30, 24, 22, 25, 31, 36, 49, 67, 83, 100,
+ 115, 108, 94, 76, 64, 50, 44, 40, 34, 41, 45, 51, 65, 77, 95, 109,
+ 118, 113, 103, 92, 80, 68, 60, 56, 54, 57, 61, 69, 81, 93, 104, 114,
+ 119, 116, 111, 106, 97, 88, 84, 74, 72, 75, 85, 89, 98, 107, 112, 117
+};
+
+static int DistanceToPlaneCode(int xsize, int dist) {
+ const int yoffset = dist / xsize;
+ const int xoffset = dist - yoffset * xsize;
+ if (xoffset <= 8 && yoffset < 8) {
+ return plane_to_code_lut[yoffset * 16 + 8 - xoffset] + 1;
+ } else if (xoffset > xsize - 8 && yoffset < 7) {
+ return plane_to_code_lut[(yoffset + 1) * 16 + 8 + (xsize - xoffset)] + 1;
+ }
+ return dist + 120;
+}
+
+static WEBP_INLINE int FindMatchLength(const uint32_t* const array1,
+ const uint32_t* const array2,
+ const int max_limit) {
+ int match_len = 0;
+ while (match_len < max_limit && array1[match_len] == array2[match_len]) {
+ ++match_len;
+ }
+ return match_len;
+}
+
+// -----------------------------------------------------------------------------
+// VP8LBackwardRefs
+
+void VP8LInitBackwardRefs(VP8LBackwardRefs* const refs) {
+ if (refs != NULL) {
+ refs->refs = NULL;
+ refs->size = 0;
+ refs->max_size = 0;
+ }
+}
+
+void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs) {
+ if (refs != NULL) {
+ free(refs->refs);
+ VP8LInitBackwardRefs(refs);
+ }
+}
+
+int VP8LBackwardRefsAlloc(VP8LBackwardRefs* const refs, int max_size) {
+ assert(refs != NULL);
+ refs->size = 0;
+ refs->max_size = 0;
+ refs->refs = (PixOrCopy*)WebPSafeMalloc((uint64_t)max_size,
+ sizeof(*refs->refs));
+ if (refs->refs == NULL) return 0;
+ refs->max_size = max_size;
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+// Hash chains
+
+static WEBP_INLINE uint64_t GetPixPairHash64(const uint32_t* const argb) {
+ uint64_t key = ((uint64_t)(argb[1]) << 32) | argb[0];
+ key = (key * HASH_MULTIPLIER) >> (64 - HASH_BITS);
+ return key;
+}
+
+static int HashChainInit(HashChain* const p, int size) {
+ int i;
+ p->chain_ = (int*)WebPSafeMalloc((uint64_t)size, sizeof(*p->chain_));
+ if (p->chain_ == NULL) {
+ return 0;
+ }
+ for (i = 0; i < size; ++i) {
+ p->chain_[i] = -1;
+ }
+ for (i = 0; i < HASH_SIZE; ++i) {
+ p->hash_to_first_index_[i] = -1;
+ }
+ return 1;
+}
+
+static void HashChainDelete(HashChain* const p) {
+ if (p != NULL) {
+ free(p->chain_);
+ free(p);
+ }
+}
+
+// Insertion of two pixels at a time.
+static void HashChainInsert(HashChain* const p,
+ const uint32_t* const argb, int pos) {
+ const uint64_t hash_code = GetPixPairHash64(argb);
+ p->chain_[pos] = p->hash_to_first_index_[hash_code];
+ p->hash_to_first_index_[hash_code] = pos;
+}
+
+static int HashChainFindCopy(const HashChain* const p,
+ int quality, int index, int xsize,
+ const uint32_t* const argb, int maxlen,
+ int* const distance_ptr,
+ int* const length_ptr) {
+ const uint64_t hash_code = GetPixPairHash64(&argb[index]);
+ int prev_length = 0;
+ int64_t best_val = 0;
+ int best_length = 0;
+ int best_distance = 0;
+ const uint32_t* const argb_start = argb + index;
+ const int iter_min_mult = (quality < 50) ? 2 : (quality < 75) ? 4 : 8;
+ const int iter_min = -quality * iter_min_mult;
+ int iter_cnt = 10 + (quality >> 1);
+ const int min_pos = (index > WINDOW_SIZE) ? index - WINDOW_SIZE : 0;
+ int pos;
+
+ assert(xsize > 0);
+ for (pos = p->hash_to_first_index_[hash_code];
+ pos >= min_pos;
+ pos = p->chain_[pos]) {
+ int64_t val;
+ int curr_length;
+ if (iter_cnt < 0) {
+ if (iter_cnt < iter_min || best_val >= 0xff0000) {
+ break;
+ }
+ }
+ --iter_cnt;
+ if (best_length != 0 &&
+ argb[pos + best_length - 1] != argb_start[best_length - 1]) {
+ continue;
+ }
+ curr_length = FindMatchLength(argb + pos, argb_start, maxlen);
+ if (curr_length < prev_length) {
+ continue;
+ }
+ val = 65536 * curr_length;
+ // Favoring 2d locality here gives savings for certain images.
+ if (index - pos < 9 * xsize) {
+ const int y = (index - pos) / xsize;
+ int x = (index - pos) % xsize;
+ if (x > xsize / 2) {
+ x = xsize - x;
+ }
+ if (x <= 7 && x >= -8) {
+ val -= y * y + x * x;
+ } else {
+ val -= 9 * 9 + 9 * 9;
+ }
+ } else {
+ val -= 9 * 9 + 9 * 9;
+ }
+ if (best_val < val) {
+ prev_length = curr_length;
+ best_val = val;
+ best_length = curr_length;
+ best_distance = index - pos;
+ if (curr_length >= MAX_LENGTH) {
+ break;
+ }
+ if ((best_distance == 1 || best_distance == xsize) &&
+ best_length >= 128) {
+ break;
+ }
+ }
+ }
+ *distance_ptr = best_distance;
+ *length_ptr = best_length;
+ return (best_length >= MIN_LENGTH);
+}
+
+static WEBP_INLINE void PushBackCopy(VP8LBackwardRefs* const refs, int length) {
+ int size = refs->size;
+ while (length >= MAX_LENGTH) {
+ refs->refs[size++] = PixOrCopyCreateCopy(1, MAX_LENGTH);
+ length -= MAX_LENGTH;
+ }
+ if (length > 0) {
+ refs->refs[size++] = PixOrCopyCreateCopy(1, length);
+ }
+ refs->size = size;
+}
+
+static void BackwardReferencesRle(int xsize, int ysize,
+ const uint32_t* const argb,
+ VP8LBackwardRefs* const refs) {
+ const int pix_count = xsize * ysize;
+ int match_len = 0;
+ int i;
+ refs->size = 0;
+ PushBackCopy(refs, match_len); // i=0 case
+ refs->refs[refs->size++] = PixOrCopyCreateLiteral(argb[0]);
+ for (i = 1; i < pix_count; ++i) {
+ if (argb[i] == argb[i - 1]) {
+ ++match_len;
+ } else {
+ PushBackCopy(refs, match_len);
+ match_len = 0;
+ refs->refs[refs->size++] = PixOrCopyCreateLiteral(argb[i]);
+ }
+ }
+ PushBackCopy(refs, match_len);
+}
+
+static int BackwardReferencesHashChain(int xsize, int ysize,
+ const uint32_t* const argb,
+ int cache_bits, int quality,
+ VP8LBackwardRefs* const refs) {
+ int i;
+ int ok = 0;
+ int cc_init = 0;
+ const int use_color_cache = (cache_bits > 0);
+ const int pix_count = xsize * ysize;
+ HashChain* const hash_chain = (HashChain*)malloc(sizeof(*hash_chain));
+ VP8LColorCache hashers;
+
+ if (hash_chain == NULL) return 0;
+ if (use_color_cache) {
+ cc_init = VP8LColorCacheInit(&hashers, cache_bits);
+ if (!cc_init) goto Error;
+ }
+
+ if (!HashChainInit(hash_chain, pix_count)) goto Error;
+
+ refs->size = 0;
+ for (i = 0; i < pix_count; ) {
+ // Alternative#1: Code the pixels starting at 'i' using backward reference.
+ int offset = 0;
+ int len = 0;
+ if (i < pix_count - 1) { // FindCopy(i,..) reads pixels at [i] and [i + 1].
+ int maxlen = pix_count - i;
+ if (maxlen > MAX_LENGTH) {
+ maxlen = MAX_LENGTH;
+ }
+ HashChainFindCopy(hash_chain, quality, i, xsize, argb, maxlen,
+ &offset, &len);
+ }
+ if (len >= MIN_LENGTH) {
+ // Alternative#2: Insert the pixel at 'i' as literal, and code the
+ // pixels starting at 'i + 1' using backward reference.
+ int offset2 = 0;
+ int len2 = 0;
+ int k;
+ HashChainInsert(hash_chain, &argb[i], i);
+ if (i < pix_count - 2) { // FindCopy(i+1,..) reads [i + 1] and [i + 2].
+ int maxlen = pix_count - (i + 1);
+ if (maxlen > MAX_LENGTH) {
+ maxlen = MAX_LENGTH;
+ }
+ HashChainFindCopy(hash_chain, quality,
+ i + 1, xsize, argb, maxlen, &offset2, &len2);
+ if (len2 > len + 1) {
+ const uint32_t pixel = argb[i];
+ // Alternative#2 is a better match. So push pixel at 'i' as literal.
+ if (use_color_cache && VP8LColorCacheContains(&hashers, pixel)) {
+ const int ix = VP8LColorCacheGetIndex(&hashers, pixel);
+ refs->refs[refs->size] = PixOrCopyCreateCacheIdx(ix);
+ } else {
+ refs->refs[refs->size] = PixOrCopyCreateLiteral(pixel);
+ }
+ ++refs->size;
+ if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel);
+ i++; // Backward reference to be done for next pixel.
+ len = len2;
+ offset = offset2;
+ }
+ }
+ if (len >= MAX_LENGTH) {
+ len = MAX_LENGTH - 1;
+ }
+ refs->refs[refs->size++] = PixOrCopyCreateCopy(offset, len);
+ if (use_color_cache) {
+ for (k = 0; k < len; ++k) {
+ VP8LColorCacheInsert(&hashers, argb[i + k]);
+ }
+ }
+ // Add to the hash_chain (but cannot add the last pixel).
+ {
+ const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i;
+ for (k = 1; k < last; ++k) {
+ HashChainInsert(hash_chain, &argb[i + k], i + k);
+ }
+ }
+ i += len;
+ } else {
+ const uint32_t pixel = argb[i];
+ if (use_color_cache && VP8LColorCacheContains(&hashers, pixel)) {
+ // push pixel as a PixOrCopyCreateCacheIdx pixel
+ const int ix = VP8LColorCacheGetIndex(&hashers, pixel);
+ refs->refs[refs->size] = PixOrCopyCreateCacheIdx(ix);
+ } else {
+ refs->refs[refs->size] = PixOrCopyCreateLiteral(pixel);
+ }
+ ++refs->size;
+ if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel);
+ if (i + 1 < pix_count) {
+ HashChainInsert(hash_chain, &argb[i], i);
+ }
+ ++i;
+ }
+ }
+ ok = 1;
+Error:
+ if (cc_init) VP8LColorCacheClear(&hashers);
+ HashChainDelete(hash_chain);
+ return ok;
+}
+
+// -----------------------------------------------------------------------------
+
+typedef struct {
+ double alpha_[VALUES_IN_BYTE];
+ double red_[VALUES_IN_BYTE];
+ double literal_[PIX_OR_COPY_CODES_MAX];
+ double blue_[VALUES_IN_BYTE];
+ double distance_[NUM_DISTANCE_CODES];
+} CostModel;
+
+static int BackwardReferencesTraceBackwards(
+ int xsize, int ysize, int recursive_cost_model,
+ const uint32_t* const argb, int cache_bits, VP8LBackwardRefs* const refs);
+
+static void ConvertPopulationCountTableToBitEstimates(
+ int num_symbols, const int population_counts[], double output[]) {
+ int sum = 0;
+ int nonzeros = 0;
+ int i;
+ for (i = 0; i < num_symbols; ++i) {
+ sum += population_counts[i];
+ if (population_counts[i] > 0) {
+ ++nonzeros;
+ }
+ }
+ if (nonzeros <= 1) {
+ memset(output, 0, num_symbols * sizeof(*output));
+ } else {
+ const double logsum = VP8LFastLog2(sum);
+ for (i = 0; i < num_symbols; ++i) {
+ output[i] = logsum - VP8LFastLog2(population_counts[i]);
+ }
+ }
+}
+
+static int CostModelBuild(CostModel* const m, int xsize, int ysize,
+ int recursion_level, const uint32_t* const argb,
+ int cache_bits) {
+ int ok = 0;
+ VP8LHistogram histo;
+ VP8LBackwardRefs refs;
+ const int quality = 100;
+
+ if (!VP8LBackwardRefsAlloc(&refs, xsize * ysize)) goto Error;
+
+ if (recursion_level > 0) {
+ if (!BackwardReferencesTraceBackwards(xsize, ysize, recursion_level - 1,
+ argb, cache_bits, &refs)) {
+ goto Error;
+ }
+ } else {
+ if (!BackwardReferencesHashChain(xsize, ysize, argb, cache_bits, quality,
+ &refs)) {
+ goto Error;
+ }
+ }
+ VP8LHistogramCreate(&histo, &refs, cache_bits);
+ ConvertPopulationCountTableToBitEstimates(
+ VP8LHistogramNumCodes(&histo), histo.literal_, m->literal_);
+ ConvertPopulationCountTableToBitEstimates(
+ VALUES_IN_BYTE, histo.red_, m->red_);
+ ConvertPopulationCountTableToBitEstimates(
+ VALUES_IN_BYTE, histo.blue_, m->blue_);
+ ConvertPopulationCountTableToBitEstimates(
+ VALUES_IN_BYTE, histo.alpha_, m->alpha_);
+ ConvertPopulationCountTableToBitEstimates(
+ NUM_DISTANCE_CODES, histo.distance_, m->distance_);
+ ok = 1;
+
+ Error:
+ VP8LClearBackwardRefs(&refs);
+ return ok;
+}
+
+static WEBP_INLINE double GetLiteralCost(const CostModel* const m, uint32_t v) {
+ return m->alpha_[v >> 24] +
+ m->red_[(v >> 16) & 0xff] +
+ m->literal_[(v >> 8) & 0xff] +
+ m->blue_[v & 0xff];
+}
+
+static WEBP_INLINE double GetCacheCost(const CostModel* const m, uint32_t idx) {
+ const int literal_idx = VALUES_IN_BYTE + NUM_LENGTH_CODES + idx;
+ return m->literal_[literal_idx];
+}
+
+static WEBP_INLINE double GetLengthCost(const CostModel* const m,
+ uint32_t length) {
+ int code, extra_bits_count, extra_bits_value;
+ PrefixEncode(length, &code, &extra_bits_count, &extra_bits_value);
+ return m->literal_[VALUES_IN_BYTE + code] + extra_bits_count;
+}
+
+static WEBP_INLINE double GetDistanceCost(const CostModel* const m,
+ uint32_t distance) {
+ int code, extra_bits_count, extra_bits_value;
+ PrefixEncode(distance, &code, &extra_bits_count, &extra_bits_value);
+ return m->distance_[code] + extra_bits_count;
+}
+
+static int BackwardReferencesHashChainDistanceOnly(
+ int xsize, int ysize, int recursive_cost_model, const uint32_t* const argb,
+ int cache_bits, uint32_t* const dist_array) {
+ int i;
+ int ok = 0;
+ int cc_init = 0;
+ const int quality = 100;
+ const int pix_count = xsize * ysize;
+ const int use_color_cache = (cache_bits > 0);
+ double* const cost =
+ (double*)WebPSafeMalloc((uint64_t)pix_count, sizeof(*cost));
+ CostModel* cost_model = (CostModel*)malloc(sizeof(*cost_model));
+ HashChain* hash_chain = (HashChain*)malloc(sizeof(*hash_chain));
+ VP8LColorCache hashers;
+ const double mul0 = (recursive_cost_model != 0) ? 1.0 : 0.68;
+ const double mul1 = (recursive_cost_model != 0) ? 1.0 : 0.82;
+
+ if (cost == NULL || cost_model == NULL || hash_chain == NULL) goto Error;
+
+ if (!HashChainInit(hash_chain, pix_count)) goto Error;
+
+ if (use_color_cache) {
+ cc_init = VP8LColorCacheInit(&hashers, cache_bits);
+ if (!cc_init) goto Error;
+ }
+
+ if (!CostModelBuild(cost_model, xsize, ysize, recursive_cost_model, argb,
+ cache_bits)) {
+ goto Error;
+ }
+
+ for (i = 0; i < pix_count; ++i) cost[i] = 1e100;
+
+ // We loop one pixel at a time, but store all currently best points to
+ // non-processed locations from this point.
+ dist_array[0] = 0;
+ for (i = 0; i < pix_count; ++i) {
+ double prev_cost = 0.0;
+ int shortmax;
+ if (i > 0) {
+ prev_cost = cost[i - 1];
+ }
+ for (shortmax = 0; shortmax < 2; ++shortmax) {
+ int offset = 0;
+ int len = 0;
+ if (i < pix_count - 1) { // FindCopy reads pixels at [i] and [i + 1].
+ int maxlen = shortmax ? 2 : MAX_LENGTH;
+ if (maxlen > pix_count - i) {
+ maxlen = pix_count - i;
+ }
+ HashChainFindCopy(hash_chain, quality, i, xsize, argb, maxlen,
+ &offset, &len);
+ }
+ if (len >= MIN_LENGTH) {
+ const int code = DistanceToPlaneCode(xsize, offset);
+ const double distance_cost =
+ prev_cost + GetDistanceCost(cost_model, code);
+ int k;
+ for (k = 1; k < len; ++k) {
+ const double cost_val =
+ distance_cost + GetLengthCost(cost_model, k);
+ if (cost[i + k] > cost_val) {
+ cost[i + k] = cost_val;
+ dist_array[i + k] = k + 1;
+ }
+ }
+ // This if is for speedup only. It roughly doubles the speed, and
+ // makes compression worse by .1 %.
+ if (len >= 128 && code < 2) {
+ // Long copy for short distances, let's skip the middle
+ // lookups for better copies.
+ // 1) insert the hashes.
+ if (use_color_cache) {
+ for (k = 0; k < len; ++k) {
+ VP8LColorCacheInsert(&hashers, argb[i + k]);
+ }
+ }
+ // 2) Add to the hash_chain (but cannot add the last pixel)
+ {
+ const int last = (len < pix_count - 1 - i) ? len
+ : pix_count - 1 - i;
+ for (k = 0; k < last; ++k) {
+ HashChainInsert(hash_chain, &argb[i + k], i + k);
+ }
+ }
+ // 3) jump.
+ i += len - 1; // for loop does ++i, thus -1 here.
+ goto next_symbol;
+ }
+ }
+ }
+ if (i < pix_count - 1) {
+ HashChainInsert(hash_chain, &argb[i], i);
+ }
+ {
+ // inserting a literal pixel
+ double cost_val = prev_cost;
+ if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) {
+ const int ix = VP8LColorCacheGetIndex(&hashers, argb[i]);
+ cost_val += GetCacheCost(cost_model, ix) * mul0;
+ } else {
+ cost_val += GetLiteralCost(cost_model, argb[i]) * mul1;
+ }
+ if (cost[i] > cost_val) {
+ cost[i] = cost_val;
+ dist_array[i] = 1; // only one is inserted.
+ }
+ if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
+ }
+ next_symbol: ;
+ }
+ // Last pixel still to do, it can only be a single step if not reached
+ // through cheaper means already.
+ ok = 1;
+Error:
+ if (cc_init) VP8LColorCacheClear(&hashers);
+ HashChainDelete(hash_chain);
+ free(cost_model);
+ free(cost);
+ return ok;
+}
+
+static int TraceBackwards(const uint32_t* const dist_array,
+ int dist_array_size,
+ uint32_t** const chosen_path,
+ int* const chosen_path_size) {
+ int i;
+ // Count how many.
+ int count = 0;
+ for (i = dist_array_size - 1; i >= 0; ) {
+ int k = dist_array[i];
+ assert(k >= 1);
+ ++count;
+ i -= k;
+ }
+ // Allocate.
+ *chosen_path_size = count;
+ *chosen_path =
+ (uint32_t*)WebPSafeMalloc((uint64_t)count, sizeof(**chosen_path));
+ if (*chosen_path == NULL) return 0;
+
+ // Write in reverse order.
+ for (i = dist_array_size - 1; i >= 0; ) {
+ int k = dist_array[i];
+ assert(k >= 1);
+ (*chosen_path)[--count] = k;
+ i -= k;
+ }
+ return 1;
+}
+
+static int BackwardReferencesHashChainFollowChosenPath(
+ int xsize, int ysize, const uint32_t* const argb, int cache_bits,
+ const uint32_t* const chosen_path, int chosen_path_size,
+ VP8LBackwardRefs* const refs) {
+ const int quality = 100;
+ const int pix_count = xsize * ysize;
+ const int use_color_cache = (cache_bits > 0);
+ int size = 0;
+ int i = 0;
+ int k;
+ int ix;
+ int ok = 0;
+ int cc_init = 0;
+ HashChain* hash_chain = (HashChain*)malloc(sizeof(*hash_chain));
+ VP8LColorCache hashers;
+
+ if (hash_chain == NULL || !HashChainInit(hash_chain, pix_count)) {
+ goto Error;
+ }
+ if (use_color_cache) {
+ cc_init = VP8LColorCacheInit(&hashers, cache_bits);
+ if (!cc_init) goto Error;
+ }
+
+ refs->size = 0;
+ for (ix = 0; ix < chosen_path_size; ++ix, ++size) {
+ int offset = 0;
+ int len = 0;
+ int maxlen = chosen_path[ix];
+ if (maxlen != 1) {
+ HashChainFindCopy(hash_chain, quality,
+ i, xsize, argb, maxlen, &offset, &len);
+ assert(len == maxlen);
+ refs->refs[size] = PixOrCopyCreateCopy(offset, len);
+ if (use_color_cache) {
+ for (k = 0; k < len; ++k) {
+ VP8LColorCacheInsert(&hashers, argb[i + k]);
+ }
+ }
+ {
+ const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i;
+ for (k = 0; k < last; ++k) {
+ HashChainInsert(hash_chain, &argb[i + k], i + k);
+ }
+ }
+ i += len;
+ } else {
+ if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) {
+ // push pixel as a color cache index
+ const int idx = VP8LColorCacheGetIndex(&hashers, argb[i]);
+ refs->refs[size] = PixOrCopyCreateCacheIdx(idx);
+ } else {
+ refs->refs[size] = PixOrCopyCreateLiteral(argb[i]);
+ }
+ if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
+ if (i + 1 < pix_count) {
+ HashChainInsert(hash_chain, &argb[i], i);
+ }
+ ++i;
+ }
+ }
+ assert(size <= refs->max_size);
+ refs->size = size;
+ ok = 1;
+Error:
+ if (cc_init) VP8LColorCacheClear(&hashers);
+ HashChainDelete(hash_chain);
+ return ok;
+}
+
+// Returns 1 on success.
+static int BackwardReferencesTraceBackwards(int xsize, int ysize,
+ int recursive_cost_model,
+ const uint32_t* const argb,
+ int cache_bits,
+ VP8LBackwardRefs* const refs) {
+ int ok = 0;
+ const int dist_array_size = xsize * ysize;
+ uint32_t* chosen_path = NULL;
+ int chosen_path_size = 0;
+ uint32_t* dist_array =
+ (uint32_t*)WebPSafeMalloc((uint64_t)dist_array_size, sizeof(*dist_array));
+
+ if (dist_array == NULL) goto Error;
+
+ if (!BackwardReferencesHashChainDistanceOnly(
+ xsize, ysize, recursive_cost_model, argb, cache_bits, dist_array)) {
+ goto Error;
+ }
+ if (!TraceBackwards(dist_array, dist_array_size,
+ &chosen_path, &chosen_path_size)) {
+ goto Error;
+ }
+ free(dist_array); // no need to retain this memory any longer
+ dist_array = NULL;
+ if (!BackwardReferencesHashChainFollowChosenPath(
+ xsize, ysize, argb, cache_bits, chosen_path, chosen_path_size, refs)) {
+ goto Error;
+ }
+ ok = 1;
+ Error:
+ free(chosen_path);
+ free(dist_array);
+ return ok;
+}
+
+static void BackwardReferences2DLocality(int xsize,
+ VP8LBackwardRefs* const refs) {
+ int i;
+ for (i = 0; i < refs->size; ++i) {
+ if (PixOrCopyIsCopy(&refs->refs[i])) {
+ const int dist = refs->refs[i].argb_or_distance;
+ const int transformed_dist = DistanceToPlaneCode(xsize, dist);
+ refs->refs[i].argb_or_distance = transformed_dist;
+ }
+ }
+}
+
+int VP8LGetBackwardReferences(int width, int height,
+ const uint32_t* const argb,
+ int quality, int cache_bits, int use_2d_locality,
+ VP8LBackwardRefs* const best) {
+ int ok = 0;
+ int lz77_is_useful;
+ VP8LBackwardRefs refs_rle, refs_lz77;
+ const int num_pix = width * height;
+
+ VP8LBackwardRefsAlloc(&refs_rle, num_pix);
+ VP8LBackwardRefsAlloc(&refs_lz77, num_pix);
+ VP8LInitBackwardRefs(best);
+ if (refs_rle.refs == NULL || refs_lz77.refs == NULL) {
+ Error1:
+ VP8LClearBackwardRefs(&refs_rle);
+ VP8LClearBackwardRefs(&refs_lz77);
+ goto End;
+ }
+
+ if (!BackwardReferencesHashChain(width, height, argb, cache_bits, quality,
+ &refs_lz77)) {
+ goto End;
+ }
+ // Backward Reference using RLE only.
+ BackwardReferencesRle(width, height, argb, &refs_rle);
+
+ {
+ double bit_cost_lz77, bit_cost_rle;
+ VP8LHistogram* const histo = (VP8LHistogram*)malloc(sizeof(*histo));
+ if (histo == NULL) goto Error1;
+ // Evaluate lz77 coding
+ VP8LHistogramCreate(histo, &refs_lz77, cache_bits);
+ bit_cost_lz77 = VP8LHistogramEstimateBits(histo);
+ // Evaluate RLE coding
+ VP8LHistogramCreate(histo, &refs_rle, cache_bits);
+ bit_cost_rle = VP8LHistogramEstimateBits(histo);
+ // Decide if LZ77 is useful.
+ lz77_is_useful = (bit_cost_lz77 < bit_cost_rle);
+ free(histo);
+ }
+
+ // Choose appropriate backward reference.
+ if (lz77_is_useful) {
+ // TraceBackwards is costly. Run it for higher qualities.
+ const int try_lz77_trace_backwards = (quality >= 75);
+ *best = refs_lz77; // default guess: lz77 is better
+ VP8LClearBackwardRefs(&refs_rle);
+ if (try_lz77_trace_backwards) {
+ const int recursion_level = (num_pix < 320 * 200) ? 1 : 0;
+ VP8LBackwardRefs refs_trace;
+ if (!VP8LBackwardRefsAlloc(&refs_trace, num_pix)) {
+ goto End;
+ }
+ if (BackwardReferencesTraceBackwards(
+ width, height, recursion_level, argb, cache_bits, &refs_trace)) {
+ VP8LClearBackwardRefs(&refs_lz77);
+ *best = refs_trace;
+ }
+ }
+ } else {
+ VP8LClearBackwardRefs(&refs_lz77);
+ *best = refs_rle;
+ }
+
+ if (use_2d_locality) BackwardReferences2DLocality(width, best);
+
+ ok = 1;
+
+ End:
+ if (!ok) {
+ VP8LClearBackwardRefs(best);
+ }
+ return ok;
+}
+
+// Returns 1 on success.
+static int ComputeCacheHistogram(const uint32_t* const argb,
+ int xsize, int ysize,
+ const VP8LBackwardRefs* const refs,
+ int cache_bits,
+ VP8LHistogram* const histo) {
+ int pixel_index = 0;
+ int i;
+ uint32_t k;
+ VP8LColorCache hashers;
+ const int use_color_cache = (cache_bits > 0);
+ int cc_init = 0;
+
+ if (use_color_cache) {
+ cc_init = VP8LColorCacheInit(&hashers, cache_bits);
+ if (!cc_init) return 0;
+ }
+
+ for (i = 0; i < refs->size; ++i) {
+ const PixOrCopy* const v = &refs->refs[i];
+ if (PixOrCopyIsLiteral(v)) {
+ if (use_color_cache &&
+ VP8LColorCacheContains(&hashers, argb[pixel_index])) {
+ // push pixel as a cache index
+ const int ix = VP8LColorCacheGetIndex(&hashers, argb[pixel_index]);
+ const PixOrCopy token = PixOrCopyCreateCacheIdx(ix);
+ VP8LHistogramAddSinglePixOrCopy(histo, &token);
+ } else {
+ VP8LHistogramAddSinglePixOrCopy(histo, v);
+ }
+ } else {
+ VP8LHistogramAddSinglePixOrCopy(histo, v);
+ }
+ if (use_color_cache) {
+ for (k = 0; k < PixOrCopyLength(v); ++k) {
+ VP8LColorCacheInsert(&hashers, argb[pixel_index + k]);
+ }
+ }
+ pixel_index += PixOrCopyLength(v);
+ }
+ assert(pixel_index == xsize * ysize);
+ (void)xsize; // xsize is not used in non-debug compilations otherwise.
+ (void)ysize; // ysize is not used in non-debug compilations otherwise.
+ if (cc_init) VP8LColorCacheClear(&hashers);
+ return 1;
+}
+
+// Returns how many bits are to be used for a color cache.
+int VP8LCalculateEstimateForCacheSize(const uint32_t* const argb,
+ int xsize, int ysize,
+ int* const best_cache_bits) {
+ int ok = 0;
+ int cache_bits;
+ double lowest_entropy = 1e99;
+ VP8LBackwardRefs refs;
+ static const double kSmallPenaltyForLargeCache = 4.0;
+ static const int quality = 30;
+ if (!VP8LBackwardRefsAlloc(&refs, xsize * ysize) ||
+ !BackwardReferencesHashChain(xsize, ysize, argb, 0, quality, &refs)) {
+ goto Error;
+ }
+ for (cache_bits = 0; cache_bits <= MAX_COLOR_CACHE_BITS; ++cache_bits) {
+ double cur_entropy;
+ VP8LHistogram histo;
+ VP8LHistogramInit(&histo, cache_bits);
+ ComputeCacheHistogram(argb, xsize, ysize, &refs, cache_bits, &histo);
+ cur_entropy = VP8LHistogramEstimateBits(&histo) +
+ kSmallPenaltyForLargeCache * cache_bits;
+ if (cache_bits == 0 || cur_entropy < lowest_entropy) {
+ *best_cache_bits = cache_bits;
+ lowest_entropy = cur_entropy;
+ }
+ }
+ ok = 1;
+ Error:
+ VP8LClearBackwardRefs(&refs);
+ return ok;
+}
diff --git a/drivers/webpold/enc/backward_references.h b/drivers/webpold/enc/backward_references.h
new file mode 100644
index 0000000000..8006a56ba1
--- /dev/null
+++ b/drivers/webpold/enc/backward_references.h
@@ -0,0 +1,212 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Author: Jyrki Alakuijala (jyrki@google.com)
+//
+
+#ifndef WEBP_ENC_BACKWARD_REFERENCES_H_
+#define WEBP_ENC_BACKWARD_REFERENCES_H_
+
+#include <assert.h>
+#include <stdlib.h>
+#include "../types.h"
+#include "../format_constants.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+// The spec allows 11, we use 9 bits to reduce memory consumption in encoding.
+// Having 9 instead of 11 only removes about 0.25 % of compression density.
+#define MAX_COLOR_CACHE_BITS 9
+
+// Max ever number of codes we'll use:
+#define PIX_OR_COPY_CODES_MAX \
+ (NUM_LITERAL_CODES + NUM_LENGTH_CODES + (1 << MAX_COLOR_CACHE_BITS))
+
+// -----------------------------------------------------------------------------
+// PrefixEncode()
+
+// use GNU builtins where available.
+#if defined(__GNUC__) && \
+ ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4)
+static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
+ return n == 0 ? -1 : 31 ^ __builtin_clz(n);
+}
+#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
+#include <intrin.h>
+#pragma intrinsic(_BitScanReverse)
+
+static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
+ unsigned long first_set_bit;
+ return _BitScanReverse(&first_set_bit, n) ? first_set_bit : -1;
+}
+#else
+static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
+ int log = 0;
+ uint32_t value = n;
+ int i;
+
+ if (value == 0) return -1;
+ for (i = 4; i >= 0; --i) {
+ const int shift = (1 << i);
+ const uint32_t x = value >> shift;
+ if (x != 0) {
+ value = x;
+ log += shift;
+ }
+ }
+ return log;
+}
+#endif
+
+static WEBP_INLINE int VP8LBitsLog2Ceiling(uint32_t n) {
+ const int floor = BitsLog2Floor(n);
+ if (n == (n & ~(n - 1))) // zero or a power of two.
+ return floor;
+ else
+ return floor + 1;
+}
+
+// Splitting of distance and length codes into prefixes and
+// extra bits. The prefixes are encoded with an entropy code
+// while the extra bits are stored just as normal bits.
+static WEBP_INLINE void PrefixEncode(int distance, int* const code,
+ int* const extra_bits_count,
+ int* const extra_bits_value) {
+ // Collect the two most significant bits where the highest bit is 1.
+ const int highest_bit = BitsLog2Floor(--distance);
+ // & 0x3f is to make behavior well defined when highest_bit
+ // does not exist or is the least significant bit.
+ const int second_highest_bit =
+ (distance >> ((highest_bit - 1) & 0x3f)) & 1;
+ *extra_bits_count = (highest_bit > 0) ? (highest_bit - 1) : 0;
+ *extra_bits_value = distance & ((1 << *extra_bits_count) - 1);
+ *code = (highest_bit > 0) ? (2 * highest_bit + second_highest_bit)
+ : (highest_bit == 0) ? 1 : 0;
+}
+
+// -----------------------------------------------------------------------------
+// PixOrCopy
+
+enum Mode {
+ kLiteral,
+ kCacheIdx,
+ kCopy,
+ kNone
+};
+
+typedef struct {
+ // mode as uint8_t to make the memory layout to be exactly 8 bytes.
+ uint8_t mode;
+ uint16_t len;
+ uint32_t argb_or_distance;
+} PixOrCopy;
+
+static WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance,
+ uint16_t len) {
+ PixOrCopy retval;
+ retval.mode = kCopy;
+ retval.argb_or_distance = distance;
+ retval.len = len;
+ return retval;
+}
+
+static WEBP_INLINE PixOrCopy PixOrCopyCreateCacheIdx(int idx) {
+ PixOrCopy retval;
+ assert(idx >= 0);
+ assert(idx < (1 << MAX_COLOR_CACHE_BITS));
+ retval.mode = kCacheIdx;
+ retval.argb_or_distance = idx;
+ retval.len = 1;
+ return retval;
+}
+
+static WEBP_INLINE PixOrCopy PixOrCopyCreateLiteral(uint32_t argb) {
+ PixOrCopy retval;
+ retval.mode = kLiteral;
+ retval.argb_or_distance = argb;
+ retval.len = 1;
+ return retval;
+}
+
+static WEBP_INLINE int PixOrCopyIsLiteral(const PixOrCopy* const p) {
+ return (p->mode == kLiteral);
+}
+
+static WEBP_INLINE int PixOrCopyIsCacheIdx(const PixOrCopy* const p) {
+ return (p->mode == kCacheIdx);
+}
+
+static WEBP_INLINE int PixOrCopyIsCopy(const PixOrCopy* const p) {
+ return (p->mode == kCopy);
+}
+
+static WEBP_INLINE uint32_t PixOrCopyLiteral(const PixOrCopy* const p,
+ int component) {
+ assert(p->mode == kLiteral);
+ return (p->argb_or_distance >> (component * 8)) & 0xff;
+}
+
+static WEBP_INLINE uint32_t PixOrCopyLength(const PixOrCopy* const p) {
+ return p->len;
+}
+
+static WEBP_INLINE uint32_t PixOrCopyArgb(const PixOrCopy* const p) {
+ assert(p->mode == kLiteral);
+ return p->argb_or_distance;
+}
+
+static WEBP_INLINE uint32_t PixOrCopyCacheIdx(const PixOrCopy* const p) {
+ assert(p->mode == kCacheIdx);
+ assert(p->argb_or_distance < (1U << MAX_COLOR_CACHE_BITS));
+ return p->argb_or_distance;
+}
+
+static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) {
+ assert(p->mode == kCopy);
+ return p->argb_or_distance;
+}
+
+// -----------------------------------------------------------------------------
+// VP8LBackwardRefs
+
+typedef struct {
+ PixOrCopy* refs;
+ int size; // currently used
+ int max_size; // maximum capacity
+} VP8LBackwardRefs;
+
+// Initialize the object. Must be called first. 'refs' can be NULL.
+void VP8LInitBackwardRefs(VP8LBackwardRefs* const refs);
+
+// Release memory and re-initialize the object. 'refs' can be NULL.
+void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs);
+
+// Allocate 'max_size' references. Returns false in case of memory error.
+int VP8LBackwardRefsAlloc(VP8LBackwardRefs* const refs, int max_size);
+
+// -----------------------------------------------------------------------------
+// Main entry points
+
+// Evaluates best possible backward references for specified quality.
+// Further optimize for 2D locality if use_2d_locality flag is set.
+int VP8LGetBackwardReferences(int width, int height,
+ const uint32_t* const argb,
+ int quality, int cache_bits, int use_2d_locality,
+ VP8LBackwardRefs* const best);
+
+// Produce an estimate for a good color cache size for the image.
+int VP8LCalculateEstimateForCacheSize(const uint32_t* const argb,
+ int xsize, int ysize,
+ int* const best_cache_bits);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif // WEBP_ENC_BACKWARD_REFERENCES_H_
diff --git a/drivers/webpold/enc/config.c b/drivers/webpold/enc/config.c
new file mode 100644
index 0000000000..4136f6c227
--- /dev/null
+++ b/drivers/webpold/enc/config.c
@@ -0,0 +1,132 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Coding tools configuration
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "../encode.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// WebPConfig
+//------------------------------------------------------------------------------
+
+int WebPConfigInitInternal(WebPConfig* config,
+ WebPPreset preset, float quality, int version) {
+ if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) {
+ return 0; // caller/system version mismatch!
+ }
+ if (config == NULL) return 0;
+
+ config->quality = quality;
+ config->target_size = 0;
+ config->target_PSNR = 0.;
+ config->method = 4;
+ config->sns_strength = 50;
+ config->filter_strength = 20; // default: light filtering
+ config->filter_sharpness = 0;
+ config->filter_type = 0; // default: simple
+ config->partitions = 0;
+ config->segments = 4;
+ config->pass = 1;
+ config->show_compressed = 0;
+ config->preprocessing = 0;
+ config->autofilter = 0;
+ config->partition_limit = 0;
+ config->alpha_compression = 1;
+ config->alpha_filtering = 1;
+ config->alpha_quality = 100;
+ config->lossless = 0;
+ config->image_hint = WEBP_HINT_DEFAULT;
+
+ // TODO(skal): tune.
+ switch (preset) {
+ case WEBP_PRESET_PICTURE:
+ config->sns_strength = 80;
+ config->filter_sharpness = 4;
+ config->filter_strength = 35;
+ break;
+ case WEBP_PRESET_PHOTO:
+ config->sns_strength = 80;
+ config->filter_sharpness = 3;
+ config->filter_strength = 30;
+ break;
+ case WEBP_PRESET_DRAWING:
+ config->sns_strength = 25;
+ config->filter_sharpness = 6;
+ config->filter_strength = 10;
+ break;
+ case WEBP_PRESET_ICON:
+ config->sns_strength = 0;
+ config->filter_strength = 0; // disable filtering to retain sharpness
+ break;
+ case WEBP_PRESET_TEXT:
+ config->sns_strength = 0;
+ config->filter_strength = 0; // disable filtering to retain sharpness
+ config->segments = 2;
+ break;
+ case WEBP_PRESET_DEFAULT:
+ default:
+ break;
+ }
+ return WebPValidateConfig(config);
+}
+
+int WebPValidateConfig(const WebPConfig* config) {
+ if (config == NULL) return 0;
+ if (config->quality < 0 || config->quality > 100)
+ return 0;
+ if (config->target_size < 0)
+ return 0;
+ if (config->target_PSNR < 0)
+ return 0;
+ if (config->method < 0 || config->method > 6)
+ return 0;
+ if (config->segments < 1 || config->segments > 4)
+ return 0;
+ if (config->sns_strength < 0 || config->sns_strength > 100)
+ return 0;
+ if (config->filter_strength < 0 || config->filter_strength > 100)
+ return 0;
+ if (config->filter_sharpness < 0 || config->filter_sharpness > 7)
+ return 0;
+ if (config->filter_type < 0 || config->filter_type > 1)
+ return 0;
+ if (config->autofilter < 0 || config->autofilter > 1)
+ return 0;
+ if (config->pass < 1 || config->pass > 10)
+ return 0;
+ if (config->show_compressed < 0 || config->show_compressed > 1)
+ return 0;
+ if (config->preprocessing < 0 || config->preprocessing > 1)
+ return 0;
+ if (config->partitions < 0 || config->partitions > 3)
+ return 0;
+ if (config->partition_limit < 0 || config->partition_limit > 100)
+ return 0;
+ if (config->alpha_compression < 0)
+ return 0;
+ if (config->alpha_filtering < 0)
+ return 0;
+ if (config->alpha_quality < 0 || config->alpha_quality > 100)
+ return 0;
+ if (config->lossless < 0 || config->lossless > 1)
+ return 0;
+ if (config->image_hint >= WEBP_HINT_LAST)
+ return 0;
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/enc/cost.c b/drivers/webpold/enc/cost.c
new file mode 100644
index 0000000000..92e0cc713c
--- /dev/null
+++ b/drivers/webpold/enc/cost.c
@@ -0,0 +1,494 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Cost tables for level and modes
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./cost.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Boolean-cost cost table
+
+const uint16_t VP8EntropyCost[256] = {
+ 1792, 1792, 1792, 1536, 1536, 1408, 1366, 1280, 1280, 1216,
+ 1178, 1152, 1110, 1076, 1061, 1024, 1024, 992, 968, 951,
+ 939, 911, 896, 878, 871, 854, 838, 820, 811, 794,
+ 786, 768, 768, 752, 740, 732, 720, 709, 704, 690,
+ 683, 672, 666, 655, 647, 640, 631, 622, 615, 607,
+ 598, 592, 586, 576, 572, 564, 559, 555, 547, 541,
+ 534, 528, 522, 512, 512, 504, 500, 494, 488, 483,
+ 477, 473, 467, 461, 458, 452, 448, 443, 438, 434,
+ 427, 424, 419, 415, 410, 406, 403, 399, 394, 390,
+ 384, 384, 377, 374, 370, 366, 362, 359, 355, 351,
+ 347, 342, 342, 336, 333, 330, 326, 323, 320, 316,
+ 312, 308, 305, 302, 299, 296, 293, 288, 287, 283,
+ 280, 277, 274, 272, 268, 266, 262, 256, 256, 256,
+ 251, 248, 245, 242, 240, 237, 234, 232, 228, 226,
+ 223, 221, 218, 216, 214, 211, 208, 205, 203, 201,
+ 198, 196, 192, 191, 188, 187, 183, 181, 179, 176,
+ 175, 171, 171, 168, 165, 163, 160, 159, 156, 154,
+ 152, 150, 148, 146, 144, 142, 139, 138, 135, 133,
+ 131, 128, 128, 125, 123, 121, 119, 117, 115, 113,
+ 111, 110, 107, 105, 103, 102, 100, 98, 96, 94,
+ 92, 91, 89, 86, 86, 83, 82, 80, 77, 76,
+ 74, 73, 71, 69, 67, 66, 64, 63, 61, 59,
+ 57, 55, 54, 52, 51, 49, 47, 46, 44, 43,
+ 41, 40, 38, 36, 35, 33, 32, 30, 29, 27,
+ 25, 24, 22, 21, 19, 18, 16, 15, 13, 12,
+ 10, 9, 7, 6, 4, 3
+};
+
+//------------------------------------------------------------------------------
+// Level cost tables
+
+// For each given level, the following table gives the pattern of contexts to
+// use for coding it (in [][0]) as well as the bit value to use for each
+// context (in [][1]).
+const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2] = {
+ {0x001, 0x000}, {0x007, 0x001}, {0x00f, 0x005},
+ {0x00f, 0x00d}, {0x033, 0x003}, {0x033, 0x003}, {0x033, 0x023},
+ {0x033, 0x023}, {0x033, 0x023}, {0x033, 0x023}, {0x0d3, 0x013},
+ {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013},
+ {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x093},
+ {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093},
+ {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093},
+ {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093},
+ {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x153, 0x053},
+ {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053},
+ {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053},
+ {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053},
+ {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053},
+ {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053},
+ {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053},
+ {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053},
+ {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x153}
+};
+
+// fixed costs for coding levels, deduce from the coding tree.
+// This is only the part that doesn't depend on the probability state.
+const uint16_t VP8LevelFixedCosts[2048] = {
+ 0, 256, 256, 256, 256, 432, 618, 630,
+ 731, 640, 640, 828, 901, 948, 1021, 1101,
+ 1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202,
+ 1245, 1275, 1318, 1337, 1380, 1410, 1453, 1497,
+ 1540, 1570, 1613, 1280, 1295, 1317, 1332, 1358,
+ 1373, 1395, 1410, 1454, 1469, 1491, 1506, 1532,
+ 1547, 1569, 1584, 1601, 1616, 1638, 1653, 1679,
+ 1694, 1716, 1731, 1775, 1790, 1812, 1827, 1853,
+ 1868, 1890, 1905, 1727, 1733, 1742, 1748, 1759,
+ 1765, 1774, 1780, 1800, 1806, 1815, 1821, 1832,
+ 1838, 1847, 1853, 1878, 1884, 1893, 1899, 1910,
+ 1916, 1925, 1931, 1951, 1957, 1966, 1972, 1983,
+ 1989, 1998, 2004, 2027, 2033, 2042, 2048, 2059,
+ 2065, 2074, 2080, 2100, 2106, 2115, 2121, 2132,
+ 2138, 2147, 2153, 2178, 2184, 2193, 2199, 2210,
+ 2216, 2225, 2231, 2251, 2257, 2266, 2272, 2283,
+ 2289, 2298, 2304, 2168, 2174, 2183, 2189, 2200,
+ 2206, 2215, 2221, 2241, 2247, 2256, 2262, 2273,
+ 2279, 2288, 2294, 2319, 2325, 2334, 2340, 2351,
+ 2357, 2366, 2372, 2392, 2398, 2407, 2413, 2424,
+ 2430, 2439, 2445, 2468, 2474, 2483, 2489, 2500,
+ 2506, 2515, 2521, 2541, 2547, 2556, 2562, 2573,
+ 2579, 2588, 2594, 2619, 2625, 2634, 2640, 2651,
+ 2657, 2666, 2672, 2692, 2698, 2707, 2713, 2724,
+ 2730, 2739, 2745, 2540, 2546, 2555, 2561, 2572,
+ 2578, 2587, 2593, 2613, 2619, 2628, 2634, 2645,
+ 2651, 2660, 2666, 2691, 2697, 2706, 2712, 2723,
+ 2729, 2738, 2744, 2764, 2770, 2779, 2785, 2796,
+ 2802, 2811, 2817, 2840, 2846, 2855, 2861, 2872,
+ 2878, 2887, 2893, 2913, 2919, 2928, 2934, 2945,
+ 2951, 2960, 2966, 2991, 2997, 3006, 3012, 3023,
+ 3029, 3038, 3044, 3064, 3070, 3079, 3085, 3096,
+ 3102, 3111, 3117, 2981, 2987, 2996, 3002, 3013,
+ 3019, 3028, 3034, 3054, 3060, 3069, 3075, 3086,
+ 3092, 3101, 3107, 3132, 3138, 3147, 3153, 3164,
+ 3170, 3179, 3185, 3205, 3211, 3220, 3226, 3237,
+ 3243, 3252, 3258, 3281, 3287, 3296, 3302, 3313,
+ 3319, 3328, 3334, 3354, 3360, 3369, 3375, 3386,
+ 3392, 3401, 3407, 3432, 3438, 3447, 3453, 3464,
+ 3470, 3479, 3485, 3505, 3511, 3520, 3526, 3537,
+ 3543, 3552, 3558, 2816, 2822, 2831, 2837, 2848,
+ 2854, 2863, 2869, 2889, 2895, 2904, 2910, 2921,
+ 2927, 2936, 2942, 2967, 2973, 2982, 2988, 2999,
+ 3005, 3014, 3020, 3040, 3046, 3055, 3061, 3072,
+ 3078, 3087, 3093, 3116, 3122, 3131, 3137, 3148,
+ 3154, 3163, 3169, 3189, 3195, 3204, 3210, 3221,
+ 3227, 3236, 3242, 3267, 3273, 3282, 3288, 3299,
+ 3305, 3314, 3320, 3340, 3346, 3355, 3361, 3372,
+ 3378, 3387, 3393, 3257, 3263, 3272, 3278, 3289,
+ 3295, 3304, 3310, 3330, 3336, 3345, 3351, 3362,
+ 3368, 3377, 3383, 3408, 3414, 3423, 3429, 3440,
+ 3446, 3455, 3461, 3481, 3487, 3496, 3502, 3513,
+ 3519, 3528, 3534, 3557, 3563, 3572, 3578, 3589,
+ 3595, 3604, 3610, 3630, 3636, 3645, 3651, 3662,
+ 3668, 3677, 3683, 3708, 3714, 3723, 3729, 3740,
+ 3746, 3755, 3761, 3781, 3787, 3796, 3802, 3813,
+ 3819, 3828, 3834, 3629, 3635, 3644, 3650, 3661,
+ 3667, 3676, 3682, 3702, 3708, 3717, 3723, 3734,
+ 3740, 3749, 3755, 3780, 3786, 3795, 3801, 3812,
+ 3818, 3827, 3833, 3853, 3859, 3868, 3874, 3885,
+ 3891, 3900, 3906, 3929, 3935, 3944, 3950, 3961,
+ 3967, 3976, 3982, 4002, 4008, 4017, 4023, 4034,
+ 4040, 4049, 4055, 4080, 4086, 4095, 4101, 4112,
+ 4118, 4127, 4133, 4153, 4159, 4168, 4174, 4185,
+ 4191, 4200, 4206, 4070, 4076, 4085, 4091, 4102,
+ 4108, 4117, 4123, 4143, 4149, 4158, 4164, 4175,
+ 4181, 4190, 4196, 4221, 4227, 4236, 4242, 4253,
+ 4259, 4268, 4274, 4294, 4300, 4309, 4315, 4326,
+ 4332, 4341, 4347, 4370, 4376, 4385, 4391, 4402,
+ 4408, 4417, 4423, 4443, 4449, 4458, 4464, 4475,
+ 4481, 4490, 4496, 4521, 4527, 4536, 4542, 4553,
+ 4559, 4568, 4574, 4594, 4600, 4609, 4615, 4626,
+ 4632, 4641, 4647, 3515, 3521, 3530, 3536, 3547,
+ 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620,
+ 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698,
+ 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771,
+ 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847,
+ 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920,
+ 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998,
+ 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071,
+ 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988,
+ 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061,
+ 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139,
+ 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212,
+ 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288,
+ 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361,
+ 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439,
+ 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512,
+ 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360,
+ 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433,
+ 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511,
+ 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584,
+ 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660,
+ 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733,
+ 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811,
+ 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884,
+ 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801,
+ 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874,
+ 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952,
+ 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025,
+ 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101,
+ 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174,
+ 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252,
+ 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325,
+ 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636,
+ 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709,
+ 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787,
+ 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860,
+ 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936,
+ 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009,
+ 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087,
+ 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160,
+ 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077,
+ 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150,
+ 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228,
+ 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301,
+ 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377,
+ 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450,
+ 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528,
+ 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601,
+ 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449,
+ 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522,
+ 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600,
+ 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673,
+ 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749,
+ 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822,
+ 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900,
+ 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973,
+ 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890,
+ 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963,
+ 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041,
+ 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114,
+ 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190,
+ 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263,
+ 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341,
+ 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414,
+ 6420, 6429, 6435, 3515, 3521, 3530, 3536, 3547,
+ 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620,
+ 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698,
+ 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771,
+ 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847,
+ 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920,
+ 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998,
+ 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071,
+ 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988,
+ 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061,
+ 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139,
+ 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212,
+ 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288,
+ 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361,
+ 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439,
+ 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512,
+ 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360,
+ 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433,
+ 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511,
+ 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584,
+ 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660,
+ 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733,
+ 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811,
+ 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884,
+ 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801,
+ 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874,
+ 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952,
+ 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025,
+ 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101,
+ 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174,
+ 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252,
+ 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325,
+ 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636,
+ 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709,
+ 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787,
+ 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860,
+ 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936,
+ 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009,
+ 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087,
+ 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160,
+ 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077,
+ 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150,
+ 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228,
+ 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301,
+ 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377,
+ 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450,
+ 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528,
+ 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601,
+ 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449,
+ 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522,
+ 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600,
+ 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673,
+ 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749,
+ 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822,
+ 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900,
+ 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973,
+ 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890,
+ 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963,
+ 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041,
+ 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114,
+ 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190,
+ 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263,
+ 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341,
+ 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414,
+ 6420, 6429, 6435, 5303, 5309, 5318, 5324, 5335,
+ 5341, 5350, 5356, 5376, 5382, 5391, 5397, 5408,
+ 5414, 5423, 5429, 5454, 5460, 5469, 5475, 5486,
+ 5492, 5501, 5507, 5527, 5533, 5542, 5548, 5559,
+ 5565, 5574, 5580, 5603, 5609, 5618, 5624, 5635,
+ 5641, 5650, 5656, 5676, 5682, 5691, 5697, 5708,
+ 5714, 5723, 5729, 5754, 5760, 5769, 5775, 5786,
+ 5792, 5801, 5807, 5827, 5833, 5842, 5848, 5859,
+ 5865, 5874, 5880, 5744, 5750, 5759, 5765, 5776,
+ 5782, 5791, 5797, 5817, 5823, 5832, 5838, 5849,
+ 5855, 5864, 5870, 5895, 5901, 5910, 5916, 5927,
+ 5933, 5942, 5948, 5968, 5974, 5983, 5989, 6000,
+ 6006, 6015, 6021, 6044, 6050, 6059, 6065, 6076,
+ 6082, 6091, 6097, 6117, 6123, 6132, 6138, 6149,
+ 6155, 6164, 6170, 6195, 6201, 6210, 6216, 6227,
+ 6233, 6242, 6248, 6268, 6274, 6283, 6289, 6300,
+ 6306, 6315, 6321, 6116, 6122, 6131, 6137, 6148,
+ 6154, 6163, 6169, 6189, 6195, 6204, 6210, 6221,
+ 6227, 6236, 6242, 6267, 6273, 6282, 6288, 6299,
+ 6305, 6314, 6320, 6340, 6346, 6355, 6361, 6372,
+ 6378, 6387, 6393, 6416, 6422, 6431, 6437, 6448,
+ 6454, 6463, 6469, 6489, 6495, 6504, 6510, 6521,
+ 6527, 6536, 6542, 6567, 6573, 6582, 6588, 6599,
+ 6605, 6614, 6620, 6640, 6646, 6655, 6661, 6672,
+ 6678, 6687, 6693, 6557, 6563, 6572, 6578, 6589,
+ 6595, 6604, 6610, 6630, 6636, 6645, 6651, 6662,
+ 6668, 6677, 6683, 6708, 6714, 6723, 6729, 6740,
+ 6746, 6755, 6761, 6781, 6787, 6796, 6802, 6813,
+ 6819, 6828, 6834, 6857, 6863, 6872, 6878, 6889,
+ 6895, 6904, 6910, 6930, 6936, 6945, 6951, 6962,
+ 6968, 6977, 6983, 7008, 7014, 7023, 7029, 7040,
+ 7046, 7055, 7061, 7081, 7087, 7096, 7102, 7113,
+ 7119, 7128, 7134, 6392, 6398, 6407, 6413, 6424,
+ 6430, 6439, 6445, 6465, 6471, 6480, 6486, 6497,
+ 6503, 6512, 6518, 6543, 6549, 6558, 6564, 6575,
+ 6581, 6590, 6596, 6616, 6622, 6631, 6637, 6648,
+ 6654, 6663, 6669, 6692, 6698, 6707, 6713, 6724,
+ 6730, 6739, 6745, 6765, 6771, 6780, 6786, 6797,
+ 6803, 6812, 6818, 6843, 6849, 6858, 6864, 6875,
+ 6881, 6890, 6896, 6916, 6922, 6931, 6937, 6948,
+ 6954, 6963, 6969, 6833, 6839, 6848, 6854, 6865,
+ 6871, 6880, 6886, 6906, 6912, 6921, 6927, 6938,
+ 6944, 6953, 6959, 6984, 6990, 6999, 7005, 7016,
+ 7022, 7031, 7037, 7057, 7063, 7072, 7078, 7089,
+ 7095, 7104, 7110, 7133, 7139, 7148, 7154, 7165,
+ 7171, 7180, 7186, 7206, 7212, 7221, 7227, 7238,
+ 7244, 7253, 7259, 7284, 7290, 7299, 7305, 7316,
+ 7322, 7331, 7337, 7357, 7363, 7372, 7378, 7389,
+ 7395, 7404, 7410, 7205, 7211, 7220, 7226, 7237,
+ 7243, 7252, 7258, 7278, 7284, 7293, 7299, 7310,
+ 7316, 7325, 7331, 7356, 7362, 7371, 7377, 7388,
+ 7394, 7403, 7409, 7429, 7435, 7444, 7450, 7461,
+ 7467, 7476, 7482, 7505, 7511, 7520, 7526, 7537,
+ 7543, 7552, 7558, 7578, 7584, 7593, 7599, 7610,
+ 7616, 7625, 7631, 7656, 7662, 7671, 7677, 7688,
+ 7694, 7703, 7709, 7729, 7735, 7744, 7750, 7761
+};
+
+static int VariableLevelCost(int level, const uint8_t probas[NUM_PROBAS]) {
+ int pattern = VP8LevelCodes[level - 1][0];
+ int bits = VP8LevelCodes[level - 1][1];
+ int cost = 0;
+ int i;
+ for (i = 2; pattern; ++i) {
+ if (pattern & 1) {
+ cost += VP8BitCost(bits & 1, probas[i]);
+ }
+ bits >>= 1;
+ pattern >>= 1;
+ }
+ return cost;
+}
+
+//------------------------------------------------------------------------------
+// Pre-calc level costs once for all
+
+void VP8CalculateLevelCosts(VP8Proba* const proba) {
+ int ctype, band, ctx;
+
+ if (!proba->dirty_) return; // nothing to do.
+
+ for (ctype = 0; ctype < NUM_TYPES; ++ctype) {
+ for (band = 0; band < NUM_BANDS; ++band) {
+ for(ctx = 0; ctx < NUM_CTX; ++ctx) {
+ const uint8_t* const p = proba->coeffs_[ctype][band][ctx];
+ uint16_t* const table = proba->level_cost_[ctype][band][ctx];
+ const int cost_base = VP8BitCost(1, p[1]);
+ int v;
+ table[0] = VP8BitCost(0, p[1]);
+ for (v = 1; v <= MAX_VARIABLE_LEVEL; ++v) {
+ table[v] = cost_base + VariableLevelCost(v, p);
+ }
+ // Starting at level 67 and up, the variable part of the cost is
+ // actually constant.
+ }
+ }
+ }
+ proba->dirty_ = 0;
+}
+
+//------------------------------------------------------------------------------
+// Mode cost tables.
+
+// These are the fixed probabilities (in the coding trees) turned into bit-cost
+// by calling VP8BitCost().
+const uint16_t VP8FixedCostsUV[4] = { 302, 984, 439, 642 };
+// note: these values include the fixed VP8BitCost(1, 145) mode selection cost.
+const uint16_t VP8FixedCostsI16[4] = { 663, 919, 872, 919 };
+const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES] = {
+ { { 251, 1362, 1934, 2085, 2314, 2230, 1839, 1988, 2437, 2348 },
+ { 403, 680, 1507, 1519, 2060, 2005, 1992, 1914, 1924, 1733 },
+ { 353, 1121, 973, 1895, 2060, 1787, 1671, 1516, 2012, 1868 },
+ { 770, 852, 1581, 632, 1393, 1780, 1823, 1936, 1074, 1218 },
+ { 510, 1270, 1467, 1319, 847, 1279, 1792, 2094, 1080, 1353 },
+ { 488, 1322, 918, 1573, 1300, 883, 1814, 1752, 1756, 1502 },
+ { 425, 992, 1820, 1514, 1843, 2440, 937, 1771, 1924, 1129 },
+ { 363, 1248, 1257, 1970, 2194, 2385, 1569, 953, 1951, 1601 },
+ { 723, 1257, 1631, 964, 963, 1508, 1697, 1824, 671, 1418 },
+ { 635, 1038, 1573, 930, 1673, 1413, 1410, 1687, 1410, 749 } },
+ { { 451, 613, 1345, 1702, 1870, 1716, 1728, 1766, 2190, 2310 },
+ { 678, 453, 1171, 1443, 1925, 1831, 2045, 1781, 1887, 1602 },
+ { 711, 666, 674, 1718, 1910, 1493, 1775, 1193, 2325, 2325 },
+ { 883, 854, 1583, 542, 1800, 1878, 1664, 2149, 1207, 1087 },
+ { 669, 994, 1248, 1122, 949, 1179, 1376, 1729, 1070, 1244 },
+ { 715, 1026, 715, 1350, 1430, 930, 1717, 1296, 1479, 1479 },
+ { 544, 841, 1656, 1450, 2094, 3883, 1010, 1759, 2076, 809 },
+ { 610, 855, 957, 1553, 2067, 1561, 1704, 824, 2066, 1226 },
+ { 833, 960, 1416, 819, 1277, 1619, 1501, 1617, 757, 1182 },
+ { 711, 964, 1252, 879, 1441, 1828, 1508, 1636, 1594, 734 } },
+ { { 605, 764, 734, 1713, 1747, 1192, 1819, 1353, 1877, 2392 },
+ { 866, 641, 586, 1622, 2072, 1431, 1888, 1346, 2189, 1764 },
+ { 901, 851, 456, 2165, 2281, 1405, 1739, 1193, 2183, 2443 },
+ { 770, 1045, 952, 1078, 1342, 1191, 1436, 1063, 1303, 995 },
+ { 901, 1086, 727, 1170, 884, 1105, 1267, 1401, 1739, 1337 },
+ { 951, 1162, 595, 1488, 1388, 703, 1790, 1366, 2057, 1724 },
+ { 534, 986, 1273, 1987, 3273, 1485, 1024, 1399, 1583, 866 },
+ { 699, 1182, 695, 1978, 1726, 1986, 1326, 714, 1750, 1672 },
+ { 951, 1217, 1209, 920, 1062, 1441, 1548, 999, 952, 932 },
+ { 733, 1284, 784, 1256, 1557, 1098, 1257, 1357, 1414, 908 } },
+ { { 316, 1075, 1653, 1220, 2145, 2051, 1730, 2131, 1884, 1790 },
+ { 745, 516, 1404, 894, 1599, 2375, 2013, 2105, 1475, 1381 },
+ { 516, 729, 1088, 1319, 1637, 3426, 1636, 1275, 1531, 1453 },
+ { 894, 943, 2138, 468, 1704, 2259, 2069, 1763, 1266, 1158 },
+ { 605, 1025, 1235, 871, 1170, 1767, 1493, 1500, 1104, 1258 },
+ { 739, 826, 1207, 1151, 1412, 846, 1305, 2726, 1014, 1569 },
+ { 558, 825, 1820, 1398, 3344, 1556, 1218, 1550, 1228, 878 },
+ { 429, 951, 1089, 1816, 3861, 3861, 1556, 969, 1568, 1828 },
+ { 883, 961, 1752, 769, 1468, 1810, 2081, 2346, 613, 1298 },
+ { 803, 895, 1372, 641, 1303, 1708, 1686, 1700, 1306, 1033 } },
+ { { 439, 1267, 1270, 1579, 963, 1193, 1723, 1729, 1198, 1993 },
+ { 705, 725, 1029, 1153, 1176, 1103, 1821, 1567, 1259, 1574 },
+ { 723, 859, 802, 1253, 972, 1202, 1407, 1665, 1520, 1674 },
+ { 894, 960, 1254, 887, 1052, 1607, 1344, 1349, 865, 1150 },
+ { 833, 1312, 1337, 1205, 572, 1288, 1414, 1529, 1088, 1430 },
+ { 842, 1279, 1068, 1861, 862, 688, 1861, 1630, 1039, 1381 },
+ { 766, 938, 1279, 1546, 3338, 1550, 1031, 1542, 1288, 640 },
+ { 715, 1090, 835, 1609, 1100, 1100, 1603, 1019, 1102, 1617 },
+ { 894, 1813, 1500, 1188, 789, 1194, 1491, 1919, 617, 1333 },
+ { 610, 1076, 1644, 1281, 1283, 975, 1179, 1688, 1434, 889 } },
+ { { 544, 971, 1146, 1849, 1221, 740, 1857, 1621, 1683, 2430 },
+ { 723, 705, 961, 1371, 1426, 821, 2081, 2079, 1839, 1380 },
+ { 783, 857, 703, 2145, 1419, 814, 1791, 1310, 1609, 2206 },
+ { 997, 1000, 1153, 792, 1229, 1162, 1810, 1418, 942, 979 },
+ { 901, 1226, 883, 1289, 793, 715, 1904, 1649, 1319, 3108 },
+ { 979, 1478, 782, 2216, 1454, 455, 3092, 1591, 1997, 1664 },
+ { 663, 1110, 1504, 1114, 1522, 3311, 676, 1522, 1530, 1024 },
+ { 605, 1138, 1153, 1314, 1569, 1315, 1157, 804, 1574, 1320 },
+ { 770, 1216, 1218, 1227, 869, 1384, 1232, 1375, 834, 1239 },
+ { 775, 1007, 843, 1216, 1225, 1074, 2527, 1479, 1149, 975 } },
+ { { 477, 817, 1309, 1439, 1708, 1454, 1159, 1241, 1945, 1672 },
+ { 577, 796, 1112, 1271, 1618, 1458, 1087, 1345, 1831, 1265 },
+ { 663, 776, 753, 1940, 1690, 1690, 1227, 1097, 3149, 1361 },
+ { 766, 1299, 1744, 1161, 1565, 1106, 1045, 1230, 1232, 707 },
+ { 915, 1026, 1404, 1182, 1184, 851, 1428, 2425, 1043, 789 },
+ { 883, 1456, 790, 1082, 1086, 985, 1083, 1484, 1238, 1160 },
+ { 507, 1345, 2261, 1995, 1847, 3636, 653, 1761, 2287, 933 },
+ { 553, 1193, 1470, 2057, 2059, 2059, 833, 779, 2058, 1263 },
+ { 766, 1275, 1515, 1039, 957, 1554, 1286, 1540, 1289, 705 },
+ { 499, 1378, 1496, 1385, 1850, 1850, 1044, 2465, 1515, 720 } },
+ { { 553, 930, 978, 2077, 1968, 1481, 1457, 761, 1957, 2362 },
+ { 694, 864, 905, 1720, 1670, 1621, 1429, 718, 2125, 1477 },
+ { 699, 968, 658, 3190, 2024, 1479, 1865, 750, 2060, 2320 },
+ { 733, 1308, 1296, 1062, 1576, 1322, 1062, 1112, 1172, 816 },
+ { 920, 927, 1052, 939, 947, 1156, 1152, 1073, 3056, 1268 },
+ { 723, 1534, 711, 1547, 1294, 892, 1553, 928, 1815, 1561 },
+ { 663, 1366, 1583, 2111, 1712, 3501, 522, 1155, 2130, 1133 },
+ { 614, 1731, 1188, 2343, 1944, 3733, 1287, 487, 3546, 1758 },
+ { 770, 1585, 1312, 826, 884, 2673, 1185, 1006, 1195, 1195 },
+ { 758, 1333, 1273, 1023, 1621, 1162, 1351, 833, 1479, 862 } },
+ { { 376, 1193, 1446, 1149, 1545, 1577, 1870, 1789, 1175, 1823 },
+ { 803, 633, 1136, 1058, 1350, 1323, 1598, 2247, 1072, 1252 },
+ { 614, 1048, 943, 981, 1152, 1869, 1461, 1020, 1618, 1618 },
+ { 1107, 1085, 1282, 592, 1779, 1933, 1648, 2403, 691, 1246 },
+ { 851, 1309, 1223, 1243, 895, 1593, 1792, 2317, 627, 1076 },
+ { 770, 1216, 1030, 1125, 921, 981, 1629, 1131, 1049, 1646 },
+ { 626, 1469, 1456, 1081, 1489, 3278, 981, 1232, 1498, 733 },
+ { 617, 1201, 812, 1220, 1476, 1476, 1478, 970, 1228, 1488 },
+ { 1179, 1393, 1540, 999, 1243, 1503, 1916, 1925, 414, 1614 },
+ { 943, 1088, 1490, 682, 1112, 1372, 1756, 1505, 966, 966 } },
+ { { 322, 1142, 1589, 1396, 2144, 1859, 1359, 1925, 2084, 1518 },
+ { 617, 625, 1241, 1234, 2121, 1615, 1524, 1858, 1720, 1004 },
+ { 553, 851, 786, 1299, 1452, 1560, 1372, 1561, 1967, 1713 },
+ { 770, 977, 1396, 568, 1893, 1639, 1540, 2108, 1430, 1013 },
+ { 684, 1120, 1375, 982, 930, 2719, 1638, 1643, 933, 993 },
+ { 553, 1103, 996, 1356, 1361, 1005, 1507, 1761, 1184, 1268 },
+ { 419, 1247, 1537, 1554, 1817, 3606, 1026, 1666, 1829, 923 },
+ { 439, 1139, 1101, 1257, 3710, 1922, 1205, 1040, 1931, 1529 },
+ { 979, 935, 1269, 847, 1202, 1286, 1530, 1535, 827, 1036 },
+ { 516, 1378, 1569, 1110, 1798, 1798, 1198, 2199, 1543, 712 } },
+};
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/enc/cost.h b/drivers/webpold/enc/cost.h
new file mode 100644
index 0000000000..09b75b699d
--- /dev/null
+++ b/drivers/webpold/enc/cost.h
@@ -0,0 +1,48 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Cost tables for level and modes.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_ENC_COST_H_
+#define WEBP_ENC_COST_H_
+
+#include "./vp8enci.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+extern const uint16_t VP8LevelFixedCosts[2048]; // approximate cost per level
+extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p)
+
+// Cost of coding one event with probability 'proba'.
+static WEBP_INLINE int VP8BitCost(int bit, uint8_t proba) {
+ return !bit ? VP8EntropyCost[proba] : VP8EntropyCost[255 - proba];
+}
+
+// Level cost calculations
+extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2];
+void VP8CalculateLevelCosts(VP8Proba* const proba);
+static WEBP_INLINE int VP8LevelCost(const uint16_t* const table, int level) {
+ return VP8LevelFixedCosts[level]
+ + table[(level > MAX_VARIABLE_LEVEL) ? MAX_VARIABLE_LEVEL : level];
+}
+
+// Mode costs
+extern const uint16_t VP8FixedCostsUV[4];
+extern const uint16_t VP8FixedCostsI16[4];
+extern const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES];
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_ENC_COST_H_ */
diff --git a/drivers/webpold/enc/filter.c b/drivers/webpold/enc/filter.c
new file mode 100644
index 0000000000..7fb78a3949
--- /dev/null
+++ b/drivers/webpold/enc/filter.c
@@ -0,0 +1,409 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Selecting filter level
+//
+// Author: somnath@google.com (Somnath Banerjee)
+
+#include "./vp8enci.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+// NOTE: clip1, tables and InitTables are repeated entries of dsp.c
+static uint8_t abs0[255 + 255 + 1]; // abs(i)
+static uint8_t abs1[255 + 255 + 1]; // abs(i)>>1
+static int8_t sclip1[1020 + 1020 + 1]; // clips [-1020, 1020] to [-128, 127]
+static int8_t sclip2[112 + 112 + 1]; // clips [-112, 112] to [-16, 15]
+static uint8_t clip1[255 + 510 + 1]; // clips [-255,510] to [0,255]
+
+static int tables_ok = 0;
+
+static void InitTables(void) {
+ if (!tables_ok) {
+ int i;
+ for (i = -255; i <= 255; ++i) {
+ abs0[255 + i] = (i < 0) ? -i : i;
+ abs1[255 + i] = abs0[255 + i] >> 1;
+ }
+ for (i = -1020; i <= 1020; ++i) {
+ sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i;
+ }
+ for (i = -112; i <= 112; ++i) {
+ sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i;
+ }
+ for (i = -255; i <= 255 + 255; ++i) {
+ clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i;
+ }
+ tables_ok = 1;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Edge filtering functions
+
+// 4 pixels in, 2 pixels out
+static WEBP_INLINE void do_filter2(uint8_t* p, int step) {
+ const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
+ const int a = 3 * (q0 - p0) + sclip1[1020 + p1 - q1];
+ const int a1 = sclip2[112 + ((a + 4) >> 3)];
+ const int a2 = sclip2[112 + ((a + 3) >> 3)];
+ p[-step] = clip1[255 + p0 + a2];
+ p[ 0] = clip1[255 + q0 - a1];
+}
+
+// 4 pixels in, 4 pixels out
+static WEBP_INLINE void do_filter4(uint8_t* p, int step) {
+ const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
+ const int a = 3 * (q0 - p0);
+ const int a1 = sclip2[112 + ((a + 4) >> 3)];
+ const int a2 = sclip2[112 + ((a + 3) >> 3)];
+ const int a3 = (a1 + 1) >> 1;
+ p[-2*step] = clip1[255 + p1 + a3];
+ p[- step] = clip1[255 + p0 + a2];
+ p[ 0] = clip1[255 + q0 - a1];
+ p[ step] = clip1[255 + q1 - a3];
+}
+
+// high edge-variance
+static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) {
+ const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
+ return (abs0[255 + p1 - p0] > thresh) || (abs0[255 + q1 - q0] > thresh);
+}
+
+static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int thresh) {
+ const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
+ return (2 * abs0[255 + p0 - q0] + abs1[255 + p1 - q1]) <= thresh;
+}
+
+static WEBP_INLINE int needs_filter2(const uint8_t* p,
+ int step, int t, int it) {
+ const int p3 = p[-4*step], p2 = p[-3*step], p1 = p[-2*step], p0 = p[-step];
+ const int q0 = p[0], q1 = p[step], q2 = p[2*step], q3 = p[3*step];
+ if ((2 * abs0[255 + p0 - q0] + abs1[255 + p1 - q1]) > t)
+ return 0;
+ return abs0[255 + p3 - p2] <= it && abs0[255 + p2 - p1] <= it &&
+ abs0[255 + p1 - p0] <= it && abs0[255 + q3 - q2] <= it &&
+ abs0[255 + q2 - q1] <= it && abs0[255 + q1 - q0] <= it;
+}
+
+//------------------------------------------------------------------------------
+// Simple In-loop filtering (Paragraph 15.2)
+
+static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
+ int i;
+ for (i = 0; i < 16; ++i) {
+ if (needs_filter(p + i, stride, thresh)) {
+ do_filter2(p + i, stride);
+ }
+ }
+}
+
+static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
+ int i;
+ for (i = 0; i < 16; ++i) {
+ if (needs_filter(p + i * stride, 1, thresh)) {
+ do_filter2(p + i * stride, 1);
+ }
+ }
+}
+
+static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4 * stride;
+ SimpleVFilter16(p, stride, thresh);
+ }
+}
+
+static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4;
+ SimpleHFilter16(p, stride, thresh);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Complex In-loop filtering (Paragraph 15.3)
+
+static WEBP_INLINE void FilterLoop24(uint8_t* p,
+ int hstride, int vstride, int size,
+ int thresh, int ithresh, int hev_thresh) {
+ while (size-- > 0) {
+ if (needs_filter2(p, hstride, thresh, ithresh)) {
+ if (hev(p, hstride, hev_thresh)) {
+ do_filter2(p, hstride);
+ } else {
+ do_filter4(p, hstride);
+ }
+ }
+ p += vstride;
+ }
+}
+
+// on three inner edges
+static void VFilter16i(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4 * stride;
+ FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh);
+ }
+}
+
+static void HFilter16i(uint8_t* p, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ int k;
+ for (k = 3; k > 0; --k) {
+ p += 4;
+ FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh);
+ }
+}
+
+static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
+ FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
+}
+
+static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
+ int thresh, int ithresh, int hev_thresh) {
+ FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
+ FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
+}
+
+//------------------------------------------------------------------------------
+
+void (*VP8EncVFilter16i)(uint8_t*, int, int, int, int) = VFilter16i;
+void (*VP8EncHFilter16i)(uint8_t*, int, int, int, int) = HFilter16i;
+void (*VP8EncVFilter8i)(uint8_t*, uint8_t*, int, int, int, int) = VFilter8i;
+void (*VP8EncHFilter8i)(uint8_t*, uint8_t*, int, int, int, int) = HFilter8i;
+
+void (*VP8EncSimpleVFilter16i)(uint8_t*, int, int) = SimpleVFilter16i;
+void (*VP8EncSimpleHFilter16i)(uint8_t*, int, int) = SimpleHFilter16i;
+
+//------------------------------------------------------------------------------
+// Paragraph 15.4: compute the inner-edge filtering strength
+
+static int GetILevel(int sharpness, int level) {
+ if (sharpness > 0) {
+ if (sharpness > 4) {
+ level >>= 2;
+ } else {
+ level >>= 1;
+ }
+ if (level > 9 - sharpness) {
+ level = 9 - sharpness;
+ }
+ }
+ if (level < 1) level = 1;
+ return level;
+}
+
+static void DoFilter(const VP8EncIterator* const it, int level) {
+ const VP8Encoder* const enc = it->enc_;
+ const int ilevel = GetILevel(enc->config_->filter_sharpness, level);
+ const int limit = 2 * level + ilevel;
+
+ uint8_t* const y_dst = it->yuv_out2_ + Y_OFF;
+ uint8_t* const u_dst = it->yuv_out2_ + U_OFF;
+ uint8_t* const v_dst = it->yuv_out2_ + V_OFF;
+
+ // copy current block to yuv_out2_
+ memcpy(y_dst, it->yuv_out_, YUV_SIZE * sizeof(uint8_t));
+
+ if (enc->filter_hdr_.simple_ == 1) { // simple
+ VP8EncSimpleHFilter16i(y_dst, BPS, limit);
+ VP8EncSimpleVFilter16i(y_dst, BPS, limit);
+ } else { // complex
+ const int hev_thresh = (level >= 40) ? 2 : (level >= 15) ? 1 : 0;
+ VP8EncHFilter16i(y_dst, BPS, limit, ilevel, hev_thresh);
+ VP8EncHFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh);
+ VP8EncVFilter16i(y_dst, BPS, limit, ilevel, hev_thresh);
+ VP8EncVFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh);
+ }
+}
+
+//------------------------------------------------------------------------------
+// SSIM metric
+
+enum { KERNEL = 3 };
+static const double kMinValue = 1.e-10; // minimal threshold
+
+void VP8SSIMAddStats(const DistoStats* const src, DistoStats* const dst) {
+ dst->w += src->w;
+ dst->xm += src->xm;
+ dst->ym += src->ym;
+ dst->xxm += src->xxm;
+ dst->xym += src->xym;
+ dst->yym += src->yym;
+}
+
+static void VP8SSIMAccumulate(const uint8_t* src1, int stride1,
+ const uint8_t* src2, int stride2,
+ int xo, int yo, int W, int H,
+ DistoStats* const stats) {
+ const int ymin = (yo - KERNEL < 0) ? 0 : yo - KERNEL;
+ const int ymax = (yo + KERNEL > H - 1) ? H - 1 : yo + KERNEL;
+ const int xmin = (xo - KERNEL < 0) ? 0 : xo - KERNEL;
+ const int xmax = (xo + KERNEL > W - 1) ? W - 1 : xo + KERNEL;
+ int x, y;
+ src1 += ymin * stride1;
+ src2 += ymin * stride2;
+ for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) {
+ for (x = xmin; x <= xmax; ++x) {
+ const int s1 = src1[x];
+ const int s2 = src2[x];
+ stats->w += 1;
+ stats->xm += s1;
+ stats->ym += s2;
+ stats->xxm += s1 * s1;
+ stats->xym += s1 * s2;
+ stats->yym += s2 * s2;
+ }
+ }
+}
+
+double VP8SSIMGet(const DistoStats* const stats) {
+ const double xmxm = stats->xm * stats->xm;
+ const double ymym = stats->ym * stats->ym;
+ const double xmym = stats->xm * stats->ym;
+ const double w2 = stats->w * stats->w;
+ double sxx = stats->xxm * stats->w - xmxm;
+ double syy = stats->yym * stats->w - ymym;
+ double sxy = stats->xym * stats->w - xmym;
+ double C1, C2;
+ double fnum;
+ double fden;
+ // small errors are possible, due to rounding. Clamp to zero.
+ if (sxx < 0.) sxx = 0.;
+ if (syy < 0.) syy = 0.;
+ C1 = 6.5025 * w2;
+ C2 = 58.5225 * w2;
+ fnum = (2 * xmym + C1) * (2 * sxy + C2);
+ fden = (xmxm + ymym + C1) * (sxx + syy + C2);
+ return (fden != 0.) ? fnum / fden : kMinValue;
+}
+
+double VP8SSIMGetSquaredError(const DistoStats* const s) {
+ if (s->w > 0.) {
+ const double iw2 = 1. / (s->w * s->w);
+ const double sxx = s->xxm * s->w - s->xm * s->xm;
+ const double syy = s->yym * s->w - s->ym * s->ym;
+ const double sxy = s->xym * s->w - s->xm * s->ym;
+ const double SSE = iw2 * (sxx + syy - 2. * sxy);
+ if (SSE > kMinValue) return SSE;
+ }
+ return kMinValue;
+}
+
+void VP8SSIMAccumulatePlane(const uint8_t* src1, int stride1,
+ const uint8_t* src2, int stride2,
+ int W, int H, DistoStats* const stats) {
+ int x, y;
+ for (y = 0; y < H; ++y) {
+ for (x = 0; x < W; ++x) {
+ VP8SSIMAccumulate(src1, stride1, src2, stride2, x, y, W, H, stats);
+ }
+ }
+}
+
+static double GetMBSSIM(const uint8_t* yuv1, const uint8_t* yuv2) {
+ int x, y;
+ DistoStats s = { .0, .0, .0, .0, .0, .0 };
+
+ // compute SSIM in a 10 x 10 window
+ for (x = 3; x < 13; x++) {
+ for (y = 3; y < 13; y++) {
+ VP8SSIMAccumulate(yuv1 + Y_OFF, BPS, yuv2 + Y_OFF, BPS, x, y, 16, 16, &s);
+ }
+ }
+ for (x = 1; x < 7; x++) {
+ for (y = 1; y < 7; y++) {
+ VP8SSIMAccumulate(yuv1 + U_OFF, BPS, yuv2 + U_OFF, BPS, x, y, 8, 8, &s);
+ VP8SSIMAccumulate(yuv1 + V_OFF, BPS, yuv2 + V_OFF, BPS, x, y, 8, 8, &s);
+ }
+ }
+ return VP8SSIMGet(&s);
+}
+
+//------------------------------------------------------------------------------
+// Exposed APIs: Encoder should call the following 3 functions to adjust
+// loop filter strength
+
+void VP8InitFilter(VP8EncIterator* const it) {
+ int s, i;
+ if (!it->lf_stats_) return;
+
+ InitTables();
+ for (s = 0; s < NUM_MB_SEGMENTS; s++) {
+ for (i = 0; i < MAX_LF_LEVELS; i++) {
+ (*it->lf_stats_)[s][i] = 0;
+ }
+ }
+}
+
+void VP8StoreFilterStats(VP8EncIterator* const it) {
+ int d;
+ const int s = it->mb_->segment_;
+ const int level0 = it->enc_->dqm_[s].fstrength_; // TODO: ref_lf_delta[]
+
+ // explore +/-quant range of values around level0
+ const int delta_min = -it->enc_->dqm_[s].quant_;
+ const int delta_max = it->enc_->dqm_[s].quant_;
+ const int step_size = (delta_max - delta_min >= 4) ? 4 : 1;
+
+ if (!it->lf_stats_) return;
+
+ // NOTE: Currently we are applying filter only across the sublock edges
+ // There are two reasons for that.
+ // 1. Applying filter on macro block edges will change the pixels in
+ // the left and top macro blocks. That will be hard to restore
+ // 2. Macro Blocks on the bottom and right are not yet compressed. So we
+ // cannot apply filter on the right and bottom macro block edges.
+ if (it->mb_->type_ == 1 && it->mb_->skip_) return;
+
+ // Always try filter level zero
+ (*it->lf_stats_)[s][0] += GetMBSSIM(it->yuv_in_, it->yuv_out_);
+
+ for (d = delta_min; d <= delta_max; d += step_size) {
+ const int level = level0 + d;
+ if (level <= 0 || level >= MAX_LF_LEVELS) {
+ continue;
+ }
+ DoFilter(it, level);
+ (*it->lf_stats_)[s][level] += GetMBSSIM(it->yuv_in_, it->yuv_out2_);
+ }
+}
+
+void VP8AdjustFilterStrength(VP8EncIterator* const it) {
+ int s;
+ VP8Encoder* const enc = it->enc_;
+
+ if (!it->lf_stats_) {
+ return;
+ }
+ for (s = 0; s < NUM_MB_SEGMENTS; s++) {
+ int i, best_level = 0;
+ // Improvement over filter level 0 should be at least 1e-5 (relatively)
+ double best_v = 1.00001 * (*it->lf_stats_)[s][0];
+ for (i = 1; i < MAX_LF_LEVELS; i++) {
+ const double v = (*it->lf_stats_)[s][i];
+ if (v > best_v) {
+ best_v = v;
+ best_level = i;
+ }
+ }
+ enc->dqm_[s].fstrength_ = best_level;
+ }
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/enc/frame.c b/drivers/webpold/enc/frame.c
new file mode 100644
index 0000000000..bdd360069b
--- /dev/null
+++ b/drivers/webpold/enc/frame.c
@@ -0,0 +1,939 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// frame coding and analysis
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "./vp8enci.h"
+#include "./cost.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define SEGMENT_VISU 0
+#define DEBUG_SEARCH 0 // useful to track search convergence
+
+// On-the-fly info about the current set of residuals. Handy to avoid
+// passing zillions of params.
+typedef struct {
+ int first;
+ int last;
+ const int16_t* coeffs;
+
+ int coeff_type;
+ ProbaArray* prob;
+ StatsArray* stats;
+ CostArray* cost;
+} VP8Residual;
+
+//------------------------------------------------------------------------------
+// Tables for level coding
+
+const uint8_t VP8EncBands[16 + 1] = {
+ 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
+ 0 // sentinel
+};
+
+static const uint8_t kCat3[] = { 173, 148, 140 };
+static const uint8_t kCat4[] = { 176, 155, 140, 135 };
+static const uint8_t kCat5[] = { 180, 157, 141, 134, 130 };
+static const uint8_t kCat6[] =
+ { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 };
+
+//------------------------------------------------------------------------------
+// Reset the statistics about: number of skips, token proba, level cost,...
+
+static void ResetStats(VP8Encoder* const enc) {
+ VP8Proba* const proba = &enc->proba_;
+ VP8CalculateLevelCosts(proba);
+ proba->nb_skip_ = 0;
+}
+
+//------------------------------------------------------------------------------
+// Skip decision probability
+
+#define SKIP_PROBA_THRESHOLD 250 // value below which using skip_proba is OK.
+
+static int CalcSkipProba(uint64_t nb, uint64_t total) {
+ return (int)(total ? (total - nb) * 255 / total : 255);
+}
+
+// Returns the bit-cost for coding the skip probability.
+static int FinalizeSkipProba(VP8Encoder* const enc) {
+ VP8Proba* const proba = &enc->proba_;
+ const int nb_mbs = enc->mb_w_ * enc->mb_h_;
+ const int nb_events = proba->nb_skip_;
+ int size;
+ proba->skip_proba_ = CalcSkipProba(nb_events, nb_mbs);
+ proba->use_skip_proba_ = (proba->skip_proba_ < SKIP_PROBA_THRESHOLD);
+ size = 256; // 'use_skip_proba' bit
+ if (proba->use_skip_proba_) {
+ size += nb_events * VP8BitCost(1, proba->skip_proba_)
+ + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba_);
+ size += 8 * 256; // cost of signaling the skip_proba_ itself.
+ }
+ return size;
+}
+
+//------------------------------------------------------------------------------
+// Recording of token probabilities.
+
+static void ResetTokenStats(VP8Encoder* const enc) {
+ VP8Proba* const proba = &enc->proba_;
+ memset(proba->stats_, 0, sizeof(proba->stats_));
+}
+
+// Record proba context used
+static int Record(int bit, proba_t* const stats) {
+ proba_t p = *stats;
+ if (p >= 0xffff0000u) { // an overflow is inbound.
+ p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2.
+ }
+ // record bit count (lower 16 bits) and increment total count (upper 16 bits).
+ p += 0x00010000u + bit;
+ *stats = p;
+ return bit;
+}
+
+// We keep the table free variant around for reference, in case.
+#define USE_LEVEL_CODE_TABLE
+
+// Simulate block coding, but only record statistics.
+// Note: no need to record the fixed probas.
+static int RecordCoeffs(int ctx, const VP8Residual* const res) {
+ int n = res->first;
+ proba_t* s = res->stats[VP8EncBands[n]][ctx];
+ if (res->last < 0) {
+ Record(0, s + 0);
+ return 0;
+ }
+ while (n <= res->last) {
+ int v;
+ Record(1, s + 0);
+ while ((v = res->coeffs[n++]) == 0) {
+ Record(0, s + 1);
+ s = res->stats[VP8EncBands[n]][0];
+ }
+ Record(1, s + 1);
+ if (!Record(2u < (unsigned int)(v + 1), s + 2)) { // v = -1 or 1
+ s = res->stats[VP8EncBands[n]][1];
+ } else {
+ v = abs(v);
+#if !defined(USE_LEVEL_CODE_TABLE)
+ if (!Record(v > 4, s + 3)) {
+ if (Record(v != 2, s + 4))
+ Record(v == 4, s + 5);
+ } else if (!Record(v > 10, s + 6)) {
+ Record(v > 6, s + 7);
+ } else if (!Record((v >= 3 + (8 << 2)), s + 8)) {
+ Record((v >= 3 + (8 << 1)), s + 9);
+ } else {
+ Record((v >= 3 + (8 << 3)), s + 10);
+ }
+#else
+ if (v > MAX_VARIABLE_LEVEL)
+ v = MAX_VARIABLE_LEVEL;
+
+ {
+ const int bits = VP8LevelCodes[v - 1][1];
+ int pattern = VP8LevelCodes[v - 1][0];
+ int i;
+ for (i = 0; (pattern >>= 1) != 0; ++i) {
+ const int mask = 2 << i;
+ if (pattern & 1) Record(!!(bits & mask), s + 3 + i);
+ }
+ }
+#endif
+ s = res->stats[VP8EncBands[n]][2];
+ }
+ }
+ if (n < 16) Record(0, s + 0);
+ return 1;
+}
+
+// Collect statistics and deduce probabilities for next coding pass.
+// Return the total bit-cost for coding the probability updates.
+static int CalcTokenProba(int nb, int total) {
+ assert(nb <= total);
+ return nb ? (255 - nb * 255 / total) : 255;
+}
+
+// Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability.
+static int BranchCost(int nb, int total, int proba) {
+ return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba);
+}
+
+static int FinalizeTokenProbas(VP8Encoder* const enc) {
+ VP8Proba* const proba = &enc->proba_;
+ int has_changed = 0;
+ int size = 0;
+ int t, b, c, p;
+ for (t = 0; t < NUM_TYPES; ++t) {
+ for (b = 0; b < NUM_BANDS; ++b) {
+ for (c = 0; c < NUM_CTX; ++c) {
+ for (p = 0; p < NUM_PROBAS; ++p) {
+ const proba_t stats = proba->stats_[t][b][c][p];
+ const int nb = (stats >> 0) & 0xffff;
+ const int total = (stats >> 16) & 0xffff;
+ const int update_proba = VP8CoeffsUpdateProba[t][b][c][p];
+ const int old_p = VP8CoeffsProba0[t][b][c][p];
+ const int new_p = CalcTokenProba(nb, total);
+ const int old_cost = BranchCost(nb, total, old_p)
+ + VP8BitCost(0, update_proba);
+ const int new_cost = BranchCost(nb, total, new_p)
+ + VP8BitCost(1, update_proba)
+ + 8 * 256;
+ const int use_new_p = (old_cost > new_cost);
+ size += VP8BitCost(use_new_p, update_proba);
+ if (use_new_p) { // only use proba that seem meaningful enough.
+ proba->coeffs_[t][b][c][p] = new_p;
+ has_changed |= (new_p != old_p);
+ size += 8 * 256;
+ } else {
+ proba->coeffs_[t][b][c][p] = old_p;
+ }
+ }
+ }
+ }
+ }
+ proba->dirty_ = has_changed;
+ return size;
+}
+
+//------------------------------------------------------------------------------
+// helper functions for residuals struct VP8Residual.
+
+static void InitResidual(int first, int coeff_type,
+ VP8Encoder* const enc, VP8Residual* const res) {
+ res->coeff_type = coeff_type;
+ res->prob = enc->proba_.coeffs_[coeff_type];
+ res->stats = enc->proba_.stats_[coeff_type];
+ res->cost = enc->proba_.level_cost_[coeff_type];
+ res->first = first;
+}
+
+static void SetResidualCoeffs(const int16_t* const coeffs,
+ VP8Residual* const res) {
+ int n;
+ res->last = -1;
+ for (n = 15; n >= res->first; --n) {
+ if (coeffs[n]) {
+ res->last = n;
+ break;
+ }
+ }
+ res->coeffs = coeffs;
+}
+
+//------------------------------------------------------------------------------
+// Mode costs
+
+static int GetResidualCost(int ctx, const VP8Residual* const res) {
+ int n = res->first;
+ int p0 = res->prob[VP8EncBands[n]][ctx][0];
+ const uint16_t* t = res->cost[VP8EncBands[n]][ctx];
+ int cost;
+
+ if (res->last < 0) {
+ return VP8BitCost(0, p0);
+ }
+ cost = 0;
+ while (n <= res->last) {
+ const int v = res->coeffs[n];
+ const int b = VP8EncBands[n + 1];
+ ++n;
+ if (v == 0) {
+ // short-case for VP8LevelCost(t, 0) (note: VP8LevelFixedCosts[0] == 0):
+ cost += t[0];
+ t = res->cost[b][0];
+ continue;
+ }
+ cost += VP8BitCost(1, p0);
+ if (2u >= (unsigned int)(v + 1)) { // v = -1 or 1
+ // short-case for "VP8LevelCost(t, 1)" (256 is VP8LevelFixedCosts[1]):
+ cost += 256 + t[1];
+ p0 = res->prob[b][1][0];
+ t = res->cost[b][1];
+ } else {
+ cost += VP8LevelCost(t, abs(v));
+ p0 = res->prob[b][2][0];
+ t = res->cost[b][2];
+ }
+ }
+ if (n < 16) cost += VP8BitCost(0, p0);
+ return cost;
+}
+
+int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) {
+ const int x = (it->i4_ & 3), y = (it->i4_ >> 2);
+ VP8Residual res;
+ VP8Encoder* const enc = it->enc_;
+ int R = 0;
+ int ctx;
+
+ InitResidual(0, 3, enc, &res);
+ ctx = it->top_nz_[x] + it->left_nz_[y];
+ SetResidualCoeffs(levels, &res);
+ R += GetResidualCost(ctx, &res);
+ return R;
+}
+
+int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd) {
+ VP8Residual res;
+ VP8Encoder* const enc = it->enc_;
+ int x, y;
+ int R = 0;
+
+ VP8IteratorNzToBytes(it); // re-import the non-zero context
+
+ // DC
+ InitResidual(0, 1, enc, &res);
+ SetResidualCoeffs(rd->y_dc_levels, &res);
+ R += GetResidualCost(it->top_nz_[8] + it->left_nz_[8], &res);
+
+ // AC
+ InitResidual(1, 0, enc, &res);
+ for (y = 0; y < 4; ++y) {
+ for (x = 0; x < 4; ++x) {
+ const int ctx = it->top_nz_[x] + it->left_nz_[y];
+ SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
+ R += GetResidualCost(ctx, &res);
+ it->top_nz_[x] = it->left_nz_[y] = (res.last >= 0);
+ }
+ }
+ return R;
+}
+
+int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) {
+ VP8Residual res;
+ VP8Encoder* const enc = it->enc_;
+ int ch, x, y;
+ int R = 0;
+
+ VP8IteratorNzToBytes(it); // re-import the non-zero context
+
+ InitResidual(0, 2, enc, &res);
+ for (ch = 0; ch <= 2; ch += 2) {
+ for (y = 0; y < 2; ++y) {
+ for (x = 0; x < 2; ++x) {
+ const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
+ SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
+ R += GetResidualCost(ctx, &res);
+ it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = (res.last >= 0);
+ }
+ }
+ }
+ return R;
+}
+
+//------------------------------------------------------------------------------
+// Coefficient coding
+
+static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) {
+ int n = res->first;
+ const uint8_t* p = res->prob[VP8EncBands[n]][ctx];
+ if (!VP8PutBit(bw, res->last >= 0, p[0])) {
+ return 0;
+ }
+
+ while (n < 16) {
+ const int c = res->coeffs[n++];
+ const int sign = c < 0;
+ int v = sign ? -c : c;
+ if (!VP8PutBit(bw, v != 0, p[1])) {
+ p = res->prob[VP8EncBands[n]][0];
+ continue;
+ }
+ if (!VP8PutBit(bw, v > 1, p[2])) {
+ p = res->prob[VP8EncBands[n]][1];
+ } else {
+ if (!VP8PutBit(bw, v > 4, p[3])) {
+ if (VP8PutBit(bw, v != 2, p[4]))
+ VP8PutBit(bw, v == 4, p[5]);
+ } else if (!VP8PutBit(bw, v > 10, p[6])) {
+ if (!VP8PutBit(bw, v > 6, p[7])) {
+ VP8PutBit(bw, v == 6, 159);
+ } else {
+ VP8PutBit(bw, v >= 9, 165);
+ VP8PutBit(bw, !(v & 1), 145);
+ }
+ } else {
+ int mask;
+ const uint8_t* tab;
+ if (v < 3 + (8 << 1)) { // kCat3 (3b)
+ VP8PutBit(bw, 0, p[8]);
+ VP8PutBit(bw, 0, p[9]);
+ v -= 3 + (8 << 0);
+ mask = 1 << 2;
+ tab = kCat3;
+ } else if (v < 3 + (8 << 2)) { // kCat4 (4b)
+ VP8PutBit(bw, 0, p[8]);
+ VP8PutBit(bw, 1, p[9]);
+ v -= 3 + (8 << 1);
+ mask = 1 << 3;
+ tab = kCat4;
+ } else if (v < 3 + (8 << 3)) { // kCat5 (5b)
+ VP8PutBit(bw, 1, p[8]);
+ VP8PutBit(bw, 0, p[10]);
+ v -= 3 + (8 << 2);
+ mask = 1 << 4;
+ tab = kCat5;
+ } else { // kCat6 (11b)
+ VP8PutBit(bw, 1, p[8]);
+ VP8PutBit(bw, 1, p[10]);
+ v -= 3 + (8 << 3);
+ mask = 1 << 10;
+ tab = kCat6;
+ }
+ while (mask) {
+ VP8PutBit(bw, !!(v & mask), *tab++);
+ mask >>= 1;
+ }
+ }
+ p = res->prob[VP8EncBands[n]][2];
+ }
+ VP8PutBitUniform(bw, sign);
+ if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) {
+ return 1; // EOB
+ }
+ }
+ return 1;
+}
+
+static void CodeResiduals(VP8BitWriter* const bw,
+ VP8EncIterator* const it,
+ const VP8ModeScore* const rd) {
+ int x, y, ch;
+ VP8Residual res;
+ uint64_t pos1, pos2, pos3;
+ const int i16 = (it->mb_->type_ == 1);
+ const int segment = it->mb_->segment_;
+ VP8Encoder* const enc = it->enc_;
+
+ VP8IteratorNzToBytes(it);
+
+ pos1 = VP8BitWriterPos(bw);
+ if (i16) {
+ InitResidual(0, 1, enc, &res);
+ SetResidualCoeffs(rd->y_dc_levels, &res);
+ it->top_nz_[8] = it->left_nz_[8] =
+ PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res);
+ InitResidual(1, 0, enc, &res);
+ } else {
+ InitResidual(0, 3, enc, &res);
+ }
+
+ // luma-AC
+ for (y = 0; y < 4; ++y) {
+ for (x = 0; x < 4; ++x) {
+ const int ctx = it->top_nz_[x] + it->left_nz_[y];
+ SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
+ it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res);
+ }
+ }
+ pos2 = VP8BitWriterPos(bw);
+
+ // U/V
+ InitResidual(0, 2, enc, &res);
+ for (ch = 0; ch <= 2; ch += 2) {
+ for (y = 0; y < 2; ++y) {
+ for (x = 0; x < 2; ++x) {
+ const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
+ SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
+ it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
+ PutCoeffs(bw, ctx, &res);
+ }
+ }
+ }
+ pos3 = VP8BitWriterPos(bw);
+ it->luma_bits_ = pos2 - pos1;
+ it->uv_bits_ = pos3 - pos2;
+ it->bit_count_[segment][i16] += it->luma_bits_;
+ it->bit_count_[segment][2] += it->uv_bits_;
+ VP8IteratorBytesToNz(it);
+}
+
+// Same as CodeResiduals, but doesn't actually write anything.
+// Instead, it just records the event distribution.
+static void RecordResiduals(VP8EncIterator* const it,
+ const VP8ModeScore* const rd) {
+ int x, y, ch;
+ VP8Residual res;
+ VP8Encoder* const enc = it->enc_;
+
+ VP8IteratorNzToBytes(it);
+
+ if (it->mb_->type_ == 1) { // i16x16
+ InitResidual(0, 1, enc, &res);
+ SetResidualCoeffs(rd->y_dc_levels, &res);
+ it->top_nz_[8] = it->left_nz_[8] =
+ RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res);
+ InitResidual(1, 0, enc, &res);
+ } else {
+ InitResidual(0, 3, enc, &res);
+ }
+
+ // luma-AC
+ for (y = 0; y < 4; ++y) {
+ for (x = 0; x < 4; ++x) {
+ const int ctx = it->top_nz_[x] + it->left_nz_[y];
+ SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
+ it->top_nz_[x] = it->left_nz_[y] = RecordCoeffs(ctx, &res);
+ }
+ }
+
+ // U/V
+ InitResidual(0, 2, enc, &res);
+ for (ch = 0; ch <= 2; ch += 2) {
+ for (y = 0; y < 2; ++y) {
+ for (x = 0; x < 2; ++x) {
+ const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
+ SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
+ it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
+ RecordCoeffs(ctx, &res);
+ }
+ }
+ }
+
+ VP8IteratorBytesToNz(it);
+}
+
+//------------------------------------------------------------------------------
+// Token buffer
+
+#ifdef USE_TOKEN_BUFFER
+
+void VP8TBufferInit(VP8TBuffer* const b) {
+ b->rows_ = NULL;
+ b->tokens_ = NULL;
+ b->last_ = &b->rows_;
+ b->left_ = 0;
+ b->error_ = 0;
+}
+
+int VP8TBufferNewPage(VP8TBuffer* const b) {
+ VP8Tokens* const page = b->error_ ? NULL : (VP8Tokens*)malloc(sizeof(*page));
+ if (page == NULL) {
+ b->error_ = 1;
+ return 0;
+ }
+ *b->last_ = page;
+ b->last_ = &page->next_;
+ b->left_ = MAX_NUM_TOKEN;
+ b->tokens_ = page->tokens_;
+ return 1;
+}
+
+void VP8TBufferClear(VP8TBuffer* const b) {
+ if (b != NULL) {
+ const VP8Tokens* p = b->rows_;
+ while (p != NULL) {
+ const VP8Tokens* const next = p->next_;
+ free((void*)p);
+ p = next;
+ }
+ VP8TBufferInit(b);
+ }
+}
+
+int VP8EmitTokens(const VP8TBuffer* const b, VP8BitWriter* const bw,
+ const uint8_t* const probas) {
+ VP8Tokens* p = b->rows_;
+ if (b->error_) return 0;
+ while (p != NULL) {
+ const int N = (p->next_ == NULL) ? b->left_ : 0;
+ int n = MAX_NUM_TOKEN;
+ while (n-- > N) {
+ VP8PutBit(bw, (p->tokens_[n] >> 15) & 1, probas[p->tokens_[n] & 0x7fff]);
+ }
+ p = p->next_;
+ }
+ return 1;
+}
+
+#define TOKEN_ID(b, ctx, p) ((p) + NUM_PROBAS * ((ctx) + (b) * NUM_CTX))
+
+static int RecordCoeffTokens(int ctx, const VP8Residual* const res,
+ VP8TBuffer* tokens) {
+ int n = res->first;
+ int b = VP8EncBands[n];
+ if (!VP8AddToken(tokens, res->last >= 0, TOKEN_ID(b, ctx, 0))) {
+ return 0;
+ }
+
+ while (n < 16) {
+ const int c = res->coeffs[n++];
+ const int sign = c < 0;
+ int v = sign ? -c : c;
+ const int base_id = TOKEN_ID(b, ctx, 0);
+ if (!VP8AddToken(tokens, v != 0, base_id + 1)) {
+ b = VP8EncBands[n];
+ ctx = 0;
+ continue;
+ }
+ if (!VP8AddToken(tokens, v > 1, base_id + 2)) {
+ b = VP8EncBands[n];
+ ctx = 1;
+ } else {
+ if (!VP8AddToken(tokens, v > 4, base_id + 3)) {
+ if (VP8AddToken(tokens, v != 2, base_id + 4))
+ VP8AddToken(tokens, v == 4, base_id + 5);
+ } else if (!VP8AddToken(tokens, v > 10, base_id + 6)) {
+ if (!VP8AddToken(tokens, v > 6, base_id + 7)) {
+// VP8AddToken(tokens, v == 6, 159);
+ } else {
+// VP8AddToken(tokens, v >= 9, 165);
+// VP8AddToken(tokens, !(v & 1), 145);
+ }
+ } else {
+ int mask;
+ const uint8_t* tab;
+ if (v < 3 + (8 << 1)) { // kCat3 (3b)
+ VP8AddToken(tokens, 0, base_id + 8);
+ VP8AddToken(tokens, 0, base_id + 9);
+ v -= 3 + (8 << 0);
+ mask = 1 << 2;
+ tab = kCat3;
+ } else if (v < 3 + (8 << 2)) { // kCat4 (4b)
+ VP8AddToken(tokens, 0, base_id + 8);
+ VP8AddToken(tokens, 1, base_id + 9);
+ v -= 3 + (8 << 1);
+ mask = 1 << 3;
+ tab = kCat4;
+ } else if (v < 3 + (8 << 3)) { // kCat5 (5b)
+ VP8AddToken(tokens, 1, base_id + 8);
+ VP8AddToken(tokens, 0, base_id + 10);
+ v -= 3 + (8 << 2);
+ mask = 1 << 4;
+ tab = kCat5;
+ } else { // kCat6 (11b)
+ VP8AddToken(tokens, 1, base_id + 8);
+ VP8AddToken(tokens, 1, base_id + 10);
+ v -= 3 + (8 << 3);
+ mask = 1 << 10;
+ tab = kCat6;
+ }
+ while (mask) {
+ // VP8AddToken(tokens, !!(v & mask), *tab++);
+ mask >>= 1;
+ }
+ }
+ ctx = 2;
+ }
+ b = VP8EncBands[n];
+ // VP8PutBitUniform(bw, sign);
+ if (n == 16 || !VP8AddToken(tokens, n <= res->last, TOKEN_ID(b, ctx, 0))) {
+ return 1; // EOB
+ }
+ }
+ return 1;
+}
+
+static void RecordTokens(VP8EncIterator* const it,
+ const VP8ModeScore* const rd, VP8TBuffer tokens[2]) {
+ int x, y, ch;
+ VP8Residual res;
+ VP8Encoder* const enc = it->enc_;
+
+ VP8IteratorNzToBytes(it);
+ if (it->mb_->type_ == 1) { // i16x16
+ InitResidual(0, 1, enc, &res);
+ SetResidualCoeffs(rd->y_dc_levels, &res);
+// TODO(skal): FIX -> it->top_nz_[8] = it->left_nz_[8] =
+ RecordCoeffTokens(it->top_nz_[8] + it->left_nz_[8], &res, &tokens[0]);
+ InitResidual(1, 0, enc, &res);
+ } else {
+ InitResidual(0, 3, enc, &res);
+ }
+
+ // luma-AC
+ for (y = 0; y < 4; ++y) {
+ for (x = 0; x < 4; ++x) {
+ const int ctx = it->top_nz_[x] + it->left_nz_[y];
+ SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
+ it->top_nz_[x] = it->left_nz_[y] =
+ RecordCoeffTokens(ctx, &res, &tokens[0]);
+ }
+ }
+
+ // U/V
+ InitResidual(0, 2, enc, &res);
+ for (ch = 0; ch <= 2; ch += 2) {
+ for (y = 0; y < 2; ++y) {
+ for (x = 0; x < 2; ++x) {
+ const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
+ SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
+ it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
+ RecordCoeffTokens(ctx, &res, &tokens[1]);
+ }
+ }
+ }
+}
+
+#endif // USE_TOKEN_BUFFER
+
+//------------------------------------------------------------------------------
+// ExtraInfo map / Debug function
+
+#if SEGMENT_VISU
+static void SetBlock(uint8_t* p, int value, int size) {
+ int y;
+ for (y = 0; y < size; ++y) {
+ memset(p, value, size);
+ p += BPS;
+ }
+}
+#endif
+
+static void ResetSSE(VP8Encoder* const enc) {
+ memset(enc->sse_, 0, sizeof(enc->sse_));
+ enc->sse_count_ = 0;
+}
+
+static void StoreSSE(const VP8EncIterator* const it) {
+ VP8Encoder* const enc = it->enc_;
+ const uint8_t* const in = it->yuv_in_;
+ const uint8_t* const out = it->yuv_out_;
+ // Note: not totally accurate at boundary. And doesn't include in-loop filter.
+ enc->sse_[0] += VP8SSE16x16(in + Y_OFF, out + Y_OFF);
+ enc->sse_[1] += VP8SSE8x8(in + U_OFF, out + U_OFF);
+ enc->sse_[2] += VP8SSE8x8(in + V_OFF, out + V_OFF);
+ enc->sse_count_ += 16 * 16;
+}
+
+static void StoreSideInfo(const VP8EncIterator* const it) {
+ VP8Encoder* const enc = it->enc_;
+ const VP8MBInfo* const mb = it->mb_;
+ WebPPicture* const pic = enc->pic_;
+
+ if (pic->stats != NULL) {
+ StoreSSE(it);
+ enc->block_count_[0] += (mb->type_ == 0);
+ enc->block_count_[1] += (mb->type_ == 1);
+ enc->block_count_[2] += (mb->skip_ != 0);
+ }
+
+ if (pic->extra_info != NULL) {
+ uint8_t* const info = &pic->extra_info[it->x_ + it->y_ * enc->mb_w_];
+ switch (pic->extra_info_type) {
+ case 1: *info = mb->type_; break;
+ case 2: *info = mb->segment_; break;
+ case 3: *info = enc->dqm_[mb->segment_].quant_; break;
+ case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break;
+ case 5: *info = mb->uv_mode_; break;
+ case 6: {
+ const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3);
+ *info = (b > 255) ? 255 : b; break;
+ }
+ default: *info = 0; break;
+ };
+ }
+#if SEGMENT_VISU // visualize segments and prediction modes
+ SetBlock(it->yuv_out_ + Y_OFF, mb->segment_ * 64, 16);
+ SetBlock(it->yuv_out_ + U_OFF, it->preds_[0] * 64, 8);
+ SetBlock(it->yuv_out_ + V_OFF, mb->uv_mode_ * 64, 8);
+#endif
+}
+
+//------------------------------------------------------------------------------
+// Main loops
+//
+// VP8EncLoop(): does the final bitstream coding.
+
+static void ResetAfterSkip(VP8EncIterator* const it) {
+ if (it->mb_->type_ == 1) {
+ *it->nz_ = 0; // reset all predictors
+ it->left_nz_[8] = 0;
+ } else {
+ *it->nz_ &= (1 << 24); // preserve the dc_nz bit
+ }
+}
+
+int VP8EncLoop(VP8Encoder* const enc) {
+ int i, s, p;
+ int ok = 1;
+ VP8EncIterator it;
+ VP8ModeScore info;
+ const int dont_use_skip = !enc->proba_.use_skip_proba_;
+ const int rd_opt = enc->rd_opt_level_;
+ const int kAverageBytesPerMB = 5; // TODO: have a kTable[quality/10]
+ const int bytes_per_parts =
+ enc->mb_w_ * enc->mb_h_ * kAverageBytesPerMB / enc->num_parts_;
+
+ // Initialize the bit-writers
+ for (p = 0; p < enc->num_parts_; ++p) {
+ VP8BitWriterInit(enc->parts_ + p, bytes_per_parts);
+ }
+
+ ResetStats(enc);
+ ResetSSE(enc);
+
+ VP8IteratorInit(enc, &it);
+ VP8InitFilter(&it);
+ do {
+ VP8IteratorImport(&it);
+ // Warning! order is important: first call VP8Decimate() and
+ // *then* decide how to code the skip decision if there's one.
+ if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) {
+ CodeResiduals(it.bw_, &it, &info);
+ } else { // reset predictors after a skip
+ ResetAfterSkip(&it);
+ }
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ if (enc->use_layer_) {
+ VP8EncCodeLayerBlock(&it);
+ }
+#endif
+ StoreSideInfo(&it);
+ VP8StoreFilterStats(&it);
+ VP8IteratorExport(&it);
+ ok = VP8IteratorProgress(&it, 20);
+ } while (ok && VP8IteratorNext(&it, it.yuv_out_));
+
+ if (ok) { // Finalize the partitions, check for extra errors.
+ for (p = 0; p < enc->num_parts_; ++p) {
+ VP8BitWriterFinish(enc->parts_ + p);
+ ok &= !enc->parts_[p].error_;
+ }
+ }
+
+ if (ok) { // All good. Finish up.
+ if (enc->pic_->stats) { // finalize byte counters...
+ for (i = 0; i <= 2; ++i) {
+ for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
+ enc->residual_bytes_[i][s] = (int)((it.bit_count_[s][i] + 7) >> 3);
+ }
+ }
+ }
+ VP8AdjustFilterStrength(&it); // ...and store filter stats.
+ } else {
+ // Something bad happened -> need to do some memory cleanup.
+ VP8EncFreeBitWriters(enc);
+ }
+
+ return ok;
+}
+
+//------------------------------------------------------------------------------
+// VP8StatLoop(): only collect statistics (number of skips, token usage, ...)
+// This is used for deciding optimal probabilities. It also
+// modifies the quantizer value if some target (size, PNSR)
+// was specified.
+
+#define kHeaderSizeEstimate (15 + 20 + 10) // TODO: fix better
+
+static int OneStatPass(VP8Encoder* const enc, float q, int rd_opt, int nb_mbs,
+ float* const PSNR, int percent_delta) {
+ VP8EncIterator it;
+ uint64_t size = 0;
+ uint64_t distortion = 0;
+ const uint64_t pixel_count = nb_mbs * 384;
+
+ // Make sure the quality parameter is inside valid bounds
+ if (q < 0.) {
+ q = 0;
+ } else if (q > 100.) {
+ q = 100;
+ }
+
+ VP8SetSegmentParams(enc, q); // setup segment quantizations and filters
+
+ ResetStats(enc);
+ ResetTokenStats(enc);
+
+ VP8IteratorInit(enc, &it);
+ do {
+ VP8ModeScore info;
+ VP8IteratorImport(&it);
+ if (VP8Decimate(&it, &info, rd_opt)) {
+ // Just record the number of skips and act like skip_proba is not used.
+ enc->proba_.nb_skip_++;
+ }
+ RecordResiduals(&it, &info);
+ size += info.R;
+ distortion += info.D;
+ if (percent_delta && !VP8IteratorProgress(&it, percent_delta))
+ return 0;
+ } while (VP8IteratorNext(&it, it.yuv_out_) && --nb_mbs > 0);
+ size += FinalizeSkipProba(enc);
+ size += FinalizeTokenProbas(enc);
+ size += enc->segment_hdr_.size_;
+ size = ((size + 1024) >> 11) + kHeaderSizeEstimate;
+
+ if (PSNR) {
+ *PSNR = (float)(10.* log10(255. * 255. * pixel_count / distortion));
+ }
+ return (int)size;
+}
+
+// successive refinement increments.
+static const int dqs[] = { 20, 15, 10, 8, 6, 4, 2, 1, 0 };
+
+int VP8StatLoop(VP8Encoder* const enc) {
+ const int do_search =
+ (enc->config_->target_size > 0 || enc->config_->target_PSNR > 0);
+ const int fast_probe = (enc->method_ < 2 && !do_search);
+ float q = enc->config_->quality;
+ const int max_passes = enc->config_->pass;
+ const int task_percent = 20;
+ const int percent_per_pass = (task_percent + max_passes / 2) / max_passes;
+ const int final_percent = enc->percent_ + task_percent;
+ int pass;
+ int nb_mbs;
+
+ // Fast mode: quick analysis pass over few mbs. Better than nothing.
+ nb_mbs = enc->mb_w_ * enc->mb_h_;
+ if (fast_probe && nb_mbs > 100) nb_mbs = 100;
+
+ // No target size: just do several pass without changing 'q'
+ if (!do_search) {
+ for (pass = 0; pass < max_passes; ++pass) {
+ const int rd_opt = (enc->method_ > 2);
+ if (!OneStatPass(enc, q, rd_opt, nb_mbs, NULL, percent_per_pass)) {
+ return 0;
+ }
+ }
+ } else {
+ // binary search for a size close to target
+ for (pass = 0; pass < max_passes && (dqs[pass] > 0); ++pass) {
+ const int rd_opt = 1;
+ float PSNR;
+ int criterion;
+ const int size = OneStatPass(enc, q, rd_opt, nb_mbs, &PSNR,
+ percent_per_pass);
+#if DEBUG_SEARCH
+ printf("#%d size=%d PSNR=%.2f q=%.2f\n", pass, size, PSNR, q);
+#endif
+ if (!size) return 0;
+ if (enc->config_->target_PSNR > 0) {
+ criterion = (PSNR < enc->config_->target_PSNR);
+ } else {
+ criterion = (size < enc->config_->target_size);
+ }
+ // dichotomize
+ if (criterion) {
+ q += dqs[pass];
+ } else {
+ q -= dqs[pass];
+ }
+ }
+ }
+ return WebPReportProgress(enc->pic_, final_percent, &enc->percent_);
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/enc/histogram.c b/drivers/webpold/enc/histogram.c
new file mode 100644
index 0000000000..ca838e064d
--- /dev/null
+++ b/drivers/webpold/enc/histogram.c
@@ -0,0 +1,406 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Author: Jyrki Alakuijala (jyrki@google.com)
+//
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+#include <stdio.h>
+
+#include "./backward_references.h"
+#include "./histogram.h"
+#include "../dsp/lossless.h"
+#include "../utils/utils.h"
+
+static void HistogramClear(VP8LHistogram* const p) {
+ memset(p->literal_, 0, sizeof(p->literal_));
+ memset(p->red_, 0, sizeof(p->red_));
+ memset(p->blue_, 0, sizeof(p->blue_));
+ memset(p->alpha_, 0, sizeof(p->alpha_));
+ memset(p->distance_, 0, sizeof(p->distance_));
+ p->bit_cost_ = 0;
+}
+
+void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs,
+ VP8LHistogram* const histo) {
+ int i;
+ for (i = 0; i < refs->size; ++i) {
+ VP8LHistogramAddSinglePixOrCopy(histo, &refs->refs[i]);
+ }
+}
+
+void VP8LHistogramCreate(VP8LHistogram* const p,
+ const VP8LBackwardRefs* const refs,
+ int palette_code_bits) {
+ if (palette_code_bits >= 0) {
+ p->palette_code_bits_ = palette_code_bits;
+ }
+ HistogramClear(p);
+ VP8LHistogramStoreRefs(refs, p);
+}
+
+void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits) {
+ p->palette_code_bits_ = palette_code_bits;
+ HistogramClear(p);
+}
+
+VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) {
+ int i;
+ VP8LHistogramSet* set;
+ VP8LHistogram* bulk;
+ const uint64_t total_size = (uint64_t)sizeof(*set)
+ + size * sizeof(*set->histograms)
+ + size * sizeof(**set->histograms);
+ uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory));
+ if (memory == NULL) return NULL;
+
+ set = (VP8LHistogramSet*)memory;
+ memory += sizeof(*set);
+ set->histograms = (VP8LHistogram**)memory;
+ memory += size * sizeof(*set->histograms);
+ bulk = (VP8LHistogram*)memory;
+ set->max_size = size;
+ set->size = size;
+ for (i = 0; i < size; ++i) {
+ set->histograms[i] = bulk + i;
+ VP8LHistogramInit(set->histograms[i], cache_bits);
+ }
+ return set;
+}
+
+// -----------------------------------------------------------------------------
+
+void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
+ const PixOrCopy* const v) {
+ if (PixOrCopyIsLiteral(v)) {
+ ++histo->alpha_[PixOrCopyLiteral(v, 3)];
+ ++histo->red_[PixOrCopyLiteral(v, 2)];
+ ++histo->literal_[PixOrCopyLiteral(v, 1)];
+ ++histo->blue_[PixOrCopyLiteral(v, 0)];
+ } else if (PixOrCopyIsCacheIdx(v)) {
+ int literal_ix = 256 + NUM_LENGTH_CODES + PixOrCopyCacheIdx(v);
+ ++histo->literal_[literal_ix];
+ } else {
+ int code, extra_bits_count, extra_bits_value;
+ PrefixEncode(PixOrCopyLength(v),
+ &code, &extra_bits_count, &extra_bits_value);
+ ++histo->literal_[256 + code];
+ PrefixEncode(PixOrCopyDistance(v),
+ &code, &extra_bits_count, &extra_bits_value);
+ ++histo->distance_[code];
+ }
+}
+
+
+
+static double BitsEntropy(const int* const array, int n) {
+ double retval = 0.;
+ int sum = 0;
+ int nonzeros = 0;
+ int max_val = 0;
+ int i;
+ double mix;
+ for (i = 0; i < n; ++i) {
+ if (array[i] != 0) {
+ sum += array[i];
+ ++nonzeros;
+ retval -= VP8LFastSLog2(array[i]);
+ if (max_val < array[i]) {
+ max_val = array[i];
+ }
+ }
+ }
+ retval += VP8LFastSLog2(sum);
+
+ if (nonzeros < 5) {
+ if (nonzeros <= 1) {
+ return 0;
+ }
+ // Two symbols, they will be 0 and 1 in a Huffman code.
+ // Let's mix in a bit of entropy to favor good clustering when
+ // distributions of these are combined.
+ if (nonzeros == 2) {
+ return 0.99 * sum + 0.01 * retval;
+ }
+ // No matter what the entropy says, we cannot be better than min_limit
+ // with Huffman coding. I am mixing a bit of entropy into the
+ // min_limit since it produces much better (~0.5 %) compression results
+ // perhaps because of better entropy clustering.
+ if (nonzeros == 3) {
+ mix = 0.95;
+ } else {
+ mix = 0.7; // nonzeros == 4.
+ }
+ } else {
+ mix = 0.627;
+ }
+
+ {
+ double min_limit = 2 * sum - max_val;
+ min_limit = mix * min_limit + (1.0 - mix) * retval;
+ return (retval < min_limit) ? min_limit : retval;
+ }
+}
+
+double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p) {
+ double retval = BitsEntropy(&p->literal_[0], VP8LHistogramNumCodes(p))
+ + BitsEntropy(&p->red_[0], 256)
+ + BitsEntropy(&p->blue_[0], 256)
+ + BitsEntropy(&p->alpha_[0], 256)
+ + BitsEntropy(&p->distance_[0], NUM_DISTANCE_CODES);
+ // Compute the extra bits cost.
+ int i;
+ for (i = 2; i < NUM_LENGTH_CODES - 2; ++i) {
+ retval +=
+ (i >> 1) * p->literal_[256 + i + 2];
+ }
+ for (i = 2; i < NUM_DISTANCE_CODES - 2; ++i) {
+ retval += (i >> 1) * p->distance_[i + 2];
+ }
+ return retval;
+}
+
+
+// Returns the cost encode the rle-encoded entropy code.
+// The constants in this function are experimental.
+static double HuffmanCost(const int* const population, int length) {
+ // Small bias because Huffman code length is typically not stored in
+ // full length.
+ static const int kHuffmanCodeOfHuffmanCodeSize = CODE_LENGTH_CODES * 3;
+ static const double kSmallBias = 9.1;
+ double retval = kHuffmanCodeOfHuffmanCodeSize - kSmallBias;
+ int streak = 0;
+ int i = 0;
+ for (; i < length - 1; ++i) {
+ ++streak;
+ if (population[i] == population[i + 1]) {
+ continue;
+ }
+ last_streak_hack:
+ // population[i] points now to the symbol in the streak of same values.
+ if (streak > 3) {
+ if (population[i] == 0) {
+ retval += 1.5625 + 0.234375 * streak;
+ } else {
+ retval += 2.578125 + 0.703125 * streak;
+ }
+ } else {
+ if (population[i] == 0) {
+ retval += 1.796875 * streak;
+ } else {
+ retval += 3.28125 * streak;
+ }
+ }
+ streak = 0;
+ }
+ if (i == length - 1) {
+ ++streak;
+ goto last_streak_hack;
+ }
+ return retval;
+}
+
+// Estimates the Huffman dictionary + other block overhead size.
+static double HistogramEstimateBitsHeader(const VP8LHistogram* const p) {
+ return HuffmanCost(&p->alpha_[0], 256) +
+ HuffmanCost(&p->red_[0], 256) +
+ HuffmanCost(&p->literal_[0], VP8LHistogramNumCodes(p)) +
+ HuffmanCost(&p->blue_[0], 256) +
+ HuffmanCost(&p->distance_[0], NUM_DISTANCE_CODES);
+}
+
+double VP8LHistogramEstimateBits(const VP8LHistogram* const p) {
+ return HistogramEstimateBitsHeader(p) + VP8LHistogramEstimateBitsBulk(p);
+}
+
+static void HistogramBuildImage(int xsize, int histo_bits,
+ const VP8LBackwardRefs* const backward_refs,
+ VP8LHistogramSet* const image) {
+ int i;
+ int x = 0, y = 0;
+ const int histo_xsize = VP8LSubSampleSize(xsize, histo_bits);
+ VP8LHistogram** const histograms = image->histograms;
+ assert(histo_bits > 0);
+ for (i = 0; i < backward_refs->size; ++i) {
+ const PixOrCopy* const v = &backward_refs->refs[i];
+ const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits);
+ VP8LHistogramAddSinglePixOrCopy(histograms[ix], v);
+ x += PixOrCopyLength(v);
+ while (x >= xsize) {
+ x -= xsize;
+ ++y;
+ }
+ }
+}
+
+static uint32_t MyRand(uint32_t *seed) {
+ *seed *= 16807U;
+ if (*seed == 0) {
+ *seed = 1;
+ }
+ return *seed;
+}
+
+static int HistogramCombine(const VP8LHistogramSet* const in,
+ VP8LHistogramSet* const out, int num_pairs) {
+ int ok = 0;
+ int i, iter;
+ uint32_t seed = 0;
+ int tries_with_no_success = 0;
+ const int min_cluster_size = 2;
+ int out_size = in->size;
+ const int outer_iters = in->size * 3;
+ VP8LHistogram* const histos = (VP8LHistogram*)malloc(2 * sizeof(*histos));
+ VP8LHistogram* cur_combo = histos + 0; // trial merged histogram
+ VP8LHistogram* best_combo = histos + 1; // best merged histogram so far
+ if (histos == NULL) goto End;
+
+ // Copy histograms from in[] to out[].
+ assert(in->size <= out->size);
+ for (i = 0; i < in->size; ++i) {
+ in->histograms[i]->bit_cost_ = VP8LHistogramEstimateBits(in->histograms[i]);
+ *out->histograms[i] = *in->histograms[i];
+ }
+
+ // Collapse similar histograms in 'out'.
+ for (iter = 0; iter < outer_iters && out_size >= min_cluster_size; ++iter) {
+ // We pick the best pair to be combined out of 'inner_iters' pairs.
+ double best_cost_diff = 0.;
+ int best_idx1 = 0, best_idx2 = 1;
+ int j;
+ seed += iter;
+ for (j = 0; j < num_pairs; ++j) {
+ double curr_cost_diff;
+ // Choose two histograms at random and try to combine them.
+ const uint32_t idx1 = MyRand(&seed) % out_size;
+ const uint32_t tmp = ((j & 7) + 1) % (out_size - 1);
+ const uint32_t diff = (tmp < 3) ? tmp : MyRand(&seed) % (out_size - 1);
+ const uint32_t idx2 = (idx1 + diff + 1) % out_size;
+ if (idx1 == idx2) {
+ continue;
+ }
+ *cur_combo = *out->histograms[idx1];
+ VP8LHistogramAdd(cur_combo, out->histograms[idx2]);
+ cur_combo->bit_cost_ = VP8LHistogramEstimateBits(cur_combo);
+ // Calculate cost reduction on combining.
+ curr_cost_diff = cur_combo->bit_cost_
+ - out->histograms[idx1]->bit_cost_
+ - out->histograms[idx2]->bit_cost_;
+ if (best_cost_diff > curr_cost_diff) { // found a better pair?
+ { // swap cur/best combo histograms
+ VP8LHistogram* const tmp_histo = cur_combo;
+ cur_combo = best_combo;
+ best_combo = tmp_histo;
+ }
+ best_cost_diff = curr_cost_diff;
+ best_idx1 = idx1;
+ best_idx2 = idx2;
+ }
+ }
+
+ if (best_cost_diff < 0.0) {
+ *out->histograms[best_idx1] = *best_combo;
+ // swap best_idx2 slot with last one (which is now unused)
+ --out_size;
+ if (best_idx2 != out_size) {
+ out->histograms[best_idx2] = out->histograms[out_size];
+ out->histograms[out_size] = NULL; // just for sanity check.
+ }
+ tries_with_no_success = 0;
+ }
+ if (++tries_with_no_success >= 50) {
+ break;
+ }
+ }
+ out->size = out_size;
+ ok = 1;
+
+ End:
+ free(histos);
+ return ok;
+}
+
+// -----------------------------------------------------------------------------
+// Histogram refinement
+
+// What is the bit cost of moving square_histogram from
+// cur_symbol to candidate_symbol.
+// TODO(skal): we don't really need to copy the histogram and Add(). Instead
+// we just need VP8LDualHistogramEstimateBits(A, B) estimation function.
+static double HistogramDistance(const VP8LHistogram* const square_histogram,
+ const VP8LHistogram* const candidate) {
+ const double previous_bit_cost = candidate->bit_cost_;
+ double new_bit_cost;
+ VP8LHistogram modified_histo;
+ modified_histo = *candidate;
+ VP8LHistogramAdd(&modified_histo, square_histogram);
+ new_bit_cost = VP8LHistogramEstimateBits(&modified_histo);
+
+ return new_bit_cost - previous_bit_cost;
+}
+
+// Find the best 'out' histogram for each of the 'in' histograms.
+// Note: we assume that out[]->bit_cost_ is already up-to-date.
+static void HistogramRemap(const VP8LHistogramSet* const in,
+ const VP8LHistogramSet* const out,
+ uint16_t* const symbols) {
+ int i;
+ for (i = 0; i < in->size; ++i) {
+ int best_out = 0;
+ double best_bits = HistogramDistance(in->histograms[i], out->histograms[0]);
+ int k;
+ for (k = 1; k < out->size; ++k) {
+ const double cur_bits =
+ HistogramDistance(in->histograms[i], out->histograms[k]);
+ if (cur_bits < best_bits) {
+ best_bits = cur_bits;
+ best_out = k;
+ }
+ }
+ symbols[i] = best_out;
+ }
+
+ // Recompute each out based on raw and symbols.
+ for (i = 0; i < out->size; ++i) {
+ HistogramClear(out->histograms[i]);
+ }
+ for (i = 0; i < in->size; ++i) {
+ VP8LHistogramAdd(out->histograms[symbols[i]], in->histograms[i]);
+ }
+}
+
+int VP8LGetHistoImageSymbols(int xsize, int ysize,
+ const VP8LBackwardRefs* const refs,
+ int quality, int histo_bits, int cache_bits,
+ VP8LHistogramSet* const image_in,
+ uint16_t* const histogram_symbols) {
+ int ok = 0;
+ const int histo_xsize = histo_bits ? VP8LSubSampleSize(xsize, histo_bits) : 1;
+ const int histo_ysize = histo_bits ? VP8LSubSampleSize(ysize, histo_bits) : 1;
+ const int num_histo_pairs = 10 + quality / 2; // For HistogramCombine().
+ const int histo_image_raw_size = histo_xsize * histo_ysize;
+ VP8LHistogramSet* const image_out =
+ VP8LAllocateHistogramSet(histo_image_raw_size, cache_bits);
+ if (image_out == NULL) return 0;
+
+ // Build histogram image.
+ HistogramBuildImage(xsize, histo_bits, refs, image_out);
+ // Collapse similar histograms.
+ if (!HistogramCombine(image_out, image_in, num_histo_pairs)) {
+ goto Error;
+ }
+ // Find the optimal map from original histograms to the final ones.
+ HistogramRemap(image_out, image_in, histogram_symbols);
+ ok = 1;
+
+Error:
+ free(image_out);
+ return ok;
+}
diff --git a/drivers/webpold/enc/histogram.h b/drivers/webpold/enc/histogram.h
new file mode 100644
index 0000000000..5b5de25539
--- /dev/null
+++ b/drivers/webpold/enc/histogram.h
@@ -0,0 +1,115 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Author: Jyrki Alakuijala (jyrki@google.com)
+//
+// Models the histograms of literal and distance codes.
+
+#ifndef WEBP_ENC_HISTOGRAM_H_
+#define WEBP_ENC_HISTOGRAM_H_
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "./backward_references.h"
+#include "../format_constants.h"
+#include "../types.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+// A simple container for histograms of data.
+typedef struct {
+ // literal_ contains green literal, palette-code and
+ // copy-length-prefix histogram
+ int literal_[PIX_OR_COPY_CODES_MAX];
+ int red_[256];
+ int blue_[256];
+ int alpha_[256];
+ // Backward reference prefix-code histogram.
+ int distance_[NUM_DISTANCE_CODES];
+ int palette_code_bits_;
+ double bit_cost_; // cached value of VP8LHistogramEstimateBits(this)
+} VP8LHistogram;
+
+// Collection of histograms with fixed capacity, allocated as one
+// big memory chunk. Can be destroyed by simply calling 'free()'.
+typedef struct {
+ int size; // number of slots currently in use
+ int max_size; // maximum capacity
+ VP8LHistogram** histograms;
+} VP8LHistogramSet;
+
+// Create the histogram.
+//
+// The input data is the PixOrCopy data, which models the literals, stop
+// codes and backward references (both distances and lengths). Also: if
+// palette_code_bits is >= 0, initialize the histogram with this value.
+void VP8LHistogramCreate(VP8LHistogram* const p,
+ const VP8LBackwardRefs* const refs,
+ int palette_code_bits);
+
+// Set the palette_code_bits and reset the stats.
+void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits);
+
+// Collect all the references into a histogram (without reset)
+void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs,
+ VP8LHistogram* const histo);
+
+// Allocate an array of pointer to histograms, allocated and initialized
+// using 'cache_bits'. Return NULL in case of memory error.
+VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits);
+
+// Accumulate a token 'v' into a histogram.
+void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
+ const PixOrCopy* const v);
+
+// Estimate how many bits the combined entropy of literals and distance
+// approximately maps to.
+double VP8LHistogramEstimateBits(const VP8LHistogram* const p);
+
+// This function estimates the cost in bits excluding the bits needed to
+// represent the entropy code itself.
+double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p);
+
+static WEBP_INLINE void VP8LHistogramAdd(VP8LHistogram* const p,
+ const VP8LHistogram* const a) {
+ int i;
+ for (i = 0; i < PIX_OR_COPY_CODES_MAX; ++i) {
+ p->literal_[i] += a->literal_[i];
+ }
+ for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
+ p->distance_[i] += a->distance_[i];
+ }
+ for (i = 0; i < 256; ++i) {
+ p->red_[i] += a->red_[i];
+ p->blue_[i] += a->blue_[i];
+ p->alpha_[i] += a->alpha_[i];
+ }
+}
+
+static WEBP_INLINE int VP8LHistogramNumCodes(const VP8LHistogram* const p) {
+ return 256 + NUM_LENGTH_CODES +
+ ((p->palette_code_bits_ > 0) ? (1 << p->palette_code_bits_) : 0);
+}
+
+// Builds the histogram image.
+int VP8LGetHistoImageSymbols(int xsize, int ysize,
+ const VP8LBackwardRefs* const refs,
+ int quality, int histogram_bits, int cache_bits,
+ VP8LHistogramSet* const image_in,
+ uint16_t* const histogram_symbols);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif // WEBP_ENC_HISTOGRAM_H_
diff --git a/drivers/webpold/enc/iterator.c b/drivers/webpold/enc/iterator.c
new file mode 100644
index 0000000000..86e473bcf0
--- /dev/null
+++ b/drivers/webpold/enc/iterator.c
@@ -0,0 +1,422 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// VP8Iterator: block iterator
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <string.h>
+
+#include "./vp8enci.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// VP8Iterator
+//------------------------------------------------------------------------------
+
+static void InitLeft(VP8EncIterator* const it) {
+ const VP8Encoder* const enc = it->enc_;
+ enc->y_left_[-1] = enc->u_left_[-1] = enc->v_left_[-1] =
+ (it->y_ > 0) ? 129 : 127;
+ memset(enc->y_left_, 129, 16);
+ memset(enc->u_left_, 129, 8);
+ memset(enc->v_left_, 129, 8);
+ it->left_nz_[8] = 0;
+}
+
+static void InitTop(VP8EncIterator* const it) {
+ const VP8Encoder* const enc = it->enc_;
+ const size_t top_size = enc->mb_w_ * 16;
+ memset(enc->y_top_, 127, 2 * top_size);
+ memset(enc->nz_, 0, enc->mb_w_ * sizeof(*enc->nz_));
+}
+
+void VP8IteratorReset(VP8EncIterator* const it) {
+ VP8Encoder* const enc = it->enc_;
+ it->x_ = 0;
+ it->y_ = 0;
+ it->y_offset_ = 0;
+ it->uv_offset_ = 0;
+ it->mb_ = enc->mb_info_;
+ it->preds_ = enc->preds_;
+ it->nz_ = enc->nz_;
+ it->bw_ = &enc->parts_[0];
+ it->done_ = enc->mb_w_* enc->mb_h_;
+ InitTop(it);
+ InitLeft(it);
+ memset(it->bit_count_, 0, sizeof(it->bit_count_));
+ it->do_trellis_ = 0;
+}
+
+void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) {
+ it->enc_ = enc;
+ it->y_stride_ = enc->pic_->y_stride;
+ it->uv_stride_ = enc->pic_->uv_stride;
+ // TODO(later): for multithreading, these should be owned by 'it'.
+ it->yuv_in_ = enc->yuv_in_;
+ it->yuv_out_ = enc->yuv_out_;
+ it->yuv_out2_ = enc->yuv_out2_;
+ it->yuv_p_ = enc->yuv_p_;
+ it->lf_stats_ = enc->lf_stats_;
+ it->percent0_ = enc->percent_;
+ VP8IteratorReset(it);
+}
+
+int VP8IteratorProgress(const VP8EncIterator* const it, int delta) {
+ VP8Encoder* const enc = it->enc_;
+ if (delta && enc->pic_->progress_hook) {
+ const int percent = (enc->mb_h_ <= 1)
+ ? it->percent0_
+ : it->percent0_ + delta * it->y_ / (enc->mb_h_ - 1);
+ return WebPReportProgress(enc->pic_, percent, &enc->percent_);
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Import the source samples into the cache. Takes care of replicating
+// boundary pixels if necessary.
+
+static void ImportBlock(const uint8_t* src, int src_stride,
+ uint8_t* dst, int w, int h, int size) {
+ int i;
+ for (i = 0; i < h; ++i) {
+ memcpy(dst, src, w);
+ if (w < size) {
+ memset(dst + w, dst[w - 1], size - w);
+ }
+ dst += BPS;
+ src += src_stride;
+ }
+ for (i = h; i < size; ++i) {
+ memcpy(dst, dst - BPS, size);
+ dst += BPS;
+ }
+}
+
+void VP8IteratorImport(const VP8EncIterator* const it) {
+ const VP8Encoder* const enc = it->enc_;
+ const int x = it->x_, y = it->y_;
+ const WebPPicture* const pic = enc->pic_;
+ const uint8_t* const ysrc = pic->y + (y * pic->y_stride + x) * 16;
+ const uint8_t* const usrc = pic->u + (y * pic->uv_stride + x) * 8;
+ const uint8_t* const vsrc = pic->v + (y * pic->uv_stride + x) * 8;
+ uint8_t* const ydst = it->yuv_in_ + Y_OFF;
+ uint8_t* const udst = it->yuv_in_ + U_OFF;
+ uint8_t* const vdst = it->yuv_in_ + V_OFF;
+ int w = (pic->width - x * 16);
+ int h = (pic->height - y * 16);
+
+ if (w > 16) w = 16;
+ if (h > 16) h = 16;
+
+ // Luma plane
+ ImportBlock(ysrc, pic->y_stride, ydst, w, h, 16);
+
+ { // U/V planes
+ const int uv_w = (w + 1) >> 1;
+ const int uv_h = (h + 1) >> 1;
+ ImportBlock(usrc, pic->uv_stride, udst, uv_w, uv_h, 8);
+ ImportBlock(vsrc, pic->uv_stride, vdst, uv_w, uv_h, 8);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Copy back the compressed samples into user space if requested.
+
+static void ExportBlock(const uint8_t* src, uint8_t* dst, int dst_stride,
+ int w, int h) {
+ while (h-- > 0) {
+ memcpy(dst, src, w);
+ dst += dst_stride;
+ src += BPS;
+ }
+}
+
+void VP8IteratorExport(const VP8EncIterator* const it) {
+ const VP8Encoder* const enc = it->enc_;
+ if (enc->config_->show_compressed) {
+ const int x = it->x_, y = it->y_;
+ const uint8_t* const ysrc = it->yuv_out_ + Y_OFF;
+ const uint8_t* const usrc = it->yuv_out_ + U_OFF;
+ const uint8_t* const vsrc = it->yuv_out_ + V_OFF;
+ const WebPPicture* const pic = enc->pic_;
+ uint8_t* const ydst = pic->y + (y * pic->y_stride + x) * 16;
+ uint8_t* const udst = pic->u + (y * pic->uv_stride + x) * 8;
+ uint8_t* const vdst = pic->v + (y * pic->uv_stride + x) * 8;
+ int w = (pic->width - x * 16);
+ int h = (pic->height - y * 16);
+
+ if (w > 16) w = 16;
+ if (h > 16) h = 16;
+
+ // Luma plane
+ ExportBlock(ysrc, ydst, pic->y_stride, w, h);
+
+ { // U/V planes
+ const int uv_w = (w + 1) >> 1;
+ const int uv_h = (h + 1) >> 1;
+ ExportBlock(usrc, udst, pic->uv_stride, uv_w, uv_h);
+ ExportBlock(vsrc, vdst, pic->uv_stride, uv_w, uv_h);
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// Non-zero contexts setup/teardown
+
+// Nz bits:
+// 0 1 2 3 Y
+// 4 5 6 7
+// 8 9 10 11
+// 12 13 14 15
+// 16 17 U
+// 18 19
+// 20 21 V
+// 22 23
+// 24 DC-intra16
+
+// Convert packed context to byte array
+#define BIT(nz, n) (!!((nz) & (1 << (n))))
+
+void VP8IteratorNzToBytes(VP8EncIterator* const it) {
+ const int tnz = it->nz_[0], lnz = it->nz_[-1];
+ int* const top_nz = it->top_nz_;
+ int* const left_nz = it->left_nz_;
+
+ // Top-Y
+ top_nz[0] = BIT(tnz, 12);
+ top_nz[1] = BIT(tnz, 13);
+ top_nz[2] = BIT(tnz, 14);
+ top_nz[3] = BIT(tnz, 15);
+ // Top-U
+ top_nz[4] = BIT(tnz, 18);
+ top_nz[5] = BIT(tnz, 19);
+ // Top-V
+ top_nz[6] = BIT(tnz, 22);
+ top_nz[7] = BIT(tnz, 23);
+ // DC
+ top_nz[8] = BIT(tnz, 24);
+
+ // left-Y
+ left_nz[0] = BIT(lnz, 3);
+ left_nz[1] = BIT(lnz, 7);
+ left_nz[2] = BIT(lnz, 11);
+ left_nz[3] = BIT(lnz, 15);
+ // left-U
+ left_nz[4] = BIT(lnz, 17);
+ left_nz[5] = BIT(lnz, 19);
+ // left-V
+ left_nz[6] = BIT(lnz, 21);
+ left_nz[7] = BIT(lnz, 23);
+ // left-DC is special, iterated separately
+}
+
+void VP8IteratorBytesToNz(VP8EncIterator* const it) {
+ uint32_t nz = 0;
+ const int* const top_nz = it->top_nz_;
+ const int* const left_nz = it->left_nz_;
+ // top
+ nz |= (top_nz[0] << 12) | (top_nz[1] << 13);
+ nz |= (top_nz[2] << 14) | (top_nz[3] << 15);
+ nz |= (top_nz[4] << 18) | (top_nz[5] << 19);
+ nz |= (top_nz[6] << 22) | (top_nz[7] << 23);
+ nz |= (top_nz[8] << 24); // we propagate the _top_ bit, esp. for intra4
+ // left
+ nz |= (left_nz[0] << 3) | (left_nz[1] << 7);
+ nz |= (left_nz[2] << 11);
+ nz |= (left_nz[4] << 17) | (left_nz[6] << 21);
+
+ *it->nz_ = nz;
+}
+
+#undef BIT
+
+//------------------------------------------------------------------------------
+// Advance to the next position, doing the bookeeping.
+
+int VP8IteratorNext(VP8EncIterator* const it,
+ const uint8_t* const block_to_save) {
+ VP8Encoder* const enc = it->enc_;
+ if (block_to_save) {
+ const int x = it->x_, y = it->y_;
+ const uint8_t* const ysrc = block_to_save + Y_OFF;
+ const uint8_t* const usrc = block_to_save + U_OFF;
+ if (x < enc->mb_w_ - 1) { // left
+ int i;
+ for (i = 0; i < 16; ++i) {
+ enc->y_left_[i] = ysrc[15 + i * BPS];
+ }
+ for (i = 0; i < 8; ++i) {
+ enc->u_left_[i] = usrc[7 + i * BPS];
+ enc->v_left_[i] = usrc[15 + i * BPS];
+ }
+ // top-left (before 'top'!)
+ enc->y_left_[-1] = enc->y_top_[x * 16 + 15];
+ enc->u_left_[-1] = enc->uv_top_[x * 16 + 0 + 7];
+ enc->v_left_[-1] = enc->uv_top_[x * 16 + 8 + 7];
+ }
+ if (y < enc->mb_h_ - 1) { // top
+ memcpy(enc->y_top_ + x * 16, ysrc + 15 * BPS, 16);
+ memcpy(enc->uv_top_ + x * 16, usrc + 7 * BPS, 8 + 8);
+ }
+ }
+
+ it->mb_++;
+ it->preds_ += 4;
+ it->nz_++;
+ it->x_++;
+ if (it->x_ == enc->mb_w_) {
+ it->x_ = 0;
+ it->y_++;
+ it->bw_ = &enc->parts_[it->y_ & (enc->num_parts_ - 1)];
+ it->preds_ = enc->preds_ + it->y_ * 4 * enc->preds_w_;
+ it->nz_ = enc->nz_;
+ InitLeft(it);
+ }
+ return (0 < --it->done_);
+}
+
+//------------------------------------------------------------------------------
+// Helper function to set mode properties
+
+void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode) {
+ uint8_t* preds = it->preds_;
+ int y;
+ for (y = 0; y < 4; ++y) {
+ memset(preds, mode, 4);
+ preds += it->enc_->preds_w_;
+ }
+ it->mb_->type_ = 1;
+}
+
+void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes) {
+ uint8_t* preds = it->preds_;
+ int y;
+ for (y = 4; y > 0; --y) {
+ memcpy(preds, modes, 4 * sizeof(*modes));
+ preds += it->enc_->preds_w_;
+ modes += 4;
+ }
+ it->mb_->type_ = 0;
+}
+
+void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode) {
+ it->mb_->uv_mode_ = mode;
+}
+
+void VP8SetSkip(const VP8EncIterator* const it, int skip) {
+ it->mb_->skip_ = skip;
+}
+
+void VP8SetSegment(const VP8EncIterator* const it, int segment) {
+ it->mb_->segment_ = segment;
+}
+
+//------------------------------------------------------------------------------
+// Intra4x4 sub-blocks iteration
+//
+// We store and update the boundary samples into an array of 37 pixels. They
+// are updated as we iterate and reconstructs each intra4x4 blocks in turn.
+// The position of the samples has the following snake pattern:
+//
+// 16|17 18 19 20|21 22 23 24|25 26 27 28|29 30 31 32|33 34 35 36 <- Top-right
+// --+-----------+-----------+-----------+-----------+
+// 15| 19| 23| 27| 31|
+// 14| 18| 22| 26| 30|
+// 13| 17| 21| 25| 29|
+// 12|13 14 15 16|17 18 19 20|21 22 23 24|25 26 27 28|
+// --+-----------+-----------+-----------+-----------+
+// 11| 15| 19| 23| 27|
+// 10| 14| 18| 22| 26|
+// 9| 13| 17| 21| 25|
+// 8| 9 10 11 12|13 14 15 16|17 18 19 20|21 22 23 24|
+// --+-----------+-----------+-----------+-----------+
+// 7| 11| 15| 19| 23|
+// 6| 10| 14| 18| 22|
+// 5| 9| 13| 17| 21|
+// 4| 5 6 7 8| 9 10 11 12|13 14 15 16|17 18 19 20|
+// --+-----------+-----------+-----------+-----------+
+// 3| 7| 11| 15| 19|
+// 2| 6| 10| 14| 18|
+// 1| 5| 9| 13| 17|
+// 0| 1 2 3 4| 5 6 7 8| 9 10 11 12|13 14 15 16|
+// --+-----------+-----------+-----------+-----------+
+
+// Array to record the position of the top sample to pass to the prediction
+// functions in dsp.c.
+static const uint8_t VP8TopLeftI4[16] = {
+ 17, 21, 25, 29,
+ 13, 17, 21, 25,
+ 9, 13, 17, 21,
+ 5, 9, 13, 17
+};
+
+void VP8IteratorStartI4(VP8EncIterator* const it) {
+ const VP8Encoder* const enc = it->enc_;
+ int i;
+
+ it->i4_ = 0; // first 4x4 sub-block
+ it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[0];
+
+ // Import the boundary samples
+ for (i = 0; i < 17; ++i) { // left
+ it->i4_boundary_[i] = enc->y_left_[15 - i];
+ }
+ for (i = 0; i < 16; ++i) { // top
+ it->i4_boundary_[17 + i] = enc->y_top_[it->x_ * 16 + i];
+ }
+ // top-right samples have a special case on the far right of the picture
+ if (it->x_ < enc->mb_w_ - 1) {
+ for (i = 16; i < 16 + 4; ++i) {
+ it->i4_boundary_[17 + i] = enc->y_top_[it->x_ * 16 + i];
+ }
+ } else { // else, replicate the last valid pixel four times
+ for (i = 16; i < 16 + 4; ++i) {
+ it->i4_boundary_[17 + i] = it->i4_boundary_[17 + 15];
+ }
+ }
+ VP8IteratorNzToBytes(it); // import the non-zero context
+}
+
+int VP8IteratorRotateI4(VP8EncIterator* const it,
+ const uint8_t* const yuv_out) {
+ const uint8_t* const blk = yuv_out + VP8Scan[it->i4_];
+ uint8_t* const top = it->i4_top_;
+ int i;
+
+ // Update the cache with 7 fresh samples
+ for (i = 0; i <= 3; ++i) {
+ top[-4 + i] = blk[i + 3 * BPS]; // store future top samples
+ }
+ if ((it->i4_ & 3) != 3) { // if not on the right sub-blocks #3, #7, #11, #15
+ for (i = 0; i <= 2; ++i) { // store future left samples
+ top[i] = blk[3 + (2 - i) * BPS];
+ }
+ } else { // else replicate top-right samples, as says the specs.
+ for (i = 0; i <= 3; ++i) {
+ top[i] = top[i + 4];
+ }
+ }
+ // move pointers to next sub-block
+ ++it->i4_;
+ if (it->i4_ == 16) { // we're done
+ return 0;
+ }
+
+ it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[it->i4_];
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webp/enc/layer.c b/drivers/webpold/enc/layer.c
index 423127df63..423127df63 100644
--- a/drivers/webp/enc/layer.c
+++ b/drivers/webpold/enc/layer.c
diff --git a/drivers/webpold/enc/picture.c b/drivers/webpold/enc/picture.c
new file mode 100644
index 0000000000..44eed06083
--- /dev/null
+++ b/drivers/webpold/enc/picture.c
@@ -0,0 +1,1041 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// WebPPicture utils: colorspace conversion, crop, ...
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "./vp8enci.h"
+#include "../utils/rescaler.h"
+#include "../utils/utils.h"
+#include "../dsp/dsp.h"
+#include "../dsp/yuv.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define HALVE(x) (((x) + 1) >> 1)
+#define IS_YUV_CSP(csp, YUV_CSP) (((csp) & WEBP_CSP_UV_MASK) == (YUV_CSP))
+
+static const union {
+ uint32_t argb;
+ uint8_t bytes[4];
+} test_endian = { 0xff000000u };
+#define ALPHA_IS_LAST (test_endian.bytes[3] == 0xff)
+
+//------------------------------------------------------------------------------
+// WebPPicture
+//------------------------------------------------------------------------------
+
+int WebPPictureAlloc(WebPPicture* picture) {
+ if (picture != NULL) {
+ const WebPEncCSP uv_csp = picture->colorspace & WEBP_CSP_UV_MASK;
+ const int has_alpha = picture->colorspace & WEBP_CSP_ALPHA_BIT;
+ const int width = picture->width;
+ const int height = picture->height;
+
+ if (!picture->use_argb) {
+ const int y_stride = width;
+ const int uv_width = HALVE(width);
+ const int uv_height = HALVE(height);
+ const int uv_stride = uv_width;
+ int uv0_stride = 0;
+ int a_width, a_stride;
+ uint64_t y_size, uv_size, uv0_size, a_size, total_size;
+ uint8_t* mem;
+
+ // U/V
+ switch (uv_csp) {
+ case WEBP_YUV420:
+ break;
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ case WEBP_YUV400: // for now, we'll just reset the U/V samples
+ break;
+ case WEBP_YUV422:
+ uv0_stride = uv_width;
+ break;
+ case WEBP_YUV444:
+ uv0_stride = width;
+ break;
+#endif
+ default:
+ return 0;
+ }
+ uv0_size = height * uv0_stride;
+
+ // alpha
+ a_width = has_alpha ? width : 0;
+ a_stride = a_width;
+ y_size = (uint64_t)y_stride * height;
+ uv_size = (uint64_t)uv_stride * uv_height;
+ a_size = (uint64_t)a_stride * height;
+
+ total_size = y_size + a_size + 2 * uv_size + 2 * uv0_size;
+
+ // Security and validation checks
+ if (width <= 0 || height <= 0 || // luma/alpha param error
+ uv_width < 0 || uv_height < 0) { // u/v param error
+ return 0;
+ }
+ // Clear previous buffer and allocate a new one.
+ WebPPictureFree(picture); // erase previous buffer
+ mem = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*mem));
+ if (mem == NULL) return 0;
+
+ // From now on, we're in the clear, we can no longer fail...
+ picture->memory_ = (void*)mem;
+ picture->y_stride = y_stride;
+ picture->uv_stride = uv_stride;
+ picture->a_stride = a_stride;
+ picture->uv0_stride = uv0_stride;
+ // TODO(skal): we could align the y/u/v planes and adjust stride.
+ picture->y = mem;
+ mem += y_size;
+
+ picture->u = mem;
+ mem += uv_size;
+ picture->v = mem;
+ mem += uv_size;
+
+ if (a_size) {
+ picture->a = mem;
+ mem += a_size;
+ }
+ if (uv0_size) {
+ picture->u0 = mem;
+ mem += uv0_size;
+ picture->v0 = mem;
+ mem += uv0_size;
+ }
+ } else {
+ void* memory;
+ const uint64_t argb_size = (uint64_t)width * height;
+ if (width <= 0 || height <= 0) {
+ return 0;
+ }
+ // Clear previous buffer and allocate a new one.
+ WebPPictureFree(picture); // erase previous buffer
+ memory = WebPSafeMalloc(argb_size, sizeof(*picture->argb));
+ if (memory == NULL) return 0;
+
+ // TODO(skal): align plane to cache line?
+ picture->memory_argb_ = memory;
+ picture->argb = (uint32_t*)memory;
+ picture->argb_stride = width;
+ }
+ }
+ return 1;
+}
+
+// Remove reference to the ARGB buffer (doesn't free anything).
+static void PictureResetARGB(WebPPicture* const picture) {
+ picture->memory_argb_ = NULL;
+ picture->argb = NULL;
+ picture->argb_stride = 0;
+}
+
+// Remove reference to the YUVA buffer (doesn't free anything).
+static void PictureResetYUVA(WebPPicture* const picture) {
+ picture->memory_ = NULL;
+ picture->y = picture->u = picture->v = picture->a = NULL;
+ picture->u0 = picture->v0 = NULL;
+ picture->y_stride = picture->uv_stride = 0;
+ picture->a_stride = 0;
+ picture->uv0_stride = 0;
+}
+
+// Grab the 'specs' (writer, *opaque, width, height...) from 'src' and copy them
+// into 'dst'. Mark 'dst' as not owning any memory.
+static void WebPPictureGrabSpecs(const WebPPicture* const src,
+ WebPPicture* const dst) {
+ assert(src != NULL && dst != NULL);
+ *dst = *src;
+ PictureResetYUVA(dst);
+ PictureResetARGB(dst);
+}
+
+// Allocate a new argb buffer, discarding any existing one and preserving
+// the other YUV(A) buffer.
+static int PictureAllocARGB(WebPPicture* const picture) {
+ WebPPicture tmp;
+ free(picture->memory_argb_);
+ PictureResetARGB(picture);
+ picture->use_argb = 1;
+ WebPPictureGrabSpecs(picture, &tmp);
+ if (!WebPPictureAlloc(&tmp)) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
+ }
+ picture->memory_argb_ = tmp.memory_argb_;
+ picture->argb = tmp.argb;
+ picture->argb_stride = tmp.argb_stride;
+ return 1;
+}
+
+// Release memory owned by 'picture' (both YUV and ARGB buffers).
+void WebPPictureFree(WebPPicture* picture) {
+ if (picture != NULL) {
+ free(picture->memory_);
+ free(picture->memory_argb_);
+ PictureResetYUVA(picture);
+ PictureResetARGB(picture);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Picture copying
+
+// Not worth moving to dsp/enc.c (only used here).
+static void CopyPlane(const uint8_t* src, int src_stride,
+ uint8_t* dst, int dst_stride, int width, int height) {
+ while (height-- > 0) {
+ memcpy(dst, src, width);
+ src += src_stride;
+ dst += dst_stride;
+ }
+}
+
+// Adjust top-left corner to chroma sample position.
+static void SnapTopLeftPosition(const WebPPicture* const pic,
+ int* const left, int* const top) {
+ if (!pic->use_argb) {
+ const int is_yuv422 = IS_YUV_CSP(pic->colorspace, WEBP_YUV422);
+ if (IS_YUV_CSP(pic->colorspace, WEBP_YUV420) || is_yuv422) {
+ *left &= ~1;
+ if (!is_yuv422) *top &= ~1;
+ }
+ }
+}
+
+// Adjust top-left corner and verify that the sub-rectangle is valid.
+static int AdjustAndCheckRectangle(const WebPPicture* const pic,
+ int* const left, int* const top,
+ int width, int height) {
+ SnapTopLeftPosition(pic, left, top);
+ if ((*left) < 0 || (*top) < 0) return 0;
+ if (width <= 0 || height <= 0) return 0;
+ if ((*left) + width > pic->width) return 0;
+ if ((*top) + height > pic->height) return 0;
+ return 1;
+}
+
+int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst) {
+ if (src == NULL || dst == NULL) return 0;
+ if (src == dst) return 1;
+
+ WebPPictureGrabSpecs(src, dst);
+ if (!WebPPictureAlloc(dst)) return 0;
+
+ if (!src->use_argb) {
+ CopyPlane(src->y, src->y_stride,
+ dst->y, dst->y_stride, dst->width, dst->height);
+ CopyPlane(src->u, src->uv_stride,
+ dst->u, dst->uv_stride, HALVE(dst->width), HALVE(dst->height));
+ CopyPlane(src->v, src->uv_stride,
+ dst->v, dst->uv_stride, HALVE(dst->width), HALVE(dst->height));
+ if (dst->a != NULL) {
+ CopyPlane(src->a, src->a_stride,
+ dst->a, dst->a_stride, dst->width, dst->height);
+ }
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ if (dst->u0 != NULL) {
+ int uv0_width = src->width;
+ if (IS_YUV_CSP(dst->colorspace, WEBP_YUV422)) {
+ uv0_width = HALVE(uv0_width);
+ }
+ CopyPlane(src->u0, src->uv0_stride,
+ dst->u0, dst->uv0_stride, uv0_width, dst->height);
+ CopyPlane(src->v0, src->uv0_stride,
+ dst->v0, dst->uv0_stride, uv0_width, dst->height);
+ }
+#endif
+ } else {
+ CopyPlane((const uint8_t*)src->argb, 4 * src->argb_stride,
+ (uint8_t*)dst->argb, 4 * dst->argb_stride,
+ 4 * dst->width, dst->height);
+ }
+ return 1;
+}
+
+int WebPPictureIsView(const WebPPicture* picture) {
+ if (picture == NULL) return 0;
+ if (picture->use_argb) {
+ return (picture->memory_argb_ == NULL);
+ }
+ return (picture->memory_ == NULL);
+}
+
+int WebPPictureView(const WebPPicture* src,
+ int left, int top, int width, int height,
+ WebPPicture* dst) {
+ if (src == NULL || dst == NULL) return 0;
+
+ // verify rectangle position.
+ if (!AdjustAndCheckRectangle(src, &left, &top, width, height)) return 0;
+
+ if (src != dst) { // beware of aliasing! We don't want to leak 'memory_'.
+ WebPPictureGrabSpecs(src, dst);
+ }
+ dst->width = width;
+ dst->height = height;
+ if (!src->use_argb) {
+ dst->y = src->y + top * src->y_stride + left;
+ dst->u = src->u + (top >> 1) * src->uv_stride + (left >> 1);
+ dst->v = src->v + (top >> 1) * src->uv_stride + (left >> 1);
+ if (src->a != NULL) {
+ dst->a = src->a + top * src->a_stride + left;
+ }
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ if (src->u0 != NULL) {
+ const int left_pos =
+ IS_YUV_CSP(dst->colorspace, WEBP_YUV422) ? (left >> 1) : left;
+ dst->u0 = src->u0 + top * src->uv0_stride + left_pos;
+ dst->v0 = src->v0 + top * src->uv0_stride + left_pos;
+ }
+#endif
+ } else {
+ dst->argb = src->argb + top * src->argb_stride + left;
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Picture cropping
+
+int WebPPictureCrop(WebPPicture* pic,
+ int left, int top, int width, int height) {
+ WebPPicture tmp;
+
+ if (pic == NULL) return 0;
+ if (!AdjustAndCheckRectangle(pic, &left, &top, width, height)) return 0;
+
+ WebPPictureGrabSpecs(pic, &tmp);
+ tmp.width = width;
+ tmp.height = height;
+ if (!WebPPictureAlloc(&tmp)) return 0;
+
+ if (!pic->use_argb) {
+ const int y_offset = top * pic->y_stride + left;
+ const int uv_offset = (top / 2) * pic->uv_stride + left / 2;
+ CopyPlane(pic->y + y_offset, pic->y_stride,
+ tmp.y, tmp.y_stride, width, height);
+ CopyPlane(pic->u + uv_offset, pic->uv_stride,
+ tmp.u, tmp.uv_stride, HALVE(width), HALVE(height));
+ CopyPlane(pic->v + uv_offset, pic->uv_stride,
+ tmp.v, tmp.uv_stride, HALVE(width), HALVE(height));
+
+ if (tmp.a != NULL) {
+ const int a_offset = top * pic->a_stride + left;
+ CopyPlane(pic->a + a_offset, pic->a_stride,
+ tmp.a, tmp.a_stride, width, height);
+ }
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ if (tmp.u0 != NULL) {
+ int w = width;
+ int left_pos = left;
+ if (IS_YUV_CSP(tmp.colorspace, WEBP_YUV422)) {
+ w = HALVE(w);
+ left_pos = HALVE(left_pos);
+ }
+ CopyPlane(pic->u0 + top * pic->uv0_stride + left_pos, pic->uv0_stride,
+ tmp.u0, tmp.uv0_stride, w, height);
+ CopyPlane(pic->v0 + top * pic->uv0_stride + left_pos, pic->uv0_stride,
+ tmp.v0, tmp.uv0_stride, w, height);
+ }
+#endif
+ } else {
+ const uint8_t* const src =
+ (const uint8_t*)(pic->argb + top * pic->argb_stride + left);
+ CopyPlane(src, pic->argb_stride * 4,
+ (uint8_t*)tmp.argb, tmp.argb_stride * 4,
+ width * 4, height);
+ }
+ WebPPictureFree(pic);
+ *pic = tmp;
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Simple picture rescaler
+
+static void RescalePlane(const uint8_t* src,
+ int src_width, int src_height, int src_stride,
+ uint8_t* dst,
+ int dst_width, int dst_height, int dst_stride,
+ int32_t* const work,
+ int num_channels) {
+ WebPRescaler rescaler;
+ int y = 0;
+ WebPRescalerInit(&rescaler, src_width, src_height,
+ dst, dst_width, dst_height, dst_stride,
+ num_channels,
+ src_width, dst_width,
+ src_height, dst_height,
+ work);
+ memset(work, 0, 2 * dst_width * num_channels * sizeof(*work));
+ while (y < src_height) {
+ y += WebPRescalerImport(&rescaler, src_height - y,
+ src + y * src_stride, src_stride);
+ WebPRescalerExport(&rescaler);
+ }
+}
+
+int WebPPictureRescale(WebPPicture* pic, int width, int height) {
+ WebPPicture tmp;
+ int prev_width, prev_height;
+ int32_t* work;
+
+ if (pic == NULL) return 0;
+ prev_width = pic->width;
+ prev_height = pic->height;
+ // if width is unspecified, scale original proportionally to height ratio.
+ if (width == 0) {
+ width = (prev_width * height + prev_height / 2) / prev_height;
+ }
+ // if height is unspecified, scale original proportionally to width ratio.
+ if (height == 0) {
+ height = (prev_height * width + prev_width / 2) / prev_width;
+ }
+ // Check if the overall dimensions still make sense.
+ if (width <= 0 || height <= 0) return 0;
+
+ WebPPictureGrabSpecs(pic, &tmp);
+ tmp.width = width;
+ tmp.height = height;
+ if (!WebPPictureAlloc(&tmp)) return 0;
+
+ if (!pic->use_argb) {
+ work = (int32_t*)WebPSafeMalloc(2ULL * width, sizeof(*work));
+ if (work == NULL) {
+ WebPPictureFree(&tmp);
+ return 0;
+ }
+
+ RescalePlane(pic->y, prev_width, prev_height, pic->y_stride,
+ tmp.y, width, height, tmp.y_stride, work, 1);
+ RescalePlane(pic->u,
+ HALVE(prev_width), HALVE(prev_height), pic->uv_stride,
+ tmp.u,
+ HALVE(width), HALVE(height), tmp.uv_stride, work, 1);
+ RescalePlane(pic->v,
+ HALVE(prev_width), HALVE(prev_height), pic->uv_stride,
+ tmp.v,
+ HALVE(width), HALVE(height), tmp.uv_stride, work, 1);
+
+ if (tmp.a != NULL) {
+ RescalePlane(pic->a, prev_width, prev_height, pic->a_stride,
+ tmp.a, width, height, tmp.a_stride, work, 1);
+ }
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ if (tmp.u0 != NULL) {
+ const int s = IS_YUV_CSP(tmp.colorspace, WEBP_YUV422) ? 2 : 1;
+ RescalePlane(
+ pic->u0, (prev_width + s / 2) / s, prev_height, pic->uv0_stride,
+ tmp.u0, (width + s / 2) / s, height, tmp.uv0_stride, work, 1);
+ RescalePlane(
+ pic->v0, (prev_width + s / 2) / s, prev_height, pic->uv0_stride,
+ tmp.v0, (width + s / 2) / s, height, tmp.uv0_stride, work, 1);
+ }
+#endif
+ } else {
+ work = (int32_t*)WebPSafeMalloc(2ULL * width * 4, sizeof(*work));
+ if (work == NULL) {
+ WebPPictureFree(&tmp);
+ return 0;
+ }
+
+ RescalePlane((const uint8_t*)pic->argb, prev_width, prev_height,
+ pic->argb_stride * 4,
+ (uint8_t*)tmp.argb, width, height,
+ tmp.argb_stride * 4,
+ work, 4);
+
+ }
+ WebPPictureFree(pic);
+ free(work);
+ *pic = tmp;
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// WebPMemoryWriter: Write-to-memory
+
+void WebPMemoryWriterInit(WebPMemoryWriter* writer) {
+ writer->mem = NULL;
+ writer->size = 0;
+ writer->max_size = 0;
+}
+
+int WebPMemoryWrite(const uint8_t* data, size_t data_size,
+ const WebPPicture* picture) {
+ WebPMemoryWriter* const w = (WebPMemoryWriter*)picture->custom_ptr;
+ uint64_t next_size;
+ if (w == NULL) {
+ return 1;
+ }
+ next_size = (uint64_t)w->size + data_size;
+ if (next_size > w->max_size) {
+ uint8_t* new_mem;
+ uint64_t next_max_size = 2ULL * w->max_size;
+ if (next_max_size < next_size) next_max_size = next_size;
+ if (next_max_size < 8192ULL) next_max_size = 8192ULL;
+ new_mem = (uint8_t*)WebPSafeMalloc(next_max_size, 1);
+ if (new_mem == NULL) {
+ return 0;
+ }
+ if (w->size > 0) {
+ memcpy(new_mem, w->mem, w->size);
+ }
+ free(w->mem);
+ w->mem = new_mem;
+ // down-cast is ok, thanks to WebPSafeMalloc
+ w->max_size = (size_t)next_max_size;
+ }
+ if (data_size > 0) {
+ memcpy(w->mem + w->size, data, data_size);
+ w->size += data_size;
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Detection of non-trivial transparency
+
+// Returns true if alpha[] has non-0xff values.
+static int CheckNonOpaque(const uint8_t* alpha, int width, int height,
+ int x_step, int y_step) {
+ if (alpha == NULL) return 0;
+ while (height-- > 0) {
+ int x;
+ for (x = 0; x < width * x_step; x += x_step) {
+ if (alpha[x] != 0xff) return 1; // TODO(skal): check 4/8 bytes at a time.
+ }
+ alpha += y_step;
+ }
+ return 0;
+}
+
+// Checking for the presence of non-opaque alpha.
+int WebPPictureHasTransparency(const WebPPicture* picture) {
+ if (picture == NULL) return 0;
+ if (!picture->use_argb) {
+ return CheckNonOpaque(picture->a, picture->width, picture->height,
+ 1, picture->a_stride);
+ } else {
+ int x, y;
+ const uint32_t* argb = picture->argb;
+ if (argb == NULL) return 0;
+ for (y = 0; y < picture->height; ++y) {
+ for (x = 0; x < picture->width; ++x) {
+ if (argb[x] < 0xff000000u) return 1; // test any alpha values != 0xff
+ }
+ argb += picture->argb_stride;
+ }
+ }
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+// RGB -> YUV conversion
+
+// TODO: we can do better than simply 2x2 averaging on U/V samples.
+#define SUM4(ptr) ((ptr)[0] + (ptr)[step] + \
+ (ptr)[rgb_stride] + (ptr)[rgb_stride + step])
+#define SUM2H(ptr) (2 * (ptr)[0] + 2 * (ptr)[step])
+#define SUM2V(ptr) (2 * (ptr)[0] + 2 * (ptr)[rgb_stride])
+#define SUM1(ptr) (4 * (ptr)[0])
+#define RGB_TO_UV(x, y, SUM) { \
+ const int src = (2 * (step * (x) + (y) * rgb_stride)); \
+ const int dst = (x) + (y) * picture->uv_stride; \
+ const int r = SUM(r_ptr + src); \
+ const int g = SUM(g_ptr + src); \
+ const int b = SUM(b_ptr + src); \
+ picture->u[dst] = VP8RGBToU(r, g, b); \
+ picture->v[dst] = VP8RGBToV(r, g, b); \
+}
+
+#define RGB_TO_UV0(x_in, x_out, y, SUM) { \
+ const int src = (step * (x_in) + (y) * rgb_stride); \
+ const int dst = (x_out) + (y) * picture->uv0_stride; \
+ const int r = SUM(r_ptr + src); \
+ const int g = SUM(g_ptr + src); \
+ const int b = SUM(b_ptr + src); \
+ picture->u0[dst] = VP8RGBToU(r, g, b); \
+ picture->v0[dst] = VP8RGBToV(r, g, b); \
+}
+
+static void MakeGray(WebPPicture* const picture) {
+ int y;
+ const int uv_width = HALVE(picture->width);
+ const int uv_height = HALVE(picture->height);
+ for (y = 0; y < uv_height; ++y) {
+ memset(picture->u + y * picture->uv_stride, 128, uv_width);
+ memset(picture->v + y * picture->uv_stride, 128, uv_width);
+ }
+}
+
+static int ImportYUVAFromRGBA(const uint8_t* const r_ptr,
+ const uint8_t* const g_ptr,
+ const uint8_t* const b_ptr,
+ const uint8_t* const a_ptr,
+ int step, // bytes per pixel
+ int rgb_stride, // bytes per scanline
+ WebPPicture* const picture) {
+ const WebPEncCSP uv_csp = picture->colorspace & WEBP_CSP_UV_MASK;
+ int x, y;
+ const int width = picture->width;
+ const int height = picture->height;
+ const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride);
+
+ picture->colorspace = uv_csp;
+ picture->use_argb = 0;
+ if (has_alpha) {
+ picture->colorspace |= WEBP_CSP_ALPHA_BIT;
+ }
+ if (!WebPPictureAlloc(picture)) return 0;
+
+ // Import luma plane
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ const int offset = step * x + y * rgb_stride;
+ picture->y[x + y * picture->y_stride] =
+ VP8RGBToY(r_ptr[offset], g_ptr[offset], b_ptr[offset]);
+ }
+ }
+
+ // Downsample U/V plane
+ if (uv_csp != WEBP_YUV400) {
+ for (y = 0; y < (height >> 1); ++y) {
+ for (x = 0; x < (width >> 1); ++x) {
+ RGB_TO_UV(x, y, SUM4);
+ }
+ if (width & 1) {
+ RGB_TO_UV(x, y, SUM2V);
+ }
+ }
+ if (height & 1) {
+ for (x = 0; x < (width >> 1); ++x) {
+ RGB_TO_UV(x, y, SUM2H);
+ }
+ if (width & 1) {
+ RGB_TO_UV(x, y, SUM1);
+ }
+ }
+
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ // Store original U/V samples too
+ if (uv_csp == WEBP_YUV422) {
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < (width >> 1); ++x) {
+ RGB_TO_UV0(2 * x, x, y, SUM2H);
+ }
+ if (width & 1) {
+ RGB_TO_UV0(2 * x, x, y, SUM1);
+ }
+ }
+ } else if (uv_csp == WEBP_YUV444) {
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ RGB_TO_UV0(x, x, y, SUM1);
+ }
+ }
+ }
+#endif
+ } else {
+ MakeGray(picture);
+ }
+
+ if (has_alpha) {
+ assert(step >= 4);
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ picture->a[x + y * picture->a_stride] =
+ a_ptr[step * x + y * rgb_stride];
+ }
+ }
+ }
+ return 1;
+}
+
+static int Import(WebPPicture* const picture,
+ const uint8_t* const rgb, int rgb_stride,
+ int step, int swap_rb, int import_alpha) {
+ const uint8_t* const r_ptr = rgb + (swap_rb ? 2 : 0);
+ const uint8_t* const g_ptr = rgb + 1;
+ const uint8_t* const b_ptr = rgb + (swap_rb ? 0 : 2);
+ const uint8_t* const a_ptr = import_alpha ? rgb + 3 : NULL;
+ const int width = picture->width;
+ const int height = picture->height;
+
+ if (!picture->use_argb) {
+ return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride,
+ picture);
+ }
+ if (import_alpha) {
+ picture->colorspace |= WEBP_CSP_ALPHA_BIT;
+ } else {
+ picture->colorspace &= ~WEBP_CSP_ALPHA_BIT;
+ }
+ if (!WebPPictureAlloc(picture)) return 0;
+
+ if (!import_alpha) {
+ int x, y;
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ const int offset = step * x + y * rgb_stride;
+ const uint32_t argb =
+ 0xff000000u |
+ (r_ptr[offset] << 16) |
+ (g_ptr[offset] << 8) |
+ (b_ptr[offset]);
+ picture->argb[x + y * picture->argb_stride] = argb;
+ }
+ }
+ } else {
+ int x, y;
+ assert(step >= 4);
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ const int offset = step * x + y * rgb_stride;
+ const uint32_t argb = (a_ptr[offset] << 24) |
+ (r_ptr[offset] << 16) |
+ (g_ptr[offset] << 8) |
+ (b_ptr[offset]);
+ picture->argb[x + y * picture->argb_stride] = argb;
+ }
+ }
+ }
+ return 1;
+}
+#undef SUM4
+#undef SUM2V
+#undef SUM2H
+#undef SUM1
+#undef RGB_TO_UV
+
+int WebPPictureImportRGB(WebPPicture* picture,
+ const uint8_t* rgb, int rgb_stride) {
+ return Import(picture, rgb, rgb_stride, 3, 0, 0);
+}
+
+int WebPPictureImportBGR(WebPPicture* picture,
+ const uint8_t* rgb, int rgb_stride) {
+ return Import(picture, rgb, rgb_stride, 3, 1, 0);
+}
+
+int WebPPictureImportRGBA(WebPPicture* picture,
+ const uint8_t* rgba, int rgba_stride) {
+ return Import(picture, rgba, rgba_stride, 4, 0, 1);
+}
+
+int WebPPictureImportBGRA(WebPPicture* picture,
+ const uint8_t* rgba, int rgba_stride) {
+ return Import(picture, rgba, rgba_stride, 4, 1, 1);
+}
+
+int WebPPictureImportRGBX(WebPPicture* picture,
+ const uint8_t* rgba, int rgba_stride) {
+ return Import(picture, rgba, rgba_stride, 4, 0, 0);
+}
+
+int WebPPictureImportBGRX(WebPPicture* picture,
+ const uint8_t* rgba, int rgba_stride) {
+ return Import(picture, rgba, rgba_stride, 4, 1, 0);
+}
+
+//------------------------------------------------------------------------------
+// Automatic YUV <-> ARGB conversions.
+
+int WebPPictureYUVAToARGB(WebPPicture* picture) {
+ if (picture == NULL) return 0;
+ if (picture->memory_ == NULL || picture->y == NULL ||
+ picture->u == NULL || picture->v == NULL) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
+ }
+ if ((picture->colorspace & WEBP_CSP_ALPHA_BIT) && picture->a == NULL) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
+ }
+ if ((picture->colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
+ }
+ // Allocate a new argb buffer (discarding the previous one).
+ if (!PictureAllocARGB(picture)) return 0;
+
+ // Convert
+ {
+ int y;
+ const int width = picture->width;
+ const int height = picture->height;
+ const int argb_stride = 4 * picture->argb_stride;
+ uint8_t* dst = (uint8_t*)picture->argb;
+ const uint8_t *cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y;
+ WebPUpsampleLinePairFunc upsample = WebPGetLinePairConverter(ALPHA_IS_LAST);
+
+ // First row, with replicated top samples.
+ upsample(NULL, cur_y, cur_u, cur_v, cur_u, cur_v, NULL, dst, width);
+ cur_y += picture->y_stride;
+ dst += argb_stride;
+ // Center rows.
+ for (y = 1; y + 1 < height; y += 2) {
+ const uint8_t* const top_u = cur_u;
+ const uint8_t* const top_v = cur_v;
+ cur_u += picture->uv_stride;
+ cur_v += picture->uv_stride;
+ upsample(cur_y, cur_y + picture->y_stride, top_u, top_v, cur_u, cur_v,
+ dst, dst + argb_stride, width);
+ cur_y += 2 * picture->y_stride;
+ dst += 2 * argb_stride;
+ }
+ // Last row (if needed), with replicated bottom samples.
+ if (height > 1 && !(height & 1)) {
+ upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width);
+ }
+ // Insert alpha values if needed, in replacement for the default 0xff ones.
+ if (picture->colorspace & WEBP_CSP_ALPHA_BIT) {
+ for (y = 0; y < height; ++y) {
+ uint32_t* const dst = picture->argb + y * picture->argb_stride;
+ const uint8_t* const src = picture->a + y * picture->a_stride;
+ int x;
+ for (x = 0; x < width; ++x) {
+ dst[x] = (dst[x] & 0x00ffffffu) | (src[x] << 24);
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+int WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) {
+ if (picture == NULL) return 0;
+ if (picture->argb == NULL) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
+ } else {
+ const uint8_t* const argb = (const uint8_t*)picture->argb;
+ const uint8_t* const r = ALPHA_IS_LAST ? argb + 2 : argb + 1;
+ const uint8_t* const g = ALPHA_IS_LAST ? argb + 1 : argb + 2;
+ const uint8_t* const b = ALPHA_IS_LAST ? argb + 0 : argb + 3;
+ const uint8_t* const a = ALPHA_IS_LAST ? argb + 3 : argb + 0;
+ // We work on a tmp copy of 'picture', because ImportYUVAFromRGBA()
+ // would be calling WebPPictureFree(picture) otherwise.
+ WebPPicture tmp = *picture;
+ PictureResetARGB(&tmp); // reset ARGB buffer so that it's not free()'d.
+ tmp.use_argb = 0;
+ tmp.colorspace = colorspace & WEBP_CSP_UV_MASK;
+ if (!ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride, &tmp)) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
+ }
+ // Copy back the YUV specs into 'picture'.
+ tmp.argb = picture->argb;
+ tmp.argb_stride = picture->argb_stride;
+ tmp.memory_argb_ = picture->memory_argb_;
+ *picture = tmp;
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Helper: clean up fully transparent area to help compressibility.
+
+#define SIZE 8
+#define SIZE2 (SIZE / 2)
+static int is_transparent_area(const uint8_t* ptr, int stride, int size) {
+ int y, x;
+ for (y = 0; y < size; ++y) {
+ for (x = 0; x < size; ++x) {
+ if (ptr[x]) {
+ return 0;
+ }
+ }
+ ptr += stride;
+ }
+ return 1;
+}
+
+static WEBP_INLINE void flatten(uint8_t* ptr, int v, int stride, int size) {
+ int y;
+ for (y = 0; y < size; ++y) {
+ memset(ptr, v, size);
+ ptr += stride;
+ }
+}
+
+void WebPCleanupTransparentArea(WebPPicture* pic) {
+ int x, y, w, h;
+ const uint8_t* a_ptr;
+ int values[3] = { 0 };
+
+ if (pic == NULL) return;
+
+ a_ptr = pic->a;
+ if (a_ptr == NULL) return; // nothing to do
+
+ w = pic->width / SIZE;
+ h = pic->height / SIZE;
+ for (y = 0; y < h; ++y) {
+ int need_reset = 1;
+ for (x = 0; x < w; ++x) {
+ const int off_a = (y * pic->a_stride + x) * SIZE;
+ const int off_y = (y * pic->y_stride + x) * SIZE;
+ const int off_uv = (y * pic->uv_stride + x) * SIZE2;
+ if (is_transparent_area(a_ptr + off_a, pic->a_stride, SIZE)) {
+ if (need_reset) {
+ values[0] = pic->y[off_y];
+ values[1] = pic->u[off_uv];
+ values[2] = pic->v[off_uv];
+ need_reset = 0;
+ }
+ flatten(pic->y + off_y, values[0], pic->y_stride, SIZE);
+ flatten(pic->u + off_uv, values[1], pic->uv_stride, SIZE2);
+ flatten(pic->v + off_uv, values[2], pic->uv_stride, SIZE2);
+ } else {
+ need_reset = 1;
+ }
+ }
+ // ignore the left-overs on right/bottom
+ }
+}
+
+#undef SIZE
+#undef SIZE2
+
+
+//------------------------------------------------------------------------------
+// Distortion
+
+// Max value returned in case of exact similarity.
+static const double kMinDistortion_dB = 99.;
+
+int WebPPictureDistortion(const WebPPicture* pic1, const WebPPicture* pic2,
+ int type, float result[5]) {
+ int c;
+ DistoStats stats[5];
+ int has_alpha;
+
+ if (pic1 == NULL || pic2 == NULL ||
+ pic1->width != pic2->width || pic1->height != pic2->height ||
+ pic1->y == NULL || pic2->y == NULL ||
+ pic1->u == NULL || pic2->u == NULL ||
+ pic1->v == NULL || pic2->v == NULL ||
+ result == NULL) {
+ return 0;
+ }
+ // TODO(skal): provide distortion for ARGB too.
+ if (pic1->use_argb == 1 || pic1->use_argb != pic2->use_argb) {
+ return 0;
+ }
+
+ has_alpha = !!(pic1->colorspace & WEBP_CSP_ALPHA_BIT);
+ if (has_alpha != !!(pic2->colorspace & WEBP_CSP_ALPHA_BIT) ||
+ (has_alpha && (pic1->a == NULL || pic2->a == NULL))) {
+ return 0;
+ }
+
+ memset(stats, 0, sizeof(stats));
+ VP8SSIMAccumulatePlane(pic1->y, pic1->y_stride,
+ pic2->y, pic2->y_stride,
+ pic1->width, pic1->height, &stats[0]);
+ VP8SSIMAccumulatePlane(pic1->u, pic1->uv_stride,
+ pic2->u, pic2->uv_stride,
+ (pic1->width + 1) >> 1, (pic1->height + 1) >> 1,
+ &stats[1]);
+ VP8SSIMAccumulatePlane(pic1->v, pic1->uv_stride,
+ pic2->v, pic2->uv_stride,
+ (pic1->width + 1) >> 1, (pic1->height + 1) >> 1,
+ &stats[2]);
+ if (has_alpha) {
+ VP8SSIMAccumulatePlane(pic1->a, pic1->a_stride,
+ pic2->a, pic2->a_stride,
+ pic1->width, pic1->height, &stats[3]);
+ }
+ for (c = 0; c <= 4; ++c) {
+ if (type == 1) {
+ const double v = VP8SSIMGet(&stats[c]);
+ result[c] = (float)((v < 1.) ? -10.0 * log10(1. - v)
+ : kMinDistortion_dB);
+ } else {
+ const double v = VP8SSIMGetSquaredError(&stats[c]);
+ result[c] = (float)((v > 0.) ? -4.3429448 * log(v / (255 * 255.))
+ : kMinDistortion_dB);
+ }
+ // Accumulate forward
+ if (c < 4) VP8SSIMAddStats(&stats[c], &stats[4]);
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Simplest high-level calls:
+
+typedef int (*Importer)(WebPPicture* const, const uint8_t* const, int);
+
+static size_t Encode(const uint8_t* rgba, int width, int height, int stride,
+ Importer import, float quality_factor, int lossless,
+ uint8_t** output) {
+ WebPPicture pic;
+ WebPConfig config;
+ WebPMemoryWriter wrt;
+ int ok;
+
+ if (!WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, quality_factor) ||
+ !WebPPictureInit(&pic)) {
+ return 0; // shouldn't happen, except if system installation is broken
+ }
+
+ config.lossless = !!lossless;
+ pic.use_argb = !!lossless;
+ pic.width = width;
+ pic.height = height;
+ pic.writer = WebPMemoryWrite;
+ pic.custom_ptr = &wrt;
+ WebPMemoryWriterInit(&wrt);
+
+ ok = import(&pic, rgba, stride) && WebPEncode(&config, &pic);
+ WebPPictureFree(&pic);
+ if (!ok) {
+ free(wrt.mem);
+ *output = NULL;
+ return 0;
+ }
+ *output = wrt.mem;
+ return wrt.size;
+}
+
+#define ENCODE_FUNC(NAME, IMPORTER) \
+size_t NAME(const uint8_t* in, int w, int h, int bps, float q, \
+ uint8_t** out) { \
+ return Encode(in, w, h, bps, IMPORTER, q, 0, out); \
+}
+
+ENCODE_FUNC(WebPEncodeRGB, WebPPictureImportRGB);
+ENCODE_FUNC(WebPEncodeBGR, WebPPictureImportBGR);
+ENCODE_FUNC(WebPEncodeRGBA, WebPPictureImportRGBA);
+ENCODE_FUNC(WebPEncodeBGRA, WebPPictureImportBGRA);
+
+#undef ENCODE_FUNC
+
+#define LOSSLESS_DEFAULT_QUALITY 70.
+#define LOSSLESS_ENCODE_FUNC(NAME, IMPORTER) \
+size_t NAME(const uint8_t* in, int w, int h, int bps, uint8_t** out) { \
+ return Encode(in, w, h, bps, IMPORTER, LOSSLESS_DEFAULT_QUALITY, 1, out); \
+}
+
+LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGB, WebPPictureImportRGB);
+LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGR, WebPPictureImportBGR);
+LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGBA, WebPPictureImportRGBA);
+LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGRA, WebPPictureImportBGRA);
+
+#undef LOSSLESS_ENCODE_FUNC
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/enc/quant.c b/drivers/webpold/enc/quant.c
new file mode 100644
index 0000000000..ea153849c8
--- /dev/null
+++ b/drivers/webpold/enc/quant.c
@@ -0,0 +1,930 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Quantization
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <math.h>
+
+#include "./vp8enci.h"
+#include "./cost.h"
+
+#define DO_TRELLIS_I4 1
+#define DO_TRELLIS_I16 1 // not a huge gain, but ok at low bitrate.
+#define DO_TRELLIS_UV 0 // disable trellis for UV. Risky. Not worth.
+#define USE_TDISTO 1
+
+#define MID_ALPHA 64 // neutral value for susceptibility
+#define MIN_ALPHA 30 // lowest usable value for susceptibility
+#define MAX_ALPHA 100 // higher meaninful value for susceptibility
+
+#define SNS_TO_DQ 0.9 // Scaling constant between the sns value and the QP
+ // power-law modulation. Must be strictly less than 1.
+
+#define MULT_8B(a, b) (((a) * (b) + 128) >> 8)
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+
+static WEBP_INLINE int clip(int v, int m, int M) {
+ return v < m ? m : v > M ? M : v;
+}
+
+static const uint8_t kZigzag[16] = {
+ 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
+};
+
+static const uint8_t kDcTable[128] = {
+ 4, 5, 6, 7, 8, 9, 10, 10,
+ 11, 12, 13, 14, 15, 16, 17, 17,
+ 18, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 25, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89,
+ 91, 93, 95, 96, 98, 100, 101, 102,
+ 104, 106, 108, 110, 112, 114, 116, 118,
+ 122, 124, 126, 128, 130, 132, 134, 136,
+ 138, 140, 143, 145, 148, 151, 154, 157
+};
+
+static const uint16_t kAcTable[128] = {
+ 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 60,
+ 62, 64, 66, 68, 70, 72, 74, 76,
+ 78, 80, 82, 84, 86, 88, 90, 92,
+ 94, 96, 98, 100, 102, 104, 106, 108,
+ 110, 112, 114, 116, 119, 122, 125, 128,
+ 131, 134, 137, 140, 143, 146, 149, 152,
+ 155, 158, 161, 164, 167, 170, 173, 177,
+ 181, 185, 189, 193, 197, 201, 205, 209,
+ 213, 217, 221, 225, 229, 234, 239, 245,
+ 249, 254, 259, 264, 269, 274, 279, 284
+};
+
+static const uint16_t kAcTable2[128] = {
+ 8, 8, 9, 10, 12, 13, 15, 17,
+ 18, 20, 21, 23, 24, 26, 27, 29,
+ 31, 32, 34, 35, 37, 38, 40, 41,
+ 43, 44, 46, 48, 49, 51, 52, 54,
+ 55, 57, 58, 60, 62, 63, 65, 66,
+ 68, 69, 71, 72, 74, 75, 77, 79,
+ 80, 82, 83, 85, 86, 88, 89, 93,
+ 96, 99, 102, 105, 108, 111, 114, 117,
+ 120, 124, 127, 130, 133, 136, 139, 142,
+ 145, 148, 151, 155, 158, 161, 164, 167,
+ 170, 173, 176, 179, 184, 189, 193, 198,
+ 203, 207, 212, 217, 221, 226, 230, 235,
+ 240, 244, 249, 254, 258, 263, 268, 274,
+ 280, 286, 292, 299, 305, 311, 317, 323,
+ 330, 336, 342, 348, 354, 362, 370, 379,
+ 385, 393, 401, 409, 416, 424, 432, 440
+};
+
+static const uint16_t kCoeffThresh[16] = {
+ 0, 10, 20, 30,
+ 10, 20, 30, 30,
+ 20, 30, 30, 30,
+ 30, 30, 30, 30
+};
+
+// TODO(skal): tune more. Coeff thresholding?
+static const uint8_t kBiasMatrices[3][16] = { // [3] = [luma-ac,luma-dc,chroma]
+ { 96, 96, 96, 96,
+ 96, 96, 96, 96,
+ 96, 96, 96, 96,
+ 96, 96, 96, 96 },
+ { 96, 96, 96, 96,
+ 96, 96, 96, 96,
+ 96, 96, 96, 96,
+ 96, 96, 96, 96 },
+ { 96, 96, 96, 96,
+ 96, 96, 96, 96,
+ 96, 96, 96, 96,
+ 96, 96, 96, 96 }
+};
+
+// Sharpening by (slightly) raising the hi-frequency coeffs (only for trellis).
+// Hack-ish but helpful for mid-bitrate range. Use with care.
+static const uint8_t kFreqSharpening[16] = {
+ 0, 30, 60, 90,
+ 30, 60, 90, 90,
+ 60, 90, 90, 90,
+ 90, 90, 90, 90
+};
+
+//------------------------------------------------------------------------------
+// Initialize quantization parameters in VP8Matrix
+
+// Returns the average quantizer
+static int ExpandMatrix(VP8Matrix* const m, int type) {
+ int i;
+ int sum = 0;
+ for (i = 2; i < 16; ++i) {
+ m->q_[i] = m->q_[1];
+ }
+ for (i = 0; i < 16; ++i) {
+ const int j = kZigzag[i];
+ const int bias = kBiasMatrices[type][j];
+ m->iq_[j] = (1 << QFIX) / m->q_[j];
+ m->bias_[j] = BIAS(bias);
+ // TODO(skal): tune kCoeffThresh[]
+ m->zthresh_[j] = ((256 /*+ kCoeffThresh[j]*/ - bias) * m->q_[j] + 127) >> 8;
+ m->sharpen_[j] = (kFreqSharpening[j] * m->q_[j]) >> 11;
+ sum += m->q_[j];
+ }
+ return (sum + 8) >> 4;
+}
+
+static void SetupMatrices(VP8Encoder* enc) {
+ int i;
+ const int tlambda_scale =
+ (enc->method_ >= 4) ? enc->config_->sns_strength
+ : 0;
+ const int num_segments = enc->segment_hdr_.num_segments_;
+ for (i = 0; i < num_segments; ++i) {
+ VP8SegmentInfo* const m = &enc->dqm_[i];
+ const int q = m->quant_;
+ int q4, q16, quv;
+ m->y1_.q_[0] = kDcTable[clip(q + enc->dq_y1_dc_, 0, 127)];
+ m->y1_.q_[1] = kAcTable[clip(q, 0, 127)];
+
+ m->y2_.q_[0] = kDcTable[ clip(q + enc->dq_y2_dc_, 0, 127)] * 2;
+ m->y2_.q_[1] = kAcTable2[clip(q + enc->dq_y2_ac_, 0, 127)];
+
+ m->uv_.q_[0] = kDcTable[clip(q + enc->dq_uv_dc_, 0, 117)];
+ m->uv_.q_[1] = kAcTable[clip(q + enc->dq_uv_ac_, 0, 127)];
+
+ q4 = ExpandMatrix(&m->y1_, 0);
+ q16 = ExpandMatrix(&m->y2_, 1);
+ quv = ExpandMatrix(&m->uv_, 2);
+
+ // TODO: Switch to kLambda*[] tables?
+ {
+ m->lambda_i4_ = (3 * q4 * q4) >> 7;
+ m->lambda_i16_ = (3 * q16 * q16);
+ m->lambda_uv_ = (3 * quv * quv) >> 6;
+ m->lambda_mode_ = (1 * q4 * q4) >> 7;
+ m->lambda_trellis_i4_ = (7 * q4 * q4) >> 3;
+ m->lambda_trellis_i16_ = (q16 * q16) >> 2;
+ m->lambda_trellis_uv_ = (quv *quv) << 1;
+ m->tlambda_ = (tlambda_scale * q4) >> 5;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// Initialize filtering parameters
+
+// Very small filter-strength values have close to no visual effect. So we can
+// save a little decoding-CPU by turning filtering off for these.
+#define FSTRENGTH_CUTOFF 3
+
+static void SetupFilterStrength(VP8Encoder* const enc) {
+ int i;
+ const int level0 = enc->config_->filter_strength;
+ for (i = 0; i < NUM_MB_SEGMENTS; ++i) {
+ // Segments with lower quantizer will be less filtered. TODO: tune (wrt SNS)
+ const int level = level0 * 256 * enc->dqm_[i].quant_ / 128;
+ const int f = level / (256 + enc->dqm_[i].beta_);
+ enc->dqm_[i].fstrength_ = (f < FSTRENGTH_CUTOFF) ? 0 : (f > 63) ? 63 : f;
+ }
+ // We record the initial strength (mainly for the case of 1-segment only).
+ enc->filter_hdr_.level_ = enc->dqm_[0].fstrength_;
+ enc->filter_hdr_.simple_ = (enc->config_->filter_type == 0);
+ enc->filter_hdr_.sharpness_ = enc->config_->filter_sharpness;
+}
+
+//------------------------------------------------------------------------------
+
+// Note: if you change the values below, remember that the max range
+// allowed by the syntax for DQ_UV is [-16,16].
+#define MAX_DQ_UV (6)
+#define MIN_DQ_UV (-4)
+
+// We want to emulate jpeg-like behaviour where the expected "good" quality
+// is around q=75. Internally, our "good" middle is around c=50. So we
+// map accordingly using linear piece-wise function
+static double QualityToCompression(double q) {
+ const double c = q / 100.;
+ return (c < 0.75) ? c * (2. / 3.) : 2. * c - 1.;
+}
+
+void VP8SetSegmentParams(VP8Encoder* const enc, float quality) {
+ int i;
+ int dq_uv_ac, dq_uv_dc;
+ const int num_segments = enc->config_->segments;
+ const double amp = SNS_TO_DQ * enc->config_->sns_strength / 100. / 128.;
+ const double c_base = QualityToCompression(quality);
+ for (i = 0; i < num_segments; ++i) {
+ // The file size roughly scales as pow(quantizer, 3.). Actually, the
+ // exponent is somewhere between 2.8 and 3.2, but we're mostly interested
+ // in the mid-quant range. So we scale the compressibility inversely to
+ // this power-law: quant ~= compression ^ 1/3. This law holds well for
+ // low quant. Finer modelling for high-quant would make use of kAcTable[]
+ // more explicitely.
+ // Additionally, we modulate the base exponent 1/3 to accommodate for the
+ // quantization susceptibility and allow denser segments to be quantized
+ // more.
+ const double expn = (1. - amp * enc->dqm_[i].alpha_) / 3.;
+ const double c = pow(c_base, expn);
+ const int q = (int)(127. * (1. - c));
+ assert(expn > 0.);
+ enc->dqm_[i].quant_ = clip(q, 0, 127);
+ }
+
+ // purely indicative in the bitstream (except for the 1-segment case)
+ enc->base_quant_ = enc->dqm_[0].quant_;
+
+ // fill-in values for the unused segments (required by the syntax)
+ for (i = num_segments; i < NUM_MB_SEGMENTS; ++i) {
+ enc->dqm_[i].quant_ = enc->base_quant_;
+ }
+
+ // uv_alpha_ is normally spread around ~60. The useful range is
+ // typically ~30 (quite bad) to ~100 (ok to decimate UV more).
+ // We map it to the safe maximal range of MAX/MIN_DQ_UV for dq_uv.
+ dq_uv_ac = (enc->uv_alpha_ - MID_ALPHA) * (MAX_DQ_UV - MIN_DQ_UV)
+ / (MAX_ALPHA - MIN_ALPHA);
+ // we rescale by the user-defined strength of adaptation
+ dq_uv_ac = dq_uv_ac * enc->config_->sns_strength / 100;
+ // and make it safe.
+ dq_uv_ac = clip(dq_uv_ac, MIN_DQ_UV, MAX_DQ_UV);
+ // We also boost the dc-uv-quant a little, based on sns-strength, since
+ // U/V channels are quite more reactive to high quants (flat DC-blocks
+ // tend to appear, and are displeasant).
+ dq_uv_dc = -4 * enc->config_->sns_strength / 100;
+ dq_uv_dc = clip(dq_uv_dc, -15, 15); // 4bit-signed max allowed
+
+ enc->dq_y1_dc_ = 0; // TODO(skal): dq-lum
+ enc->dq_y2_dc_ = 0;
+ enc->dq_y2_ac_ = 0;
+ enc->dq_uv_dc_ = dq_uv_dc;
+ enc->dq_uv_ac_ = dq_uv_ac;
+
+ SetupMatrices(enc);
+
+ SetupFilterStrength(enc); // initialize segments' filtering, eventually
+}
+
+//------------------------------------------------------------------------------
+// Form the predictions in cache
+
+// Must be ordered using {DC_PRED, TM_PRED, V_PRED, H_PRED} as index
+const int VP8I16ModeOffsets[4] = { I16DC16, I16TM16, I16VE16, I16HE16 };
+const int VP8UVModeOffsets[4] = { C8DC8, C8TM8, C8VE8, C8HE8 };
+
+// Must be indexed using {B_DC_PRED -> B_HU_PRED} as index
+const int VP8I4ModeOffsets[NUM_BMODES] = {
+ I4DC4, I4TM4, I4VE4, I4HE4, I4RD4, I4VR4, I4LD4, I4VL4, I4HD4, I4HU4
+};
+
+void VP8MakeLuma16Preds(const VP8EncIterator* const it) {
+ const VP8Encoder* const enc = it->enc_;
+ const uint8_t* const left = it->x_ ? enc->y_left_ : NULL;
+ const uint8_t* const top = it->y_ ? enc->y_top_ + it->x_ * 16 : NULL;
+ VP8EncPredLuma16(it->yuv_p_, left, top);
+}
+
+void VP8MakeChroma8Preds(const VP8EncIterator* const it) {
+ const VP8Encoder* const enc = it->enc_;
+ const uint8_t* const left = it->x_ ? enc->u_left_ : NULL;
+ const uint8_t* const top = it->y_ ? enc->uv_top_ + it->x_ * 16 : NULL;
+ VP8EncPredChroma8(it->yuv_p_, left, top);
+}
+
+void VP8MakeIntra4Preds(const VP8EncIterator* const it) {
+ VP8EncPredLuma4(it->yuv_p_, it->i4_top_);
+}
+
+//------------------------------------------------------------------------------
+// Quantize
+
+// Layout:
+// +----+
+// |YYYY| 0
+// |YYYY| 4
+// |YYYY| 8
+// |YYYY| 12
+// +----+
+// |UUVV| 16
+// |UUVV| 20
+// +----+
+
+const int VP8Scan[16 + 4 + 4] = {
+ // Luma
+ 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS,
+ 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS,
+ 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS,
+ 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS,
+
+ 0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U
+ 8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V
+};
+
+//------------------------------------------------------------------------------
+// Distortion measurement
+
+static const uint16_t kWeightY[16] = {
+ 38, 32, 20, 9, 32, 28, 17, 7, 20, 17, 10, 4, 9, 7, 4, 2
+};
+
+static const uint16_t kWeightTrellis[16] = {
+#if USE_TDISTO == 0
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
+#else
+ 30, 27, 19, 11,
+ 27, 24, 17, 10,
+ 19, 17, 12, 8,
+ 11, 10, 8, 6
+#endif
+};
+
+// Init/Copy the common fields in score.
+static void InitScore(VP8ModeScore* const rd) {
+ rd->D = 0;
+ rd->SD = 0;
+ rd->R = 0;
+ rd->nz = 0;
+ rd->score = MAX_COST;
+}
+
+static void CopyScore(VP8ModeScore* const dst, const VP8ModeScore* const src) {
+ dst->D = src->D;
+ dst->SD = src->SD;
+ dst->R = src->R;
+ dst->nz = src->nz; // note that nz is not accumulated, but just copied.
+ dst->score = src->score;
+}
+
+static void AddScore(VP8ModeScore* const dst, const VP8ModeScore* const src) {
+ dst->D += src->D;
+ dst->SD += src->SD;
+ dst->R += src->R;
+ dst->nz |= src->nz; // here, new nz bits are accumulated.
+ dst->score += src->score;
+}
+
+//------------------------------------------------------------------------------
+// Performs trellis-optimized quantization.
+
+// Trellis
+
+typedef struct {
+ int prev; // best previous
+ int level; // level
+ int sign; // sign of coeff_i
+ score_t cost; // bit cost
+ score_t error; // distortion = sum of (|coeff_i| - level_i * Q_i)^2
+ int ctx; // context (only depends on 'level'. Could be spared.)
+} Node;
+
+// If a coefficient was quantized to a value Q (using a neutral bias),
+// we test all alternate possibilities between [Q-MIN_DELTA, Q+MAX_DELTA]
+// We don't test negative values though.
+#define MIN_DELTA 0 // how much lower level to try
+#define MAX_DELTA 1 // how much higher
+#define NUM_NODES (MIN_DELTA + 1 + MAX_DELTA)
+#define NODE(n, l) (nodes[(n) + 1][(l) + MIN_DELTA])
+
+static WEBP_INLINE void SetRDScore(int lambda, VP8ModeScore* const rd) {
+ // TODO: incorporate the "* 256" in the tables?
+ rd->score = rd->R * lambda + 256 * (rd->D + rd->SD);
+}
+
+static WEBP_INLINE score_t RDScoreTrellis(int lambda, score_t rate,
+ score_t distortion) {
+ return rate * lambda + 256 * distortion;
+}
+
+static int TrellisQuantizeBlock(const VP8EncIterator* const it,
+ int16_t in[16], int16_t out[16],
+ int ctx0, int coeff_type,
+ const VP8Matrix* const mtx,
+ int lambda) {
+ ProbaArray* const last_costs = it->enc_->proba_.coeffs_[coeff_type];
+ CostArray* const costs = it->enc_->proba_.level_cost_[coeff_type];
+ const int first = (coeff_type == 0) ? 1 : 0;
+ Node nodes[17][NUM_NODES];
+ int best_path[3] = {-1, -1, -1}; // store best-last/best-level/best-previous
+ score_t best_score;
+ int best_node;
+ int last = first - 1;
+ int n, m, p, nz;
+
+ {
+ score_t cost;
+ score_t max_error;
+ const int thresh = mtx->q_[1] * mtx->q_[1] / 4;
+ const int last_proba = last_costs[VP8EncBands[first]][ctx0][0];
+
+ // compute maximal distortion.
+ max_error = 0;
+ for (n = first; n < 16; ++n) {
+ const int j = kZigzag[n];
+ const int err = in[j] * in[j];
+ max_error += kWeightTrellis[j] * err;
+ if (err > thresh) last = n;
+ }
+ // we don't need to go inspect up to n = 16 coeffs. We can just go up
+ // to last + 1 (inclusive) without losing much.
+ if (last < 15) ++last;
+
+ // compute 'skip' score. This is the max score one can do.
+ cost = VP8BitCost(0, last_proba);
+ best_score = RDScoreTrellis(lambda, cost, max_error);
+
+ // initialize source node.
+ n = first - 1;
+ for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) {
+ NODE(n, m).cost = 0;
+ NODE(n, m).error = max_error;
+ NODE(n, m).ctx = ctx0;
+ }
+ }
+
+ // traverse trellis.
+ for (n = first; n <= last; ++n) {
+ const int j = kZigzag[n];
+ const int Q = mtx->q_[j];
+ const int iQ = mtx->iq_[j];
+ const int B = BIAS(0x00); // neutral bias
+ // note: it's important to take sign of the _original_ coeff,
+ // so we don't have to consider level < 0 afterward.
+ const int sign = (in[j] < 0);
+ int coeff0 = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
+ int level0;
+ if (coeff0 > 2047) coeff0 = 2047;
+
+ level0 = QUANTDIV(coeff0, iQ, B);
+ // test all alternate level values around level0.
+ for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) {
+ Node* const cur = &NODE(n, m);
+ int delta_error, new_error;
+ score_t cur_score = MAX_COST;
+ int level = level0 + m;
+ int last_proba;
+
+ cur->sign = sign;
+ cur->level = level;
+ cur->ctx = (level == 0) ? 0 : (level == 1) ? 1 : 2;
+ if (level >= 2048 || level < 0) { // node is dead?
+ cur->cost = MAX_COST;
+ continue;
+ }
+ last_proba = last_costs[VP8EncBands[n + 1]][cur->ctx][0];
+
+ // Compute delta_error = how much coding this level will
+ // subtract as distortion to max_error
+ new_error = coeff0 - level * Q;
+ delta_error =
+ kWeightTrellis[j] * (coeff0 * coeff0 - new_error * new_error);
+
+ // Inspect all possible non-dead predecessors. Retain only the best one.
+ for (p = -MIN_DELTA; p <= MAX_DELTA; ++p) {
+ const Node* const prev = &NODE(n - 1, p);
+ const int prev_ctx = prev->ctx;
+ const uint16_t* const tcost = costs[VP8EncBands[n]][prev_ctx];
+ const score_t total_error = prev->error - delta_error;
+ score_t cost, base_cost, score;
+
+ if (prev->cost >= MAX_COST) { // dead node?
+ continue;
+ }
+
+ // Base cost of both terminal/non-terminal
+ base_cost = prev->cost + VP8LevelCost(tcost, level);
+
+ // Examine node assuming it's a non-terminal one.
+ cost = base_cost;
+ if (level && n < 15) {
+ cost += VP8BitCost(1, last_proba);
+ }
+ score = RDScoreTrellis(lambda, cost, total_error);
+ if (score < cur_score) {
+ cur_score = score;
+ cur->cost = cost;
+ cur->error = total_error;
+ cur->prev = p;
+ }
+
+ // Now, record best terminal node (and thus best entry in the graph).
+ if (level) {
+ cost = base_cost;
+ if (n < 15) cost += VP8BitCost(0, last_proba);
+ score = RDScoreTrellis(lambda, cost, total_error);
+ if (score < best_score) {
+ best_score = score;
+ best_path[0] = n; // best eob position
+ best_path[1] = m; // best level
+ best_path[2] = p; // best predecessor
+ }
+ }
+ }
+ }
+ }
+
+ // Fresh start
+ memset(in + first, 0, (16 - first) * sizeof(*in));
+ memset(out + first, 0, (16 - first) * sizeof(*out));
+ if (best_path[0] == -1) {
+ return 0; // skip!
+ }
+
+ // Unwind the best path.
+ // Note: best-prev on terminal node is not necessarily equal to the
+ // best_prev for non-terminal. So we patch best_path[2] in.
+ n = best_path[0];
+ best_node = best_path[1];
+ NODE(n, best_node).prev = best_path[2]; // force best-prev for terminal
+ nz = 0;
+
+ for (; n >= first; --n) {
+ const Node* const node = &NODE(n, best_node);
+ const int j = kZigzag[n];
+ out[n] = node->sign ? -node->level : node->level;
+ nz |= (node->level != 0);
+ in[j] = out[n] * mtx->q_[j];
+ best_node = node->prev;
+ }
+ return nz;
+}
+
+#undef NODE
+
+//------------------------------------------------------------------------------
+// Performs: difference, transform, quantize, back-transform, add
+// all at once. Output is the reconstructed block in *yuv_out, and the
+// quantized levels in *levels.
+
+static int ReconstructIntra16(VP8EncIterator* const it,
+ VP8ModeScore* const rd,
+ uint8_t* const yuv_out,
+ int mode) {
+ const VP8Encoder* const enc = it->enc_;
+ const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode];
+ const uint8_t* const src = it->yuv_in_ + Y_OFF;
+ const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
+ int nz = 0;
+ int n;
+ int16_t tmp[16][16], dc_tmp[16];
+
+ for (n = 0; n < 16; ++n) {
+ VP8FTransform(src + VP8Scan[n], ref + VP8Scan[n], tmp[n]);
+ }
+ VP8FTransformWHT(tmp[0], dc_tmp);
+ nz |= VP8EncQuantizeBlock(dc_tmp, rd->y_dc_levels, 0, &dqm->y2_) << 24;
+
+ if (DO_TRELLIS_I16 && it->do_trellis_) {
+ int x, y;
+ VP8IteratorNzToBytes(it);
+ for (y = 0, n = 0; y < 4; ++y) {
+ for (x = 0; x < 4; ++x, ++n) {
+ const int ctx = it->top_nz_[x] + it->left_nz_[y];
+ const int non_zero =
+ TrellisQuantizeBlock(it, tmp[n], rd->y_ac_levels[n], ctx, 0,
+ &dqm->y1_, dqm->lambda_trellis_i16_);
+ it->top_nz_[x] = it->left_nz_[y] = non_zero;
+ nz |= non_zero << n;
+ }
+ }
+ } else {
+ for (n = 0; n < 16; ++n) {
+ nz |= VP8EncQuantizeBlock(tmp[n], rd->y_ac_levels[n], 1, &dqm->y1_) << n;
+ }
+ }
+
+ // Transform back
+ VP8ITransformWHT(dc_tmp, tmp[0]);
+ for (n = 0; n < 16; n += 2) {
+ VP8ITransform(ref + VP8Scan[n], tmp[n], yuv_out + VP8Scan[n], 1);
+ }
+
+ return nz;
+}
+
+static int ReconstructIntra4(VP8EncIterator* const it,
+ int16_t levels[16],
+ const uint8_t* const src,
+ uint8_t* const yuv_out,
+ int mode) {
+ const VP8Encoder* const enc = it->enc_;
+ const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode];
+ const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
+ int nz = 0;
+ int16_t tmp[16];
+
+ VP8FTransform(src, ref, tmp);
+ if (DO_TRELLIS_I4 && it->do_trellis_) {
+ const int x = it->i4_ & 3, y = it->i4_ >> 2;
+ const int ctx = it->top_nz_[x] + it->left_nz_[y];
+ nz = TrellisQuantizeBlock(it, tmp, levels, ctx, 3, &dqm->y1_,
+ dqm->lambda_trellis_i4_);
+ } else {
+ nz = VP8EncQuantizeBlock(tmp, levels, 0, &dqm->y1_);
+ }
+ VP8ITransform(ref, tmp, yuv_out, 0);
+ return nz;
+}
+
+static int ReconstructUV(VP8EncIterator* const it, VP8ModeScore* const rd,
+ uint8_t* const yuv_out, int mode) {
+ const VP8Encoder* const enc = it->enc_;
+ const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode];
+ const uint8_t* const src = it->yuv_in_ + U_OFF;
+ const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
+ int nz = 0;
+ int n;
+ int16_t tmp[8][16];
+
+ for (n = 0; n < 8; ++n) {
+ VP8FTransform(src + VP8Scan[16 + n], ref + VP8Scan[16 + n], tmp[n]);
+ }
+ if (DO_TRELLIS_UV && it->do_trellis_) {
+ int ch, x, y;
+ for (ch = 0, n = 0; ch <= 2; ch += 2) {
+ for (y = 0; y < 2; ++y) {
+ for (x = 0; x < 2; ++x, ++n) {
+ const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
+ const int non_zero =
+ TrellisQuantizeBlock(it, tmp[n], rd->uv_levels[n], ctx, 2,
+ &dqm->uv_, dqm->lambda_trellis_uv_);
+ it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = non_zero;
+ nz |= non_zero << n;
+ }
+ }
+ }
+ } else {
+ for (n = 0; n < 8; ++n) {
+ nz |= VP8EncQuantizeBlock(tmp[n], rd->uv_levels[n], 0, &dqm->uv_) << n;
+ }
+ }
+
+ for (n = 0; n < 8; n += 2) {
+ VP8ITransform(ref + VP8Scan[16 + n], tmp[n], yuv_out + VP8Scan[16 + n], 1);
+ }
+ return (nz << 16);
+}
+
+//------------------------------------------------------------------------------
+// RD-opt decision. Reconstruct each modes, evalue distortion and bit-cost.
+// Pick the mode is lower RD-cost = Rate + lamba * Distortion.
+
+static void SwapPtr(uint8_t** a, uint8_t** b) {
+ uint8_t* const tmp = *a;
+ *a = *b;
+ *b = tmp;
+}
+
+static void SwapOut(VP8EncIterator* const it) {
+ SwapPtr(&it->yuv_out_, &it->yuv_out2_);
+}
+
+static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* const rd) {
+ const VP8Encoder* const enc = it->enc_;
+ const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
+ const int lambda = dqm->lambda_i16_;
+ const int tlambda = dqm->tlambda_;
+ const uint8_t* const src = it->yuv_in_ + Y_OFF;
+ VP8ModeScore rd16;
+ int mode;
+
+ rd->mode_i16 = -1;
+ for (mode = 0; mode < 4; ++mode) {
+ uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF; // scratch buffer
+ int nz;
+
+ // Reconstruct
+ nz = ReconstructIntra16(it, &rd16, tmp_dst, mode);
+
+ // Measure RD-score
+ rd16.D = VP8SSE16x16(src, tmp_dst);
+ rd16.SD = tlambda ? MULT_8B(tlambda, VP8TDisto16x16(src, tmp_dst, kWeightY))
+ : 0;
+ rd16.R = VP8GetCostLuma16(it, &rd16);
+ rd16.R += VP8FixedCostsI16[mode];
+
+ // Since we always examine Intra16 first, we can overwrite *rd directly.
+ SetRDScore(lambda, &rd16);
+ if (mode == 0 || rd16.score < rd->score) {
+ CopyScore(rd, &rd16);
+ rd->mode_i16 = mode;
+ rd->nz = nz;
+ memcpy(rd->y_ac_levels, rd16.y_ac_levels, sizeof(rd16.y_ac_levels));
+ memcpy(rd->y_dc_levels, rd16.y_dc_levels, sizeof(rd16.y_dc_levels));
+ SwapOut(it);
+ }
+ }
+ SetRDScore(dqm->lambda_mode_, rd); // finalize score for mode decision.
+ VP8SetIntra16Mode(it, rd->mode_i16);
+}
+
+//------------------------------------------------------------------------------
+
+// return the cost array corresponding to the surrounding prediction modes.
+static const uint16_t* GetCostModeI4(VP8EncIterator* const it,
+ const uint8_t modes[16]) {
+ const int preds_w = it->enc_->preds_w_;
+ const int x = (it->i4_ & 3), y = it->i4_ >> 2;
+ const int left = (x == 0) ? it->preds_[y * preds_w - 1] : modes[it->i4_ - 1];
+ const int top = (y == 0) ? it->preds_[-preds_w + x] : modes[it->i4_ - 4];
+ return VP8FixedCostsI4[top][left];
+}
+
+static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) {
+ const VP8Encoder* const enc = it->enc_;
+ const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
+ const int lambda = dqm->lambda_i4_;
+ const int tlambda = dqm->tlambda_;
+ const uint8_t* const src0 = it->yuv_in_ + Y_OFF;
+ uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF;
+ int total_header_bits = 0;
+ VP8ModeScore rd_best;
+
+ if (enc->max_i4_header_bits_ == 0) {
+ return 0;
+ }
+
+ InitScore(&rd_best);
+ rd_best.score = 211; // '211' is the value of VP8BitCost(0, 145)
+ VP8IteratorStartI4(it);
+ do {
+ VP8ModeScore rd_i4;
+ int mode;
+ int best_mode = -1;
+ const uint8_t* const src = src0 + VP8Scan[it->i4_];
+ const uint16_t* const mode_costs = GetCostModeI4(it, rd->modes_i4);
+ uint8_t* best_block = best_blocks + VP8Scan[it->i4_];
+ uint8_t* tmp_dst = it->yuv_p_ + I4TMP; // scratch buffer.
+
+ InitScore(&rd_i4);
+ VP8MakeIntra4Preds(it);
+ for (mode = 0; mode < NUM_BMODES; ++mode) {
+ VP8ModeScore rd_tmp;
+ int16_t tmp_levels[16];
+
+ // Reconstruct
+ rd_tmp.nz =
+ ReconstructIntra4(it, tmp_levels, src, tmp_dst, mode) << it->i4_;
+
+ // Compute RD-score
+ rd_tmp.D = VP8SSE4x4(src, tmp_dst);
+ rd_tmp.SD =
+ tlambda ? MULT_8B(tlambda, VP8TDisto4x4(src, tmp_dst, kWeightY))
+ : 0;
+ rd_tmp.R = VP8GetCostLuma4(it, tmp_levels);
+ rd_tmp.R += mode_costs[mode];
+
+ SetRDScore(lambda, &rd_tmp);
+ if (best_mode < 0 || rd_tmp.score < rd_i4.score) {
+ CopyScore(&rd_i4, &rd_tmp);
+ best_mode = mode;
+ SwapPtr(&tmp_dst, &best_block);
+ memcpy(rd_best.y_ac_levels[it->i4_], tmp_levels, sizeof(tmp_levels));
+ }
+ }
+ SetRDScore(dqm->lambda_mode_, &rd_i4);
+ AddScore(&rd_best, &rd_i4);
+ total_header_bits += mode_costs[best_mode];
+ if (rd_best.score >= rd->score ||
+ total_header_bits > enc->max_i4_header_bits_) {
+ return 0;
+ }
+ // Copy selected samples if not in the right place already.
+ if (best_block != best_blocks + VP8Scan[it->i4_])
+ VP8Copy4x4(best_block, best_blocks + VP8Scan[it->i4_]);
+ rd->modes_i4[it->i4_] = best_mode;
+ it->top_nz_[it->i4_ & 3] = it->left_nz_[it->i4_ >> 2] = (rd_i4.nz ? 1 : 0);
+ } while (VP8IteratorRotateI4(it, best_blocks));
+
+ // finalize state
+ CopyScore(rd, &rd_best);
+ VP8SetIntra4Mode(it, rd->modes_i4);
+ SwapOut(it);
+ memcpy(rd->y_ac_levels, rd_best.y_ac_levels, sizeof(rd->y_ac_levels));
+ return 1; // select intra4x4 over intra16x16
+}
+
+//------------------------------------------------------------------------------
+
+static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) {
+ const VP8Encoder* const enc = it->enc_;
+ const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
+ const int lambda = dqm->lambda_uv_;
+ const uint8_t* const src = it->yuv_in_ + U_OFF;
+ uint8_t* const tmp_dst = it->yuv_out2_ + U_OFF; // scratch buffer
+ uint8_t* const dst0 = it->yuv_out_ + U_OFF;
+ VP8ModeScore rd_best;
+ int mode;
+
+ rd->mode_uv = -1;
+ InitScore(&rd_best);
+ for (mode = 0; mode < 4; ++mode) {
+ VP8ModeScore rd_uv;
+
+ // Reconstruct
+ rd_uv.nz = ReconstructUV(it, &rd_uv, tmp_dst, mode);
+
+ // Compute RD-score
+ rd_uv.D = VP8SSE16x8(src, tmp_dst);
+ rd_uv.SD = 0; // TODO: should we call TDisto? it tends to flatten areas.
+ rd_uv.R = VP8GetCostUV(it, &rd_uv);
+ rd_uv.R += VP8FixedCostsUV[mode];
+
+ SetRDScore(lambda, &rd_uv);
+ if (mode == 0 || rd_uv.score < rd_best.score) {
+ CopyScore(&rd_best, &rd_uv);
+ rd->mode_uv = mode;
+ memcpy(rd->uv_levels, rd_uv.uv_levels, sizeof(rd->uv_levels));
+ memcpy(dst0, tmp_dst, UV_SIZE); // TODO: SwapUVOut() ?
+ }
+ }
+ VP8SetIntraUVMode(it, rd->mode_uv);
+ AddScore(rd, &rd_best);
+}
+
+//------------------------------------------------------------------------------
+// Final reconstruction and quantization.
+
+static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) {
+ const VP8Encoder* const enc = it->enc_;
+ const int i16 = (it->mb_->type_ == 1);
+ int nz = 0;
+
+ if (i16) {
+ nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF, it->preds_[0]);
+ } else {
+ VP8IteratorStartI4(it);
+ do {
+ const int mode =
+ it->preds_[(it->i4_ & 3) + (it->i4_ >> 2) * enc->preds_w_];
+ const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_];
+ uint8_t* const dst = it->yuv_out_ + Y_OFF + VP8Scan[it->i4_];
+ VP8MakeIntra4Preds(it);
+ nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_],
+ src, dst, mode) << it->i4_;
+ } while (VP8IteratorRotateI4(it, it->yuv_out_ + Y_OFF));
+ }
+
+ nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF, it->mb_->uv_mode_);
+ rd->nz = nz;
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, int rd_opt) {
+ int is_skipped;
+
+ InitScore(rd);
+
+ // We can perform predictions for Luma16x16 and Chroma8x8 already.
+ // Luma4x4 predictions needs to be done as-we-go.
+ VP8MakeLuma16Preds(it);
+ VP8MakeChroma8Preds(it);
+
+ // for rd_opt = 2, we perform trellis-quant on the final decision only.
+ // for rd_opt > 2, we use it for every scoring (=much slower).
+ if (rd_opt > 0) {
+ it->do_trellis_ = (rd_opt > 2);
+ PickBestIntra16(it, rd);
+ if (it->enc_->method_ >= 2) {
+ PickBestIntra4(it, rd);
+ }
+ PickBestUV(it, rd);
+ if (rd_opt == 2) {
+ it->do_trellis_ = 1;
+ SimpleQuantize(it, rd);
+ }
+ } else {
+ // TODO: for method_ == 2, pick the best intra4/intra16 based on SSE
+ it->do_trellis_ = (it->enc_->method_ == 2);
+ SimpleQuantize(it, rd);
+ }
+ is_skipped = (rd->nz == 0);
+ VP8SetSkip(it, is_skipped);
+ return is_skipped;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/enc/syntax.c b/drivers/webpold/enc/syntax.c
new file mode 100644
index 0000000000..4221436ff9
--- /dev/null
+++ b/drivers/webpold/enc/syntax.c
@@ -0,0 +1,437 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Header syntax writing
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+
+#include "../format_constants.h"
+#include "./vp8enci.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Helper functions
+
+// TODO(later): Move to webp/format_constants.h?
+static void PutLE24(uint8_t* const data, uint32_t val) {
+ data[0] = (val >> 0) & 0xff;
+ data[1] = (val >> 8) & 0xff;
+ data[2] = (val >> 16) & 0xff;
+}
+
+static void PutLE32(uint8_t* const data, uint32_t val) {
+ PutLE24(data, val);
+ data[3] = (val >> 24) & 0xff;
+}
+
+static int IsVP8XNeeded(const VP8Encoder* const enc) {
+ return !!enc->has_alpha_; // Currently the only case when VP8X is needed.
+ // This could change in the future.
+}
+
+static int PutPaddingByte(const WebPPicture* const pic) {
+
+ const uint8_t pad_byte[1] = { 0 };
+ return !!pic->writer(pad_byte, 1, pic);
+}
+
+//------------------------------------------------------------------------------
+// Writers for header's various pieces (in order of appearance)
+
+static WebPEncodingError PutRIFFHeader(const VP8Encoder* const enc,
+ size_t riff_size) {
+ const WebPPicture* const pic = enc->pic_;
+ uint8_t riff[RIFF_HEADER_SIZE] = {
+ 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P'
+ };
+ assert(riff_size == (uint32_t)riff_size);
+ PutLE32(riff + TAG_SIZE, (uint32_t)riff_size);
+ if (!pic->writer(riff, sizeof(riff), pic)) {
+ return VP8_ENC_ERROR_BAD_WRITE;
+ }
+ return VP8_ENC_OK;
+}
+
+static WebPEncodingError PutVP8XHeader(const VP8Encoder* const enc) {
+ const WebPPicture* const pic = enc->pic_;
+ uint8_t vp8x[CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE] = {
+ 'V', 'P', '8', 'X'
+ };
+ uint32_t flags = 0;
+
+ assert(IsVP8XNeeded(enc));
+ assert(pic->width >= 1 && pic->height >= 1);
+ assert(pic->width <= MAX_CANVAS_SIZE && pic->height <= MAX_CANVAS_SIZE);
+
+ if (enc->has_alpha_) {
+ flags |= ALPHA_FLAG_BIT;
+ }
+
+ PutLE32(vp8x + TAG_SIZE, VP8X_CHUNK_SIZE);
+ PutLE32(vp8x + CHUNK_HEADER_SIZE, flags);
+ PutLE24(vp8x + CHUNK_HEADER_SIZE + 4, pic->width - 1);
+ PutLE24(vp8x + CHUNK_HEADER_SIZE + 7, pic->height - 1);
+ if(!pic->writer(vp8x, sizeof(vp8x), pic)) {
+ return VP8_ENC_ERROR_BAD_WRITE;
+ }
+ return VP8_ENC_OK;
+}
+
+static WebPEncodingError PutAlphaChunk(const VP8Encoder* const enc) {
+ const WebPPicture* const pic = enc->pic_;
+ uint8_t alpha_chunk_hdr[CHUNK_HEADER_SIZE] = {
+ 'A', 'L', 'P', 'H'
+ };
+
+ assert(enc->has_alpha_);
+
+ // Alpha chunk header.
+ PutLE32(alpha_chunk_hdr + TAG_SIZE, enc->alpha_data_size_);
+ if (!pic->writer(alpha_chunk_hdr, sizeof(alpha_chunk_hdr), pic)) {
+ return VP8_ENC_ERROR_BAD_WRITE;
+ }
+
+ // Alpha chunk data.
+ if (!pic->writer(enc->alpha_data_, enc->alpha_data_size_, pic)) {
+ return VP8_ENC_ERROR_BAD_WRITE;
+ }
+
+ // Padding.
+ if ((enc->alpha_data_size_ & 1) && !PutPaddingByte(pic)) {
+ return VP8_ENC_ERROR_BAD_WRITE;
+ }
+ return VP8_ENC_OK;
+}
+
+static WebPEncodingError PutVP8Header(const WebPPicture* const pic,
+ size_t vp8_size) {
+ uint8_t vp8_chunk_hdr[CHUNK_HEADER_SIZE] = {
+ 'V', 'P', '8', ' '
+ };
+ assert(vp8_size == (uint32_t)vp8_size);
+ PutLE32(vp8_chunk_hdr + TAG_SIZE, (uint32_t)vp8_size);
+ if (!pic->writer(vp8_chunk_hdr, sizeof(vp8_chunk_hdr), pic)) {
+ return VP8_ENC_ERROR_BAD_WRITE;
+ }
+ return VP8_ENC_OK;
+}
+
+static WebPEncodingError PutVP8FrameHeader(const WebPPicture* const pic,
+ int profile, size_t size0) {
+ uint8_t vp8_frm_hdr[VP8_FRAME_HEADER_SIZE];
+ uint32_t bits;
+
+ if (size0 >= VP8_MAX_PARTITION0_SIZE) { // partition #0 is too big to fit
+ return VP8_ENC_ERROR_PARTITION0_OVERFLOW;
+ }
+
+ // Paragraph 9.1.
+ bits = 0 // keyframe (1b)
+ | (profile << 1) // profile (3b)
+ | (1 << 4) // visible (1b)
+ | ((uint32_t)size0 << 5); // partition length (19b)
+ vp8_frm_hdr[0] = (bits >> 0) & 0xff;
+ vp8_frm_hdr[1] = (bits >> 8) & 0xff;
+ vp8_frm_hdr[2] = (bits >> 16) & 0xff;
+ // signature
+ vp8_frm_hdr[3] = (VP8_SIGNATURE >> 16) & 0xff;
+ vp8_frm_hdr[4] = (VP8_SIGNATURE >> 8) & 0xff;
+ vp8_frm_hdr[5] = (VP8_SIGNATURE >> 0) & 0xff;
+ // dimensions
+ vp8_frm_hdr[6] = pic->width & 0xff;
+ vp8_frm_hdr[7] = pic->width >> 8;
+ vp8_frm_hdr[8] = pic->height & 0xff;
+ vp8_frm_hdr[9] = pic->height >> 8;
+
+ if (!pic->writer(vp8_frm_hdr, sizeof(vp8_frm_hdr), pic)) {
+ return VP8_ENC_ERROR_BAD_WRITE;
+ }
+ return VP8_ENC_OK;
+}
+
+// WebP Headers.
+static int PutWebPHeaders(const VP8Encoder* const enc, size_t size0,
+ size_t vp8_size, size_t riff_size) {
+ WebPPicture* const pic = enc->pic_;
+ WebPEncodingError err = VP8_ENC_OK;
+
+ // RIFF header.
+ err = PutRIFFHeader(enc, riff_size);
+ if (err != VP8_ENC_OK) goto Error;
+
+ // VP8X.
+ if (IsVP8XNeeded(enc)) {
+ err = PutVP8XHeader(enc);
+ if (err != VP8_ENC_OK) goto Error;
+ }
+
+ // Alpha.
+ if (enc->has_alpha_) {
+ err = PutAlphaChunk(enc);
+ if (err != VP8_ENC_OK) goto Error;
+ }
+
+ // VP8 header.
+ err = PutVP8Header(pic, vp8_size);
+ if (err != VP8_ENC_OK) goto Error;
+
+ // VP8 frame header.
+ err = PutVP8FrameHeader(pic, enc->profile_, size0);
+ if (err != VP8_ENC_OK) goto Error;
+
+ // All OK.
+ return 1;
+
+ // Error.
+ Error:
+ return WebPEncodingSetError(pic, err);
+}
+
+// Segmentation header
+static void PutSegmentHeader(VP8BitWriter* const bw,
+ const VP8Encoder* const enc) {
+ const VP8SegmentHeader* const hdr = &enc->segment_hdr_;
+ const VP8Proba* const proba = &enc->proba_;
+ if (VP8PutBitUniform(bw, (hdr->num_segments_ > 1))) {
+ // We always 'update' the quant and filter strength values
+ const int update_data = 1;
+ int s;
+ VP8PutBitUniform(bw, hdr->update_map_);
+ if (VP8PutBitUniform(bw, update_data)) {
+ // we always use absolute values, not relative ones
+ VP8PutBitUniform(bw, 1); // (segment_feature_mode = 1. Paragraph 9.3.)
+ for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
+ VP8PutSignedValue(bw, enc->dqm_[s].quant_, 7);
+ }
+ for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
+ VP8PutSignedValue(bw, enc->dqm_[s].fstrength_, 6);
+ }
+ }
+ if (hdr->update_map_) {
+ for (s = 0; s < 3; ++s) {
+ if (VP8PutBitUniform(bw, (proba->segments_[s] != 255u))) {
+ VP8PutValue(bw, proba->segments_[s], 8);
+ }
+ }
+ }
+ }
+}
+
+// Filtering parameters header
+static void PutFilterHeader(VP8BitWriter* const bw,
+ const VP8FilterHeader* const hdr) {
+ const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0);
+ VP8PutBitUniform(bw, hdr->simple_);
+ VP8PutValue(bw, hdr->level_, 6);
+ VP8PutValue(bw, hdr->sharpness_, 3);
+ if (VP8PutBitUniform(bw, use_lf_delta)) {
+ // '0' is the default value for i4x4_lf_delta_ at frame #0.
+ const int need_update = (hdr->i4x4_lf_delta_ != 0);
+ if (VP8PutBitUniform(bw, need_update)) {
+ // we don't use ref_lf_delta => emit four 0 bits
+ VP8PutValue(bw, 0, 4);
+ // we use mode_lf_delta for i4x4
+ VP8PutSignedValue(bw, hdr->i4x4_lf_delta_, 6);
+ VP8PutValue(bw, 0, 3); // all others unused
+ }
+ }
+}
+
+// Nominal quantization parameters
+static void PutQuant(VP8BitWriter* const bw,
+ const VP8Encoder* const enc) {
+ VP8PutValue(bw, enc->base_quant_, 7);
+ VP8PutSignedValue(bw, enc->dq_y1_dc_, 4);
+ VP8PutSignedValue(bw, enc->dq_y2_dc_, 4);
+ VP8PutSignedValue(bw, enc->dq_y2_ac_, 4);
+ VP8PutSignedValue(bw, enc->dq_uv_dc_, 4);
+ VP8PutSignedValue(bw, enc->dq_uv_ac_, 4);
+}
+
+// Partition sizes
+static int EmitPartitionsSize(const VP8Encoder* const enc,
+ WebPPicture* const pic) {
+ uint8_t buf[3 * (MAX_NUM_PARTITIONS - 1)];
+ int p;
+ for (p = 0; p < enc->num_parts_ - 1; ++p) {
+ const size_t part_size = VP8BitWriterSize(enc->parts_ + p);
+ if (part_size >= VP8_MAX_PARTITION_SIZE) {
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_PARTITION_OVERFLOW);
+ }
+ buf[3 * p + 0] = (part_size >> 0) & 0xff;
+ buf[3 * p + 1] = (part_size >> 8) & 0xff;
+ buf[3 * p + 2] = (part_size >> 16) & 0xff;
+ }
+ return p ? pic->writer(buf, 3 * p, pic) : 1;
+}
+
+//------------------------------------------------------------------------------
+
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+
+#define KTRAILER_SIZE 8
+
+static int WriteExtensions(VP8Encoder* const enc) {
+ uint8_t buffer[KTRAILER_SIZE];
+ VP8BitWriter* const bw = &enc->bw_;
+ WebPPicture* const pic = enc->pic_;
+
+ // Layer (bytes 0..3)
+ PutLE24(buffer + 0, enc->layer_data_size_);
+ buffer[3] = enc->pic_->colorspace & WEBP_CSP_UV_MASK;
+ if (enc->layer_data_size_ > 0) {
+ assert(enc->use_layer_);
+ // append layer data to last partition
+ if (!VP8BitWriterAppend(&enc->parts_[enc->num_parts_ - 1],
+ enc->layer_data_, enc->layer_data_size_)) {
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY);
+ }
+ }
+
+ buffer[KTRAILER_SIZE - 1] = 0x01; // marker
+ if (!VP8BitWriterAppend(bw, buffer, KTRAILER_SIZE)) {
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY);
+ }
+ return 1;
+}
+
+#endif /* WEBP_EXPERIMENTAL_FEATURES */
+
+//------------------------------------------------------------------------------
+
+static size_t GeneratePartition0(VP8Encoder* const enc) {
+ VP8BitWriter* const bw = &enc->bw_;
+ const int mb_size = enc->mb_w_ * enc->mb_h_;
+ uint64_t pos1, pos2, pos3;
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ const int need_extensions = enc->use_layer_;
+#endif
+
+ pos1 = VP8BitWriterPos(bw);
+ VP8BitWriterInit(bw, mb_size * 7 / 8); // ~7 bits per macroblock
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ VP8PutBitUniform(bw, need_extensions); // extensions
+#else
+ VP8PutBitUniform(bw, 0); // colorspace
+#endif
+ VP8PutBitUniform(bw, 0); // clamp type
+
+ PutSegmentHeader(bw, enc);
+ PutFilterHeader(bw, &enc->filter_hdr_);
+ VP8PutValue(bw, enc->config_->partitions, 2);
+ PutQuant(bw, enc);
+ VP8PutBitUniform(bw, 0); // no proba update
+ VP8WriteProbas(bw, &enc->proba_);
+ pos2 = VP8BitWriterPos(bw);
+ VP8CodeIntraModes(enc);
+ VP8BitWriterFinish(bw);
+
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ if (need_extensions && !WriteExtensions(enc)) {
+ return 0;
+ }
+#endif
+
+ pos3 = VP8BitWriterPos(bw);
+
+ if (enc->pic_->stats) {
+ enc->pic_->stats->header_bytes[0] = (int)((pos2 - pos1 + 7) >> 3);
+ enc->pic_->stats->header_bytes[1] = (int)((pos3 - pos2 + 7) >> 3);
+ enc->pic_->stats->alpha_data_size = (int)enc->alpha_data_size_;
+ enc->pic_->stats->layer_data_size = (int)enc->layer_data_size_;
+ }
+ return !bw->error_;
+}
+
+void VP8EncFreeBitWriters(VP8Encoder* const enc) {
+ int p;
+ VP8BitWriterWipeOut(&enc->bw_);
+ for (p = 0; p < enc->num_parts_; ++p) {
+ VP8BitWriterWipeOut(enc->parts_ + p);
+ }
+}
+
+int VP8EncWrite(VP8Encoder* const enc) {
+ WebPPicture* const pic = enc->pic_;
+ VP8BitWriter* const bw = &enc->bw_;
+ const int task_percent = 19;
+ const int percent_per_part = task_percent / enc->num_parts_;
+ const int final_percent = enc->percent_ + task_percent;
+ int ok = 0;
+ size_t vp8_size, pad, riff_size;
+ int p;
+
+ // Partition #0 with header and partition sizes
+ ok = !!GeneratePartition0(enc);
+
+ // Compute VP8 size
+ vp8_size = VP8_FRAME_HEADER_SIZE +
+ VP8BitWriterSize(bw) +
+ 3 * (enc->num_parts_ - 1);
+ for (p = 0; p < enc->num_parts_; ++p) {
+ vp8_size += VP8BitWriterSize(enc->parts_ + p);
+ }
+ pad = vp8_size & 1;
+ vp8_size += pad;
+
+ // Compute RIFF size
+ // At the minimum it is: "WEBPVP8 nnnn" + VP8 data size.
+ riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8_size;
+ if (IsVP8XNeeded(enc)) { // Add size for: VP8X header + data.
+ riff_size += CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE;
+ }
+ if (enc->has_alpha_) { // Add size for: ALPH header + data.
+ const uint32_t padded_alpha_size = enc->alpha_data_size_ +
+ (enc->alpha_data_size_ & 1);
+ riff_size += CHUNK_HEADER_SIZE + padded_alpha_size;
+ }
+ // Sanity check.
+ if (riff_size > 0xfffffffeU) {
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_FILE_TOO_BIG);
+ }
+
+ // Emit headers and partition #0
+ {
+ const uint8_t* const part0 = VP8BitWriterBuf(bw);
+ const size_t size0 = VP8BitWriterSize(bw);
+ ok = ok && PutWebPHeaders(enc, size0, vp8_size, riff_size)
+ && pic->writer(part0, size0, pic)
+ && EmitPartitionsSize(enc, pic);
+ VP8BitWriterWipeOut(bw); // will free the internal buffer.
+ }
+
+ // Token partitions
+ for (p = 0; p < enc->num_parts_; ++p) {
+ const uint8_t* const buf = VP8BitWriterBuf(enc->parts_ + p);
+ const size_t size = VP8BitWriterSize(enc->parts_ + p);
+ if (size)
+ ok = ok && pic->writer(buf, size, pic);
+ VP8BitWriterWipeOut(enc->parts_ + p); // will free the internal buffer.
+ ok = ok && WebPReportProgress(pic, enc->percent_ + percent_per_part,
+ &enc->percent_);
+ }
+
+ // Padding byte
+ if (ok && pad) {
+ ok = PutPaddingByte(pic);
+ }
+
+ enc->coded_size_ = (int)(CHUNK_HEADER_SIZE + riff_size);
+ ok = ok && WebPReportProgress(pic, final_percent, &enc->percent_);
+ return ok;
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/enc/tree.c b/drivers/webpold/enc/tree.c
new file mode 100644
index 0000000000..8b25e5e488
--- /dev/null
+++ b/drivers/webpold/enc/tree.c
@@ -0,0 +1,510 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Token probabilities
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./vp8enci.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Default probabilities
+
+// Paragraph 13.5
+const uint8_t
+ VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
+ // genereated using vp8_default_coef_probs() in entropy.c:129
+ { { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
+ },
+ { { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 },
+ { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 },
+ { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 }
+ },
+ { { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 },
+ { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 },
+ { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 },
+ },
+ { { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 },
+ { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 },
+ { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 },
+ },
+ { { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 },
+ { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 },
+ { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 }
+ },
+ { { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 },
+ { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 },
+ { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 }
+ },
+ { { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 },
+ { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 },
+ { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 }
+ },
+ { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
+ }
+ },
+ { { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 },
+ { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 },
+ { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 }
+ },
+ { { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 },
+ { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 },
+ { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 }
+ },
+ { { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 },
+ { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 },
+ { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 }
+ },
+ { { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 },
+ { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 },
+ { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 }
+ },
+ { { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 },
+ { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 },
+ { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 }
+ },
+ { { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 },
+ { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 },
+ { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 }
+ },
+ { { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 },
+ { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 },
+ { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 }
+ },
+ { { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 },
+ { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 },
+ { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 }
+ }
+ },
+ { { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 },
+ { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 },
+ { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 }
+ },
+ { { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 },
+ { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 },
+ { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 }
+ },
+ { { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 },
+ { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 },
+ { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 }
+ },
+ { { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 },
+ { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 },
+ { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 }
+ },
+ { { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 },
+ { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 },
+ { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
+ },
+ { { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
+ },
+ { { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 },
+ { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 },
+ { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
+ },
+ { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
+ }
+ },
+ { { { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 },
+ { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 },
+ { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 }
+ },
+ { { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 },
+ { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 },
+ { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 }
+ },
+ { { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 },
+ { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 },
+ { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 }
+ },
+ { { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 },
+ { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 },
+ { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 }
+ },
+ { { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 },
+ { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 },
+ { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 }
+ },
+ { { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 },
+ { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 },
+ { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 }
+ },
+ { { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 },
+ { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 },
+ { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 }
+ },
+ { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+ { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
+ }
+ }
+};
+
+void VP8DefaultProbas(VP8Encoder* const enc) {
+ VP8Proba* const probas = &enc->proba_;
+ probas->use_skip_proba_ = 0;
+ memset(probas->segments_, 255u, sizeof(probas->segments_));
+ memcpy(probas->coeffs_, VP8CoeffsProba0, sizeof(VP8CoeffsProba0));
+ // Note: we could hard-code the level_costs_ corresponding to VP8CoeffsProba0,
+ // but that's ~11k of static data. Better call VP8CalculateLevelCosts() later.
+ probas->dirty_ = 1;
+}
+
+// Paragraph 11.5. 900bytes.
+static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = {
+ { { 231, 120, 48, 89, 115, 113, 120, 152, 112 },
+ { 152, 179, 64, 126, 170, 118, 46, 70, 95 },
+ { 175, 69, 143, 80, 85, 82, 72, 155, 103 },
+ { 56, 58, 10, 171, 218, 189, 17, 13, 152 },
+ { 114, 26, 17, 163, 44, 195, 21, 10, 173 },
+ { 121, 24, 80, 195, 26, 62, 44, 64, 85 },
+ { 144, 71, 10, 38, 171, 213, 144, 34, 26 },
+ { 170, 46, 55, 19, 136, 160, 33, 206, 71 },
+ { 63, 20, 8, 114, 114, 208, 12, 9, 226 },
+ { 81, 40, 11, 96, 182, 84, 29, 16, 36 } },
+ { { 134, 183, 89, 137, 98, 101, 106, 165, 148 },
+ { 72, 187, 100, 130, 157, 111, 32, 75, 80 },
+ { 66, 102, 167, 99, 74, 62, 40, 234, 128 },
+ { 41, 53, 9, 178, 241, 141, 26, 8, 107 },
+ { 74, 43, 26, 146, 73, 166, 49, 23, 157 },
+ { 65, 38, 105, 160, 51, 52, 31, 115, 128 },
+ { 104, 79, 12, 27, 217, 255, 87, 17, 7 },
+ { 87, 68, 71, 44, 114, 51, 15, 186, 23 },
+ { 47, 41, 14, 110, 182, 183, 21, 17, 194 },
+ { 66, 45, 25, 102, 197, 189, 23, 18, 22 } },
+ { { 88, 88, 147, 150, 42, 46, 45, 196, 205 },
+ { 43, 97, 183, 117, 85, 38, 35, 179, 61 },
+ { 39, 53, 200, 87, 26, 21, 43, 232, 171 },
+ { 56, 34, 51, 104, 114, 102, 29, 93, 77 },
+ { 39, 28, 85, 171, 58, 165, 90, 98, 64 },
+ { 34, 22, 116, 206, 23, 34, 43, 166, 73 },
+ { 107, 54, 32, 26, 51, 1, 81, 43, 31 },
+ { 68, 25, 106, 22, 64, 171, 36, 225, 114 },
+ { 34, 19, 21, 102, 132, 188, 16, 76, 124 },
+ { 62, 18, 78, 95, 85, 57, 50, 48, 51 } },
+ { { 193, 101, 35, 159, 215, 111, 89, 46, 111 },
+ { 60, 148, 31, 172, 219, 228, 21, 18, 111 },
+ { 112, 113, 77, 85, 179, 255, 38, 120, 114 },
+ { 40, 42, 1, 196, 245, 209, 10, 25, 109 },
+ { 88, 43, 29, 140, 166, 213, 37, 43, 154 },
+ { 61, 63, 30, 155, 67, 45, 68, 1, 209 },
+ { 100, 80, 8, 43, 154, 1, 51, 26, 71 },
+ { 142, 78, 78, 16, 255, 128, 34, 197, 171 },
+ { 41, 40, 5, 102, 211, 183, 4, 1, 221 },
+ { 51, 50, 17, 168, 209, 192, 23, 25, 82 } },
+ { { 138, 31, 36, 171, 27, 166, 38, 44, 229 },
+ { 67, 87, 58, 169, 82, 115, 26, 59, 179 },
+ { 63, 59, 90, 180, 59, 166, 93, 73, 154 },
+ { 40, 40, 21, 116, 143, 209, 34, 39, 175 },
+ { 47, 15, 16, 183, 34, 223, 49, 45, 183 },
+ { 46, 17, 33, 183, 6, 98, 15, 32, 183 },
+ { 57, 46, 22, 24, 128, 1, 54, 17, 37 },
+ { 65, 32, 73, 115, 28, 128, 23, 128, 205 },
+ { 40, 3, 9, 115, 51, 192, 18, 6, 223 },
+ { 87, 37, 9, 115, 59, 77, 64, 21, 47 } },
+ { { 104, 55, 44, 218, 9, 54, 53, 130, 226 },
+ { 64, 90, 70, 205, 40, 41, 23, 26, 57 },
+ { 54, 57, 112, 184, 5, 41, 38, 166, 213 },
+ { 30, 34, 26, 133, 152, 116, 10, 32, 134 },
+ { 39, 19, 53, 221, 26, 114, 32, 73, 255 },
+ { 31, 9, 65, 234, 2, 15, 1, 118, 73 },
+ { 75, 32, 12, 51, 192, 255, 160, 43, 51 },
+ { 88, 31, 35, 67, 102, 85, 55, 186, 85 },
+ { 56, 21, 23, 111, 59, 205, 45, 37, 192 },
+ { 55, 38, 70, 124, 73, 102, 1, 34, 98 } },
+ { { 125, 98, 42, 88, 104, 85, 117, 175, 82 },
+ { 95, 84, 53, 89, 128, 100, 113, 101, 45 },
+ { 75, 79, 123, 47, 51, 128, 81, 171, 1 },
+ { 57, 17, 5, 71, 102, 57, 53, 41, 49 },
+ { 38, 33, 13, 121, 57, 73, 26, 1, 85 },
+ { 41, 10, 67, 138, 77, 110, 90, 47, 114 },
+ { 115, 21, 2, 10, 102, 255, 166, 23, 6 },
+ { 101, 29, 16, 10, 85, 128, 101, 196, 26 },
+ { 57, 18, 10, 102, 102, 213, 34, 20, 43 },
+ { 117, 20, 15, 36, 163, 128, 68, 1, 26 } },
+ { { 102, 61, 71, 37, 34, 53, 31, 243, 192 },
+ { 69, 60, 71, 38, 73, 119, 28, 222, 37 },
+ { 68, 45, 128, 34, 1, 47, 11, 245, 171 },
+ { 62, 17, 19, 70, 146, 85, 55, 62, 70 },
+ { 37, 43, 37, 154, 100, 163, 85, 160, 1 },
+ { 63, 9, 92, 136, 28, 64, 32, 201, 85 },
+ { 75, 15, 9, 9, 64, 255, 184, 119, 16 },
+ { 86, 6, 28, 5, 64, 255, 25, 248, 1 },
+ { 56, 8, 17, 132, 137, 255, 55, 116, 128 },
+ { 58, 15, 20, 82, 135, 57, 26, 121, 40 } },
+ { { 164, 50, 31, 137, 154, 133, 25, 35, 218 },
+ { 51, 103, 44, 131, 131, 123, 31, 6, 158 },
+ { 86, 40, 64, 135, 148, 224, 45, 183, 128 },
+ { 22, 26, 17, 131, 240, 154, 14, 1, 209 },
+ { 45, 16, 21, 91, 64, 222, 7, 1, 197 },
+ { 56, 21, 39, 155, 60, 138, 23, 102, 213 },
+ { 83, 12, 13, 54, 192, 255, 68, 47, 28 },
+ { 85, 26, 85, 85, 128, 128, 32, 146, 171 },
+ { 18, 11, 7, 63, 144, 171, 4, 4, 246 },
+ { 35, 27, 10, 146, 174, 171, 12, 26, 128 } },
+ { { 190, 80, 35, 99, 180, 80, 126, 54, 45 },
+ { 85, 126, 47, 87, 176, 51, 41, 20, 32 },
+ { 101, 75, 128, 139, 118, 146, 116, 128, 85 },
+ { 56, 41, 15, 176, 236, 85, 37, 9, 62 },
+ { 71, 30, 17, 119, 118, 255, 17, 18, 138 },
+ { 101, 38, 60, 138, 55, 70, 43, 26, 142 },
+ { 146, 36, 19, 30, 171, 255, 97, 27, 20 },
+ { 138, 45, 61, 62, 219, 1, 81, 188, 64 },
+ { 32, 41, 20, 117, 151, 142, 20, 21, 163 },
+ { 112, 19, 12, 61, 195, 128, 48, 4, 24 } }
+};
+
+static int PutI4Mode(VP8BitWriter* const bw, int mode,
+ const uint8_t* const prob) {
+ if (VP8PutBit(bw, mode != B_DC_PRED, prob[0])) {
+ if (VP8PutBit(bw, mode != B_TM_PRED, prob[1])) {
+ if (VP8PutBit(bw, mode != B_VE_PRED, prob[2])) {
+ if (!VP8PutBit(bw, mode >= B_LD_PRED, prob[3])) {
+ if (VP8PutBit(bw, mode != B_HE_PRED, prob[4])) {
+ VP8PutBit(bw, mode != B_RD_PRED, prob[5]);
+ }
+ } else {
+ if (VP8PutBit(bw, mode != B_LD_PRED, prob[6])) {
+ if (VP8PutBit(bw, mode != B_VL_PRED, prob[7])) {
+ VP8PutBit(bw, mode != B_HD_PRED, prob[8]);
+ }
+ }
+ }
+ }
+ }
+ }
+ return mode;
+}
+
+static void PutI16Mode(VP8BitWriter* const bw, int mode) {
+ if (VP8PutBit(bw, (mode == TM_PRED || mode == H_PRED), 156)) {
+ VP8PutBit(bw, mode == TM_PRED, 128); // TM or HE
+ } else {
+ VP8PutBit(bw, mode == V_PRED, 163); // VE or DC
+ }
+}
+
+static void PutUVMode(VP8BitWriter* const bw, int uv_mode) {
+ if (VP8PutBit(bw, uv_mode != DC_PRED, 142)) {
+ if (VP8PutBit(bw, uv_mode != V_PRED, 114)) {
+ VP8PutBit(bw, uv_mode != H_PRED, 183); // else: TM_PRED
+ }
+ }
+}
+
+static void PutSegment(VP8BitWriter* const bw, int s, const uint8_t* p) {
+ if (VP8PutBit(bw, s >= 2, p[0])) p += 1;
+ VP8PutBit(bw, s & 1, p[1]);
+}
+
+void VP8CodeIntraModes(VP8Encoder* const enc) {
+ VP8BitWriter* const bw = &enc->bw_;
+ VP8EncIterator it;
+ VP8IteratorInit(enc, &it);
+ do {
+ const VP8MBInfo* mb = it.mb_;
+ const uint8_t* preds = it.preds_;
+ if (enc->segment_hdr_.update_map_) {
+ PutSegment(bw, mb->segment_, enc->proba_.segments_);
+ }
+ if (enc->proba_.use_skip_proba_) {
+ VP8PutBit(bw, mb->skip_, enc->proba_.skip_proba_);
+ }
+ if (VP8PutBit(bw, (mb->type_ != 0), 145)) { // i16x16
+ PutI16Mode(bw, preds[0]);
+ } else {
+ const int preds_w = enc->preds_w_;
+ const uint8_t* top_pred = preds - preds_w;
+ int x, y;
+ for (y = 0; y < 4; ++y) {
+ int left = preds[-1];
+ for (x = 0; x < 4; ++x) {
+ const uint8_t* const probas = kBModesProba[top_pred[x]][left];
+ left = PutI4Mode(bw, preds[x], probas);
+ }
+ top_pred = preds;
+ preds += preds_w;
+ }
+ }
+ PutUVMode(bw, mb->uv_mode_);
+ } while (VP8IteratorNext(&it, 0));
+}
+
+//------------------------------------------------------------------------------
+// Paragraph 13
+
+const uint8_t
+ VP8CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
+ { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 },
+ { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 },
+ { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ }
+ },
+ { { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 },
+ { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 }
+ },
+ { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ }
+ },
+ { { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 },
+ { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 }
+ },
+ { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ }
+ },
+ { { { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 },
+ { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ },
+ { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
+ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
+ }
+ }
+};
+
+void VP8WriteProbas(VP8BitWriter* const bw, const VP8Proba* const probas) {
+ int t, b, c, p;
+ for (t = 0; t < NUM_TYPES; ++t) {
+ for (b = 0; b < NUM_BANDS; ++b) {
+ for (c = 0; c < NUM_CTX; ++c) {
+ for (p = 0; p < NUM_PROBAS; ++p) {
+ const uint8_t p0 = probas->coeffs_[t][b][c][p];
+ const int update = (p0 != VP8CoeffsProba0[t][b][c][p]);
+ if (VP8PutBit(bw, update, VP8CoeffsUpdateProba[t][b][c][p])) {
+ VP8PutValue(bw, p0, 8);
+ }
+ }
+ }
+ }
+ }
+ if (VP8PutBitUniform(bw, probas->use_skip_proba_)) {
+ VP8PutValue(bw, probas->skip_proba_, 8);
+ }
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/enc/vp8enci.h b/drivers/webpold/enc/vp8enci.h
new file mode 100644
index 0000000000..936e1c18ce
--- /dev/null
+++ b/drivers/webpold/enc/vp8enci.h
@@ -0,0 +1,525 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// WebP encoder: internal header.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_ENC_VP8ENCI_H_
+#define WEBP_ENC_VP8ENCI_H_
+
+#include <string.h> // for memcpy()
+#include "../encode.h"
+#include "../dsp/dsp.h"
+#include "../utils/bit_writer.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Various defines and enums
+
+// version numbers
+#define ENC_MAJ_VERSION 0
+#define ENC_MIN_VERSION 2
+#define ENC_REV_VERSION 0
+
+// size of histogram used by CollectHistogram.
+#define MAX_COEFF_THRESH 64
+
+// intra prediction modes
+enum { B_DC_PRED = 0, // 4x4 modes
+ B_TM_PRED = 1,
+ B_VE_PRED = 2,
+ B_HE_PRED = 3,
+ B_RD_PRED = 4,
+ B_VR_PRED = 5,
+ B_LD_PRED = 6,
+ B_VL_PRED = 7,
+ B_HD_PRED = 8,
+ B_HU_PRED = 9,
+ NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10
+
+ // Luma16 or UV modes
+ DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED,
+ H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED
+ };
+
+enum { NUM_MB_SEGMENTS = 4,
+ MAX_NUM_PARTITIONS = 8,
+ NUM_TYPES = 4, // 0: i16-AC, 1: i16-DC, 2:chroma-AC, 3:i4-AC
+ NUM_BANDS = 8,
+ NUM_CTX = 3,
+ NUM_PROBAS = 11,
+ MAX_LF_LEVELS = 64, // Maximum loop filter level
+ MAX_VARIABLE_LEVEL = 67 // last (inclusive) level with variable cost
+ };
+
+// YUV-cache parameters. Cache is 16-pixels wide.
+// The original or reconstructed samples can be accessed using VP8Scan[]
+// The predicted blocks can be accessed using offsets to yuv_p_ and
+// the arrays VP8*ModeOffsets[];
+// +----+ YUV Samples area. See VP8Scan[] for accessing the blocks.
+// Y_OFF |YYYY| <- original samples (enc->yuv_in_)
+// |YYYY|
+// |YYYY|
+// |YYYY|
+// U_OFF |UUVV| V_OFF (=U_OFF + 8)
+// |UUVV|
+// +----+
+// Y_OFF |YYYY| <- compressed/decoded samples ('yuv_out_')
+// |YYYY| There are two buffers like this ('yuv_out_'/'yuv_out2_')
+// |YYYY|
+// |YYYY|
+// U_OFF |UUVV| V_OFF
+// |UUVV|
+// x2 (for yuv_out2_)
+// +----+ Prediction area ('yuv_p_', size = PRED_SIZE)
+// I16DC16 |YYYY| Intra16 predictions (16x16 block each)
+// |YYYY|
+// |YYYY|
+// |YYYY|
+// I16TM16 |YYYY|
+// |YYYY|
+// |YYYY|
+// |YYYY|
+// I16VE16 |YYYY|
+// |YYYY|
+// |YYYY|
+// |YYYY|
+// I16HE16 |YYYY|
+// |YYYY|
+// |YYYY|
+// |YYYY|
+// +----+ Chroma U/V predictions (16x8 block each)
+// C8DC8 |UUVV|
+// |UUVV|
+// C8TM8 |UUVV|
+// |UUVV|
+// C8VE8 |UUVV|
+// |UUVV|
+// C8HE8 |UUVV|
+// |UUVV|
+// +----+ Intra 4x4 predictions (4x4 block each)
+// |YYYY| I4DC4 I4TM4 I4VE4 I4HE4
+// |YYYY| I4RD4 I4VR4 I4LD4 I4VL4
+// |YY..| I4HD4 I4HU4 I4TMP
+// +----+
+#define BPS 16 // this is the common stride
+#define Y_SIZE (BPS * 16)
+#define UV_SIZE (BPS * 8)
+#define YUV_SIZE (Y_SIZE + UV_SIZE)
+#define PRED_SIZE (6 * 16 * BPS + 12 * BPS)
+#define Y_OFF (0)
+#define U_OFF (Y_SIZE)
+#define V_OFF (U_OFF + 8)
+#define ALIGN_CST 15
+#define DO_ALIGN(PTR) ((uintptr_t)((PTR) + ALIGN_CST) & ~ALIGN_CST)
+
+extern const int VP8Scan[16 + 4 + 4]; // in quant.c
+extern const int VP8UVModeOffsets[4]; // in analyze.c
+extern const int VP8I16ModeOffsets[4];
+extern const int VP8I4ModeOffsets[NUM_BMODES];
+
+// Layout of prediction blocks
+// intra 16x16
+#define I16DC16 (0 * 16 * BPS)
+#define I16TM16 (1 * 16 * BPS)
+#define I16VE16 (2 * 16 * BPS)
+#define I16HE16 (3 * 16 * BPS)
+// chroma 8x8, two U/V blocks side by side (hence: 16x8 each)
+#define C8DC8 (4 * 16 * BPS)
+#define C8TM8 (4 * 16 * BPS + 8 * BPS)
+#define C8VE8 (5 * 16 * BPS)
+#define C8HE8 (5 * 16 * BPS + 8 * BPS)
+// intra 4x4
+#define I4DC4 (6 * 16 * BPS + 0)
+#define I4TM4 (6 * 16 * BPS + 4)
+#define I4VE4 (6 * 16 * BPS + 8)
+#define I4HE4 (6 * 16 * BPS + 12)
+#define I4RD4 (6 * 16 * BPS + 4 * BPS + 0)
+#define I4VR4 (6 * 16 * BPS + 4 * BPS + 4)
+#define I4LD4 (6 * 16 * BPS + 4 * BPS + 8)
+#define I4VL4 (6 * 16 * BPS + 4 * BPS + 12)
+#define I4HD4 (6 * 16 * BPS + 8 * BPS + 0)
+#define I4HU4 (6 * 16 * BPS + 8 * BPS + 4)
+#define I4TMP (6 * 16 * BPS + 8 * BPS + 8)
+
+typedef int64_t score_t; // type used for scores, rate, distortion
+#define MAX_COST ((score_t)0x7fffffffffffffLL)
+
+#define QFIX 17
+#define BIAS(b) ((b) << (QFIX - 8))
+// Fun fact: this is the _only_ line where we're actually being lossy and
+// discarding bits.
+static WEBP_INLINE int QUANTDIV(int n, int iQ, int B) {
+ return (n * iQ + B) >> QFIX;
+}
+extern const uint8_t VP8Zigzag[16];
+
+//------------------------------------------------------------------------------
+// Headers
+
+typedef uint32_t proba_t; // 16b + 16b
+typedef uint8_t ProbaArray[NUM_CTX][NUM_PROBAS];
+typedef proba_t StatsArray[NUM_CTX][NUM_PROBAS];
+typedef uint16_t CostArray[NUM_CTX][MAX_VARIABLE_LEVEL + 1];
+typedef double LFStats[NUM_MB_SEGMENTS][MAX_LF_LEVELS]; // filter stats
+
+typedef struct VP8Encoder VP8Encoder;
+
+// segment features
+typedef struct {
+ int num_segments_; // Actual number of segments. 1 segment only = unused.
+ int update_map_; // whether to update the segment map or not.
+ // must be 0 if there's only 1 segment.
+ int size_; // bit-cost for transmitting the segment map
+} VP8SegmentHeader;
+
+// Struct collecting all frame-persistent probabilities.
+typedef struct {
+ uint8_t segments_[3]; // probabilities for segment tree
+ uint8_t skip_proba_; // final probability of being skipped.
+ ProbaArray coeffs_[NUM_TYPES][NUM_BANDS]; // 924 bytes
+ StatsArray stats_[NUM_TYPES][NUM_BANDS]; // 4224 bytes
+ CostArray level_cost_[NUM_TYPES][NUM_BANDS]; // 11.4k
+ int dirty_; // if true, need to call VP8CalculateLevelCosts()
+ int use_skip_proba_; // Note: we always use skip_proba for now.
+ int nb_skip_; // number of skipped blocks
+} VP8Proba;
+
+// Filter parameters. Not actually used in the code (we don't perform
+// the in-loop filtering), but filled from user's config
+typedef struct {
+ int simple_; // filtering type: 0=complex, 1=simple
+ int level_; // base filter level [0..63]
+ int sharpness_; // [0..7]
+ int i4x4_lf_delta_; // delta filter level for i4x4 relative to i16x16
+} VP8FilterHeader;
+
+//------------------------------------------------------------------------------
+// Informations about the macroblocks.
+
+typedef struct {
+ // block type
+ unsigned int type_:2; // 0=i4x4, 1=i16x16
+ unsigned int uv_mode_:2;
+ unsigned int skip_:1;
+ unsigned int segment_:2;
+ uint8_t alpha_; // quantization-susceptibility
+} VP8MBInfo;
+
+typedef struct VP8Matrix {
+ uint16_t q_[16]; // quantizer steps
+ uint16_t iq_[16]; // reciprocals, fixed point.
+ uint16_t bias_[16]; // rounding bias
+ uint16_t zthresh_[16]; // value under which a coefficient is zeroed
+ uint16_t sharpen_[16]; // frequency boosters for slight sharpening
+} VP8Matrix;
+
+typedef struct {
+ VP8Matrix y1_, y2_, uv_; // quantization matrices
+ int alpha_; // quant-susceptibility, range [-127,127]. Zero is neutral.
+ // Lower values indicate a lower risk of blurriness.
+ int beta_; // filter-susceptibility, range [0,255].
+ int quant_; // final segment quantizer.
+ int fstrength_; // final in-loop filtering strength
+ // reactivities
+ int lambda_i16_, lambda_i4_, lambda_uv_;
+ int lambda_mode_, lambda_trellis_, tlambda_;
+ int lambda_trellis_i16_, lambda_trellis_i4_, lambda_trellis_uv_;
+} VP8SegmentInfo;
+
+// Handy transcient struct to accumulate score and info during RD-optimization
+// and mode evaluation.
+typedef struct {
+ score_t D, SD, R, score; // Distortion, spectral distortion, rate, score.
+ int16_t y_dc_levels[16]; // Quantized levels for luma-DC, luma-AC, chroma.
+ int16_t y_ac_levels[16][16];
+ int16_t uv_levels[4 + 4][16];
+ int mode_i16; // mode number for intra16 prediction
+ uint8_t modes_i4[16]; // mode numbers for intra4 predictions
+ int mode_uv; // mode number of chroma prediction
+ uint32_t nz; // non-zero blocks
+} VP8ModeScore;
+
+// Iterator structure to iterate through macroblocks, pointing to the
+// right neighbouring data (samples, predictions, contexts, ...)
+typedef struct {
+ int x_, y_; // current macroblock
+ int y_offset_, uv_offset_; // offset to the luma / chroma planes
+ int y_stride_, uv_stride_; // respective strides
+ uint8_t* yuv_in_; // borrowed from enc_ (for now)
+ uint8_t* yuv_out_; // ''
+ uint8_t* yuv_out2_; // ''
+ uint8_t* yuv_p_; // ''
+ VP8Encoder* enc_; // back-pointer
+ VP8MBInfo* mb_; // current macroblock
+ VP8BitWriter* bw_; // current bit-writer
+ uint8_t* preds_; // intra mode predictors (4x4 blocks)
+ uint32_t* nz_; // non-zero pattern
+ uint8_t i4_boundary_[37]; // 32+5 boundary samples needed by intra4x4
+ uint8_t* i4_top_; // pointer to the current top boundary sample
+ int i4_; // current intra4x4 mode being tested
+ int top_nz_[9]; // top-non-zero context.
+ int left_nz_[9]; // left-non-zero. left_nz[8] is independent.
+ uint64_t bit_count_[4][3]; // bit counters for coded levels.
+ uint64_t luma_bits_; // macroblock bit-cost for luma
+ uint64_t uv_bits_; // macroblock bit-cost for chroma
+ LFStats* lf_stats_; // filter stats (borrowed from enc_)
+ int do_trellis_; // if true, perform extra level optimisation
+ int done_; // true when scan is finished
+ int percent0_; // saved initial progress percent
+} VP8EncIterator;
+
+ // in iterator.c
+// must be called first.
+void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it);
+// restart a scan.
+void VP8IteratorReset(VP8EncIterator* const it);
+// import samples from source
+void VP8IteratorImport(const VP8EncIterator* const it);
+// export decimated samples
+void VP8IteratorExport(const VP8EncIterator* const it);
+// go to next macroblock. Returns !done_. If *block_to_save is non-null, will
+// save the boundary values to top_/left_ arrays. block_to_save can be
+// it->yuv_out_ or it->yuv_in_.
+int VP8IteratorNext(VP8EncIterator* const it,
+ const uint8_t* const block_to_save);
+// Report progression based on macroblock rows. Return 0 for user-abort request.
+int VP8IteratorProgress(const VP8EncIterator* const it,
+ int final_delta_percent);
+// Intra4x4 iterations
+void VP8IteratorStartI4(VP8EncIterator* const it);
+// returns true if not done.
+int VP8IteratorRotateI4(VP8EncIterator* const it,
+ const uint8_t* const yuv_out);
+
+// Non-zero context setup/teardown
+void VP8IteratorNzToBytes(VP8EncIterator* const it);
+void VP8IteratorBytesToNz(VP8EncIterator* const it);
+
+// Helper functions to set mode properties
+void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode);
+void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes);
+void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode);
+void VP8SetSkip(const VP8EncIterator* const it, int skip);
+void VP8SetSegment(const VP8EncIterator* const it, int segment);
+
+//------------------------------------------------------------------------------
+// Paginated token buffer
+
+// WIP: #define USE_TOKEN_BUFFER
+
+#ifdef USE_TOKEN_BUFFER
+
+#define MAX_NUM_TOKEN 2048
+
+typedef struct VP8Tokens VP8Tokens;
+struct VP8Tokens {
+ uint16_t tokens_[MAX_NUM_TOKEN]; // bit#15: bit, bits 0..14: slot
+ int left_;
+ VP8Tokens* next_;
+};
+
+typedef struct {
+ VP8Tokens* rows_;
+ uint16_t* tokens_; // set to (*last_)->tokens_
+ VP8Tokens** last_;
+ int left_;
+ int error_; // true in case of malloc error
+} VP8TBuffer;
+
+void VP8TBufferInit(VP8TBuffer* const b); // initialize an empty buffer
+int VP8TBufferNewPage(VP8TBuffer* const b); // allocate a new page
+void VP8TBufferClear(VP8TBuffer* const b); // de-allocate memory
+
+int VP8EmitTokens(const VP8TBuffer* const b, VP8BitWriter* const bw,
+ const uint8_t* const probas);
+
+static WEBP_INLINE int VP8AddToken(VP8TBuffer* const b,
+ int bit, int proba_idx) {
+ if (b->left_ > 0 || VP8TBufferNewPage(b)) {
+ const int slot = --b->left_;
+ b->tokens_[slot] = (bit << 15) | proba_idx;
+ }
+ return bit;
+}
+
+#endif // USE_TOKEN_BUFFER
+
+//------------------------------------------------------------------------------
+// VP8Encoder
+
+struct VP8Encoder {
+ const WebPConfig* config_; // user configuration and parameters
+ WebPPicture* pic_; // input / output picture
+
+ // headers
+ VP8FilterHeader filter_hdr_; // filtering information
+ VP8SegmentHeader segment_hdr_; // segment information
+
+ int profile_; // VP8's profile, deduced from Config.
+
+ // dimension, in macroblock units.
+ int mb_w_, mb_h_;
+ int preds_w_; // stride of the *preds_ prediction plane (=4*mb_w + 1)
+
+ // number of partitions (1, 2, 4 or 8 = MAX_NUM_PARTITIONS)
+ int num_parts_;
+
+ // per-partition boolean decoders.
+ VP8BitWriter bw_; // part0
+ VP8BitWriter parts_[MAX_NUM_PARTITIONS]; // token partitions
+
+ int percent_; // for progress
+
+ // transparency blob
+ int has_alpha_;
+ uint8_t* alpha_data_; // non-NULL if transparency is present
+ uint32_t alpha_data_size_;
+
+ // enhancement layer
+ int use_layer_;
+ VP8BitWriter layer_bw_;
+ uint8_t* layer_data_;
+ size_t layer_data_size_;
+
+ // quantization info (one set of DC/AC dequant factor per segment)
+ VP8SegmentInfo dqm_[NUM_MB_SEGMENTS];
+ int base_quant_; // nominal quantizer value. Only used
+ // for relative coding of segments' quant.
+ int uv_alpha_; // U/V quantization susceptibility
+ // global offset of quantizers, shared by all segments
+ int dq_y1_dc_;
+ int dq_y2_dc_, dq_y2_ac_;
+ int dq_uv_dc_, dq_uv_ac_;
+
+ // probabilities and statistics
+ VP8Proba proba_;
+ uint64_t sse_[4]; // sum of Y/U/V/A squared errors for all macroblocks
+ uint64_t sse_count_; // pixel count for the sse_[] stats
+ int coded_size_;
+ int residual_bytes_[3][4];
+ int block_count_[3];
+
+ // quality/speed settings
+ int method_; // 0=fastest, 6=best/slowest.
+ int rd_opt_level_; // Deduced from method_.
+ int max_i4_header_bits_; // partition #0 safeness factor
+
+ // Memory
+ VP8MBInfo* mb_info_; // contextual macroblock infos (mb_w_ + 1)
+ uint8_t* preds_; // predictions modes: (4*mb_w+1) * (4*mb_h+1)
+ uint32_t* nz_; // non-zero bit context: mb_w+1
+ uint8_t* yuv_in_; // input samples
+ uint8_t* yuv_out_; // output samples
+ uint8_t* yuv_out2_; // secondary scratch out-buffer. swapped with yuv_out_.
+ uint8_t* yuv_p_; // scratch buffer for prediction
+ uint8_t *y_top_; // top luma samples.
+ uint8_t *uv_top_; // top u/v samples.
+ // U and V are packed into 16 pixels (8 U + 8 V)
+ uint8_t *y_left_; // left luma samples (adressable from index -1 to 15).
+ uint8_t *u_left_; // left u samples (adressable from index -1 to 7)
+ uint8_t *v_left_; // left v samples (adressable from index -1 to 7)
+
+ LFStats *lf_stats_; // autofilter stats (if NULL, autofilter is off)
+};
+
+//------------------------------------------------------------------------------
+// internal functions. Not public.
+
+ // in tree.c
+extern const uint8_t VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS];
+extern const uint8_t
+ VP8CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS];
+// Reset the token probabilities to their initial (default) values
+void VP8DefaultProbas(VP8Encoder* const enc);
+// Write the token probabilities
+void VP8WriteProbas(VP8BitWriter* const bw, const VP8Proba* const probas);
+// Writes the partition #0 modes (that is: all intra modes)
+void VP8CodeIntraModes(VP8Encoder* const enc);
+
+ // in syntax.c
+// Generates the final bitstream by coding the partition0 and headers,
+// and appending an assembly of all the pre-coded token partitions.
+// Return true if everything is ok.
+int VP8EncWrite(VP8Encoder* const enc);
+// Release memory allocated for bit-writing in VP8EncLoop & seq.
+void VP8EncFreeBitWriters(VP8Encoder* const enc);
+
+ // in frame.c
+extern const uint8_t VP8EncBands[16 + 1];
+// Form all the four Intra16x16 predictions in the yuv_p_ cache
+void VP8MakeLuma16Preds(const VP8EncIterator* const it);
+// Form all the four Chroma8x8 predictions in the yuv_p_ cache
+void VP8MakeChroma8Preds(const VP8EncIterator* const it);
+// Form all the ten Intra4x4 predictions in the yuv_p_ cache
+// for the 4x4 block it->i4_
+void VP8MakeIntra4Preds(const VP8EncIterator* const it);
+// Rate calculation
+int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd);
+int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]);
+int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd);
+// Main stat / coding passes
+int VP8EncLoop(VP8Encoder* const enc);
+int VP8StatLoop(VP8Encoder* const enc);
+
+ // in webpenc.c
+// Assign an error code to a picture. Return false for convenience.
+int WebPEncodingSetError(const WebPPicture* const pic, WebPEncodingError error);
+int WebPReportProgress(const WebPPicture* const pic,
+ int percent, int* const percent_store);
+
+ // in analysis.c
+// Main analysis loop. Decides the segmentations and complexity.
+// Assigns a first guess for Intra16 and uvmode_ prediction modes.
+int VP8EncAnalyze(VP8Encoder* const enc);
+
+ // in quant.c
+// Sets up segment's quantization values, base_quant_ and filter strengths.
+void VP8SetSegmentParams(VP8Encoder* const enc, float quality);
+// Pick best modes and fills the levels. Returns true if skipped.
+int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, int rd_opt);
+
+ // in alpha.c
+void VP8EncInitAlpha(VP8Encoder* const enc); // initialize alpha compression
+int VP8EncFinishAlpha(VP8Encoder* const enc); // finalize compressed data
+void VP8EncDeleteAlpha(VP8Encoder* const enc); // delete compressed data
+
+ // in layer.c
+void VP8EncInitLayer(VP8Encoder* const enc); // init everything
+void VP8EncCodeLayerBlock(VP8EncIterator* it); // code one more macroblock
+int VP8EncFinishLayer(VP8Encoder* const enc); // finalize coding
+void VP8EncDeleteLayer(VP8Encoder* enc); // reclaim memory
+
+ // in filter.c
+
+// SSIM utils
+typedef struct {
+ double w, xm, ym, xxm, xym, yym;
+} DistoStats;
+void VP8SSIMAddStats(const DistoStats* const src, DistoStats* const dst);
+void VP8SSIMAccumulatePlane(const uint8_t* src1, int stride1,
+ const uint8_t* src2, int stride2,
+ int W, int H, DistoStats* const stats);
+double VP8SSIMGet(const DistoStats* const stats);
+double VP8SSIMGetSquaredError(const DistoStats* const stats);
+
+// autofilter
+void VP8InitFilter(VP8EncIterator* const it);
+void VP8StoreFilterStats(VP8EncIterator* const it);
+void VP8AdjustFilterStrength(VP8EncIterator* const it);
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_ENC_VP8ENCI_H_ */
diff --git a/drivers/webpold/enc/vp8l.c b/drivers/webpold/enc/vp8l.c
new file mode 100644
index 0000000000..f4eb6e783f
--- /dev/null
+++ b/drivers/webpold/enc/vp8l.c
@@ -0,0 +1,1150 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// main entry for the lossless encoder.
+//
+// Author: Vikas Arora (vikaas.arora@gmail.com)
+//
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "./backward_references.h"
+#include "./vp8enci.h"
+#include "./vp8li.h"
+#include "../dsp/lossless.h"
+#include "../utils/bit_writer.h"
+#include "../utils/huffman_encode.h"
+#include "../utils/utils.h"
+#include "../format_constants.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define PALETTE_KEY_RIGHT_SHIFT 22 // Key for 1K buffer.
+#define MAX_HUFF_IMAGE_SIZE (16 * 1024 * 1024)
+#define MAX_COLORS_FOR_GRAPH 64
+
+// -----------------------------------------------------------------------------
+// Palette
+
+static int CompareColors(const void* p1, const void* p2) {
+ const uint32_t a = *(const uint32_t*)p1;
+ const uint32_t b = *(const uint32_t*)p2;
+ return (a < b) ? -1 : (a > b) ? 1 : 0;
+}
+
+// If number of colors in the image is less than or equal to MAX_PALETTE_SIZE,
+// creates a palette and returns true, else returns false.
+static int AnalyzeAndCreatePalette(const WebPPicture* const pic,
+ uint32_t palette[MAX_PALETTE_SIZE],
+ int* const palette_size) {
+ int i, x, y, key;
+ int num_colors = 0;
+ uint8_t in_use[MAX_PALETTE_SIZE * 4] = { 0 };
+ uint32_t colors[MAX_PALETTE_SIZE * 4];
+ static const uint32_t kHashMul = 0x1e35a7bd;
+ const uint32_t* argb = pic->argb;
+ const int width = pic->width;
+ const int height = pic->height;
+ uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0]
+
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ if (argb[x] == last_pix) {
+ continue;
+ }
+ last_pix = argb[x];
+ key = (kHashMul * last_pix) >> PALETTE_KEY_RIGHT_SHIFT;
+ while (1) {
+ if (!in_use[key]) {
+ colors[key] = last_pix;
+ in_use[key] = 1;
+ ++num_colors;
+ if (num_colors > MAX_PALETTE_SIZE) {
+ return 0;
+ }
+ break;
+ } else if (colors[key] == last_pix) {
+ // The color is already there.
+ break;
+ } else {
+ // Some other color sits there.
+ // Do linear conflict resolution.
+ ++key;
+ key &= (MAX_PALETTE_SIZE * 4 - 1); // key mask for 1K buffer.
+ }
+ }
+ }
+ argb += pic->argb_stride;
+ }
+
+ // TODO(skal): could we reuse in_use[] to speed up ApplyPalette()?
+ num_colors = 0;
+ for (i = 0; i < (int)(sizeof(in_use) / sizeof(in_use[0])); ++i) {
+ if (in_use[i]) {
+ palette[num_colors] = colors[i];
+ ++num_colors;
+ }
+ }
+
+ qsort(palette, num_colors, sizeof(*palette), CompareColors);
+ *palette_size = num_colors;
+ return 1;
+}
+
+static int AnalyzeEntropy(const uint32_t* argb,
+ int width, int height, int argb_stride,
+ double* const nonpredicted_bits,
+ double* const predicted_bits) {
+ int x, y;
+ const uint32_t* last_line = NULL;
+ uint32_t last_pix = argb[0]; // so we're sure that pix_diff == 0
+
+ VP8LHistogram* nonpredicted = NULL;
+ VP8LHistogram* predicted =
+ (VP8LHistogram*)malloc(2 * sizeof(*predicted));
+ if (predicted == NULL) return 0;
+ nonpredicted = predicted + 1;
+
+ VP8LHistogramInit(predicted, 0);
+ VP8LHistogramInit(nonpredicted, 0);
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ const uint32_t pix = argb[x];
+ const uint32_t pix_diff = VP8LSubPixels(pix, last_pix);
+ if (pix_diff == 0) continue;
+ if (last_line != NULL && pix == last_line[x]) {
+ continue;
+ }
+ last_pix = pix;
+ {
+ const PixOrCopy pix_token = PixOrCopyCreateLiteral(pix);
+ const PixOrCopy pix_diff_token = PixOrCopyCreateLiteral(pix_diff);
+ VP8LHistogramAddSinglePixOrCopy(nonpredicted, &pix_token);
+ VP8LHistogramAddSinglePixOrCopy(predicted, &pix_diff_token);
+ }
+ }
+ last_line = argb;
+ argb += argb_stride;
+ }
+ *nonpredicted_bits = VP8LHistogramEstimateBitsBulk(nonpredicted);
+ *predicted_bits = VP8LHistogramEstimateBitsBulk(predicted);
+ free(predicted);
+ return 1;
+}
+
+static int VP8LEncAnalyze(VP8LEncoder* const enc, WebPImageHint image_hint) {
+ const WebPPicture* const pic = enc->pic_;
+ assert(pic != NULL && pic->argb != NULL);
+
+ enc->use_palette_ =
+ AnalyzeAndCreatePalette(pic, enc->palette_, &enc->palette_size_);
+
+ if (image_hint == WEBP_HINT_GRAPH) {
+ if (enc->use_palette_ && enc->palette_size_ < MAX_COLORS_FOR_GRAPH) {
+ enc->use_palette_ = 0;
+ }
+ }
+
+ if (!enc->use_palette_) {
+ if (image_hint == WEBP_HINT_PHOTO) {
+ enc->use_predict_ = 1;
+ enc->use_cross_color_ = 1;
+ } else {
+ double non_pred_entropy, pred_entropy;
+ if (!AnalyzeEntropy(pic->argb, pic->width, pic->height, pic->argb_stride,
+ &non_pred_entropy, &pred_entropy)) {
+ return 0;
+ }
+ if (pred_entropy < 0.95 * non_pred_entropy) {
+ enc->use_predict_ = 1;
+ // TODO(vikasa): Observed some correlation of cross_color transform with
+ // predict. Need to investigate this further and add separate heuristic
+ // for setting use_cross_color flag.
+ enc->use_cross_color_ = 1;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static int GetHuffBitLengthsAndCodes(
+ const VP8LHistogramSet* const histogram_image,
+ HuffmanTreeCode* const huffman_codes) {
+ int i, k;
+ int ok = 1;
+ uint64_t total_length_size = 0;
+ uint8_t* mem_buf = NULL;
+ const int histogram_image_size = histogram_image->size;
+
+ // Iterate over all histograms and get the aggregate number of codes used.
+ for (i = 0; i < histogram_image_size; ++i) {
+ const VP8LHistogram* const histo = histogram_image->histograms[i];
+ HuffmanTreeCode* const codes = &huffman_codes[5 * i];
+ for (k = 0; k < 5; ++k) {
+ const int num_symbols = (k == 0) ? VP8LHistogramNumCodes(histo)
+ : (k == 4) ? NUM_DISTANCE_CODES
+ : 256;
+ codes[k].num_symbols = num_symbols;
+ total_length_size += num_symbols;
+ }
+ }
+
+ // Allocate and Set Huffman codes.
+ {
+ uint16_t* codes;
+ uint8_t* lengths;
+ mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size,
+ sizeof(*lengths) + sizeof(*codes));
+ if (mem_buf == NULL) {
+ ok = 0;
+ goto End;
+ }
+ codes = (uint16_t*)mem_buf;
+ lengths = (uint8_t*)&codes[total_length_size];
+ for (i = 0; i < 5 * histogram_image_size; ++i) {
+ const int bit_length = huffman_codes[i].num_symbols;
+ huffman_codes[i].codes = codes;
+ huffman_codes[i].code_lengths = lengths;
+ codes += bit_length;
+ lengths += bit_length;
+ }
+ }
+
+ // Create Huffman trees.
+ for (i = 0; i < histogram_image_size; ++i) {
+ HuffmanTreeCode* const codes = &huffman_codes[5 * i];
+ VP8LHistogram* const histo = histogram_image->histograms[i];
+ ok = ok && VP8LCreateHuffmanTree(histo->literal_, 15, codes + 0);
+ ok = ok && VP8LCreateHuffmanTree(histo->red_, 15, codes + 1);
+ ok = ok && VP8LCreateHuffmanTree(histo->blue_, 15, codes + 2);
+ ok = ok && VP8LCreateHuffmanTree(histo->alpha_, 15, codes + 3);
+ ok = ok && VP8LCreateHuffmanTree(histo->distance_, 15, codes + 4);
+ }
+
+ End:
+ if (!ok) free(mem_buf);
+ return ok;
+}
+
+static void StoreHuffmanTreeOfHuffmanTreeToBitMask(
+ VP8LBitWriter* const bw, const uint8_t* code_length_bitdepth) {
+ // RFC 1951 will calm you down if you are worried about this funny sequence.
+ // This sequence is tuned from that, but more weighted for lower symbol count,
+ // and more spiking histograms.
+ static const uint8_t kStorageOrder[CODE_LENGTH_CODES] = {
+ 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+ };
+ int i;
+ // Throw away trailing zeros:
+ int codes_to_store = CODE_LENGTH_CODES;
+ for (; codes_to_store > 4; --codes_to_store) {
+ if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) {
+ break;
+ }
+ }
+ VP8LWriteBits(bw, 4, codes_to_store - 4);
+ for (i = 0; i < codes_to_store; ++i) {
+ VP8LWriteBits(bw, 3, code_length_bitdepth[kStorageOrder[i]]);
+ }
+}
+
+static void ClearHuffmanTreeIfOnlyOneSymbol(
+ HuffmanTreeCode* const huffman_code) {
+ int k;
+ int count = 0;
+ for (k = 0; k < huffman_code->num_symbols; ++k) {
+ if (huffman_code->code_lengths[k] != 0) {
+ ++count;
+ if (count > 1) return;
+ }
+ }
+ for (k = 0; k < huffman_code->num_symbols; ++k) {
+ huffman_code->code_lengths[k] = 0;
+ huffman_code->codes[k] = 0;
+ }
+}
+
+static void StoreHuffmanTreeToBitMask(
+ VP8LBitWriter* const bw,
+ const HuffmanTreeToken* const tokens, const int num_tokens,
+ const HuffmanTreeCode* const huffman_code) {
+ int i;
+ for (i = 0; i < num_tokens; ++i) {
+ const int ix = tokens[i].code;
+ const int extra_bits = tokens[i].extra_bits;
+ VP8LWriteBits(bw, huffman_code->code_lengths[ix], huffman_code->codes[ix]);
+ switch (ix) {
+ case 16:
+ VP8LWriteBits(bw, 2, extra_bits);
+ break;
+ case 17:
+ VP8LWriteBits(bw, 3, extra_bits);
+ break;
+ case 18:
+ VP8LWriteBits(bw, 7, extra_bits);
+ break;
+ }
+ }
+}
+
+static int StoreFullHuffmanCode(VP8LBitWriter* const bw,
+ const HuffmanTreeCode* const tree) {
+ int ok = 0;
+ uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 };
+ uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 };
+ const int max_tokens = tree->num_symbols;
+ int num_tokens;
+ HuffmanTreeCode huffman_code;
+ HuffmanTreeToken* const tokens =
+ (HuffmanTreeToken*)WebPSafeMalloc((uint64_t)max_tokens, sizeof(*tokens));
+ if (tokens == NULL) return 0;
+
+ huffman_code.num_symbols = CODE_LENGTH_CODES;
+ huffman_code.code_lengths = code_length_bitdepth;
+ huffman_code.codes = code_length_bitdepth_symbols;
+
+ VP8LWriteBits(bw, 1, 0);
+ num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens);
+ {
+ int histogram[CODE_LENGTH_CODES] = { 0 };
+ int i;
+ for (i = 0; i < num_tokens; ++i) {
+ ++histogram[tokens[i].code];
+ }
+
+ if (!VP8LCreateHuffmanTree(histogram, 7, &huffman_code)) {
+ goto End;
+ }
+ }
+
+ StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth);
+ ClearHuffmanTreeIfOnlyOneSymbol(&huffman_code);
+ {
+ int trailing_zero_bits = 0;
+ int trimmed_length = num_tokens;
+ int write_trimmed_length;
+ int length;
+ int i = num_tokens;
+ while (i-- > 0) {
+ const int ix = tokens[i].code;
+ if (ix == 0 || ix == 17 || ix == 18) {
+ --trimmed_length; // discount trailing zeros
+ trailing_zero_bits += code_length_bitdepth[ix];
+ if (ix == 17) {
+ trailing_zero_bits += 3;
+ } else if (ix == 18) {
+ trailing_zero_bits += 7;
+ }
+ } else {
+ break;
+ }
+ }
+ write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12);
+ length = write_trimmed_length ? trimmed_length : num_tokens;
+ VP8LWriteBits(bw, 1, write_trimmed_length);
+ if (write_trimmed_length) {
+ const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1);
+ const int nbitpairs = (nbits == 0) ? 1 : (nbits + 1) / 2;
+ VP8LWriteBits(bw, 3, nbitpairs - 1);
+ assert(trimmed_length >= 2);
+ VP8LWriteBits(bw, nbitpairs * 2, trimmed_length - 2);
+ }
+ StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code);
+ }
+ ok = 1;
+ End:
+ free(tokens);
+ return ok;
+}
+
+static int StoreHuffmanCode(VP8LBitWriter* const bw,
+ const HuffmanTreeCode* const huffman_code) {
+ int i;
+ int count = 0;
+ int symbols[2] = { 0, 0 };
+ const int kMaxBits = 8;
+ const int kMaxSymbol = 1 << kMaxBits;
+
+ // Check whether it's a small tree.
+ for (i = 0; i < huffman_code->num_symbols && count < 3; ++i) {
+ if (huffman_code->code_lengths[i] != 0) {
+ if (count < 2) symbols[count] = i;
+ ++count;
+ }
+ }
+
+ if (count == 0) { // emit minimal tree for empty cases
+ // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0
+ VP8LWriteBits(bw, 4, 0x01);
+ return 1;
+ } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) {
+ VP8LWriteBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols.
+ VP8LWriteBits(bw, 1, count - 1);
+ if (symbols[0] <= 1) {
+ VP8LWriteBits(bw, 1, 0); // Code bit for small (1 bit) symbol value.
+ VP8LWriteBits(bw, 1, symbols[0]);
+ } else {
+ VP8LWriteBits(bw, 1, 1);
+ VP8LWriteBits(bw, 8, symbols[0]);
+ }
+ if (count == 2) {
+ VP8LWriteBits(bw, 8, symbols[1]);
+ }
+ return 1;
+ } else {
+ return StoreFullHuffmanCode(bw, huffman_code);
+ }
+}
+
+static void WriteHuffmanCode(VP8LBitWriter* const bw,
+ const HuffmanTreeCode* const code, int index) {
+ const int depth = code->code_lengths[index];
+ const int symbol = code->codes[index];
+ VP8LWriteBits(bw, depth, symbol);
+}
+
+static void StoreImageToBitMask(
+ VP8LBitWriter* const bw, int width, int histo_bits,
+ const VP8LBackwardRefs* const refs,
+ const uint16_t* histogram_symbols,
+ const HuffmanTreeCode* const huffman_codes) {
+ // x and y trace the position in the image.
+ int x = 0;
+ int y = 0;
+ const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1;
+ int i;
+ for (i = 0; i < refs->size; ++i) {
+ const PixOrCopy* const v = &refs->refs[i];
+ const int histogram_ix = histogram_symbols[histo_bits ?
+ (y >> histo_bits) * histo_xsize +
+ (x >> histo_bits) : 0];
+ const HuffmanTreeCode* const codes = huffman_codes + 5 * histogram_ix;
+ if (PixOrCopyIsCacheIdx(v)) {
+ const int code = PixOrCopyCacheIdx(v);
+ const int literal_ix = 256 + NUM_LENGTH_CODES + code;
+ WriteHuffmanCode(bw, codes, literal_ix);
+ } else if (PixOrCopyIsLiteral(v)) {
+ static const int order[] = { 1, 2, 0, 3 };
+ int k;
+ for (k = 0; k < 4; ++k) {
+ const int code = PixOrCopyLiteral(v, order[k]);
+ WriteHuffmanCode(bw, codes + k, code);
+ }
+ } else {
+ int bits, n_bits;
+ int code, distance;
+
+ PrefixEncode(v->len, &code, &n_bits, &bits);
+ WriteHuffmanCode(bw, codes, 256 + code);
+ VP8LWriteBits(bw, n_bits, bits);
+
+ distance = PixOrCopyDistance(v);
+ PrefixEncode(distance, &code, &n_bits, &bits);
+ WriteHuffmanCode(bw, codes + 4, code);
+ VP8LWriteBits(bw, n_bits, bits);
+ }
+ x += PixOrCopyLength(v);
+ while (x >= width) {
+ x -= width;
+ ++y;
+ }
+ }
+}
+
+// Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31
+static int EncodeImageNoHuffman(VP8LBitWriter* const bw,
+ const uint32_t* const argb,
+ int width, int height, int quality) {
+ int i;
+ int ok = 0;
+ VP8LBackwardRefs refs;
+ HuffmanTreeCode huffman_codes[5] = { { 0, NULL, NULL } };
+ const uint16_t histogram_symbols[1] = { 0 }; // only one tree, one symbol
+ VP8LHistogramSet* const histogram_image = VP8LAllocateHistogramSet(1, 0);
+ if (histogram_image == NULL) return 0;
+
+ // Calculate backward references from ARGB image.
+ if (!VP8LGetBackwardReferences(width, height, argb, quality, 0, 1, &refs)) {
+ goto Error;
+ }
+ // Build histogram image and symbols from backward references.
+ VP8LHistogramStoreRefs(&refs, histogram_image->histograms[0]);
+
+ // Create Huffman bit lengths and codes for each histogram image.
+ assert(histogram_image->size == 1);
+ if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
+ goto Error;
+ }
+
+ // No color cache, no Huffman image.
+ VP8LWriteBits(bw, 1, 0);
+
+ // Store Huffman codes.
+ for (i = 0; i < 5; ++i) {
+ HuffmanTreeCode* const codes = &huffman_codes[i];
+ if (!StoreHuffmanCode(bw, codes)) {
+ goto Error;
+ }
+ ClearHuffmanTreeIfOnlyOneSymbol(codes);
+ }
+
+ // Store actual literals.
+ StoreImageToBitMask(bw, width, 0, &refs, histogram_symbols, huffman_codes);
+ ok = 1;
+
+ Error:
+ free(histogram_image);
+ VP8LClearBackwardRefs(&refs);
+ free(huffman_codes[0].codes);
+ return ok;
+}
+
+static int EncodeImageInternal(VP8LBitWriter* const bw,
+ const uint32_t* const argb,
+ int width, int height, int quality,
+ int cache_bits, int histogram_bits) {
+ int ok = 0;
+ const int use_2d_locality = 1;
+ const int use_color_cache = (cache_bits > 0);
+ const uint32_t histogram_image_xysize =
+ VP8LSubSampleSize(width, histogram_bits) *
+ VP8LSubSampleSize(height, histogram_bits);
+ VP8LHistogramSet* histogram_image =
+ VP8LAllocateHistogramSet(histogram_image_xysize, 0);
+ int histogram_image_size = 0;
+ size_t bit_array_size = 0;
+ HuffmanTreeCode* huffman_codes = NULL;
+ VP8LBackwardRefs refs;
+ uint16_t* const histogram_symbols =
+ (uint16_t*)WebPSafeMalloc((uint64_t)histogram_image_xysize,
+ sizeof(*histogram_symbols));
+ assert(histogram_bits >= MIN_HUFFMAN_BITS);
+ assert(histogram_bits <= MAX_HUFFMAN_BITS);
+ if (histogram_image == NULL || histogram_symbols == NULL) goto Error;
+
+ // Calculate backward references from ARGB image.
+ if (!VP8LGetBackwardReferences(width, height, argb, quality, cache_bits,
+ use_2d_locality, &refs)) {
+ goto Error;
+ }
+ // Build histogram image and symbols from backward references.
+ if (!VP8LGetHistoImageSymbols(width, height, &refs,
+ quality, histogram_bits, cache_bits,
+ histogram_image,
+ histogram_symbols)) {
+ goto Error;
+ }
+ // Create Huffman bit lengths and codes for each histogram image.
+ histogram_image_size = histogram_image->size;
+ bit_array_size = 5 * histogram_image_size;
+ huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size,
+ sizeof(*huffman_codes));
+ if (huffman_codes == NULL ||
+ !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
+ goto Error;
+ }
+
+ // Color Cache parameters.
+ VP8LWriteBits(bw, 1, use_color_cache);
+ if (use_color_cache) {
+ VP8LWriteBits(bw, 4, cache_bits);
+ }
+
+ // Huffman image + meta huffman.
+ {
+ const int write_histogram_image = (histogram_image_size > 1);
+ VP8LWriteBits(bw, 1, write_histogram_image);
+ if (write_histogram_image) {
+ uint32_t* const histogram_argb =
+ (uint32_t*)WebPSafeMalloc((uint64_t)histogram_image_xysize,
+ sizeof(*histogram_argb));
+ int max_index = 0;
+ uint32_t i;
+ if (histogram_argb == NULL) goto Error;
+ for (i = 0; i < histogram_image_xysize; ++i) {
+ const int index = histogram_symbols[i] & 0xffff;
+ histogram_argb[i] = 0xff000000 | (index << 8);
+ if (index >= max_index) {
+ max_index = index + 1;
+ }
+ }
+ histogram_image_size = max_index;
+
+ VP8LWriteBits(bw, 3, histogram_bits - 2);
+ ok = EncodeImageNoHuffman(bw, histogram_argb,
+ VP8LSubSampleSize(width, histogram_bits),
+ VP8LSubSampleSize(height, histogram_bits),
+ quality);
+ free(histogram_argb);
+ if (!ok) goto Error;
+ }
+ }
+
+ // Store Huffman codes.
+ {
+ int i;
+ for (i = 0; i < 5 * histogram_image_size; ++i) {
+ HuffmanTreeCode* const codes = &huffman_codes[i];
+ if (!StoreHuffmanCode(bw, codes)) goto Error;
+ ClearHuffmanTreeIfOnlyOneSymbol(codes);
+ }
+ }
+ // Free combined histograms.
+ free(histogram_image);
+ histogram_image = NULL;
+
+ // Store actual literals.
+ StoreImageToBitMask(bw, width, histogram_bits, &refs,
+ histogram_symbols, huffman_codes);
+ ok = 1;
+
+ Error:
+ if (!ok) free(histogram_image);
+
+ VP8LClearBackwardRefs(&refs);
+ if (huffman_codes != NULL) {
+ free(huffman_codes->codes);
+ free(huffman_codes);
+ }
+ free(histogram_symbols);
+ return ok;
+}
+
+// -----------------------------------------------------------------------------
+// Transforms
+
+// Check if it would be a good idea to subtract green from red and blue. We
+// only impact entropy in red/blue components, don't bother to look at others.
+static int EvalAndApplySubtractGreen(VP8LEncoder* const enc,
+ int width, int height,
+ VP8LBitWriter* const bw) {
+ if (!enc->use_palette_) {
+ int i;
+ const uint32_t* const argb = enc->argb_;
+ double bit_cost_before, bit_cost_after;
+ VP8LHistogram* const histo = (VP8LHistogram*)malloc(sizeof(*histo));
+ if (histo == NULL) return 0;
+
+ VP8LHistogramInit(histo, 1);
+ for (i = 0; i < width * height; ++i) {
+ const uint32_t c = argb[i];
+ ++histo->red_[(c >> 16) & 0xff];
+ ++histo->blue_[(c >> 0) & 0xff];
+ }
+ bit_cost_before = VP8LHistogramEstimateBits(histo);
+
+ VP8LHistogramInit(histo, 1);
+ for (i = 0; i < width * height; ++i) {
+ const uint32_t c = argb[i];
+ const int green = (c >> 8) & 0xff;
+ ++histo->red_[((c >> 16) - green) & 0xff];
+ ++histo->blue_[((c >> 0) - green) & 0xff];
+ }
+ bit_cost_after = VP8LHistogramEstimateBits(histo);
+ free(histo);
+
+ // Check if subtracting green yields low entropy.
+ enc->use_subtract_green_ = (bit_cost_after < bit_cost_before);
+ if (enc->use_subtract_green_) {
+ VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
+ VP8LWriteBits(bw, 2, SUBTRACT_GREEN);
+ VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height);
+ }
+ }
+ return 1;
+}
+
+static int ApplyPredictFilter(const VP8LEncoder* const enc,
+ int width, int height, int quality,
+ VP8LBitWriter* const bw) {
+ const int pred_bits = enc->transform_bits_;
+ const int transform_width = VP8LSubSampleSize(width, pred_bits);
+ const int transform_height = VP8LSubSampleSize(height, pred_bits);
+
+ VP8LResidualImage(width, height, pred_bits, enc->argb_, enc->argb_scratch_,
+ enc->transform_data_);
+ VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
+ VP8LWriteBits(bw, 2, PREDICTOR_TRANSFORM);
+ assert(pred_bits >= 2);
+ VP8LWriteBits(bw, 3, pred_bits - 2);
+ if (!EncodeImageNoHuffman(bw, enc->transform_data_,
+ transform_width, transform_height, quality)) {
+ return 0;
+ }
+ return 1;
+}
+
+static int ApplyCrossColorFilter(const VP8LEncoder* const enc,
+ int width, int height, int quality,
+ VP8LBitWriter* const bw) {
+ const int ccolor_transform_bits = enc->transform_bits_;
+ const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits);
+ const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits);
+ const int step = (quality == 0) ? 32 : 8;
+
+ VP8LColorSpaceTransform(width, height, ccolor_transform_bits, step,
+ enc->argb_, enc->transform_data_);
+ VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
+ VP8LWriteBits(bw, 2, CROSS_COLOR_TRANSFORM);
+ assert(ccolor_transform_bits >= 2);
+ VP8LWriteBits(bw, 3, ccolor_transform_bits - 2);
+ if (!EncodeImageNoHuffman(bw, enc->transform_data_,
+ transform_width, transform_height, quality)) {
+ return 0;
+ }
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+
+static void PutLE32(uint8_t* const data, uint32_t val) {
+ data[0] = (val >> 0) & 0xff;
+ data[1] = (val >> 8) & 0xff;
+ data[2] = (val >> 16) & 0xff;
+ data[3] = (val >> 24) & 0xff;
+}
+
+static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic,
+ size_t riff_size, size_t vp8l_size) {
+ uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = {
+ 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P',
+ 'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE,
+ };
+ PutLE32(riff + TAG_SIZE, (uint32_t)riff_size);
+ PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size);
+ if (!pic->writer(riff, sizeof(riff), pic)) {
+ return VP8_ENC_ERROR_BAD_WRITE;
+ }
+ return VP8_ENC_OK;
+}
+
+static int WriteImageSize(const WebPPicture* const pic,
+ VP8LBitWriter* const bw) {
+ const int width = pic->width - 1;
+ const int height = pic->height - 1;
+ assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION);
+
+ VP8LWriteBits(bw, VP8L_IMAGE_SIZE_BITS, width);
+ VP8LWriteBits(bw, VP8L_IMAGE_SIZE_BITS, height);
+ return !bw->error_;
+}
+
+static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) {
+ VP8LWriteBits(bw, 1, has_alpha);
+ VP8LWriteBits(bw, VP8L_VERSION_BITS, VP8L_VERSION);
+ return !bw->error_;
+}
+
+static WebPEncodingError WriteImage(const WebPPicture* const pic,
+ VP8LBitWriter* const bw,
+ size_t* const coded_size) {
+ WebPEncodingError err = VP8_ENC_OK;
+ const uint8_t* const webpll_data = VP8LBitWriterFinish(bw);
+ const size_t webpll_size = VP8LBitWriterNumBytes(bw);
+ const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size;
+ const size_t pad = vp8l_size & 1;
+ const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad;
+
+ err = WriteRiffHeader(pic, riff_size, vp8l_size);
+ if (err != VP8_ENC_OK) goto Error;
+
+ if (!pic->writer(webpll_data, webpll_size, pic)) {
+ err = VP8_ENC_ERROR_BAD_WRITE;
+ goto Error;
+ }
+
+ if (pad) {
+ const uint8_t pad_byte[1] = { 0 };
+ if (!pic->writer(pad_byte, 1, pic)) {
+ err = VP8_ENC_ERROR_BAD_WRITE;
+ goto Error;
+ }
+ }
+ *coded_size = CHUNK_HEADER_SIZE + riff_size;
+ return VP8_ENC_OK;
+
+ Error:
+ return err;
+}
+
+// -----------------------------------------------------------------------------
+
+// Allocates the memory for argb (W x H) buffer, 2 rows of context for
+// prediction and transform data.
+static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc,
+ int width, int height) {
+ WebPEncodingError err = VP8_ENC_OK;
+ const int tile_size = 1 << enc->transform_bits_;
+ const uint64_t image_size = width * height;
+ const uint64_t argb_scratch_size = tile_size * width + width;
+ const uint64_t transform_data_size =
+ (uint64_t)VP8LSubSampleSize(width, enc->transform_bits_) *
+ (uint64_t)VP8LSubSampleSize(height, enc->transform_bits_);
+ const uint64_t total_size =
+ image_size + argb_scratch_size + transform_data_size;
+ uint32_t* mem = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*mem));
+ if (mem == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+ enc->argb_ = mem;
+ mem += image_size;
+ enc->argb_scratch_ = mem;
+ mem += argb_scratch_size;
+ enc->transform_data_ = mem;
+ enc->current_width_ = width;
+
+ Error:
+ return err;
+}
+
+// Bundles multiple (2, 4 or 8) pixels into a single pixel.
+// Returns the new xsize.
+static void BundleColorMap(const WebPPicture* const pic,
+ int xbits, uint32_t* bundled_argb, int xs) {
+ int y;
+ const int bit_depth = 1 << (3 - xbits);
+ uint32_t code = 0;
+ const uint32_t* argb = pic->argb;
+ const int width = pic->width;
+ const int height = pic->height;
+
+ for (y = 0; y < height; ++y) {
+ int x;
+ for (x = 0; x < width; ++x) {
+ const int mask = (1 << xbits) - 1;
+ const int xsub = x & mask;
+ if (xsub == 0) {
+ code = 0;
+ }
+ // TODO(vikasa): simplify the bundling logic.
+ code |= (argb[x] & 0xff00) << (bit_depth * xsub);
+ bundled_argb[y * xs + (x >> xbits)] = 0xff000000 | code;
+ }
+ argb += pic->argb_stride;
+ }
+}
+
+// Note: Expects "enc->palette_" to be set properly.
+// Also, "enc->palette_" will be modified after this call and should not be used
+// later.
+static WebPEncodingError ApplyPalette(VP8LBitWriter* const bw,
+ VP8LEncoder* const enc, int quality) {
+ WebPEncodingError err = VP8_ENC_OK;
+ int i, x, y;
+ const WebPPicture* const pic = enc->pic_;
+ uint32_t* argb = pic->argb;
+ const int width = pic->width;
+ const int height = pic->height;
+ uint32_t* const palette = enc->palette_;
+ const int palette_size = enc->palette_size_;
+
+ // Replace each input pixel by corresponding palette index.
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ const uint32_t pix = argb[x];
+ for (i = 0; i < palette_size; ++i) {
+ if (pix == palette[i]) {
+ argb[x] = 0xff000000u | (i << 8);
+ break;
+ }
+ }
+ }
+ argb += pic->argb_stride;
+ }
+
+ // Save palette to bitstream.
+ VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
+ VP8LWriteBits(bw, 2, COLOR_INDEXING_TRANSFORM);
+ assert(palette_size >= 1);
+ VP8LWriteBits(bw, 8, palette_size - 1);
+ for (i = palette_size - 1; i >= 1; --i) {
+ palette[i] = VP8LSubPixels(palette[i], palette[i - 1]);
+ }
+ if (!EncodeImageNoHuffman(bw, palette, palette_size, 1, quality)) {
+ err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
+ goto Error;
+ }
+
+ if (palette_size <= 16) {
+ // Image can be packed (multiple pixels per uint32_t).
+ int xbits = 1;
+ if (palette_size <= 2) {
+ xbits = 3;
+ } else if (palette_size <= 4) {
+ xbits = 2;
+ }
+ err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height);
+ if (err != VP8_ENC_OK) goto Error;
+ BundleColorMap(pic, xbits, enc->argb_, enc->current_width_);
+ }
+
+ Error:
+ return err;
+}
+
+// -----------------------------------------------------------------------------
+
+static int GetHistoBits(const WebPConfig* const config,
+ const WebPPicture* const pic) {
+ const int width = pic->width;
+ const int height = pic->height;
+ const size_t hist_size = sizeof(VP8LHistogram);
+ // Make tile size a function of encoding method (Range: 0 to 6).
+ int histo_bits = 7 - config->method;
+ while (1) {
+ const size_t huff_image_size = VP8LSubSampleSize(width, histo_bits) *
+ VP8LSubSampleSize(height, histo_bits) *
+ hist_size;
+ if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break;
+ ++histo_bits;
+ }
+ return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS :
+ (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits;
+}
+
+static void InitEncParams(VP8LEncoder* const enc) {
+ const WebPConfig* const config = enc->config_;
+ const WebPPicture* const picture = enc->pic_;
+ const int method = config->method;
+ const float quality = config->quality;
+ enc->transform_bits_ = (method < 4) ? 5 : (method > 4) ? 3 : 4;
+ enc->histo_bits_ = GetHistoBits(config, picture);
+ enc->cache_bits_ = (quality <= 25.f) ? 0 : 7;
+}
+
+// -----------------------------------------------------------------------------
+// VP8LEncoder
+
+static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config,
+ const WebPPicture* const picture) {
+ VP8LEncoder* const enc = (VP8LEncoder*)calloc(1, sizeof(*enc));
+ if (enc == NULL) {
+ WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+ enc->config_ = config;
+ enc->pic_ = picture;
+ return enc;
+}
+
+static void VP8LEncoderDelete(VP8LEncoder* enc) {
+ free(enc->argb_);
+ free(enc);
+}
+
+// -----------------------------------------------------------------------------
+// Main call
+
+WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
+ const WebPPicture* const picture,
+ VP8LBitWriter* const bw) {
+ WebPEncodingError err = VP8_ENC_OK;
+ const int quality = (int)config->quality;
+ const int width = picture->width;
+ const int height = picture->height;
+ VP8LEncoder* const enc = VP8LEncoderNew(config, picture);
+ const size_t byte_position = VP8LBitWriterNumBytes(bw);
+
+ if (enc == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+
+ InitEncParams(enc);
+
+ // ---------------------------------------------------------------------------
+ // Analyze image (entropy, num_palettes etc)
+
+ if (!VP8LEncAnalyze(enc, config->image_hint)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+
+ if (enc->use_palette_) {
+ err = ApplyPalette(bw, enc, quality);
+ if (err != VP8_ENC_OK) goto Error;
+ // Color cache is disabled for palette.
+ enc->cache_bits_ = 0;
+ }
+
+ // In case image is not packed.
+ if (enc->argb_ == NULL) {
+ int y;
+ err = AllocateTransformBuffer(enc, width, height);
+ if (err != VP8_ENC_OK) goto Error;
+ for (y = 0; y < height; ++y) {
+ memcpy(enc->argb_ + y * width,
+ picture->argb + y * picture->argb_stride,
+ width * sizeof(*enc->argb_));
+ }
+ enc->current_width_ = width;
+ }
+
+ // ---------------------------------------------------------------------------
+ // Apply transforms and write transform data.
+
+ if (!EvalAndApplySubtractGreen(enc, enc->current_width_, height, bw)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+
+ if (enc->use_predict_) {
+ if (!ApplyPredictFilter(enc, enc->current_width_, height, quality, bw)) {
+ err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
+ goto Error;
+ }
+ }
+
+ if (enc->use_cross_color_) {
+ if (!ApplyCrossColorFilter(enc, enc->current_width_, height, quality, bw)) {
+ err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
+ goto Error;
+ }
+ }
+
+ VP8LWriteBits(bw, 1, !TRANSFORM_PRESENT); // No more transforms.
+
+ // ---------------------------------------------------------------------------
+ // Estimate the color cache size.
+
+ if (enc->cache_bits_ > 0) {
+ if (!VP8LCalculateEstimateForCacheSize(enc->argb_, enc->current_width_,
+ height, &enc->cache_bits_)) {
+ err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
+ goto Error;
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+ // Encode and write the transformed image.
+
+ if (!EncodeImageInternal(bw, enc->argb_, enc->current_width_, height,
+ quality, enc->cache_bits_, enc->histo_bits_)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+
+ if (picture->stats != NULL) {
+ WebPAuxStats* const stats = picture->stats;
+ stats->lossless_features = 0;
+ if (enc->use_predict_) stats->lossless_features |= 1;
+ if (enc->use_cross_color_) stats->lossless_features |= 2;
+ if (enc->use_subtract_green_) stats->lossless_features |= 4;
+ if (enc->use_palette_) stats->lossless_features |= 8;
+ stats->histogram_bits = enc->histo_bits_;
+ stats->transform_bits = enc->transform_bits_;
+ stats->cache_bits = enc->cache_bits_;
+ stats->palette_size = enc->palette_size_;
+ stats->lossless_size = (int)(VP8LBitWriterNumBytes(bw) - byte_position);
+ }
+
+ Error:
+ VP8LEncoderDelete(enc);
+ return err;
+}
+
+int VP8LEncodeImage(const WebPConfig* const config,
+ const WebPPicture* const picture) {
+ int width, height;
+ int has_alpha;
+ size_t coded_size;
+ int percent = 0;
+ WebPEncodingError err = VP8_ENC_OK;
+ VP8LBitWriter bw;
+
+ if (picture == NULL) return 0;
+
+ if (config == NULL || picture->argb == NULL) {
+ err = VP8_ENC_ERROR_NULL_PARAMETER;
+ WebPEncodingSetError(picture, err);
+ return 0;
+ }
+
+ width = picture->width;
+ height = picture->height;
+ if (!VP8LBitWriterInit(&bw, (width * height) >> 1)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+
+ if (!WebPReportProgress(picture, 1, &percent)) {
+ UserAbort:
+ err = VP8_ENC_ERROR_USER_ABORT;
+ goto Error;
+ }
+ // Reset stats (for pure lossless coding)
+ if (picture->stats != NULL) {
+ WebPAuxStats* const stats = picture->stats;
+ memset(stats, 0, sizeof(*stats));
+ stats->PSNR[0] = 99.f;
+ stats->PSNR[1] = 99.f;
+ stats->PSNR[2] = 99.f;
+ stats->PSNR[3] = 99.f;
+ stats->PSNR[4] = 99.f;
+ }
+
+ // Write image size.
+ if (!WriteImageSize(picture, &bw)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+
+ has_alpha = WebPPictureHasTransparency(picture);
+ // Write the non-trivial Alpha flag and lossless version.
+ if (!WriteRealAlphaAndVersion(&bw, has_alpha)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+
+ if (!WebPReportProgress(picture, 5, &percent)) goto UserAbort;
+
+ // Encode main image stream.
+ err = VP8LEncodeStream(config, picture, &bw);
+ if (err != VP8_ENC_OK) goto Error;
+
+ // TODO(skal): have a fine-grained progress report in VP8LEncodeStream().
+ if (!WebPReportProgress(picture, 90, &percent)) goto UserAbort;
+
+ // Finish the RIFF chunk.
+ err = WriteImage(picture, &bw, &coded_size);
+ if (err != VP8_ENC_OK) goto Error;
+
+ if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort;
+
+ // Save size.
+ if (picture->stats != NULL) {
+ picture->stats->coded_size += (int)coded_size;
+ picture->stats->lossless_size = (int)coded_size;
+ }
+
+ if (picture->extra_info != NULL) {
+ const int mb_w = (width + 15) >> 4;
+ const int mb_h = (height + 15) >> 4;
+ memset(picture->extra_info, 0, mb_w * mb_h * sizeof(*picture->extra_info));
+ }
+
+ Error:
+ if (bw.error_) err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ VP8LBitWriterDestroy(&bw);
+ if (err != VP8_ENC_OK) {
+ WebPEncodingSetError(picture, err);
+ return 0;
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/enc/vp8li.h b/drivers/webpold/enc/vp8li.h
new file mode 100644
index 0000000000..bb111aec33
--- /dev/null
+++ b/drivers/webpold/enc/vp8li.h
@@ -0,0 +1,68 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Lossless encoder: internal header.
+//
+// Author: Vikas Arora (vikaas.arora@gmail.com)
+
+#ifndef WEBP_ENC_VP8LI_H_
+#define WEBP_ENC_VP8LI_H_
+
+#include "./histogram.h"
+#include "../utils/bit_writer.h"
+#include "../encode.h"
+#include "../format_constants.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+typedef struct {
+ const WebPConfig* config_; // user configuration and parameters
+ const WebPPicture* pic_; // input picture.
+
+ uint32_t* argb_; // Transformed argb image data.
+ uint32_t* argb_scratch_; // Scratch memory for argb rows
+ // (used for prediction).
+ uint32_t* transform_data_; // Scratch memory for transform data.
+ int current_width_; // Corresponds to packed image width.
+
+ // Encoding parameters derived from quality parameter.
+ int histo_bits_;
+ int transform_bits_;
+ int cache_bits_; // If equal to 0, don't use color cache.
+
+ // Encoding parameters derived from image characteristics.
+ int use_cross_color_;
+ int use_subtract_green_;
+ int use_predict_;
+ int use_palette_;
+ int palette_size_;
+ uint32_t palette_[MAX_PALETTE_SIZE];
+} VP8LEncoder;
+
+//------------------------------------------------------------------------------
+// internal functions. Not public.
+
+// Encodes the picture.
+// Returns 0 if config or picture is NULL or picture doesn't have valid argb
+// input.
+int VP8LEncodeImage(const WebPConfig* const config,
+ const WebPPicture* const picture);
+
+// Encodes the main image stream using the supplied bit writer.
+WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
+ const WebPPicture* const picture,
+ VP8LBitWriter* const bw);
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_ENC_VP8LI_H_ */
diff --git a/drivers/webpold/enc/webpenc.c b/drivers/webpold/enc/webpenc.c
new file mode 100644
index 0000000000..3c275589fc
--- /dev/null
+++ b/drivers/webpold/enc/webpenc.c
@@ -0,0 +1,389 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// WebP encoder: main entry point
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "./vp8enci.h"
+#include "./vp8li.h"
+#include "../utils/utils.h"
+
+// #define PRINT_MEMORY_INFO
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#ifdef PRINT_MEMORY_INFO
+#include <stdio.h>
+#endif
+
+//------------------------------------------------------------------------------
+
+int WebPGetEncoderVersion(void) {
+ return (ENC_MAJ_VERSION << 16) | (ENC_MIN_VERSION << 8) | ENC_REV_VERSION;
+}
+
+//------------------------------------------------------------------------------
+// WebPPicture
+//------------------------------------------------------------------------------
+
+static int DummyWriter(const uint8_t* data, size_t data_size,
+ const WebPPicture* const picture) {
+ // The following are to prevent 'unused variable' error message.
+ (void)data;
+ (void)data_size;
+ (void)picture;
+ return 1;
+}
+
+int WebPPictureInitInternal(WebPPicture* picture, int version) {
+ if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) {
+ return 0; // caller/system version mismatch!
+ }
+ if (picture != NULL) {
+ memset(picture, 0, sizeof(*picture));
+ picture->writer = DummyWriter;
+ WebPEncodingSetError(picture, VP8_ENC_OK);
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// VP8Encoder
+//------------------------------------------------------------------------------
+
+static void ResetSegmentHeader(VP8Encoder* const enc) {
+ VP8SegmentHeader* const hdr = &enc->segment_hdr_;
+ hdr->num_segments_ = enc->config_->segments;
+ hdr->update_map_ = (hdr->num_segments_ > 1);
+ hdr->size_ = 0;
+}
+
+static void ResetFilterHeader(VP8Encoder* const enc) {
+ VP8FilterHeader* const hdr = &enc->filter_hdr_;
+ hdr->simple_ = 1;
+ hdr->level_ = 0;
+ hdr->sharpness_ = 0;
+ hdr->i4x4_lf_delta_ = 0;
+}
+
+static void ResetBoundaryPredictions(VP8Encoder* const enc) {
+ // init boundary values once for all
+ // Note: actually, initializing the preds_[] is only needed for intra4.
+ int i;
+ uint8_t* const top = enc->preds_ - enc->preds_w_;
+ uint8_t* const left = enc->preds_ - 1;
+ for (i = -1; i < 4 * enc->mb_w_; ++i) {
+ top[i] = B_DC_PRED;
+ }
+ for (i = 0; i < 4 * enc->mb_h_; ++i) {
+ left[i * enc->preds_w_] = B_DC_PRED;
+ }
+ enc->nz_[-1] = 0; // constant
+}
+
+// Map configured quality level to coding tools used.
+//-------------+---+---+---+---+---+---+
+// Quality | 0 | 1 | 2 | 3 | 4 | 5 +
+//-------------+---+---+---+---+---+---+
+// dynamic prob| ~ | x | x | x | x | x |
+//-------------+---+---+---+---+---+---+
+// rd-opt modes| | | x | x | x | x |
+//-------------+---+---+---+---+---+---+
+// fast i4/i16 | x | x | | | | |
+//-------------+---+---+---+---+---+---+
+// rd-opt i4/16| | | x | x | x | x |
+//-------------+---+---+---+---+---+---+
+// Trellis | | x | | | x | x |
+//-------------+---+---+---+---+---+---+
+// full-SNS | | | | | | x |
+//-------------+---+---+---+---+---+---+
+
+static void MapConfigToTools(VP8Encoder* const enc) {
+ const int method = enc->config_->method;
+ const int limit = 100 - enc->config_->partition_limit;
+ enc->method_ = method;
+ enc->rd_opt_level_ = (method >= 6) ? 3
+ : (method >= 5) ? 2
+ : (method >= 3) ? 1
+ : 0;
+ enc->max_i4_header_bits_ =
+ 256 * 16 * 16 * // upper bound: up to 16bit per 4x4 block
+ (limit * limit) / (100 * 100); // ... modulated with a quadratic curve.
+}
+
+// Memory scaling with dimensions:
+// memory (bytes) ~= 2.25 * w + 0.0625 * w * h
+//
+// Typical memory footprint (768x510 picture)
+// Memory used:
+// encoder: 33919
+// block cache: 2880
+// info: 3072
+// preds: 24897
+// top samples: 1623
+// non-zero: 196
+// lf-stats: 2048
+// total: 68635
+// Transcient object sizes:
+// VP8EncIterator: 352
+// VP8ModeScore: 912
+// VP8SegmentInfo: 532
+// VP8Proba: 31032
+// LFStats: 2048
+// Picture size (yuv): 589824
+
+static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
+ WebPPicture* const picture) {
+ const int use_filter =
+ (config->filter_strength > 0) || (config->autofilter > 0);
+ const int mb_w = (picture->width + 15) >> 4;
+ const int mb_h = (picture->height + 15) >> 4;
+ const int preds_w = 4 * mb_w + 1;
+ const int preds_h = 4 * mb_h + 1;
+ const size_t preds_size = preds_w * preds_h * sizeof(uint8_t);
+ const int top_stride = mb_w * 16;
+ const size_t nz_size = (mb_w + 1) * sizeof(uint32_t);
+ const size_t cache_size = (3 * YUV_SIZE + PRED_SIZE) * sizeof(uint8_t);
+ const size_t info_size = mb_w * mb_h * sizeof(VP8MBInfo);
+ const size_t samples_size = (2 * top_stride + // top-luma/u/v
+ 16 + 16 + 16 + 8 + 1 + // left y/u/v
+ 2 * ALIGN_CST) // align all
+ * sizeof(uint8_t);
+ const size_t lf_stats_size =
+ config->autofilter ? sizeof(LFStats) + ALIGN_CST : 0;
+ VP8Encoder* enc;
+ uint8_t* mem;
+ const uint64_t size = (uint64_t)sizeof(VP8Encoder) // main struct
+ + ALIGN_CST // cache alignment
+ + cache_size // working caches
+ + info_size // modes info
+ + preds_size // prediction modes
+ + samples_size // top/left samples
+ + nz_size // coeff context bits
+ + lf_stats_size; // autofilter stats
+
+#ifdef PRINT_MEMORY_INFO
+ printf("===================================\n");
+ printf("Memory used:\n"
+ " encoder: %ld\n"
+ " block cache: %ld\n"
+ " info: %ld\n"
+ " preds: %ld\n"
+ " top samples: %ld\n"
+ " non-zero: %ld\n"
+ " lf-stats: %ld\n"
+ " total: %ld\n",
+ sizeof(VP8Encoder) + ALIGN_CST, cache_size, info_size,
+ preds_size, samples_size, nz_size, lf_stats_size, size);
+ printf("Transcient object sizes:\n"
+ " VP8EncIterator: %ld\n"
+ " VP8ModeScore: %ld\n"
+ " VP8SegmentInfo: %ld\n"
+ " VP8Proba: %ld\n"
+ " LFStats: %ld\n",
+ sizeof(VP8EncIterator), sizeof(VP8ModeScore),
+ sizeof(VP8SegmentInfo), sizeof(VP8Proba),
+ sizeof(LFStats));
+ printf("Picture size (yuv): %ld\n",
+ mb_w * mb_h * 384 * sizeof(uint8_t));
+ printf("===================================\n");
+#endif
+ mem = (uint8_t*)WebPSafeMalloc(size, sizeof(*mem));
+ if (mem == NULL) {
+ WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+ enc = (VP8Encoder*)mem;
+ mem = (uint8_t*)DO_ALIGN(mem + sizeof(*enc));
+ memset(enc, 0, sizeof(*enc));
+ enc->num_parts_ = 1 << config->partitions;
+ enc->mb_w_ = mb_w;
+ enc->mb_h_ = mb_h;
+ enc->preds_w_ = preds_w;
+ enc->yuv_in_ = (uint8_t*)mem;
+ mem += YUV_SIZE;
+ enc->yuv_out_ = (uint8_t*)mem;
+ mem += YUV_SIZE;
+ enc->yuv_out2_ = (uint8_t*)mem;
+ mem += YUV_SIZE;
+ enc->yuv_p_ = (uint8_t*)mem;
+ mem += PRED_SIZE;
+ enc->mb_info_ = (VP8MBInfo*)mem;
+ mem += info_size;
+ enc->preds_ = ((uint8_t*)mem) + 1 + enc->preds_w_;
+ mem += preds_w * preds_h * sizeof(uint8_t);
+ enc->nz_ = 1 + (uint32_t*)mem;
+ mem += nz_size;
+ enc->lf_stats_ = lf_stats_size ? (LFStats*)DO_ALIGN(mem) : NULL;
+ mem += lf_stats_size;
+
+ // top samples (all 16-aligned)
+ mem = (uint8_t*)DO_ALIGN(mem);
+ enc->y_top_ = (uint8_t*)mem;
+ enc->uv_top_ = enc->y_top_ + top_stride;
+ mem += 2 * top_stride;
+ mem = (uint8_t*)DO_ALIGN(mem + 1);
+ enc->y_left_ = (uint8_t*)mem;
+ mem += 16 + 16;
+ enc->u_left_ = (uint8_t*)mem;
+ mem += 16;
+ enc->v_left_ = (uint8_t*)mem;
+ mem += 8;
+
+ enc->config_ = config;
+ enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2;
+ enc->pic_ = picture;
+ enc->percent_ = 0;
+
+ MapConfigToTools(enc);
+ VP8EncDspInit();
+ VP8DefaultProbas(enc);
+ ResetSegmentHeader(enc);
+ ResetFilterHeader(enc);
+ ResetBoundaryPredictions(enc);
+
+ VP8EncInitAlpha(enc);
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ VP8EncInitLayer(enc);
+#endif
+
+ return enc;
+}
+
+static void DeleteVP8Encoder(VP8Encoder* enc) {
+ if (enc != NULL) {
+ VP8EncDeleteAlpha(enc);
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ VP8EncDeleteLayer(enc);
+#endif
+ free(enc);
+ }
+}
+
+//------------------------------------------------------------------------------
+
+static double GetPSNR(uint64_t err, uint64_t size) {
+ return err ? 10. * log10(255. * 255. * size / err) : 99.;
+}
+
+static void FinalizePSNR(const VP8Encoder* const enc) {
+ WebPAuxStats* stats = enc->pic_->stats;
+ const uint64_t size = enc->sse_count_;
+ const uint64_t* const sse = enc->sse_;
+ stats->PSNR[0] = (float)GetPSNR(sse[0], size);
+ stats->PSNR[1] = (float)GetPSNR(sse[1], size / 4);
+ stats->PSNR[2] = (float)GetPSNR(sse[2], size / 4);
+ stats->PSNR[3] = (float)GetPSNR(sse[0] + sse[1] + sse[2], size * 3 / 2);
+ stats->PSNR[4] = (float)GetPSNR(sse[3], size);
+}
+
+static void StoreStats(VP8Encoder* const enc) {
+ WebPAuxStats* const stats = enc->pic_->stats;
+ if (stats != NULL) {
+ int i, s;
+ for (i = 0; i < NUM_MB_SEGMENTS; ++i) {
+ stats->segment_level[i] = enc->dqm_[i].fstrength_;
+ stats->segment_quant[i] = enc->dqm_[i].quant_;
+ for (s = 0; s <= 2; ++s) {
+ stats->residual_bytes[s][i] = enc->residual_bytes_[s][i];
+ }
+ }
+ FinalizePSNR(enc);
+ stats->coded_size = enc->coded_size_;
+ for (i = 0; i < 3; ++i) {
+ stats->block_count[i] = enc->block_count_[i];
+ }
+ }
+ WebPReportProgress(enc->pic_, 100, &enc->percent_); // done!
+}
+
+int WebPEncodingSetError(const WebPPicture* const pic,
+ WebPEncodingError error) {
+ assert((int)error < VP8_ENC_ERROR_LAST);
+ assert((int)error >= VP8_ENC_OK);
+ ((WebPPicture*)pic)->error_code = error;
+ return 0;
+}
+
+int WebPReportProgress(const WebPPicture* const pic,
+ int percent, int* const percent_store) {
+ if (percent_store != NULL && percent != *percent_store) {
+ *percent_store = percent;
+ if (pic->progress_hook && !pic->progress_hook(percent, pic)) {
+ // user abort requested
+ WebPEncodingSetError(pic, VP8_ENC_ERROR_USER_ABORT);
+ return 0;
+ }
+ }
+ return 1; // ok
+}
+//------------------------------------------------------------------------------
+
+int WebPEncode(const WebPConfig* config, WebPPicture* pic) {
+ int ok;
+
+ if (pic == NULL)
+ return 0;
+ WebPEncodingSetError(pic, VP8_ENC_OK); // all ok so far
+ if (config == NULL) // bad params
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
+ if (!WebPValidateConfig(config))
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION);
+ if (pic->width <= 0 || pic->height <= 0)
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
+ if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION)
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
+
+ if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats));
+
+ if (!config->lossless) {
+ VP8Encoder* enc = NULL;
+ if (pic->y == NULL || pic->u == NULL || pic->v == NULL) {
+ if (pic->argb != NULL) {
+ if (!WebPPictureARGBToYUVA(pic, WEBP_YUV420)) return 0;
+ } else {
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
+ }
+ }
+
+ enc = InitVP8Encoder(config, pic);
+ if (enc == NULL) return 0; // pic->error is already set.
+ // Note: each of the tasks below account for 20% in the progress report.
+ ok = VP8EncAnalyze(enc)
+ && VP8StatLoop(enc)
+ && VP8EncLoop(enc)
+ && VP8EncFinishAlpha(enc)
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ && VP8EncFinishLayer(enc)
+#endif
+ && VP8EncWrite(enc);
+ StoreStats(enc);
+ if (!ok) {
+ VP8EncFreeBitWriters(enc);
+ }
+ DeleteVP8Encoder(enc);
+ } else {
+ if (pic->argb == NULL)
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
+
+ ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem.
+ }
+
+ return ok;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/encode.h b/drivers/webpold/encode.h
new file mode 100644
index 0000000000..2e37cfabe7
--- /dev/null
+++ b/drivers/webpold/encode.h
@@ -0,0 +1,463 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// WebP encoder: main interface
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_WEBP_ENCODE_H_
+#define WEBP_WEBP_ENCODE_H_
+
+#include "./types.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define WEBP_ENCODER_ABI_VERSION 0x0200 // MAJOR(8b) + MINOR(8b)
+
+// Return the encoder's version number, packed in hexadecimal using 8bits for
+// each of major/minor/revision. E.g: v2.5.7 is 0x020507.
+WEBP_EXTERN(int) WebPGetEncoderVersion(void);
+
+//------------------------------------------------------------------------------
+// One-stop-shop call! No questions asked:
+
+// Returns the size of the compressed data (pointed to by *output), or 0 if
+// an error occurred. The compressed data must be released by the caller
+// using the call 'free(*output)'.
+// These functions compress using the lossy format, and the quality_factor
+// can go from 0 (smaller output, lower quality) to 100 (best quality,
+// larger output).
+WEBP_EXTERN(size_t) WebPEncodeRGB(const uint8_t* rgb,
+ int width, int height, int stride,
+ float quality_factor, uint8_t** output);
+WEBP_EXTERN(size_t) WebPEncodeBGR(const uint8_t* bgr,
+ int width, int height, int stride,
+ float quality_factor, uint8_t** output);
+WEBP_EXTERN(size_t) WebPEncodeRGBA(const uint8_t* rgba,
+ int width, int height, int stride,
+ float quality_factor, uint8_t** output);
+WEBP_EXTERN(size_t) WebPEncodeBGRA(const uint8_t* bgra,
+ int width, int height, int stride,
+ float quality_factor, uint8_t** output);
+
+// These functions are the equivalent of the above, but compressing in a
+// lossless manner. Files are usually larger than lossy format, but will
+// not suffer any compression loss.
+WEBP_EXTERN(size_t) WebPEncodeLosslessRGB(const uint8_t* rgb,
+ int width, int height, int stride,
+ uint8_t** output);
+WEBP_EXTERN(size_t) WebPEncodeLosslessBGR(const uint8_t* bgr,
+ int width, int height, int stride,
+ uint8_t** output);
+WEBP_EXTERN(size_t) WebPEncodeLosslessRGBA(const uint8_t* rgba,
+ int width, int height, int stride,
+ uint8_t** output);
+WEBP_EXTERN(size_t) WebPEncodeLosslessBGRA(const uint8_t* bgra,
+ int width, int height, int stride,
+ uint8_t** output);
+
+//------------------------------------------------------------------------------
+// Coding parameters
+
+// Image characteristics hint for the underlying encoder.
+typedef enum {
+ WEBP_HINT_DEFAULT = 0, // default preset.
+ WEBP_HINT_PICTURE, // digital picture, like portrait, inner shot
+ WEBP_HINT_PHOTO, // outdoor photograph, with natural lighting
+ WEBP_HINT_GRAPH, // Discrete tone image (graph, map-tile etc).
+ WEBP_HINT_LAST
+} WebPImageHint;
+
+typedef struct {
+ int lossless; // Lossless encoding (0=lossy(default), 1=lossless).
+ float quality; // between 0 (smallest file) and 100 (biggest)
+ int method; // quality/speed trade-off (0=fast, 6=slower-better)
+
+ WebPImageHint image_hint; // Hint for image type (lossless only for now).
+
+ // Parameters related to lossy compression only:
+ int target_size; // if non-zero, set the desired target size in bytes.
+ // Takes precedence over the 'compression' parameter.
+ float target_PSNR; // if non-zero, specifies the minimal distortion to
+ // try to achieve. Takes precedence over target_size.
+ int segments; // maximum number of segments to use, in [1..4]
+ int sns_strength; // Spatial Noise Shaping. 0=off, 100=maximum.
+ int filter_strength; // range: [0 = off .. 100 = strongest]
+ int filter_sharpness; // range: [0 = off .. 7 = least sharp]
+ int filter_type; // filtering type: 0 = simple, 1 = strong (only used
+ // if filter_strength > 0 or autofilter > 0)
+ int autofilter; // Auto adjust filter's strength [0 = off, 1 = on]
+ int alpha_compression; // Algorithm for encoding the alpha plane (0 = none,
+ // 1 = compressed with WebP lossless). Default is 1.
+ int alpha_filtering; // Predictive filtering method for alpha plane.
+ // 0: none, 1: fast, 2: best. Default if 1.
+ int alpha_quality; // Between 0 (smallest size) and 100 (lossless).
+ // Default is 100.
+ int pass; // number of entropy-analysis passes (in [1..10]).
+
+ int show_compressed; // if true, export the compressed picture back.
+ // In-loop filtering is not applied.
+ int preprocessing; // preprocessing filter (0=none, 1=segment-smooth)
+ int partitions; // log2(number of token partitions) in [0..3]. Default
+ // is set to 0 for easier progressive decoding.
+ int partition_limit; // quality degradation allowed to fit the 512k limit
+ // on prediction modes coding (0: no degradation,
+ // 100: maximum possible degradation).
+
+ uint32_t pad[8]; // padding for later use
+} WebPConfig;
+
+// Enumerate some predefined settings for WebPConfig, depending on the type
+// of source picture. These presets are used when calling WebPConfigPreset().
+typedef enum {
+ WEBP_PRESET_DEFAULT = 0, // default preset.
+ WEBP_PRESET_PICTURE, // digital picture, like portrait, inner shot
+ WEBP_PRESET_PHOTO, // outdoor photograph, with natural lighting
+ WEBP_PRESET_DRAWING, // hand or line drawing, with high-contrast details
+ WEBP_PRESET_ICON, // small-sized colorful images
+ WEBP_PRESET_TEXT // text-like
+} WebPPreset;
+
+// Internal, version-checked, entry point
+WEBP_EXTERN(int) WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int);
+
+// Should always be called, to initialize a fresh WebPConfig structure before
+// modification. Returns false in case of version mismatch. WebPConfigInit()
+// must have succeeded before using the 'config' object.
+// Note that the default values are lossless=0 and quality=75.
+static WEBP_INLINE int WebPConfigInit(WebPConfig* config) {
+ return WebPConfigInitInternal(config, WEBP_PRESET_DEFAULT, 75.f,
+ WEBP_ENCODER_ABI_VERSION);
+}
+
+// This function will initialize the configuration according to a predefined
+// set of parameters (referred to by 'preset') and a given quality factor.
+// This function can be called as a replacement to WebPConfigInit(). Will
+// return false in case of error.
+static WEBP_INLINE int WebPConfigPreset(WebPConfig* config,
+ WebPPreset preset, float quality) {
+ return WebPConfigInitInternal(config, preset, quality,
+ WEBP_ENCODER_ABI_VERSION);
+}
+
+// Returns true if 'config' is non-NULL and all configuration parameters are
+// within their valid ranges.
+WEBP_EXTERN(int) WebPValidateConfig(const WebPConfig* config);
+
+//------------------------------------------------------------------------------
+// Input / Output
+
+typedef struct WebPPicture WebPPicture; // main structure for I/O
+
+// Structure for storing auxiliary statistics (mostly for lossy encoding).
+typedef struct {
+ int coded_size; // final size
+
+ float PSNR[5]; // peak-signal-to-noise ratio for Y/U/V/All/Alpha
+ int block_count[3]; // number of intra4/intra16/skipped macroblocks
+ int header_bytes[2]; // approximate number of bytes spent for header
+ // and mode-partition #0
+ int residual_bytes[3][4]; // approximate number of bytes spent for
+ // DC/AC/uv coefficients for each (0..3) segments.
+ int segment_size[4]; // number of macroblocks in each segments
+ int segment_quant[4]; // quantizer values for each segments
+ int segment_level[4]; // filtering strength for each segments [0..63]
+
+ int alpha_data_size; // size of the transparency data
+ int layer_data_size; // size of the enhancement layer data
+
+ // lossless encoder statistics
+ uint32_t lossless_features; // bit0:predictor bit1:cross-color transform
+ // bit2:subtract-green bit3:color indexing
+ int histogram_bits; // number of precision bits of histogram
+ int transform_bits; // precision bits for transform
+ int cache_bits; // number of bits for color cache lookup
+ int palette_size; // number of color in palette, if used
+ int lossless_size; // final lossless size
+
+ uint32_t pad[4]; // padding for later use
+} WebPAuxStats;
+
+// Signature for output function. Should return true if writing was successful.
+// data/data_size is the segment of data to write, and 'picture' is for
+// reference (and so one can make use of picture->custom_ptr).
+typedef int (*WebPWriterFunction)(const uint8_t* data, size_t data_size,
+ const WebPPicture* picture);
+
+// WebPMemoryWrite: a special WebPWriterFunction that writes to memory using
+// the following WebPMemoryWriter object (to be set as a custom_ptr).
+typedef struct {
+ uint8_t* mem; // final buffer (of size 'max_size', larger than 'size').
+ size_t size; // final size
+ size_t max_size; // total capacity
+ uint32_t pad[1]; // padding for later use
+} WebPMemoryWriter;
+
+// The following must be called first before any use.
+WEBP_EXTERN(void) WebPMemoryWriterInit(WebPMemoryWriter* writer);
+
+// The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon
+// completion, writer.mem and writer.size will hold the coded data.
+WEBP_EXTERN(int) WebPMemoryWrite(const uint8_t* data, size_t data_size,
+ const WebPPicture* picture);
+
+// Progress hook, called from time to time to report progress. It can return
+// false to request an abort of the encoding process, or true otherwise if
+// everything is OK.
+typedef int (*WebPProgressHook)(int percent, const WebPPicture* picture);
+
+typedef enum {
+ // chroma sampling
+ WEBP_YUV420 = 0, // 4:2:0
+ WEBP_YUV422 = 1, // 4:2:2
+ WEBP_YUV444 = 2, // 4:4:4
+ WEBP_YUV400 = 3, // grayscale
+ WEBP_CSP_UV_MASK = 3, // bit-mask to get the UV sampling factors
+ // alpha channel variants
+ WEBP_YUV420A = 4,
+ WEBP_YUV422A = 5,
+ WEBP_YUV444A = 6,
+ WEBP_YUV400A = 7, // grayscale + alpha
+ WEBP_CSP_ALPHA_BIT = 4 // bit that is set if alpha is present
+} WebPEncCSP;
+
+// Encoding error conditions.
+typedef enum {
+ VP8_ENC_OK = 0,
+ VP8_ENC_ERROR_OUT_OF_MEMORY, // memory error allocating objects
+ VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, // memory error while flushing bits
+ VP8_ENC_ERROR_NULL_PARAMETER, // a pointer parameter is NULL
+ VP8_ENC_ERROR_INVALID_CONFIGURATION, // configuration is invalid
+ VP8_ENC_ERROR_BAD_DIMENSION, // picture has invalid width/height
+ VP8_ENC_ERROR_PARTITION0_OVERFLOW, // partition is bigger than 512k
+ VP8_ENC_ERROR_PARTITION_OVERFLOW, // partition is bigger than 16M
+ VP8_ENC_ERROR_BAD_WRITE, // error while flushing bytes
+ VP8_ENC_ERROR_FILE_TOO_BIG, // file is bigger than 4G
+ VP8_ENC_ERROR_USER_ABORT, // abort request by user
+ VP8_ENC_ERROR_LAST // list terminator. always last.
+} WebPEncodingError;
+
+// maximum width/height allowed (inclusive), in pixels
+#define WEBP_MAX_DIMENSION 16383
+
+// Main exchange structure (input samples, output bytes, statistics)
+struct WebPPicture {
+
+ // INPUT
+ //////////////
+ // Main flag for encoder selecting between ARGB or YUV input.
+ // It is recommended to use ARGB input (*argb, argb_stride) for lossless
+ // compression, and YUV input (*y, *u, *v, etc.) for lossy compression
+ // since these are the respective native colorspace for these formats.
+ int use_argb;
+
+ // YUV input (mostly used for input to lossy compression)
+ WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr).
+ int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION)
+ uint8_t *y, *u, *v; // pointers to luma/chroma planes.
+ int y_stride, uv_stride; // luma/chroma strides.
+ uint8_t* a; // pointer to the alpha plane
+ int a_stride; // stride of the alpha plane
+ uint32_t pad1[2]; // padding for later use
+
+ // ARGB input (mostly used for input to lossless compression)
+ uint32_t* argb; // Pointer to argb (32 bit) plane.
+ int argb_stride; // This is stride in pixels units, not bytes.
+ uint32_t pad2[3]; // padding for later use
+
+ // OUTPUT
+ ///////////////
+ // Byte-emission hook, to store compressed bytes as they are ready.
+ WebPWriterFunction writer; // can be NULL
+ void* custom_ptr; // can be used by the writer.
+
+ // map for extra information (only for lossy compression mode)
+ int extra_info_type; // 1: intra type, 2: segment, 3: quant
+ // 4: intra-16 prediction mode,
+ // 5: chroma prediction mode,
+ // 6: bit cost, 7: distortion
+ uint8_t* extra_info; // if not NULL, points to an array of size
+ // ((width + 15) / 16) * ((height + 15) / 16) that
+ // will be filled with a macroblock map, depending
+ // on extra_info_type.
+
+ // STATS AND REPORTS
+ ///////////////////////////
+ // Pointer to side statistics (updated only if not NULL)
+ WebPAuxStats* stats;
+
+ // Error code for the latest error encountered during encoding
+ WebPEncodingError error_code;
+
+ // If not NULL, report progress during encoding.
+ WebPProgressHook progress_hook;
+
+ void* user_data; // this field is free to be set to any value and
+ // used during callbacks (like progress-report e.g.).
+
+ uint32_t pad3[3]; // padding for later use
+
+ // Unused for now: original samples (for non-YUV420 modes)
+ uint8_t *u0, *v0;
+ int uv0_stride;
+
+ uint32_t pad4[7]; // padding for later use
+
+ // PRIVATE FIELDS
+ ////////////////////
+ void* memory_; // row chunk of memory for yuva planes
+ void* memory_argb_; // and for argb too.
+ void* pad5[2]; // padding for later use
+};
+
+// Internal, version-checked, entry point
+WEBP_EXTERN(int) WebPPictureInitInternal(WebPPicture*, int);
+
+// Should always be called, to initialize the structure. Returns false in case
+// of version mismatch. WebPPictureInit() must have succeeded before using the
+// 'picture' object.
+// Note that, by default, use_argb is false and colorspace is WEBP_YUV420.
+static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) {
+ return WebPPictureInitInternal(picture, WEBP_ENCODER_ABI_VERSION);
+}
+
+//------------------------------------------------------------------------------
+// WebPPicture utils
+
+// Convenience allocation / deallocation based on picture->width/height:
+// Allocate y/u/v buffers as per colorspace/width/height specification.
+// Note! This function will free the previous buffer if needed.
+// Returns false in case of memory error.
+WEBP_EXTERN(int) WebPPictureAlloc(WebPPicture* picture);
+
+// Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*().
+// Note that this function does _not_ free the memory used by the 'picture'
+// object itself.
+// Besides memory (which is reclaimed) all other fields of 'picture' are
+// preserved.
+WEBP_EXTERN(void) WebPPictureFree(WebPPicture* picture);
+
+// Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return,
+// *dst will fully own the copied pixels (this is not a view).
+// Returns false in case of memory allocation error.
+WEBP_EXTERN(int) WebPPictureCopy(const WebPPicture* src, WebPPicture* dst);
+
+// Compute PSNR or SSIM distortion between two pictures.
+// Result is in dB, stores in result[] in the Y/U/V/Alpha/All order.
+// Returns false in case of error (pic1 and pic2 don't have same dimension, ...)
+// Warning: this function is rather CPU-intensive.
+WEBP_EXTERN(int) WebPPictureDistortion(
+ const WebPPicture* pic1, const WebPPicture* pic2,
+ int metric_type, // 0 = PSNR, 1 = SSIM
+ float result[5]);
+
+// self-crops a picture to the rectangle defined by top/left/width/height.
+// Returns false in case of memory allocation error, or if the rectangle is
+// outside of the source picture.
+// The rectangle for the view is defined by the top-left corner pixel
+// coordinates (left, top) as well as its width and height. This rectangle
+// must be fully be comprised inside the 'src' source picture. If the source
+// picture uses the YUV420 colorspace, the top and left coordinates will be
+// snapped to even values.
+WEBP_EXTERN(int) WebPPictureCrop(WebPPicture* picture,
+ int left, int top, int width, int height);
+
+// Extracts a view from 'src' picture into 'dst'. The rectangle for the view
+// is defined by the top-left corner pixel coordinates (left, top) as well
+// as its width and height. This rectangle must be fully be comprised inside
+// the 'src' source picture. If the source picture uses the YUV420 colorspace,
+// the top and left coordinates will be snapped to even values.
+// Picture 'src' must out-live 'dst' picture. Self-extraction of view is allowed
+// ('src' equal to 'dst') as a mean of fast-cropping (but note that doing so,
+// the original dimension will be lost).
+// Returns false in case of memory allocation error or invalid parameters.
+WEBP_EXTERN(int) WebPPictureView(const WebPPicture* src,
+ int left, int top, int width, int height,
+ WebPPicture* dst);
+
+// Returns true if the 'picture' is actually a view and therefore does
+// not own the memory for pixels.
+WEBP_EXTERN(int) WebPPictureIsView(const WebPPicture* picture);
+
+// Rescale a picture to new dimension width x height.
+// Now gamma correction is applied.
+// Returns false in case of error (invalid parameter or insufficient memory).
+WEBP_EXTERN(int) WebPPictureRescale(WebPPicture* pic, int width, int height);
+
+// Colorspace conversion function to import RGB samples.
+// Previous buffer will be free'd, if any.
+// *rgb buffer should have a size of at least height * rgb_stride.
+// Returns false in case of memory error.
+WEBP_EXTERN(int) WebPPictureImportRGB(
+ WebPPicture* picture, const uint8_t* rgb, int rgb_stride);
+// Same, but for RGBA buffer.
+WEBP_EXTERN(int) WebPPictureImportRGBA(
+ WebPPicture* picture, const uint8_t* rgba, int rgba_stride);
+// Same, but for RGBA buffer. Imports the RGB direct from the 32-bit format
+// input buffer ignoring the alpha channel. Avoids needing to copy the data
+// to a temporary 24-bit RGB buffer to import the RGB only.
+WEBP_EXTERN(int) WebPPictureImportRGBX(
+ WebPPicture* picture, const uint8_t* rgbx, int rgbx_stride);
+
+// Variants of the above, but taking BGR(A|X) input.
+WEBP_EXTERN(int) WebPPictureImportBGR(
+ WebPPicture* picture, const uint8_t* bgr, int bgr_stride);
+WEBP_EXTERN(int) WebPPictureImportBGRA(
+ WebPPicture* picture, const uint8_t* bgra, int bgra_stride);
+WEBP_EXTERN(int) WebPPictureImportBGRX(
+ WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride);
+
+// Converts picture->argb data to the YUVA format specified by 'colorspace'.
+// Upon return, picture->use_argb is set to false. The presence of real
+// non-opaque transparent values is detected, and 'colorspace' will be
+// adjusted accordingly. Note that this method is lossy.
+// Returns false in case of error.
+WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture,
+ WebPEncCSP colorspace);
+
+// Converts picture->yuv to picture->argb and sets picture->use_argb to true.
+// The input format must be YUV_420 or YUV_420A.
+// Note that the use of this method is discouraged if one has access to the
+// raw ARGB samples, since using YUV420 is comparatively lossy. Also, the
+// conversion from YUV420 to ARGB incurs a small loss too.
+// Returns false in case of error.
+WEBP_EXTERN(int) WebPPictureYUVAToARGB(WebPPicture* picture);
+
+// Helper function: given a width x height plane of YUV(A) samples
+// (with stride 'stride'), clean-up the YUV samples under fully transparent
+// area, to help compressibility (no guarantee, though).
+WEBP_EXTERN(void) WebPCleanupTransparentArea(WebPPicture* picture);
+
+// Scan the picture 'picture' for the presence of non fully opaque alpha values.
+// Returns true in such case. Otherwise returns false (indicating that the
+// alpha plane can be ignored altogether e.g.).
+WEBP_EXTERN(int) WebPPictureHasTransparency(const WebPPicture* picture);
+
+//------------------------------------------------------------------------------
+// Main call
+
+// Main encoding call, after config and picture have been initialized.
+// 'picture' must be less than 16384x16384 in dimension (cf WEBP_MAX_DIMENSION),
+// and the 'config' object must be a valid one.
+// Returns false in case of error, true otherwise.
+// In case of error, picture->error_code is updated accordingly.
+// 'picture' can hold the source samples in both YUV(A) or ARGB input, depending
+// on the value of 'picture->use_argb'. It is highly recommended to use
+// the former for lossy encoding, and the latter for lossless encoding
+// (when config.lossless is true). Automatic conversion from one format to
+// another is provided but they both incur some loss.
+WEBP_EXTERN(int) WebPEncode(const WebPConfig* config, WebPPicture* picture);
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_WEBP_ENCODE_H_ */
diff --git a/drivers/webpold/format_constants.h b/drivers/webpold/format_constants.h
new file mode 100644
index 0000000000..7ce498f672
--- /dev/null
+++ b/drivers/webpold/format_constants.h
@@ -0,0 +1,90 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Internal header for constants related to WebP file format.
+//
+// Author: Urvang (urvang@google.com)
+
+#ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_
+#define WEBP_WEBP_FORMAT_CONSTANTS_H_
+
+// VP8 related constants.
+#define VP8_SIGNATURE 0x9d012a // Signature in VP8 data.
+#define VP8_MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition
+#define VP8_MAX_PARTITION_SIZE (1 << 24) // max size for token partition
+#define VP8_FRAME_HEADER_SIZE 10 // Size of the frame header within VP8 data.
+
+// VP8L related constants.
+#define VP8L_SIGNATURE_SIZE 1 // VP8L signature size.
+#define VP8L_MAGIC_BYTE 0x2f // VP8L signature byte.
+#define VP8L_IMAGE_SIZE_BITS 14 // Number of bits used to store
+ // width and height.
+#define VP8L_VERSION_BITS 3 // 3 bits reserved for version.
+#define VP8L_VERSION 0 // version 0
+#define VP8L_FRAME_HEADER_SIZE 5 // Size of the VP8L frame header.
+
+#define MAX_PALETTE_SIZE 256
+#define MAX_CACHE_BITS 11
+#define HUFFMAN_CODES_PER_META_CODE 5
+#define ARGB_BLACK 0xff000000
+
+#define DEFAULT_CODE_LENGTH 8
+#define MAX_ALLOWED_CODE_LENGTH 15
+
+#define NUM_LITERAL_CODES 256
+#define NUM_LENGTH_CODES 24
+#define NUM_DISTANCE_CODES 40
+#define CODE_LENGTH_CODES 19
+
+#define MIN_HUFFMAN_BITS 2 // min number of Huffman bits
+#define MAX_HUFFMAN_BITS 9 // max number of Huffman bits
+
+#define TRANSFORM_PRESENT 1 // The bit to be written when next data
+ // to be read is a transform.
+#define NUM_TRANSFORMS 4 // Maximum number of allowed transform
+ // in a bitstream.
+typedef enum {
+ PREDICTOR_TRANSFORM = 0,
+ CROSS_COLOR_TRANSFORM = 1,
+ SUBTRACT_GREEN = 2,
+ COLOR_INDEXING_TRANSFORM = 3
+} VP8LImageTransformType;
+
+// Alpha related constants.
+#define ALPHA_HEADER_LEN 1
+#define ALPHA_NO_COMPRESSION 0
+#define ALPHA_LOSSLESS_COMPRESSION 1
+#define ALPHA_PREPROCESSED_LEVELS 1
+
+// Mux related constants.
+#define TAG_SIZE 4 // Size of a chunk tag (e.g. "VP8L").
+#define CHUNK_SIZE_BYTES 4 // Size needed to store chunk's size.
+#define CHUNK_HEADER_SIZE 8 // Size of a chunk header.
+#define RIFF_HEADER_SIZE 12 // Size of the RIFF header ("RIFFnnnnWEBP").
+#define FRAME_CHUNK_SIZE 15 // Size of a FRM chunk.
+#define LOOP_CHUNK_SIZE 2 // Size of a LOOP chunk.
+#define TILE_CHUNK_SIZE 6 // Size of a TILE chunk.
+#define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk.
+
+#define TILING_FLAG_BIT 0x01 // Set if tiles are possibly used.
+#define ANIMATION_FLAG_BIT 0x02 // Set if some animation is expected
+#define ICC_FLAG_BIT 0x04 // Whether ICC is present or not.
+#define METADATA_FLAG_BIT 0x08 // Set if some META chunk is possibly present.
+#define ALPHA_FLAG_BIT 0x10 // Should be same as the ALPHA_FLAG in mux.h
+#define ROTATION_FLAG_BITS 0xe0 // all 3 bits for rotation + symmetry
+
+#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height.
+#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height.
+#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count
+#define MAX_DURATION (1 << 24) // maximum duration
+#define MAX_POSITION_OFFSET (1 << 24) // maximum frame/tile x/y offset
+
+// Maximum chunk payload is such that adding the header and padding won't
+// overflow a uint32_t.
+#define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1)
+
+#endif /* WEBP_WEBP_FORMAT_CONSTANTS_H_ */
diff --git a/drivers/webpold/image_loader_webp.cpp b/drivers/webpold/image_loader_webp.cpp
new file mode 100644
index 0000000000..5fb14eaf7a
--- /dev/null
+++ b/drivers/webpold/image_loader_webp.cpp
@@ -0,0 +1,165 @@
+/*************************************************/
+/* image_loader_webp.cpp */
+/*************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/*************************************************/
+/* Source code within this file is: */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
+/* All Rights Reserved. */
+/*************************************************/
+
+#include "image_loader_webp.h"
+
+#include "print_string.h"
+#include "os/os.h"
+#include "drivers/webp/decode.h"
+#include "drivers/webp/encode.h"
+#include "io/marshalls.h"
+#include <stdlib.h>
+
+static DVector<uint8_t> _webp_lossy_pack(const Image& p_image,float p_quality) {
+
+ ERR_FAIL_COND_V(p_image.empty(),DVector<uint8_t>());
+
+ Image img=p_image;
+ if (img.detect_alpha())
+ img.convert(Image::FORMAT_RGBA);
+ else
+ img.convert(Image::FORMAT_RGB);
+
+ Size2 s(img.get_width(),img.get_height());
+ DVector<uint8_t> data = img.get_data();
+ DVector<uint8_t>::Read r = data.read();
+
+ uint8_t *dst_buff=NULL;
+ size_t dst_size=0;
+ if (img.get_format()==Image::FORMAT_RGB) {
+
+ dst_size = WebPEncodeRGB(r.ptr(),s.width,s.height,3*s.width,CLAMP(p_quality*100.0,0,100.0),&dst_buff);
+ } else {
+ dst_size = WebPEncodeRGBA(r.ptr(),s.width,s.height,4*s.width,CLAMP(p_quality*100.0,0,100.0),&dst_buff);
+ }
+
+ ERR_FAIL_COND_V(dst_size==0,DVector<uint8_t>());
+ DVector<uint8_t> dst;
+ dst.resize(4+dst_size);
+ DVector<uint8_t>::Write w = dst.write();
+ w[0]='W';
+ w[1]='E';
+ w[2]='B';
+ w[3]='P';
+ copymem(&w[4],dst_buff,dst_size);
+ free(dst_buff);
+ w=DVector<uint8_t>::Write();
+ return dst;
+}
+
+static Image _webp_lossy_unpack(const DVector<uint8_t>& p_buffer) {
+
+ int size = p_buffer.size()-4;
+ ERR_FAIL_COND_V(size<=0,Image());
+ DVector<uint8_t>::Read r = p_buffer.read();
+
+ ERR_FAIL_COND_V(r[0]!='W' || r[1]!='E' || r[2]!='B' || r[3]!='P',Image());
+ WebPBitstreamFeatures features;
+ if (WebPGetFeatures(&r[4],size,&features)!=VP8_STATUS_OK) {
+ ERR_EXPLAIN("Error unpacking WEBP image:");
+ ERR_FAIL_V(Image());
+ }
+
+ //print_line("width: "+itos(features.width));
+ //print_line("height: "+itos(features.height));
+ //print_line("alpha: "+itos(features.has_alpha));
+
+ DVector<uint8_t> dst_image;
+ int datasize = features.width*features.height*(features.has_alpha?4:3);
+ dst_image.resize(datasize);
+
+ DVector<uint8_t>::Write dst_w = dst_image.write();
+
+ bool errdec=false;
+ if (features.has_alpha) {
+ errdec = WebPDecodeRGBAInto(&r[4],size,dst_w.ptr(),datasize,4*features.width)==NULL;
+ } else {
+ errdec = WebPDecodeRGBInto(&r[4],size,dst_w.ptr(),datasize,3*features.width)==NULL;
+
+ }
+
+ //ERR_EXPLAIN("Error decoding webp! - "+p_file);
+ ERR_FAIL_COND_V(errdec,Image());
+
+ dst_w = DVector<uint8_t>::Write();
+
+ return Image(features.width,features.height,0,features.has_alpha?Image::FORMAT_RGBA:Image::FORMAT_RGB,dst_image);
+
+}
+
+
+Error ImageLoaderWEBP::load_image(Image *p_image,FileAccess *f) {
+
+
+ uint32_t size = f->get_len();
+ DVector<uint8_t> src_image;
+ src_image.resize(size);
+
+ WebPBitstreamFeatures features;
+
+ DVector<uint8_t>::Write src_w = src_image.write();
+ f->get_buffer(src_w.ptr(),size);
+ ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_EOF);
+
+ if (WebPGetFeatures(src_w.ptr(),size,&features)!=VP8_STATUS_OK) {
+ f->close();
+ //ERR_EXPLAIN("Error decoding WEBP image: "+p_file);
+ ERR_FAIL_V(ERR_FILE_CORRUPT);
+ }
+
+ print_line("width: "+itos(features.width));
+ print_line("height: "+itos(features.height));
+ print_line("alpha: "+itos(features.has_alpha));
+
+ src_w = DVector<uint8_t>::Write();
+
+ DVector<uint8_t> dst_image;
+ int datasize = features.width*features.height*(features.has_alpha?4:3);
+ dst_image.resize(datasize);
+
+ DVector<uint8_t>::Read src_r = src_image.read();
+ DVector<uint8_t>::Write dst_w = dst_image.write();
+
+
+ bool errdec=false;
+ if (features.has_alpha) {
+ errdec = WebPDecodeRGBAInto(src_r.ptr(),size,dst_w.ptr(),datasize,4*features.width)==NULL;
+ } else {
+ errdec = WebPDecodeRGBInto(src_r.ptr(),size,dst_w.ptr(),datasize,3*features.width)==NULL;
+
+ }
+
+ //ERR_EXPLAIN("Error decoding webp! - "+p_file);
+ ERR_FAIL_COND_V(errdec,ERR_FILE_CORRUPT);
+
+ src_r = DVector<uint8_t>::Read();
+ dst_w = DVector<uint8_t>::Write();
+
+ *p_image = Image(features.width,features.height,0,features.has_alpha?Image::FORMAT_RGBA:Image::FORMAT_RGB,dst_image);
+
+
+ return OK;
+
+}
+
+void ImageLoaderWEBP::get_recognized_extensions(List<String> *p_extensions) const {
+
+ p_extensions->push_back("webp");
+}
+
+
+ImageLoaderWEBP::ImageLoaderWEBP() {
+
+ Image::lossy_packer=_webp_lossy_pack;
+ Image::lossy_unpacker=_webp_lossy_unpack;
+}
+
+
diff --git a/drivers/webpold/image_loader_webp.h b/drivers/webpold/image_loader_webp.h
new file mode 100644
index 0000000000..ea99a60676
--- /dev/null
+++ b/drivers/webpold/image_loader_webp.h
@@ -0,0 +1,32 @@
+/*************************************************/
+/* image_loader_webp.h */
+/*************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/*************************************************/
+/* Source code within this file is: */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
+/* All Rights Reserved. */
+/*************************************************/
+
+#ifndef IMAGE_LOADER_WEBP_H
+#define IMAGE_LOADER_WEBP_H
+
+#include "io/image_loader.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class ImageLoaderWEBP : public ImageFormatLoader {
+
+
+public:
+
+ virtual Error load_image(Image *p_image,FileAccess *f);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ ImageLoaderWEBP();
+};
+
+
+
+#endif
diff --git a/drivers/webpold/mux.h b/drivers/webpold/mux.h
new file mode 100644
index 0000000000..5139af80fa
--- /dev/null
+++ b/drivers/webpold/mux.h
@@ -0,0 +1,604 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// RIFF container manipulation for WEBP images.
+//
+// Authors: Urvang (urvang@google.com)
+// Vikas (vikasa@google.com)
+
+// This API allows manipulation of WebP container images containing features
+// like Color profile, XMP metadata, Animation and Tiling.
+//
+// Code Example#1: Creating a MUX with image data, color profile and XMP
+// metadata.
+//
+// int copy_data = 0;
+// WebPMux* mux = WebPMuxNew();
+// // ... (Prepare image data).
+// WebPMuxSetImage(mux, &image, copy_data);
+// // ... (Prepare ICCP color profile data).
+// WebPMuxSetColorProfile(mux, &icc_profile, copy_data);
+// // ... (Prepare XMP metadata).
+// WebPMuxSetMetadata(mux, &xmp, copy_data);
+// // Get data from mux in WebP RIFF format.
+// WebPMuxAssemble(mux, &output_data);
+// WebPMuxDelete(mux);
+// // ... (Consume output_data; e.g. write output_data.bytes_ to file).
+// WebPDataClear(&output_data);
+//
+// Code Example#2: Get image and color profile data from a WebP file.
+//
+// int copy_data = 0;
+// // ... (Read data from file).
+// WebPMux* mux = WebPMuxCreate(&data, copy_data);
+// WebPMuxGetImage(mux, &image);
+// // ... (Consume image; e.g. call WebPDecode() to decode the data).
+// WebPMuxGetColorProfile(mux, &icc_profile);
+// // ... (Consume icc_data).
+// WebPMuxDelete(mux);
+// free(data);
+
+#ifndef WEBP_WEBP_MUX_H_
+#define WEBP_WEBP_MUX_H_
+
+#include "./types.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define WEBP_MUX_ABI_VERSION 0x0100 // MAJOR(8b) + MINOR(8b)
+
+// Error codes
+typedef enum {
+ WEBP_MUX_OK = 1,
+ WEBP_MUX_NOT_FOUND = 0,
+ WEBP_MUX_INVALID_ARGUMENT = -1,
+ WEBP_MUX_BAD_DATA = -2,
+ WEBP_MUX_MEMORY_ERROR = -3,
+ WEBP_MUX_NOT_ENOUGH_DATA = -4
+} WebPMuxError;
+
+// Flag values for different features used in VP8X chunk.
+typedef enum {
+ TILE_FLAG = 0x00000001,
+ ANIMATION_FLAG = 0x00000002,
+ ICCP_FLAG = 0x00000004,
+ META_FLAG = 0x00000008,
+ ALPHA_FLAG = 0x00000010
+} WebPFeatureFlags;
+
+// IDs for different types of chunks.
+typedef enum {
+ WEBP_CHUNK_VP8X, // VP8X
+ WEBP_CHUNK_ICCP, // ICCP
+ WEBP_CHUNK_LOOP, // LOOP
+ WEBP_CHUNK_FRAME, // FRM
+ WEBP_CHUNK_TILE, // TILE
+ WEBP_CHUNK_ALPHA, // ALPH
+ WEBP_CHUNK_IMAGE, // VP8/VP8L
+ WEBP_CHUNK_META, // META
+ WEBP_CHUNK_UNKNOWN, // Other chunks.
+ WEBP_CHUNK_NIL
+} WebPChunkId;
+
+typedef struct WebPMux WebPMux; // main opaque object.
+
+// Data type used to describe 'raw' data, e.g., chunk data
+// (ICC profile, metadata) and WebP compressed image data.
+typedef struct {
+ const uint8_t* bytes_;
+ size_t size_;
+} WebPData;
+
+//------------------------------------------------------------------------------
+// Manipulation of a WebPData object.
+
+// Initializes the contents of the 'webp_data' object with default values.
+WEBP_EXTERN(void) WebPDataInit(WebPData* webp_data);
+
+// Clears the contents of the 'webp_data' object by calling free(). Does not
+// deallocate the object itself.
+WEBP_EXTERN(void) WebPDataClear(WebPData* webp_data);
+
+// Allocates necessary storage for 'dst' and copies the contents of 'src'.
+// Returns true on success.
+WEBP_EXTERN(int) WebPDataCopy(const WebPData* src, WebPData* dst);
+
+//------------------------------------------------------------------------------
+// Life of a Mux object
+
+// Internal, version-checked, entry point
+WEBP_EXTERN(WebPMux*) WebPNewInternal(int);
+
+// Creates an empty mux object.
+// Returns:
+// A pointer to the newly created empty mux object.
+static WEBP_INLINE WebPMux* WebPMuxNew(void) {
+ return WebPNewInternal(WEBP_MUX_ABI_VERSION);
+}
+
+// Deletes the mux object.
+// Parameters:
+// mux - (in/out) object to be deleted
+WEBP_EXTERN(void) WebPMuxDelete(WebPMux* mux);
+
+//------------------------------------------------------------------------------
+// Mux creation.
+
+// Internal, version-checked, entry point
+WEBP_EXTERN(WebPMux*) WebPMuxCreateInternal(const WebPData*, int, int);
+
+// Creates a mux object from raw data given in WebP RIFF format.
+// Parameters:
+// bitstream - (in) the bitstream data in WebP RIFF format
+// copy_data - (in) value 1 indicates given data WILL copied to the mux, and
+// value 0 indicates data will NOT be copied.
+// Returns:
+// A pointer to the mux object created from given data - on success.
+// NULL - In case of invalid data or memory error.
+static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream,
+ int copy_data) {
+ return WebPMuxCreateInternal(bitstream, copy_data, WEBP_MUX_ABI_VERSION);
+}
+
+//------------------------------------------------------------------------------
+// Single Image.
+
+// Sets the image in the mux object. Any existing images (including frame/tile)
+// will be removed.
+// Parameters:
+// mux - (in/out) object in which the image is to be set
+// bitstream - (in) can either be a raw VP8/VP8L bitstream or a single-image
+// WebP file (non-animated and non-tiled)
+// copy_data - (in) value 1 indicates given data WILL copied to the mux, and
+// value 0 indicates data will NOT be copied.
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL.
+// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxSetImage(WebPMux* mux,
+ const WebPData* bitstream,
+ int copy_data);
+
+// Gets image data from the mux object.
+// The content of 'bitstream' is allocated using malloc(), and NOT
+// owned by the 'mux' object. It MUST be deallocated by the caller by calling
+// WebPDataClear().
+// Parameters:
+// mux - (in) object from which the image is to be fetched
+// bitstream - (out) the image data
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if either mux or bitstream is NULL
+// OR mux contains animation/tiling.
+// WEBP_MUX_NOT_FOUND - if image is not present in mux object.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxGetImage(const WebPMux* mux,
+ WebPData* bitstream);
+
+// Deletes the image in the mux object.
+// Parameters:
+// mux - (in/out) object from which the image is to be deleted
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL
+// OR if mux contains animation/tiling.
+// WEBP_MUX_NOT_FOUND - if image is not present in mux object.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxDeleteImage(WebPMux* mux);
+
+//------------------------------------------------------------------------------
+// XMP Metadata.
+
+// Sets the XMP metadata in the mux object. Any existing metadata chunk(s) will
+// be removed.
+// Parameters:
+// mux - (in/out) object to which the XMP metadata is to be added
+// metadata - (in) the XMP metadata data to be added
+// copy_data - (in) value 1 indicates given data WILL copied to the mux, and
+// value 0 indicates data will NOT be copied.
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if mux or metadata is NULL.
+// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxSetMetadata(WebPMux* mux,
+ const WebPData* metadata,
+ int copy_data);
+
+// Gets a reference to the XMP metadata in the mux object.
+// The caller should NOT free the returned data.
+// Parameters:
+// mux - (in) object from which the XMP metadata is to be fetched
+// metadata - (out) XMP metadata
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if either mux or metadata is NULL.
+// WEBP_MUX_NOT_FOUND - if metadata is not present in mux object.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxGetMetadata(const WebPMux* mux,
+ WebPData* metadata);
+
+// Deletes the XMP metadata in the mux object.
+// Parameters:
+// mux - (in/out) object from which XMP metadata is to be deleted
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL
+// WEBP_MUX_NOT_FOUND - If mux does not contain metadata.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxDeleteMetadata(WebPMux* mux);
+
+//------------------------------------------------------------------------------
+// ICC Color Profile.
+
+// Sets the color profile in the mux object. Any existing color profile chunk(s)
+// will be removed.
+// Parameters:
+// mux - (in/out) object to which the color profile is to be added
+// color_profile - (in) the color profile data to be added
+// copy_data - (in) value 1 indicates given data WILL copied to the mux, and
+// value 0 indicates data will NOT be copied.
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if mux or color_profile is NULL
+// WEBP_MUX_MEMORY_ERROR - on memory allocation error
+// WEBP_MUX_OK - on success
+WEBP_EXTERN(WebPMuxError) WebPMuxSetColorProfile(WebPMux* mux,
+ const WebPData* color_profile,
+ int copy_data);
+
+// Gets a reference to the color profile in the mux object.
+// The caller should NOT free the returned data.
+// Parameters:
+// mux - (in) object from which the color profile data is to be fetched
+// color_profile - (out) color profile data
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if either mux or color_profile is NULL.
+// WEBP_MUX_NOT_FOUND - if color profile is not present in mux object.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxGetColorProfile(const WebPMux* mux,
+ WebPData* color_profile);
+
+// Deletes the color profile in the mux object.
+// Parameters:
+// mux - (in/out) object from which color profile is to be deleted
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL
+// WEBP_MUX_NOT_FOUND - If mux does not contain color profile.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxDeleteColorProfile(WebPMux* mux);
+
+//------------------------------------------------------------------------------
+// Animation.
+
+// Adds an animation frame at the end of the mux object.
+// Note: as WebP only supports even offsets, any odd offset will be snapped to
+// an even location using: offset &= ~1
+// Parameters:
+// mux - (in/out) object to which an animation frame is to be added
+// bitstream - (in) the image data corresponding to the frame. It can either
+// be a raw VP8/VP8L bitstream or a single-image WebP file
+// (non-animated and non-tiled)
+// x_offset - (in) x-offset of the frame to be added
+// y_offset - (in) y-offset of the frame to be added
+// duration - (in) duration of the frame to be added (in milliseconds)
+// copy_data - (in) value 1 indicates given data WILL copied to the mux, and
+// value 0 indicates data will NOT be copied.
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL
+// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxPushFrame(
+ WebPMux* mux, const WebPData* bitstream,
+ int x_offset, int y_offset, int duration, int copy_data);
+
+// TODO(urvang): Create a struct as follows to reduce argument list size:
+// typedef struct {
+// WebPData bitstream;
+// int x_offset, y_offset;
+// int duration;
+// } FrameInfo;
+
+// Gets the nth animation frame from the mux object.
+// The content of 'bitstream' is allocated using malloc(), and NOT
+// owned by the 'mux' object. It MUST be deallocated by the caller by calling
+// WebPDataClear().
+// nth=0 has a special meaning - last position.
+// Parameters:
+// mux - (in) object from which the info is to be fetched
+// nth - (in) index of the frame in the mux object
+// bitstream - (out) the image data
+// x_offset - (out) x-offset of the returned frame
+// y_offset - (out) y-offset of the returned frame
+// duration - (out) duration of the returned frame (in milliseconds)
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if either mux, bitstream, x_offset,
+// y_offset, or duration is NULL
+// WEBP_MUX_NOT_FOUND - if there are less than nth frames in the mux object.
+// WEBP_MUX_BAD_DATA - if nth frame chunk in mux is invalid.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxGetFrame(
+ const WebPMux* mux, uint32_t nth, WebPData* bitstream,
+ int* x_offset, int* y_offset, int* duration);
+
+// Deletes an animation frame from the mux object.
+// nth=0 has a special meaning - last position.
+// Parameters:
+// mux - (in/out) object from which a frame is to be deleted
+// nth - (in) The position from which the frame is to be deleted
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL
+// WEBP_MUX_NOT_FOUND - If there are less than nth frames in the mux object
+// before deletion.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth);
+
+// Sets the animation loop count in the mux object. Any existing loop count
+// value(s) will be removed.
+// Parameters:
+// mux - (in/out) object in which loop chunk is to be set/added
+// loop_count - (in) animation loop count value.
+// Note that loop_count of zero denotes infinite loop.
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL
+// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxSetLoopCount(WebPMux* mux, int loop_count);
+
+// Gets the animation loop count from the mux object.
+// Parameters:
+// mux - (in) object from which the loop count is to be fetched
+// loop_count - (out) the loop_count value present in the LOOP chunk
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if either of mux or loop_count is NULL
+// WEBP_MUX_NOT_FOUND - if loop chunk is not present in mux object.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxGetLoopCount(const WebPMux* mux,
+ int* loop_count);
+
+//------------------------------------------------------------------------------
+// Tiling.
+
+// Adds a tile at the end of the mux object.
+// Note: as WebP only supports even offsets, any odd offset will be snapped to
+// an even location using: offset &= ~1
+// Parameters:
+// mux - (in/out) object to which a tile is to be added.
+// bitstream - (in) the image data corresponding to the frame. It can either
+// be a raw VP8/VP8L bitstream or a single-image WebP file
+// (non-animated and non-tiled)
+// x_offset - (in) x-offset of the tile to be added
+// y_offset - (in) y-offset of the tile to be added
+// copy_data - (in) value 1 indicates given data WILL copied to the mux, and
+// value 0 indicates data will NOT be copied.
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL
+// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxPushTile(
+ WebPMux* mux, const WebPData* bitstream,
+ int x_offset, int y_offset, int copy_data);
+
+// Gets the nth tile from the mux object.
+// The content of 'bitstream' is allocated using malloc(), and NOT
+// owned by the 'mux' object. It MUST be deallocated by the caller by calling
+// WebPDataClear().
+// nth=0 has a special meaning - last position.
+// Parameters:
+// mux - (in) object from which the info is to be fetched
+// nth - (in) index of the tile in the mux object
+// bitstream - (out) the image data
+// x_offset - (out) x-offset of the returned tile
+// y_offset - (out) y-offset of the returned tile
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if either mux, bitstream, x_offset or
+// y_offset is NULL
+// WEBP_MUX_NOT_FOUND - if there are less than nth tiles in the mux object.
+// WEBP_MUX_BAD_DATA - if nth tile chunk in mux is invalid.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxGetTile(
+ const WebPMux* mux, uint32_t nth, WebPData* bitstream,
+ int* x_offset, int* y_offset);
+
+// Deletes a tile from the mux object.
+// nth=0 has a special meaning - last position
+// Parameters:
+// mux - (in/out) object from which a tile is to be deleted
+// nth - (in) The position from which the tile is to be deleted
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL
+// WEBP_MUX_NOT_FOUND - If there are less than nth tiles in the mux object
+// before deletion.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxDeleteTile(WebPMux* mux, uint32_t nth);
+
+//------------------------------------------------------------------------------
+// Misc Utilities.
+
+// Gets the feature flags from the mux object.
+// Parameters:
+// mux - (in) object from which the features are to be fetched
+// flags - (out) the flags specifying which features are present in the
+// mux object. This will be an OR of various flag values.
+// Enum 'WebPFeatureFlags' can be used to test individual flag values.
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if mux or flags is NULL
+// WEBP_MUX_NOT_FOUND - if VP8X chunk is not present in mux object.
+// WEBP_MUX_BAD_DATA - if VP8X chunk in mux is invalid.
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxGetFeatures(const WebPMux* mux,
+ uint32_t* flags);
+
+// Gets number of chunks having tag value tag in the mux object.
+// Parameters:
+// mux - (in) object from which the info is to be fetched
+// id - (in) chunk id specifying the type of chunk
+// num_elements - (out) number of chunks with the given chunk id
+// Returns:
+// WEBP_MUX_INVALID_ARGUMENT - if either mux, or num_elements is NULL
+// WEBP_MUX_OK - on success.
+WEBP_EXTERN(WebPMuxError) WebPMuxNumChunks(const WebPMux* mux,
+ WebPChunkId id, int* num_elements);
+
+// Assembles all chunks in WebP RIFF format and returns in 'assembled_data'.
+// This function also validates the mux object.
+// Note: The content of 'assembled_data' will be ignored and overwritten.
+// Also, the content of 'assembled_data' is allocated using malloc(), and NOT
+// owned by the 'mux' object. It MUST be deallocated by the caller by calling
+// WebPDataClear().
+// Parameters:
+// mux - (in/out) object whose chunks are to be assembled
+// assembled_data - (out) assembled WebP data
+// Returns:
+// WEBP_MUX_BAD_DATA - if mux object is invalid.
+// WEBP_MUX_INVALID_ARGUMENT - if either mux, output_data or output_size is
+// NULL.
+// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
+// WEBP_MUX_OK - on success
+WEBP_EXTERN(WebPMuxError) WebPMuxAssemble(WebPMux* mux,
+ WebPData* assembled_data);
+
+//------------------------------------------------------------------------------
+// Demux API.
+// Enables extraction of image and extended format data from WebP files.
+
+#define WEBP_DEMUX_ABI_VERSION 0x0100 // MAJOR(8b) + MINOR(8b)
+
+typedef struct WebPDemuxer WebPDemuxer;
+
+typedef enum {
+ WEBP_DEMUX_PARSING_HEADER, // Not enough data to parse full header.
+ WEBP_DEMUX_PARSED_HEADER, // Header parsing complete, data may be available.
+ WEBP_DEMUX_DONE // Entire file has been parsed.
+} WebPDemuxState;
+
+//------------------------------------------------------------------------------
+// Life of a Demux object
+
+// Internal, version-checked, entry point
+WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal(
+ const WebPData*, int, WebPDemuxState*, int);
+
+// Parses the WebP file given by 'data'.
+// A complete WebP file must be present in 'data' for the function to succeed.
+// Returns a WebPDemuxer object on successful parse, NULL otherwise.
+static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) {
+ return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION);
+}
+
+// Parses the WebP file given by 'data'.
+// If 'state' is non-NULL it will be set to indicate the status of the demuxer.
+// Returns a WebPDemuxer object on successful parse, NULL otherwise.
+static WEBP_INLINE WebPDemuxer* WebPDemuxPartial(
+ const WebPData* data, WebPDemuxState* state) {
+ return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION);
+}
+
+// Frees memory associated with 'dmux'.
+WEBP_EXTERN(void) WebPDemuxDelete(WebPDemuxer* dmux);
+
+//------------------------------------------------------------------------------
+// Data/information extraction.
+
+typedef enum {
+ WEBP_FF_FORMAT_FLAGS, // Extended format flags present in the 'VP8X' chunk.
+ WEBP_FF_CANVAS_WIDTH,
+ WEBP_FF_CANVAS_HEIGHT,
+ WEBP_FF_LOOP_COUNT
+} WebPFormatFeature;
+
+// Get the 'feature' value from the 'dmux'.
+// NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial()
+// returned a state > WEBP_DEMUX_PARSING_HEADER.
+WEBP_EXTERN(uint32_t) WebPDemuxGetI(
+ const WebPDemuxer* dmux, WebPFormatFeature feature);
+
+//------------------------------------------------------------------------------
+// Frame iteration.
+
+typedef struct {
+ int frame_num_;
+ int num_frames_;
+ int tile_num_;
+ int num_tiles_;
+ int x_offset_, y_offset_; // offset relative to the canvas.
+ int width_, height_; // dimensions of this frame or tile.
+ int duration_; // display duration in milliseconds.
+ int complete_; // true if 'tile_' contains a full frame. partial images may
+ // still be decoded with the WebP incremental decoder.
+ WebPData tile_; // The frame or tile given by 'frame_num_' and 'tile_num_'.
+
+ uint32_t pad[4]; // padding for later use
+ void* private_;
+} WebPIterator;
+
+// Retrieves frame 'frame_number' from 'dmux'.
+// 'iter->tile_' points to the first tile on return from this function.
+// Individual tiles may be extracted using WebPDemuxSetTile().
+// Setting 'frame_number' equal to 0 will return the last frame of the image.
+// Returns false if 'dmux' is NULL or frame 'frame_number' is not present.
+// Call WebPDemuxReleaseIterator() when use of the iterator is complete.
+// NOTE: 'dmux' must persist for the lifetime of 'iter'.
+WEBP_EXTERN(int) WebPDemuxGetFrame(
+ const WebPDemuxer* dmux, int frame_number, WebPIterator* iter);
+
+// Sets 'iter->tile_' to point to the next ('iter->frame_num_' + 1) or previous
+// ('iter->frame_num_' - 1) frame. These functions do not loop.
+// Returns true on success, false otherwise.
+WEBP_EXTERN(int) WebPDemuxNextFrame(WebPIterator* iter);
+WEBP_EXTERN(int) WebPDemuxPrevFrame(WebPIterator* iter);
+
+// Sets 'iter->tile_' to reflect tile number 'tile_number'.
+// Returns true if tile 'tile_number' is present, false otherwise.
+WEBP_EXTERN(int) WebPDemuxSelectTile(WebPIterator* iter, int tile_number);
+
+// Releases any memory associated with 'iter'.
+// Must be called before destroying the associated WebPDemuxer with
+// WebPDemuxDelete().
+WEBP_EXTERN(void) WebPDemuxReleaseIterator(WebPIterator* iter);
+
+//------------------------------------------------------------------------------
+// Chunk iteration.
+
+typedef struct {
+ // The current and total number of chunks with the fourcc given to
+ // WebPDemuxGetChunk().
+ int chunk_num_;
+ int num_chunks_;
+ WebPData chunk_; // The payload of the chunk.
+
+ uint32_t pad[6]; // padding for later use
+ void* private_;
+} WebPChunkIterator;
+
+// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from
+// 'dmux'.
+// 'fourcc' is a character array containing the fourcc of the chunk to return,
+// e.g., "ICCP", "META", "EXIF", etc.
+// Setting 'chunk_number' equal to 0 will return the last chunk in a set.
+// Returns true if the chunk is found, false otherwise. Image related chunk
+// payloads are accessed through WebPDemuxGetFrame() and related functions.
+// Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete.
+// NOTE: 'dmux' must persist for the lifetime of the iterator.
+WEBP_EXTERN(int) WebPDemuxGetChunk(const WebPDemuxer* dmux,
+ const char fourcc[4], int chunk_number,
+ WebPChunkIterator* iter);
+
+// Sets 'iter->chunk_' to point to the next ('iter->chunk_num_' + 1) or previous
+// ('iter->chunk_num_' - 1) chunk. These functions do not loop.
+// Returns true on success, false otherwise.
+WEBP_EXTERN(int) WebPDemuxNextChunk(WebPChunkIterator* iter);
+WEBP_EXTERN(int) WebPDemuxPrevChunk(WebPChunkIterator* iter);
+
+// Releases any memory associated with 'iter'.
+// Must be called before destroying the associated WebPDemuxer with
+// WebPDemuxDelete().
+WEBP_EXTERN(void) WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter);
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_WEBP_MUX_H_ */
diff --git a/drivers/webp/mux/demux.c b/drivers/webpold/mux/demux.c
index 501d08f41d..501d08f41d 100644
--- a/drivers/webp/mux/demux.c
+++ b/drivers/webpold/mux/demux.c
diff --git a/drivers/webpold/mux/muxedit.c b/drivers/webpold/mux/muxedit.c
new file mode 100644
index 0000000000..08629d4ae2
--- /dev/null
+++ b/drivers/webpold/mux/muxedit.c
@@ -0,0 +1,712 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Set and delete APIs for mux.
+//
+// Authors: Urvang (urvang@google.com)
+// Vikas (vikasa@google.com)
+
+#include <assert.h>
+#include "./muxi.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Life of a mux object.
+
+static void MuxInit(WebPMux* const mux) {
+ if (mux == NULL) return;
+ memset(mux, 0, sizeof(*mux));
+}
+
+WebPMux* WebPNewInternal(int version) {
+ if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_MUX_ABI_VERSION)) {
+ return NULL;
+ } else {
+ WebPMux* const mux = (WebPMux*)malloc(sizeof(WebPMux));
+ // If mux is NULL MuxInit is a noop.
+ MuxInit(mux);
+ return mux;
+ }
+}
+
+static void DeleteAllChunks(WebPChunk** const chunk_list) {
+ while (*chunk_list) {
+ *chunk_list = ChunkDelete(*chunk_list);
+ }
+}
+
+static void MuxRelease(WebPMux* const mux) {
+ if (mux == NULL) return;
+ MuxImageDeleteAll(&mux->images_);
+ DeleteAllChunks(&mux->vp8x_);
+ DeleteAllChunks(&mux->iccp_);
+ DeleteAllChunks(&mux->loop_);
+ DeleteAllChunks(&mux->meta_);
+ DeleteAllChunks(&mux->unknown_);
+}
+
+void WebPMuxDelete(WebPMux* mux) {
+ // If mux is NULL MuxRelease is a noop.
+ MuxRelease(mux);
+ free(mux);
+}
+
+//------------------------------------------------------------------------------
+// Helper method(s).
+
+// Handy MACRO, makes MuxSet() very symmetric to MuxGet().
+#define SWITCH_ID_LIST(INDEX, LIST) \
+ if (idx == (INDEX)) { \
+ err = ChunkAssignData(&chunk, data, copy_data, kChunks[(INDEX)].tag); \
+ if (err == WEBP_MUX_OK) { \
+ err = ChunkSetNth(&chunk, (LIST), nth); \
+ } \
+ return err; \
+ }
+
+static WebPMuxError MuxSet(WebPMux* const mux, CHUNK_INDEX idx, uint32_t nth,
+ const WebPData* const data, int copy_data) {
+ WebPChunk chunk;
+ WebPMuxError err = WEBP_MUX_NOT_FOUND;
+ assert(mux != NULL);
+ assert(!IsWPI(kChunks[idx].id));
+
+ ChunkInit(&chunk);
+ SWITCH_ID_LIST(IDX_VP8X, &mux->vp8x_);
+ SWITCH_ID_LIST(IDX_ICCP, &mux->iccp_);
+ SWITCH_ID_LIST(IDX_LOOP, &mux->loop_);
+ SWITCH_ID_LIST(IDX_META, &mux->meta_);
+ if (idx == IDX_UNKNOWN && data->size_ > TAG_SIZE) {
+ // For raw-data unknown chunk, the first four bytes should be the tag to be
+ // used for the chunk.
+ const WebPData tmp = { data->bytes_ + TAG_SIZE, data->size_ - TAG_SIZE };
+ err = ChunkAssignData(&chunk, &tmp, copy_data, GetLE32(data->bytes_ + 0));
+ if (err == WEBP_MUX_OK)
+ err = ChunkSetNth(&chunk, &mux->unknown_, nth);
+ }
+ return err;
+}
+#undef SWITCH_ID_LIST
+
+static WebPMuxError MuxAddChunk(WebPMux* const mux, uint32_t nth, uint32_t tag,
+ const uint8_t* data, size_t size,
+ int copy_data) {
+ const CHUNK_INDEX idx = ChunkGetIndexFromTag(tag);
+ const WebPData chunk_data = { data, size };
+ assert(mux != NULL);
+ assert(size <= MAX_CHUNK_PAYLOAD);
+ assert(idx != IDX_NIL);
+ return MuxSet(mux, idx, nth, &chunk_data, copy_data);
+}
+
+// Create data for frame/tile given image data, offsets and duration.
+static WebPMuxError CreateFrameTileData(const WebPData* const image,
+ int x_offset, int y_offset,
+ int duration, int is_lossless,
+ int is_frame,
+ WebPData* const frame_tile) {
+ int width;
+ int height;
+ uint8_t* frame_tile_bytes;
+ const size_t frame_tile_size = kChunks[is_frame ? IDX_FRAME : IDX_TILE].size;
+
+ const int ok = is_lossless ?
+ VP8LGetInfo(image->bytes_, image->size_, &width, &height, NULL) :
+ VP8GetInfo(image->bytes_, image->size_, image->size_, &width, &height);
+ if (!ok) return WEBP_MUX_INVALID_ARGUMENT;
+
+ assert(width > 0 && height > 0 && duration > 0);
+ // Note: assertion on upper bounds is done in PutLE24().
+
+ frame_tile_bytes = (uint8_t*)malloc(frame_tile_size);
+ if (frame_tile_bytes == NULL) return WEBP_MUX_MEMORY_ERROR;
+
+ PutLE24(frame_tile_bytes + 0, x_offset / 2);
+ PutLE24(frame_tile_bytes + 3, y_offset / 2);
+
+ if (is_frame) {
+ PutLE24(frame_tile_bytes + 6, width - 1);
+ PutLE24(frame_tile_bytes + 9, height - 1);
+ PutLE24(frame_tile_bytes + 12, duration - 1);
+ }
+
+ frame_tile->bytes_ = frame_tile_bytes;
+ frame_tile->size_ = frame_tile_size;
+ return WEBP_MUX_OK;
+}
+
+// Outputs image data given a bitstream. The bitstream can either be a
+// single-image WebP file or raw VP8/VP8L data.
+// Also outputs 'is_lossless' to be true if the given bitstream is lossless.
+static WebPMuxError GetImageData(const WebPData* const bitstream,
+ WebPData* const image, WebPData* const alpha,
+ int* const is_lossless) {
+ WebPDataInit(alpha); // Default: no alpha.
+ if (bitstream->size_ < TAG_SIZE ||
+ memcmp(bitstream->bytes_, "RIFF", TAG_SIZE)) {
+ // It is NOT webp file data. Return input data as is.
+ *image = *bitstream;
+ } else {
+ // It is webp file data. Extract image data from it.
+ const WebPMuxImage* wpi;
+ WebPMux* const mux = WebPMuxCreate(bitstream, 0);
+ if (mux == NULL) return WEBP_MUX_BAD_DATA;
+ wpi = mux->images_;
+ assert(wpi != NULL && wpi->img_ != NULL);
+ *image = wpi->img_->data_;
+ if (wpi->alpha_ != NULL) {
+ *alpha = wpi->alpha_->data_;
+ }
+ WebPMuxDelete(mux);
+ }
+ *is_lossless = VP8LCheckSignature(image->bytes_, image->size_);
+ return WEBP_MUX_OK;
+}
+
+static WebPMuxError DeleteChunks(WebPChunk** chunk_list, uint32_t tag) {
+ WebPMuxError err = WEBP_MUX_NOT_FOUND;
+ assert(chunk_list);
+ while (*chunk_list) {
+ WebPChunk* const chunk = *chunk_list;
+ if (chunk->tag_ == tag) {
+ *chunk_list = ChunkDelete(chunk);
+ err = WEBP_MUX_OK;
+ } else {
+ chunk_list = &chunk->next_;
+ }
+ }
+ return err;
+}
+
+static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, CHUNK_INDEX idx) {
+ const WebPChunkId id = kChunks[idx].id;
+ WebPChunk** chunk_list;
+
+ if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ if (IsWPI(id)) return WEBP_MUX_INVALID_ARGUMENT;
+
+ chunk_list = MuxGetChunkListFromId(mux, id);
+ if (chunk_list == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+
+ return DeleteChunks(chunk_list, kChunks[idx].tag);
+}
+
+static WebPMuxError DeleteLoopCount(WebPMux* const mux) {
+ return MuxDeleteAllNamedData(mux, IDX_LOOP);
+}
+
+//------------------------------------------------------------------------------
+// Set API(s).
+
+WebPMuxError WebPMuxSetImage(WebPMux* mux,
+ const WebPData* bitstream, int copy_data) {
+ WebPMuxError err;
+ WebPChunk chunk;
+ WebPMuxImage wpi;
+ WebPData image;
+ WebPData alpha;
+ int is_lossless;
+ int image_tag;
+
+ if (mux == NULL || bitstream == NULL || bitstream->bytes_ == NULL ||
+ bitstream->size_ > MAX_CHUNK_PAYLOAD) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+
+ // If given data is for a whole webp file,
+ // extract only the VP8/VP8L data from it.
+ err = GetImageData(bitstream, &image, &alpha, &is_lossless);
+ if (err != WEBP_MUX_OK) return err;
+ image_tag = is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag;
+
+ // Delete the existing images.
+ MuxImageDeleteAll(&mux->images_);
+
+ MuxImageInit(&wpi);
+
+ if (alpha.bytes_ != NULL) { // Add alpha chunk.
+ ChunkInit(&chunk);
+ err = ChunkAssignData(&chunk, &alpha, copy_data, kChunks[IDX_ALPHA].tag);
+ if (err != WEBP_MUX_OK) goto Err;
+ err = ChunkSetNth(&chunk, &wpi.alpha_, 1);
+ if (err != WEBP_MUX_OK) goto Err;
+ }
+
+ // Add image chunk.
+ ChunkInit(&chunk);
+ err = ChunkAssignData(&chunk, &image, copy_data, image_tag);
+ if (err != WEBP_MUX_OK) goto Err;
+ err = ChunkSetNth(&chunk, &wpi.img_, 1);
+ if (err != WEBP_MUX_OK) goto Err;
+
+ // Add this image to mux.
+ err = MuxImagePush(&wpi, &mux->images_);
+ if (err != WEBP_MUX_OK) goto Err;
+
+ // All OK.
+ return WEBP_MUX_OK;
+
+ Err:
+ // Something bad happened.
+ ChunkRelease(&chunk);
+ MuxImageRelease(&wpi);
+ return err;
+}
+
+WebPMuxError WebPMuxSetMetadata(WebPMux* mux, const WebPData* metadata,
+ int copy_data) {
+ WebPMuxError err;
+
+ if (mux == NULL || metadata == NULL || metadata->bytes_ == NULL ||
+ metadata->size_ > MAX_CHUNK_PAYLOAD) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+
+ // Delete the existing metadata chunk(s).
+ err = WebPMuxDeleteMetadata(mux);
+ if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
+
+ // Add the given metadata chunk.
+ return MuxSet(mux, IDX_META, 1, metadata, copy_data);
+}
+
+WebPMuxError WebPMuxSetColorProfile(WebPMux* mux, const WebPData* color_profile,
+ int copy_data) {
+ WebPMuxError err;
+
+ if (mux == NULL || color_profile == NULL || color_profile->bytes_ == NULL ||
+ color_profile->size_ > MAX_CHUNK_PAYLOAD) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+
+ // Delete the existing ICCP chunk(s).
+ err = WebPMuxDeleteColorProfile(mux);
+ if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
+
+ // Add the given ICCP chunk.
+ return MuxSet(mux, IDX_ICCP, 1, color_profile, copy_data);
+}
+
+WebPMuxError WebPMuxSetLoopCount(WebPMux* mux, int loop_count) {
+ WebPMuxError err;
+ uint8_t* data = NULL;
+
+ if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ if (loop_count >= MAX_LOOP_COUNT) return WEBP_MUX_INVALID_ARGUMENT;
+
+ // Delete the existing LOOP chunk(s).
+ err = DeleteLoopCount(mux);
+ if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
+
+ // Add the given loop count.
+ data = (uint8_t*)malloc(kChunks[IDX_LOOP].size);
+ if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
+
+ PutLE16(data, loop_count);
+ err = MuxAddChunk(mux, 1, kChunks[IDX_LOOP].tag, data,
+ kChunks[IDX_LOOP].size, 1);
+ free(data);
+ return err;
+}
+
+static WebPMuxError MuxPushFrameTileInternal(
+ WebPMux* const mux, const WebPData* const bitstream, int x_offset,
+ int y_offset, int duration, int copy_data, uint32_t tag) {
+ WebPChunk chunk;
+ WebPData image;
+ WebPData alpha;
+ WebPMuxImage wpi;
+ WebPMuxError err;
+ WebPData frame_tile;
+ const int is_frame = (tag == kChunks[IDX_FRAME].tag) ? 1 : 0;
+ int is_lossless;
+ int image_tag;
+
+ // Sanity checks.
+ if (mux == NULL || bitstream == NULL || bitstream->bytes_ == NULL ||
+ bitstream->size_ > MAX_CHUNK_PAYLOAD) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+ if (x_offset < 0 || x_offset >= MAX_POSITION_OFFSET ||
+ y_offset < 0 || y_offset >= MAX_POSITION_OFFSET ||
+ duration <= 0 || duration > MAX_DURATION) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+
+ // Snap offsets to even positions.
+ x_offset &= ~1;
+ y_offset &= ~1;
+
+ // If given data is for a whole webp file,
+ // extract only the VP8/VP8L data from it.
+ err = GetImageData(bitstream, &image, &alpha, &is_lossless);
+ if (err != WEBP_MUX_OK) return err;
+ image_tag = is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag;
+
+ WebPDataInit(&frame_tile);
+ ChunkInit(&chunk);
+ MuxImageInit(&wpi);
+
+ if (alpha.bytes_ != NULL) {
+ // Add alpha chunk.
+ err = ChunkAssignData(&chunk, &alpha, copy_data, kChunks[IDX_ALPHA].tag);
+ if (err != WEBP_MUX_OK) goto Err;
+ err = ChunkSetNth(&chunk, &wpi.alpha_, 1);
+ if (err != WEBP_MUX_OK) goto Err;
+ ChunkInit(&chunk); // chunk owned by wpi.alpha_ now.
+ }
+
+ // Add image chunk.
+ err = ChunkAssignData(&chunk, &image, copy_data, image_tag);
+ if (err != WEBP_MUX_OK) goto Err;
+ err = ChunkSetNth(&chunk, &wpi.img_, 1);
+ if (err != WEBP_MUX_OK) goto Err;
+ ChunkInit(&chunk); // chunk owned by wpi.img_ now.
+
+ // Create frame/tile data.
+ err = CreateFrameTileData(&image, x_offset, y_offset, duration, is_lossless,
+ is_frame, &frame_tile);
+ if (err != WEBP_MUX_OK) goto Err;
+
+ // Add frame/tile chunk (with copy_data = 1).
+ err = ChunkAssignData(&chunk, &frame_tile, 1, tag);
+ if (err != WEBP_MUX_OK) goto Err;
+ WebPDataClear(&frame_tile);
+ err = ChunkSetNth(&chunk, &wpi.header_, 1);
+ if (err != WEBP_MUX_OK) goto Err;
+ ChunkInit(&chunk); // chunk owned by wpi.header_ now.
+
+ // Add this WebPMuxImage to mux.
+ err = MuxImagePush(&wpi, &mux->images_);
+ if (err != WEBP_MUX_OK) goto Err;
+
+ // All is well.
+ return WEBP_MUX_OK;
+
+ Err: // Something bad happened.
+ WebPDataClear(&frame_tile);
+ ChunkRelease(&chunk);
+ MuxImageRelease(&wpi);
+ return err;
+}
+
+WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPData* bitstream,
+ int x_offset, int y_offset,
+ int duration, int copy_data) {
+ return MuxPushFrameTileInternal(mux, bitstream, x_offset, y_offset,
+ duration, copy_data, kChunks[IDX_FRAME].tag);
+}
+
+WebPMuxError WebPMuxPushTile(WebPMux* mux, const WebPData* bitstream,
+ int x_offset, int y_offset,
+ int copy_data) {
+ return MuxPushFrameTileInternal(mux, bitstream, x_offset, y_offset,
+ 1 /* unused duration */, copy_data,
+ kChunks[IDX_TILE].tag);
+}
+
+//------------------------------------------------------------------------------
+// Delete API(s).
+
+WebPMuxError WebPMuxDeleteImage(WebPMux* mux) {
+ WebPMuxError err;
+
+ if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+
+ err = MuxValidateForImage(mux);
+ if (err != WEBP_MUX_OK) return err;
+
+ // All well, delete image.
+ MuxImageDeleteAll(&mux->images_);
+ return WEBP_MUX_OK;
+}
+
+WebPMuxError WebPMuxDeleteMetadata(WebPMux* mux) {
+ return MuxDeleteAllNamedData(mux, IDX_META);
+}
+
+WebPMuxError WebPMuxDeleteColorProfile(WebPMux* mux) {
+ return MuxDeleteAllNamedData(mux, IDX_ICCP);
+}
+
+static WebPMuxError DeleteFrameTileInternal(WebPMux* const mux, uint32_t nth,
+ CHUNK_INDEX idx) {
+ const WebPChunkId id = kChunks[idx].id;
+ if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+
+ assert(idx == IDX_FRAME || idx == IDX_TILE);
+ return MuxImageDeleteNth(&mux->images_, nth, id);
+}
+
+WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) {
+ return DeleteFrameTileInternal(mux, nth, IDX_FRAME);
+}
+
+WebPMuxError WebPMuxDeleteTile(WebPMux* mux, uint32_t nth) {
+ return DeleteFrameTileInternal(mux, nth, IDX_TILE);
+}
+
+//------------------------------------------------------------------------------
+// Assembly of the WebP RIFF file.
+
+static WebPMuxError GetFrameTileInfo(const WebPChunk* const frame_tile_chunk,
+ int* const x_offset, int* const y_offset,
+ int* const duration) {
+ const uint32_t tag = frame_tile_chunk->tag_;
+ const int is_frame = (tag == kChunks[IDX_FRAME].tag);
+ const WebPData* const data = &frame_tile_chunk->data_;
+ const size_t expected_data_size =
+ is_frame ? FRAME_CHUNK_SIZE : TILE_CHUNK_SIZE;
+ assert(frame_tile_chunk != NULL);
+ assert(tag == kChunks[IDX_FRAME].tag || tag == kChunks[IDX_TILE].tag);
+ if (data->size_ != expected_data_size) return WEBP_MUX_INVALID_ARGUMENT;
+
+ *x_offset = 2 * GetLE24(data->bytes_ + 0);
+ *y_offset = 2 * GetLE24(data->bytes_ + 3);
+ if (is_frame) *duration = 1 + GetLE24(data->bytes_ + 12);
+ return WEBP_MUX_OK;
+}
+
+WebPMuxError MuxGetImageWidthHeight(const WebPChunk* const image_chunk,
+ int* const width, int* const height) {
+ const uint32_t tag = image_chunk->tag_;
+ const WebPData* const data = &image_chunk->data_;
+ int w, h;
+ int ok;
+ assert(image_chunk != NULL);
+ assert(tag == kChunks[IDX_VP8].tag || tag == kChunks[IDX_VP8L].tag);
+ ok = (tag == kChunks[IDX_VP8].tag) ?
+ VP8GetInfo(data->bytes_, data->size_, data->size_, &w, &h) :
+ VP8LGetInfo(data->bytes_, data->size_, &w, &h, NULL);
+ if (ok) {
+ *width = w;
+ *height = h;
+ return WEBP_MUX_OK;
+ } else {
+ return WEBP_MUX_BAD_DATA;
+ }
+}
+
+static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi,
+ int* const x_offset, int* const y_offset,
+ int* const duration,
+ int* const width, int* const height) {
+ const WebPChunk* const image_chunk = wpi->img_;
+ const WebPChunk* const frame_tile_chunk = wpi->header_;
+
+ // Get offsets and duration from FRM/TILE chunk.
+ const WebPMuxError err =
+ GetFrameTileInfo(frame_tile_chunk, x_offset, y_offset, duration);
+ if (err != WEBP_MUX_OK) return err;
+
+ // Get width and height from VP8/VP8L chunk.
+ return MuxGetImageWidthHeight(image_chunk, width, height);
+}
+
+static WebPMuxError GetImageCanvasWidthHeight(
+ const WebPMux* const mux, uint32_t flags,
+ int* const width, int* const height) {
+ WebPMuxImage* wpi = NULL;
+ assert(mux != NULL);
+ assert(width != NULL && height != NULL);
+
+ wpi = mux->images_;
+ assert(wpi != NULL);
+ assert(wpi->img_ != NULL);
+
+ if (wpi->next_) {
+ int max_x = 0;
+ int max_y = 0;
+ int64_t image_area = 0;
+ // Aggregate the bounding box for animation frames & tiled images.
+ for (; wpi != NULL; wpi = wpi->next_) {
+ int x_offset, y_offset, duration, w, h;
+ const WebPMuxError err = GetImageInfo(wpi, &x_offset, &y_offset,
+ &duration, &w, &h);
+ const int max_x_pos = x_offset + w;
+ const int max_y_pos = y_offset + h;
+ if (err != WEBP_MUX_OK) return err;
+ assert(x_offset < MAX_POSITION_OFFSET);
+ assert(y_offset < MAX_POSITION_OFFSET);
+
+ if (max_x_pos > max_x) max_x = max_x_pos;
+ if (max_y_pos > max_y) max_y = max_y_pos;
+ image_area += w * h;
+ }
+ *width = max_x;
+ *height = max_y;
+ // Crude check to validate that there are no image overlaps/holes for tile
+ // images. Check that the aggregated image area for individual tiles exactly
+ // matches the image area of the constructed canvas. However, the area-match
+ // is necessary but not sufficient condition.
+ if ((flags & TILE_FLAG) && (image_area != (max_x * max_y))) {
+ *width = 0;
+ *height = 0;
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+ } else {
+ // For a single image, extract the width & height from VP8/VP8L image-data.
+ int w, h;
+ const WebPChunk* const image_chunk = wpi->img_;
+ const WebPMuxError err = MuxGetImageWidthHeight(image_chunk, &w, &h);
+ if (err != WEBP_MUX_OK) return err;
+ *width = w;
+ *height = h;
+ }
+ return WEBP_MUX_OK;
+}
+
+// VP8X format:
+// Total Size : 10,
+// Flags : 4 bytes,
+// Width : 3 bytes,
+// Height : 3 bytes.
+static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
+ WebPMuxError err = WEBP_MUX_OK;
+ uint32_t flags = 0;
+ int width = 0;
+ int height = 0;
+ uint8_t data[VP8X_CHUNK_SIZE];
+ const size_t data_size = VP8X_CHUNK_SIZE;
+ const WebPMuxImage* images = NULL;
+
+ assert(mux != NULL);
+ images = mux->images_; // First image.
+ if (images == NULL || images->img_ == NULL ||
+ images->img_->data_.bytes_ == NULL) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+
+ // If VP8X chunk(s) is(are) already present, remove them (and later add new
+ // VP8X chunk with updated flags).
+ err = MuxDeleteAllNamedData(mux, IDX_VP8X);
+ if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
+
+ // Set flags.
+ if (mux->iccp_ != NULL && mux->iccp_->data_.bytes_ != NULL) {
+ flags |= ICCP_FLAG;
+ }
+
+ if (mux->meta_ != NULL && mux->meta_->data_.bytes_ != NULL) {
+ flags |= META_FLAG;
+ }
+
+ if (images->header_ != NULL) {
+ if (images->header_->tag_ == kChunks[IDX_TILE].tag) {
+ // This is a tiled image.
+ flags |= TILE_FLAG;
+ } else if (images->header_->tag_ == kChunks[IDX_FRAME].tag) {
+ // This is an image with animation.
+ flags |= ANIMATION_FLAG;
+ }
+ }
+
+ if (MuxImageCount(images, WEBP_CHUNK_ALPHA) > 0) {
+ flags |= ALPHA_FLAG; // Some images have an alpha channel.
+ }
+
+ if (flags == 0) {
+ // For Simple Image, VP8X chunk should not be added.
+ return WEBP_MUX_OK;
+ }
+
+ err = GetImageCanvasWidthHeight(mux, flags, &width, &height);
+ if (err != WEBP_MUX_OK) return err;
+
+ if (width <= 0 || height <= 0) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+ if (width > MAX_CANVAS_SIZE || height > MAX_CANVAS_SIZE) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+
+ if (MuxHasLosslessImages(images)) {
+ // We have a file with a VP8X chunk having some lossless images.
+ // As lossless images implicitly contain alpha, force ALPHA_FLAG to be true.
+ // Note: This 'flags' update must NOT be done for a lossless image
+ // without a VP8X chunk!
+ flags |= ALPHA_FLAG;
+ }
+
+ PutLE32(data + 0, flags); // VP8X chunk flags.
+ PutLE24(data + 4, width - 1); // canvas width.
+ PutLE24(data + 7, height - 1); // canvas height.
+
+ err = MuxAddChunk(mux, 1, kChunks[IDX_VP8X].tag, data, data_size, 1);
+ return err;
+}
+
+WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) {
+ size_t size = 0;
+ uint8_t* data = NULL;
+ uint8_t* dst = NULL;
+ int num_frames;
+ int num_loop_chunks;
+ WebPMuxError err;
+
+ if (mux == NULL || assembled_data == NULL) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+
+ // Remove LOOP chunk if unnecessary.
+ err = WebPMuxNumChunks(mux, kChunks[IDX_LOOP].id, &num_loop_chunks);
+ if (err != WEBP_MUX_OK) return err;
+ if (num_loop_chunks >= 1) {
+ err = WebPMuxNumChunks(mux, kChunks[IDX_FRAME].id, &num_frames);
+ if (err != WEBP_MUX_OK) return err;
+ if (num_frames == 0) {
+ err = DeleteLoopCount(mux);
+ if (err != WEBP_MUX_OK) return err;
+ }
+ }
+
+ // Create VP8X chunk.
+ err = CreateVP8XChunk(mux);
+ if (err != WEBP_MUX_OK) return err;
+
+ // Allocate data.
+ size = ChunksListDiskSize(mux->vp8x_) + ChunksListDiskSize(mux->iccp_)
+ + ChunksListDiskSize(mux->loop_) + MuxImageListDiskSize(mux->images_)
+ + ChunksListDiskSize(mux->meta_) + ChunksListDiskSize(mux->unknown_)
+ + RIFF_HEADER_SIZE;
+
+ data = (uint8_t*)malloc(size);
+ if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
+
+ // Emit header & chunks.
+ dst = MuxEmitRiffHeader(data, size);
+ dst = ChunkListEmit(mux->vp8x_, dst);
+ dst = ChunkListEmit(mux->iccp_, dst);
+ dst = ChunkListEmit(mux->loop_, dst);
+ dst = MuxImageListEmit(mux->images_, dst);
+ dst = ChunkListEmit(mux->meta_, dst);
+ dst = ChunkListEmit(mux->unknown_, dst);
+ assert(dst == data + size);
+
+ // Validate mux.
+ err = MuxValidate(mux);
+ if (err != WEBP_MUX_OK) {
+ free(data);
+ data = NULL;
+ size = 0;
+ }
+
+ // Finalize.
+ assembled_data->bytes_ = data;
+ assembled_data->size_ = size;
+
+ return err;
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/mux/muxi.h b/drivers/webpold/mux/muxi.h
new file mode 100644
index 0000000000..2f06f3ed03
--- /dev/null
+++ b/drivers/webpold/mux/muxi.h
@@ -0,0 +1,271 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Internal header for mux library.
+//
+// Author: Urvang (urvang@google.com)
+
+#ifndef WEBP_MUX_MUXI_H_
+#define WEBP_MUX_MUXI_H_
+
+#include <stdlib.h>
+#include "../dec/vp8i.h"
+#include "../dec/vp8li.h"
+#include "../format_constants.h"
+#include "../mux.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Defines and constants.
+
+// Chunk object.
+typedef struct WebPChunk WebPChunk;
+struct WebPChunk {
+ uint32_t tag_;
+ int owner_; // True if *data_ memory is owned internally.
+ // VP8X, Loop, and other internally created chunks
+ // like frame/tile are always owned.
+ WebPData data_;
+ WebPChunk* next_;
+};
+
+// MuxImage object. Store a full webp image (including frame/tile chunk, alpha
+// chunk and VP8/VP8L chunk),
+typedef struct WebPMuxImage WebPMuxImage;
+struct WebPMuxImage {
+ WebPChunk* header_; // Corresponds to WEBP_CHUNK_FRAME/WEBP_CHUNK_TILE.
+ WebPChunk* alpha_; // Corresponds to WEBP_CHUNK_ALPHA.
+ WebPChunk* img_; // Corresponds to WEBP_CHUNK_IMAGE.
+ int is_partial_; // True if only some of the chunks are filled.
+ WebPMuxImage* next_;
+};
+
+// Main mux object. Stores data chunks.
+struct WebPMux {
+ WebPMuxImage* images_;
+ WebPChunk* iccp_;
+ WebPChunk* meta_;
+ WebPChunk* loop_;
+ WebPChunk* vp8x_;
+
+ WebPChunk* unknown_;
+};
+
+// CHUNK_INDEX enum: used for indexing within 'kChunks' (defined below) only.
+// Note: the reason for having two enums ('WebPChunkId' and 'CHUNK_INDEX') is to
+// allow two different chunks to have the same id (e.g. WebPChunkId
+// 'WEBP_CHUNK_IMAGE' can correspond to CHUNK_INDEX 'IDX_VP8' or 'IDX_VP8L').
+typedef enum {
+ IDX_VP8X = 0,
+ IDX_ICCP,
+ IDX_LOOP,
+ IDX_FRAME,
+ IDX_TILE,
+ IDX_ALPHA,
+ IDX_VP8,
+ IDX_VP8L,
+ IDX_META,
+ IDX_UNKNOWN,
+
+ IDX_NIL,
+ IDX_LAST_CHUNK
+} CHUNK_INDEX;
+
+#define NIL_TAG 0x00000000u // To signal void chunk.
+
+#define MKFOURCC(a, b, c, d) ((uint32_t)(a) | (b) << 8 | (c) << 16 | (d) << 24)
+
+typedef struct {
+ uint32_t tag;
+ WebPChunkId id;
+ uint32_t size;
+} ChunkInfo;
+
+extern const ChunkInfo kChunks[IDX_LAST_CHUNK];
+
+//------------------------------------------------------------------------------
+// Helper functions.
+
+// Read 16, 24 or 32 bits stored in little-endian order.
+static WEBP_INLINE int GetLE16(const uint8_t* const data) {
+ return (int)(data[0] << 0) | (data[1] << 8);
+}
+
+static WEBP_INLINE int GetLE24(const uint8_t* const data) {
+ return GetLE16(data) | (data[2] << 16);
+}
+
+static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) {
+ return (uint32_t)GetLE16(data) | (GetLE16(data + 2) << 16);
+}
+
+// Store 16, 24 or 32 bits in little-endian order.
+static WEBP_INLINE void PutLE16(uint8_t* const data, int val) {
+ assert(val < (1 << 16));
+ data[0] = (val >> 0);
+ data[1] = (val >> 8);
+}
+
+static WEBP_INLINE void PutLE24(uint8_t* const data, int val) {
+ assert(val < (1 << 24));
+ PutLE16(data, val & 0xffff);
+ data[2] = (val >> 16);
+}
+
+static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) {
+ PutLE16(data, (int)(val & 0xffff));
+ PutLE16(data + 2, (int)(val >> 16));
+}
+
+static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) {
+ return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U);
+}
+
+//------------------------------------------------------------------------------
+// Chunk object management.
+
+// Initialize.
+void ChunkInit(WebPChunk* const chunk);
+
+// Get chunk index from chunk tag. Returns IDX_NIL if not found.
+CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag);
+
+// Get chunk id from chunk tag. Returns WEBP_CHUNK_NIL if not found.
+WebPChunkId ChunkGetIdFromTag(uint32_t tag);
+
+// Search for nth chunk with given 'tag' in the chunk list.
+// nth = 0 means "last of the list".
+WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag);
+
+// Fill the chunk with the given data.
+WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
+ int copy_data, uint32_t tag);
+
+// Sets 'chunk' at nth position in the 'chunk_list'.
+// nth = 0 has the special meaning "last of the list".
+WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
+ uint32_t nth);
+
+// Releases chunk and returns chunk->next_.
+WebPChunk* ChunkRelease(WebPChunk* const chunk);
+
+// Deletes given chunk & returns chunk->next_.
+WebPChunk* ChunkDelete(WebPChunk* const chunk);
+
+// Size of a chunk including header and padding.
+static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) {
+ const size_t data_size = chunk->data_.size_;
+ assert(data_size < MAX_CHUNK_PAYLOAD);
+ return SizeWithPadding(data_size);
+}
+
+// Total size of a list of chunks.
+size_t ChunksListDiskSize(const WebPChunk* chunk_list);
+
+// Write out the given list of chunks into 'dst'.
+uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst);
+
+// Get the width & height of image stored in 'image_chunk'.
+WebPMuxError MuxGetImageWidthHeight(const WebPChunk* const image_chunk,
+ int* const width, int* const height);
+
+//------------------------------------------------------------------------------
+// MuxImage object management.
+
+// Initialize.
+void MuxImageInit(WebPMuxImage* const wpi);
+
+// Releases image 'wpi' and returns wpi->next.
+WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi);
+
+// Delete image 'wpi' and return the next image in the list or NULL.
+// 'wpi' can be NULL.
+WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi);
+
+// Delete all images in 'wpi_list'.
+void MuxImageDeleteAll(WebPMuxImage** const wpi_list);
+
+// Count number of images matching the given tag id in the 'wpi_list'.
+int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id);
+
+// Check if given ID corresponds to an image related chunk.
+static WEBP_INLINE int IsWPI(WebPChunkId id) {
+ switch (id) {
+ case WEBP_CHUNK_FRAME:
+ case WEBP_CHUNK_TILE:
+ case WEBP_CHUNK_ALPHA:
+ case WEBP_CHUNK_IMAGE: return 1;
+ default: return 0;
+ }
+}
+
+// Get a reference to appropriate chunk list within an image given chunk tag.
+static WEBP_INLINE WebPChunk** MuxImageGetListFromId(
+ const WebPMuxImage* const wpi, WebPChunkId id) {
+ assert(wpi != NULL);
+ switch (id) {
+ case WEBP_CHUNK_FRAME:
+ case WEBP_CHUNK_TILE: return (WebPChunk**)&wpi->header_;
+ case WEBP_CHUNK_ALPHA: return (WebPChunk**)&wpi->alpha_;
+ case WEBP_CHUNK_IMAGE: return (WebPChunk**)&wpi->img_;
+ default: return NULL;
+ }
+}
+
+// Pushes 'wpi' at the end of 'wpi_list'.
+WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list);
+
+// Delete nth image in the image list with given tag id.
+WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth,
+ WebPChunkId id);
+
+// Get nth image in the image list with given tag id.
+WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth,
+ WebPChunkId id, WebPMuxImage** wpi);
+
+// Total size of the given image.
+size_t MuxImageDiskSize(const WebPMuxImage* const wpi);
+
+// Total size of a list of images.
+size_t MuxImageListDiskSize(const WebPMuxImage* wpi_list);
+
+// Write out the given image into 'dst'.
+uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst);
+
+// Write out the given list of images into 'dst'.
+uint8_t* MuxImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst);
+
+//------------------------------------------------------------------------------
+// Helper methods for mux.
+
+// Checks if the given image list contains at least one lossless image.
+int MuxHasLosslessImages(const WebPMuxImage* images);
+
+// Write out RIFF header into 'data', given total data size 'size'.
+uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size);
+
+// Returns the list where chunk with given ID is to be inserted in mux.
+// Return value is NULL if this chunk should be inserted in mux->images_ list
+// or if 'id' is not known.
+WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id);
+
+// Validates that the given mux has a single image.
+WebPMuxError MuxValidateForImage(const WebPMux* const mux);
+
+// Validates the given mux object.
+WebPMuxError MuxValidate(const WebPMux* const mux);
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_MUX_MUXI_H_ */
diff --git a/drivers/webpold/mux/muxinternal.c b/drivers/webpold/mux/muxinternal.c
new file mode 100644
index 0000000000..6c3c4fe60a
--- /dev/null
+++ b/drivers/webpold/mux/muxinternal.c
@@ -0,0 +1,576 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Internal objects and utils for mux.
+//
+// Authors: Urvang (urvang@google.com)
+// Vikas (vikasa@google.com)
+
+#include <assert.h>
+#include "./muxi.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define UNDEFINED_CHUNK_SIZE (-1)
+
+const ChunkInfo kChunks[] = {
+ { MKFOURCC('V', 'P', '8', 'X'), WEBP_CHUNK_VP8X, VP8X_CHUNK_SIZE },
+ { MKFOURCC('I', 'C', 'C', 'P'), WEBP_CHUNK_ICCP, UNDEFINED_CHUNK_SIZE },
+ { MKFOURCC('L', 'O', 'O', 'P'), WEBP_CHUNK_LOOP, LOOP_CHUNK_SIZE },
+ { MKFOURCC('F', 'R', 'M', ' '), WEBP_CHUNK_FRAME, FRAME_CHUNK_SIZE },
+ { MKFOURCC('T', 'I', 'L', 'E'), WEBP_CHUNK_TILE, TILE_CHUNK_SIZE },
+ { MKFOURCC('A', 'L', 'P', 'H'), WEBP_CHUNK_ALPHA, UNDEFINED_CHUNK_SIZE },
+ { MKFOURCC('V', 'P', '8', ' '), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
+ { MKFOURCC('V', 'P', '8', 'L'), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
+ { MKFOURCC('M', 'E', 'T', 'A'), WEBP_CHUNK_META, UNDEFINED_CHUNK_SIZE },
+ { MKFOURCC('U', 'N', 'K', 'N'), WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE },
+
+ { NIL_TAG, WEBP_CHUNK_NIL, UNDEFINED_CHUNK_SIZE }
+};
+
+//------------------------------------------------------------------------------
+// Life of a chunk object.
+
+void ChunkInit(WebPChunk* const chunk) {
+ assert(chunk);
+ memset(chunk, 0, sizeof(*chunk));
+ chunk->tag_ = NIL_TAG;
+}
+
+WebPChunk* ChunkRelease(WebPChunk* const chunk) {
+ WebPChunk* next;
+ if (chunk == NULL) return NULL;
+ if (chunk->owner_) {
+ WebPDataClear(&chunk->data_);
+ }
+ next = chunk->next_;
+ ChunkInit(chunk);
+ return next;
+}
+
+//------------------------------------------------------------------------------
+// Chunk misc methods.
+
+CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag) {
+ int i;
+ for (i = 0; kChunks[i].tag != NIL_TAG; ++i) {
+ if (tag == kChunks[i].tag) return i;
+ }
+ return IDX_NIL;
+}
+
+WebPChunkId ChunkGetIdFromTag(uint32_t tag) {
+ int i;
+ for (i = 0; kChunks[i].tag != NIL_TAG; ++i) {
+ if (tag == kChunks[i].tag) return kChunks[i].id;
+ }
+ return WEBP_CHUNK_NIL;
+}
+
+//------------------------------------------------------------------------------
+// Chunk search methods.
+
+// Returns next chunk in the chunk list with the given tag.
+static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) {
+ while (chunk && chunk->tag_ != tag) {
+ chunk = chunk->next_;
+ }
+ return chunk;
+}
+
+WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
+ uint32_t iter = nth;
+ first = ChunkSearchNextInList(first, tag);
+ if (!first) return NULL;
+
+ while (--iter != 0) {
+ WebPChunk* next_chunk = ChunkSearchNextInList(first->next_, tag);
+ if (next_chunk == NULL) break;
+ first = next_chunk;
+ }
+ return ((nth > 0) && (iter > 0)) ? NULL : first;
+}
+
+// Outputs a pointer to 'prev_chunk->next_',
+// where 'prev_chunk' is the pointer to the chunk at position (nth - 1).
+// Returns 1 if nth chunk was found, 0 otherwise.
+static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth,
+ WebPChunk*** const location) {
+ uint32_t count = 0;
+ assert(chunk_list);
+ *location = chunk_list;
+
+ while (*chunk_list) {
+ WebPChunk* const cur_chunk = *chunk_list;
+ ++count;
+ if (count == nth) return 1; // Found.
+ chunk_list = &cur_chunk->next_;
+ *location = chunk_list;
+ }
+
+ // *chunk_list is ok to be NULL if adding at last location.
+ return (nth == 0 || (count == nth - 1)) ? 1 : 0;
+}
+
+//------------------------------------------------------------------------------
+// Chunk writer methods.
+
+WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
+ int copy_data, uint32_t tag) {
+ // For internally allocated chunks, always copy data & make it owner of data.
+ if (tag == kChunks[IDX_VP8X].tag || tag == kChunks[IDX_LOOP].tag) {
+ copy_data = 1;
+ }
+
+ ChunkRelease(chunk);
+
+ if (data != NULL) {
+ if (copy_data) {
+ // Copy data.
+ chunk->data_.bytes_ = (uint8_t*)malloc(data->size_);
+ if (chunk->data_.bytes_ == NULL) return WEBP_MUX_MEMORY_ERROR;
+ memcpy((uint8_t*)chunk->data_.bytes_, data->bytes_, data->size_);
+ chunk->data_.size_ = data->size_;
+
+ // Chunk is owner of data.
+ chunk->owner_ = 1;
+ } else {
+ // Don't copy data.
+ chunk->data_ = *data;
+ }
+ }
+
+ chunk->tag_ = tag;
+
+ return WEBP_MUX_OK;
+}
+
+WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
+ uint32_t nth) {
+ WebPChunk* new_chunk;
+
+ if (!ChunkSearchListToSet(chunk_list, nth, &chunk_list)) {
+ return WEBP_MUX_NOT_FOUND;
+ }
+
+ new_chunk = (WebPChunk*)malloc(sizeof(*new_chunk));
+ if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR;
+ *new_chunk = *chunk;
+ new_chunk->next_ = *chunk_list;
+ *chunk_list = new_chunk;
+ return WEBP_MUX_OK;
+}
+
+//------------------------------------------------------------------------------
+// Chunk deletion method(s).
+
+WebPChunk* ChunkDelete(WebPChunk* const chunk) {
+ WebPChunk* const next = ChunkRelease(chunk);
+ free(chunk);
+ return next;
+}
+
+//------------------------------------------------------------------------------
+// Chunk serialization methods.
+
+size_t ChunksListDiskSize(const WebPChunk* chunk_list) {
+ size_t size = 0;
+ while (chunk_list) {
+ size += ChunkDiskSize(chunk_list);
+ chunk_list = chunk_list->next_;
+ }
+ return size;
+}
+
+static uint8_t* ChunkEmit(const WebPChunk* const chunk, uint8_t* dst) {
+ const size_t chunk_size = chunk->data_.size_;
+ assert(chunk);
+ assert(chunk->tag_ != NIL_TAG);
+ PutLE32(dst + 0, chunk->tag_);
+ PutLE32(dst + TAG_SIZE, (uint32_t)chunk_size);
+ assert(chunk_size == (uint32_t)chunk_size);
+ memcpy(dst + CHUNK_HEADER_SIZE, chunk->data_.bytes_, chunk_size);
+ if (chunk_size & 1)
+ dst[CHUNK_HEADER_SIZE + chunk_size] = 0; // Add padding.
+ return dst + ChunkDiskSize(chunk);
+}
+
+uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) {
+ while (chunk_list) {
+ dst = ChunkEmit(chunk_list, dst);
+ chunk_list = chunk_list->next_;
+ }
+ return dst;
+}
+
+//------------------------------------------------------------------------------
+// Manipulation of a WebPData object.
+
+void WebPDataInit(WebPData* webp_data) {
+ if (webp_data != NULL) {
+ memset(webp_data, 0, sizeof(*webp_data));
+ }
+}
+
+void WebPDataClear(WebPData* webp_data) {
+ if (webp_data != NULL) {
+ free((void*)webp_data->bytes_);
+ WebPDataInit(webp_data);
+ }
+}
+
+int WebPDataCopy(const WebPData* src, WebPData* dst) {
+ if (src == NULL || dst == NULL) return 0;
+
+ WebPDataInit(dst);
+ if (src->bytes_ != NULL && src->size_ != 0) {
+ dst->bytes_ = (uint8_t*)malloc(src->size_);
+ if (dst->bytes_ == NULL) return 0;
+ memcpy((void*)dst->bytes_, src->bytes_, src->size_);
+ dst->size_ = src->size_;
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Life of a MuxImage object.
+
+void MuxImageInit(WebPMuxImage* const wpi) {
+ assert(wpi);
+ memset(wpi, 0, sizeof(*wpi));
+}
+
+WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) {
+ WebPMuxImage* next;
+ if (wpi == NULL) return NULL;
+ ChunkDelete(wpi->header_);
+ ChunkDelete(wpi->alpha_);
+ ChunkDelete(wpi->img_);
+
+ next = wpi->next_;
+ MuxImageInit(wpi);
+ return next;
+}
+
+//------------------------------------------------------------------------------
+// MuxImage search methods.
+
+int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id) {
+ int count = 0;
+ const WebPMuxImage* current;
+ for (current = wpi_list; current != NULL; current = current->next_) {
+ const WebPChunk* const wpi_chunk = *MuxImageGetListFromId(current, id);
+ if (wpi_chunk != NULL) {
+ const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_);
+ if (wpi_chunk_id == id) ++count;
+ }
+ }
+ return count;
+}
+
+// Outputs a pointer to 'prev_wpi->next_',
+// where 'prev_wpi' is the pointer to the image at position (nth - 1).
+// Returns 1 if nth image with given id was found, 0 otherwise.
+static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth,
+ WebPChunkId id,
+ WebPMuxImage*** const location) {
+ uint32_t count = 0;
+ assert(wpi_list);
+ *location = wpi_list;
+
+ // Search makes sense only for the following.
+ assert(id == WEBP_CHUNK_FRAME || id == WEBP_CHUNK_TILE ||
+ id == WEBP_CHUNK_IMAGE);
+ assert(id != WEBP_CHUNK_IMAGE || nth == 1);
+
+ if (nth == 0) {
+ nth = MuxImageCount(*wpi_list, id);
+ if (nth == 0) return 0; // Not found.
+ }
+
+ while (*wpi_list) {
+ WebPMuxImage* const cur_wpi = *wpi_list;
+ const WebPChunk* const wpi_chunk = *MuxImageGetListFromId(cur_wpi, id);
+ if (wpi_chunk != NULL) {
+ const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_);
+ if (wpi_chunk_id == id) {
+ ++count;
+ if (count == nth) return 1; // Found.
+ }
+ }
+ wpi_list = &cur_wpi->next_;
+ *location = wpi_list;
+ }
+ return 0; // Not found.
+}
+
+//------------------------------------------------------------------------------
+// MuxImage writer methods.
+
+WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list) {
+ WebPMuxImage* new_wpi;
+
+ while (*wpi_list != NULL) {
+ WebPMuxImage* const cur_wpi = *wpi_list;
+ if (cur_wpi->next_ == NULL) break;
+ wpi_list = &cur_wpi->next_;
+ }
+
+ new_wpi = (WebPMuxImage*)malloc(sizeof(*new_wpi));
+ if (new_wpi == NULL) return WEBP_MUX_MEMORY_ERROR;
+ *new_wpi = *wpi;
+ new_wpi->next_ = NULL;
+
+ if (*wpi_list != NULL) {
+ (*wpi_list)->next_ = new_wpi;
+ } else {
+ *wpi_list = new_wpi;
+ }
+ return WEBP_MUX_OK;
+}
+
+//------------------------------------------------------------------------------
+// MuxImage deletion methods.
+
+WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi) {
+ // Delete the components of wpi. If wpi is NULL this is a noop.
+ WebPMuxImage* const next = MuxImageRelease(wpi);
+ free(wpi);
+ return next;
+}
+
+void MuxImageDeleteAll(WebPMuxImage** const wpi_list) {
+ while (*wpi_list) {
+ *wpi_list = MuxImageDelete(*wpi_list);
+ }
+}
+
+WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth,
+ WebPChunkId id) {
+ assert(wpi_list);
+ if (!SearchImageToGetOrDelete(wpi_list, nth, id, &wpi_list)) {
+ return WEBP_MUX_NOT_FOUND;
+ }
+ *wpi_list = MuxImageDelete(*wpi_list);
+ return WEBP_MUX_OK;
+}
+
+//------------------------------------------------------------------------------
+// MuxImage reader methods.
+
+WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth,
+ WebPChunkId id, WebPMuxImage** wpi) {
+ assert(wpi_list);
+ assert(wpi);
+ if (!SearchImageToGetOrDelete((WebPMuxImage**)wpi_list, nth, id,
+ (WebPMuxImage***)&wpi_list)) {
+ return WEBP_MUX_NOT_FOUND;
+ }
+ *wpi = (WebPMuxImage*)*wpi_list;
+ return WEBP_MUX_OK;
+}
+
+//------------------------------------------------------------------------------
+// MuxImage serialization methods.
+
+// Size of an image.
+size_t MuxImageDiskSize(const WebPMuxImage* const wpi) {
+ size_t size = 0;
+ if (wpi->header_ != NULL) size += ChunkDiskSize(wpi->header_);
+ if (wpi->alpha_ != NULL) size += ChunkDiskSize(wpi->alpha_);
+ if (wpi->img_ != NULL) size += ChunkDiskSize(wpi->img_);
+ return size;
+}
+
+size_t MuxImageListDiskSize(const WebPMuxImage* wpi_list) {
+ size_t size = 0;
+ while (wpi_list) {
+ size += MuxImageDiskSize(wpi_list);
+ wpi_list = wpi_list->next_;
+ }
+ return size;
+}
+
+uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst) {
+ // Ordering of chunks to be emitted is strictly as follows:
+ // 1. Frame/Tile chunk (if present).
+ // 2. Alpha chunk (if present).
+ // 3. VP8/VP8L chunk.
+ assert(wpi);
+ if (wpi->header_ != NULL) dst = ChunkEmit(wpi->header_, dst);
+ if (wpi->alpha_ != NULL) dst = ChunkEmit(wpi->alpha_, dst);
+ if (wpi->img_ != NULL) dst = ChunkEmit(wpi->img_, dst);
+ return dst;
+}
+
+uint8_t* MuxImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst) {
+ while (wpi_list) {
+ dst = MuxImageEmit(wpi_list, dst);
+ wpi_list = wpi_list->next_;
+ }
+ return dst;
+}
+
+//------------------------------------------------------------------------------
+// Helper methods for mux.
+
+int MuxHasLosslessImages(const WebPMuxImage* images) {
+ while (images != NULL) {
+ assert(images->img_ != NULL);
+ if (images->img_->tag_ == kChunks[IDX_VP8L].tag) {
+ return 1;
+ }
+ images = images->next_;
+ }
+ return 0;
+}
+
+uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size) {
+ PutLE32(data + 0, MKFOURCC('R', 'I', 'F', 'F'));
+ PutLE32(data + TAG_SIZE, (uint32_t)size - CHUNK_HEADER_SIZE);
+ assert(size == (uint32_t)size);
+ PutLE32(data + TAG_SIZE + CHUNK_SIZE_BYTES, MKFOURCC('W', 'E', 'B', 'P'));
+ return data + RIFF_HEADER_SIZE;
+}
+
+WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id) {
+ assert(mux != NULL);
+ switch(id) {
+ case WEBP_CHUNK_VP8X: return (WebPChunk**)&mux->vp8x_;
+ case WEBP_CHUNK_ICCP: return (WebPChunk**)&mux->iccp_;
+ case WEBP_CHUNK_LOOP: return (WebPChunk**)&mux->loop_;
+ case WEBP_CHUNK_META: return (WebPChunk**)&mux->meta_;
+ case WEBP_CHUNK_UNKNOWN: return (WebPChunk**)&mux->unknown_;
+ default: return NULL;
+ }
+}
+
+WebPMuxError MuxValidateForImage(const WebPMux* const mux) {
+ const int num_images = MuxImageCount(mux->images_, WEBP_CHUNK_IMAGE);
+ const int num_frames = MuxImageCount(mux->images_, WEBP_CHUNK_FRAME);
+ const int num_tiles = MuxImageCount(mux->images_, WEBP_CHUNK_TILE);
+
+ if (num_images == 0) {
+ // No images in mux.
+ return WEBP_MUX_NOT_FOUND;
+ } else if (num_images == 1 && num_frames == 0 && num_tiles == 0) {
+ // Valid case (single image).
+ return WEBP_MUX_OK;
+ } else {
+ // Frame/Tile case OR an invalid mux.
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+}
+
+static int IsNotCompatible(int feature, int num_items) {
+ return (feature != 0) != (num_items > 0);
+}
+
+#define NO_FLAG 0
+
+// Test basic constraints:
+// retrieval, maximum number of chunks by index (use -1 to skip)
+// and feature incompatibility (use NO_FLAG to skip).
+// On success returns WEBP_MUX_OK and stores the chunk count in *num.
+static WebPMuxError ValidateChunk(const WebPMux* const mux, CHUNK_INDEX idx,
+ WebPFeatureFlags feature,
+ WebPFeatureFlags vp8x_flags,
+ int max, int* num) {
+ const WebPMuxError err =
+ WebPMuxNumChunks(mux, kChunks[idx].id, num);
+ if (err != WEBP_MUX_OK) return err;
+ if (max > -1 && *num > max) return WEBP_MUX_INVALID_ARGUMENT;
+ if (feature != NO_FLAG && IsNotCompatible(vp8x_flags & feature, *num)) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+ return WEBP_MUX_OK;
+}
+
+WebPMuxError MuxValidate(const WebPMux* const mux) {
+ int num_iccp;
+ int num_meta;
+ int num_loop_chunks;
+ int num_frames;
+ int num_tiles;
+ int num_vp8x;
+ int num_images;
+ int num_alpha;
+ uint32_t flags;
+ WebPMuxError err;
+
+ // Verify mux is not NULL.
+ if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+
+ // Verify mux has at least one image.
+ if (mux->images_ == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+
+ err = WebPMuxGetFeatures(mux, &flags);
+ if (err != WEBP_MUX_OK) return err;
+
+ // At most one color profile chunk.
+ err = ValidateChunk(mux, IDX_ICCP, ICCP_FLAG, flags, 1, &num_iccp);
+ if (err != WEBP_MUX_OK) return err;
+
+ // At most one XMP metadata.
+ err = ValidateChunk(mux, IDX_META, META_FLAG, flags, 1, &num_meta);
+ if (err != WEBP_MUX_OK) return err;
+
+ // Animation: ANIMATION_FLAG, loop chunk and frame chunk(s) are consistent.
+ // At most one loop chunk.
+ err = ValidateChunk(mux, IDX_LOOP, NO_FLAG, flags, 1, &num_loop_chunks);
+ if (err != WEBP_MUX_OK) return err;
+ err = ValidateChunk(mux, IDX_FRAME, NO_FLAG, flags, -1, &num_frames);
+ if (err != WEBP_MUX_OK) return err;
+
+ {
+ const int has_animation = !!(flags & ANIMATION_FLAG);
+ if (has_animation && (num_loop_chunks == 0 || num_frames == 0)) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+ if (!has_animation && (num_loop_chunks == 1 || num_frames > 0)) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+ }
+
+ // Tiling: TILE_FLAG and tile chunk(s) are consistent.
+ err = ValidateChunk(mux, IDX_TILE, TILE_FLAG, flags, -1, &num_tiles);
+ if (err != WEBP_MUX_OK) return err;
+
+ // Verify either VP8X chunk is present OR there is only one elem in
+ // mux->images_.
+ err = ValidateChunk(mux, IDX_VP8X, NO_FLAG, flags, 1, &num_vp8x);
+ if (err != WEBP_MUX_OK) return err;
+ err = ValidateChunk(mux, IDX_VP8, NO_FLAG, flags, -1, &num_images);
+ if (err != WEBP_MUX_OK) return err;
+ if (num_vp8x == 0 && num_images != 1) return WEBP_MUX_INVALID_ARGUMENT;
+
+ // ALPHA_FLAG & alpha chunk(s) are consistent.
+ if (num_vp8x > 0 && MuxHasLosslessImages(mux->images_)) {
+ // Special case: we have a VP8X chunk as well as some lossless images.
+ if (!(flags & ALPHA_FLAG)) return WEBP_MUX_INVALID_ARGUMENT;
+ } else {
+ err = ValidateChunk(mux, IDX_ALPHA, ALPHA_FLAG, flags, -1, &num_alpha);
+ if (err != WEBP_MUX_OK) return err;
+ }
+
+ // num_tiles & num_images are consistent.
+ if (num_tiles > 0 && num_images != num_tiles) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+
+ return WEBP_MUX_OK;
+}
+
+#undef NO_FLAG
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/mux/muxread.c b/drivers/webpold/mux/muxread.c
new file mode 100644
index 0000000000..21c3cfbaeb
--- /dev/null
+++ b/drivers/webpold/mux/muxread.c
@@ -0,0 +1,411 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Read APIs for mux.
+//
+// Authors: Urvang (urvang@google.com)
+// Vikas (vikasa@google.com)
+
+#include <assert.h>
+#include "./muxi.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Helper method(s).
+
+// Handy MACRO.
+#define SWITCH_ID_LIST(INDEX, LIST) \
+ if (idx == (INDEX)) { \
+ const WebPChunk* const chunk = ChunkSearchList((LIST), nth, \
+ kChunks[(INDEX)].tag); \
+ if (chunk) { \
+ *data = chunk->data_; \
+ return WEBP_MUX_OK; \
+ } else { \
+ return WEBP_MUX_NOT_FOUND; \
+ } \
+ }
+
+static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx,
+ uint32_t nth, WebPData* const data) {
+ assert(mux != NULL);
+ assert(!IsWPI(kChunks[idx].id));
+ WebPDataInit(data);
+
+ SWITCH_ID_LIST(IDX_VP8X, mux->vp8x_);
+ SWITCH_ID_LIST(IDX_ICCP, mux->iccp_);
+ SWITCH_ID_LIST(IDX_LOOP, mux->loop_);
+ SWITCH_ID_LIST(IDX_META, mux->meta_);
+ SWITCH_ID_LIST(IDX_UNKNOWN, mux->unknown_);
+ return WEBP_MUX_NOT_FOUND;
+}
+#undef SWITCH_ID_LIST
+
+// Fill the chunk with the given data (includes chunk header bytes), after some
+// verifications.
+static WebPMuxError ChunkVerifyAndAssignData(WebPChunk* chunk,
+ const uint8_t* data,
+ size_t data_size, size_t riff_size,
+ int copy_data) {
+ uint32_t chunk_size;
+ WebPData chunk_data;
+
+ // Sanity checks.
+ if (data_size < TAG_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA;
+ chunk_size = GetLE32(data + TAG_SIZE);
+
+ {
+ const size_t chunk_disk_size = SizeWithPadding(chunk_size);
+ if (chunk_disk_size > riff_size) return WEBP_MUX_BAD_DATA;
+ if (chunk_disk_size > data_size) return WEBP_MUX_NOT_ENOUGH_DATA;
+ }
+
+ // Data assignment.
+ chunk_data.bytes_ = data + CHUNK_HEADER_SIZE;
+ chunk_data.size_ = chunk_size;
+ return ChunkAssignData(chunk, &chunk_data, copy_data, GetLE32(data + 0));
+}
+
+//------------------------------------------------------------------------------
+// Create a mux object from WebP-RIFF data.
+
+WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
+ int version) {
+ size_t riff_size;
+ uint32_t tag;
+ const uint8_t* end;
+ WebPMux* mux = NULL;
+ WebPMuxImage* wpi = NULL;
+ const uint8_t* data;
+ size_t size;
+ WebPChunk chunk;
+ ChunkInit(&chunk);
+
+ // Sanity checks.
+ if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_MUX_ABI_VERSION)) {
+ return NULL; // version mismatch
+ }
+ if (bitstream == NULL) return NULL;
+
+ data = bitstream->bytes_;
+ size = bitstream->size_;
+
+ if (data == NULL) return NULL;
+ if (size < RIFF_HEADER_SIZE) return NULL;
+ if (GetLE32(data + 0) != MKFOURCC('R', 'I', 'F', 'F') ||
+ GetLE32(data + CHUNK_HEADER_SIZE) != MKFOURCC('W', 'E', 'B', 'P')) {
+ return NULL;
+ }
+
+ mux = WebPMuxNew();
+ if (mux == NULL) return NULL;
+
+ if (size < RIFF_HEADER_SIZE + TAG_SIZE) goto Err;
+
+ tag = GetLE32(data + RIFF_HEADER_SIZE);
+ if (tag != kChunks[IDX_VP8].tag &&
+ tag != kChunks[IDX_VP8L].tag &&
+ tag != kChunks[IDX_VP8X].tag) {
+ goto Err; // First chunk should be VP8, VP8L or VP8X.
+ }
+
+ riff_size = SizeWithPadding(GetLE32(data + TAG_SIZE));
+ if (riff_size > MAX_CHUNK_PAYLOAD || riff_size > size) {
+ goto Err;
+ } else {
+ if (riff_size < size) { // Redundant data after last chunk.
+ size = riff_size; // To make sure we don't read any data beyond mux_size.
+ }
+ }
+
+ end = data + size;
+ data += RIFF_HEADER_SIZE;
+ size -= RIFF_HEADER_SIZE;
+
+ wpi = (WebPMuxImage*)malloc(sizeof(*wpi));
+ if (wpi == NULL) goto Err;
+ MuxImageInit(wpi);
+
+ // Loop over chunks.
+ while (data != end) {
+ WebPChunkId id;
+ WebPMuxError err;
+
+ err = ChunkVerifyAndAssignData(&chunk, data, size, riff_size, copy_data);
+ if (err != WEBP_MUX_OK) goto Err;
+
+ id = ChunkGetIdFromTag(chunk.tag_);
+
+ if (IsWPI(id)) { // An image chunk (frame/tile/alpha/vp8).
+ WebPChunk** wpi_chunk_ptr =
+ MuxImageGetListFromId(wpi, id); // Image chunk to set.
+ assert(wpi_chunk_ptr != NULL);
+ if (*wpi_chunk_ptr != NULL) goto Err; // Consecutive alpha chunks or
+ // consecutive frame/tile chunks.
+ if (ChunkSetNth(&chunk, wpi_chunk_ptr, 1) != WEBP_MUX_OK) goto Err;
+ if (id == WEBP_CHUNK_IMAGE) {
+ wpi->is_partial_ = 0; // wpi is completely filled.
+ // Add this to mux->images_ list.
+ if (MuxImagePush(wpi, &mux->images_) != WEBP_MUX_OK) goto Err;
+ MuxImageInit(wpi); // Reset for reading next image.
+ } else {
+ wpi->is_partial_ = 1; // wpi is only partially filled.
+ }
+ } else { // A non-image chunk.
+ WebPChunk** chunk_list;
+ if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before
+ // getting all chunks of an image.
+ chunk_list = MuxGetChunkListFromId(mux, id); // List to add this chunk.
+ if (chunk_list == NULL) chunk_list = &mux->unknown_;
+ if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err;
+ }
+ {
+ const size_t data_size = ChunkDiskSize(&chunk);
+ data += data_size;
+ size -= data_size;
+ }
+ ChunkInit(&chunk);
+ }
+
+ // Validate mux if complete.
+ if (MuxValidate(mux) != WEBP_MUX_OK) goto Err;
+
+ MuxImageDelete(wpi);
+ return mux; // All OK;
+
+ Err: // Something bad happened.
+ ChunkRelease(&chunk);
+ MuxImageDelete(wpi);
+ WebPMuxDelete(mux);
+ return NULL;
+}
+
+//------------------------------------------------------------------------------
+// Get API(s).
+
+WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, uint32_t* flags) {
+ WebPData data;
+ WebPMuxError err;
+
+ if (mux == NULL || flags == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ *flags = 0;
+
+ // Check if VP8X chunk is present.
+ err = MuxGet(mux, IDX_VP8X, 1, &data);
+ if (err == WEBP_MUX_NOT_FOUND) {
+ // Check if VP8/VP8L chunk is present.
+ err = WebPMuxGetImage(mux, &data);
+ WebPDataClear(&data);
+ return err;
+ } else if (err != WEBP_MUX_OK) {
+ return err;
+ }
+
+ if (data.size_ < CHUNK_SIZE_BYTES) return WEBP_MUX_BAD_DATA;
+
+ // All OK. Fill up flags.
+ *flags = GetLE32(data.bytes_);
+ return WEBP_MUX_OK;
+}
+
+static uint8_t* EmitVP8XChunk(uint8_t* const dst, int width,
+ int height, uint32_t flags) {
+ const size_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE;
+ assert(width >= 1 && height >= 1);
+ assert(width <= MAX_CANVAS_SIZE && height <= MAX_CANVAS_SIZE);
+ assert(width * (uint64_t)height < MAX_IMAGE_AREA);
+ PutLE32(dst, MKFOURCC('V', 'P', '8', 'X'));
+ PutLE32(dst + TAG_SIZE, VP8X_CHUNK_SIZE);
+ PutLE32(dst + CHUNK_HEADER_SIZE, flags);
+ PutLE24(dst + CHUNK_HEADER_SIZE + 4, width - 1);
+ PutLE24(dst + CHUNK_HEADER_SIZE + 7, height - 1);
+ return dst + vp8x_size;
+}
+
+// Assemble a single image WebP bitstream from 'wpi'.
+static WebPMuxError SynthesizeBitstream(WebPMuxImage* const wpi,
+ WebPData* const bitstream) {
+ uint8_t* dst;
+
+ // Allocate data.
+ const int need_vp8x = (wpi->alpha_ != NULL);
+ const size_t vp8x_size = need_vp8x ? CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE : 0;
+ const size_t alpha_size = need_vp8x ? ChunkDiskSize(wpi->alpha_) : 0;
+ // Note: No need to output FRM/TILE chunk for a single image.
+ const size_t size = RIFF_HEADER_SIZE + vp8x_size + alpha_size +
+ ChunkDiskSize(wpi->img_);
+ uint8_t* const data = (uint8_t*)malloc(size);
+ if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
+
+ // Main RIFF header.
+ dst = MuxEmitRiffHeader(data, size);
+
+ if (need_vp8x) {
+ int w, h;
+ WebPMuxError err;
+ assert(wpi->img_ != NULL);
+ err = MuxGetImageWidthHeight(wpi->img_, &w, &h);
+ if (err != WEBP_MUX_OK) {
+ free(data);
+ return err;
+ }
+ dst = EmitVP8XChunk(dst, w, h, ALPHA_FLAG); // VP8X.
+ dst = ChunkListEmit(wpi->alpha_, dst); // ALPH.
+ }
+
+ // Bitstream.
+ dst = ChunkListEmit(wpi->img_, dst);
+ assert(dst == data + size);
+
+ // Output.
+ bitstream->bytes_ = data;
+ bitstream->size_ = size;
+ return WEBP_MUX_OK;
+}
+
+WebPMuxError WebPMuxGetImage(const WebPMux* mux, WebPData* bitstream) {
+ WebPMuxError err;
+ WebPMuxImage* wpi = NULL;
+
+ if (mux == NULL || bitstream == NULL) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+
+ err = MuxValidateForImage(mux);
+ if (err != WEBP_MUX_OK) return err;
+
+ // All well. Get the image.
+ err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, WEBP_CHUNK_IMAGE,
+ &wpi);
+ assert(err == WEBP_MUX_OK); // Already tested above.
+
+ return SynthesizeBitstream(wpi, bitstream);
+}
+
+WebPMuxError WebPMuxGetMetadata(const WebPMux* mux, WebPData* metadata) {
+ if (mux == NULL || metadata == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ return MuxGet(mux, IDX_META, 1, metadata);
+}
+
+WebPMuxError WebPMuxGetColorProfile(const WebPMux* mux,
+ WebPData* color_profile) {
+ if (mux == NULL || color_profile == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ return MuxGet(mux, IDX_ICCP, 1, color_profile);
+}
+
+WebPMuxError WebPMuxGetLoopCount(const WebPMux* mux, int* loop_count) {
+ WebPData image;
+ WebPMuxError err;
+
+ if (mux == NULL || loop_count == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+
+ err = MuxGet(mux, IDX_LOOP, 1, &image);
+ if (err != WEBP_MUX_OK) return err;
+ if (image.size_ < kChunks[WEBP_CHUNK_LOOP].size) return WEBP_MUX_BAD_DATA;
+ *loop_count = GetLE16(image.bytes_);
+
+ return WEBP_MUX_OK;
+}
+
+static WebPMuxError MuxGetFrameTileInternal(
+ const WebPMux* const mux, uint32_t nth, WebPData* const bitstream,
+ int* const x_offset, int* const y_offset, int* const duration,
+ uint32_t tag) {
+ const WebPData* frame_tile_data;
+ WebPMuxError err;
+ WebPMuxImage* wpi;
+
+ const int is_frame = (tag == kChunks[WEBP_CHUNK_FRAME].tag) ? 1 : 0;
+ const CHUNK_INDEX idx = is_frame ? IDX_FRAME : IDX_TILE;
+ const WebPChunkId id = kChunks[idx].id;
+
+ if (mux == NULL || bitstream == NULL ||
+ x_offset == NULL || y_offset == NULL || (is_frame && duration == NULL)) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+
+ // Get the nth WebPMuxImage.
+ err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, id, &wpi);
+ if (err != WEBP_MUX_OK) return err;
+
+ // Get frame chunk.
+ assert(wpi->header_ != NULL); // As MuxImageGetNth() already checked header_.
+ frame_tile_data = &wpi->header_->data_;
+
+ if (frame_tile_data->size_ < kChunks[idx].size) return WEBP_MUX_BAD_DATA;
+ *x_offset = 2 * GetLE24(frame_tile_data->bytes_ + 0);
+ *y_offset = 2 * GetLE24(frame_tile_data->bytes_ + 3);
+ if (is_frame) *duration = 1 + GetLE24(frame_tile_data->bytes_ + 12);
+
+ return SynthesizeBitstream(wpi, bitstream);
+}
+
+WebPMuxError WebPMuxGetFrame(const WebPMux* mux, uint32_t nth,
+ WebPData* bitstream,
+ int* x_offset, int* y_offset, int* duration) {
+ return MuxGetFrameTileInternal(mux, nth, bitstream, x_offset, y_offset,
+ duration, kChunks[IDX_FRAME].tag);
+}
+
+WebPMuxError WebPMuxGetTile(const WebPMux* mux, uint32_t nth,
+ WebPData* bitstream,
+ int* x_offset, int* y_offset) {
+ return MuxGetFrameTileInternal(mux, nth, bitstream, x_offset, y_offset, NULL,
+ kChunks[IDX_TILE].tag);
+}
+
+// Get chunk index from chunk id. Returns IDX_NIL if not found.
+static CHUNK_INDEX ChunkGetIndexFromId(WebPChunkId id) {
+ int i;
+ for (i = 0; kChunks[i].id != WEBP_CHUNK_NIL; ++i) {
+ if (id == kChunks[i].id) return i;
+ }
+ return IDX_NIL;
+}
+
+// Count number of chunks matching 'tag' in the 'chunk_list'.
+// If tag == NIL_TAG, any tag will be matched.
+static int CountChunks(const WebPChunk* const chunk_list, uint32_t tag) {
+ int count = 0;
+ const WebPChunk* current;
+ for (current = chunk_list; current != NULL; current = current->next_) {
+ if (tag == NIL_TAG || current->tag_ == tag) {
+ count++; // Count chunks whose tags match.
+ }
+ }
+ return count;
+}
+
+WebPMuxError WebPMuxNumChunks(const WebPMux* mux,
+ WebPChunkId id, int* num_elements) {
+ if (mux == NULL || num_elements == NULL) {
+ return WEBP_MUX_INVALID_ARGUMENT;
+ }
+
+ if (IsWPI(id)) {
+ *num_elements = MuxImageCount(mux->images_, id);
+ } else {
+ WebPChunk* const* chunk_list = MuxGetChunkListFromId(mux, id);
+ if (chunk_list == NULL) {
+ *num_elements = 0;
+ } else {
+ const CHUNK_INDEX idx = ChunkGetIndexFromId(id);
+ *num_elements = CountChunks(*chunk_list, kChunks[idx].tag);
+ }
+ }
+
+ return WEBP_MUX_OK;
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/types.h b/drivers/webpold/types.h
new file mode 100644
index 0000000000..3e27190bef
--- /dev/null
+++ b/drivers/webpold/types.h
@@ -0,0 +1,45 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Common types
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_WEBP_TYPES_H_
+#define WEBP_WEBP_TYPES_H_
+
+#include <stddef.h> // for size_t
+
+#ifndef _MSC_VER
+#include <inttypes.h>
+#ifdef __STRICT_ANSI__
+#define WEBP_INLINE
+#else /* __STRICT_ANSI__ */
+#define WEBP_INLINE inline
+#endif
+#else
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long int uint64_t;
+typedef long long int int64_t;
+#define WEBP_INLINE __forceinline
+#endif /* _MSC_VER */
+
+#ifndef WEBP_EXTERN
+// This explicitly marks library functions and allows for changing the
+// signature for e.g., Windows DLL builds.
+#define WEBP_EXTERN(type) extern type
+#endif /* WEBP_EXTERN */
+
+// Macro to check ABI compatibility (same major revision number)
+#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8))
+
+#endif /* WEBP_WEBP_TYPES_H_ */
diff --git a/drivers/webpold/utils/bit_reader.c b/drivers/webpold/utils/bit_reader.c
new file mode 100644
index 0000000000..1afb1db890
--- /dev/null
+++ b/drivers/webpold/utils/bit_reader.c
@@ -0,0 +1,229 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Boolean decoder
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./bit_reader.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define MK(X) (((bit_t)(X) << (BITS)) | (MASK))
+
+//------------------------------------------------------------------------------
+// VP8BitReader
+
+void VP8InitBitReader(VP8BitReader* const br,
+ const uint8_t* const start, const uint8_t* const end) {
+ assert(br != NULL);
+ assert(start != NULL);
+ assert(start <= end);
+ br->range_ = MK(255 - 1);
+ br->buf_ = start;
+ br->buf_end_ = end;
+ br->value_ = 0;
+ br->missing_ = 8; // to load the very first 8bits
+ br->eof_ = 0;
+}
+
+const uint8_t kVP8Log2Range[128] = {
+ 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0
+};
+
+// range = (range << kVP8Log2Range[range]) + trailing 1's
+const bit_t kVP8NewRange[128] = {
+ MK(127), MK(127), MK(191), MK(127), MK(159), MK(191), MK(223), MK(127),
+ MK(143), MK(159), MK(175), MK(191), MK(207), MK(223), MK(239), MK(127),
+ MK(135), MK(143), MK(151), MK(159), MK(167), MK(175), MK(183), MK(191),
+ MK(199), MK(207), MK(215), MK(223), MK(231), MK(239), MK(247), MK(127),
+ MK(131), MK(135), MK(139), MK(143), MK(147), MK(151), MK(155), MK(159),
+ MK(163), MK(167), MK(171), MK(175), MK(179), MK(183), MK(187), MK(191),
+ MK(195), MK(199), MK(203), MK(207), MK(211), MK(215), MK(219), MK(223),
+ MK(227), MK(231), MK(235), MK(239), MK(243), MK(247), MK(251), MK(127),
+ MK(129), MK(131), MK(133), MK(135), MK(137), MK(139), MK(141), MK(143),
+ MK(145), MK(147), MK(149), MK(151), MK(153), MK(155), MK(157), MK(159),
+ MK(161), MK(163), MK(165), MK(167), MK(169), MK(171), MK(173), MK(175),
+ MK(177), MK(179), MK(181), MK(183), MK(185), MK(187), MK(189), MK(191),
+ MK(193), MK(195), MK(197), MK(199), MK(201), MK(203), MK(205), MK(207),
+ MK(209), MK(211), MK(213), MK(215), MK(217), MK(219), MK(221), MK(223),
+ MK(225), MK(227), MK(229), MK(231), MK(233), MK(235), MK(237), MK(239),
+ MK(241), MK(243), MK(245), MK(247), MK(249), MK(251), MK(253), MK(127)
+};
+
+#undef MK
+
+void VP8LoadFinalBytes(VP8BitReader* const br) {
+ assert(br != NULL && br->buf_ != NULL);
+ // Only read 8bits at a time
+ if (br->buf_ < br->buf_end_) {
+ br->value_ |= (bit_t)(*br->buf_++) << ((BITS) - 8 + br->missing_);
+ br->missing_ -= 8;
+ } else {
+ br->eof_ = 1;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Higher-level calls
+
+uint32_t VP8GetValue(VP8BitReader* const br, int bits) {
+ uint32_t v = 0;
+ while (bits-- > 0) {
+ v |= VP8GetBit(br, 0x80) << bits;
+ }
+ return v;
+}
+
+int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) {
+ const int value = VP8GetValue(br, bits);
+ return VP8Get(br) ? -value : value;
+}
+
+//------------------------------------------------------------------------------
+// VP8LBitReader
+
+#define MAX_NUM_BIT_READ 25
+
+static const uint32_t kBitMask[MAX_NUM_BIT_READ] = {
+ 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767,
+ 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215
+};
+
+void VP8LInitBitReader(VP8LBitReader* const br,
+ const uint8_t* const start,
+ size_t length) {
+ size_t i;
+ assert(br != NULL);
+ assert(start != NULL);
+ assert(length < 0xfffffff8u); // can't happen with a RIFF chunk.
+
+ br->buf_ = start;
+ br->len_ = length;
+ br->val_ = 0;
+ br->pos_ = 0;
+ br->bit_pos_ = 0;
+ br->eos_ = 0;
+ br->error_ = 0;
+ for (i = 0; i < sizeof(br->val_) && i < br->len_; ++i) {
+ br->val_ |= ((uint64_t)br->buf_[br->pos_]) << (8 * i);
+ ++br->pos_;
+ }
+}
+
+void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
+ const uint8_t* const buf, size_t len) {
+ assert(br != NULL);
+ assert(buf != NULL);
+ assert(len < 0xfffffff8u); // can't happen with a RIFF chunk.
+ br->eos_ = (br->pos_ >= len);
+ br->buf_ = buf;
+ br->len_ = len;
+}
+
+static void ShiftBytes(VP8LBitReader* const br) {
+ while (br->bit_pos_ >= 8 && br->pos_ < br->len_) {
+ br->val_ >>= 8;
+ br->val_ |= ((uint64_t)br->buf_[br->pos_]) << 56;
+ ++br->pos_;
+ br->bit_pos_ -= 8;
+ }
+}
+
+void VP8LFillBitWindow(VP8LBitReader* const br) {
+ if (br->bit_pos_ >= 32) {
+#if defined(__x86_64__) || defined(_M_X64)
+ if (br->pos_ + 8 < br->len_) {
+ br->val_ >>= 32;
+ // The expression below needs a little-endian arch to work correctly.
+ // This gives a large speedup for decoding speed.
+ br->val_ |= *(const uint64_t *)(br->buf_ + br->pos_) << 32;
+ br->pos_ += 4;
+ br->bit_pos_ -= 32;
+ } else {
+ // Slow path.
+ ShiftBytes(br);
+ }
+#else
+ // Always the slow path.
+ ShiftBytes(br);
+#endif
+ }
+ if (br->pos_ == br->len_ && br->bit_pos_ == 64) {
+ br->eos_ = 1;
+ }
+}
+
+uint32_t VP8LReadOneBit(VP8LBitReader* const br) {
+ const uint32_t val = (br->val_ >> br->bit_pos_) & 1;
+ // Flag an error at end_of_stream.
+ if (!br->eos_) {
+ ++br->bit_pos_;
+ if (br->bit_pos_ >= 32) {
+ ShiftBytes(br);
+ }
+ // After this last bit is read, check if eos needs to be flagged.
+ if (br->pos_ == br->len_ && br->bit_pos_ == 64) {
+ br->eos_ = 1;
+ }
+ } else {
+ br->error_ = 1;
+ }
+ return val;
+}
+
+uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) {
+ uint32_t val = 0;
+ assert(n_bits >= 0);
+ // Flag an error if end_of_stream or n_bits is more than allowed limit.
+ if (!br->eos_ && n_bits < MAX_NUM_BIT_READ) {
+ // If this read is going to cross the read buffer, set the eos flag.
+ if (br->pos_ == br->len_) {
+ if ((br->bit_pos_ + n_bits) >= 64) {
+ br->eos_ = 1;
+ if ((br->bit_pos_ + n_bits) > 64) return val;
+ }
+ }
+ val = (br->val_ >> br->bit_pos_) & kBitMask[n_bits];
+ br->bit_pos_ += n_bits;
+ if (br->bit_pos_ >= 40) {
+ if (br->pos_ + 5 < br->len_) {
+ br->val_ >>= 40;
+ br->val_ |=
+ (((uint64_t)br->buf_[br->pos_ + 0]) << 24) |
+ (((uint64_t)br->buf_[br->pos_ + 1]) << 32) |
+ (((uint64_t)br->buf_[br->pos_ + 2]) << 40) |
+ (((uint64_t)br->buf_[br->pos_ + 3]) << 48) |
+ (((uint64_t)br->buf_[br->pos_ + 4]) << 56);
+ br->pos_ += 5;
+ br->bit_pos_ -= 40;
+ }
+ if (br->bit_pos_ >= 8) {
+ ShiftBytes(br);
+ }
+ }
+ } else {
+ br->error_ = 1;
+ }
+ return val;
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/utils/bit_reader.h b/drivers/webpold/utils/bit_reader.h
new file mode 100644
index 0000000000..43cd948fd4
--- /dev/null
+++ b/drivers/webpold/utils/bit_reader.h
@@ -0,0 +1,198 @@
+//
+// Copyright 2010 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Boolean decoder
+//
+// Author: Skal (pascal.massimino@gmail.com)
+// Vikas Arora (vikaas.arora@gmail.com)
+
+#ifndef WEBP_UTILS_BIT_READER_H_
+#define WEBP_UTILS_BIT_READER_H_
+
+#include <assert.h>
+#ifdef _MSC_VER
+#include <stdlib.h> // _byteswap_ulong
+#endif
+#include <string.h> // For memcpy
+#include "../types.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define BITS 32 // can be 32, 16 or 8
+#define MASK ((((bit_t)1) << (BITS)) - 1)
+#if (BITS == 32)
+typedef uint64_t bit_t; // natural register type
+typedef uint32_t lbit_t; // natural type for memory I/O
+#elif (BITS == 16)
+typedef uint32_t bit_t;
+typedef uint16_t lbit_t;
+#else
+typedef uint32_t bit_t;
+typedef uint8_t lbit_t;
+#endif
+
+//------------------------------------------------------------------------------
+// Bitreader and code-tree reader
+
+typedef struct VP8BitReader VP8BitReader;
+struct VP8BitReader {
+ const uint8_t* buf_; // next byte to be read
+ const uint8_t* buf_end_; // end of read buffer
+ int eof_; // true if input is exhausted
+
+ // boolean decoder
+ bit_t range_; // current range minus 1. In [127, 254] interval.
+ bit_t value_; // current value
+ int missing_; // number of missing bits in value_ (8bit)
+};
+
+// Initialize the bit reader and the boolean decoder.
+void VP8InitBitReader(VP8BitReader* const br,
+ const uint8_t* const start, const uint8_t* const end);
+
+// return the next value made of 'num_bits' bits
+uint32_t VP8GetValue(VP8BitReader* const br, int num_bits);
+static WEBP_INLINE uint32_t VP8Get(VP8BitReader* const br) {
+ return VP8GetValue(br, 1);
+}
+
+// return the next value with sign-extension.
+int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits);
+
+// Read a bit with proba 'prob'. Speed-critical function!
+extern const uint8_t kVP8Log2Range[128];
+extern const bit_t kVP8NewRange[128];
+
+void VP8LoadFinalBytes(VP8BitReader* const br); // special case for the tail
+
+static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) {
+ assert(br && br->buf_);
+ // Read 'BITS' bits at a time if possible.
+ if (br->buf_ + sizeof(lbit_t) <= br->buf_end_) {
+ // convert memory type to register type (with some zero'ing!)
+ bit_t bits;
+ lbit_t in_bits = *(lbit_t*)br->buf_;
+ br->buf_ += (BITS) >> 3;
+#if !defined(__BIG_ENDIAN__)
+#if (BITS == 32)
+#if defined(__i386__) || defined(__x86_64__)
+ __asm__ volatile("bswap %k0" : "=r"(in_bits) : "0"(in_bits));
+ bits = (bit_t)in_bits; // 32b -> 64b zero-extension
+#elif defined(_MSC_VER)
+ bits = _byteswap_ulong(in_bits);
+#else
+ bits = (bit_t)(in_bits >> 24) | ((in_bits >> 8) & 0xff00)
+ | ((in_bits << 8) & 0xff0000) | (in_bits << 24);
+#endif // x86
+#elif (BITS == 16)
+ // gcc will recognize a 'rorw $8, ...' here:
+ bits = (bit_t)(in_bits >> 8) | ((in_bits & 0xff) << 8);
+#endif
+#else // LITTLE_ENDIAN
+ bits = (bit_t)in_bits;
+#endif
+ br->value_ |= bits << br->missing_;
+ br->missing_ -= (BITS);
+ } else {
+ VP8LoadFinalBytes(br); // no need to be inlined
+ }
+}
+
+static WEBP_INLINE int VP8BitUpdate(VP8BitReader* const br, bit_t split) {
+ const bit_t value_split = split | (MASK);
+ if (br->missing_ > 0) { // Make sure we have a least BITS bits in 'value_'
+ VP8LoadNewBytes(br);
+ }
+ if (br->value_ > value_split) {
+ br->range_ -= value_split + 1;
+ br->value_ -= value_split + 1;
+ return 1;
+ } else {
+ br->range_ = value_split;
+ return 0;
+ }
+}
+
+static WEBP_INLINE void VP8Shift(VP8BitReader* const br) {
+ // range_ is in [0..127] interval here.
+ const int idx = br->range_ >> (BITS);
+ const int shift = kVP8Log2Range[idx];
+ br->range_ = kVP8NewRange[idx];
+ br->value_ <<= shift;
+ br->missing_ += shift;
+}
+
+static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) {
+ // It's important to avoid generating a 64bit x 64bit multiply here.
+ // We just need an 8b x 8b after all.
+ const bit_t split =
+ (bit_t)((uint32_t)(br->range_ >> (BITS)) * prob) << ((BITS) - 8);
+ const int bit = VP8BitUpdate(br, split);
+ if (br->range_ <= (((bit_t)0x7e << (BITS)) | (MASK))) {
+ VP8Shift(br);
+ }
+ return bit;
+}
+
+static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) {
+ const bit_t split = (br->range_ >> 1);
+ const int bit = VP8BitUpdate(br, split);
+ VP8Shift(br);
+ return bit ? -v : v;
+}
+
+
+// -----------------------------------------------------------------------------
+// Bitreader
+
+typedef struct {
+ uint64_t val_;
+ const uint8_t* buf_;
+ size_t len_;
+ size_t pos_;
+ int bit_pos_;
+ int eos_;
+ int error_;
+} VP8LBitReader;
+
+void VP8LInitBitReader(VP8LBitReader* const br,
+ const uint8_t* const start,
+ size_t length);
+
+// Sets a new data buffer.
+void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
+ const uint8_t* const buffer, size_t length);
+
+// Reads the specified number of bits from Read Buffer.
+// Flags an error in case end_of_stream or n_bits is more than allowed limit.
+// Flags eos if this read attempt is going to cross the read buffer.
+uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits);
+
+// Reads one bit from Read Buffer. Flags an error in case end_of_stream.
+// Flags eos after reading last bit from the buffer.
+uint32_t VP8LReadOneBit(VP8LBitReader* const br);
+
+// VP8LReadOneBitUnsafe is faster than VP8LReadOneBit, but it can be called only
+// 32 times after the last VP8LFillBitWindow. Any subsequent calls
+// (without VP8LFillBitWindow) will return invalid data.
+static WEBP_INLINE uint32_t VP8LReadOneBitUnsafe(VP8LBitReader* const br) {
+ const uint32_t val = (br->val_ >> br->bit_pos_) & 1;
+ ++br->bit_pos_;
+ return val;
+}
+
+// Advances the Read buffer by 4 bytes to make room for reading next 32 bits.
+void VP8LFillBitWindow(VP8LBitReader* const br);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_UTILS_BIT_READER_H_ */
diff --git a/drivers/webpold/utils/bit_writer.c b/drivers/webpold/utils/bit_writer.c
new file mode 100644
index 0000000000..671159cacd
--- /dev/null
+++ b/drivers/webpold/utils/bit_writer.c
@@ -0,0 +1,284 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Bit writing and boolean coder
+//
+// Author: Skal (pascal.massimino@gmail.com)
+// Vikas Arora (vikaas.arora@gmail.com)
+
+#include <assert.h>
+#include <string.h> // for memcpy()
+#include <stdlib.h>
+#include "./bit_writer.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// VP8BitWriter
+
+static int BitWriterResize(VP8BitWriter* const bw, size_t extra_size) {
+ uint8_t* new_buf;
+ size_t new_size;
+ const uint64_t needed_size_64b = (uint64_t)bw->pos_ + extra_size;
+ const size_t needed_size = (size_t)needed_size_64b;
+ if (needed_size_64b != needed_size) {
+ bw->error_ = 1;
+ return 0;
+ }
+ if (needed_size <= bw->max_pos_) return 1;
+ // If the following line wraps over 32bit, the test just after will catch it.
+ new_size = 2 * bw->max_pos_;
+ if (new_size < needed_size) new_size = needed_size;
+ if (new_size < 1024) new_size = 1024;
+ new_buf = (uint8_t*)malloc(new_size);
+ if (new_buf == NULL) {
+ bw->error_ = 1;
+ return 0;
+ }
+ memcpy(new_buf, bw->buf_, bw->pos_);
+ free(bw->buf_);
+ bw->buf_ = new_buf;
+ bw->max_pos_ = new_size;
+ return 1;
+}
+
+static void kFlush(VP8BitWriter* const bw) {
+ const int s = 8 + bw->nb_bits_;
+ const int32_t bits = bw->value_ >> s;
+ assert(bw->nb_bits_ >= 0);
+ bw->value_ -= bits << s;
+ bw->nb_bits_ -= 8;
+ if ((bits & 0xff) != 0xff) {
+ size_t pos = bw->pos_;
+ if (!BitWriterResize(bw, bw->run_ + 1)) {
+ return;
+ }
+ if (bits & 0x100) { // overflow -> propagate carry over pending 0xff's
+ if (pos > 0) bw->buf_[pos - 1]++;
+ }
+ if (bw->run_ > 0) {
+ const int value = (bits & 0x100) ? 0x00 : 0xff;
+ for (; bw->run_ > 0; --bw->run_) bw->buf_[pos++] = value;
+ }
+ bw->buf_[pos++] = bits;
+ bw->pos_ = pos;
+ } else {
+ bw->run_++; // delay writing of bytes 0xff, pending eventual carry.
+ }
+}
+
+//------------------------------------------------------------------------------
+// renormalization
+
+static const uint8_t kNorm[128] = { // renorm_sizes[i] = 8 - log2(i)
+ 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0
+};
+
+// range = ((range + 1) << kVP8Log2Range[range]) - 1
+static const uint8_t kNewRange[128] = {
+ 127, 127, 191, 127, 159, 191, 223, 127, 143, 159, 175, 191, 207, 223, 239,
+ 127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239,
+ 247, 127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179,
+ 183, 187, 191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239,
+ 243, 247, 251, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149,
+ 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179,
+ 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209,
+ 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239,
+ 241, 243, 245, 247, 249, 251, 253, 127
+};
+
+int VP8PutBit(VP8BitWriter* const bw, int bit, int prob) {
+ const int split = (bw->range_ * prob) >> 8;
+ if (bit) {
+ bw->value_ += split + 1;
+ bw->range_ -= split + 1;
+ } else {
+ bw->range_ = split;
+ }
+ if (bw->range_ < 127) { // emit 'shift' bits out and renormalize
+ const int shift = kNorm[bw->range_];
+ bw->range_ = kNewRange[bw->range_];
+ bw->value_ <<= shift;
+ bw->nb_bits_ += shift;
+ if (bw->nb_bits_ > 0) kFlush(bw);
+ }
+ return bit;
+}
+
+int VP8PutBitUniform(VP8BitWriter* const bw, int bit) {
+ const int split = bw->range_ >> 1;
+ if (bit) {
+ bw->value_ += split + 1;
+ bw->range_ -= split + 1;
+ } else {
+ bw->range_ = split;
+ }
+ if (bw->range_ < 127) {
+ bw->range_ = kNewRange[bw->range_];
+ bw->value_ <<= 1;
+ bw->nb_bits_ += 1;
+ if (bw->nb_bits_ > 0) kFlush(bw);
+ }
+ return bit;
+}
+
+void VP8PutValue(VP8BitWriter* const bw, int value, int nb_bits) {
+ int mask;
+ for (mask = 1 << (nb_bits - 1); mask; mask >>= 1)
+ VP8PutBitUniform(bw, value & mask);
+}
+
+void VP8PutSignedValue(VP8BitWriter* const bw, int value, int nb_bits) {
+ if (!VP8PutBitUniform(bw, value != 0))
+ return;
+ if (value < 0) {
+ VP8PutValue(bw, ((-value) << 1) | 1, nb_bits + 1);
+ } else {
+ VP8PutValue(bw, value << 1, nb_bits + 1);
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size) {
+ bw->range_ = 255 - 1;
+ bw->value_ = 0;
+ bw->run_ = 0;
+ bw->nb_bits_ = -8;
+ bw->pos_ = 0;
+ bw->max_pos_ = 0;
+ bw->error_ = 0;
+ bw->buf_ = NULL;
+ return (expected_size > 0) ? BitWriterResize(bw, expected_size) : 1;
+}
+
+uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw) {
+ VP8PutValue(bw, 0, 9 - bw->nb_bits_);
+ bw->nb_bits_ = 0; // pad with zeroes
+ kFlush(bw);
+ return bw->buf_;
+}
+
+int VP8BitWriterAppend(VP8BitWriter* const bw,
+ const uint8_t* data, size_t size) {
+ assert(data);
+ if (bw->nb_bits_ != -8) return 0; // kFlush() must have been called
+ if (!BitWriterResize(bw, size)) return 0;
+ memcpy(bw->buf_ + bw->pos_, data, size);
+ bw->pos_ += size;
+ return 1;
+}
+
+void VP8BitWriterWipeOut(VP8BitWriter* const bw) {
+ if (bw) {
+ free(bw->buf_);
+ memset(bw, 0, sizeof(*bw));
+ }
+}
+
+//------------------------------------------------------------------------------
+// VP8LBitWriter
+
+// Returns 1 on success.
+static int VP8LBitWriterResize(VP8LBitWriter* const bw, size_t extra_size) {
+ uint8_t* allocated_buf;
+ size_t allocated_size;
+ const size_t current_size = VP8LBitWriterNumBytes(bw);
+ const uint64_t size_required_64b = (uint64_t)current_size + extra_size;
+ const size_t size_required = (size_t)size_required_64b;
+ if (size_required != size_required_64b) {
+ bw->error_ = 1;
+ return 0;
+ }
+ if (bw->max_bytes_ > 0 && size_required <= bw->max_bytes_) return 1;
+ allocated_size = (3 * bw->max_bytes_) >> 1;
+ if (allocated_size < size_required) allocated_size = size_required;
+ // make allocated size multiple of 1k
+ allocated_size = (((allocated_size >> 10) + 1) << 10);
+ allocated_buf = (uint8_t*)malloc(allocated_size);
+ if (allocated_buf == NULL) {
+ bw->error_ = 1;
+ return 0;
+ }
+ memcpy(allocated_buf, bw->buf_, current_size);
+ free(bw->buf_);
+ bw->buf_ = allocated_buf;
+ bw->max_bytes_ = allocated_size;
+ memset(allocated_buf + current_size, 0, allocated_size - current_size);
+ return 1;
+}
+
+int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) {
+ memset(bw, 0, sizeof(*bw));
+ return VP8LBitWriterResize(bw, expected_size);
+}
+
+void VP8LBitWriterDestroy(VP8LBitWriter* const bw) {
+ if (bw != NULL) {
+ free(bw->buf_);
+ memset(bw, 0, sizeof(*bw));
+ }
+}
+
+void VP8LWriteBits(VP8LBitWriter* const bw, int n_bits, uint32_t bits) {
+ if (n_bits < 1) return;
+#if !defined(__BIG_ENDIAN__)
+ // Technically, this branch of the code can write up to 25 bits at a time,
+ // but in prefix encoding, the maximum number of bits written is 18 at a time.
+ {
+ uint8_t* const p = &bw->buf_[bw->bit_pos_ >> 3];
+ uint32_t v = *(const uint32_t*)p;
+ v |= bits << (bw->bit_pos_ & 7);
+ *(uint32_t*)p = v;
+ bw->bit_pos_ += n_bits;
+ }
+#else // BIG_ENDIAN
+ {
+ uint8_t* p = &bw->buf_[bw->bit_pos_ >> 3];
+ const int bits_reserved_in_first_byte = bw->bit_pos_ & 7;
+ const int bits_left_to_write = n_bits - 8 + bits_reserved_in_first_byte;
+ // implicit & 0xff is assumed for uint8_t arithmetics
+ *p++ |= bits << bits_reserved_in_first_byte;
+ bits >>= 8 - bits_reserved_in_first_byte;
+ if (bits_left_to_write >= 1) {
+ *p++ = bits;
+ bits >>= 8;
+ if (bits_left_to_write >= 9) {
+ *p++ = bits;
+ bits >>= 8;
+ }
+ }
+ assert(n_bits <= 25);
+ *p = bits;
+ bw->bit_pos_ += n_bits;
+ }
+#endif
+ if ((bw->bit_pos_ >> 3) > (bw->max_bytes_ - 8)) {
+ const uint64_t extra_size = 32768ULL + bw->max_bytes_;
+ if (extra_size != (size_t)extra_size ||
+ !VP8LBitWriterResize(bw, (size_t)extra_size)) {
+ bw->bit_pos_ = 0;
+ bw->error_ = 1;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/utils/bit_writer.h b/drivers/webpold/utils/bit_writer.h
new file mode 100644
index 0000000000..57f39b11b1
--- /dev/null
+++ b/drivers/webpold/utils/bit_writer.h
@@ -0,0 +1,123 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Bit writing and boolean coder
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_UTILS_BIT_WRITER_H_
+#define WEBP_UTILS_BIT_WRITER_H_
+
+#include "../types.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Bit-writing
+
+typedef struct VP8BitWriter VP8BitWriter;
+struct VP8BitWriter {
+ int32_t range_; // range-1
+ int32_t value_;
+ int run_; // number of outstanding bits
+ int nb_bits_; // number of pending bits
+ uint8_t* buf_; // internal buffer. Re-allocated regularly. Not owned.
+ size_t pos_;
+ size_t max_pos_;
+ int error_; // true in case of error
+};
+
+// Initialize the object. Allocates some initial memory based on expected_size.
+int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size);
+// Finalize the bitstream coding. Returns a pointer to the internal buffer.
+uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw);
+// Release any pending memory and zeroes the object. Not a mandatory call.
+// Only useful in case of error, when the internal buffer hasn't been grabbed!
+void VP8BitWriterWipeOut(VP8BitWriter* const bw);
+
+int VP8PutBit(VP8BitWriter* const bw, int bit, int prob);
+int VP8PutBitUniform(VP8BitWriter* const bw, int bit);
+void VP8PutValue(VP8BitWriter* const bw, int value, int nb_bits);
+void VP8PutSignedValue(VP8BitWriter* const bw, int value, int nb_bits);
+
+// Appends some bytes to the internal buffer. Data is copied.
+int VP8BitWriterAppend(VP8BitWriter* const bw,
+ const uint8_t* data, size_t size);
+
+// return approximate write position (in bits)
+static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) {
+ return (uint64_t)(bw->pos_ + bw->run_) * 8 + 8 + bw->nb_bits_;
+}
+
+// Returns a pointer to the internal buffer.
+static WEBP_INLINE uint8_t* VP8BitWriterBuf(const VP8BitWriter* const bw) {
+ return bw->buf_;
+}
+// Returns the size of the internal buffer.
+static WEBP_INLINE size_t VP8BitWriterSize(const VP8BitWriter* const bw) {
+ return bw->pos_;
+}
+
+//------------------------------------------------------------------------------
+// VP8LBitWriter
+// TODO(vikasa): VP8LBitWriter is copied as-is from lossless code. There's scope
+// of re-using VP8BitWriter. Will evaluate once basic lossless encoder is
+// implemented.
+
+typedef struct {
+ uint8_t* buf_;
+ size_t bit_pos_;
+ size_t max_bytes_;
+
+ // After all bits are written, the caller must observe the state of
+ // error_. A value of 1 indicates that a memory allocation failure
+ // has happened during bit writing. A value of 0 indicates successful
+ // writing of bits.
+ int error_;
+} VP8LBitWriter;
+
+static WEBP_INLINE size_t VP8LBitWriterNumBytes(VP8LBitWriter* const bw) {
+ return (bw->bit_pos_ + 7) >> 3;
+}
+
+static WEBP_INLINE uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw) {
+ return bw->buf_;
+}
+
+// Returns 0 in case of memory allocation error.
+int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size);
+
+void VP8LBitWriterDestroy(VP8LBitWriter* const bw);
+
+// This function writes bits into bytes in increasing addresses, and within
+// a byte least-significant-bit first.
+//
+// The function can write up to 16 bits in one go with WriteBits
+// Example: let's assume that 3 bits (Rs below) have been written already:
+//
+// BYTE-0 BYTE+1 BYTE+2
+//
+// 0000 0RRR 0000 0000 0000 0000
+//
+// Now, we could write 5 or less bits in MSB by just sifting by 3
+// and OR'ing to BYTE-0.
+//
+// For n bits, we take the last 5 bytes, OR that with high bits in BYTE-0,
+// and locate the rest in BYTE+1 and BYTE+2.
+//
+// VP8LBitWriter's error_ flag is set in case of memory allocation error.
+void VP8LWriteBits(VP8LBitWriter* const bw, int n_bits, uint32_t bits);
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_UTILS_BIT_WRITER_H_ */
diff --git a/drivers/webpold/utils/color_cache.c b/drivers/webpold/utils/color_cache.c
new file mode 100644
index 0000000000..560f81db10
--- /dev/null
+++ b/drivers/webpold/utils/color_cache.c
@@ -0,0 +1,44 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Color Cache for WebP Lossless
+//
+// Author: Jyrki Alakuijala (jyrki@google.com)
+
+#include <assert.h>
+#include <stdlib.h>
+#include "./color_cache.h"
+#include "../utils/utils.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// VP8LColorCache.
+
+int VP8LColorCacheInit(VP8LColorCache* const cc, int hash_bits) {
+ const int hash_size = 1 << hash_bits;
+ assert(cc != NULL);
+ assert(hash_bits > 0);
+ cc->colors_ = (uint32_t*)WebPSafeCalloc((uint64_t)hash_size,
+ sizeof(*cc->colors_));
+ if (cc->colors_ == NULL) return 0;
+ cc->hash_shift_ = 32 - hash_bits;
+ return 1;
+}
+
+void VP8LColorCacheClear(VP8LColorCache* const cc) {
+ if (cc != NULL) {
+ free(cc->colors_);
+ cc->colors_ = NULL;
+ }
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
diff --git a/drivers/webpold/utils/color_cache.h b/drivers/webpold/utils/color_cache.h
new file mode 100644
index 0000000000..da5e260195
--- /dev/null
+++ b/drivers/webpold/utils/color_cache.h
@@ -0,0 +1,68 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Color Cache for WebP Lossless
+//
+// Authors: Jyrki Alakuijala (jyrki@google.com)
+// Urvang Joshi (urvang@google.com)
+
+#ifndef WEBP_UTILS_COLOR_CACHE_H_
+#define WEBP_UTILS_COLOR_CACHE_H_
+
+#include "../types.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+// Main color cache struct.
+typedef struct {
+ uint32_t *colors_; // color entries
+ int hash_shift_; // Hash shift: 32 - hash_bits.
+} VP8LColorCache;
+
+static const uint32_t kHashMul = 0x1e35a7bd;
+
+static WEBP_INLINE uint32_t VP8LColorCacheLookup(
+ const VP8LColorCache* const cc, uint32_t key) {
+ assert(key <= (~0U >> cc->hash_shift_));
+ return cc->colors_[key];
+}
+
+static WEBP_INLINE void VP8LColorCacheInsert(const VP8LColorCache* const cc,
+ uint32_t argb) {
+ const uint32_t key = (kHashMul * argb) >> cc->hash_shift_;
+ cc->colors_[key] = argb;
+}
+
+static WEBP_INLINE int VP8LColorCacheGetIndex(const VP8LColorCache* const cc,
+ uint32_t argb) {
+ return (kHashMul * argb) >> cc->hash_shift_;
+}
+
+static WEBP_INLINE int VP8LColorCacheContains(const VP8LColorCache* const cc,
+ uint32_t argb) {
+ const uint32_t key = (kHashMul * argb) >> cc->hash_shift_;
+ return cc->colors_[key] == argb;
+}
+
+//------------------------------------------------------------------------------
+
+// Initializes the color cache with 'hash_bits' bits for the keys.
+// Returns false in case of memory error.
+int VP8LColorCacheInit(VP8LColorCache* const color_cache, int hash_bits);
+
+// Delete the memory associated to color cache.
+void VP8LColorCacheClear(VP8LColorCache* const color_cache);
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif // WEBP_UTILS_COLOR_CACHE_H_
diff --git a/drivers/webpold/utils/filters.c b/drivers/webpold/utils/filters.c
new file mode 100644
index 0000000000..08f52a3d20
--- /dev/null
+++ b/drivers/webpold/utils/filters.c
@@ -0,0 +1,229 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Spatial prediction using various filters
+//
+// Author: Urvang (urvang@google.com)
+
+#include "./filters.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Helpful macro.
+
+# define SANITY_CHECK(in, out) \
+ assert(in != NULL); \
+ assert(out != NULL); \
+ assert(width > 0); \
+ assert(height > 0); \
+ assert(bpp > 0); \
+ assert(stride >= width * bpp);
+
+static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred,
+ uint8_t* dst, int length, int inverse) {
+ int i;
+ if (inverse) {
+ for (i = 0; i < length; ++i) dst[i] = src[i] + pred[i];
+ } else {
+ for (i = 0; i < length; ++i) dst[i] = src[i] - pred[i];
+ }
+}
+
+//------------------------------------------------------------------------------
+// Horizontal filter.
+
+static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in,
+ int width, int height, int bpp, int stride, int inverse, uint8_t* out) {
+ int h;
+ const uint8_t* preds = (inverse ? out : in);
+ SANITY_CHECK(in, out);
+
+ // Filter line-by-line.
+ for (h = 0; h < height; ++h) {
+ // Leftmost pixel is predicted from above (except for topmost scanline).
+ if (h == 0) {
+ memcpy((void*)out, (const void*)in, bpp);
+ } else {
+ PredictLine(in, preds - stride, out, bpp, inverse);
+ }
+ PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse);
+ preds += stride;
+ in += stride;
+ out += stride;
+ }
+}
+
+static void HorizontalFilter(const uint8_t* data, int width, int height,
+ int bpp, int stride, uint8_t* filtered_data) {
+ DoHorizontalFilter(data, width, height, bpp, stride, 0, filtered_data);
+}
+
+static void HorizontalUnfilter(const uint8_t* data, int width, int height,
+ int bpp, int stride, uint8_t* recon_data) {
+ DoHorizontalFilter(data, width, height, bpp, stride, 1, recon_data);
+}
+
+//------------------------------------------------------------------------------
+// Vertical filter.
+
+static WEBP_INLINE void DoVerticalFilter(const uint8_t* in,
+ int width, int height, int bpp, int stride, int inverse, uint8_t* out) {
+ int h;
+ const uint8_t* preds = (inverse ? out : in);
+ SANITY_CHECK(in, out);
+
+ // Very first top-left pixel is copied.
+ memcpy((void*)out, (const void*)in, bpp);
+ // Rest of top scan-line is left-predicted.
+ PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse);
+
+ // Filter line-by-line.
+ for (h = 1; h < height; ++h) {
+ in += stride;
+ out += stride;
+ PredictLine(in, preds, out, bpp * width, inverse);
+ preds += stride;
+ }
+}
+
+static void VerticalFilter(const uint8_t* data, int width, int height,
+ int bpp, int stride, uint8_t* filtered_data) {
+ DoVerticalFilter(data, width, height, bpp, stride, 0, filtered_data);
+}
+
+static void VerticalUnfilter(const uint8_t* data, int width, int height,
+ int bpp, int stride, uint8_t* recon_data) {
+ DoVerticalFilter(data, width, height, bpp, stride, 1, recon_data);
+}
+
+//------------------------------------------------------------------------------
+// Gradient filter.
+
+static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) {
+ const int g = a + b - c;
+ return (g < 0) ? 0 : (g > 255) ? 255 : g;
+}
+
+static WEBP_INLINE
+void DoGradientFilter(const uint8_t* in, int width, int height,
+ int bpp, int stride, int inverse, uint8_t* out) {
+ const uint8_t* preds = (inverse ? out : in);
+ int h;
+ SANITY_CHECK(in, out);
+
+ // left prediction for top scan-line
+ memcpy((void*)out, (const void*)in, bpp);
+ PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse);
+
+ // Filter line-by-line.
+ for (h = 1; h < height; ++h) {
+ int w;
+ preds += stride;
+ in += stride;
+ out += stride;
+ // leftmost pixel: predict from above.
+ PredictLine(in, preds - stride, out, bpp, inverse);
+ for (w = bpp; w < width * bpp; ++w) {
+ const int pred = GradientPredictor(preds[w - bpp],
+ preds[w - stride],
+ preds[w - stride - bpp]);
+ out[w] = in[w] + (inverse ? pred : -pred);
+ }
+ }
+}
+
+static void GradientFilter(const uint8_t* data, int width, int height,
+ int bpp, int stride, uint8_t* filtered_data) {
+ DoGradientFilter(data, width, height, bpp, stride, 0, filtered_data);
+}
+
+static void GradientUnfilter(const uint8_t* data, int width, int height,
+ int bpp, int stride, uint8_t* recon_data) {
+ DoGradientFilter(data, width, height, bpp, stride, 1, recon_data);
+}
+
+#undef SANITY_CHECK
+
+// -----------------------------------------------------------------------------
+// Quick estimate of a potentially interesting filter mode to try, in addition
+// to the default NONE.
+
+#define SMAX 16
+#define SDIFF(a, b) (abs((a) - (b)) >> 4) // Scoring diff, in [0..SMAX)
+
+WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data,
+ int width, int height, int stride) {
+ int i, j;
+ int bins[WEBP_FILTER_LAST][SMAX];
+ memset(bins, 0, sizeof(bins));
+ // We only sample every other pixels. That's enough.
+ for (j = 2; j < height - 1; j += 2) {
+ const uint8_t* const p = data + j * stride;
+ int mean = p[0];
+ for (i = 2; i < width - 1; i += 2) {
+ const int diff0 = SDIFF(p[i], mean);
+ const int diff1 = SDIFF(p[i], p[i - 1]);
+ const int diff2 = SDIFF(p[i], p[i - width]);
+ const int grad_pred =
+ GradientPredictor(p[i - 1], p[i - width], p[i - width - 1]);
+ const int diff3 = SDIFF(p[i], grad_pred);
+ bins[WEBP_FILTER_NONE][diff0] = 1;
+ bins[WEBP_FILTER_HORIZONTAL][diff1] = 1;
+ bins[WEBP_FILTER_VERTICAL][diff2] = 1;
+ bins[WEBP_FILTER_GRADIENT][diff3] = 1;
+ mean = (3 * mean + p[i] + 2) >> 2;
+ }
+ }
+ {
+ WEBP_FILTER_TYPE filter, best_filter = WEBP_FILTER_NONE;
+ int best_score = 0x7fffffff;
+ for (filter = WEBP_FILTER_NONE; filter < WEBP_FILTER_LAST; ++filter) {
+ int score = 0;
+ for (i = 0; i < SMAX; ++i) {
+ if (bins[filter][i] > 0) {
+ score += i;
+ }
+ }
+ if (score < best_score) {
+ best_score = score;
+ best_filter = filter;
+ }
+ }
+ return best_filter;
+ }
+}
+
+#undef SMAX
+#undef SDIFF
+
+//------------------------------------------------------------------------------
+
+const WebPFilterFunc WebPFilters[WEBP_FILTER_LAST] = {
+ NULL, // WEBP_FILTER_NONE
+ HorizontalFilter, // WEBP_FILTER_HORIZONTAL
+ VerticalFilter, // WEBP_FILTER_VERTICAL
+ GradientFilter // WEBP_FILTER_GRADIENT
+};
+
+const WebPFilterFunc WebPUnfilters[WEBP_FILTER_LAST] = {
+ NULL, // WEBP_FILTER_NONE
+ HorizontalUnfilter, // WEBP_FILTER_HORIZONTAL
+ VerticalUnfilter, // WEBP_FILTER_VERTICAL
+ GradientUnfilter // WEBP_FILTER_GRADIENT
+};
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/utils/filters.h b/drivers/webpold/utils/filters.h
new file mode 100644
index 0000000000..db886be29a
--- /dev/null
+++ b/drivers/webpold/utils/filters.h
@@ -0,0 +1,54 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Spatial prediction using various filters
+//
+// Author: Urvang (urvang@google.com)
+
+#ifndef WEBP_UTILS_FILTERS_H_
+#define WEBP_UTILS_FILTERS_H_
+
+#include "../types.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+// Filters.
+typedef enum {
+ WEBP_FILTER_NONE = 0,
+ WEBP_FILTER_HORIZONTAL,
+ WEBP_FILTER_VERTICAL,
+ WEBP_FILTER_GRADIENT,
+ WEBP_FILTER_LAST = WEBP_FILTER_GRADIENT + 1, // end marker
+ WEBP_FILTER_BEST,
+ WEBP_FILTER_FAST
+} WEBP_FILTER_TYPE;
+
+typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height,
+ int bpp, int stride, uint8_t* out);
+
+// Filter the given data using the given predictor.
+// 'in' corresponds to a 2-dimensional pixel array of size (stride * height)
+// in raster order.
+// 'bpp' is number of bytes per pixel, and
+// 'stride' is number of bytes per scan line (with possible padding).
+// 'out' should be pre-allocated.
+extern const WebPFilterFunc WebPFilters[WEBP_FILTER_LAST];
+
+// Reconstruct the original data from the given filtered data.
+extern const WebPFilterFunc WebPUnfilters[WEBP_FILTER_LAST];
+
+// Fast estimate of a potentially good filter.
+extern WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data,
+ int width, int height, int stride);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_UTILS_FILTERS_H_ */
diff --git a/drivers/webpold/utils/huffman.c b/drivers/webpold/utils/huffman.c
new file mode 100644
index 0000000000..1cc1cfd355
--- /dev/null
+++ b/drivers/webpold/utils/huffman.c
@@ -0,0 +1,238 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Utilities for building and looking up Huffman trees.
+//
+// Author: Urvang Joshi (urvang@google.com)
+
+#include <assert.h>
+#include <stdlib.h>
+#include "./huffman.h"
+#include "../utils/utils.h"
+#include "../format_constants.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define NON_EXISTENT_SYMBOL (-1)
+
+static void TreeNodeInit(HuffmanTreeNode* const node) {
+ node->children_ = -1; // means: 'unassigned so far'
+}
+
+static int NodeIsEmpty(const HuffmanTreeNode* const node) {
+ return (node->children_ < 0);
+}
+
+static int IsFull(const HuffmanTree* const tree) {
+ return (tree->num_nodes_ == tree->max_nodes_);
+}
+
+static void AssignChildren(HuffmanTree* const tree,
+ HuffmanTreeNode* const node) {
+ HuffmanTreeNode* const children = tree->root_ + tree->num_nodes_;
+ node->children_ = (int)(children - node);
+ assert(children - node == (int)(children - node));
+ tree->num_nodes_ += 2;
+ TreeNodeInit(children + 0);
+ TreeNodeInit(children + 1);
+}
+
+static int TreeInit(HuffmanTree* const tree, int num_leaves) {
+ assert(tree != NULL);
+ if (num_leaves == 0) return 0;
+ // We allocate maximum possible nodes in the tree at once.
+ // Note that a Huffman tree is a full binary tree; and in a full binary tree
+ // with L leaves, the total number of nodes N = 2 * L - 1.
+ tree->max_nodes_ = 2 * num_leaves - 1;
+ tree->root_ = (HuffmanTreeNode*)WebPSafeMalloc((uint64_t)tree->max_nodes_,
+ sizeof(*tree->root_));
+ if (tree->root_ == NULL) return 0;
+ TreeNodeInit(tree->root_); // Initialize root.
+ tree->num_nodes_ = 1;
+ return 1;
+}
+
+void HuffmanTreeRelease(HuffmanTree* const tree) {
+ if (tree != NULL) {
+ free(tree->root_);
+ tree->root_ = NULL;
+ tree->max_nodes_ = 0;
+ tree->num_nodes_ = 0;
+ }
+}
+
+int HuffmanCodeLengthsToCodes(const int* const code_lengths,
+ int code_lengths_size, int* const huff_codes) {
+ int symbol;
+ int code_len;
+ int code_length_hist[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 };
+ int curr_code;
+ int next_codes[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 };
+ int max_code_length = 0;
+
+ assert(code_lengths != NULL);
+ assert(code_lengths_size > 0);
+ assert(huff_codes != NULL);
+
+ // Calculate max code length.
+ for (symbol = 0; symbol < code_lengths_size; ++symbol) {
+ if (code_lengths[symbol] > max_code_length) {
+ max_code_length = code_lengths[symbol];
+ }
+ }
+ if (max_code_length > MAX_ALLOWED_CODE_LENGTH) return 0;
+
+ // Calculate code length histogram.
+ for (symbol = 0; symbol < code_lengths_size; ++symbol) {
+ ++code_length_hist[code_lengths[symbol]];
+ }
+ code_length_hist[0] = 0;
+
+ // Calculate the initial values of 'next_codes' for each code length.
+ // next_codes[code_len] denotes the code to be assigned to the next symbol
+ // of code length 'code_len'.
+ curr_code = 0;
+ next_codes[0] = -1; // Unused, as code length = 0 implies code doesn't exist.
+ for (code_len = 1; code_len <= max_code_length; ++code_len) {
+ curr_code = (curr_code + code_length_hist[code_len - 1]) << 1;
+ next_codes[code_len] = curr_code;
+ }
+
+ // Get symbols.
+ for (symbol = 0; symbol < code_lengths_size; ++symbol) {
+ if (code_lengths[symbol] > 0) {
+ huff_codes[symbol] = next_codes[code_lengths[symbol]]++;
+ } else {
+ huff_codes[symbol] = NON_EXISTENT_SYMBOL;
+ }
+ }
+ return 1;
+}
+
+static int TreeAddSymbol(HuffmanTree* const tree,
+ int symbol, int code, int code_length) {
+ HuffmanTreeNode* node = tree->root_;
+ const HuffmanTreeNode* const max_node = tree->root_ + tree->max_nodes_;
+ while (code_length-- > 0) {
+ if (node >= max_node) {
+ return 0;
+ }
+ if (NodeIsEmpty(node)) {
+ if (IsFull(tree)) return 0; // error: too many symbols.
+ AssignChildren(tree, node);
+ } else if (HuffmanTreeNodeIsLeaf(node)) {
+ return 0; // leaf is already occupied.
+ }
+ node += node->children_ + ((code >> code_length) & 1);
+ }
+ if (NodeIsEmpty(node)) {
+ node->children_ = 0; // turn newly created node into a leaf.
+ } else if (!HuffmanTreeNodeIsLeaf(node)) {
+ return 0; // trying to assign a symbol to already used code.
+ }
+ node->symbol_ = symbol; // Add symbol in this node.
+ return 1;
+}
+
+int HuffmanTreeBuildImplicit(HuffmanTree* const tree,
+ const int* const code_lengths,
+ int code_lengths_size) {
+ int symbol;
+ int num_symbols = 0;
+ int root_symbol = 0;
+
+ assert(tree != NULL);
+ assert(code_lengths != NULL);
+
+ // Find out number of symbols and the root symbol.
+ for (symbol = 0; symbol < code_lengths_size; ++symbol) {
+ if (code_lengths[symbol] > 0) {
+ // Note: code length = 0 indicates non-existent symbol.
+ ++num_symbols;
+ root_symbol = symbol;
+ }
+ }
+
+ // Initialize the tree. Will fail for num_symbols = 0
+ if (!TreeInit(tree, num_symbols)) return 0;
+
+ // Build tree.
+ if (num_symbols == 1) { // Trivial case.
+ const int max_symbol = code_lengths_size;
+ if (root_symbol < 0 || root_symbol >= max_symbol) {
+ HuffmanTreeRelease(tree);
+ return 0;
+ }
+ return TreeAddSymbol(tree, root_symbol, 0, 0);
+ } else { // Normal case.
+ int ok = 0;
+
+ // Get Huffman codes from the code lengths.
+ int* const codes =
+ (int*)WebPSafeMalloc((uint64_t)code_lengths_size, sizeof(*codes));
+ if (codes == NULL) goto End;
+
+ if (!HuffmanCodeLengthsToCodes(code_lengths, code_lengths_size, codes)) {
+ goto End;
+ }
+
+ // Add symbols one-by-one.
+ for (symbol = 0; symbol < code_lengths_size; ++symbol) {
+ if (code_lengths[symbol] > 0) {
+ if (!TreeAddSymbol(tree, symbol, codes[symbol], code_lengths[symbol])) {
+ goto End;
+ }
+ }
+ }
+ ok = 1;
+ End:
+ free(codes);
+ ok = ok && IsFull(tree);
+ if (!ok) HuffmanTreeRelease(tree);
+ return ok;
+ }
+}
+
+int HuffmanTreeBuildExplicit(HuffmanTree* const tree,
+ const int* const code_lengths,
+ const int* const codes,
+ const int* const symbols, int max_symbol,
+ int num_symbols) {
+ int ok = 0;
+ int i;
+
+ assert(tree != NULL);
+ assert(code_lengths != NULL);
+ assert(codes != NULL);
+ assert(symbols != NULL);
+
+ // Initialize the tree. Will fail if num_symbols = 0.
+ if (!TreeInit(tree, num_symbols)) return 0;
+
+ // Add symbols one-by-one.
+ for (i = 0; i < num_symbols; ++i) {
+ if (codes[i] != NON_EXISTENT_SYMBOL) {
+ if (symbols[i] < 0 || symbols[i] >= max_symbol) {
+ goto End;
+ }
+ if (!TreeAddSymbol(tree, symbols[i], codes[i], code_lengths[i])) {
+ goto End;
+ }
+ }
+ }
+ ok = 1;
+ End:
+ ok = ok && IsFull(tree);
+ if (!ok) HuffmanTreeRelease(tree);
+ return ok;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/utils/huffman.h b/drivers/webpold/utils/huffman.h
new file mode 100644
index 0000000000..f16447e649
--- /dev/null
+++ b/drivers/webpold/utils/huffman.h
@@ -0,0 +1,78 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Utilities for building and looking up Huffman trees.
+//
+// Author: Urvang Joshi (urvang@google.com)
+
+#ifndef WEBP_UTILS_HUFFMAN_H_
+#define WEBP_UTILS_HUFFMAN_H_
+
+#include <assert.h>
+#include "../types.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+// A node of a Huffman tree.
+typedef struct {
+ int symbol_;
+ int children_; // delta offset to both children (contiguous) or 0 if leaf.
+} HuffmanTreeNode;
+
+// Huffman Tree.
+typedef struct HuffmanTree HuffmanTree;
+struct HuffmanTree {
+ HuffmanTreeNode* root_; // all the nodes, starting at root.
+ int max_nodes_; // max number of nodes
+ int num_nodes_; // number of currently occupied nodes
+};
+
+// Returns true if the given node is a leaf of the Huffman tree.
+static WEBP_INLINE int HuffmanTreeNodeIsLeaf(
+ const HuffmanTreeNode* const node) {
+ return (node->children_ == 0);
+}
+
+// Go down one level. Most critical function. 'right_child' must be 0 or 1.
+static WEBP_INLINE const HuffmanTreeNode* HuffmanTreeNextNode(
+ const HuffmanTreeNode* node, int right_child) {
+ return node + node->children_ + right_child;
+}
+
+// Releases the nodes of the Huffman tree.
+// Note: It does NOT free 'tree' itself.
+void HuffmanTreeRelease(HuffmanTree* const tree);
+
+// Builds Huffman tree assuming code lengths are implicitly in symbol order.
+// Returns false in case of error (invalid tree or memory error).
+int HuffmanTreeBuildImplicit(HuffmanTree* const tree,
+ const int* const code_lengths,
+ int code_lengths_size);
+
+// Build a Huffman tree with explicitly given lists of code lengths, codes
+// and symbols. Verifies that all symbols added are smaller than max_symbol.
+// Returns false in case of an invalid symbol, invalid tree or memory error.
+int HuffmanTreeBuildExplicit(HuffmanTree* const tree,
+ const int* const code_lengths,
+ const int* const codes,
+ const int* const symbols, int max_symbol,
+ int num_symbols);
+
+// Utility: converts Huffman code lengths to corresponding Huffman codes.
+// 'huff_codes' should be pre-allocated.
+// Returns false in case of error (memory allocation, invalid codes).
+int HuffmanCodeLengthsToCodes(const int* const code_lengths,
+ int code_lengths_size, int* const huff_codes);
+
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif // WEBP_UTILS_HUFFMAN_H_
diff --git a/drivers/webpold/utils/huffman_encode.c b/drivers/webpold/utils/huffman_encode.c
new file mode 100644
index 0000000000..e172b10a85
--- /dev/null
+++ b/drivers/webpold/utils/huffman_encode.c
@@ -0,0 +1,439 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Author: Jyrki Alakuijala (jyrki@google.com)
+//
+// Entropy encoding (Huffman) for webp lossless.
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "./huffman_encode.h"
+#include "../utils/utils.h"
+#include "../format_constants.h"
+
+// -----------------------------------------------------------------------------
+// Util function to optimize the symbol map for RLE coding
+
+// Heuristics for selecting the stride ranges to collapse.
+static int ValuesShouldBeCollapsedToStrideAverage(int a, int b) {
+ return abs(a - b) < 4;
+}
+
+// Change the population counts in a way that the consequent
+// Hufmann tree compression, especially its RLE-part, give smaller output.
+static int OptimizeHuffmanForRle(int length, int* const counts) {
+ uint8_t* good_for_rle;
+ // 1) Let's make the Huffman code more compatible with rle encoding.
+ int i;
+ for (; length >= 0; --length) {
+ if (length == 0) {
+ return 1; // All zeros.
+ }
+ if (counts[length - 1] != 0) {
+ // Now counts[0..length - 1] does not have trailing zeros.
+ break;
+ }
+ }
+ // 2) Let's mark all population counts that already can be encoded
+ // with an rle code.
+ good_for_rle = (uint8_t*)calloc(length, 1);
+ if (good_for_rle == NULL) {
+ return 0;
+ }
+ {
+ // Let's not spoil any of the existing good rle codes.
+ // Mark any seq of 0's that is longer as 5 as a good_for_rle.
+ // Mark any seq of non-0's that is longer as 7 as a good_for_rle.
+ int symbol = counts[0];
+ int stride = 0;
+ for (i = 0; i < length + 1; ++i) {
+ if (i == length || counts[i] != symbol) {
+ if ((symbol == 0 && stride >= 5) ||
+ (symbol != 0 && stride >= 7)) {
+ int k;
+ for (k = 0; k < stride; ++k) {
+ good_for_rle[i - k - 1] = 1;
+ }
+ }
+ stride = 1;
+ if (i != length) {
+ symbol = counts[i];
+ }
+ } else {
+ ++stride;
+ }
+ }
+ }
+ // 3) Let's replace those population counts that lead to more rle codes.
+ {
+ int stride = 0;
+ int limit = counts[0];
+ int sum = 0;
+ for (i = 0; i < length + 1; ++i) {
+ if (i == length || good_for_rle[i] ||
+ (i != 0 && good_for_rle[i - 1]) ||
+ !ValuesShouldBeCollapsedToStrideAverage(counts[i], limit)) {
+ if (stride >= 4 || (stride >= 3 && sum == 0)) {
+ int k;
+ // The stride must end, collapse what we have, if we have enough (4).
+ int count = (sum + stride / 2) / stride;
+ if (count < 1) {
+ count = 1;
+ }
+ if (sum == 0) {
+ // Don't make an all zeros stride to be upgraded to ones.
+ count = 0;
+ }
+ for (k = 0; k < stride; ++k) {
+ // We don't want to change value at counts[i],
+ // that is already belonging to the next stride. Thus - 1.
+ counts[i - k - 1] = count;
+ }
+ }
+ stride = 0;
+ sum = 0;
+ if (i < length - 3) {
+ // All interesting strides have a count of at least 4,
+ // at least when non-zeros.
+ limit = (counts[i] + counts[i + 1] +
+ counts[i + 2] + counts[i + 3] + 2) / 4;
+ } else if (i < length) {
+ limit = counts[i];
+ } else {
+ limit = 0;
+ }
+ }
+ ++stride;
+ if (i != length) {
+ sum += counts[i];
+ if (stride >= 4) {
+ limit = (sum + stride / 2) / stride;
+ }
+ }
+ }
+ }
+ free(good_for_rle);
+ return 1;
+}
+
+typedef struct {
+ int total_count_;
+ int value_;
+ int pool_index_left_;
+ int pool_index_right_;
+} HuffmanTree;
+
+// A comparer function for two Huffman trees: sorts first by 'total count'
+// (more comes first), and then by 'value' (more comes first).
+static int CompareHuffmanTrees(const void* ptr1, const void* ptr2) {
+ const HuffmanTree* const t1 = (const HuffmanTree*)ptr1;
+ const HuffmanTree* const t2 = (const HuffmanTree*)ptr2;
+ if (t1->total_count_ > t2->total_count_) {
+ return -1;
+ } else if (t1->total_count_ < t2->total_count_) {
+ return 1;
+ } else {
+ if (t1->value_ < t2->value_) {
+ return -1;
+ }
+ if (t1->value_ > t2->value_) {
+ return 1;
+ }
+ return 0;
+ }
+}
+
+static void SetBitDepths(const HuffmanTree* const tree,
+ const HuffmanTree* const pool,
+ uint8_t* const bit_depths, int level) {
+ if (tree->pool_index_left_ >= 0) {
+ SetBitDepths(&pool[tree->pool_index_left_], pool, bit_depths, level + 1);
+ SetBitDepths(&pool[tree->pool_index_right_], pool, bit_depths, level + 1);
+ } else {
+ bit_depths[tree->value_] = level;
+ }
+}
+
+// Create an optimal Huffman tree.
+//
+// (data,length): population counts.
+// tree_limit: maximum bit depth (inclusive) of the codes.
+// bit_depths[]: how many bits are used for the symbol.
+//
+// Returns 0 when an error has occurred.
+//
+// The catch here is that the tree cannot be arbitrarily deep
+//
+// count_limit is the value that is to be faked as the minimum value
+// and this minimum value is raised until the tree matches the
+// maximum length requirement.
+//
+// This algorithm is not of excellent performance for very long data blocks,
+// especially when population counts are longer than 2**tree_limit, but
+// we are not planning to use this with extremely long blocks.
+//
+// See http://en.wikipedia.org/wiki/Huffman_coding
+static int GenerateOptimalTree(const int* const histogram, int histogram_size,
+ int tree_depth_limit,
+ uint8_t* const bit_depths) {
+ int count_min;
+ HuffmanTree* tree_pool;
+ HuffmanTree* tree;
+ int tree_size_orig = 0;
+ int i;
+
+ for (i = 0; i < histogram_size; ++i) {
+ if (histogram[i] != 0) {
+ ++tree_size_orig;
+ }
+ }
+
+ // 3 * tree_size is enough to cover all the nodes representing a
+ // population and all the inserted nodes combining two existing nodes.
+ // The tree pool needs 2 * (tree_size_orig - 1) entities, and the
+ // tree needs exactly tree_size_orig entities.
+ tree = (HuffmanTree*)WebPSafeMalloc(3ULL * tree_size_orig, sizeof(*tree));
+ if (tree == NULL) return 0;
+ tree_pool = tree + tree_size_orig;
+
+ // For block sizes with less than 64k symbols we never need to do a
+ // second iteration of this loop.
+ // If we actually start running inside this loop a lot, we would perhaps
+ // be better off with the Katajainen algorithm.
+ assert(tree_size_orig <= (1 << (tree_depth_limit - 1)));
+ for (count_min = 1; ; count_min *= 2) {
+ int tree_size = tree_size_orig;
+ // We need to pack the Huffman tree in tree_depth_limit bits.
+ // So, we try by faking histogram entries to be at least 'count_min'.
+ int idx = 0;
+ int j;
+ for (j = 0; j < histogram_size; ++j) {
+ if (histogram[j] != 0) {
+ const int count =
+ (histogram[j] < count_min) ? count_min : histogram[j];
+ tree[idx].total_count_ = count;
+ tree[idx].value_ = j;
+ tree[idx].pool_index_left_ = -1;
+ tree[idx].pool_index_right_ = -1;
+ ++idx;
+ }
+ }
+
+ // Build the Huffman tree.
+ qsort(tree, tree_size, sizeof(*tree), CompareHuffmanTrees);
+
+ if (tree_size > 1) { // Normal case.
+ int tree_pool_size = 0;
+ while (tree_size > 1) { // Finish when we have only one root.
+ int count;
+ tree_pool[tree_pool_size++] = tree[tree_size - 1];
+ tree_pool[tree_pool_size++] = tree[tree_size - 2];
+ count = tree_pool[tree_pool_size - 1].total_count_ +
+ tree_pool[tree_pool_size - 2].total_count_;
+ tree_size -= 2;
+ {
+ // Search for the insertion point.
+ int k;
+ for (k = 0; k < tree_size; ++k) {
+ if (tree[k].total_count_ <= count) {
+ break;
+ }
+ }
+ memmove(tree + (k + 1), tree + k, (tree_size - k) * sizeof(*tree));
+ tree[k].total_count_ = count;
+ tree[k].value_ = -1;
+
+ tree[k].pool_index_left_ = tree_pool_size - 1;
+ tree[k].pool_index_right_ = tree_pool_size - 2;
+ tree_size = tree_size + 1;
+ }
+ }
+ SetBitDepths(&tree[0], tree_pool, bit_depths, 0);
+ } else if (tree_size == 1) { // Trivial case: only one element.
+ bit_depths[tree[0].value_] = 1;
+ }
+
+ {
+ // Test if this Huffman tree satisfies our 'tree_depth_limit' criteria.
+ int max_depth = bit_depths[0];
+ for (j = 1; j < histogram_size; ++j) {
+ if (max_depth < bit_depths[j]) {
+ max_depth = bit_depths[j];
+ }
+ }
+ if (max_depth <= tree_depth_limit) {
+ break;
+ }
+ }
+ }
+ free(tree);
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+// Coding of the Huffman tree values
+
+static HuffmanTreeToken* CodeRepeatedValues(int repetitions,
+ HuffmanTreeToken* tokens,
+ int value, int prev_value) {
+ assert(value <= MAX_ALLOWED_CODE_LENGTH);
+ if (value != prev_value) {
+ tokens->code = value;
+ tokens->extra_bits = 0;
+ ++tokens;
+ --repetitions;
+ }
+ while (repetitions >= 1) {
+ if (repetitions < 3) {
+ int i;
+ for (i = 0; i < repetitions; ++i) {
+ tokens->code = value;
+ tokens->extra_bits = 0;
+ ++tokens;
+ }
+ break;
+ } else if (repetitions < 7) {
+ tokens->code = 16;
+ tokens->extra_bits = repetitions - 3;
+ ++tokens;
+ break;
+ } else {
+ tokens->code = 16;
+ tokens->extra_bits = 3;
+ ++tokens;
+ repetitions -= 6;
+ }
+ }
+ return tokens;
+}
+
+static HuffmanTreeToken* CodeRepeatedZeros(int repetitions,
+ HuffmanTreeToken* tokens) {
+ while (repetitions >= 1) {
+ if (repetitions < 3) {
+ int i;
+ for (i = 0; i < repetitions; ++i) {
+ tokens->code = 0; // 0-value
+ tokens->extra_bits = 0;
+ ++tokens;
+ }
+ break;
+ } else if (repetitions < 11) {
+ tokens->code = 17;
+ tokens->extra_bits = repetitions - 3;
+ ++tokens;
+ break;
+ } else if (repetitions < 139) {
+ tokens->code = 18;
+ tokens->extra_bits = repetitions - 11;
+ ++tokens;
+ break;
+ } else {
+ tokens->code = 18;
+ tokens->extra_bits = 0x7f; // 138 repeated 0s
+ ++tokens;
+ repetitions -= 138;
+ }
+ }
+ return tokens;
+}
+
+int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree,
+ HuffmanTreeToken* tokens, int max_tokens) {
+ HuffmanTreeToken* const starting_token = tokens;
+ HuffmanTreeToken* const ending_token = tokens + max_tokens;
+ const int depth_size = tree->num_symbols;
+ int prev_value = 8; // 8 is the initial value for rle.
+ int i = 0;
+ assert(tokens != NULL);
+ while (i < depth_size) {
+ const int value = tree->code_lengths[i];
+ int k = i + 1;
+ int runs;
+ while (k < depth_size && tree->code_lengths[k] == value) ++k;
+ runs = k - i;
+ if (value == 0) {
+ tokens = CodeRepeatedZeros(runs, tokens);
+ } else {
+ tokens = CodeRepeatedValues(runs, tokens, value, prev_value);
+ prev_value = value;
+ }
+ i += runs;
+ assert(tokens <= ending_token);
+ }
+ (void)ending_token; // suppress 'unused variable' warning
+ return (int)(tokens - starting_token);
+}
+
+// -----------------------------------------------------------------------------
+
+// Pre-reversed 4-bit values.
+static const uint8_t kReversedBits[16] = {
+ 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
+ 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
+};
+
+static uint32_t ReverseBits(int num_bits, uint32_t bits) {
+ uint32_t retval = 0;
+ int i = 0;
+ while (i < num_bits) {
+ i += 4;
+ retval |= kReversedBits[bits & 0xf] << (MAX_ALLOWED_CODE_LENGTH + 1 - i);
+ bits >>= 4;
+ }
+ retval >>= (MAX_ALLOWED_CODE_LENGTH + 1 - num_bits);
+ return retval;
+}
+
+// Get the actual bit values for a tree of bit depths.
+static void ConvertBitDepthsToSymbols(HuffmanTreeCode* const tree) {
+ // 0 bit-depth means that the symbol does not exist.
+ int i;
+ int len;
+ uint32_t next_code[MAX_ALLOWED_CODE_LENGTH + 1];
+ int depth_count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 };
+
+ assert(tree != NULL);
+ len = tree->num_symbols;
+ for (i = 0; i < len; ++i) {
+ const int code_length = tree->code_lengths[i];
+ assert(code_length <= MAX_ALLOWED_CODE_LENGTH);
+ ++depth_count[code_length];
+ }
+ depth_count[0] = 0; // ignore unused symbol
+ next_code[0] = 0;
+ {
+ uint32_t code = 0;
+ for (i = 1; i <= MAX_ALLOWED_CODE_LENGTH; ++i) {
+ code = (code + depth_count[i - 1]) << 1;
+ next_code[i] = code;
+ }
+ }
+ for (i = 0; i < len; ++i) {
+ const int code_length = tree->code_lengths[i];
+ tree->codes[i] = ReverseBits(code_length, next_code[code_length]++);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Main entry point
+
+int VP8LCreateHuffmanTree(int* const histogram, int tree_depth_limit,
+ HuffmanTreeCode* const tree) {
+ const int num_symbols = tree->num_symbols;
+ if (!OptimizeHuffmanForRle(num_symbols, histogram)) {
+ return 0;
+ }
+ if (!GenerateOptimalTree(histogram, num_symbols,
+ tree_depth_limit, tree->code_lengths)) {
+ return 0;
+ }
+ // Create the actual bit codes for the bit lengths.
+ ConvertBitDepthsToSymbols(tree);
+ return 1;
+}
diff --git a/drivers/webpold/utils/huffman_encode.h b/drivers/webpold/utils/huffman_encode.h
new file mode 100644
index 0000000000..7f4aedc102
--- /dev/null
+++ b/drivers/webpold/utils/huffman_encode.h
@@ -0,0 +1,47 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Author: Jyrki Alakuijala (jyrki@google.com)
+//
+// Entropy encoding (Huffman) for webp lossless
+
+#ifndef WEBP_UTILS_HUFFMAN_ENCODE_H_
+#define WEBP_UTILS_HUFFMAN_ENCODE_H_
+
+#include "../types.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+// Struct for holding the tree header in coded form.
+typedef struct {
+ uint8_t code; // value (0..15) or escape code (16,17,18)
+ uint8_t extra_bits; // extra bits for escape codes
+} HuffmanTreeToken;
+
+// Struct to represent the tree codes (depth and bits array).
+typedef struct {
+ int num_symbols; // Number of symbols.
+ uint8_t* code_lengths; // Code lengths of the symbols.
+ uint16_t* codes; // Symbol Codes.
+} HuffmanTreeCode;
+
+// Turn the Huffman tree into a token sequence.
+// Returns the number of tokens used.
+int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree,
+ HuffmanTreeToken* tokens, int max_tokens);
+
+// Create an optimized tree, and tokenize it.
+int VP8LCreateHuffmanTree(int* const histogram, int tree_depth_limit,
+ HuffmanTreeCode* const tree);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif // WEBP_UTILS_HUFFMAN_ENCODE_H_
diff --git a/drivers/webpold/utils/quant_levels.c b/drivers/webpold/utils/quant_levels.c
new file mode 100644
index 0000000000..f6884392aa
--- /dev/null
+++ b/drivers/webpold/utils/quant_levels.c
@@ -0,0 +1,154 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Quantize levels for specified number of quantization-levels ([2, 256]).
+// Min and max values are preserved (usual 0 and 255 for alpha plane).
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+
+#include "./quant_levels.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define NUM_SYMBOLS 256
+
+#define MAX_ITER 6 // Maximum number of convergence steps.
+#define ERROR_THRESHOLD 1e-4 // MSE stopping criterion.
+
+// -----------------------------------------------------------------------------
+// Quantize levels.
+
+int QuantizeLevels(uint8_t* const data, int width, int height,
+ int num_levels, uint64_t* const sse) {
+ int freq[NUM_SYMBOLS] = { 0 };
+ int q_level[NUM_SYMBOLS] = { 0 };
+ double inv_q_level[NUM_SYMBOLS] = { 0 };
+ int min_s = 255, max_s = 0;
+ const size_t data_size = height * width;
+ int i, num_levels_in, iter;
+ double last_err = 1.e38, err = 0.;
+ const double err_threshold = ERROR_THRESHOLD * data_size;
+
+ if (data == NULL) {
+ return 0;
+ }
+
+ if (width <= 0 || height <= 0) {
+ return 0;
+ }
+
+ if (num_levels < 2 || num_levels > 256) {
+ return 0;
+ }
+
+ {
+ size_t n;
+ num_levels_in = 0;
+ for (n = 0; n < data_size; ++n) {
+ num_levels_in += (freq[data[n]] == 0);
+ if (min_s > data[n]) min_s = data[n];
+ if (max_s < data[n]) max_s = data[n];
+ ++freq[data[n]];
+ }
+ }
+
+ if (num_levels_in <= num_levels) goto End; // nothing to do!
+
+ // Start with uniformly spread centroids.
+ for (i = 0; i < num_levels; ++i) {
+ inv_q_level[i] = min_s + (double)(max_s - min_s) * i / (num_levels - 1);
+ }
+
+ // Fixed values. Won't be changed.
+ q_level[min_s] = 0;
+ q_level[max_s] = num_levels - 1;
+ assert(inv_q_level[0] == min_s);
+ assert(inv_q_level[num_levels - 1] == max_s);
+
+ // k-Means iterations.
+ for (iter = 0; iter < MAX_ITER; ++iter) {
+ double q_sum[NUM_SYMBOLS] = { 0 };
+ double q_count[NUM_SYMBOLS] = { 0 };
+ int s, slot = 0;
+
+ // Assign classes to representatives.
+ for (s = min_s; s <= max_s; ++s) {
+ // Keep track of the nearest neighbour 'slot'
+ while (slot < num_levels - 1 &&
+ 2 * s > inv_q_level[slot] + inv_q_level[slot + 1]) {
+ ++slot;
+ }
+ if (freq[s] > 0) {
+ q_sum[slot] += s * freq[s];
+ q_count[slot] += freq[s];
+ }
+ q_level[s] = slot;
+ }
+
+ // Assign new representatives to classes.
+ if (num_levels > 2) {
+ for (slot = 1; slot < num_levels - 1; ++slot) {
+ const double count = q_count[slot];
+ if (count > 0.) {
+ inv_q_level[slot] = q_sum[slot] / count;
+ }
+ }
+ }
+
+ // Compute convergence error.
+ err = 0.;
+ for (s = min_s; s <= max_s; ++s) {
+ const double error = s - inv_q_level[q_level[s]];
+ err += freq[s] * error * error;
+ }
+
+ // Check for convergence: we stop as soon as the error is no
+ // longer improving.
+ if (last_err - err < err_threshold) break;
+ last_err = err;
+ }
+
+ // Remap the alpha plane to quantized values.
+ {
+ // double->int rounding operation can be costly, so we do it
+ // once for all before remapping. We also perform the data[] -> slot
+ // mapping, while at it (avoid one indirection in the final loop).
+ uint8_t map[NUM_SYMBOLS];
+ int s;
+ size_t n;
+ for (s = min_s; s <= max_s; ++s) {
+ const int slot = q_level[s];
+ map[s] = (uint8_t)(inv_q_level[slot] + .5);
+ }
+ // Final pass.
+ for (n = 0; n < data_size; ++n) {
+ data[n] = map[data[n]];
+ }
+ }
+ End:
+ // Store sum of squared error if needed.
+ if (sse != NULL) *sse = (uint64_t)err;
+
+ return 1;
+}
+
+int DequantizeLevels(uint8_t* const data, int width, int height) {
+ if (data == NULL || width <= 0 || height <= 0) return 0;
+ // TODO(skal): implement gradient smoothing.
+ (void)data;
+ (void)width;
+ (void)height;
+ return 1;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/utils/quant_levels.h b/drivers/webpold/utils/quant_levels.h
new file mode 100644
index 0000000000..4f165fd230
--- /dev/null
+++ b/drivers/webpold/utils/quant_levels.h
@@ -0,0 +1,39 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Alpha plane quantization utility
+//
+// Author: Vikas Arora (vikasa@google.com)
+
+#ifndef WEBP_UTILS_QUANT_LEVELS_H_
+#define WEBP_UTILS_QUANT_LEVELS_H_
+
+#include <stdlib.h>
+
+#include "../types.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+// Replace the input 'data' of size 'width'x'height' with 'num-levels'
+// quantized values. If not NULL, 'sse' will contain the sum of squared error.
+// Valid range for 'num_levels' is [2, 256].
+// Returns false in case of error (data is NULL, or parameters are invalid).
+int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels,
+ uint64_t* const sse);
+
+// Apply post-processing to input 'data' of size 'width'x'height' assuming
+// that the source was quantized to a reduced number of levels.
+// Returns false in case of error (data is NULL, invalid parameters, ...).
+int DequantizeLevels(uint8_t* const data, int width, int height);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_UTILS_QUANT_LEVELS_H_ */
diff --git a/drivers/webpold/utils/rescaler.c b/drivers/webpold/utils/rescaler.c
new file mode 100644
index 0000000000..9825dcbc5f
--- /dev/null
+++ b/drivers/webpold/utils/rescaler.c
@@ -0,0 +1,152 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Rescaling functions
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <stdlib.h>
+#include "./rescaler.h"
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define RFIX 30
+#define MULT_FIX(x,y) (((int64_t)(x) * (y) + (1 << (RFIX - 1))) >> RFIX)
+
+void WebPRescalerInit(WebPRescaler* const wrk, int src_width, int src_height,
+ uint8_t* const dst, int dst_width, int dst_height,
+ int dst_stride, int num_channels, int x_add, int x_sub,
+ int y_add, int y_sub, int32_t* const work) {
+ wrk->x_expand = (src_width < dst_width);
+ wrk->src_width = src_width;
+ wrk->src_height = src_height;
+ wrk->dst_width = dst_width;
+ wrk->dst_height = dst_height;
+ wrk->dst = dst;
+ wrk->dst_stride = dst_stride;
+ wrk->num_channels = num_channels;
+ // for 'x_expand', we use bilinear interpolation
+ wrk->x_add = wrk->x_expand ? (x_sub - 1) : x_add - x_sub;
+ wrk->x_sub = wrk->x_expand ? (x_add - 1) : x_sub;
+ wrk->y_accum = y_add;
+ wrk->y_add = y_add;
+ wrk->y_sub = y_sub;
+ wrk->fx_scale = (1 << RFIX) / x_sub;
+ wrk->fy_scale = (1 << RFIX) / y_sub;
+ wrk->fxy_scale = wrk->x_expand ?
+ ((int64_t)dst_height << RFIX) / (x_sub * src_height) :
+ ((int64_t)dst_height << RFIX) / (x_add * src_height);
+ wrk->irow = work;
+ wrk->frow = work + num_channels * dst_width;
+}
+
+void WebPRescalerImportRow(WebPRescaler* const wrk,
+ const uint8_t* const src, int channel) {
+ const int x_stride = wrk->num_channels;
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+ int x_in = channel;
+ int x_out;
+ int accum = 0;
+ if (!wrk->x_expand) {
+ int sum = 0;
+ for (x_out = channel; x_out < x_out_max; x_out += x_stride) {
+ accum += wrk->x_add;
+ for (; accum > 0; accum -= wrk->x_sub) {
+ sum += src[x_in];
+ x_in += x_stride;
+ }
+ { // Emit next horizontal pixel.
+ const int32_t base = src[x_in];
+ const int32_t frac = base * (-accum);
+ x_in += x_stride;
+ wrk->frow[x_out] = (sum + base) * wrk->x_sub - frac;
+ // fresh fractional start for next pixel
+ sum = (int)MULT_FIX(frac, wrk->fx_scale);
+ }
+ }
+ } else { // simple bilinear interpolation
+ int left = src[channel], right = src[channel];
+ for (x_out = channel; x_out < x_out_max; x_out += x_stride) {
+ if (accum < 0) {
+ left = right;
+ x_in += x_stride;
+ right = src[x_in];
+ accum += wrk->x_add;
+ }
+ wrk->frow[x_out] = right * wrk->x_add + (left - right) * accum;
+ accum -= wrk->x_sub;
+ }
+ }
+ // Accumulate the new row's contribution
+ for (x_out = channel; x_out < x_out_max; x_out += x_stride) {
+ wrk->irow[x_out] += wrk->frow[x_out];
+ }
+}
+
+uint8_t* WebPRescalerExportRow(WebPRescaler* const wrk) {
+ if (wrk->y_accum <= 0) {
+ int x_out;
+ uint8_t* const dst = wrk->dst;
+ int32_t* const irow = wrk->irow;
+ const int32_t* const frow = wrk->frow;
+ const int yscale = wrk->fy_scale * (-wrk->y_accum);
+ const int x_out_max = wrk->dst_width * wrk->num_channels;
+
+ for (x_out = 0; x_out < x_out_max; ++x_out) {
+ const int frac = (int)MULT_FIX(frow[x_out], yscale);
+ const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
+ dst[x_out] = (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255;
+ irow[x_out] = frac; // new fractional start
+ }
+ wrk->y_accum += wrk->y_add;
+ wrk->dst += wrk->dst_stride;
+ return dst;
+ } else {
+ return NULL;
+ }
+}
+
+#undef MULT_FIX
+#undef RFIX
+
+//------------------------------------------------------------------------------
+// all-in-one calls
+
+int WebPRescalerImport(WebPRescaler* const wrk, int num_lines,
+ const uint8_t* src, int src_stride) {
+ int total_imported = 0;
+ while (total_imported < num_lines && wrk->y_accum > 0) {
+ int channel;
+ for (channel = 0; channel < wrk->num_channels; ++channel) {
+ WebPRescalerImportRow(wrk, src, channel);
+ }
+ src += src_stride;
+ ++total_imported;
+ wrk->y_accum -= wrk->y_sub;
+ }
+ return total_imported;
+}
+
+int WebPRescalerExport(WebPRescaler* const rescaler) {
+ int total_exported = 0;
+ while (WebPRescalerHasPendingOutput(rescaler)) {
+ WebPRescalerExportRow(rescaler);
+ ++total_exported;
+ }
+ return total_exported;
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/utils/rescaler.h b/drivers/webpold/utils/rescaler.h
new file mode 100644
index 0000000000..9c9133d19b
--- /dev/null
+++ b/drivers/webpold/utils/rescaler.h
@@ -0,0 +1,76 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Rescaling functions
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_UTILS_RESCALER_H_
+#define WEBP_UTILS_RESCALER_H_
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include "../types.h"
+
+// Structure used for on-the-fly rescaling
+typedef struct {
+ int x_expand; // true if we're expanding in the x direction
+ int num_channels; // bytes to jump between pixels
+ int fy_scale, fx_scale; // fixed-point scaling factor
+ int64_t fxy_scale; // ''
+ // we need hpel-precise add/sub increments, for the downsampled U/V planes.
+ int y_accum; // vertical accumulator
+ int y_add, y_sub; // vertical increments (add ~= src, sub ~= dst)
+ int x_add, x_sub; // horizontal increments (add ~= src, sub ~= dst)
+ int src_width, src_height; // source dimensions
+ int dst_width, dst_height; // destination dimensions
+ uint8_t* dst;
+ int dst_stride;
+ int32_t* irow, *frow; // work buffer
+} WebPRescaler;
+
+// Initialize a rescaler given scratch area 'work' and dimensions of src & dst.
+void WebPRescalerInit(WebPRescaler* const wrk, int src_width, int src_height,
+ uint8_t* const dst,
+ int dst_width, int dst_height, int dst_stride,
+ int num_channels,
+ int x_add, int x_sub,
+ int y_add, int y_sub,
+ int32_t* const work);
+
+// Import a row of data and save its contribution in the rescaler.
+// 'channel' denotes the channel number to be imported.
+void WebPRescalerImportRow(WebPRescaler* const rescaler,
+ const uint8_t* const src, int channel);
+
+// Import multiple rows over all channels, until at least one row is ready to
+// be exported. Returns the actual number of lines that were imported.
+int WebPRescalerImport(WebPRescaler* const rescaler, int num_rows,
+ const uint8_t* src, int src_stride);
+
+// Return true if there is pending output rows ready.
+static WEBP_INLINE
+int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) {
+ return (rescaler->y_accum <= 0);
+}
+
+// Export one row from rescaler. Returns the pointer where output was written,
+// or NULL if no row was pending.
+uint8_t* WebPRescalerExportRow(WebPRescaler* const wrk);
+
+// Export as many rows as possible. Return the numbers of rows written.
+int WebPRescalerExport(WebPRescaler* const wrk);
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_UTILS_RESCALER_H_ */
diff --git a/drivers/webpold/utils/thread.c b/drivers/webpold/utils/thread.c
new file mode 100644
index 0000000000..ce89cf9dc7
--- /dev/null
+++ b/drivers/webpold/utils/thread.c
@@ -0,0 +1,247 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Multi-threaded worker
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <string.h> // for memset()
+#include "./thread.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#ifdef WEBP_USE_THREAD
+
+#if defined(_WIN32)
+
+//------------------------------------------------------------------------------
+// simplistic pthread emulation layer
+
+#include <process.h>
+
+// _beginthreadex requires __stdcall
+#define THREADFN unsigned int __stdcall
+#define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val)
+
+static int pthread_create(pthread_t* const thread, const void* attr,
+ unsigned int (__stdcall *start)(void*), void* arg) {
+ (void)attr;
+ *thread = (pthread_t)_beginthreadex(NULL, /* void *security */
+ 0, /* unsigned stack_size */
+ start,
+ arg,
+ 0, /* unsigned initflag */
+ NULL); /* unsigned *thrdaddr */
+ if (*thread == NULL) return 1;
+ SetThreadPriority(*thread, THREAD_PRIORITY_ABOVE_NORMAL);
+ return 0;
+}
+
+static int pthread_join(pthread_t thread, void** value_ptr) {
+ (void)value_ptr;
+ return (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0 ||
+ CloseHandle(thread) == 0);
+}
+
+// Mutex
+static int pthread_mutex_init(pthread_mutex_t* const mutex, void* mutexattr) {
+ (void)mutexattr;
+ InitializeCriticalSection(mutex);
+ return 0;
+}
+
+static int pthread_mutex_lock(pthread_mutex_t* const mutex) {
+ EnterCriticalSection(mutex);
+ return 0;
+}
+
+static int pthread_mutex_unlock(pthread_mutex_t* const mutex) {
+ LeaveCriticalSection(mutex);
+ return 0;
+}
+
+static int pthread_mutex_destroy(pthread_mutex_t* const mutex) {
+ DeleteCriticalSection(mutex);
+ return 0;
+}
+
+// Condition
+static int pthread_cond_destroy(pthread_cond_t* const condition) {
+ int ok = 1;
+ ok &= (CloseHandle(condition->waiting_sem_) != 0);
+ ok &= (CloseHandle(condition->received_sem_) != 0);
+ ok &= (CloseHandle(condition->signal_event_) != 0);
+ return !ok;
+}
+
+static int pthread_cond_init(pthread_cond_t* const condition, void* cond_attr) {
+ (void)cond_attr;
+ condition->waiting_sem_ = CreateSemaphore(NULL, 0, 1, NULL);
+ condition->received_sem_ = CreateSemaphore(NULL, 0, 1, NULL);
+ condition->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (condition->waiting_sem_ == NULL ||
+ condition->received_sem_ == NULL ||
+ condition->signal_event_ == NULL) {
+ pthread_cond_destroy(condition);
+ return 1;
+ }
+ return 0;
+}
+
+static int pthread_cond_signal(pthread_cond_t* const condition) {
+ int ok = 1;
+ if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) {
+ // a thread is waiting in pthread_cond_wait: allow it to be notified
+ ok = SetEvent(condition->signal_event_);
+ // wait until the event is consumed so the signaler cannot consume
+ // the event via its own pthread_cond_wait.
+ ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) !=
+ WAIT_OBJECT_0);
+ }
+ return !ok;
+}
+
+static int pthread_cond_wait(pthread_cond_t* const condition,
+ pthread_mutex_t* const mutex) {
+ int ok;
+ // note that there is a consumer available so the signal isn't dropped in
+ // pthread_cond_signal
+ if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL))
+ return 1;
+ // now unlock the mutex so pthread_cond_signal may be issued
+ pthread_mutex_unlock(mutex);
+ ok = (WaitForSingleObject(condition->signal_event_, INFINITE) ==
+ WAIT_OBJECT_0);
+ ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL);
+ pthread_mutex_lock(mutex);
+ return !ok;
+}
+
+#else // _WIN32
+# define THREADFN void*
+# define THREAD_RETURN(val) val
+#endif
+
+//------------------------------------------------------------------------------
+
+static THREADFN WebPWorkerThreadLoop(void *ptr) { // thread loop
+ WebPWorker* const worker = (WebPWorker*)ptr;
+ int done = 0;
+ while (!done) {
+ pthread_mutex_lock(&worker->mutex_);
+ while (worker->status_ == OK) { // wait in idling mode
+ pthread_cond_wait(&worker->condition_, &worker->mutex_);
+ }
+ if (worker->status_ == WORK) {
+ if (worker->hook) {
+ worker->had_error |= !worker->hook(worker->data1, worker->data2);
+ }
+ worker->status_ = OK;
+ } else if (worker->status_ == NOT_OK) { // finish the worker
+ done = 1;
+ }
+ // signal to the main thread that we're done (for Sync())
+ pthread_cond_signal(&worker->condition_);
+ pthread_mutex_unlock(&worker->mutex_);
+ }
+ return THREAD_RETURN(NULL); // Thread is finished
+}
+
+// main thread state control
+static void WebPWorkerChangeState(WebPWorker* const worker,
+ WebPWorkerStatus new_status) {
+ // no-op when attempting to change state on a thread that didn't come up
+ if (worker->status_ < OK) return;
+
+ pthread_mutex_lock(&worker->mutex_);
+ // wait for the worker to finish
+ while (worker->status_ != OK) {
+ pthread_cond_wait(&worker->condition_, &worker->mutex_);
+ }
+ // assign new status and release the working thread if needed
+ if (new_status != OK) {
+ worker->status_ = new_status;
+ pthread_cond_signal(&worker->condition_);
+ }
+ pthread_mutex_unlock(&worker->mutex_);
+}
+
+#endif
+
+//------------------------------------------------------------------------------
+
+void WebPWorkerInit(WebPWorker* const worker) {
+ memset(worker, 0, sizeof(*worker));
+ worker->status_ = NOT_OK;
+}
+
+int WebPWorkerSync(WebPWorker* const worker) {
+#ifdef WEBP_USE_THREAD
+ WebPWorkerChangeState(worker, OK);
+#endif
+ assert(worker->status_ <= OK);
+ return !worker->had_error;
+}
+
+int WebPWorkerReset(WebPWorker* const worker) {
+ int ok = 1;
+ worker->had_error = 0;
+ if (worker->status_ < OK) {
+#ifdef WEBP_USE_THREAD
+ if (pthread_mutex_init(&worker->mutex_, NULL) ||
+ pthread_cond_init(&worker->condition_, NULL)) {
+ return 0;
+ }
+ pthread_mutex_lock(&worker->mutex_);
+ ok = !pthread_create(&worker->thread_, NULL, WebPWorkerThreadLoop, worker);
+ if (ok) worker->status_ = OK;
+ pthread_mutex_unlock(&worker->mutex_);
+#else
+ worker->status_ = OK;
+#endif
+ } else if (worker->status_ > OK) {
+ ok = WebPWorkerSync(worker);
+ }
+ assert(!ok || (worker->status_ == OK));
+ return ok;
+}
+
+void WebPWorkerLaunch(WebPWorker* const worker) {
+#ifdef WEBP_USE_THREAD
+ WebPWorkerChangeState(worker, WORK);
+#else
+ if (worker->hook)
+ worker->had_error |= !worker->hook(worker->data1, worker->data2);
+#endif
+}
+
+void WebPWorkerEnd(WebPWorker* const worker) {
+ if (worker->status_ >= OK) {
+#ifdef WEBP_USE_THREAD
+ WebPWorkerChangeState(worker, NOT_OK);
+ pthread_join(worker->thread_, NULL);
+ pthread_mutex_destroy(&worker->mutex_);
+ pthread_cond_destroy(&worker->condition_);
+#else
+ worker->status_ = NOT_OK;
+#endif
+ }
+ assert(worker->status_ == NOT_OK);
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/utils/thread.h b/drivers/webpold/utils/thread.h
new file mode 100644
index 0000000000..3191890b76
--- /dev/null
+++ b/drivers/webpold/utils/thread.h
@@ -0,0 +1,86 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Multi-threaded worker
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_UTILS_THREAD_H_
+#define WEBP_UTILS_THREAD_H_
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#if WEBP_USE_THREAD
+
+#if defined(_WIN32)
+
+#include <windows.h>
+typedef HANDLE pthread_t;
+typedef CRITICAL_SECTION pthread_mutex_t;
+typedef struct {
+ HANDLE waiting_sem_;
+ HANDLE received_sem_;
+ HANDLE signal_event_;
+} pthread_cond_t;
+
+#else
+
+#include <pthread.h>
+
+#endif /* _WIN32 */
+#endif /* WEBP_USE_THREAD */
+
+// State of the worker thread object
+typedef enum {
+ NOT_OK = 0, // object is unusable
+ OK, // ready to work
+ WORK // busy finishing the current task
+} WebPWorkerStatus;
+
+// Function to be called by the worker thread. Takes two opaque pointers as
+// arguments (data1 and data2), and should return false in case of error.
+typedef int (*WebPWorkerHook)(void*, void*);
+
+// Synchronize object used to launch job in the worker thread
+typedef struct {
+#if WEBP_USE_THREAD
+ pthread_mutex_t mutex_;
+ pthread_cond_t condition_;
+ pthread_t thread_;
+#endif
+ WebPWorkerStatus status_;
+ WebPWorkerHook hook; // hook to call
+ void* data1; // first argument passed to 'hook'
+ void* data2; // second argument passed to 'hook'
+ int had_error; // return value of the last call to 'hook'
+} WebPWorker;
+
+// Must be called first, before any other method.
+void WebPWorkerInit(WebPWorker* const worker);
+// Must be called initialize the object and spawn the thread. Re-entrant.
+// Will potentially launch the thread. Returns false in case of error.
+int WebPWorkerReset(WebPWorker* const worker);
+// Make sure the previous work is finished. Returns true if worker->had_error
+// was not set and not error condition was triggered by the working thread.
+int WebPWorkerSync(WebPWorker* const worker);
+// Trigger the thread to call hook() with data1 and data2 argument. These
+// hook/data1/data2 can be changed at any time before calling this function,
+// but not be changed afterward until the next call to WebPWorkerSync().
+void WebPWorkerLaunch(WebPWorker* const worker);
+// Kill the thread and terminate the object. To use the object again, one
+// must call WebPWorkerReset() again.
+void WebPWorkerEnd(WebPWorker* const worker);
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_UTILS_THREAD_H_ */
diff --git a/drivers/webpold/utils/utils.c b/drivers/webpold/utils/utils.c
new file mode 100644
index 0000000000..673b7e284c
--- /dev/null
+++ b/drivers/webpold/utils/utils.c
@@ -0,0 +1,44 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Misc. common utility functions
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <stdlib.h>
+#include "./utils.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Checked memory allocation
+
+static int CheckSizeArguments(uint64_t nmemb, size_t size) {
+ const uint64_t total_size = nmemb * size;
+ if (nmemb == 0) return 1;
+ if ((uint64_t)size > WEBP_MAX_ALLOCABLE_MEMORY / nmemb) return 0;
+ if (total_size != (size_t)total_size) return 0;
+ return 1;
+}
+
+void* WebPSafeMalloc(uint64_t nmemb, size_t size) {
+ if (!CheckSizeArguments(nmemb, size)) return NULL;
+ return malloc((size_t)(nmemb * size));
+}
+
+void* WebPSafeCalloc(uint64_t nmemb, size_t size) {
+ if (!CheckSizeArguments(nmemb, size)) return NULL;
+ return calloc((size_t)nmemb, size);
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
diff --git a/drivers/webpold/utils/utils.h b/drivers/webpold/utils/utils.h
new file mode 100644
index 0000000000..316ac90612
--- /dev/null
+++ b/drivers/webpold/utils/utils.h
@@ -0,0 +1,44 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+// -----------------------------------------------------------------------------
+//
+// Misc. common utility functions
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_UTILS_UTILS_H_
+#define WEBP_UTILS_UTILS_H_
+
+#include "../types.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Memory allocation
+
+// This is the maximum memory amount that libwebp will ever try to allocate.
+#define WEBP_MAX_ALLOCABLE_MEMORY (1ULL << 40)
+
+// size-checking safe malloc/calloc: verify that the requested size is not too
+// large, or return NULL. You don't need to call these for constructs like
+// malloc(sizeof(foo)), but only if there's picture-dependent size involved
+// somewhere (like: malloc(num_pixels * sizeof(*something))). That's why this
+// safe malloc() borrows the signature from calloc(), pointing at the dangerous
+// underlying multiply involved.
+void* WebPSafeMalloc(uint64_t nmemb, size_t size);
+// Note that WebPSafeCalloc() expects the second argument type to be 'size_t'
+// in order to favor the "calloc(num_foo, sizeof(foo))" pattern.
+void* WebPSafeCalloc(uint64_t nmemb, size_t size);
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif
+
+#endif /* WEBP_UTILS_UTILS_H_ */
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 7c81e8e051..0a413979fc 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h
index 384bc8327d..6861291fd9 100644
--- a/drivers/windows/dir_access_windows.h
+++ b/drivers/windows/dir_access_windows.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index 90903f2cbd..66181a6f44 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -72,6 +72,8 @@ Error FileAccessWindows::_open(const String& p_filename, int p_mode_flags) {
mode_string=L"wb";
else if (p_mode_flags==READ_WRITE)
mode_string=L"rb+";
+ else if (p_mode_flags==WRITE_READ)
+ mode_string=L"wb+";
else
return ERR_INVALID_PARAMETER;
diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h
index a2598bfeec..b02b6f66a7 100644
--- a/drivers/windows/file_access_windows.h
+++ b/drivers/windows/file_access_windows.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/windows/mutex_windows.cpp b/drivers/windows/mutex_windows.cpp
index 09f8590510..f63415d0f8 100644
--- a/drivers/windows/mutex_windows.cpp
+++ b/drivers/windows/mutex_windows.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/windows/mutex_windows.h b/drivers/windows/mutex_windows.h
index 9447f17a1c..4cff027906 100644
--- a/drivers/windows/mutex_windows.h
+++ b/drivers/windows/mutex_windows.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/windows/semaphore_windows.cpp b/drivers/windows/semaphore_windows.cpp
index 50cdf7cce5..74094f482a 100644
--- a/drivers/windows/semaphore_windows.cpp
+++ b/drivers/windows/semaphore_windows.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/windows/semaphore_windows.h b/drivers/windows/semaphore_windows.h
index 43f6c0b560..e8836e49dc 100644
--- a/drivers/windows/semaphore_windows.h
+++ b/drivers/windows/semaphore_windows.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/windows/shell_windows.cpp b/drivers/windows/shell_windows.cpp
index 670f4e483d..c69d371a65 100644
--- a/drivers/windows/shell_windows.cpp
+++ b/drivers/windows/shell_windows.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/windows/shell_windows.h b/drivers/windows/shell_windows.h
index 98eae81175..6f97964a09 100644
--- a/drivers/windows/shell_windows.h
+++ b/drivers/windows/shell_windows.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/windows/thread_windows.cpp b/drivers/windows/thread_windows.cpp
index 6a9e97ba01..d5e489aab4 100644
--- a/drivers/windows/thread_windows.cpp
+++ b/drivers/windows/thread_windows.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/drivers/windows/thread_windows.h b/drivers/windows/thread_windows.h
index 3c8f92ce57..b051bfe370 100644
--- a/drivers/windows/thread_windows.h
+++ b/drivers/windows/thread_windows.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/logo_small.png b/logo_small.png
deleted file mode 100644
index 61e4cc95d6..0000000000
--- a/logo_small.png
+++ /dev/null
Binary files differ
diff --git a/main/input_default.cpp b/main/input_default.cpp
index 878d21c302..4e5d753ea9 100644
--- a/main/input_default.cpp
+++ b/main/input_default.cpp
@@ -112,8 +112,8 @@ float InputDefault::get_joy_axis(int p_device,int p_axis) {
_THREAD_SAFE_METHOD_
int c = _combine_device(p_axis,p_device);
- if (joy_axis.has(c)) {
- return joy_axis[c];
+ if (_joy_axis.has(c)) {
+ return _joy_axis[c];
} else {
return 0;
}
@@ -122,13 +122,51 @@ float InputDefault::get_joy_axis(int p_device,int p_axis) {
String InputDefault::get_joy_name(int p_idx) {
_THREAD_SAFE_METHOD_
- return joy_names[p_idx];
+ return joy_names[p_idx].name;
};
-void InputDefault::joy_connection_changed(int p_idx, bool p_connected, String p_name) {
+static String _hex_str(uint8_t p_byte) {
+
+ static const char* dict = "0123456789abcdef";
+ char ret[3];
+ ret[2] = 0;
+
+ ret[0] = dict[p_byte>>4];
+ ret[1] = dict[p_byte & 0xf];
+
+ return ret;
+};
+
+void InputDefault::joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid) {
_THREAD_SAFE_METHOD_
- joy_names[p_idx] = p_connected ? p_name : "";
+ Joystick js;
+ js.name = p_connected ? p_name : "";
+ js.uid = p_connected ? p_guid : "";
+ js.mapping = -1;
+ js.hat_current = 0;
+
+ if (p_connected) {
+
+ String uidname = p_guid;
+ if (p_guid == "") {
+ int uidlen = MIN(p_name.length(), 16);
+ for (int i=0; i<uidlen; i++) {
+ uidname = uidname + _hex_str(p_name[i]);
+ };
+ };
+ js.uid = uidname;
+ //printf("looking for mappings for guid %ls\n", uidname.c_str());
+ int mapping = -1;
+ for (int i=0; i < map_db.size(); i++) {
+ if (js.uid == map_db[i].uid) {
+ mapping = i;
+ //printf("found mapping\n");
+ };
+ };
+ js.mapping = mapping;
+ };
+ joy_names[p_idx] = js;
emit_signal("joy_connection_changed", p_idx, p_connected);
};
@@ -224,7 +262,7 @@ void InputDefault::set_joy_axis(int p_device,int p_axis,float p_value) {
_THREAD_SAFE_METHOD_
int c = _combine_device(p_axis,p_device);
- joy_axis[c]=p_value;
+ _joy_axis[c]=p_value;
}
void InputDefault::set_accelerometer(const Vector3& p_accel) {
@@ -335,9 +373,502 @@ void InputDefault::set_mouse_in_window(bool p_in_window) {
}
}
+// from github.com/gabomdq/SDL_GameControllerDB
+static const char *s_ControllerMappings [] =
+{
+ #ifdef WINDOWS_ENABLED
+ "8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
+ "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+ "ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+ "6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+ "6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+ "88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,",
+ "4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,",
+ "25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,",
+ "4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+ "6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13,",
+ "4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows,",
+ "00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,",
+ "00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,",
+ "28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,",
+ "ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,",
+ "8f0e0300000000000000504944564944,Piranha xtreme,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
+ "8f0e0d31000000000000504944564944,Multilaser JS071 USB,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "10080300000000000000504944564944,PS2 USB,platform:Windows,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5,",
+ "79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows,",
+ "4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,platform:Windows,",
+ "d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,",
+ "a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows,",
+ "8f0e0300000000000000504944564944,Trust GTX 28,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,",
+ "4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,platform:Windows,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
+ "83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Windows,",
+ "c911f055000000000000504944564944,GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
+ "79000600000000000000504944564944,Generic Speedlink,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,",
+ "__XINPUT_DEVICE__,XInput Gamepad,a:b12,b:b13,x:b14,y:b15,start:b4,back:b5,leftstick:b6,rightstick:b7,leftshoulder:b8,rightshoulder:b9,dpup:b0,dpdown:b1,dpleft:b2,dpright:b3,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,",
+
+ #endif
+ #ifdef OSX_ENABLED
+ "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
+ "6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
+ "6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+ "6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
+ "6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* This includes F710 in DInput mode and the "Logitech Cordless RumblePad 2", at the very least. */
+ "4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
+ "4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
+ "5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
+ #endif
+ #if X11_ENABLED
+ "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
+ "03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,",
+ "030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+ "030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+ "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
+ "030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,",
+ "03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,",
+ "03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,",
+ "030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,",
+ "030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,",
+ "030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
+ "030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
+ "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
+ "030000006d04000016c2000010010000,Logitech Logitech Dual Action,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,",
+ "030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,",
+ "030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,",
+ "030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,",
+ "0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
+ "0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
+ "030000006f0e00001f01000000010000,Generic X-Box pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "03000000280400000140000000010000,Gravis GamePad Pro USB ,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,",
+ "030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
+ "03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,",
+ "030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
+ "030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,",
+ "03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
+ "050000004c050000c405000000010000,PS4 Controller (Bluetooth),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
+ "060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,",
+ "03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,",
+ "05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,",
+ "05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,",
+ "030000008916000001fd000024010000,Razer Onza Classic Edition,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "030000005e040000d102000001010000,Microsoft X-Box One pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "03000000790000001100000010010000,RetroLink Saturn Classic Controller,platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
+ "050000007e0500003003000001000000,Nintendo Wii U Pro Controller,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16,",
+ "030000005e0400008e02000004010000,Microsoft X-Box 360 pad,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
+ "030000000d0f00002200000011010000,HORI CO.,LTD. REAL ARCADE Pro.V3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,",
+ "030000000d0f00001000000011010000,HORI CO.,LTD. FIGHTING STICK 3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7",
+ "03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux,",
+ #endif
+
+ #if defined(__ANDROID__)
+ "4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
+ #endif
+
+ #ifdef JAVASCRIPT_ENABLED
+ "Default HTML5 Gamepad, Default Mapping,leftx:a0,lefty:a1,dpdown:b13,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:b14,lefttrigger:a6,x:b2,dpup:b12,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:b15,righttrigger:a7,b:b1,",
+ "303534632d303236382d536f6e792050,PS3 Controller USB/Linux,leftx:a0,lefty:a1,dpdown:b6,rightstick:b2,rightshoulder:b11,rightx:a2,start:b3,righty:a3,dpleft:b7,lefttrigger:b8,x:b15,dpup:b4,back:b0,leftstick:b1,leftshoulder:b10,y:b12,a:b14,dpright:b5,righttrigger:b9,b:b13,",
+ "303534632d303563342d536f6e792043,PS4 Controller USB/Linux,leftx:a0,lefty:a1,dpdown:a7,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a5,dpleft:a6,lefttrigger:a3,x:b0,dpup:a7,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b1,dpright:a6,righttrigger:a4,b:b2,",
+ "303534632d303563342d576972656c65,PS4 Controller USB/Win,leftx:a0,lefty:a1,dpdown:b15,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a5,lefttrigger:a3,x:b0,dpup:b14,dpleft:b16,dpright:b17,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b1,righttrigger:b7,b:b2,",
+ "303435652d303238652d4d6963726f73,Wired X360 Controller,leftx:a0,lefty:a1,dpdown:a7,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:a6,lefttrigger:a2,x:b2,dpup:a7,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:a6,righttrigger:a5,b:b1,",
+ "303435652d303731392d58626f782033,Wireless X360 Controller,leftx:a0,lefty:a1,dpdown:b14,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:b11,lefttrigger:a2,x:b2,dpup:b13,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:b12,righttrigger:a5,b:b1,",
+ "c2a94d6963726f736f66742058626f78,Wireless X360 Controller,leftx:a0,lefty:a1,dpdown:b14,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:b11,lefttrigger:a2,x:b2,dpup:b13,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:b12,righttrigger:a5,b:b1,",
+ #endif
+ NULL
+};
+
InputDefault::InputDefault() {
mouse_button_mask=0;
emulate_touch=false;
main_loop=NULL;
+
+ hat_map_default[HAT_UP].type = TYPE_BUTTON;
+ hat_map_default[HAT_UP].index = JOY_DPAD_UP;
+ hat_map_default[HAT_UP].value = 0;
+
+ hat_map_default[HAT_RIGHT].type = TYPE_BUTTON;
+ hat_map_default[HAT_RIGHT].index = JOY_DPAD_RIGHT;
+ hat_map_default[HAT_RIGHT].value = 0;
+
+ hat_map_default[HAT_DOWN].type = TYPE_BUTTON;
+ hat_map_default[HAT_DOWN].index = JOY_DPAD_DOWN;
+ hat_map_default[HAT_DOWN].value = 0;
+
+ hat_map_default[HAT_LEFT].type = TYPE_BUTTON;
+ hat_map_default[HAT_LEFT].index = JOY_DPAD_LEFT;
+ hat_map_default[HAT_LEFT].value = 0;
+
+ String env_mapping = OS::get_singleton()->get_environment("SDL_GAMECONTROLLERCONFIG");
+ if (env_mapping != "") {
+
+ Vector<String> entries = env_mapping.split("\n");
+ for (int i=0; i < entries.size(); i++) {
+ if (entries[i] == "")
+ continue;
+ parse_mapping(entries[i]);
+ };
+ };
+
+ int i = 0;
+ while (s_ControllerMappings[i]) {
+
+ parse_mapping(s_ControllerMappings[i++]);
+ };
+}
+
+
+uint32_t InputDefault::joy_button(uint32_t p_last_id, int p_device, int p_button, bool p_pressed) {
+
+ _THREAD_SAFE_METHOD_;
+ Joystick& joy = joy_names[p_device];
+ //printf("got button %i, mapping is %i\n", p_button, joy.mapping);
+ if (joy.last_buttons[p_button] == p_pressed) {
+ return p_last_id;
+ //printf("same button value\n");
+ }
+ joy.last_buttons[p_button] = p_pressed;
+ if (joy.mapping == -1) {
+ return _button_event(p_last_id, p_device, p_button, p_pressed);
+ };
+
+ Map<int,JoyEvent>::Element* el = map_db[joy.mapping].buttons.find(p_button);
+ if (!el) {
+ //don't process un-mapped events for now, it could mess things up badly for devices with additional buttons/axis
+ //return _button_event(p_last_id, p_device, p_button, p_pressed);
+ return p_last_id;
+ };
+
+ JoyEvent map = el->get();
+ if (map.type == TYPE_BUTTON) {
+ //fake additional axis event for triggers
+ if (map.index == JOY_L2 || map.index == JOY_R2) {
+ float value = p_pressed ? 1.0f : 0.0f;
+ int axis = map.index == JOY_L2 ? JOY_ANALOG_L2 : JOY_ANALOG_R2;
+ p_last_id = _axis_event(p_last_id, p_device, axis, value);
+ }
+ return _button_event(p_last_id, p_device, map.index, p_pressed);
+ };
+
+ if (map.type == TYPE_AXIS) {
+ return _axis_event(p_last_id, p_device, map.index, p_pressed ? 1.0 : 0.0);
+ };
+
+ return p_last_id; // no event?
+};
+
+uint32_t InputDefault::joy_axis(uint32_t p_last_id, int p_device, int p_axis, const JoyAxis& p_value) {
+
+ _THREAD_SAFE_METHOD_;
+
+ Joystick& joy = joy_names[p_device];
+
+ if (joy.last_axis[p_axis] == p_value.value) {
+ return p_last_id;
+ }
+
+ if (p_value.value > joy.last_axis[p_axis]) {
+
+ if (p_value.value < joy.last_axis[p_axis] + joy.filter ) {
+
+ return p_last_id;
+ }
+ }
+ else if (p_value.value > joy.last_axis[p_axis] - joy.filter) {
+
+ return p_last_id;
+ }
+
+
+ joy.last_axis[p_axis] = p_value.value;
+ float val = p_value.min == 0 ? -1.0f + 2.0f * p_value.value : p_value.value;
+
+ if (joy.mapping == -1) {
+ return _axis_event(p_last_id, p_device, p_axis, val);
+ };
+
+ Map<int,JoyEvent>::Element* el = map_db[joy.mapping].axis.find(p_axis);
+ if (!el) {
+ //return _axis_event(p_last_id, p_device, p_axis, p_value);
+ return p_last_id;
+ };
+
+
+ JoyEvent map = el->get();
+
+ if (map.type == TYPE_BUTTON) {
+ //send axis event for triggers
+ if (map.index == JOY_L2 || map.index == JOY_R2) {
+ float value = p_value.min == 0 ? p_value.value : 0.5f + p_value.value / 2.0f;
+ int axis = map.index == JOY_L2 ? JOY_ANALOG_L2 : JOY_ANALOG_R2;
+ p_last_id = _axis_event(p_last_id, p_device, axis, value);
+ }
+
+ if (map.index == JOY_DPAD_UP || map.index == JOY_DPAD_DOWN) {
+ bool pressed = p_value.value != 0.0f;
+ int button = p_value.value < 0 ? JOY_DPAD_UP : JOY_DPAD_DOWN;
+
+ if (!pressed) {
+ if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_UP, p_device))) {
+ p_last_id = _button_event(p_last_id, p_device, JOY_DPAD_UP, false);
+ }
+ if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_DOWN, p_device))) {
+ p_last_id = _button_event(p_last_id, p_device, JOY_DPAD_DOWN, false);
+ }
+ }
+ if ( pressed == joy_buttons_pressed.has(_combine_device(button, p_device))) {
+ return p_last_id;
+ }
+ return _button_event(p_last_id, p_device, button, true);
+ }
+ if (map.index == JOY_DPAD_LEFT || map.index == JOY_DPAD_RIGHT) {
+ bool pressed = p_value.value != 0.0f;
+ int button = p_value.value < 0 ? JOY_DPAD_LEFT : JOY_DPAD_RIGHT;
+
+ if (!pressed) {
+ if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_LEFT, p_device))) {
+ p_last_id = _button_event(p_last_id, p_device, JOY_DPAD_LEFT, false);
+ }
+ if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_RIGHT, p_device))) {
+ p_last_id = _button_event(p_last_id, p_device, JOY_DPAD_RIGHT, false);
+ }
+ }
+ if ( pressed == joy_buttons_pressed.has(_combine_device(button, p_device))) {
+ return p_last_id;
+ }
+ return _button_event(p_last_id, p_device, button, true);
+ }
+ float deadzone = p_value.min == 0 ? 0.5f : 0.0f;
+ bool pressed = p_value.value > deadzone ? true : false;
+ if (pressed == joy_buttons_pressed.has(_combine_device(map.index,p_device))) {
+ // button already pressed or released, this is an axis bounce value
+ return p_last_id;
+ };
+ return _button_event(p_last_id, p_device, map.index, pressed);
+ };
+
+ if (map.type == TYPE_AXIS) {
+
+ return _axis_event(p_last_id, p_device, map.index, val );
+ };
+ //printf("invalid mapping\n");
+ return p_last_id;
+};
+
+uint32_t InputDefault::joy_hat(uint32_t p_last_id, int p_device, int p_val) {
+
+ _THREAD_SAFE_METHOD_;
+ const Joystick& joy = joy_names[p_device];
+
+ JoyEvent* map;
+
+ if (joy.mapping == -1) {
+ map = hat_map_default;
+ } else {
+ map = map_db[joy.mapping].hat;
+ };
+
+ int cur_val = joy_names[p_device].hat_current;
+
+ if ( (p_val & HAT_MASK_UP) != (cur_val & HAT_MASK_UP) ) {
+ p_last_id = _button_event(p_last_id, p_device, map[HAT_UP].index, p_val & HAT_MASK_UP);
+ };
+
+ if ( (p_val & HAT_MASK_RIGHT) != (cur_val & HAT_MASK_RIGHT) ) {
+ p_last_id = _button_event(p_last_id, p_device, map[HAT_RIGHT].index, p_val & HAT_MASK_RIGHT);
+ };
+ if ( (p_val & HAT_MASK_DOWN) != (cur_val & HAT_MASK_DOWN) ) {
+ p_last_id = _button_event(p_last_id, p_device, map[HAT_DOWN].index, p_val & HAT_MASK_DOWN);
+ };
+ if ( (p_val & HAT_MASK_LEFT) != (cur_val & HAT_MASK_LEFT) ) {
+ p_last_id = _button_event(p_last_id, p_device, map[HAT_LEFT].index, p_val & HAT_MASK_LEFT);
+ };
+
+ joy_names[p_device].hat_current = p_val;
+
+ return p_last_id;
+};
+
+uint32_t InputDefault::_button_event(uint32_t p_last_id, int p_device, int p_index, bool p_pressed) {
+
+ InputEvent ievent;
+ ievent.type = InputEvent::JOYSTICK_BUTTON;
+ ievent.device = p_device;
+ ievent.ID = ++p_last_id;
+ ievent.joy_button.button_index = p_index;
+ ievent.joy_button.pressed = p_pressed;
+
+ parse_input_event(ievent);
+
+ return p_last_id;
+};
+
+uint32_t InputDefault::_axis_event(uint32_t p_last_id, int p_device, int p_axis, float p_value) {
+
+ InputEvent ievent;
+ ievent.type = InputEvent::JOYSTICK_MOTION;
+ ievent.device = p_device;
+ ievent.ID = ++p_last_id;
+ ievent.joy_motion.axis = p_axis;
+ ievent.joy_motion.axis_value = p_value;
+
+ parse_input_event( ievent );
+
+ return p_last_id;
+};
+
+InputDefault::JoyEvent InputDefault::_find_to_event(String p_to) {
+
+ // string names of the SDL buttons in the same order as input_event.h godot buttons
+ static const char* buttons[] = {"a", "b", "x", "y", "leftshoulder", "rightshoulder", "lefttrigger", "righttrigger", "leftstick", "rightstick", "back", "start", "dpup", "dpdown", "dpleft", "dpright", "guide", NULL };
+
+ static const char* axis[] = {"leftx", "lefty", "rightx", "righty", NULL };
+
+ JoyEvent ret;
+ ret.type = -1;
+
+ int i=0;
+ while (buttons[i]) {
+
+ if (p_to == buttons[i]) {
+ //printf("mapping button %s\n", buttons[i]);
+ ret.type = TYPE_BUTTON;
+ ret.index = i;
+ ret.value = 0;
+ return ret;
+ };
+ ++i;
+ };
+
+ i = 0;
+ while (axis[i]) {
+
+ if (p_to == axis[i]) {
+ ret.type = TYPE_AXIS;
+ ret.index = i;
+ ret.value = 0;
+ return ret;
+ };
+ ++i;
+ };
+
+ return ret;
+};
+
+void InputDefault::parse_mapping(String p_mapping) {
+
+ _THREAD_SAFE_METHOD_;
+ JoyDeviceMapping mapping;
+
+ Vector<String> entry = p_mapping.split(",");
+ CharString uid;
+ uid.resize(17);
+
+ mapping.uid = entry[0];
+
+ int idx = 1;
+ while (++idx < entry.size()) {
+
+ if (entry[idx] == "")
+ continue;
+
+ String from = entry[idx].get_slice(":", 1);
+ String to = entry[idx].get_slice(":", 0);
+
+ JoyEvent to_event = _find_to_event(to);
+ if (to_event.type == -1)
+ continue;
+
+ String etype = from.substr(0, 1);
+ if (etype == "a") {
+
+ int aid = from.substr(1, from.length()-1).to_int();
+ mapping.axis[aid] = to_event;
+
+ } else if (etype == "b") {
+
+ int bid = from.substr(1, from.length()-1).to_int();
+ mapping.buttons[bid] = to_event;
+
+ } else if (etype == "h") {
+
+ int hat_value = from.get_slice(".", 1).to_int();
+ switch (hat_value) {
+ case 1:
+ mapping.hat[HAT_UP] = to_event;
+ break;
+ case 2:
+ mapping.hat[HAT_RIGHT] = to_event;
+ break;
+ case 4:
+ mapping.hat[HAT_DOWN] = to_event;
+ break;
+ case 8:
+ mapping.hat[HAT_LEFT] = to_event;
+ break;
+ };
+ };
+ };
+ map_db.push_back(mapping);
+ //printf("added mapping with uuid %ls\n", mapping.uid.c_str());
+};
+
+void InputDefault::add_joy_mapping(String p_mapping, bool p_update_existing) {
+ parse_mapping(p_mapping);
+ if (p_update_existing) {
+ Vector<String> entry = p_mapping.split(",");
+ String uid = entry[0];
+ for (int i=0; i<joy_names.size(); i++) {
+ if (uid == joy_names[i].uid) {
+ joy_names[i].mapping = map_db.size() -1;
+ }
+ }
+ }
+}
+
+void InputDefault::remove_joy_mapping(String p_guid) {
+ for (int i=map_db.size()-1; i >= 0;i--) {
+ if (p_guid == map_db[i].uid) {
+ map_db.remove(i);
+ }
+ }
+ for (int i=0; i<joy_names.size(); i++) {
+ if (joy_names[i].uid == p_guid) {
+ joy_names[i].mapping = -1;
+ }
+ }
+}
+
+//Defaults to simple implementation for platforms with a fixed gamepad layout, like consoles.
+bool InputDefault::is_joy_known(int p_device) {
+
+ return OS::get_singleton()->is_joy_known(p_device);
}
+
+String InputDefault::get_joy_guid(int p_device) const {
+ return OS::get_singleton()->get_joy_guid(p_device);
+}
+
+//platforms that use the remapping system can override and call to these ones
+bool InputDefault::is_joy_mapped(int p_device) {
+ return joy_names[p_device].mapping != -1 ? true : false;
+}
+
+String InputDefault::get_joy_guid_remapped(int p_device) const {
+ return joy_names[p_device].uid;
+}
+
diff --git a/main/input_default.h b/main/input_default.h
index 2ef4f727c6..a75865e0cb 100644
--- a/main/input_default.h
+++ b/main/input_default.h
@@ -11,9 +11,8 @@ class InputDefault : public Input {
int mouse_button_mask;
Set<int> keys_pressed;
Set<int> joy_buttons_pressed;
- Map<int,float> joy_axis;
+ Map<int,float> _joy_axis;
Map<StringName,int> custom_action_press;
- Map<int, String> joy_names;
Vector3 accelerometer;
Vector2 mouse_pos;
MainLoop *main_loop;
@@ -34,12 +33,93 @@ class InputDefault : public Input {
SpeedTrack();
};
- SpeedTrack mouse_speed_track;
+ struct Joystick {
+ StringName name;
+ StringName uid;
+ bool last_buttons[JOY_BUTTON_MAX + 2]; //html5 needs support for 18 buttons to map some devices correctly
+ float last_axis[JOY_AXIS_MAX];
+ float filter;
+ int last_hat;
+ int mapping;
+ int hat_current;
+
+ Joystick() {
+
+ for (int i = 0; i < JOY_AXIS_MAX; i++) {
+
+ last_axis[i] = 0.0f;
+ }
+ for (int i = 0; i < JOY_BUTTON_MAX + 2; i++) {
+
+ last_buttons[i] = false;
+ }
+ last_hat = HAT_MASK_CENTER;
+ filter = 0.01f;
+ mapping = -1;
+ }
+ };
+
+ SpeedTrack mouse_speed_track;
+ Map<int, Joystick> joy_names;
RES custom_cursor;
+public:
+ enum HatMask {
+ HAT_MASK_CENTER = 0,
+ HAT_MASK_UP = 1,
+ HAT_MASK_RIGHT = 2,
+ HAT_MASK_DOWN = 4,
+ HAT_MASK_LEFT = 8,
+ };
+
+ enum HatDir {
+ HAT_UP,
+ HAT_RIGHT,
+ HAT_DOWN,
+ HAT_LEFT,
+ HAT_MAX,
+ };
+ struct JoyAxis {
+ int min;
+ float value;
+ };
+
+private:
+
+ enum JoyType {
+ TYPE_BUTTON,
+ TYPE_AXIS,
+ TYPE_HAT,
+ TYPE_MAX,
+ };
+
+ struct JoyEvent {
+ int type;
+ int index;
+ int value;
+ };
+
+ struct JoyDeviceMapping {
+
+ String uid;
+ Map<int,JoyEvent> buttons;
+ Map<int,JoyEvent> axis;
+ JoyEvent hat[HAT_MAX];
+ };
+
+ JoyEvent hat_map_default[HAT_MAX];
+
+ Vector<JoyDeviceMapping> map_db;
+
+ JoyEvent _find_to_event(String p_to);
+ uint32_t _button_event(uint32_t p_last_id, int p_device, int p_index, bool p_pressed);
+ uint32_t _axis_event(uint32_t p_last_id, int p_device, int p_axis, float p_value);
+ float _handle_deadzone(int p_device, int p_axis, float p_value);
public:
+
+
virtual bool is_key_pressed(int p_scancode);
virtual bool is_mouse_button_pressed(int p_button);
virtual bool is_joy_button_pressed(int p_device, int p_button);
@@ -47,7 +127,8 @@ public:
virtual float get_joy_axis(int p_device,int p_axis);
String get_joy_name(int p_idx);
- void joy_connection_changed(int p_idx, bool p_connected, String p_name);
+ void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid = "");
+ void parse_joystick_mapping(String p_mapping, bool p_update_existing);
virtual Vector3 get_accelerometer();
@@ -76,8 +157,20 @@ public:
virtual void set_custom_mouse_cursor(const RES& p_cursor,const Vector2& p_hotspot=Vector2());
virtual void set_mouse_in_window(bool p_in_window);
- InputDefault();
+ void parse_mapping(String p_mapping);
+ uint32_t joy_button(uint32_t p_last_id, int p_device, int p_button, bool p_pressed);
+ uint32_t joy_axis(uint32_t p_last_id, int p_device, int p_axis, const JoyAxis& p_value);
+ uint32_t joy_hat(uint32_t p_last_id, int p_device, int p_val);
+ virtual void add_joy_mapping(String p_mapping, bool p_update_existing=false);
+ virtual void remove_joy_mapping(String p_guid);
+ virtual bool is_joy_known(int p_device);
+ virtual String get_joy_guid(int p_device) const;
+
+ bool is_joy_mapped(int p_device);
+ String get_joy_guid_remapped(int p_device) const;
+
+ InputDefault();
};
#endif // INPUT_DEFAULT_H
diff --git a/main/main.cpp b/main/main.cpp
index a060dbd232..19fe037613 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -56,7 +56,7 @@
#ifdef TOOLS_ENABLED
#include "tools/editor/editor_node.h"
#include "tools/editor/project_manager.h"
-#include "tools/editor/console.h"
+
#include "tools/pck/pck_packer.h"
#endif
@@ -95,6 +95,7 @@ static TranslationServer *translation_server = NULL;
static OS::VideoMode video_mode;
static bool init_maximized=false;
+static bool init_windowed=false;
static bool init_fullscreen=false;
static bool init_use_custom_pos=false;
static bool debug_collisions=false;
@@ -123,7 +124,7 @@ static String unescape_cmdline(const String& p_str) {
void Main::print_help(const char* p_binary) {
- OS::get_singleton()->print(VERSION_FULL_NAME" (c) 2008-2015 Juan Linietsky, Ariel Manzur.\n");
+ OS::get_singleton()->print(VERSION_FULL_NAME" (c) 2008-2016 Juan Linietsky, Ariel Manzur.\n");
OS::get_singleton()->print("Usage: %s [options] [scene]\n",p_binary);
OS::get_singleton()->print("Options:\n");
OS::get_singleton()->print("\t-path [dir] : Path to a game, containing engine.cfg\n");
@@ -146,6 +147,7 @@ void Main::print_help(const char* p_binary) {
OS::get_singleton()->print("\t-p XxY\t : Request Window Position\n");
OS::get_singleton()->print("\t-f\t\t : Request Fullscreen\n");
OS::get_singleton()->print("\t-mx\t\t Request Maximized\n");
+ OS::get_singleton()->print("\t-w\t\t Request Windowed\n");
OS::get_singleton()->print("\t-vd DRIVER\t : Video Driver (");
for (int i=0;i<OS::get_singleton()->get_video_driver_count();i++) {
@@ -354,6 +356,9 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
} else if (I->get()=="-mx") { // video driver
init_maximized=true;
+ } else if (I->get()=="-w") { // video driver
+
+ init_windowed=true;
} else if (I->get()=="-vd") { // video driver
if (I->next()) {
@@ -702,6 +707,7 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
GLOBAL_DEF("display/test_width",0);
GLOBAL_DEF("display/test_height",0);
OS::get_singleton()->_pixel_snap=GLOBAL_DEF("display/use_2d_pixel_snap",false);
+ OS::get_singleton()->_keep_screen_on=GLOBAL_DEF("display/keep_screen_on",true);
if (rtm==-1) {
rtm=GLOBAL_DEF("render/thread_model",OS::RENDER_THREAD_SAFE);
if (rtm>=1) //hack for now
@@ -709,8 +715,12 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
}
- if (rtm>=0 && rtm<3)
+ if (rtm>=0 && rtm<3) {
+ if (editor) {
+ rtm=OS::RENDER_THREAD_SAFE;
+ }
OS::get_singleton()->_render_thread_mode=OS::RenderThreadMode(rtm);
+ }
@@ -841,11 +851,7 @@ Error Main::setup2() {
if (init_use_custom_pos) {
OS::get_singleton()->set_window_position(init_custom_pos);
}
- if (init_maximized) {
- OS::get_singleton()->set_window_maximized(true);
- } else if (init_fullscreen) {
- OS::get_singleton()->set_window_fullscreen(true);
- }
+
register_core_singletons();
@@ -859,8 +865,12 @@ Error Main::setup2() {
if (init_screen!=-1) {
OS::get_singleton()->set_current_screen(init_screen);
}
- if (init_maximized) {
+ if (init_windowed) {
+ //do none..
+ } else if (init_maximized) {
OS::get_singleton()->set_window_maximized(true);
+ } else if (init_fullscreen) {
+ OS::get_singleton()->set_window_fullscreen(true);
}
MAIN_PRINT("Main: Load Remaps");
@@ -1318,6 +1328,8 @@ bool Main::start() {
//autoload
List<PropertyInfo> props;
Globals::get_singleton()->get_property_list(&props);
+
+ //first pass, add the constants so they exist before any script is loaded
for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
String s = E->get().name;
@@ -1325,6 +1337,34 @@ bool Main::start() {
continue;
String name = s.get_slicec('/',1);
String path = Globals::get_singleton()->get(s);
+ bool global_var=false;
+ if (path.begins_with("*")) {
+ global_var=true;
+ }
+
+ if (global_var) {
+ for(int i=0;i<ScriptServer::get_language_count();i++) {
+ ScriptServer::get_language(i)->add_global_constant(name,Variant());
+ }
+ }
+
+ }
+
+ //second pass, load into global constants
+ List<Node*> to_add;
+ for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
+
+ String s = E->get().name;
+ if (!s.begins_with("autoload/"))
+ continue;
+ String name = s.get_slicec('/',1);
+ String path = Globals::get_singleton()->get(s);
+ bool global_var=false;
+ if (path.begins_with("*")) {
+ global_var=true;
+ path=path.substr(1,path.length()-1);
+ }
+
RES res = ResourceLoader::load(path);
ERR_EXPLAIN("Can't autoload: "+path);
ERR_CONTINUE(res.is_null());
@@ -1335,12 +1375,13 @@ bool Main::start() {
} else if (res->is_type("Script")) {
Ref<Script> s = res;
StringName ibt = s->get_instance_base_type();
+ bool valid_type = ObjectTypeDB::is_type(ibt,"Node");
ERR_EXPLAIN("Script does not inherit a Node: "+path);
- ERR_CONTINUE( !ObjectTypeDB::is_type(ibt,"Node") );
+ ERR_CONTINUE( !valid_type );
Object *obj = ObjectTypeDB::instance(ibt);
- ERR_EXPLAIN("Cannot instance node for autoload type: "+String(ibt));
+ ERR_EXPLAIN("Cannot instance script for autoload, expected 'Node' inheritance, got: "+String(ibt));
ERR_CONTINUE( obj==NULL );
n = obj->cast_to<Node>();
@@ -1350,9 +1391,26 @@ bool Main::start() {
ERR_EXPLAIN("Path in autoload not a node or script: "+path);
ERR_CONTINUE(!n);
n->set_name(name);
- sml->get_root()->add_child(n);
+
+ //defer so references are all valid on _ready()
+ //sml->get_root()->add_child(n);
+ to_add.push_back(n);
+
+ if (global_var) {
+ for(int i=0;i<ScriptServer::get_language_count();i++) {
+ ScriptServer::get_language(i)->add_global_constant(name,n);
+ }
+ }
+
}
+ for(List<Node*>::Element *E=to_add.front();E;E=E->next()) {
+
+ sml->get_root()->add_child(E->get());
+ }
+
+
+
}
Node *scene=NULL;
diff --git a/main/main.h b/main/main.h
index 12b4411d56..bc8b18776e 100644
--- a/main/main.h
+++ b/main/main.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/main/performance.cpp b/main/performance.cpp
index f8c5df42d1..13ae0504f6 100644
--- a/main/performance.cpp
+++ b/main/performance.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/main/performance.h b/main/performance.h
index f0cd217b2b..81e42710ca 100644
--- a/main/performance.h
+++ b/main/performance.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/main/splash.h b/main/splash.h
index f69383cf00..832f504288 100644
--- a/main/splash.h
+++ b/main/splash.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/makerel.bat b/makerel.bat
deleted file mode 100644
index 7db76e1dd7..0000000000
--- a/makerel.bat
+++ /dev/null
@@ -1 +0,0 @@
-"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" && c:\python27\scons p=windows target=debug_release tools=no
diff --git a/methods.py b/methods.py
index 21c2293bf0..e8de4696cd 100755
--- a/methods.py
+++ b/methods.py
@@ -1274,30 +1274,35 @@ def win32_spawn(sh, escape, cmd, args, spawnenv):
return exit_code
"""
-def android_module_source(self,subpath,manifest=""):
- base_path = "../../../modules/"+self.current_module+"/"+subpath
- self.android_source_modules.append(base_path)
-
-def android_module_library(self,subpath,manifest=""):
- base_path = ""
- if (os.path.isabs(subpath)):
- base_path=subpath
- else:
- base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+subpath
- self.android_module_libraries.append(base_path)
-
-def android_module_file(self,file):
- base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+file
- self.android_source_files.append(base_path)
-def android_module_manifest(self,file):
+def android_add_maven_repository(self,url):
+ self.android_maven_repos.append(url)
+
+def android_add_dependency(self,depline):
+ self.android_dependencies.append(depline)
+
+def android_add_java_dir(self,subpath):
+ base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+subpath
+ self.android_java_dirs.append(base_path)
+
+def android_add_res_dir(self,subpath):
+ base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+subpath
+ self.android_res_dirs.append(base_path)
+def android_add_aidl_dir(self,subpath):
+ base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+subpath
+ self.android_aidl_dirs.append(base_path)
+def android_add_jni_dir(self,subpath):
+ base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+subpath
+ self.android_jni_dirs.append(base_path)
+
+def android_add_to_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):
+def android_add_to_permissions(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):
+def android_add_to_attributes(self,file):
base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+file
f = open(base_path,"rb")
self.android_appattributes_chunk+=f.read()
diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp
index a62225f663..53519030fc 100644
--- a/modules/gdscript/gd_compiler.cpp
+++ b/modules/gdscript/gd_compiler.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1156,6 +1156,10 @@ Error GDCompiler::_parse_block(CodeGen& codegen,const GDParser::BlockNode *p_blo
codegen.opcodes.push_back(GDFunction::OPCODE_ASSERT);
codegen.opcodes.push_back(ret);
} break;
+ case GDParser::Node::TYPE_BREAKPOINT: {
+ // try subblocks
+ codegen.opcodes.push_back(GDFunction::OPCODE_BREAKPOINT);
+ } break;
case GDParser::Node::TYPE_LOCAL_VAR: {
@@ -1181,7 +1185,7 @@ Error GDCompiler::_parse_block(CodeGen& codegen,const GDParser::BlockNode *p_blo
}
-Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *p_class,const GDParser::FunctionNode *p_func) {
+Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *p_class,const GDParser::FunctionNode *p_func,bool p_for_ready) {
Vector<int> bytecode;
CodeGen codegen;
@@ -1212,9 +1216,9 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *
/* Parse initializer -if applies- */
- bool is_initializer=false || !p_func;
+ bool is_initializer=!p_for_ready && !p_func;
- if (!p_func || String(p_func->name)=="_init") {
+ if (is_initializer || (p_func && String(p_func->name)=="_init")) {
//parse initializer for class members
if (!p_func && p_class->extends_used && p_script->native.is_null()){
@@ -1232,12 +1236,24 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *
}
+ if (p_for_ready || (p_func && String(p_func->name)=="_ready")) {
+ //parse initializer for class members
+ if (p_class->ready->statements.size()) {
+ Error err = _parse_block(codegen,p_class->ready,stack_level);
+ if (err)
+ return err;
+ }
+
+ }
+
+
/* Parse default argument code -if applies- */
Vector<int> defarg_addr;
StringName func_name;
if (p_func) {
+
if (p_func->default_values.size()) {
codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_TO_DEF_ARGUMENT);
@@ -1260,7 +1276,10 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *
func_name=p_func->name;
} else {
- func_name="_init";
+ if (p_for_ready)
+ func_name="_ready";
+ else
+ func_name="_init";
}
codegen.opcodes.push_back(GDFunction::OPCODE_END);
@@ -1328,7 +1347,7 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *
if (defarg_addr.size()) {
gdfunc->default_arguments=defarg_addr;
- gdfunc->_default_arg_count=defarg_addr.size();
+ gdfunc->_default_arg_count=defarg_addr.size()-1;
gdfunc->_default_arg_ptr=&gdfunc->default_arguments[0];
} else {
gdfunc->_default_arg_count=0;
@@ -1614,10 +1633,14 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
//parse methods
bool has_initializer=false;
+ bool has_ready=false;
+
for(int i=0;i<p_class->functions.size();i++) {
if (!has_initializer && p_class->functions[i]->name=="_init")
has_initializer=true;
+ if (!has_ready && p_class->functions[i]->name=="_ready")
+ has_ready=true;
Error err = _parse_function(p_script,p_class,p_class->functions[i]);
if (err)
return err;
@@ -1640,6 +1663,13 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
return err;
}
+ if (!has_ready && p_class->ready->statements.size()) {
+ //create a constructor
+ Error err = _parse_function(p_script,p_class,NULL,true);
+ if (err)
+ return err;
+ }
+
#ifdef DEBUG_ENABLED
//validate setters/getters if debug is enabled
for(int i=0;i<p_class->variables.size();i++) {
diff --git a/modules/gdscript/gd_compiler.h b/modules/gdscript/gd_compiler.h
index bdf4e9816a..5bf7ec980d 100644
--- a/modules/gdscript/gd_compiler.h
+++ b/modules/gdscript/gd_compiler.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -143,7 +143,7 @@ class GDCompiler {
int _parse_assign_right_expression(CodeGen& codegen,const GDParser::OperatorNode *p_expression, int p_stack_level);
int _parse_expression(CodeGen& codegen,const GDParser::Node *p_expression, int p_stack_level,bool p_root=false,bool p_initializer=false);
Error _parse_block(CodeGen& codegen,const GDParser::BlockNode *p_block,int p_stack_level=0,int p_break_addr=-1,int p_continue_addr=-1);
- Error _parse_function(GDScript *p_script,const GDParser::ClassNode *p_class,const GDParser::FunctionNode *p_func);
+ Error _parse_function(GDScript *p_script,const GDParser::ClassNode *p_class,const GDParser::FunctionNode *p_func,bool p_for_ready=false);
Error _parse_class(GDScript *p_script,GDScript *p_owner,const GDParser::ClassNode *p_class);
int err_line;
int err_column;
diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp
index 381edcba50..126a8cd1eb 100644
--- a/modules/gdscript/gd_editor.cpp
+++ b/modules/gdscript/gd_editor.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1147,8 +1147,54 @@ static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const
}
}
+ //autoloads as singletons
+ List<PropertyInfo> props;
+ Globals::get_singleton()->get_property_list(&props);
+ for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
+ String s = E->get().name;
+ if (!s.begins_with("autoload/"))
+ continue;
+ String name = s.get_slice("/",1);
+ if (name==String(p_identifier)) {
+
+ String path = Globals::get_singleton()->get(s);
+ if (path.begins_with("*")) {
+ String script =path.substr(1,path.length());
+
+ if (!script.ends_with(".gd")) {
+ //not a script, try find the script anyway,
+ //may have some success
+ script=script.basename()+".gd";
+ }
+
+ if (FileAccess::exists(script)) {
+
+ //print_line("is a script");
+
+
+ Ref<Script> scr;
+ if (ScriptCodeCompletionCache::get_sigleton())
+ scr = ScriptCodeCompletionCache::get_sigleton()->get_cached_resource(script);
+ else
+ scr = ResourceLoader::load(script);
+
+
+ r_type.obj_type="Node";
+ r_type.type=Variant::OBJECT;
+ r_type.script=scr;
+ r_type.value=Variant();
+
+ return true;
+
+ }
+ }
+ }
+
+ }
+
+ //global
for(Map<StringName,int>::Element *E=GDScriptLanguage::get_singleton()->get_global_map().front();E;E=E->next()) {
if (E->key()==p_identifier) {
@@ -1336,6 +1382,24 @@ static void _find_identifiers(GDCompletionContext& context,int p_line,bool p_onl
result.insert(_type_names[i]);
}
+ //autoload singletons
+ List<PropertyInfo> props;
+ Globals::get_singleton()->get_property_list(&props);
+
+ for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
+
+ String s = E->get().name;
+ if (!s.begins_with("autoload/"))
+ continue;
+ String name = s.get_slice("/",1);
+ String path = Globals::get_singleton()->get(s);
+ if (path.begins_with("*")) {
+ result.insert(name);
+ }
+
+ }
+
+
for(const Map<StringName,int>::Element *E=GDScriptLanguage::get_singleton()->get_global_map().front();E;E=E->next()) {
result.insert(E->key().operator String());
}
diff --git a/modules/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp
index 6f51ac5312..e015ddb65e 100644
--- a/modules/gdscript/gd_functions.cpp
+++ b/modules/gdscript/gd_functions.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,6 +33,8 @@
#include "gd_script.h"
#include "func_ref.h"
#include "os/os.h"
+#include "variant_parser.h"
+#include "io/marshalls.h"
const char *GDFunctions::get_func_name(Function p_func) {
@@ -93,11 +95,14 @@ const char *GDFunctions::get_func_name(Function p_func) {
"printraw",
"var2str",
"str2var",
+ "var2bytes",
+ "bytes2var",
"range",
"load",
"inst2dict",
"dict2inst",
"hash",
+ "Color8",
"print_stack",
"instance_from_id",
};
@@ -524,6 +529,7 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
for(int i=0;i<p_arg_count;i++) {
String os = p_args[i]->operator String();;
+
if (i==0)
str=os;
else
@@ -607,7 +613,9 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
} break;
case VAR_TO_STR: {
VALIDATE_ARG_COUNT(1);
- r_ret=p_args[0]->get_construct_string();
+ String vars;
+ VariantWriter::write_to_string(*p_args[0],vars);
+ r_ret=vars;
} break;
case STR_TO_VAR: {
VALIDATE_ARG_COUNT(1);
@@ -618,7 +626,72 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
r_ret=Variant();
return;
}
- Variant::construct_from_string(*p_args[0],r_ret);
+
+ VariantParser::StreamString ss;
+ ss.s=*p_args[0];
+
+ String errs;
+ int line;
+ Error err = VariantParser::parse(&ss,r_ret,errs,line);
+
+ if (err!=OK) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::STRING;
+ r_ret=Variant();
+ }
+
+ } break;
+ case VAR_TO_BYTES: {
+ VALIDATE_ARG_COUNT(1);
+
+ ByteArray barr;
+ int len;
+ Error err = encode_variant(*p_args[0],NULL,len);
+ if (err) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::NIL;
+ r_ret=Variant();
+ return;
+ }
+
+ barr.resize(len);
+ {
+ ByteArray::Write w = barr.write();
+ encode_variant(*p_args[0],w.ptr(),len);
+
+ }
+ r_ret=barr;
+ } break;
+ case BYTES_TO_VAR: {
+ VALIDATE_ARG_COUNT(1);
+ if (p_args[0]->get_type()!=Variant::RAW_ARRAY) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::RAW_ARRAY;
+ r_ret=Variant();
+ return;
+ }
+
+ ByteArray varr=*p_args[0];
+ Variant ret;
+ {
+ ByteArray::Read r=varr.read();
+ Error err = decode_variant(ret,r.ptr(),varr.size(),NULL);
+ if (err!=OK) {
+ ERR_PRINT("Not enough bytes for decoding..");
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::RAW_ARRAY;
+ r_ret=Variant();
+ return;
+ }
+
+ }
+
+ r_ret=ret;
+
} break;
case GEN_RANGE: {
@@ -920,6 +993,33 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
r_ret=p_args[0]->hash();
} break;
+ case COLOR8: {
+
+ if (p_arg_count<3) {
+ r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument=3;
+ return;
+ }
+ if (p_arg_count>4) {
+ r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument=4;
+ return;
+ }
+
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ VALIDATE_ARG_NUM(2);
+
+ Color color(*p_args[0],*p_args[1],*p_args[2]);
+
+ if (p_arg_count==4) {
+ VALIDATE_ARG_NUM(3);
+ color.a=*p_args[3];
+ }
+
+ r_ret=color;
+
+ } break;
case PRINT_STACK: {
@@ -999,6 +1099,7 @@ bool GDFunctions::is_deterministic(Function p_func) {
case TYPE_CONVERT:
case TYPE_OF:
case TEXT_STR:
+ case COLOR8:
// enable for debug only, otherwise not desirable - case GEN_RANGE:
return true;
default:
@@ -1307,7 +1408,19 @@ MethodInfo GDFunctions::get_info(Function p_func) {
} break;
case STR_TO_VAR: {
- MethodInfo mi("str2var:var",PropertyInfo(Variant::STRING,"string"));
+ MethodInfo mi("str2var:Variant",PropertyInfo(Variant::STRING,"string"));
+ mi.return_val.type=Variant::NIL;
+ return mi;
+ } break;
+ case VAR_TO_BYTES: {
+ MethodInfo mi("var2bytes",PropertyInfo(Variant::NIL,"var"));
+ mi.return_val.type=Variant::RAW_ARRAY;
+ return mi;
+
+ } break;
+ case BYTES_TO_VAR: {
+
+ MethodInfo mi("bytes2var:Variant",PropertyInfo(Variant::RAW_ARRAY,"bytes"));
mi.return_val.type=Variant::NIL;
return mi;
} break;
@@ -1338,10 +1451,16 @@ MethodInfo GDFunctions::get_info(Function p_func) {
} break;
case HASH: {
- MethodInfo mi("hash",PropertyInfo(Variant::NIL,"var:var"));
+ MethodInfo mi("hash",PropertyInfo(Variant::NIL,"var:Variant"));
mi.return_val.type=Variant::INT;
return mi;
} break;
+ case COLOR8: {
+
+ MethodInfo mi("Color8",PropertyInfo(Variant::INT,"r8"),PropertyInfo(Variant::INT,"g8"),PropertyInfo(Variant::INT,"b8"),PropertyInfo(Variant::INT,"a8"));
+ mi.return_val.type=Variant::COLOR;
+ return mi;
+ } break;
case PRINT_STACK: {
MethodInfo mi("print_stack");
diff --git a/modules/gdscript/gd_functions.h b/modules/gdscript/gd_functions.h
index ad35a628d5..8c88472567 100644
--- a/modules/gdscript/gd_functions.h
+++ b/modules/gdscript/gd_functions.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -89,11 +89,14 @@ public:
TEXT_PRINTRAW,
VAR_TO_STR,
STR_TO_VAR,
+ VAR_TO_BYTES,
+ BYTES_TO_VAR,
GEN_RANGE,
RESOURCE_LOAD,
INST2DICT,
DICT2INST,
HASH,
+ COLOR8,
PRINT_STACK,
INSTANCE_FROM_ID,
FUNC_MAX
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index c55bfee591..4c6b6ff2dd 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -75,20 +75,28 @@ bool GDParser::_enter_indent_block(BlockNode* p_block) {
if (tokenizer->get_token()!=GDTokenizer::TK_NEWLINE) {
- _set_error("newline expected after ':'.");
- return false;
+ // be more python-like
+ int current = tab_level.back()->get();
+ tab_level.push_back(current+1);
+ return true;
+ //_set_error("newline expected after ':'.");
+ //return false;
}
while(true) {
if (tokenizer->get_token()!=GDTokenizer::TK_NEWLINE) {
+ print_line("no newline");
return false; //wtf
} else if (tokenizer->get_token(1)!=GDTokenizer::TK_NEWLINE) {
int indent = tokenizer->get_token_line_indent();
int current = tab_level.back()->get();
- if (indent<=current)
+ if (indent<=current) {
+ print_line("current: "+itos(current)+" indent: "+itos(indent));
+ print_line("less than current");
return false;
+ }
tab_level.push_back(indent);
tokenizer->advance();
@@ -259,6 +267,13 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
constant->value=tokenizer->get_token_constant();
tokenizer->advance();
expr=constant;
+ } else if (tokenizer->get_token()==GDTokenizer::TK_CONST_PI) {
+
+ //constant defined by tokenizer
+ ConstantNode *constant = alloc_node<ConstantNode>();
+ constant->value=Math_PI;
+ tokenizer->advance();
+ expr=constant;
} else if (tokenizer->get_token()==GDTokenizer::TK_PR_PRELOAD) {
//constant defined by tokenizer
@@ -1588,6 +1603,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
p_block->sub_blocks.push_back(cf_if->body);
if (!_enter_indent_block(cf_if->body)) {
+ _set_error("Expected intended block after 'if'");
p_block->end_line=tokenizer->get_token_line();
return;
}
@@ -1647,6 +1663,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
if (!_enter_indent_block(cf_if->body)) {
+ _set_error("Expected indented block after 'elif'");
p_block->end_line=tokenizer->get_token_line();
return;
}
@@ -1661,7 +1678,6 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
} else if (tokenizer->get_token()==GDTokenizer::TK_CF_ELSE) {
if (tab_level.back()->get() > indent_level) {
-
_set_error("Invalid indent");
return;
}
@@ -1673,6 +1689,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
p_block->sub_blocks.push_back(cf_if->body_else);
if (!_enter_indent_block(cf_if->body_else)) {
+ _set_error("Expected indented block after 'else'");
p_block->end_line=tokenizer->get_token_line();
return;
}
@@ -1713,6 +1730,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
p_block->sub_blocks.push_back(cf_while->body);
if (!_enter_indent_block(cf_while->body)) {
+ _set_error("Expected indented block after 'while'");
p_block->end_line=tokenizer->get_token_line();
return;
}
@@ -1764,6 +1782,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
p_block->sub_blocks.push_back(cf_for->body);
if (!_enter_indent_block(cf_for->body)) {
+ _set_error("Expected indented block after 'while'");
p_block->end_line=tokenizer->get_token_line();
return;
}
@@ -1850,6 +1869,17 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
return;
}
} break;
+ case GDTokenizer::TK_PR_BREAKPOINT: {
+
+ tokenizer->advance();
+ BreakpointNode *bn = alloc_node<BreakpointNode>();
+ p_block->statements.push_back(bn);
+
+ if (!_end_statement()) {
+ _set_error("Expected end of statement after breakpoint.");
+ return;
+ }
+ } break;
default: {
Node *expression = _parse_and_reduce_expression(p_block,p_static,false,true);
@@ -2058,6 +2088,8 @@ void GDParser::_parse_class(ClassNode *p_class) {
ClassNode *newclass = alloc_node<ClassNode>();
newclass->initializer = alloc_node<BlockNode>();
newclass->initializer->parent_class=newclass;
+ newclass->ready = alloc_node<BlockNode>();
+ newclass->ready->parent_class=newclass;
newclass->name=name;
newclass->owner=p_class;
@@ -2381,10 +2413,48 @@ void GDParser::_parse_class(ClassNode *p_class) {
current_export.hint=PROPERTY_HINT_ALL_FLAGS;
tokenizer->advance();
- if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' in hint.");
+
+ if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ break;
+ }
+ if (tokenizer->get_token()!=GDTokenizer::TK_COMMA)
+ {
+ _set_error("Expected ')' or ',' in bit flags hint.");
return;
}
+
+ current_export.hint=PROPERTY_HINT_FLAGS;
+ tokenizer->advance();
+
+ bool first = true;
+ while(true) {
+
+ if (tokenizer->get_token()!=GDTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type()!=Variant::STRING) {
+ current_export=PropertyInfo();
+ _set_error("Expected a string constant in named bit flags hint.");
+ return;
+ }
+
+ String c = tokenizer->get_token_constant();
+ if (!first)
+ current_export.hint_string+=",";
+ else
+ first=false;
+
+ current_export.hint_string+=c.xml_escape();
+
+ tokenizer->advance();
+ if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE)
+ break;
+
+ if (tokenizer->get_token()!=GDTokenizer::TK_COMMA) {
+ current_export=PropertyInfo();
+ _set_error("Expected ')' or ',' in named bit flags hint.");
+ return;
+ }
+ tokenizer->advance();
+ }
+
break;
}
@@ -2439,6 +2509,23 @@ void GDParser::_parse_class(ClassNode *p_class) {
break;
}
+ // range
+ if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier()=="EXP") {
+
+ current_export.hint=PROPERTY_HINT_EXP_RANGE;
+ tokenizer->advance();
+
+ if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE)
+ break;
+ else if (tokenizer->get_token()!=GDTokenizer::TK_COMMA) {
+ _set_error("Expected ')' or ',' in exponential range hint.");
+ return;
+ }
+ tokenizer->advance();
+ }
+ else
+ current_export.hint=PROPERTY_HINT_RANGE;
+
float sign=1.0;
if (tokenizer->get_token()==GDTokenizer::TK_OP_SUB) {
@@ -2452,8 +2539,6 @@ void GDParser::_parse_class(ClassNode *p_class) {
return;
}
- //enumeration
- current_export.hint=PROPERTY_HINT_RANGE;
current_export.hint_string=rtos(sign*double(tokenizer->get_token_constant()));
tokenizer->advance();
@@ -2556,10 +2641,32 @@ void GDParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier()=="DIR") {
- current_export.hint=PROPERTY_HINT_DIR;
tokenizer->advance();
- if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' in hint.");
+
+ if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE)
+ current_export.hint=PROPERTY_HINT_DIR;
+ else if (tokenizer->get_token()==GDTokenizer::TK_COMMA ) {
+
+ tokenizer->advance();
+
+ if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER || !(tokenizer->get_token_identifier()=="GLOBAL")) {
+ _set_error("Expected 'GLOBAL' after comma in directory hint.");
+ return;
+ }
+ if (!p_class->tool) {
+ _set_error("Global filesystem hints may only be used in tool scripts.");
+ return;
+ }
+ current_export.hint=PROPERTY_HINT_GLOBAL_DIR;
+ tokenizer->advance();
+
+ if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected ')' in hint.");
+ return;
+ }
+ }
+ else {
+ _set_error("Expected ')' or ',' in hint.");
return;
}
break;
@@ -2573,9 +2680,32 @@ void GDParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token()==GDTokenizer::TK_COMMA) {
tokenizer->advance();
+
+ if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier()=="GLOBAL") {
+
+ if (!p_class->tool) {
+ _set_error("Global filesystem hints may only be used in tool scripts.");
+ return;
+ }
+ current_export.hint=PROPERTY_HINT_GLOBAL_FILE;
+ tokenizer->advance();
+
+ if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE)
+ break;
+ else if (tokenizer->get_token()==GDTokenizer::TK_COMMA)
+ tokenizer->advance();
+ else {
+ _set_error("Expected ')' or ',' in hint.");
+ return;
+ }
+ }
+
if (tokenizer->get_token()!=GDTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type()!=Variant::STRING) {
- _set_error("Expected string constant with filter");
+ if (current_export.hint==PROPERTY_HINT_GLOBAL_FILE)
+ _set_error("Expected string constant with filter");
+ else
+ _set_error("Expected 'GLOBAL' or string constant with filter");
return;
}
current_export.hint_string=tokenizer->get_token_constant();
@@ -2669,6 +2799,17 @@ void GDParser::_parse_class(ClassNode *p_class) {
}
}; //fallthrough to var
+ case GDTokenizer::TK_PR_ONREADY: {
+
+ if (token==GDTokenizer::TK_PR_ONREADY) {
+ //may be fallthrough from export, ignore if so
+ tokenizer->advance();
+ if (tokenizer->get_token()!=GDTokenizer::TK_PR_VAR) {
+ _set_error("Expected 'var'.");
+ return;
+ }
+ }
+ }; //fallthrough to var
case GDTokenizer::TK_PR_VAR: {
//variale declaration and (eventual) initialization
@@ -2679,6 +2820,8 @@ void GDParser::_parse_class(ClassNode *p_class) {
current_export=PropertyInfo();
}
+ bool onready = tokenizer->get_token(-1)==GDTokenizer::TK_PR_ONREADY;
+
tokenizer->advance();
if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) {
@@ -2709,6 +2852,21 @@ void GDParser::_parse_class(ClassNode *p_class) {
return;
}
+ //discourage common error
+ if (!onready && subexpr->type==Node::TYPE_OPERATOR) {
+
+ OperatorNode *op=static_cast<OperatorNode*>(subexpr);
+ if (op->op==OperatorNode::OP_CALL && op->arguments[0]->type==Node::TYPE_SELF && op->arguments[1]->type==Node::TYPE_IDENTIFIER) {
+ IdentifierNode *id=static_cast<IdentifierNode*>(op->arguments[1]);
+ if (id->name=="get_node") {
+
+ _set_error("Use 'onready var "+String(member.identifier)+" = get_node(..)' instead");
+ return;
+
+ }
+ }
+ }
+
member.expression=subexpr;
if (autoexport) {
@@ -2755,12 +2913,19 @@ void GDParser::_parse_class(ClassNode *p_class) {
op->arguments.push_back(id);
op->arguments.push_back(subexpr);
+
#ifdef DEBUG_ENABLED
NewLineNode *nl = alloc_node<NewLineNode>();
nl->line=line;
- p_class->initializer->statements.push_back(nl);
+ if (onready)
+ p_class->ready->statements.push_back(nl);
+ else
+ p_class->initializer->statements.push_back(nl);
#endif
- p_class->initializer->statements.push_back(op);
+ if (onready)
+ p_class->ready->statements.push_back(op);
+ else
+ p_class->initializer->statements.push_back(op);
@@ -2911,6 +3076,8 @@ Error GDParser::_parse(const String& p_base_path) {
ClassNode *main_class = alloc_node<ClassNode>();
main_class->initializer = alloc_node<BlockNode>();
main_class->initializer->parent_class=main_class;
+ main_class->ready = alloc_node<BlockNode>();
+ main_class->ready->parent_class=main_class;
current_class=main_class;
_parse_class(main_class);
@@ -2978,6 +3145,11 @@ Error GDParser::parse(const String& p_code, const String& p_base_path, bool p_ju
return ret;
}
+bool GDParser::is_tool_script() const {
+
+ return (head && head->type==Node::TYPE_CLASS && static_cast<const ClassNode*>(head)->tool);
+}
+
const GDParser::Node *GDParser::get_parse_tree() const {
return head;
diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h
index 04f3dff3de..6c49c1df52 100644
--- a/modules/gdscript/gd_parser.h
+++ b/modules/gdscript/gd_parser.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -54,6 +54,7 @@ public:
TYPE_CONTROL_FLOW,
TYPE_LOCAL_VAR,
TYPE_ASSERT,
+ TYPE_BREAKPOINT,
TYPE_NEWLINE,
};
@@ -105,6 +106,7 @@ public:
Vector<FunctionNode*> static_functions;
Vector<Signal> _signals;
BlockNode *initializer;
+ BlockNode *ready;
ClassNode *owner;
//Vector<Node*> initializers;
int end_line;
@@ -275,6 +277,10 @@ public:
AssertNode() { type=TYPE_ASSERT; }
};
+ struct BreakpointNode : public Node {
+ BreakpointNode() { type=TYPE_BREAKPOINT; }
+ };
+
struct NewLineNode : public Node {
NewLineNode() { type=TYPE_NEWLINE; }
};
@@ -448,6 +454,7 @@ public:
Error parse(const String& p_code, const String& p_base_path="", bool p_just_validate=false,const String& p_self_path="",bool p_for_completion=false);
Error parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p_base_path="",const String& p_self_path="");
+ bool is_tool_script() const;
const Node *get_parse_tree() const;
//completion info
diff --git a/modules/gdscript/gd_pretty_print.cpp b/modules/gdscript/gd_pretty_print.cpp
index 9c290eac4a..cca3cd3984 100644
--- a/modules/gdscript/gd_pretty_print.cpp
+++ b/modules/gdscript/gd_pretty_print.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/gd_pretty_print.h b/modules/gdscript/gd_pretty_print.h
index 998fdc53ab..0106d873d9 100644
--- a/modules/gdscript/gd_pretty_print.h
+++ b/modules/gdscript/gd_pretty_print.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index 8746f92c9e..62c5eb735a 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,17 +33,6 @@
#include "os/file_access.h"
#include "io/file_access_encrypted.h"
-/* TODO:
-
- *populate globals
- *do checks as close to debugger as possible (but don't do debugger)
- *const check plz
- *check arguments and default arguments in GDFunction
- -get property list in instance?
- *missing opcodes
- -const checks
- -make thread safe
- */
@@ -232,6 +221,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
r_err.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
r_err.argument=_argument_count;
+
return Variant();
} else if (p_argcount < _argument_count - _default_arg_count) {
@@ -1077,6 +1067,14 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
ip+=2;
} continue;
+ case OPCODE_BREAKPOINT: {
+#ifdef DEBUG_ENABLED
+ if (ScriptDebugger::get_singleton()) {
+ GDScriptLanguage::get_singleton()->debug_break("Breakpoint Statement",true);
+ }
+#endif
+ ip+=1;
+ } continue;
case OPCODE_LINE: {
CHECK_SPACE(2);
@@ -1141,7 +1139,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (!GDScriptLanguage::get_singleton()->debug_break(err_text,false)) {
// debugger break did not happen
- _err_print_error(err_func.utf8().get_data(),err_file.utf8().get_data(),err_line,err_text.utf8().get_data());
+ _err_print_error(err_func.utf8().get_data(),err_file.utf8().get_data(),err_line,err_text.utf8().get_data(),ERR_HANDLER_SCRIPT);
}
@@ -1370,7 +1368,7 @@ Variant GDFunctionState::resume(const Variant& p_arg) {
void GDFunctionState::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("resume:var","arg"),&GDFunctionState::resume,DEFVAL(Variant()));
+ ObjectTypeDB::bind_method(_MD("resume:Variant","arg"),&GDFunctionState::resume,DEFVAL(Variant()));
ObjectTypeDB::bind_method(_MD("is_valid"),&GDFunctionState::is_valid);
ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"_signal_callback",&GDFunctionState::_signal_callback,MethodInfo("_signal_callback"));
@@ -1595,6 +1593,28 @@ void GDScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) {
}*/
#endif
+
+bool GDScript::get_property_default_value(const StringName& p_property, Variant &r_value) const {
+
+#ifdef TOOLS_ENABLED
+
+ //for (const Map<StringName,Variant>::Element *I=member_default_values.front();I;I=I->next()) {
+ // print_line("\t"+String(String(I->key())+":"+String(I->get())));
+ //}
+ const Map<StringName,Variant>::Element *E=member_default_values_cache.find(p_property);
+ if (E) {
+ r_value=E->get();
+ return true;
+ }
+
+ if (base_cache.is_valid()) {
+ return base_cache->get_property_default_value(p_property,r_value);
+ }
+#endif
+ return false;
+
+}
+
ScriptInstance* GDScript::instance_create(Object *p_this) {
@@ -1732,16 +1752,21 @@ bool GDScript::_update_exports() {
}
}
- Ref<GDScript> bf = ResourceLoader::load(path);
+ if (path!=get_path()) {
- if (bf.is_valid()) {
+ Ref<GDScript> bf = ResourceLoader::load(path);
- //print_line("parent is: "+bf->get_path());
- base_cache=bf;
- bf->inheriters_cache.insert(get_instance_ID());
+ if (bf.is_valid()) {
- //bf->_update_exports(p_instances,true,false);
+ //print_line("parent is: "+bf->get_path());
+ base_cache=bf;
+ bf->inheriters_cache.insert(get_instance_ID());
+ //bf->_update_exports(p_instances,true,false);
+
+ }
+ } else {
+ ERR_PRINT(("Path extending itself in "+path).utf8().get_data());
}
}
@@ -1849,19 +1874,27 @@ Error GDScript::reload() {
if (ScriptDebugger::get_singleton()) {
GDScriptLanguage::get_singleton()->debug_break_parse(get_path(),parser.get_error_line(),"Parser Error: "+parser.get_error());
}
- _err_print_error("GDScript::reload",path.empty()?"built-in":(const char*)path.utf8().get_data(),parser.get_error_line(),("Parse Error: "+parser.get_error()).utf8().get_data());
+ _err_print_error("GDScript::reload",path.empty()?"built-in":(const char*)path.utf8().get_data(),parser.get_error_line(),("Parse Error: "+parser.get_error()).utf8().get_data(),ERR_HANDLER_SCRIPT);
ERR_FAIL_V(ERR_PARSE_ERROR);
}
+
+ bool can_run = ScriptServer::is_scripting_enabled() || parser.is_tool_script();
+
GDCompiler compiler;
err = compiler.compile(&parser,this);
if (err) {
- if (ScriptDebugger::get_singleton()) {
- GDScriptLanguage::get_singleton()->debug_break_parse(get_path(),compiler.get_error_line(),"Parser Error: "+compiler.get_error());
+
+ if (can_run) {
+ if (ScriptDebugger::get_singleton()) {
+ GDScriptLanguage::get_singleton()->debug_break_parse(get_path(),compiler.get_error_line(),"Parser Error: "+compiler.get_error());
+ }
+ _err_print_error("GDScript::reload",path.empty()?"built-in":(const char*)path.utf8().get_data(),compiler.get_error_line(),("Compile Error: "+compiler.get_error()).utf8().get_data(),ERR_HANDLER_SCRIPT);
+ ERR_FAIL_V(ERR_COMPILATION_FAILED);
+ } else {
+ return err;
}
- _err_print_error("GDScript::reload",path.empty()?"built-in":(const char*)path.utf8().get_data(),compiler.get_error_line(),("Compile Error: "+compiler.get_error()).utf8().get_data());
- ERR_FAIL_V(ERR_COMPILATION_FAILED);
}
valid=true;
@@ -2028,7 +2061,7 @@ Error GDScript::load_byte_code(const String& p_path) {
GDParser parser;
Error err = parser.parse_bytecode(bytecode,basedir,get_path());
if (err) {
- _err_print_error("GDScript::load_byte_code",path.empty()?"built-in":(const char*)path.utf8().get_data(),parser.get_error_line(),("Parse Error: "+parser.get_error()).utf8().get_data());
+ _err_print_error("GDScript::load_byte_code",path.empty()?"built-in":(const char*)path.utf8().get_data(),parser.get_error_line(),("Parse Error: "+parser.get_error()).utf8().get_data(),ERR_HANDLER_SCRIPT);
ERR_FAIL_V(ERR_PARSE_ERROR);
}
@@ -2036,7 +2069,7 @@ Error GDScript::load_byte_code(const String& p_path) {
err = compiler.compile(&parser,this);
if (err) {
- _err_print_error("GDScript::load_byte_code",path.empty()?"built-in":(const char*)path.utf8().get_data(),compiler.get_error_line(),("Compile Error: "+compiler.get_error()).utf8().get_data());
+ _err_print_error("GDScript::load_byte_code",path.empty()?"built-in":(const char*)path.utf8().get_data(),compiler.get_error_line(),("Compile Error: "+compiler.get_error()).utf8().get_data(),ERR_HANDLER_SCRIPT);
ERR_FAIL_V(ERR_COMPILATION_FAILED);
}
@@ -2274,6 +2307,26 @@ bool GDInstance::get(const StringName& p_name, Variant &r_ret) const {
return false;
}
+
+Variant::Type GDInstance::get_property_type(const StringName& p_name,bool *r_is_valid) const {
+
+
+ const GDScript *sptr=script.ptr();
+ while(sptr) {
+
+ if (sptr->member_info.has(p_name)) {
+ if (r_is_valid)
+ *r_is_valid=true;
+ return sptr->member_info[p_name].type;
+ }
+ sptr = sptr->_base;
+ }
+
+ if (r_is_valid)
+ *r_is_valid=false;
+ return Variant::NIL;
+}
+
void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const {
// exported members, not doen yet!
@@ -2550,6 +2603,12 @@ void GDScriptLanguage::_add_global(const StringName& p_name,const Variant& p_val
_global_array=global_array.ptr();
}
+void GDScriptLanguage::add_global_constant(const StringName& p_variable,const Variant& p_value) {
+
+ _add_global(p_variable,p_value);
+}
+
+
void GDScriptLanguage::init() {
@@ -2626,6 +2685,7 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"elif",
"enum",
"extends" ,
+ "onready",
"for" ,
"func" ,
"if" ,
@@ -2645,6 +2705,7 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"or",
"export",
"assert",
+ "breakpoint",
"yield",
"static",
"float",
diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h
index 850ffec05f..a69f99314a 100644
--- a/modules/gdscript/gd_script.h
+++ b/modules/gdscript/gd_script.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -71,6 +71,7 @@ public:
OPCODE_ITERATE_BEGIN,
OPCODE_ITERATE,
OPCODE_ASSERT,
+ OPCODE_BREAKPOINT,
OPCODE_LINE,
OPCODE_END
};
@@ -351,6 +352,8 @@ public:
Vector<uint8_t> get_as_byte_code() const;
+ bool get_property_default_value(const StringName& p_property,Variant& r_value) const;
+
virtual ScriptLanguage *get_language() const;
GDScript();
@@ -373,6 +376,8 @@ public:
virtual bool set(const StringName& p_name, const Variant& p_value);
virtual bool get(const StringName& p_name, Variant &r_ret) const;
virtual void get_property_list(List<PropertyInfo> *p_properties) const;
+ virtual Variant::Type get_property_type(const StringName& p_name,bool *r_is_valid=NULL) const;
+
virtual void get_method_list(List<MethodInfo> *p_list) const;
virtual bool has_method(const StringName& p_method) const;
@@ -527,6 +532,8 @@ public:
virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const;
virtual Error complete_code(const String& p_code, const String& p_base_path, Object*p_owner,List<String>* r_options,String& r_call_hint);
virtual void auto_indent_code(String& p_code,int p_from_line,int p_to_line) const;
+ virtual void add_global_constant(const StringName& p_variable,const Variant& p_value);
+
/* DEBUGGER FUNCTIONS */
diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp
index b591ed3b4b..71c56aba01 100644
--- a/modules/gdscript/gd_tokenizer.cpp
+++ b/modules/gdscript/gd_tokenizer.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -88,6 +88,7 @@ const char* GDTokenizer::token_names[TK_MAX]={
"func",
"class",
"extends",
+"onready",
"tool",
"static",
"export",
@@ -98,6 +99,7 @@ const char* GDTokenizer::token_names[TK_MAX]={
"assert",
"yield",
"signal",
+"breakpoint",
"'['",
"']'",
"'{'",
@@ -110,6 +112,7 @@ const char* GDTokenizer::token_names[TK_MAX]={
"'?'",
"':'",
"'\\n'",
+"PI",
"Error",
"EOF",
"Cursor"};
@@ -259,6 +262,7 @@ void GDTokenizerText::_advance() {
}
INCPOS(1);
+ line++;
while(GETCHAR(0)==' ' || GETCHAR(0)=='\t') {
INCPOS(1);
@@ -774,20 +778,15 @@ void GDTokenizerText::_advance() {
{Variant::INT,"int"},
{Variant::REAL,"float"},
{Variant::STRING,"String"},
- {Variant::VECTOR2,"vec2"},
{Variant::VECTOR2,"Vector2"},
{Variant::RECT2,"Rect2"},
{Variant::MATRIX32,"Matrix32"},
- {Variant::MATRIX32,"mat32"},
- {Variant::VECTOR3,"vec3"},
{Variant::VECTOR3,"Vector3"},
{Variant::_AABB,"AABB"},
{Variant::_AABB,"Rect3"},
{Variant::PLANE,"Plane"},
{Variant::QUAT,"Quat"},
- {Variant::MATRIX3,"mat3"},
{Variant::MATRIX3,"Matrix3"},
- {Variant::TRANSFORM,"trn"},
{Variant::TRANSFORM,"Transform"},
{Variant::COLOR,"Color"},
{Variant::IMAGE,"Image"},
@@ -795,7 +794,6 @@ void GDTokenizerText::_advance() {
{Variant::OBJECT,"Object"},
{Variant::INPUT_EVENT,"InputEvent"},
{Variant::NODE_PATH,"NodePath"},
- {Variant::DICTIONARY,"dict"},
{Variant::DICTIONARY,"Dictionary"},
{Variant::ARRAY,"Array"},
{Variant::RAW_ARRAY,"RawArray"},
@@ -854,9 +852,9 @@ void GDTokenizerText::_advance() {
{TK_OP_AND,"and"},
//func
{TK_PR_FUNCTION,"func"},
- {TK_PR_FUNCTION,"function"},
{TK_PR_CLASS,"class"},
{TK_PR_EXTENDS,"extends"},
+ {TK_PR_ONREADY,"onready"},
{TK_PR_TOOL,"tool"},
{TK_PR_STATIC,"static"},
{TK_PR_EXPORT,"export"},
@@ -866,6 +864,7 @@ void GDTokenizerText::_advance() {
{TK_PR_ASSERT,"assert"},
{TK_PR_YIELD,"yield"},
{TK_PR_SIGNAL,"signal"},
+ {TK_PR_BREAKPOINT,"breakpoint"},
{TK_PR_CONST,"const"},
//controlflow
{TK_CF_IF,"if"},
@@ -880,6 +879,7 @@ void GDTokenizerText::_advance() {
{TK_CF_RETURN,"return"},
{TK_CF_PASS,"pass"},
{TK_SELF,"self"},
+ {TK_CONST_PI,"PI"},
{TK_ERROR,NULL}
};
@@ -1046,7 +1046,7 @@ void GDTokenizerText::advance(int p_amount) {
//////////////////////////////////////////////////////////////////////////////////////////////////////
-#define BYTECODE_VERSION 5
+#define BYTECODE_VERSION 10
Error GDTokenizerBuffer::set_code_buffer(const Vector<uint8_t> & p_buffer) {
diff --git a/modules/gdscript/gd_tokenizer.h b/modules/gdscript/gd_tokenizer.h
index d6bd63c5b8..aaff573090 100644
--- a/modules/gdscript/gd_tokenizer.h
+++ b/modules/gdscript/gd_tokenizer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -95,6 +95,7 @@ public:
TK_PR_FUNCTION,
TK_PR_CLASS,
TK_PR_EXTENDS,
+ TK_PR_ONREADY,
TK_PR_TOOL,
TK_PR_STATIC,
TK_PR_EXPORT,
@@ -105,6 +106,7 @@ public:
TK_PR_ASSERT,
TK_PR_YIELD,
TK_PR_SIGNAL,
+ TK_PR_BREAKPOINT,
TK_BRACKET_OPEN,
TK_BRACKET_CLOSE,
TK_CURLY_BRACKET_OPEN,
@@ -117,6 +119,7 @@ public:
TK_QUESTION_MARK,
TK_COLON,
TK_NEWLINE,
+ TK_CONST_PI,
TK_ERROR,
TK_EOF,
TK_CURSOR, //used for code completion
diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp
index 4470b7ca0c..2aea494f39 100644
--- a/modules/gdscript/register_types.cpp
+++ b/modules/gdscript/register_types.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/modules/gdscript/register_types.h b/modules/gdscript/register_types.h
index 9eb5d1846b..aed11cd1d4 100644
--- a/modules/gdscript/register_types.h
+++ b/modules/gdscript/register_types.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index ad7c392cd0..7d463b13d4 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1096,7 +1096,7 @@ void GridMap::_bind_methods() {
// ObjectTypeDB::bind_method(_MD("_recreate_octants"),&GridMap::_recreate_octants);
ObjectTypeDB::bind_method(_MD("_update_dirty_map_callback"),&GridMap::_update_dirty_map_callback);
- ObjectTypeDB::bind_method(_MD("resource_changed"),&GridMap::resource_changed);
+ ObjectTypeDB::bind_method(_MD("resource_changed","resource"),&GridMap::resource_changed);
ObjectTypeDB::bind_method(_MD("set_center_x","enable"),&GridMap::set_center_x);
ObjectTypeDB::bind_method(_MD("get_center_x"),&GridMap::get_center_x);
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index 9d3b1dcf95..66d3e6b44a 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index e4559ca100..6043807db3 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h
index 03b2d4226e..fc43866ef3 100644
--- a/modules/gridmap/grid_map_editor_plugin.h
+++ b/modules/gridmap/grid_map_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gridmap/register_types.cpp b/modules/gridmap/register_types.cpp
index 2bc440759d..9dcc04b22a 100644
--- a/modules/gridmap/register_types.cpp
+++ b/modules/gridmap/register_types.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gridmap/register_types.h b/modules/gridmap/register_types.h
index 326d7acf24..7b5c10f9e5 100644
--- a/modules/gridmap/register_types.h
+++ b/modules/gridmap/register_types.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/android/AndroidManifest.xml.template b/platform/android/AndroidManifest.xml.template
index c95c86c060..37dee4a9a5 100644
--- a/platform/android/AndroidManifest.xml.template
+++ b/platform/android/AndroidManifest.xml.template
@@ -3,7 +3,7 @@
package="com.godot.game"
android:versionCode="1"
android:versionName="1.0"
- android:installLocation="preferExternal"
+ android:installLocation="auto"
>
<supports-screens android:smallScreens="true"
android:normalScreens="true"
@@ -11,7 +11,7 @@
android:xlargeScreens="true"/>
<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"
+ <activity android:name="org.godotengine.godot.Godot"
android:label="@string/godot_project_name_string"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:launchMode="singleTask"
@@ -23,7 +23,7 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- <service android:name="com.android.godot.GodotDownloaderService" />
+ <service android:name="org.godotengine.godot.GodotDownloaderService" />
@@ -189,7 +189,7 @@ $$ADD_PERMISSION_CHUNKS$$
<uses-permission android:name="godot.custom.7"/>
<uses-permission android:name="godot.custom.8"/>
<uses-permission android:name="godot.custom.9"/>
-<uses-permission android:name="godot.custom.0"/>
+<uses-permission android:name="godot.custom.10"/>
<uses-permission android:name="godot.custom.11"/>
<uses-permission android:name="godot.custom.12"/>
<uses-permission android:name="godot.custom.13"/>
diff --git a/platform/android/SCsub b/platform/android/SCsub
index 834ee58adc..3d645de38f 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -37,19 +37,59 @@ prog = None
abspath=env.Dir(".").abspath
-pp_basein = open(abspath+"/project.properties.template","rb")
-pp_baseout = open(abspath+"/java/project.properties","wb")
-pp_baseout.write( pp_basein.read() )
+gradle_basein = open(abspath+"/build.gradle.template","rb")
+gradle_baseout = open(abspath+"/java/build.gradle","wb")
-refcount=1
+gradle_text = gradle_basein.read()
-for x in env.android_source_modules:
- pp_baseout.write("android.library.reference."+str(refcount)+"="+x+"\n")
- refcount+=1
+gradle_maven_repos_text=""
+if len(env.android_maven_repos) > 0:
+ gradle_maven_repos_text+="maven {\n"
+ for x in env.android_maven_repos:
+ gradle_maven_repos_text+="\t\t"+x+"\n"
+ gradle_maven_repos_text+="\t}\n"
-pp_baseout.close()
+gradle_maven_dependencies_text=""
+
+for x in env.android_dependencies:
+ gradle_maven_dependencies_text+=x+"\n"
+
+gradle_java_dirs_text=""
+
+for x in env.android_java_dirs:
+ gradle_java_dirs_text+=",'"+x+"'"
+
+
+gradle_res_dirs_text=""
+
+for x in env.android_res_dirs:
+ gradle_res_dirs_text+=",'"+x+"'"
+
+gradle_aidl_dirs_text=""
+
+for x in env.android_aidl_dirs:
+ gradle_aidl_dirs_text+=",'"+x+"'"
+
+gradle_jni_dirs_text=""
+
+for x in env.android_jni_dirs:
+ gradle_jni_dirs_text+=",'"+x+"'"
+
+gradle_asset_dirs_text=""
+
+gradle_text = gradle_text.replace("$$GRADLE_REPOSITORY_URLS$$",gradle_maven_repos_text)
+gradle_text = gradle_text.replace("$$GRADLE_DEPENDENCIES$$",gradle_maven_dependencies_text)
+gradle_text = gradle_text.replace("$$GRADLE_JAVA_DIRS$$",gradle_java_dirs_text)
+gradle_text = gradle_text.replace("$$GRADLE_RES_DIRS$$",gradle_res_dirs_text)
+gradle_text = gradle_text.replace("$$GRADLE_ASSET_DIRS$$",gradle_asset_dirs_text)
+gradle_text = gradle_text.replace("$$GRADLE_AIDL_DIRS$$",gradle_aidl_dirs_text)
+gradle_text = gradle_text.replace("$$GRADLE_JNI_DIRS$$",gradle_jni_dirs_text)
+
+
+gradle_baseout.write( gradle_text )
+gradle_baseout.close()
pp_basein = open(abspath+"/AndroidManifest.xml.template","rb")
@@ -61,13 +101,6 @@ manifest = manifest.replace("$$ADD_APPATTRIBUTE_CHUNKS$$",env.android_appattribu
pp_baseout.write( manifest )
-for x in env.android_source_files:
- shutil.copy(x,abspath+"/java/src/com/android/godot")
-
-for x in env.android_module_libraries:
- shutil.copy(x,abspath+"/java/libs")
-
-
env_android.SharedLibrary("#bin/libgodot",[android_objects],SHLIBSUFFIX=env["SHLIBSUFFIX"])
#env.Command('#bin/libgodot_android.so', '#platform/android/libgodot_android.so', Copy('bin/libgodot_android.so', 'platform/android/libgodot_android.so'))
diff --git a/platform/android/android_native_app_glue.h b/platform/android/android_native_app_glue.h
index f5ba27ae66..3e7a4ea7a0 100644
--- a/platform/android/android_native_app_glue.h
+++ b/platform/android/android_native_app_glue.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/android/audio_driver_jandroid.cpp b/platform/android/audio_driver_jandroid.cpp
index 1a3a1cb563..6d428e3fe5 100644
--- a/platform/android/audio_driver_jandroid.cpp
+++ b/platform/android/audio_driver_jandroid.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -147,13 +147,13 @@ void AudioDriverAndroid::setup( jobject p_io) {
void AudioDriverAndroid::thread_func(JNIEnv *env) {
- jclass cls = env->FindClass("com/android/godot/Godot");
+ jclass cls = env->FindClass("org/godotengine/godot/Godot");
if (cls) {
cls=(jclass)env->NewGlobalRef(cls);
__android_log_print(ANDROID_LOG_INFO,"godot","*******CLASS FOUND!!!");
}
- jfieldID fid = env->GetStaticFieldID(cls, "io", "Lcom/android/godot/GodotIO;");
+ jfieldID fid = env->GetStaticFieldID(cls, "io", "Lorg/godotengine/godot/GodotIO;");
jobject ob = env->GetStaticObjectField(cls,fid);
jobject gob = env->NewGlobalRef(ob);
jclass c = env->GetObjectClass(gob);
diff --git a/platform/android/audio_driver_jandroid.h b/platform/android/audio_driver_jandroid.h
index bf8584051d..f79057efe5 100644
--- a/platform/android/audio_driver_jandroid.h
+++ b/platform/android/audio_driver_jandroid.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/android/audio_driver_opensl.cpp b/platform/android/audio_driver_opensl.cpp
index 761bef27aa..a908f6193e 100644
--- a/platform/android/audio_driver_opensl.cpp
+++ b/platform/android/audio_driver_opensl.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/android/audio_driver_opensl.h b/platform/android/audio_driver_opensl.h
index e9d7c7a7ea..1b04f32fd2 100644
--- a/platform/android/audio_driver_opensl.h
+++ b/platform/android/audio_driver_opensl.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/android/build.gradle.template b/platform/android/build.gradle.template
new file mode 100644
index 0000000000..9461cd2e99
--- /dev/null
+++ b/platform/android/build.gradle.template
@@ -0,0 +1,70 @@
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.2.0'
+ }
+}
+
+apply plugin: 'com.android.application'
+
+allprojects {
+ repositories {
+ mavenCentral()
+ $$GRADLE_REPOSITORY_URLS$$
+ }
+}
+
+dependencies {
+
+ $$GRADLE_DEPENDENCIES$$
+}
+
+android {
+
+ lintOptions {
+ abortOnError false
+ }
+
+ compileSdkVersion 19
+ buildToolsVersion "19.1"
+
+ packagingOptions {
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/NOTICE'
+ }
+ defaultConfig {
+ minSdkVersion 14
+ targetSdkVersion 19
+ }
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src'
+ $$GRADLE_JAVA_DIRS$$
+ ]
+ resources.srcDirs = [
+ 'res'
+ $$GRADLE_RES_DIRS$$
+ ]
+ res.srcDirs = ['res']
+ // libs.srcDirs = ['libs']
+ aidl.srcDirs = [
+ 'aidl'
+ $$GRADLE_AIDL_DIRS$$
+ ]
+ assets.srcDirs = [
+ 'assets'
+ $$GRADLE_ASSET_DIRS$$
+ ]
+ jniLibs.srcDirs = [
+ 'libs'
+ $$GRADLE_JNI_DIRS$$
+ ]
+ }
+
+ }
+
+
+}
diff --git a/platform/android/detect.py b/platform/android/detect.py
index 66097a5149..ee3dc119c2 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -106,10 +106,6 @@ def configure(env):
#env['SPAWN'] = methods.win32_spawn
env['SHLIBSUFFIX'] = '.so'
- #env.android_source_modules.append("../libs/apk_expansion")
- env.android_source_modules.append("../libs/google_play_services")
- env.android_source_modules.append("../libs/downloader_library")
- env.android_source_modules.append("../libs/play_licensing")
neon_text=""
if env["android_arch"]=="armv7" and env['android_neon']=='yes':
diff --git a/platform/android/dir_access_android.cpp b/platform/android/dir_access_android.cpp
index ca1e58da3f..85df5dc37a 100644
--- a/platform/android/dir_access_android.cpp
+++ b/platform/android/dir_access_android.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/android/dir_access_android.h b/platform/android/dir_access_android.h
index cbbcdb71bb..9477ca48fd 100644
--- a/platform/android/dir_access_android.h
+++ b/platform/android/dir_access_android.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp
index 2b5fc6a50a..8b7cb992d9 100644
--- a/platform/android/dir_access_jandroid.cpp
+++ b/platform/android/dir_access_jandroid.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -96,7 +96,7 @@ void DirAccessJAndroid::list_dir_end(){
return;
JNIEnv *env = ThreadAndroid::get_env();
- env->CallObjectMethod(io,_dir_close,id);
+ env->CallVoidMethod(io,_dir_close,id);
id=0;
@@ -143,7 +143,7 @@ Error DirAccessJAndroid::change_dir(String p_dir){
if (res<=0)
return ERR_INVALID_PARAMETER;
- env->CallObjectMethod(io,_dir_close,res);
+ env->CallVoidMethod(io,_dir_close,res);
current_dir=new_dir;
diff --git a/platform/android/dir_access_jandroid.h b/platform/android/dir_access_jandroid.h
index 7b6242ca32..356828dcc1 100644
--- a/platform/android/dir_access_jandroid.h
+++ b/platform/android/dir_access_jandroid.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 1deeb3457a..d4755f4ed6 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -1020,18 +1020,24 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
EditorProgress ep("export","Exporting for Android",104);
- String apk_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
-
- if (p_debug) {
-
- src_apk=custom_debug_package!=""?custom_debug_package:apk_path+"android_debug.apk";
- } else {
-
- src_apk=custom_release_package!=""?custom_release_package:apk_path+"android_release.apk";
+ if (p_debug)
+ src_apk=custom_debug_package;
+ else
+ src_apk=custom_release_package;
+ if (src_apk=="") {
+ String err;
+ if (p_debug) {
+ src_apk=find_export_template("android_debug.apk", &err);
+ } else {
+ src_apk=find_export_template("android_release.apk", &err);
+ }
+ if (src_apk=="") {
+ EditorNode::add_io_error(err);
+ return ERR_FILE_NOT_FOUND;
+ }
}
-
FileAccess *src_f=NULL;
zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
@@ -1162,7 +1168,7 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
gen_export_flags(cl,p_flags);
- if (p_flags) {
+ if (p_flags&EXPORT_DUMB_CLIENT) {
/*String host = EditorSettings::get_singleton()->get("file_server/host");
int port = EditorSettings::get_singleton()->get("file_server/post");
@@ -1507,6 +1513,13 @@ Error EditorExportPlatformAndroid::run(int p_device, int p_flags) {
//export_temp
ep.step("Exporting APK",0);
+
+ bool use_adb_over_usb = bool(EDITOR_DEF("android/use_remote_debug_over_adb",true));
+
+ if (use_adb_over_usb) {
+ p_flags|=EXPORT_REMOTE_DEBUG_LOCALHOST;
+ }
+
String export_to=EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmpexport.apk";
Error err = export_project(export_to,true,p_flags);
if (err) {
@@ -1553,6 +1566,35 @@ Error EditorExportPlatformAndroid::run(int p_device, int p_flags) {
return ERR_CANT_CREATE;
}
+ if (use_adb_over_usb) {
+
+ args.clear();
+ args.push_back("reverse");
+ args.push_back("--remove-all");
+ err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv);
+
+ int port = Globals::get_singleton()->get("debug/debug_port");
+ args.clear();
+ args.push_back("reverse");
+ args.push_back("tcp:"+itos(port));
+ args.push_back("tcp:"+itos(port));
+
+ err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv);
+ print_line("Reverse result: "+itos(rv));
+
+ int fs_port = EditorSettings::get_singleton()->get("file_server/port");
+
+ args.clear();
+ args.push_back("reverse");
+ args.push_back("tcp:"+itos(fs_port));
+ args.push_back("tcp:"+itos(fs_port));
+
+ err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv);
+ print_line("Reverse result2: "+itos(rv));
+
+ }
+
+
ep.step("Running on Device..",3);
args.clear();
args.push_back("-s");
@@ -1563,7 +1605,7 @@ Error EditorExportPlatformAndroid::run(int p_device, int p_flags) {
args.push_back("-a");
args.push_back("android.intent.action.MAIN");
args.push_back("-n");
- args.push_back(get_package_name()+"/com.android.godot.Godot");
+ args.push_back(get_package_name()+"/org.godotengine.godot.Godot");
err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv);
if (err || rv!=0) {
@@ -1659,10 +1701,7 @@ bool EditorExportPlatformAndroid::can_export(String *r_error) const {
err+="Debug Keystore not configured in editor settings.\n";
}
-
- String exe_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
-
- if (!FileAccess::exists(exe_path+"android_debug.apk") || !FileAccess::exists(exe_path+"android_release.apk")) {
+ if (!exists_export_template("android_debug.apk") || !exists_export_template("android_release.apk")) {
valid=false;
err+="No export templates found.\nDownload and install export templates.\n";
}
@@ -1721,6 +1760,7 @@ void register_android_exporter() {
//EDITOR_DEF("android/release_username","");
//EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"android/release_keystore",PROPERTY_HINT_GLOBAL_FILE,"*.keystore"));
EDITOR_DEF("android/timestamping_authority_url","");
+ EDITOR_DEF("android/use_remote_debug_over_adb",false);
Ref<EditorExportPlatformAndroid> exporter = Ref<EditorExportPlatformAndroid>( memnew(EditorExportPlatformAndroid) );
EditorImportExport::get_singleton()->add_export_platform(exporter);
diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp
index ff70d5ae76..7a038cca64 100644
--- a/platform/android/file_access_android.cpp
+++ b/platform/android/file_access_android.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -132,12 +132,18 @@ int FileAccessAndroid::get_buffer(uint8_t *p_dst, int p_length) const {
off_t r = AAsset_read(a,p_dst,p_length);
+
+ if (pos+p_length >len ) {
+ eof=true;
+ }
+
if (r>=0) {
+
pos+=r;
if (pos>len) {
pos=len;
- eof=true;
}
+
}
return r;
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index 506c2c023f..3fcd7836c3 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/android/file_access_jandroid.cpp b/platform/android/file_access_jandroid.cpp
index be38d806b2..b1b758edb1 100644
--- a/platform/android/file_access_jandroid.cpp
+++ b/platform/android/file_access_jandroid.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/android/file_access_jandroid.h b/platform/android/file_access_jandroid.h
index 13ac4e17b8..d576af93d6 100644
--- a/platform/android/file_access_jandroid.h
+++ b/platform/android/file_access_jandroid.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/android/godot_android.cpp b/platform/android/godot_android.cpp
index 388ff06c10..f9feb3481f 100644
--- a/platform/android/godot_android.cpp
+++ b/platform/android/godot_android.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -50,9 +50,9 @@
extern "C" {
- JNIEXPORT void JNICALL Java_com_android_godot_Godot_registerSingleton(JNIEnv * env, jobject obj, jstring name,jobject p_object);
- JNIEXPORT void JNICALL Java_com_android_godot_Godot_registerMethod(JNIEnv * env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args);
- JNIEXPORT jstring JNICALL Java_com_android_godot_Godot_getGlobal(JNIEnv * env, jobject obj, jstring path);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerSingleton(JNIEnv * env, jobject obj, jstring name,jobject p_object);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerMethod(JNIEnv * env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args);
+ JNIEXPORT jstring JNICALL Java_org_godotengine_godot_Godot_getGlobal(JNIEnv * env, jobject obj, jstring path);
};
class JNISingleton : public Object {
@@ -671,12 +671,12 @@ static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
static JNINativeMethod methods[] = {
- {"registerSingleton", "(Ljava/lang/String;Ljava/lang/Object;)V",(void *)&Java_com_android_godot_Godot_registerSingleton},
- {"registerMethod", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V",(void *)&Java_com_android_godot_Godot_registerMethod},
- {"getGlobal", "(Ljava/lang/String;)Ljava/lang/String;", (void *)&Java_com_android_godot_Godot_getGlobal},
+ {"registerSingleton", "(Ljava/lang/String;Ljava/lang/Object;)V",(void *)&Java_org_godotengine_godot_Godot_registerSingleton},
+ {"registerMethod", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V",(void *)&Java_org_godotengine_godot_Godot_registerMethod},
+ {"getGlobal", "(Ljava/lang/String;)Ljava/lang/String;", (void *)&Java_org_godotengine_godot_Godot_getGlobal},
};
- jstring gstrClassName = engine->jni->NewStringUTF("com/android/godot/Godot");
+ jstring gstrClassName = engine->jni->NewStringUTF("org/godotengine/godot/Godot");
jclass GodotClass = (jclass)engine->jni->CallObjectMethod(cls, findClass, gstrClassName);
__android_log_print(ANDROID_LOG_INFO,"godot","godot ****^*^*?^*^*class data %x",GodotClass);
@@ -692,7 +692,7 @@ static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
jclass singletonClass = (jclass)engine->jni->CallObjectMethod(cls, findClass, strClassName);
__android_log_print(ANDROID_LOG_INFO,"godot","****^*^*?^*^*class data %x",singletonClass);
- jmethodID initialize = engine->jni->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lcom/android/godot/Godot$SingletonBase;");
+ jmethodID initialize = engine->jni->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lorg/godotengine/godot/Godot$SingletonBase;");
jobject obj = engine->jni->CallStaticObjectMethod(singletonClass,initialize,app->activity->clazz);
@@ -863,7 +863,7 @@ void android_main(struct android_app* state) {
-JNIEXPORT void JNICALL Java_com_android_godot_Godot_registerSingleton(JNIEnv * env, jobject obj, jstring name,jobject p_object){
+JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerSingleton(JNIEnv * env, jobject obj, jstring name,jobject p_object){
String singname = env->GetStringUTFChars( name, NULL );
JNISingleton *s = memnew( JNISingleton );
@@ -938,7 +938,7 @@ static const char* get_jni_sig(const String& p_type) {
return "";
}
-JNIEXPORT jstring JNICALL Java_com_android_godot_Godot_getGlobal(JNIEnv * env, jobject obj, jstring path) {
+JNIEXPORT jstring JNICALL Java_org_godotengine_godot_Godot_getGlobal(JNIEnv * env, jobject obj, jstring path) {
String js = env->GetStringUTFChars( path, NULL );
@@ -949,7 +949,7 @@ JNIEXPORT jstring JNICALL Java_com_android_godot_Godot_getGlobal(JNIEnv * env, j
-JNIEXPORT void JNICALL Java_com_android_godot_Godot_registerMethod(JNIEnv * env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args){
+JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerMethod(JNIEnv * env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args){
String singname = env->GetStringUTFChars( sname, NULL );
diff --git a/platform/android/java/aidl/com/android/vending/billing/IInAppBillingService.aidl b/platform/android/java/aidl/com/android/vending/billing/IInAppBillingService.aidl
new file mode 100644
index 0000000000..2a492f7845
--- /dev/null
+++ b/platform/android/java/aidl/com/android/vending/billing/IInAppBillingService.aidl
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.vending.billing;
+
+import android.os.Bundle;
+
+/**
+ * InAppBillingService is the service that provides in-app billing version 3 and beyond.
+ * This service provides the following features:
+ * 1. Provides a new API to get details of in-app items published for the app including
+ * price, type, title and description.
+ * 2. The purchase flow is synchronous and purchase information is available immediately
+ * after it completes.
+ * 3. Purchase information of in-app purchases is maintained within the Google Play system
+ * till the purchase is consumed.
+ * 4. An API to consume a purchase of an inapp item. All purchases of one-time
+ * in-app items are consumable and thereafter can be purchased again.
+ * 5. An API to get current purchases of the user immediately. This will not contain any
+ * consumed purchases.
+ *
+ * All calls will give a response code with the following possible values
+ * RESULT_OK = 0 - success
+ * RESULT_USER_CANCELED = 1 - user pressed back or canceled a dialog
+ * RESULT_BILLING_UNAVAILABLE = 3 - this billing API version is not supported for the type requested
+ * RESULT_ITEM_UNAVAILABLE = 4 - requested SKU is not available for purchase
+ * RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API
+ * RESULT_ERROR = 6 - Fatal error during the API action
+ * RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned
+ * RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned
+ */
+interface IInAppBillingService {
+ /**
+ * Checks support for the requested billing API version, package and in-app type.
+ * Minimum API version supported by this interface is 3.
+ * @param apiVersion the billing version which the app is using
+ * @param packageName the package name of the calling app
+ * @param type type of the in-app item being purchased "inapp" for one-time purchases
+ * and "subs" for subscription.
+ * @return RESULT_OK(0) on success, corresponding result code on failures
+ */
+ int isBillingSupported(int apiVersion, String packageName, String type);
+
+ /**
+ * Provides details of a list of SKUs
+ * Given a list of SKUs of a valid type in the skusBundle, this returns a bundle
+ * with a list JSON strings containing the productId, price, title and description.
+ * This API can be called with a maximum of 20 SKUs.
+ * @param apiVersion billing API version that the Third-party is using
+ * @param packageName the package name of the calling app
+ * @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST"
+ * @return Bundle containing the following key-value pairs
+ * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
+ * failure as listed above.
+ * "DETAILS_LIST" with a StringArrayList containing purchase information
+ * in JSON format similar to:
+ * '{ "productId" : "exampleSku", "type" : "inapp", "price" : "$5.00",
+ * "title : "Example Title", "description" : "This is an example description" }'
+ */
+ Bundle getSkuDetails(int apiVersion, String packageName, String type, in Bundle skusBundle);
+
+ /**
+ * Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU,
+ * the type, a unique purchase token and an optional developer payload.
+ * @param apiVersion billing API version that the app is using
+ * @param packageName package name of the calling app
+ * @param sku the SKU of the in-app item as published in the developer console
+ * @param type the type of the in-app item ("inapp" for one-time purchases
+ * and "subs" for subscription).
+ * @param developerPayload optional argument to be sent back with the purchase information
+ * @return Bundle containing the following key-value pairs
+ * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
+ * failure as listed above.
+ * "BUY_INTENT" - PendingIntent to start the purchase flow
+ *
+ * The Pending intent should be launched with startIntentSenderForResult. When purchase flow
+ * has completed, the onActivityResult() will give a resultCode of OK or CANCELED.
+ * If the purchase is successful, the result data will contain the following key-value pairs
+ * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
+ * failure as listed above.
+ * "INAPP_PURCHASE_DATA" - String in JSON format similar to
+ * '{"orderId":"12999763169054705758.1371079406387615",
+ * "packageName":"com.example.app",
+ * "productId":"exampleSku",
+ * "purchaseTime":1345678900000,
+ * "purchaseToken" : "122333444455555",
+ * "developerPayload":"example developer payload" }'
+ * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that
+ * was signed with the private key of the developer
+ * TODO: change this to app-specific keys.
+ */
+ Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type,
+ String developerPayload);
+
+ /**
+ * Returns the current SKUs owned by the user of the type and package name specified along with
+ * purchase information and a signature of the data to be validated.
+ * This will return all SKUs that have been purchased in V3 and managed items purchased using
+ * V1 and V2 that have not been consumed.
+ * @param apiVersion billing API version that the app is using
+ * @param packageName package name of the calling app
+ * @param type the type of the in-app items being requested
+ * ("inapp" for one-time purchases and "subs" for subscription).
+ * @param continuationToken to be set as null for the first call, if the number of owned
+ * skus are too many, a continuationToken is returned in the response bundle.
+ * This method can be called again with the continuation token to get the next set of
+ * owned skus.
+ * @return Bundle containing the following key-value pairs
+ * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
+ * failure as listed above.
+ * "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs
+ * "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information
+ * "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures
+ * of the purchase information
+ * "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the
+ * next set of in-app purchases. Only set if the
+ * user has more owned skus than the current list.
+ */
+ Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken);
+
+ /**
+ * Consume the last purchase of the given SKU. This will result in this item being removed
+ * from all subsequent responses to getPurchases() and allow re-purchase of this item.
+ * @param apiVersion billing API version that the app is using
+ * @param packageName package name of the calling app
+ * @param purchaseToken token in the purchase information JSON that identifies the purchase
+ * to be consumed
+ * @return 0 if consumption succeeded. Appropriate error values for failures.
+ */
+ int consumePurchase(int apiVersion, String packageName, String purchaseToken);
+}
diff --git a/platform/android/java/ant.properties b/platform/android/java/ant.properties
deleted file mode 100644
index b0971e891e..0000000000
--- a/platform/android/java/ant.properties
+++ /dev/null
@@ -1,17 +0,0 @@
-# This file is used to override default values used by the Ant build system.
-#
-# This file must be checked into Version Control Systems, as it is
-# integral to the build system of your project.
-
-# This file is only used by the Ant script.
-
-# You can use this to override default values such as
-# 'source.dir' for the location of your java source folder and
-# 'out.dir' for the location of your output folder.
-
-# You can also use it define how the release builds are signed by declaring
-# the following properties:
-# 'key.store' for the location of your keystore and
-# 'key.alias' for the name of the key to use.
-# The password will be asked during the build when you use the 'release' target.
-
diff --git a/platform/android/java/build.properties b/platform/android/java/build.properties
deleted file mode 100644
index ee52d86d94..0000000000
--- a/platform/android/java/build.properties
+++ /dev/null
@@ -1,17 +0,0 @@
-# This file is used to override default values used by the Ant build system.
-#
-# This file must be checked in Version Control Systems, as it is
-# integral to the build system of your project.
-
-# This file is only used by the Ant script.
-
-# You can use this to override default values such as
-# 'source.dir' for the location of your java source folder and
-# 'out.dir' for the location of your output folder.
-
-# You can also use it define how the release builds are signed by declaring
-# the following properties:
-# 'key.store' for the location of your keystore and
-# 'key.alias' for the name of the key to use.
-# The password will be asked during the build when you use the 'release' target.
-
diff --git a/platform/android/java/build.xml b/platform/android/java/build.xml
deleted file mode 100644
index 424e2827dc..0000000000
--- a/platform/android/java/build.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="Godot" default="help">
-
- <!-- The local.properties file is created and updated by the 'android' tool.
- It contains the path to the SDK. It should *NOT* be checked into
- Version Control Systems. -->
- <property file="local.properties" />
-
- <!-- The ant.properties file can be created by you. It is only edited by the
- 'android' tool to add properties to it.
- This is the place to change some Ant specific build properties.
- Here are some properties you may want to change/update:
-
- source.dir
- The name of the source directory. Default is 'src'.
- out.dir
- The name of the output directory. Default is 'bin'.
-
- For other overridable properties, look at the beginning of the rules
- files in the SDK, at tools/ant/build.xml
-
- Properties related to the SDK location or the project target should
- be updated using the 'android' tool with the 'update' action.
-
- This file is an integral part of the build system for your
- application and should be checked into Version Control Systems.
-
- -->
- <property file="ant.properties" />
-
- <!-- if sdk.dir was not set from one of the property file, then
- get it from the ANDROID_HOME env var.
- This must be done before we load project.properties since
- the proguard config can use sdk.dir -->
- <property environment="env" />
- <condition property="sdk.dir" value="${env.ANDROID_HOME}">
- <isset property="env.ANDROID_HOME" />
- </condition>
-
- <!-- The project.properties file is created and updated by the 'android'
- tool, as well as ADT.
-
- This contains project specific properties such as project target, and library
- dependencies. Lower level build properties are stored in ant.properties
- (or in .classpath for Eclipse projects).
-
- This file is an integral part of the build system for your
- application and should be checked into Version Control Systems. -->
- <loadproperties srcFile="project.properties" />
-
- <!-- quick check on sdk.dir -->
- <fail
- message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
- unless="sdk.dir"
- />
-
- <!--
- Import per project custom build rules if present at the root of the project.
- This is the place to put custom intermediary targets such as:
- -pre-build
- -pre-compile
- -post-compile (This is typically used for code obfuscation.
- Compiled code location: ${out.classes.absolute.dir}
- If this is not done in place, override ${out.dex.input.absolute.dir})
- -post-package
- -post-build
- -pre-clean
- -->
- <import file="custom_rules.xml" optional="true" />
-
- <!-- Import the actual build file.
-
- To customize existing targets, there are two options:
- - Customize only one target:
- - copy/paste the target into this file, *before* the
- <import> task.
- - customize it to your needs.
- - Customize the whole content of build.xml
- - copy/paste the content of the rules files (minus the top node)
- into this file, replacing the <import> task.
- - customize to your needs.
-
- ***********************
- ****** IMPORTANT ******
- ***********************
- In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
- in order to avoid having your file be overridden by tools such as "android update project"
- -->
- <!-- version-tag: 1 -->
- <import file="${sdk.dir}/tools/ant/build.xml" />
-
-</project>
diff --git a/platform/android/java/default.properties b/platform/android/java/default.properties
deleted file mode 100644
index e2e8061f26..0000000000
--- a/platform/android/java/default.properties
+++ /dev/null
@@ -1,11 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system use,
-# "build.properties", and override values to adapt the script to your
-# project structure.
-
-# Project target.
-target=android-8
diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.jar b/platform/android/java/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000..8c0fb64a86
--- /dev/null
+++ b/platform/android/java/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.properties b/platform/android/java/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000..0c71e760dc
--- /dev/null
+++ b/platform/android/java/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
diff --git a/platform/android/java/gradlew b/platform/android/java/gradlew
new file mode 100755
index 0000000000..91a7e269e1
--- /dev/null
+++ b/platform/android/java/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/platform/android/java/gradlew.bat b/platform/android/java/gradlew.bat
new file mode 100644
index 0000000000..aec99730b4
--- /dev/null
+++ b/platform/android/java/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/platform/android/java/my-release-key.keystore b/platform/android/java/my-release-key.keystore
deleted file mode 100644
index 410cccd865..0000000000
--- a/platform/android/java/my-release-key.keystore
+++ /dev/null
Binary files differ
diff --git a/platform/android/java/proguard-project.txt b/platform/android/java/proguard-project.txt
deleted file mode 100644
index f2fe1559a2..0000000000
--- a/platform/android/java/proguard-project.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-# To enable ProGuard in your project, edit project.properties
-# to define the proguard.config property as described in that file.
-#
-# Add project specific ProGuard rules here.
-# By default, the flags in this file are appended to flags specified
-# in ${sdk.dir}/tools/proguard/proguard-android.txt
-# You can edit the include path and order by changing the ProGuard
-# include property in project.properties.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# Add any project specific keep options here:
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
diff --git a/platform/android/java/proguard.cfg b/platform/android/java/proguard.cfg
deleted file mode 100644
index 12dd0392c0..0000000000
--- a/platform/android/java/proguard.cfg
+++ /dev/null
@@ -1,36 +0,0 @@
--optimizationpasses 5
--dontusemixedcaseclassnames
--dontskipnonpubliclibraryclasses
--dontpreverify
--verbose
--optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-
--keep public class * extends android.app.Activity
--keep public class * extends android.app.Application
--keep public class * extends android.app.Service
--keep public class * extends android.content.BroadcastReceiver
--keep public class * extends android.content.ContentProvider
--keep public class * extends android.app.backup.BackupAgentHelper
--keep public class * extends android.preference.Preference
--keep public class com.android.vending.licensing.ILicensingService
-
--keepclasseswithmembernames class * {
- native <methods>;
-}
-
--keepclasseswithmembernames class * {
- public <init>(android.content.Context, android.util.AttributeSet);
-}
-
--keepclasseswithmembernames class * {
- public <init>(android.content.Context, android.util.AttributeSet, int);
-}
-
--keepclassmembers enum * {
- public static **[] values();
- public static ** valueOf(java.lang.String);
-}
-
--keep class * implements android.os.Parcelable {
- public static final android.os.Parcelable$Creator *;
-}
diff --git a/platform/android/libs/apk_expansion/res/drawable-hdpi/notify_panel_notification_icon_bg.png b/platform/android/java/res/drawable-hdpi/notify_panel_notification_icon_bg.png
index f5b762ecf3..f5b762ecf3 100644
--- a/platform/android/libs/apk_expansion/res/drawable-hdpi/notify_panel_notification_icon_bg.png
+++ b/platform/android/java/res/drawable-hdpi/notify_panel_notification_icon_bg.png
Binary files differ
diff --git a/platform/android/libs/apk_expansion/res/drawable-mdpi/notify_panel_notification_icon_bg.png b/platform/android/java/res/drawable-mdpi/notify_panel_notification_icon_bg.png
index 9ecb8af06c..9ecb8af06c 100644
--- a/platform/android/libs/apk_expansion/res/drawable-mdpi/notify_panel_notification_icon_bg.png
+++ b/platform/android/java/res/drawable-mdpi/notify_panel_notification_icon_bg.png
Binary files differ
diff --git a/platform/android/libs/apk_expansion/res/layout/status_bar_ongoing_event_progress_bar.xml b/platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml
index 23bac02294..23bac02294 100644
--- a/platform/android/libs/apk_expansion/res/layout/status_bar_ongoing_event_progress_bar.xml
+++ b/platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml
diff --git a/platform/android/libs/apk_expansion/res/values-v11/styles.xml b/platform/android/java/res/values-v11/styles.xml
index f2013bc0bf..f2013bc0bf 100644
--- a/platform/android/libs/apk_expansion/res/values-v11/styles.xml
+++ b/platform/android/java/res/values-v11/styles.xml
diff --git a/platform/android/libs/apk_expansion/res/values-v9/styles.xml b/platform/android/java/res/values-v9/styles.xml
index 736e77a5d6..736e77a5d6 100644
--- a/platform/android/libs/apk_expansion/res/values-v9/styles.xml
+++ b/platform/android/java/res/values-v9/styles.xml
diff --git a/platform/android/java/res/values/strings.xml b/platform/android/java/res/values/strings.xml
index 49ebcc06f9..e1dbdfc062 100644
--- a/platform/android/java/res/values/strings.xml
+++ b/platform/android/java/res/values/strings.xml
@@ -14,4 +14,44 @@
<string name="text_button_resume">Resume Download</string>
<string name="text_button_cancel">Cancel</string>
<string name="text_button_cancel_verify">Cancel Verification</string>
-</resources>
+
+ <!-- APK Expansion Strings -->
+
+ <!-- When a download completes, a notification is displayed, and this
+ string is used to indicate that the download successfully completed.
+ Note that such a download could have been initiated by a variety of
+ applications, including (but not limited to) the browser, an email
+ application, a content marketplace. -->
+ <string name="notification_download_complete">Download complete</string>
+
+ <!-- When a download completes, a notification is displayed, and this
+ string is used to indicate that the download failed.
+ Note that such a download could have been initiated by a variety of
+ applications, including (but not limited to) the browser, an email
+ application, a content marketplace. -->
+ <string name="notification_download_failed">Download unsuccessful</string>
+
+
+ <string name="state_unknown">Starting..."</string>
+ <string name="state_idle">Waiting for download to start</string>
+ <string name="state_fetching_url">Looking for resources to download</string>
+ <string name="state_connecting">Connecting to the download server</string>
+ <string name="state_downloading">Downloading resources</string>
+ <string name="state_completed">Download finished</string>
+ <string name="state_paused_network_unavailable">Download paused because no network is available</string>
+ <string name="state_paused_network_setup_failure">Download paused. Test a website in browser</string>
+ <string name="state_paused_by_request">Download paused</string>
+ <string name="state_paused_wifi_unavailable">Download paused because wifi is unavailable</string>
+ <string name="state_paused_wifi_disabled">Download paused because wifi is disabled</string>
+ <string name="state_paused_roaming">Download paused because you are roaming</string>
+ <string name="state_paused_sdcard_unavailable">Download paused because the external storage is unavailable</string>
+ <string name="state_failed_unlicensed">Download failed because you may not have purchased this app</string>
+ <string name="state_failed_fetching_url">Download failed because the resources could not be found</string>
+ <string name="state_failed_sdcard_full">Download failed because the external storage is full</string>
+ <string name="state_failed_cancelled">Download cancelled</string>
+ <string name="state_failed">Download failed</string>
+
+ <string name="kilobytes_per_second">%1$s KB/s</string>
+ <string name="time_remaining">Time remaining: %1$s</string>
+ <string name="time_remaining_notification">%1$s left</string>
+</resources> \ No newline at end of file
diff --git a/platform/android/libs/apk_expansion/res/values/styles.xml b/platform/android/java/res/values/styles.xml
index a442f61e7e..a442f61e7e 100644
--- a/platform/android/libs/apk_expansion/res/values/styles.xml
+++ b/platform/android/java/res/values/styles.xml
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/AESObfuscator.java b/platform/android/java/src/com/android/vending/licensing/AESObfuscator.java
index ee12c68deb..ee12c68deb 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/AESObfuscator.java
+++ b/platform/android/java/src/com/android/vending/licensing/AESObfuscator.java
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/APKExpansionPolicy.java b/platform/android/java/src/com/android/vending/licensing/APKExpansionPolicy.java
index 17cc7a7cfd..17cc7a7cfd 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/APKExpansionPolicy.java
+++ b/platform/android/java/src/com/android/vending/licensing/APKExpansionPolicy.java
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/DeviceLimiter.java b/platform/android/java/src/com/android/vending/licensing/DeviceLimiter.java
index e5c5e2d7ca..e5c5e2d7ca 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/DeviceLimiter.java
+++ b/platform/android/java/src/com/android/vending/licensing/DeviceLimiter.java
diff --git a/platform/android/libs/play_licensing/aidl/ILicenseResultListener.aidl b/platform/android/java/src/com/android/vending/licensing/ILicenseResultListener.aidl
index c816558afc..c816558afc 100644
--- a/platform/android/libs/play_licensing/aidl/ILicenseResultListener.aidl
+++ b/platform/android/java/src/com/android/vending/licensing/ILicenseResultListener.aidl
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ILicenseResultListener.java b/platform/android/java/src/com/android/vending/licensing/ILicenseResultListener.java
index d90d6eac7b..d90d6eac7b 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ILicenseResultListener.java
+++ b/platform/android/java/src/com/android/vending/licensing/ILicenseResultListener.java
diff --git a/platform/android/libs/play_licensing/aidl/ILicensingService.aidl b/platform/android/java/src/com/android/vending/licensing/ILicensingService.aidl
index 664510ce0c..664510ce0c 100644
--- a/platform/android/libs/play_licensing/aidl/ILicensingService.aidl
+++ b/platform/android/java/src/com/android/vending/licensing/ILicensingService.aidl
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ILicensingService.java b/platform/android/java/src/com/android/vending/licensing/ILicensingService.java
index 95599544e4..95599544e4 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ILicensingService.java
+++ b/platform/android/java/src/com/android/vending/licensing/ILicensingService.java
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/LicenseChecker.java b/platform/android/java/src/com/android/vending/licensing/LicenseChecker.java
index 8b53545e61..0b1c4b6cca 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/LicenseChecker.java
+++ b/platform/android/java/src/com/android/vending/licensing/LicenseChecker.java
@@ -63,7 +63,7 @@ public class LicenseChecker implements ServiceConnection {
private static final int TIMEOUT_MS = 10 * 1000;
private static final SecureRandom RANDOM = new SecureRandom();
- private static final boolean DEBUG_LICENSE_ERROR = true;
+ private static final boolean DEBUG_LICENSE_ERROR = false;
private ILicensingService mService;
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/LicenseCheckerCallback.java b/platform/android/java/src/com/android/vending/licensing/LicenseCheckerCallback.java
index b250a7147b..b250a7147b 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/LicenseCheckerCallback.java
+++ b/platform/android/java/src/com/android/vending/licensing/LicenseCheckerCallback.java
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/LicenseValidator.java b/platform/android/java/src/com/android/vending/licensing/LicenseValidator.java
index 61d3c7e79e..61d3c7e79e 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/LicenseValidator.java
+++ b/platform/android/java/src/com/android/vending/licensing/LicenseValidator.java
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/NullDeviceLimiter.java b/platform/android/java/src/com/android/vending/licensing/NullDeviceLimiter.java
index d87af3153f..d87af3153f 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/NullDeviceLimiter.java
+++ b/platform/android/java/src/com/android/vending/licensing/NullDeviceLimiter.java
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/Obfuscator.java b/platform/android/java/src/com/android/vending/licensing/Obfuscator.java
index b5d510d72d..b5d510d72d 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/Obfuscator.java
+++ b/platform/android/java/src/com/android/vending/licensing/Obfuscator.java
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/Policy.java b/platform/android/java/src/com/android/vending/licensing/Policy.java
index fa267fc71a..fa267fc71a 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/Policy.java
+++ b/platform/android/java/src/com/android/vending/licensing/Policy.java
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/PreferenceObfuscator.java b/platform/android/java/src/com/android/vending/licensing/PreferenceObfuscator.java
index 7c42bfc28a..7c42bfc28a 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/PreferenceObfuscator.java
+++ b/platform/android/java/src/com/android/vending/licensing/PreferenceObfuscator.java
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ResponseData.java b/platform/android/java/src/com/android/vending/licensing/ResponseData.java
index 2adef3709e..2adef3709e 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ResponseData.java
+++ b/platform/android/java/src/com/android/vending/licensing/ResponseData.java
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ServerManagedPolicy.java b/platform/android/java/src/com/android/vending/licensing/ServerManagedPolicy.java
index fbf8cf6d00..fbf8cf6d00 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ServerManagedPolicy.java
+++ b/platform/android/java/src/com/android/vending/licensing/ServerManagedPolicy.java
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/StrictPolicy.java b/platform/android/java/src/com/android/vending/licensing/StrictPolicy.java
index d8d83b4e4b..d8d83b4e4b 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/StrictPolicy.java
+++ b/platform/android/java/src/com/android/vending/licensing/StrictPolicy.java
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ValidationException.java b/platform/android/java/src/com/android/vending/licensing/ValidationException.java
index ee4df47c68..ee4df47c68 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/ValidationException.java
+++ b/platform/android/java/src/com/android/vending/licensing/ValidationException.java
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/util/Base64.java b/platform/android/java/src/com/android/vending/licensing/util/Base64.java
index a0d2779af2..a0d2779af2 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/util/Base64.java
+++ b/platform/android/java/src/com/android/vending/licensing/util/Base64.java
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/util/Base64DecoderException.java b/platform/android/java/src/com/android/vending/licensing/util/Base64DecoderException.java
index 1aef1b54b8..1aef1b54b8 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/util/Base64DecoderException.java
+++ b/platform/android/java/src/com/android/vending/licensing/util/Base64DecoderException.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/Constants.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/Constants.java
index ff2c6f535a..ff2c6f535a 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/Constants.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/Constants.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java
index 9cb294d721..9cb294d721 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java
index 2201751254..2201751254 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java
index 054eaa9895..054eaa9895 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/Helpers.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/Helpers.java
index 1e84e54a0f..b4c28d36e7 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/Helpers.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/Helpers.java
@@ -16,7 +16,7 @@
package com.google.android.vending.expansion.downloader;
-import com.android.vending.expansion.downloader.R;
+import com.godot.game.R;
import android.content.Context;
import android.os.Environment;
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java
index b8511a62a0..b8511a62a0 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/IDownloaderService.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/IDownloaderService.java
index 4789afe19c..4789afe19c 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/IDownloaderService.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/IDownloaderService.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/IStub.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/IStub.java
index d5bc3a843e..d5bc3a843e 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/IStub.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/IStub.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/SystemFacade.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/SystemFacade.java
index 12edd97ab2..12edd97ab2 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/SystemFacade.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/SystemFacade.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/AndroidHttpClient.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/AndroidHttpClient.java
index 4667acce67..4667acce67 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/AndroidHttpClient.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/AndroidHttpClient.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java
index b77af7e085..b77af7e085 100755
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/CustomNotificationFactory.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/CustomNotificationFactory.java
index 9a0ca02122..9a0ca02122 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/CustomNotificationFactory.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/CustomNotificationFactory.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java
index 45111b16a3..45111b16a3 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java
index eef205d7b7..d82b658bc3 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java
@@ -16,7 +16,7 @@
package com.google.android.vending.expansion.downloader.impl;
-import com.android.vending.expansion.downloader.R;
+import com.godot.game.R;
import com.google.android.vending.expansion.downloader.DownloadProgressInfo;
import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller;
import com.google.android.vending.expansion.downloader.Helpers;
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java
index 056d1eca0b..056d1eca0b 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java
index 627bf3eedd..627bf3eedd 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java
index 250299c400..250299c400 100755
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java
index 3f440e9893..3f440e9893 100644
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/V14CustomNotification.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/V14CustomNotification.java
index e736603e2a..2e049a4d47 100644
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/V14CustomNotification.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/V14CustomNotification.java
@@ -16,7 +16,7 @@
package com.google.android.vending.expansion.downloader.impl;
-import com.android.vending.expansion.downloader.R;
+import com.godot.game.R;
import com.google.android.vending.expansion.downloader.Helpers;
import android.app.Notification;
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/V3CustomNotification.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/V3CustomNotification.java
index e3666e05b9..94e21de7ca 100644
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/V3CustomNotification.java
+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/V3CustomNotification.java
@@ -16,7 +16,7 @@
package com.google.android.vending.expansion.downloader.impl;
-import com.android.vending.expansion.downloader.R;
+import com.godot.game.R;
import com.google.android.vending.expansion.downloader.Helpers;
import android.app.Notification;
diff --git a/platform/android/java/src/com/android/godot/Dictionary.java b/platform/android/java/src/org/godotengine/godot/Dictionary.java
index 4ed12f5818..34051c4bb8 100644
--- a/platform/android/java/src/com/android/godot/Dictionary.java
+++ b/platform/android/java/src/org/godotengine/godot/Dictionary.java
@@ -26,7 +26,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-package com.android.godot;
+package org.godotengine.godot;
import java.util.HashMap;
import java.util.Set;
diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java
index 4c5a313576..1f208f8fb6 100644
--- a/platform/android/java/src/com/android/godot/Godot.java
+++ b/platform/android/java/src/org/godotengine/godot/Godot.java
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,7 +26,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-package com.android.godot;
+package org.godotengine.godot;
import android.R;
import android.app.Activity;
@@ -60,14 +60,14 @@ import java.lang.reflect.Method;
import java.util.List;
import java.util.ArrayList;
-import com.android.godot.payments.PaymentsManager;
+import org.godotengine.godot.payments.PaymentsManager;
import java.io.IOException;
import android.provider.Settings.Secure;
import android.widget.FrameLayout;
-import com.android.godot.input.*;
+import org.godotengine.godot.input.*;
import java.io.InputStream;
import javax.microedition.khronos.opengles.GL10;
@@ -113,6 +113,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
private boolean use_immersive=false;
private boolean mStatePaused;
private int mState;
+ private boolean keep_screen_on=true;
private void setState(int newState) {
if (mState != newState) {
@@ -259,7 +260,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
mView = new GodotView(getApplication(),io,use_gl2,use_32_bits, this);
layout.addView(mView,new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
- mView.setKeepScreenOn(true);
+ setKeepScreenOn(GodotLib.getGlobal("display/keep_screen_on").equals("True"));
edittext.setView(mView);
io.setEdit(edittext);
@@ -270,7 +271,19 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
layout.addView(adLayout);
}
-
+
+ public void setKeepScreenOn(final boolean p_enabled) {
+ keep_screen_on = p_enabled;
+ if (mView != null){
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mView.setKeepScreenOn(p_enabled);
+ }
+ });
+ }
+ }
+
private static Godot _self;
public static Godot getInstance(){
@@ -385,8 +398,8 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
super.onCreate(icicle);
_self = this;
Window window = getWindow();
- window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
- | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ //window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
//check for apk expansion API
diff --git a/platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java b/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java
index e82c3eb0fe..b602f4757c 100644
--- a/platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java
@@ -1,4 +1,4 @@
-package com.android.godot;
+package org.godotengine.godot;
import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller;
diff --git a/platform/android/java/src/com/android/godot/GodotDownloaderService.java b/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java
index 2657edc1d2..6735d387f3 100644
--- a/platform/android/java/src/com/android/godot/GodotDownloaderService.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java
@@ -1,4 +1,4 @@
-package com.android.godot;
+package org.godotengine.godot;
import android.content.Context;
import android.content.SharedPreferences;
diff --git a/platform/android/java/src/com/android/godot/GodotIO.java b/platform/android/java/src/org/godotengine/godot/GodotIO.java
index a7dc0c2f75..3e6919c2ad 100644
--- a/platform/android/java/src/com/android/godot/GodotIO.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotIO.java
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,7 +26,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-package com.android.godot;
+package org.godotengine.godot;
import java.util.HashMap;
import java.util.Locale;
import android.net.Uri;
@@ -47,7 +47,7 @@ import android.media.*;
import android.hardware.*;
import android.content.*;
import android.content.pm.ActivityInfo;
-import com.android.godot.input.*;
+import org.godotengine.godot.input.*;
//android.os.Build
// Wrapper for native library
diff --git a/platform/android/java/src/com/android/godot/GodotLib.java b/platform/android/java/src/org/godotengine/godot/GodotLib.java
index f099e0feff..aef6591864 100644
--- a/platform/android/java/src/com/android/godot/GodotLib.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotLib.java
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,7 +26,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-package com.android.godot;
+package org.godotengine.godot;
// Wrapper for native library
@@ -46,7 +46,7 @@ public class GodotLib {
public static native void initialize(Godot p_instance,boolean need_reload_hook,String[] p_cmdline,Object p_asset_manager);
public static native void resize(int width, int height,boolean reload);
- public static native void newcontext();
+ public static native void newcontext(boolean p_32_bits);
public static native void quit();
public static native void step();
public static native void touch(int what,int pointer,int howmany, int[] arr);
diff --git a/platform/android/java/src/com/android/godot/GodotPaymentV3.java b/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java
index 0799e1e83d..6bec49410d 100644
--- a/platform/android/java/src/com/android/godot/GodotPaymentV3.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java
@@ -1,6 +1,6 @@
-package com.android.godot;
+package org.godotengine.godot;
-import com.android.godot.Dictionary;
+import org.godotengine.godot.Dictionary;
import android.app.Activity;
import android.util.Log;
diff --git a/platform/android/java/src/com/android/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java
index 1a84923065..492eb4cb54 100644
--- a/platform/android/java/src/com/android/godot/GodotView.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotView.java
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,7 +26,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-package com.android.godot;
+package org.godotengine.godot;
import android.content.Context;
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
@@ -425,6 +425,7 @@ public class GodotView extends GLSurfaceView {
if (ec == null) {
Log.w(TAG, "Trying ConfigChooser fallback");
ec = fallback.chooseConfig(egl, display, configs);
+ use_32=false;
}
return ec;
}
@@ -654,7 +655,7 @@ public class GodotView extends GLSurfaceView {
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
- GodotLib.newcontext();
+ GodotLib.newcontext(use_32);
}
}
}
diff --git a/platform/android/java/src/com/android/godot/input/GodotEditText.java b/platform/android/java/src/org/godotengine/godot/input/GodotEditText.java
index 5898e95423..c8ffa74ecd 100644
--- a/platform/android/java/src/com/android/godot/input/GodotEditText.java
+++ b/platform/android/java/src/org/godotengine/godot/input/GodotEditText.java
@@ -1,9 +1,9 @@
-package com.android.godot.input;
+package org.godotengine.godot.input;
import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.EditText;
-import com.android.godot.*;
+import org.godotengine.godot.*;
import android.os.Handler;
import android.os.Message;
import android.view.inputmethod.InputMethodManager;
diff --git a/platform/android/java/src/com/android/godot/input/GodotTextInputWrapper.java b/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
index 537fa6aa76..64d8826b44 100644
--- a/platform/android/java/src/com/android/godot/input/GodotTextInputWrapper.java
+++ b/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
@@ -1,4 +1,4 @@
-package com.android.godot.input;
+package org.godotengine.godot.input;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
@@ -8,7 +8,7 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
-import com.android.godot.*;
+import org.godotengine.godot.*;
public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListener {
// ===========================================================
diff --git a/platform/android/java/src/com/android/godot/payments/ConsumeTask.java b/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java
index c983960770..61ccb97161 100644
--- a/platform/android/java/src/com/android/godot/payments/ConsumeTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java
@@ -1,4 +1,4 @@
-package com.android.godot.payments;
+package org.godotengine.godot.payments;
import com.android.vending.billing.IInAppBillingService;
diff --git a/platform/android/java/src/com/android/godot/payments/GenericConsumeTask.java b/platform/android/java/src/org/godotengine/godot/payments/GenericConsumeTask.java
index d68f029246..293e903284 100644
--- a/platform/android/java/src/com/android/godot/payments/GenericConsumeTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/GenericConsumeTask.java
@@ -1,4 +1,4 @@
-package com.android.godot.payments;
+package org.godotengine.godot.payments;
import com.android.vending.billing.IInAppBillingService;
diff --git a/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java b/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java
index 4c31704cc8..d120551e4a 100644
--- a/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java
@@ -1,10 +1,10 @@
-package com.android.godot.payments;
+package org.godotengine.godot.payments;
import org.json.JSONException;
import org.json.JSONObject;
-import com.android.godot.GodotLib;
-import com.android.godot.utils.Crypt;
+import org.godotengine.godot.GodotLib;
+import org.godotengine.godot.utils.Crypt;
import com.android.vending.billing.IInAppBillingService;
import android.app.Activity;
diff --git a/platform/android/java/src/com/android/godot/payments/PaymentsCache.java b/platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java
index 1de772bf28..5f3d931593 100644
--- a/platform/android/java/src/com/android/godot/payments/PaymentsCache.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java
@@ -1,4 +1,4 @@
-package com.android.godot.payments;
+package org.godotengine.godot.payments;
import android.content.Context;
import android.content.SharedPreferences;
diff --git a/platform/android/java/src/com/android/godot/payments/PaymentsManager.java b/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java
index 189f7108c1..effb58aa35 100644
--- a/platform/android/java/src/com/android/godot/payments/PaymentsManager.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java
@@ -1,4 +1,4 @@
-package com.android.godot.payments;
+package org.godotengine.godot.payments;
import java.util.ArrayList;
import java.util.List;
@@ -17,9 +17,9 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONStringer;
-import com.android.godot.Dictionary;
-import com.android.godot.Godot;
-import com.android.godot.GodotPaymentV3;
+import org.godotengine.godot.Dictionary;
+import org.godotengine.godot.Godot;
+import org.godotengine.godot.GodotPaymentV3;
import com.android.vending.billing.IInAppBillingService;
public class PaymentsManager {
diff --git a/platform/android/java/src/com/android/godot/payments/PurchaseTask.java b/platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java
index c1f9d164a1..8b048d8065 100644
--- a/platform/android/java/src/com/android/godot/payments/PurchaseTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java
@@ -1,10 +1,10 @@
-package com.android.godot.payments;
+package org.godotengine.godot.payments;
import org.json.JSONException;
import org.json.JSONObject;
-import com.android.godot.GodotLib;
-import com.android.godot.utils.Crypt;
+import org.godotengine.godot.GodotLib;
+import org.godotengine.godot.utils.Crypt;
import com.android.vending.billing.IInAppBillingService;
import android.app.Activity;
diff --git a/platform/android/java/src/com/android/godot/payments/ReleaseAllConsumablesTask.java b/platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java
index c1a9c5d421..7bb5131b49 100644
--- a/platform/android/java/src/com/android/godot/payments/ReleaseAllConsumablesTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java
@@ -1,12 +1,12 @@
-package com.android.godot.payments;
+package org.godotengine.godot.payments;
import java.util.ArrayList;
import org.json.JSONException;
import org.json.JSONObject;
-import com.android.godot.Dictionary;
-import com.android.godot.Godot;
+import org.godotengine.godot.Dictionary;
+import org.godotengine.godot.Godot;
import com.android.vending.billing.IInAppBillingService;
import android.content.Context;
diff --git a/platform/android/java/src/com/android/godot/payments/ValidateTask.java b/platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java
index 6ea415e8a9..2fcf7483b4 100644
--- a/platform/android/java/src/com/android/godot/payments/ValidateTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java
@@ -1,14 +1,14 @@
-package com.android.godot.payments;
+package org.godotengine.godot.payments;
import org.json.JSONException;
import org.json.JSONObject;
-import com.android.godot.Godot;
-import com.android.godot.GodotLib;
-import com.android.godot.GodotPaymentV3;
-import com.android.godot.utils.Crypt;
-import com.android.godot.utils.HttpRequester;
-import com.android.godot.utils.RequestParams;
+import org.godotengine.godot.Godot;
+import org.godotengine.godot.GodotLib;
+import org.godotengine.godot.GodotPaymentV3;
+import org.godotengine.godot.utils.Crypt;
+import org.godotengine.godot.utils.HttpRequester;
+import org.godotengine.godot.utils.RequestParams;
import com.android.vending.billing.IInAppBillingService;
import android.app.Activity;
diff --git a/platform/android/java/src/com/android/godot/utils/Crypt.java b/platform/android/java/src/org/godotengine/godot/utils/Crypt.java
index 7801f474b9..2fb81cef8c 100644
--- a/platform/android/java/src/com/android/godot/utils/Crypt.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/Crypt.java
@@ -1,4 +1,4 @@
-package com.android.godot.utils;
+package org.godotengine.godot.utils;
import java.security.MessageDigest;
import java.util.Random;
diff --git a/platform/android/java/src/com/android/godot/utils/CustomSSLSocketFactory.java b/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
index 5f2b44fc8c..2db88fcc9b 100644
--- a/platform/android/java/src/com/android/godot/utils/CustomSSLSocketFactory.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
@@ -1,4 +1,4 @@
-package com.android.godot.utils;
+package org.godotengine.godot.utils;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
diff --git a/platform/android/java/src/com/android/godot/utils/HttpRequester.java b/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
index 7de77881d0..14346702cc 100644
--- a/platform/android/java/src/com/android/godot/utils/HttpRequester.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
@@ -1,4 +1,4 @@
-package com.android.godot.utils;
+package org.godotengine.godot.utils;
import java.io.BufferedReader;
import java.io.IOException;
diff --git a/platform/android/java/src/com/android/godot/utils/RequestParams.java b/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
index 31bf1940ad..36753e368c 100644
--- a/platform/android/java/src/com/android/godot/utils/RequestParams.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
@@ -1,4 +1,4 @@
-package com.android.godot.utils;
+package org.godotengine.godot.utils;
import java.util.ArrayList;
import java.util.Date;
diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp
index d4cf848484..283ea81152 100644
--- a/platform/android/java_class_wrapper.cpp
+++ b/platform/android/java_class_wrapper.cpp
@@ -1281,7 +1281,7 @@ JavaClassWrapper::JavaClassWrapper(jobject p_activity) {
JNIEnv *env = ThreadAndroid::get_env();
- jclass activityClass = env->FindClass("com/android/godot/Godot");
+ jclass activityClass = env->FindClass("org/godotengine/godot/Godot");
jmethodID getClassLoader = env->GetMethodID(activityClass,"getClassLoader", "()Ljava/lang/ClassLoader;");
classLoader = env->CallObjectMethod(p_activity, getClassLoader);
classLoader=(jclass)env->NewGlobalRef(classLoader);
diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp
index d001cface2..75c1d78151 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -138,7 +138,7 @@ jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_a
case Variant::DICTIONARY: {
Dictionary dict = *p_arg;
- jclass dclass = env->FindClass("com/android/godot/Dictionary");
+ jclass dclass = env->FindClass("org/godotengine/godot/Dictionary");
jmethodID ctor = env->GetMethodID(dclass, "<init>", "()V");
jobject jdict = env->NewObject(dclass, ctor);
@@ -373,7 +373,7 @@ Variant _jobject_to_variant(JNIEnv * env, jobject obj) {
return varr;
};
- if (name == "java.util.HashMap" || name == "com.android.godot.Dictionary") {
+ if (name == "java.util.HashMap" || name == "org.godotengine.godot.Dictionary") {
Dictionary ret(true);
jclass oclass = c;
@@ -671,7 +671,7 @@ static jmethodID _playVideo=0;
static jmethodID _isVideoPlaying=0;
static jmethodID _pauseVideo=0;
static jmethodID _stopVideo=0;
-
+static jmethodID _setKeepScreenOn=0;
static void _gfx_init_func(void* ud, bool gl2) {
@@ -765,7 +765,12 @@ static void _stop_video() {
env->CallVoidMethod(godot_io, _stopVideo);
}
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, jobject obj, jobject activity,jboolean p_need_reload_hook, jobjectArray p_cmdline,jobject p_asset_manager) {
+static void _set_keep_screen_on(bool p_enabled) {
+ JNIEnv* env = ThreadAndroid::get_env();
+ env->CallVoidMethod(_godot_instance, _setKeepScreenOn, p_enabled);
+}
+
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv * env, jobject obj, jobject activity,jboolean p_need_reload_hook, jobjectArray p_cmdline,jobject p_asset_manager) {
__android_log_print(ANDROID_LOG_INFO,"godot","**INIT EVENT! - %p\n",env);
@@ -783,7 +788,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env,
{
//setup IO Object
- jclass cls = env->FindClass("com/android/godot/Godot");
+ jclass cls = env->FindClass("org/godotengine/godot/Godot");
if (cls) {
cls=(jclass)env->NewGlobalRef(cls);
@@ -791,7 +796,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env,
}
__android_log_print(ANDROID_LOG_INFO,"godot","STEP2, %p",cls);
- jfieldID fid = env->GetStaticFieldID(cls, "io", "Lcom/android/godot/GodotIO;");
+ jfieldID fid = env->GetStaticFieldID(cls, "io", "Lorg/godotengine/godot/GodotIO;");
__android_log_print(ANDROID_LOG_INFO,"godot","STEP3 %i",fid);
jobject ob = env->GetStaticObjectField(cls,fid);
__android_log_print(ANDROID_LOG_INFO,"godot","STEP4, %p",ob);
@@ -801,8 +806,9 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env,
godot_io=gob;
_on_video_init = env->GetMethodID(cls, "onVideoInit", "(Z)V");
+ _setKeepScreenOn = env->GetMethodID(cls,"setKeepScreenOn","(Z)V");
- jclass clsio = env->FindClass("com/android/godot/Godot");
+ jclass clsio = env->FindClass("org/godotengine/godot/Godot");
if (cls) {
jclass c = env->GetObjectClass(gob);
_openURI = env->GetMethodID(c,"openURI","(Ljava/lang/String;)I");
@@ -863,7 +869,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env,
__android_log_print(ANDROID_LOG_INFO,"godot","CMDLINE LEN %i - APK EXPANSION %I\n",cmdlen,int(use_apk_expansion));
- os_android = new OS_Android(_gfx_init_func,env,_open_uri,_get_data_dir,_get_locale, _get_model,_show_vk, _hide_vk,_set_screen_orient,_get_unique_id, _get_system_dir, _play_video,_is_video_playing, _pause_video, _stop_video,use_apk_expansion);
+ os_android = new OS_Android(_gfx_init_func,env,_open_uri,_get_data_dir,_get_locale, _get_model,_show_vk, _hide_vk,_set_screen_orient,_get_unique_id, _get_system_dir, _play_video,_is_video_playing, _pause_video, _stop_video, _set_keep_screen_on, use_apk_expansion);
os_android->set_need_reload_hooks(p_need_reload_hook);
char wd[500];
@@ -905,7 +911,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env,
}
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_resize(JNIEnv * env, jobject obj, jint width, jint height, jboolean reload) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv * env, jobject obj, jint width, jint height, jboolean reload) {
__android_log_print(ANDROID_LOG_INFO,"godot","^_^_^_^_^ resize %lld, %i, %i\n",Thread::get_caller_ID(),width,height);
if (os_android)
@@ -920,18 +926,24 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_resize(JNIEnv * env, jobj
}
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_newcontext(JNIEnv * env, jobject obj) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv * env, jobject obj,bool p_32_bits) {
__android_log_print(ANDROID_LOG_INFO,"godot","^_^_^_^_^ newcontext %lld\n",Thread::get_caller_ID());
+
+ if (os_android) {
+ os_android->set_context_is_16_bits(!p_32_bits);
+ }
+
if (os_android && step > 0) {
os_android->reload_gfx();
}
+
}
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_quit(JNIEnv * env, jobject obj) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_quit(JNIEnv * env, jobject obj) {
input_mutex->lock();
quit_request=true;
@@ -952,7 +964,7 @@ static void _initialize_java_modules() {
JNIEnv *env = ThreadAndroid::get_env();
- jclass activityClass = env->FindClass("com/android/godot/Godot");
+ jclass activityClass = env->FindClass("org/godotengine/godot/Godot");
jmethodID getClassLoader = env->GetMethodID(activityClass,"getClassLoader", "()Ljava/lang/ClassLoader;");
@@ -981,7 +993,7 @@ static void _initialize_java_modules() {
//singletonClass=(jclass)env->NewGlobalRef(singletonClass);
__android_log_print(ANDROID_LOG_INFO,"godot","****^*^*?^*^*class data %x",singletonClass);
- jmethodID initialize = env->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lcom/android/godot/Godot$SingletonBase;");
+ jmethodID initialize = env->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lorg/godotengine/godot/Godot$SingletonBase;");
if (!initialize) {
@@ -1001,7 +1013,7 @@ static void _initialize_java_modules() {
}
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_step(JNIEnv * env, jobject obj)
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv * env, jobject obj)
{
@@ -1068,7 +1080,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_step(JNIEnv * env, jobjec
if (os_android->main_loop_iterate()==true) {
- jclass cls = env->FindClass("com/android/godot/Godot");
+ jclass cls = env->FindClass("org/godotengine/godot/Godot");
jmethodID _finish = env->GetMethodID(cls, "forceQuit", "()V");
env->CallVoidMethod(_godot_instance, _finish);
__android_log_print(ANDROID_LOG_INFO,"godot","**FINISH REQUEST!!! - %p-%i\n",env,Thread::get_caller_ID());
@@ -1079,7 +1091,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_step(JNIEnv * env, jobjec
}
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_touch(JNIEnv * env, jobject obj, jint ev,jint pointer, jint count, jintArray positions) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv * env, jobject obj, jint ev,jint pointer, jint count, jintArray positions) {
@@ -1384,7 +1396,7 @@ static int find_device(int p_device) {
return joy_device_ids.size() - 1;
};
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_joybutton(JNIEnv * env, jobject obj, jint p_device, jint p_button, jboolean p_pressed) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv * env, jobject obj, jint p_device, jint p_button, jboolean p_pressed) {
InputEvent ievent;
ievent.type = InputEvent::JOYSTICK_BUTTON;
@@ -1397,7 +1409,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_joybutton(JNIEnv * env, j
input_mutex->unlock();
};
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_joyaxis(JNIEnv * env, jobject obj, jint p_device, jint p_axis, jfloat p_value) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv * env, jobject obj, jint p_device, jint p_axis, jfloat p_value) {
InputEvent ievent;
ievent.type = InputEvent::JOYSTICK_MOTION;
@@ -1411,7 +1423,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_joyaxis(JNIEnv * env, job
};
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_key(JNIEnv * env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv * env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed) {
InputEvent ievent;
ievent.type = InputEvent::KEY;
@@ -1449,7 +1461,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_key(JNIEnv * env, jobject
};
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_accelerometer(JNIEnv * env, jobject obj, jfloat x, jfloat y, jfloat z) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv * env, jobject obj, jfloat x, jfloat y, jfloat z) {
input_mutex->lock();
accelerometer=Vector3(x,y,z);
@@ -1457,7 +1469,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_accelerometer(JNIEnv * en
}
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_focusin(JNIEnv * env, jobject obj){
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv * env, jobject obj){
if (!suspend_mutex)
return;
@@ -1469,7 +1481,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_focusin(JNIEnv * env, job
suspend_mutex->unlock();
}
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_focusout(JNIEnv * env, jobject obj){
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusout(JNIEnv * env, jobject obj){
if (!suspend_mutex)
return;
@@ -1484,7 +1496,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_focusout(JNIEnv * env, jo
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_audio(JNIEnv * env, jobject obj) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv * env, jobject obj) {
ThreadAndroid::setup_thread();
AudioDriverAndroid::thread_func(env);
@@ -1493,7 +1505,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_audio(JNIEnv * env, jobje
}
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_singleton(JNIEnv * env, jobject obj, jstring name,jobject p_object){
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_singleton(JNIEnv * env, jobject obj, jstring name,jobject p_object){
String singname = env->GetStringUTFChars( name, NULL );
JNISingleton *s = memnew( JNISingleton );
@@ -1522,7 +1534,7 @@ static Variant::Type get_jni_type(const String& p_type) {
{"[B",Variant::RAW_ARRAY},
{"[F",Variant::REAL_ARRAY},
{"[java.lang.String",Variant::STRING_ARRAY},
- {"com.android.godot.Dictionary", Variant::DICTIONARY},
+ {"org.godotengine.godot.Dictionary", Variant::DICTIONARY},
{NULL,Variant::NIL}
};
@@ -1553,7 +1565,7 @@ static const char* get_jni_sig(const String& p_type) {
{"float","F"},
{"double","D"},
{"java.lang.String","Ljava/lang/String;"},
- {"com.android.godot.Dictionary", "Lcom/android/godot/Dictionary;"},
+ {"org.godotengine.godot.Dictionary", "Lorg/godotengine/godot/Dictionary;"},
{"[I","[I"},
{"[B","[B"},
{"[F","[F"},
@@ -1575,7 +1587,7 @@ static const char* get_jni_sig(const String& p_type) {
return "Ljava/lang/Object;";
}
-JNIEXPORT jstring JNICALL Java_com_android_godot_GodotLib_getGlobal(JNIEnv * env, jobject obj, jstring path) {
+JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv * env, jobject obj, jstring path) {
String js = env->GetStringUTFChars( path, NULL );
@@ -1585,7 +1597,7 @@ JNIEXPORT jstring JNICALL Java_com_android_godot_GodotLib_getGlobal(JNIEnv * env
}
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_method(JNIEnv * env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args){
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_method(JNIEnv * env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args){
String singname = env->GetStringUTFChars( sname, NULL );
@@ -1626,7 +1638,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_method(JNIEnv * env, jobj
}
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_callobject(JNIEnv * env, jobject p_obj, jint ID, jstring method, jobjectArray params) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv * env, jobject p_obj, jint ID, jstring method, jobjectArray params) {
Object* obj = ObjectDB::get_instance(ID);
ERR_FAIL_COND(!obj);
@@ -1661,7 +1673,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_callobject(JNIEnv * env,
};
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_calldeferred(JNIEnv * env, jobject p_obj, jint ID, jstring method, jobjectArray params) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv * env, jobject p_obj, jint ID, jstring method, jobjectArray params) {
Object* obj = ObjectDB::get_instance(ID);
diff --git a/platform/android/java_glue.h b/platform/android/java_glue.h
index 9410fe7132..efa5b2839d 100644
--- a/platform/android/java_glue.h
+++ b/platform/android/java_glue.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,24 +36,24 @@
extern "C" {
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, jobject obj, jobject activity,jboolean p_need_reload_hook, jobjectArray p_cmdline,jobject p_asset_manager);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_resize(JNIEnv * env, jobject obj, jint width, jint height, jboolean reload);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_newcontext(JNIEnv * env, jobject obj);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_step(JNIEnv * env, jobject obj);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_quit(JNIEnv * env, jobject obj);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_touch(JNIEnv * env, jobject obj, jint ev,jint pointer, jint count, jintArray positions);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_key(JNIEnv * env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_joybutton(JNIEnv * env, jobject obj, jint p_device, jint p_button, jboolean p_pressed);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_joyaxis(JNIEnv * env, jobject obj, jint p_device, jint p_axis, jfloat p_value);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_audio(JNIEnv * env, jobject obj);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_accelerometer(JNIEnv * env, jobject obj, jfloat x, jfloat y, jfloat z);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_focusin(JNIEnv * env, jobject obj);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_focusout(JNIEnv * env, jobject obj);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_singleton(JNIEnv * env, jobject obj, jstring name,jobject p_object);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_method(JNIEnv * env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args);
- JNIEXPORT jstring JNICALL Java_com_android_godot_GodotLib_getGlobal(JNIEnv * env, jobject obj, jstring path);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_callobject(JNIEnv * env, jobject obj, jint ID, jstring method, jobjectArray params);
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_calldeferred(JNIEnv * env, jobject obj, jint ID, jstring method, jobjectArray params);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv * env, jobject obj, jobject activity,jboolean p_need_reload_hook, jobjectArray p_cmdline,jobject p_asset_manager);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv * env, jobject obj, jint width, jint height, jboolean reload);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv * env, jobject obj, bool p_32_bits);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv * env, jobject obj);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_quit(JNIEnv * env, jobject obj);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv * env, jobject obj, jint ev,jint pointer, jint count, jintArray positions);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv * env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv * env, jobject obj, jint p_device, jint p_button, jboolean p_pressed);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv * env, jobject obj, jint p_device, jint p_axis, jfloat p_value);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv * env, jobject obj);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv * env, jobject obj, jfloat x, jfloat y, jfloat z);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv * env, jobject obj);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusout(JNIEnv * env, jobject obj);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_singleton(JNIEnv * env, jobject obj, jstring name,jobject p_object);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_method(JNIEnv * env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args);
+ JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv * env, jobject obj, jstring path);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv * env, jobject obj, jint ID, jstring method, jobjectArray params);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv * env, jobject obj, jint ID, jstring method, jobjectArray params);
};
diff --git a/platform/android/libs/apk_expansion/AndroidManifest.xml b/platform/android/libs/apk_expansion/AndroidManifest.xml
deleted file mode 100644
index 20b74a2988..0000000000
--- a/platform/android/libs/apk_expansion/AndroidManifest.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.vending.expansion.downloader"
- android:versionCode="2"
- android:versionName="1.1" >
-
- <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="15"/>
-
-</manifest> \ No newline at end of file
diff --git a/platform/android/libs/apk_expansion/build.xml b/platform/android/libs/apk_expansion/build.xml
deleted file mode 100644
index 5b2f2c590e..0000000000
--- a/platform/android/libs/apk_expansion/build.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="apk_expansion" default="help">
-
- <!-- The local.properties file is created and updated by the 'android' tool.
- It contains the path to the SDK. It should *NOT* be checked into
- Version Control Systems. -->
- <property file="local.properties" />
-
- <!-- The ant.properties file can be created by you. It is only edited by the
- 'android' tool to add properties to it.
- This is the place to change some Ant specific build properties.
- Here are some properties you may want to change/update:
-
- source.dir
- The name of the source directory. Default is 'src'.
- out.dir
- The name of the output directory. Default is 'bin'.
-
- For other overridable properties, look at the beginning of the rules
- files in the SDK, at tools/ant/build.xml
-
- Properties related to the SDK location or the project target should
- be updated using the 'android' tool with the 'update' action.
-
- This file is an integral part of the build system for your
- application and should be checked into Version Control Systems.
-
- -->
- <property file="ant.properties" />
-
- <!-- if sdk.dir was not set from one of the property file, then
- get it from the ANDROID_HOME env var.
- This must be done before we load project.properties since
- the proguard config can use sdk.dir -->
- <property environment="env" />
- <condition property="sdk.dir" value="${env.ANDROID_HOME}">
- <isset property="env.ANDROID_HOME" />
- </condition>
-
- <!-- The project.properties file is created and updated by the 'android'
- tool, as well as ADT.
-
- This contains project specific properties such as project target, and library
- dependencies. Lower level build properties are stored in ant.properties
- (or in .classpath for Eclipse projects).
-
- This file is an integral part of the build system for your
- application and should be checked into Version Control Systems. -->
- <loadproperties srcFile="project.properties" />
-
- <!-- quick check on sdk.dir -->
- <fail
- message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
- unless="sdk.dir"
- />
-
- <!--
- Import per project custom build rules if present at the root of the project.
- This is the place to put custom intermediary targets such as:
- -pre-build
- -pre-compile
- -post-compile (This is typically used for code obfuscation.
- Compiled code location: ${out.classes.absolute.dir}
- If this is not done in place, override ${out.dex.input.absolute.dir})
- -post-package
- -post-build
- -pre-clean
- -->
- <import file="custom_rules.xml" optional="true" />
-
- <!-- Import the actual build file.
-
- To customize existing targets, there are two options:
- - Customize only one target:
- - copy/paste the target into this file, *before* the
- <import> task.
- - customize it to your needs.
- - Customize the whole content of build.xml
- - copy/paste the content of the rules files (minus the top node)
- into this file, replacing the <import> task.
- - customize to your needs.
-
- ***********************
- ****** IMPORTANT ******
- ***********************
- In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
- in order to avoid having your file be overridden by tools such as "android update project"
- -->
- <!-- version-tag: 1 -->
- <import file="${sdk.dir}/tools/ant/build.xml" />
-
-</project>
diff --git a/platform/android/libs/apk_expansion/proguard-project.txt b/platform/android/libs/apk_expansion/proguard-project.txt
deleted file mode 100644
index f2fe1559a2..0000000000
--- a/platform/android/libs/apk_expansion/proguard-project.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-# To enable ProGuard in your project, edit project.properties
-# to define the proguard.config property as described in that file.
-#
-# Add project specific ProGuard rules here.
-# By default, the flags in this file are appended to flags specified
-# in ${sdk.dir}/tools/proguard/proguard-android.txt
-# You can edit the include path and order by changing the ProGuard
-# include property in project.properties.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# Add any project specific keep options here:
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
diff --git a/platform/android/libs/apk_expansion/project.properties b/platform/android/libs/apk_expansion/project.properties
deleted file mode 100644
index eda83430bf..0000000000
--- a/platform/android/libs/apk_expansion/project.properties
+++ /dev/null
@@ -1,13 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system use,
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-
-# Project target.
-target=android-15
-android.library=true
-android.library.reference.1=../play_licensing
diff --git a/platform/android/libs/apk_expansion/res/values/strings.xml b/platform/android/libs/apk_expansion/res/values/strings.xml
deleted file mode 100644
index b84749faf2..0000000000
--- a/platform/android/libs/apk_expansion/res/values/strings.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
- <!-- When a download completes, a notification is displayed, and this
- string is used to indicate that the download successfully completed.
- Note that such a download could have been initiated by a variety of
- applications, including (but not limited to) the browser, an email
- application, a content marketplace. -->
- <string name="notification_download_complete">Download complete</string>
-
- <!-- When a download completes, a notification is displayed, and this
- string is used to indicate that the download failed.
- Note that such a download could have been initiated by a variety of
- applications, including (but not limited to) the browser, an email
- application, a content marketplace. -->
- <string name="notification_download_failed">Download unsuccessful</string>
-
-
- <string name="state_unknown">Starting..."</string>
- <string name="state_idle">Waiting for download to start</string>
- <string name="state_fetching_url">Looking for resources to download</string>
- <string name="state_connecting">Connecting to the download server</string>
- <string name="state_downloading">Downloading resources</string>
- <string name="state_completed">Download finished</string>
- <string name="state_paused_network_unavailable">Download paused because no network is available</string>
- <string name="state_paused_network_setup_failure">Download paused. Test a website in browser</string>
- <string name="state_paused_by_request">Download paused</string>
- <string name="state_paused_wifi_unavailable">Download paused because wifi is unavailable</string>
- <string name="state_paused_wifi_disabled">Download paused because wifi is disabled</string>
- <string name="state_paused_roaming">Download paused because you are roaming</string>
- <string name="state_paused_sdcard_unavailable">Download paused because the external storage is unavailable</string>
- <string name="state_failed_unlicensed">Download failed because you may not have purchased this app</string>
- <string name="state_failed_fetching_url">Download failed because the resources could not be found</string>
- <string name="state_failed_sdcard_full">Download failed because the external storage is full</string>
- <string name="state_failed_cancelled">Download cancelled</string>
- <string name="state_failed">Download failed</string>
-
- <string name="kilobytes_per_second">%1$s KB/s</string>
- <string name="time_remaining">Time remaining: %1$s</string>
- <string name="time_remaining_notification">%1$s left</string>
-</resources> \ No newline at end of file
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/V14CustomNotification.java b/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/V14CustomNotification.java
deleted file mode 100644
index e736603e2a..0000000000
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/V14CustomNotification.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader.impl;
-
-import com.android.vending.expansion.downloader.R;
-import com.google.android.vending.expansion.downloader.Helpers;
-
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.content.Context;
-
-public class V14CustomNotification implements DownloadNotification.ICustomNotification {
-
- CharSequence mTitle;
- CharSequence mTicker;
- int mIcon;
- long mTotalKB = -1;
- long mCurrentKB = -1;
- long mTimeRemaining;
- PendingIntent mPendingIntent;
-
- @Override
- public void setIcon(int icon) {
- mIcon = icon;
- }
-
- @Override
- public void setTitle(CharSequence title) {
- mTitle = title;
- }
-
- @Override
- public void setTotalBytes(long totalBytes) {
- mTotalKB = totalBytes;
- }
-
- @Override
- public void setCurrentBytes(long currentBytes) {
- mCurrentKB = currentBytes;
- }
-
- void setProgress(Notification.Builder builder) {
-
- }
-
- @Override
- public Notification updateNotification(Context c) {
- Notification.Builder builder = new Notification.Builder(c);
- builder.setContentTitle(mTitle);
- if (mTotalKB > 0 && -1 != mCurrentKB) {
- builder.setProgress((int) (mTotalKB >> 8), (int) (mCurrentKB >> 8), false);
- } else {
- builder.setProgress(0, 0, true);
- }
- builder.setContentText(Helpers.getDownloadProgressString(mCurrentKB, mTotalKB));
- builder.setContentInfo(c.getString(R.string.time_remaining_notification,
- Helpers.getTimeRemaining(mTimeRemaining)));
- if (mIcon != 0) {
- builder.setSmallIcon(mIcon);
- } else {
- int iconResource = android.R.drawable.stat_sys_download;
- builder.setSmallIcon(iconResource);
- }
- builder.setOngoing(true);
- builder.setTicker(mTicker);
- builder.setContentIntent(mPendingIntent);
- builder.setOnlyAlertOnce(true);
-
- return builder.getNotification();
- }
-
- @Override
- public void setPendingIntent(PendingIntent contentIntent) {
- mPendingIntent = contentIntent;
- }
-
- @Override
- public void setTicker(CharSequence ticker) {
- mTicker = ticker;
- }
-
- @Override
- public void setTimeRemaining(long timeRemaining) {
- mTimeRemaining = timeRemaining;
- }
-
-}
diff --git a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/V3CustomNotification.java b/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/V3CustomNotification.java
deleted file mode 100644
index e3666e05b9..0000000000
--- a/platform/android/libs/apk_expansion/src/com/google/android/vending/expansion/downloader/impl/V3CustomNotification.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader.impl;
-
-import com.android.vending.expansion.downloader.R;
-import com.google.android.vending.expansion.downloader.Helpers;
-
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.graphics.BitmapFactory;
-import android.view.View;
-import android.widget.RemoteViews;
-
-public class V3CustomNotification implements DownloadNotification.ICustomNotification {
-
- CharSequence mTitle;
- CharSequence mTicker;
- int mIcon;
- long mTotalBytes = -1;
- long mCurrentBytes = -1;
- long mTimeRemaining;
- PendingIntent mPendingIntent;
- Notification mNotification = new Notification();
-
- @Override
- public void setIcon(int icon) {
- mIcon = icon;
- }
-
- @Override
- public void setTitle(CharSequence title) {
- mTitle = title;
- }
-
- @Override
- public void setTotalBytes(long totalBytes) {
- mTotalBytes = totalBytes;
- }
-
- @Override
- public void setCurrentBytes(long currentBytes) {
- mCurrentBytes = currentBytes;
- }
-
- @Override
- public Notification updateNotification(Context c) {
- Notification n = mNotification;
-
- n.icon = mIcon;
-
- n.flags |= Notification.FLAG_ONGOING_EVENT;
-
- if (android.os.Build.VERSION.SDK_INT > 10) {
- n.flags |= Notification.FLAG_ONLY_ALERT_ONCE; // only matters for
- // Honeycomb
- }
-
- // Build the RemoteView object
- RemoteViews expandedView = new RemoteViews(
- c.getPackageName(),
- R.layout.status_bar_ongoing_event_progress_bar);
-
- expandedView.setTextViewText(R.id.title, mTitle);
- // look at strings
- expandedView.setViewVisibility(R.id.description, View.VISIBLE);
- expandedView.setTextViewText(R.id.description,
- Helpers.getDownloadProgressString(mCurrentBytes, mTotalBytes));
- expandedView.setViewVisibility(R.id.progress_bar_frame, View.VISIBLE);
- expandedView.setProgressBar(R.id.progress_bar,
- (int) (mTotalBytes >> 8),
- (int) (mCurrentBytes >> 8),
- mTotalBytes <= 0);
- expandedView.setViewVisibility(R.id.time_remaining, View.VISIBLE);
- expandedView.setTextViewText(
- R.id.time_remaining,
- c.getString(R.string.time_remaining_notification,
- Helpers.getTimeRemaining(mTimeRemaining)));
- expandedView.setTextViewText(R.id.progress_text,
- Helpers.getDownloadProgressPercent(mCurrentBytes, mTotalBytes));
- expandedView.setImageViewResource(R.id.appIcon, mIcon);
- n.contentView = expandedView;
- n.contentIntent = mPendingIntent;
- return n;
- }
-
- @Override
- public void setPendingIntent(PendingIntent contentIntent) {
- mPendingIntent = contentIntent;
- }
-
- @Override
- public void setTicker(CharSequence ticker) {
- mTicker = ticker;
- }
-
- @Override
- public void setTimeRemaining(long timeRemaining) {
- mTimeRemaining = timeRemaining;
- }
-
-}
diff --git a/platform/android/libs/downloader_library/.classpath b/platform/android/libs/downloader_library/.classpath
deleted file mode 100644
index 7bc01d9a9c..0000000000
--- a/platform/android/libs/downloader_library/.classpath
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="src" path="gen"/>
- <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
- <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
- <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
- <classpathentry kind="output" path="bin/classes"/>
-</classpath>
diff --git a/platform/android/libs/downloader_library/.settings/org.eclipse.jdt.core.prefs b/platform/android/libs/downloader_library/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index b080d2ddc8..0000000000
--- a/platform/android/libs/downloader_library/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,4 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.source=1.6
diff --git a/platform/android/libs/downloader_library/AndroidManifest.xml b/platform/android/libs/downloader_library/AndroidManifest.xml
deleted file mode 100644
index 20b74a2988..0000000000
--- a/platform/android/libs/downloader_library/AndroidManifest.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.vending.expansion.downloader"
- android:versionCode="2"
- android:versionName="1.1" >
-
- <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="15"/>
-
-</manifest> \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/build.xml b/platform/android/libs/downloader_library/build.xml
deleted file mode 100644
index d65c145148..0000000000
--- a/platform/android/libs/downloader_library/build.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="downloader_library" default="help">
-
- <!-- The local.properties file is created and updated by the 'android' tool.
- It contains the path to the SDK. It should *NOT* be checked into
- Version Control Systems. -->
- <property file="local.properties" />
-
- <!-- The ant.properties file can be created by you. It is only edited by the
- 'android' tool to add properties to it.
- This is the place to change some Ant specific build properties.
- Here are some properties you may want to change/update:
-
- source.dir
- The name of the source directory. Default is 'src'.
- out.dir
- The name of the output directory. Default is 'bin'.
-
- For other overridable properties, look at the beginning of the rules
- files in the SDK, at tools/ant/build.xml
-
- Properties related to the SDK location or the project target should
- be updated using the 'android' tool with the 'update' action.
-
- This file is an integral part of the build system for your
- application and should be checked into Version Control Systems.
-
- -->
- <property file="ant.properties" />
-
- <!-- if sdk.dir was not set from one of the property file, then
- get it from the ANDROID_HOME env var.
- This must be done before we load project.properties since
- the proguard config can use sdk.dir -->
- <property environment="env" />
- <condition property="sdk.dir" value="${env.ANDROID_HOME}">
- <isset property="env.ANDROID_HOME" />
- </condition>
-
- <!-- The project.properties file is created and updated by the 'android'
- tool, as well as ADT.
-
- This contains project specific properties such as project target, and library
- dependencies. Lower level build properties are stored in ant.properties
- (or in .classpath for Eclipse projects).
-
- This file is an integral part of the build system for your
- application and should be checked into Version Control Systems. -->
- <loadproperties srcFile="project.properties" />
-
- <!-- quick check on sdk.dir -->
- <fail
- message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
- unless="sdk.dir"
- />
-
- <!--
- Import per project custom build rules if present at the root of the project.
- This is the place to put custom intermediary targets such as:
- -pre-build
- -pre-compile
- -post-compile (This is typically used for code obfuscation.
- Compiled code location: ${out.classes.absolute.dir}
- If this is not done in place, override ${out.dex.input.absolute.dir})
- -post-package
- -post-build
- -pre-clean
- -->
- <import file="custom_rules.xml" optional="true" />
-
- <!-- Import the actual build file.
-
- To customize existing targets, there are two options:
- - Customize only one target:
- - copy/paste the target into this file, *before* the
- <import> task.
- - customize it to your needs.
- - Customize the whole content of build.xml
- - copy/paste the content of the rules files (minus the top node)
- into this file, replacing the <import> task.
- - customize to your needs.
-
- ***********************
- ****** IMPORTANT ******
- ***********************
- In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
- in order to avoid having your file be overridden by tools such as "android update project"
- -->
- <!-- version-tag: 1 -->
- <import file="${sdk.dir}/tools/ant/build.xml" />
-
-</project>
diff --git a/platform/android/libs/downloader_library/proguard-project.txt b/platform/android/libs/downloader_library/proguard-project.txt
deleted file mode 100644
index f2fe1559a2..0000000000
--- a/platform/android/libs/downloader_library/proguard-project.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-# To enable ProGuard in your project, edit project.properties
-# to define the proguard.config property as described in that file.
-#
-# Add project specific ProGuard rules here.
-# By default, the flags in this file are appended to flags specified
-# in ${sdk.dir}/tools/proguard/proguard-android.txt
-# You can edit the include path and order by changing the ProGuard
-# include property in project.properties.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# Add any project specific keep options here:
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
diff --git a/platform/android/libs/downloader_library/project.properties b/platform/android/libs/downloader_library/project.properties
deleted file mode 100644
index eda83430bf..0000000000
--- a/platform/android/libs/downloader_library/project.properties
+++ /dev/null
@@ -1,13 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system use,
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-
-# Project target.
-target=android-15
-android.library=true
-android.library.reference.1=../play_licensing
diff --git a/platform/android/libs/downloader_library/res/drawable-hdpi/notify_panel_notification_icon_bg.png b/platform/android/libs/downloader_library/res/drawable-hdpi/notify_panel_notification_icon_bg.png
deleted file mode 100644
index f5b762ecf3..0000000000
--- a/platform/android/libs/downloader_library/res/drawable-hdpi/notify_panel_notification_icon_bg.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/downloader_library/res/drawable-mdpi/notify_panel_notification_icon_bg.png b/platform/android/libs/downloader_library/res/drawable-mdpi/notify_panel_notification_icon_bg.png
deleted file mode 100644
index 9ecb8af06c..0000000000
--- a/platform/android/libs/downloader_library/res/drawable-mdpi/notify_panel_notification_icon_bg.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/downloader_library/res/layout/status_bar_ongoing_event_progress_bar.xml b/platform/android/libs/downloader_library/res/layout/status_bar_ongoing_event_progress_bar.xml
deleted file mode 100644
index 23bac02294..0000000000
--- a/platform/android/libs/downloader_library/res/layout/status_bar_ongoing_event_progress_bar.xml
+++ /dev/null
@@ -1,104 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<LinearLayout android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:baselineAligned="false"
- android:orientation="horizontal" android:id="@+id/notificationLayout" xmlns:android="http://schemas.android.com/apk/res/android">
-
- <RelativeLayout
- android:layout_width="35dp"
- android:layout_height="fill_parent"
- android:paddingTop="10dp"
- android:paddingBottom="8dp" >
-
- <ImageView
- android:id="@+id/appIcon"
- android:layout_width="fill_parent"
- android:layout_height="25dp"
- android:scaleType="centerInside"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:src="@android:drawable/stat_sys_download" />
-
- <TextView
- android:id="@+id/progress_text"
- style="@style/NotificationText"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentBottom="true"
- android:layout_gravity="center_horizontal"
- android:singleLine="true"
- android:gravity="center" />
- </RelativeLayout>
-
- <RelativeLayout
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1.0"
- android:clickable="true"
- android:focusable="true"
- android:paddingTop="10dp"
- android:paddingRight="8dp"
- android:paddingBottom="8dp" >
-
- <TextView
- android:id="@+id/title"
- style="@style/NotificationTitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:singleLine="true"/>
-
- <TextView
- android:id="@+id/time_remaining"
- style="@style/NotificationText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:singleLine="true"/>
- <!-- Only one of progress_bar and paused_text will be visible. -->
-
- <FrameLayout
- android:id="@+id/progress_bar_frame"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true" >
-
- <ProgressBar
- android:id="@+id/progress_bar"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingRight="25dp" />
-
- <TextView
- android:id="@+id/description"
- style="@style/NotificationTextShadow"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:paddingRight="25dp"
- android:singleLine="true" />
- </FrameLayout>
-
- </RelativeLayout>
-
-</LinearLayout> \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/res/values-v11/styles.xml b/platform/android/libs/downloader_library/res/values-v11/styles.xml
deleted file mode 100644
index f2013bc0bf..0000000000
--- a/platform/android/libs/downloader_library/res/values-v11/styles.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="NotificationTextSecondary" parent="NotificationText">
- <item name="android:textSize">12sp</item>
- </style>
-</resources> \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/res/values-v9/styles.xml b/platform/android/libs/downloader_library/res/values-v9/styles.xml
deleted file mode 100644
index 736e77a5d6..0000000000
--- a/platform/android/libs/downloader_library/res/values-v9/styles.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="NotificationText" parent="android:TextAppearance.StatusBar.EventContent" />
- <style name="NotificationTitle" parent="android:TextAppearance.StatusBar.EventContent.Title" />
-</resources> \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/res/values/strings.xml b/platform/android/libs/downloader_library/res/values/strings.xml
deleted file mode 100644
index b84749faf2..0000000000
--- a/platform/android/libs/downloader_library/res/values/strings.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
- <!-- When a download completes, a notification is displayed, and this
- string is used to indicate that the download successfully completed.
- Note that such a download could have been initiated by a variety of
- applications, including (but not limited to) the browser, an email
- application, a content marketplace. -->
- <string name="notification_download_complete">Download complete</string>
-
- <!-- When a download completes, a notification is displayed, and this
- string is used to indicate that the download failed.
- Note that such a download could have been initiated by a variety of
- applications, including (but not limited to) the browser, an email
- application, a content marketplace. -->
- <string name="notification_download_failed">Download unsuccessful</string>
-
-
- <string name="state_unknown">Starting..."</string>
- <string name="state_idle">Waiting for download to start</string>
- <string name="state_fetching_url">Looking for resources to download</string>
- <string name="state_connecting">Connecting to the download server</string>
- <string name="state_downloading">Downloading resources</string>
- <string name="state_completed">Download finished</string>
- <string name="state_paused_network_unavailable">Download paused because no network is available</string>
- <string name="state_paused_network_setup_failure">Download paused. Test a website in browser</string>
- <string name="state_paused_by_request">Download paused</string>
- <string name="state_paused_wifi_unavailable">Download paused because wifi is unavailable</string>
- <string name="state_paused_wifi_disabled">Download paused because wifi is disabled</string>
- <string name="state_paused_roaming">Download paused because you are roaming</string>
- <string name="state_paused_sdcard_unavailable">Download paused because the external storage is unavailable</string>
- <string name="state_failed_unlicensed">Download failed because you may not have purchased this app</string>
- <string name="state_failed_fetching_url">Download failed because the resources could not be found</string>
- <string name="state_failed_sdcard_full">Download failed because the external storage is full</string>
- <string name="state_failed_cancelled">Download cancelled</string>
- <string name="state_failed">Download failed</string>
-
- <string name="kilobytes_per_second">%1$s KB/s</string>
- <string name="time_remaining">Time remaining: %1$s</string>
- <string name="time_remaining_notification">%1$s left</string>
-</resources> \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/res/values/styles.xml b/platform/android/libs/downloader_library/res/values/styles.xml
deleted file mode 100644
index a442f61e7e..0000000000
--- a/platform/android/libs/downloader_library/res/values/styles.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
- <style name="NotificationText">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
- </style>
-
- <style name="NotificationTextShadow" parent="NotificationText">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
- <item name="android:shadowColor">@android:color/background_dark</item>
- <item name="android:shadowDx">1.0</item>
- <item name="android:shadowDy">1.0</item>
- <item name="android:shadowRadius">1</item>
- </style>
-
- <style name="NotificationTitle">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
- <item name="android:textStyle">bold</item>
- </style>
-
- <style name="ButtonBackground">
- <item name="android:background">@android:color/background_dark</item>
- </style>
-
-</resources> \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Constants.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Constants.java
deleted file mode 100644
index ff2c6f535a..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Constants.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader;
-
-import java.io.File;
-
-
-/**
- * Contains the internal constants that are used in the download manager.
- * As a general rule, modifying these constants should be done with care.
- */
-public class Constants {
- /** Tag used for debugging/logging */
- public static final String TAG = "LVLDL";
-
- /**
- * Expansion path where we store obb files
- */
- public static final String EXP_PATH = File.separator + "Android"
- + File.separator + "obb" + File.separator;
-
- /** The intent that gets sent when the service must wake up for a retry */
- public static final String ACTION_RETRY = "android.intent.action.DOWNLOAD_WAKEUP";
-
- /** the intent that gets sent when clicking a successful download */
- public static final String ACTION_OPEN = "android.intent.action.DOWNLOAD_OPEN";
-
- /** the intent that gets sent when clicking an incomplete/failed download */
- public static final String ACTION_LIST = "android.intent.action.DOWNLOAD_LIST";
-
- /** the intent that gets sent when deleting the notification of a completed download */
- public static final String ACTION_HIDE = "android.intent.action.DOWNLOAD_HIDE";
-
- /**
- * When a number has to be appended to the filename, this string is used to separate the
- * base filename from the sequence number
- */
- public static final String FILENAME_SEQUENCE_SEPARATOR = "-";
-
- /** The default user agent used for downloads */
- public static final String DEFAULT_USER_AGENT = "Android.LVLDM";
-
- /** The buffer size used to stream the data */
- public static final int BUFFER_SIZE = 4096;
-
- /** The minimum amount of progress that has to be done before the progress bar gets updated */
- public static final int MIN_PROGRESS_STEP = 4096;
-
- /** The minimum amount of time that has to elapse before the progress bar gets updated, in ms */
- public static final long MIN_PROGRESS_TIME = 1000;
-
- /** The maximum number of rows in the database (FIFO) */
- public static final int MAX_DOWNLOADS = 1000;
-
- /**
- * The number of times that the download manager will retry its network
- * operations when no progress is happening before it gives up.
- */
- public static final int MAX_RETRIES = 5;
-
- /**
- * The minimum amount of time that the download manager accepts for
- * a Retry-After response header with a parameter in delta-seconds.
- */
- public static final int MIN_RETRY_AFTER = 30; // 30s
-
- /**
- * The maximum amount of time that the download manager accepts for
- * a Retry-After response header with a parameter in delta-seconds.
- */
- public static final int MAX_RETRY_AFTER = 24 * 60 * 60; // 24h
-
- /**
- * The maximum number of redirects.
- */
- public static final int MAX_REDIRECTS = 5; // can't be more than 7.
-
- /**
- * The time between a failure and the first retry after an IOException.
- * Each subsequent retry grows exponentially, doubling each time.
- * The time is in seconds.
- */
- public static final int RETRY_FIRST_DELAY = 30;
-
- /** Enable separate connectivity logging */
- public static final boolean LOGX = true;
-
- /** Enable verbose logging */
- public static final boolean LOGV = false;
-
- /** Enable super-verbose logging */
- private static final boolean LOCAL_LOGVV = false;
- public static final boolean LOGVV = LOCAL_LOGVV && LOGV;
-
- /**
- * This download has successfully completed.
- * Warning: there might be other status values that indicate success
- * in the future.
- * Use isSucccess() to capture the entire category.
- */
- public static final int STATUS_SUCCESS = 200;
-
- /**
- * This request couldn't be parsed. This is also used when processing
- * requests with unknown/unsupported URI schemes.
- */
- public static final int STATUS_BAD_REQUEST = 400;
-
- /**
- * This download can't be performed because the content type cannot be
- * handled.
- */
- public static final int STATUS_NOT_ACCEPTABLE = 406;
-
- /**
- * This download cannot be performed because the length cannot be
- * determined accurately. This is the code for the HTTP error "Length
- * Required", which is typically used when making requests that require
- * a content length but don't have one, and it is also used in the
- * client when a response is received whose length cannot be determined
- * accurately (therefore making it impossible to know when a download
- * completes).
- */
- public static final int STATUS_LENGTH_REQUIRED = 411;
-
- /**
- * This download was interrupted and cannot be resumed.
- * This is the code for the HTTP error "Precondition Failed", and it is
- * also used in situations where the client doesn't have an ETag at all.
- */
- public static final int STATUS_PRECONDITION_FAILED = 412;
-
- /**
- * The lowest-valued error status that is not an actual HTTP status code.
- */
- public static final int MIN_ARTIFICIAL_ERROR_STATUS = 488;
-
- /**
- * The requested destination file already exists.
- */
- public static final int STATUS_FILE_ALREADY_EXISTS_ERROR = 488;
-
- /**
- * Some possibly transient error occurred, but we can't resume the download.
- */
- public static final int STATUS_CANNOT_RESUME = 489;
-
- /**
- * This download was canceled
- */
- public static final int STATUS_CANCELED = 490;
-
- /**
- * This download has completed with an error.
- * Warning: there will be other status values that indicate errors in
- * the future. Use isStatusError() to capture the entire category.
- */
- public static final int STATUS_UNKNOWN_ERROR = 491;
-
- /**
- * This download couldn't be completed because of a storage issue.
- * Typically, that's because the filesystem is missing or full.
- * Use the more specific {@link #STATUS_INSUFFICIENT_SPACE_ERROR}
- * and {@link #STATUS_DEVICE_NOT_FOUND_ERROR} when appropriate.
- */
- public static final int STATUS_FILE_ERROR = 492;
-
- /**
- * This download couldn't be completed because of an HTTP
- * redirect response that the download manager couldn't
- * handle.
- */
- public static final int STATUS_UNHANDLED_REDIRECT = 493;
-
- /**
- * This download couldn't be completed because of an
- * unspecified unhandled HTTP code.
- */
- public static final int STATUS_UNHANDLED_HTTP_CODE = 494;
-
- /**
- * This download couldn't be completed because of an
- * error receiving or processing data at the HTTP level.
- */
- public static final int STATUS_HTTP_DATA_ERROR = 495;
-
- /**
- * This download couldn't be completed because of an
- * HttpException while setting up the request.
- */
- public static final int STATUS_HTTP_EXCEPTION = 496;
-
- /**
- * This download couldn't be completed because there were
- * too many redirects.
- */
- public static final int STATUS_TOO_MANY_REDIRECTS = 497;
-
- /**
- * This download couldn't be completed due to insufficient storage
- * space. Typically, this is because the SD card is full.
- */
- public static final int STATUS_INSUFFICIENT_SPACE_ERROR = 498;
-
- /**
- * This download couldn't be completed because no external storage
- * device was found. Typically, this is because the SD card is not
- * mounted.
- */
- public static final int STATUS_DEVICE_NOT_FOUND_ERROR = 499;
-
- /**
- * The wake duration to check to see if a download is possible.
- */
- public static final long WATCHDOG_WAKE_TIMER = 60*1000;
-
- /**
- * The wake duration to check to see if the process was killed.
- */
- public static final long ACTIVE_THREAD_WATCHDOG = 5*1000;
-
-} \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java
deleted file mode 100644
index 9cb294d721..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-
-/**
- * This class contains progress information about the active download(s).
- *
- * When you build the Activity that initiates a download and tracks the
- * progress by implementing the {@link IDownloaderClient} interface, you'll
- * receive a DownloadProgressInfo object in each call to the {@link
- * IDownloaderClient#onDownloadProgress} method. This allows you to update
- * your activity's UI with information about the download progress, such
- * as the progress so far, time remaining and current speed.
- */
-public class DownloadProgressInfo implements Parcelable {
- public long mOverallTotal;
- public long mOverallProgress;
- public long mTimeRemaining; // time remaining
- public float mCurrentSpeed; // speed in KB/S
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel p, int i) {
- p.writeLong(mOverallTotal);
- p.writeLong(mOverallProgress);
- p.writeLong(mTimeRemaining);
- p.writeFloat(mCurrentSpeed);
- }
-
- public DownloadProgressInfo(Parcel p) {
- mOverallTotal = p.readLong();
- mOverallProgress = p.readLong();
- mTimeRemaining = p.readLong();
- mCurrentSpeed = p.readFloat();
- }
-
- public DownloadProgressInfo(long overallTotal, long overallProgress,
- long timeRemaining,
- float currentSpeed) {
- this.mOverallTotal = overallTotal;
- this.mOverallProgress = overallProgress;
- this.mTimeRemaining = timeRemaining;
- this.mCurrentSpeed = currentSpeed;
- }
-
- public static final Creator<DownloadProgressInfo> CREATOR = new Creator<DownloadProgressInfo>() {
- @Override
- public DownloadProgressInfo createFromParcel(Parcel parcel) {
- return new DownloadProgressInfo(parcel);
- }
-
- @Override
- public DownloadProgressInfo[] newArray(int i) {
- return new DownloadProgressInfo[i];
- }
- };
-
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java
deleted file mode 100644
index 2201751254..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader;
-
-import com.google.android.vending.expansion.downloader.impl.DownloaderService;
-
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
-import android.util.Log;
-
-
-
-/**
- * This class binds the service API to your application client. It contains the IDownloaderClient proxy,
- * which is used to call functions in your client as well as the Stub, which is used to call functions
- * in the client implementation of IDownloaderClient.
- *
- * <p>The IPC is implemented using an Android Messenger and a service Binder. The connect method
- * should be called whenever the client wants to bind to the service. It opens up a service connection
- * that ends up calling the onServiceConnected client API that passes the service messenger
- * in. If the client wants to be notified by the service, it is responsible for then passing its
- * messenger to the service in a separate call.
- *
- * <p>Critical methods are {@link #startDownloadServiceIfRequired} and {@link #CreateStub}.
- *
- * <p>When your application first starts, you should first check whether your app's expansion files are
- * already on the device. If not, you should then call {@link #startDownloadServiceIfRequired}, which
- * starts your {@link impl.DownloaderService} to download the expansion files if necessary. The method
- * returns a value indicating whether download is required or not.
- *
- * <p>If a download is required, {@link #startDownloadServiceIfRequired} begins the download through
- * the specified service and you should then call {@link #CreateStub} to instantiate a member {@link
- * IStub} object that you need in order to receive calls through your {@link IDownloaderClient}
- * interface.
- */
-public class DownloaderClientMarshaller {
- public static final int MSG_ONDOWNLOADSTATE_CHANGED = 10;
- public static final int MSG_ONDOWNLOADPROGRESS = 11;
- public static final int MSG_ONSERVICECONNECTED = 12;
-
- public static final String PARAM_NEW_STATE = "newState";
- public static final String PARAM_PROGRESS = "progress";
- public static final String PARAM_MESSENGER = DownloaderService.EXTRA_MESSAGE_HANDLER;
-
- public static final int NO_DOWNLOAD_REQUIRED = DownloaderService.NO_DOWNLOAD_REQUIRED;
- public static final int LVL_CHECK_REQUIRED = DownloaderService.LVL_CHECK_REQUIRED;
- public static final int DOWNLOAD_REQUIRED = DownloaderService.DOWNLOAD_REQUIRED;
-
- private static class Proxy implements IDownloaderClient {
- private Messenger mServiceMessenger;
-
- @Override
- public void onDownloadStateChanged(int newState) {
- Bundle params = new Bundle(1);
- params.putInt(PARAM_NEW_STATE, newState);
- send(MSG_ONDOWNLOADSTATE_CHANGED, params);
- }
-
- @Override
- public void onDownloadProgress(DownloadProgressInfo progress) {
- Bundle params = new Bundle(1);
- params.putParcelable(PARAM_PROGRESS, progress);
- send(MSG_ONDOWNLOADPROGRESS, params);
- }
-
- private void send(int method, Bundle params) {
- Message m = Message.obtain(null, method);
- m.setData(params);
- try {
- mServiceMessenger.send(m);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
-
- public Proxy(Messenger msg) {
- mServiceMessenger = msg;
- }
-
- @Override
- public void onServiceConnected(Messenger m) {
- /**
- * This is never called through the proxy.
- */
- }
- }
-
- private static class Stub implements IStub {
- private IDownloaderClient mItf = null;
- private Class<?> mDownloaderServiceClass;
- private boolean mBound;
- private Messenger mServiceMessenger;
- private Context mContext;
- /**
- * Target we publish for clients to send messages to IncomingHandler.
- */
- final Messenger mMessenger = new Messenger(new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_ONDOWNLOADPROGRESS:
- Bundle bun = msg.getData();
- if ( null != mContext ) {
- bun.setClassLoader(mContext.getClassLoader());
- DownloadProgressInfo dpi = (DownloadProgressInfo) msg.getData()
- .getParcelable(PARAM_PROGRESS);
- mItf.onDownloadProgress(dpi);
- }
- break;
- case MSG_ONDOWNLOADSTATE_CHANGED:
- mItf.onDownloadStateChanged(msg.getData().getInt(PARAM_NEW_STATE));
- break;
- case MSG_ONSERVICECONNECTED:
- mItf.onServiceConnected(
- (Messenger) msg.getData().getParcelable(PARAM_MESSENGER));
- break;
- }
- }
- });
-
- public Stub(IDownloaderClient itf, Class<?> downloaderService) {
- mItf = itf;
- mDownloaderServiceClass = downloaderService;
- }
-
- /**
- * Class for interacting with the main interface of the service.
- */
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- // This is called when the connection with the service has been
- // established, giving us the object we can use to
- // interact with the service. We are communicating with the
- // service using a Messenger, so here we get a client-side
- // representation of that from the raw IBinder object.
- mServiceMessenger = new Messenger(service);
- mItf.onServiceConnected(
- mServiceMessenger);
- }
-
- public void onServiceDisconnected(ComponentName className) {
- // This is called when the connection with the service has been
- // unexpectedly disconnected -- that is, its process crashed.
- mServiceMessenger = null;
- }
- };
-
- @Override
- public void connect(Context c) {
- mContext = c;
- Intent bindIntent = new Intent(c, mDownloaderServiceClass);
- bindIntent.putExtra(PARAM_MESSENGER, mMessenger);
- if ( !c.bindService(bindIntent, mConnection, Context.BIND_DEBUG_UNBIND) ) {
- if ( Constants.LOGVV ) {
- Log.d(Constants.TAG, "Service Unbound");
- }
- } else {
- mBound = true;
- }
-
- }
-
- @Override
- public void disconnect(Context c) {
- if (mBound) {
- c.unbindService(mConnection);
- mBound = false;
- }
- mContext = null;
- }
-
- @Override
- public Messenger getMessenger() {
- return mMessenger;
- }
- }
-
- /**
- * Returns a proxy that will marshal calls to IDownloaderClient methods
- *
- * @param msg
- * @return
- */
- public static IDownloaderClient CreateProxy(Messenger msg) {
- return new Proxy(msg);
- }
-
- /**
- * Returns a stub object that, when connected, will listen for marshaled
- * {@link IDownloaderClient} methods and translate them into calls to the supplied
- * interface.
- *
- * @param itf An implementation of IDownloaderClient that will be called
- * when remote method calls are unmarshaled.
- * @param downloaderService The class for your implementation of {@link
- * impl.DownloaderService}.
- * @return The {@link IStub} that allows you to connect to the service such that
- * your {@link IDownloaderClient} receives status updates.
- */
- public static IStub CreateStub(IDownloaderClient itf, Class<?> downloaderService) {
- return new Stub(itf, downloaderService);
- }
-
- /**
- * Starts the download if necessary. This function starts a flow that does `
- * many things. 1) Checks to see if the APK version has been checked and
- * the metadata database updated 2) If the APK version does not match,
- * checks the new LVL status to see if a new download is required 3) If the
- * APK version does match, then checks to see if the download(s) have been
- * completed 4) If the downloads have been completed, returns
- * NO_DOWNLOAD_REQUIRED The idea is that this can be called during the
- * startup of an application to quickly ascertain if the application needs
- * to wait to hear about any updated APK expansion files. Note that this does
- * mean that the application MUST be run for the first time with a network
- * connection, even if Market delivers all of the files.
- *
- * @param context Your application Context.
- * @param notificationClient A PendingIntent to start the Activity in your application
- * that shows the download progress and which will also start the application when download
- * completes.
- * @param serviceClass the class of your {@link imp.DownloaderService} implementation
- * @return whether the service was started and the reason for starting the service.
- * Either {@link #NO_DOWNLOAD_REQUIRED}, {@link #LVL_CHECK_REQUIRED}, or {@link
- * #DOWNLOAD_REQUIRED}.
- * @throws NameNotFoundException
- */
- public static int startDownloadServiceIfRequired(Context context, PendingIntent notificationClient,
- Class<?> serviceClass)
- throws NameNotFoundException {
- return DownloaderService.startDownloadServiceIfRequired(context, notificationClient,
- serviceClass);
- }
-
- /**
- * This version assumes that the intent contains the pending intent as a parameter. This
- * is used for responding to alarms.
- * <p>The pending intent must be in an extra with the key {@link
- * impl.DownloaderService#EXTRA_PENDING_INTENT}.
- *
- * @param context
- * @param notificationClient
- * @param serviceClass the class of the service to start
- * @return
- * @throws NameNotFoundException
- */
- public static int startDownloadServiceIfRequired(Context context, Intent notificationClient,
- Class<?> serviceClass)
- throws NameNotFoundException {
- return DownloaderService.startDownloadServiceIfRequired(context, notificationClient,
- serviceClass);
- }
-
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java
deleted file mode 100644
index 054eaa9895..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader;
-
-import com.google.android.vending.expansion.downloader.impl.DownloaderService;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
-
-
-
-/**
- * This class is used by the client activity to proxy requests to the Downloader
- * Service.
- *
- * Most importantly, you must call {@link #CreateProxy} during the {@link
- * IDownloaderClient#onServiceConnected} callback in your activity in order to instantiate
- * an {@link IDownloaderService} object that you can then use to issue commands to the {@link
- * DownloaderService} (such as to pause and resume downloads).
- */
-public class DownloaderServiceMarshaller {
-
- public static final int MSG_REQUEST_ABORT_DOWNLOAD =
- 1;
- public static final int MSG_REQUEST_PAUSE_DOWNLOAD =
- 2;
- public static final int MSG_SET_DOWNLOAD_FLAGS =
- 3;
- public static final int MSG_REQUEST_CONTINUE_DOWNLOAD =
- 4;
- public static final int MSG_REQUEST_DOWNLOAD_STATE =
- 5;
- public static final int MSG_REQUEST_CLIENT_UPDATE =
- 6;
-
- public static final String PARAMS_FLAGS = "flags";
- public static final String PARAM_MESSENGER = DownloaderService.EXTRA_MESSAGE_HANDLER;
-
- private static class Proxy implements IDownloaderService {
- private Messenger mMsg;
-
- private void send(int method, Bundle params) {
- Message m = Message.obtain(null, method);
- m.setData(params);
- try {
- mMsg.send(m);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
-
- public Proxy(Messenger msg) {
- mMsg = msg;
- }
-
- @Override
- public void requestAbortDownload() {
- send(MSG_REQUEST_ABORT_DOWNLOAD, new Bundle());
- }
-
- @Override
- public void requestPauseDownload() {
- send(MSG_REQUEST_PAUSE_DOWNLOAD, new Bundle());
- }
-
- @Override
- public void setDownloadFlags(int flags) {
- Bundle params = new Bundle();
- params.putInt(PARAMS_FLAGS, flags);
- send(MSG_SET_DOWNLOAD_FLAGS, params);
- }
-
- @Override
- public void requestContinueDownload() {
- send(MSG_REQUEST_CONTINUE_DOWNLOAD, new Bundle());
- }
-
- @Override
- public void requestDownloadStatus() {
- send(MSG_REQUEST_DOWNLOAD_STATE, new Bundle());
- }
-
- @Override
- public void onClientUpdated(Messenger clientMessenger) {
- Bundle bundle = new Bundle(1);
- bundle.putParcelable(PARAM_MESSENGER, clientMessenger);
- send(MSG_REQUEST_CLIENT_UPDATE, bundle);
- }
- }
-
- private static class Stub implements IStub {
- private IDownloaderService mItf = null;
- final Messenger mMessenger = new Messenger(new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_REQUEST_ABORT_DOWNLOAD:
- mItf.requestAbortDownload();
- break;
- case MSG_REQUEST_CONTINUE_DOWNLOAD:
- mItf.requestContinueDownload();
- break;
- case MSG_REQUEST_PAUSE_DOWNLOAD:
- mItf.requestPauseDownload();
- break;
- case MSG_SET_DOWNLOAD_FLAGS:
- mItf.setDownloadFlags(msg.getData().getInt(PARAMS_FLAGS));
- break;
- case MSG_REQUEST_DOWNLOAD_STATE:
- mItf.requestDownloadStatus();
- break;
- case MSG_REQUEST_CLIENT_UPDATE:
- mItf.onClientUpdated((Messenger) msg.getData().getParcelable(
- PARAM_MESSENGER));
- break;
- }
- }
- });
-
- public Stub(IDownloaderService itf) {
- mItf = itf;
- }
-
- @Override
- public Messenger getMessenger() {
- return mMessenger;
- }
-
- @Override
- public void connect(Context c) {
-
- }
-
- @Override
- public void disconnect(Context c) {
-
- }
- }
-
- /**
- * Returns a proxy that will marshall calls to IDownloaderService methods
- *
- * @param ctx
- * @return
- */
- public static IDownloaderService CreateProxy(Messenger msg) {
- return new Proxy(msg);
- }
-
- /**
- * Returns a stub object that, when connected, will listen for marshalled
- * IDownloaderService methods and translate them into calls to the supplied
- * interface.
- *
- * @param itf An implementation of IDownloaderService that will be called
- * when remote method calls are unmarshalled.
- * @return
- */
- public static IStub CreateStub(IDownloaderService itf) {
- return new Stub(itf);
- }
-
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Helpers.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Helpers.java
deleted file mode 100644
index 1e84e54a0f..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Helpers.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader;
-
-import com.android.vending.expansion.downloader.R;
-
-import android.content.Context;
-import android.os.Environment;
-import android.os.StatFs;
-import android.os.SystemClock;
-import android.util.Log;
-
-import java.io.File;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.Random;
-import java.util.TimeZone;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Some helper functions for the download manager
- */
-public class Helpers {
-
- public static Random sRandom = new Random(SystemClock.uptimeMillis());
-
- /** Regex used to parse content-disposition headers */
- private static final Pattern CONTENT_DISPOSITION_PATTERN = Pattern
- .compile("attachment;\\s*filename\\s*=\\s*\"([^\"]*)\"");
-
- private Helpers() {
- }
-
- /*
- * Parse the Content-Disposition HTTP Header. The format of the header is
- * defined here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html This
- * header provides a filename for content that is going to be downloaded to
- * the file system. We only support the attachment type.
- */
- static String parseContentDisposition(String contentDisposition) {
- try {
- Matcher m = CONTENT_DISPOSITION_PATTERN.matcher(contentDisposition);
- if (m.find()) {
- return m.group(1);
- }
- } catch (IllegalStateException ex) {
- // This function is defined as returning null when it can't parse
- // the header
- }
- return null;
- }
-
- /**
- * @return the root of the filesystem containing the given path
- */
- public static File getFilesystemRoot(String path) {
- File cache = Environment.getDownloadCacheDirectory();
- if (path.startsWith(cache.getPath())) {
- return cache;
- }
- File external = Environment.getExternalStorageDirectory();
- if (path.startsWith(external.getPath())) {
- return external;
- }
- throw new IllegalArgumentException(
- "Cannot determine filesystem root for " + path);
- }
-
- public static boolean isExternalMediaMounted() {
- if (!Environment.getExternalStorageState().equals(
- Environment.MEDIA_MOUNTED)) {
- // No SD card found.
- if ( Constants.LOGVV ) {
- Log.d(Constants.TAG, "no external storage");
- }
- return false;
- }
- return true;
- }
-
- /**
- * @return the number of bytes available on the filesystem rooted at the
- * given File
- */
- public static long getAvailableBytes(File root) {
- StatFs stat = new StatFs(root.getPath());
- // put a bit of margin (in case creating the file grows the system by a
- // few blocks)
- long availableBlocks = (long) stat.getAvailableBlocks() - 4;
- return stat.getBlockSize() * availableBlocks;
- }
-
- /**
- * Checks whether the filename looks legitimate
- */
- public static boolean isFilenameValid(String filename) {
- filename = filename.replaceFirst("/+", "/"); // normalize leading
- // slashes
- return filename.startsWith(Environment.getDownloadCacheDirectory().toString())
- || filename.startsWith(Environment.getExternalStorageDirectory().toString());
- }
-
- /*
- * Delete the given file from device
- */
- /* package */static void deleteFile(String path) {
- try {
- File file = new File(path);
- file.delete();
- } catch (Exception e) {
- Log.w(Constants.TAG, "file: '" + path + "' couldn't be deleted", e);
- }
- }
-
- /**
- * Showing progress in MB here. It would be nice to choose the unit (KB, MB,
- * GB) based on total file size, but given what we know about the expected
- * ranges of file sizes for APK expansion files, it's probably not necessary.
- *
- * @param overallProgress
- * @param overallTotal
- * @return
- */
-
- static public String getDownloadProgressString(long overallProgress, long overallTotal) {
- if (overallTotal == 0) {
- if ( Constants.LOGVV ) {
- Log.e(Constants.TAG, "Notification called when total is zero");
- }
- return "";
- }
- return String.format("%.2f",
- (float) overallProgress / (1024.0f * 1024.0f))
- + "MB /" +
- String.format("%.2f", (float) overallTotal /
- (1024.0f * 1024.0f)) + "MB";
- }
-
- /**
- * Adds a percentile to getDownloadProgressString.
- *
- * @param overallProgress
- * @param overallTotal
- * @return
- */
- static public String getDownloadProgressStringNotification(long overallProgress,
- long overallTotal) {
- if (overallTotal == 0) {
- if ( Constants.LOGVV ) {
- Log.e(Constants.TAG, "Notification called when total is zero");
- }
- return "";
- }
- return getDownloadProgressString(overallProgress, overallTotal) + " (" +
- getDownloadProgressPercent(overallProgress, overallTotal) + ")";
- }
-
- public static String getDownloadProgressPercent(long overallProgress, long overallTotal) {
- if (overallTotal == 0) {
- if ( Constants.LOGVV ) {
- Log.e(Constants.TAG, "Notification called when total is zero");
- }
- return "";
- }
- return Long.toString(overallProgress * 100 / overallTotal) + "%";
- }
-
- public static String getSpeedString(float bytesPerMillisecond) {
- return String.format("%.2f", bytesPerMillisecond * 1000 / 1024);
- }
-
- public static String getTimeRemaining(long durationInMilliseconds) {
- SimpleDateFormat sdf;
- if (durationInMilliseconds > 1000 * 60 * 60) {
- sdf = new SimpleDateFormat("HH:mm", Locale.getDefault());
- } else {
- sdf = new SimpleDateFormat("mm:ss", Locale.getDefault());
- }
- return sdf.format(new Date(durationInMilliseconds - TimeZone.getDefault().getRawOffset()));
- }
-
- /**
- * Returns the file name (without full path) for an Expansion APK file from
- * the given context.
- *
- * @param c the context
- * @param mainFile true for main file, false for patch file
- * @param versionCode the version of the file
- * @return String the file name of the expansion file
- */
- public static String getExpansionAPKFileName(Context c, boolean mainFile, int versionCode) {
- return (mainFile ? "main." : "patch.") + versionCode + "." + c.getPackageName() + ".obb";
- }
-
- /**
- * Returns the filename (where the file should be saved) from info about a
- * download
- */
- static public String generateSaveFileName(Context c, String fileName) {
- String path = getSaveFilePath(c)
- + File.separator + fileName;
- return path;
- }
-
- static public String getSaveFilePath(Context c) {
- File root = Environment.getExternalStorageDirectory();
- String path = root.toString() + Constants.EXP_PATH + c.getPackageName();
- return path;
- }
-
- /**
- * Helper function to ascertain the existence of a file and return
- * true/false appropriately
- *
- * @param c the app/activity/service context
- * @param fileName the name (sans path) of the file to query
- * @param fileSize the size that the file must match
- * @param deleteFileOnMismatch if the file sizes do not match, delete the
- * file
- * @return true if it does exist, false otherwise
- */
- static public boolean doesFileExist(Context c, String fileName, long fileSize,
- boolean deleteFileOnMismatch) {
- // the file may have been delivered by Market --- let's make sure
- // it's the size we expect
- File fileForNewFile = new File(Helpers.generateSaveFileName(c, fileName));
- if (fileForNewFile.exists()) {
- if (fileForNewFile.length() == fileSize) {
- return true;
- }
- if (deleteFileOnMismatch) {
- // delete the file --- we won't be able to resume
- // because we cannot confirm the integrity of the file
- fileForNewFile.delete();
- }
- }
- return false;
- }
-
- /**
- * Converts download states that are returned by the {@link
- * IDownloaderClient#onDownloadStateChanged} callback into usable strings.
- * This is useful if using the state strings built into the library to display user messages.
- * @param state One of the STATE_* constants from {@link IDownloaderClient}.
- * @return string resource ID for the corresponding string.
- */
- static public int getDownloaderStringResourceIDFromState(int state) {
- switch (state) {
- case IDownloaderClient.STATE_IDLE:
- return R.string.state_idle;
- case IDownloaderClient.STATE_FETCHING_URL:
- return R.string.state_fetching_url;
- case IDownloaderClient.STATE_CONNECTING:
- return R.string.state_connecting;
- case IDownloaderClient.STATE_DOWNLOADING:
- return R.string.state_downloading;
- case IDownloaderClient.STATE_COMPLETED:
- return R.string.state_completed;
- case IDownloaderClient.STATE_PAUSED_NETWORK_UNAVAILABLE:
- return R.string.state_paused_network_unavailable;
- case IDownloaderClient.STATE_PAUSED_BY_REQUEST:
- return R.string.state_paused_by_request;
- case IDownloaderClient.STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION:
- return R.string.state_paused_wifi_disabled;
- case IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION:
- return R.string.state_paused_wifi_unavailable;
- case IDownloaderClient.STATE_PAUSED_WIFI_DISABLED:
- return R.string.state_paused_wifi_disabled;
- case IDownloaderClient.STATE_PAUSED_NEED_WIFI:
- return R.string.state_paused_wifi_unavailable;
- case IDownloaderClient.STATE_PAUSED_ROAMING:
- return R.string.state_paused_roaming;
- case IDownloaderClient.STATE_PAUSED_NETWORK_SETUP_FAILURE:
- return R.string.state_paused_network_setup_failure;
- case IDownloaderClient.STATE_PAUSED_SDCARD_UNAVAILABLE:
- return R.string.state_paused_sdcard_unavailable;
- case IDownloaderClient.STATE_FAILED_UNLICENSED:
- return R.string.state_failed_unlicensed;
- case IDownloaderClient.STATE_FAILED_FETCHING_URL:
- return R.string.state_failed_fetching_url;
- case IDownloaderClient.STATE_FAILED_SDCARD_FULL:
- return R.string.state_failed_sdcard_full;
- case IDownloaderClient.STATE_FAILED_CANCELED:
- return R.string.state_failed_cancelled;
- default:
- return R.string.state_unknown;
- }
- }
-
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java
deleted file mode 100644
index b8511a62a0..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader;
-
-import android.os.Messenger;
-
-/**
- * This interface should be implemented by the client activity for the
- * downloader. It is used to pass status from the service to the client.
- */
-public interface IDownloaderClient {
- static final int STATE_IDLE = 1;
- static final int STATE_FETCHING_URL = 2;
- static final int STATE_CONNECTING = 3;
- static final int STATE_DOWNLOADING = 4;
- static final int STATE_COMPLETED = 5;
-
- static final int STATE_PAUSED_NETWORK_UNAVAILABLE = 6;
- static final int STATE_PAUSED_BY_REQUEST = 7;
-
- /**
- * Both STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION and
- * STATE_PAUSED_NEED_CELLULAR_PERMISSION imply that Wi-Fi is unavailable and
- * cellular permission will restart the service. Wi-Fi disabled means that
- * the Wi-Fi manager is returning that Wi-Fi is not enabled, while in the
- * other case Wi-Fi is enabled but not available.
- */
- static final int STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION = 8;
- static final int STATE_PAUSED_NEED_CELLULAR_PERMISSION = 9;
-
- /**
- * Both STATE_PAUSED_WIFI_DISABLED and STATE_PAUSED_NEED_WIFI imply that
- * Wi-Fi is unavailable and cellular permission will NOT restart the
- * service. Wi-Fi disabled means that the Wi-Fi manager is returning that
- * Wi-Fi is not enabled, while in the other case Wi-Fi is enabled but not
- * available.
- * <p>
- * The service does not return these values. We recommend that app
- * developers with very large payloads do not allow these payloads to be
- * downloaded over cellular connections.
- */
- static final int STATE_PAUSED_WIFI_DISABLED = 10;
- static final int STATE_PAUSED_NEED_WIFI = 11;
-
- static final int STATE_PAUSED_ROAMING = 12;
-
- /**
- * Scary case. We were on a network that redirected us to another website
- * that delivered us the wrong file.
- */
- static final int STATE_PAUSED_NETWORK_SETUP_FAILURE = 13;
-
- static final int STATE_PAUSED_SDCARD_UNAVAILABLE = 14;
-
- static final int STATE_FAILED_UNLICENSED = 15;
- static final int STATE_FAILED_FETCHING_URL = 16;
- static final int STATE_FAILED_SDCARD_FULL = 17;
- static final int STATE_FAILED_CANCELED = 18;
-
- static final int STATE_FAILED = 19;
-
- /**
- * Called internally by the stub when the service is bound to the client.
- * <p>
- * Critical implementation detail. In onServiceConnected we create the
- * remote service and marshaler. This is how we pass the client information
- * back to the service so the client can be properly notified of changes. We
- * must do this every time we reconnect to the service.
- * <p>
- * That is, when you receive this callback, you should call
- * {@link DownloaderServiceMarshaller#CreateProxy} to instantiate a member
- * instance of {@link IDownloaderService}, then call
- * {@link IDownloaderService#onClientUpdated} with the Messenger retrieved
- * from your {@link IStub} proxy object.
- *
- * @param m the service Messenger. This Messenger is used to call the
- * service API from the client.
- */
- void onServiceConnected(Messenger m);
-
- /**
- * Called when the download state changes. Depending on the state, there may
- * be user requests. The service is free to change the download state in the
- * middle of a user request, so the client should be able to handle this.
- * <p>
- * The Downloader Library includes a collection of string resources that
- * correspond to each of the states, which you can use to provide users a
- * useful message based on the state provided in this callback. To fetch the
- * appropriate string for a state, call
- * {@link Helpers#getDownloaderStringResourceIDFromState}.
- * <p>
- * What this means to the developer: The application has gotten a message
- * that the download has paused due to lack of WiFi. The developer should
- * then show UI asking the user if they want to enable downloading over
- * cellular connections with appropriate warnings. If the application
- * suddenly starts downloading, the application should revert to showing the
- * progress again, rather than leaving up the download over cellular UI up.
- *
- * @param newState one of the STATE_* values defined in IDownloaderClient
- */
- void onDownloadStateChanged(int newState);
-
- /**
- * Shows the download progress. This is intended to be used to fill out a
- * client UI. This progress should only be shown in a few states such as
- * STATE_DOWNLOADING.
- *
- * @param progress the DownloadProgressInfo object containing the current
- * progress of all downloads.
- */
- void onDownloadProgress(DownloadProgressInfo progress);
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderService.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderService.java
deleted file mode 100644
index 4789afe19c..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderService.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader;
-
-import com.google.android.vending.expansion.downloader.impl.DownloaderService;
-import android.os.Messenger;
-
-/**
- * This interface is implemented by the DownloaderService and by the
- * DownloaderServiceMarshaller. It contains functions to control the service.
- * When a client binds to the service, it must call the onClientUpdated
- * function.
- * <p>
- * You can acquire a proxy that implements this interface for your service by
- * calling {@link DownloaderServiceMarshaller#CreateProxy} during the
- * {@link IDownloaderClient#onServiceConnected} callback. At which point, you
- * should immediately call {@link #onClientUpdated}.
- */
-public interface IDownloaderService {
- /**
- * Set this flag in response to the
- * IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION state and then
- * call RequestContinueDownload to resume a download
- */
- public static final int FLAGS_DOWNLOAD_OVER_CELLULAR = 1;
-
- /**
- * Request that the service abort the current download. The service should
- * respond by changing the state to {@link IDownloaderClient.STATE_ABORTED}.
- */
- void requestAbortDownload();
-
- /**
- * Request that the service pause the current download. The service should
- * respond by changing the state to
- * {@link IDownloaderClient.STATE_PAUSED_BY_REQUEST}.
- */
- void requestPauseDownload();
-
- /**
- * Request that the service continue a paused download, when in any paused
- * or failed state, including
- * {@link IDownloaderClient.STATE_PAUSED_BY_REQUEST}.
- */
- void requestContinueDownload();
-
- /**
- * Set the flags for this download (e.g.
- * {@link DownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR}).
- *
- * @param flags
- */
- void setDownloadFlags(int flags);
-
- /**
- * Requests that the download status be sent to the client.
- */
- void requestDownloadStatus();
-
- /**
- * Call this when you get {@link
- * IDownloaderClient.onServiceConnected(Messenger m)} from the
- * DownloaderClient to register the client with the service. It will
- * automatically send the current status to the client.
- *
- * @param clientMessenger
- */
- void onClientUpdated(Messenger clientMessenger);
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IStub.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IStub.java
deleted file mode 100644
index d5bc3a843e..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IStub.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader;
-
-import android.content.Context;
-import android.os.Messenger;
-
-/**
- * This is the interface that is used to connect/disconnect from the downloader
- * service.
- * <p>
- * You should get a proxy object that implements this interface by calling
- * {@link DownloaderClientMarshaller#CreateStub} in your activity when the
- * downloader service starts. Then, call {@link #connect} during your activity's
- * onResume() and call {@link #disconnect} during onStop().
- * <p>
- * Then during the {@link IDownloaderClient#onServiceConnected} callback, you
- * should call {@link #getMessenger} to pass the stub's Messenger object to
- * {@link IDownloaderService#onClientUpdated}.
- */
-public interface IStub {
- Messenger getMessenger();
-
- void connect(Context c);
-
- void disconnect(Context c);
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/SystemFacade.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/SystemFacade.java
deleted file mode 100644
index 12edd97ab2..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/SystemFacade.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-
-/**
- * Contains useful helper functions, typically tied to the application context.
- */
-class SystemFacade {
- private Context mContext;
- private NotificationManager mNotificationManager;
-
- public SystemFacade(Context context) {
- mContext = context;
- mNotificationManager = (NotificationManager)
- mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- }
-
- public long currentTimeMillis() {
- return System.currentTimeMillis();
- }
-
- public Integer getActiveNetworkType() {
- ConnectivityManager connectivity =
- (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- if (connectivity == null) {
- Log.w(Constants.TAG, "couldn't get connectivity manager");
- return null;
- }
-
- NetworkInfo activeInfo = connectivity.getActiveNetworkInfo();
- if (activeInfo == null) {
- if (Constants.LOGVV) {
- Log.v(Constants.TAG, "network is not available");
- }
- return null;
- }
- return activeInfo.getType();
- }
-
- public boolean isNetworkRoaming() {
- ConnectivityManager connectivity =
- (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- if (connectivity == null) {
- Log.w(Constants.TAG, "couldn't get connectivity manager");
- return false;
- }
-
- NetworkInfo info = connectivity.getActiveNetworkInfo();
- boolean isMobile = (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE);
- TelephonyManager tm = (TelephonyManager) mContext
- .getSystemService(Context.TELEPHONY_SERVICE);
- if (null == tm) {
- Log.w(Constants.TAG, "couldn't get telephony manager");
- return false;
- }
- boolean isRoaming = isMobile && tm.isNetworkRoaming();
- if (Constants.LOGVV && isRoaming) {
- Log.v(Constants.TAG, "network is roaming");
- }
- return isRoaming;
- }
-
- public Long getMaxBytesOverMobile() {
- return (long) Integer.MAX_VALUE;
- }
-
- public Long getRecommendedMaxBytesOverMobile() {
- return 2097152L;
- }
-
- public void sendBroadcast(Intent intent) {
- mContext.sendBroadcast(intent);
- }
-
- public boolean userOwnsPackage(int uid, String packageName) throws NameNotFoundException {
- return mContext.getPackageManager().getApplicationInfo(packageName, 0).uid == uid;
- }
-
- public void postNotification(long id, Notification notification) {
- /**
- * TODO: The system notification manager takes ints, not longs, as IDs,
- * but the download manager uses IDs take straight from the database,
- * which are longs. This will have to be dealt with at some point.
- */
- mNotificationManager.notify((int) id, notification);
- }
-
- public void cancelNotification(long id) {
- mNotificationManager.cancel((int) id);
- }
-
- public void cancelAllNotifications() {
- mNotificationManager.cancelAll();
- }
-
- public void startThread(Thread thread) {
- thread.start();
- }
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/AndroidHttpClient.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/AndroidHttpClient.java
deleted file mode 100644
index 4667acce67..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/AndroidHttpClient.java
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * This is a port of AndroidHttpClient to pre-Froyo devices, that takes advantage of
- * the SSLSessionCache added Froyo devices using reflection.
- */
-
-package com.google.android.vending.expansion.downloader.impl;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.URI;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpEntityEnclosingRequest;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpRequestInterceptor;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.ResponseHandler;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.params.HttpClientParams;
-import org.apache.http.client.protocol.ClientContext;
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.scheme.PlainSocketFactory;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.scheme.SocketFactory;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.entity.AbstractHttpEntity;
-import org.apache.http.entity.ByteArrayEntity;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.client.RequestWrapper;
-import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpParams;
-import org.apache.http.params.HttpProtocolParams;
-import org.apache.http.protocol.BasicHttpContext;
-import org.apache.http.protocol.BasicHttpProcessor;
-import org.apache.http.protocol.HttpContext;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.net.SSLCertificateSocketFactory;
-import android.os.Looper;
-import android.util.Log;
-
-/**
- * Subclass of the Apache {@link DefaultHttpClient} that is configured with
- * reasonable default settings and registered schemes for Android, and
- * also lets the user add {@link HttpRequestInterceptor} classes.
- * Don't create this directly, use the {@link #newInstance} factory method.
- *
- * <p>This client processes cookies but does not retain them by default.
- * To retain cookies, simply add a cookie store to the HttpContext:</p>
- *
- * <pre>context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);</pre>
- */
-public final class AndroidHttpClient implements HttpClient {
-
- static Class<?> sSslSessionCacheClass;
- static {
- // if we are on Froyo+ devices, we can take advantage of the SSLSessionCache
- try {
- sSslSessionCacheClass = Class.forName("android.net.SSLSessionCache");
- } catch (Exception e) {
-
- }
- }
-
- // Gzip of data shorter than this probably won't be worthwhile
- public static long DEFAULT_SYNC_MIN_GZIP_BYTES = 256;
-
- // Default connection and socket timeout of 60 seconds. Tweak to taste.
- private static final int SOCKET_OPERATION_TIMEOUT = 60 * 1000;
-
- private static final String TAG = "AndroidHttpClient";
-
-
- /** Interceptor throws an exception if the executing thread is blocked */
- private static final HttpRequestInterceptor sThreadCheckInterceptor =
- new HttpRequestInterceptor() {
- public void process(HttpRequest request, HttpContext context) {
- // Prevent the HttpRequest from being sent on the main thread
- if (Looper.myLooper() != null && Looper.myLooper() == Looper.getMainLooper() ) {
- throw new RuntimeException("This thread forbids HTTP requests");
- }
- }
- };
-
- /**
- * Create a new HttpClient with reasonable defaults (which you can update).
- *
- * @param userAgent to report in your HTTP requests
- * @param context to use for caching SSL sessions (may be null for no caching)
- * @return AndroidHttpClient for you to use for all your requests.
- */
- public static AndroidHttpClient newInstance(String userAgent, Context context) {
- HttpParams params = new BasicHttpParams();
-
- // Turn off stale checking. Our connections break all the time anyway,
- // and it's not worth it to pay the penalty of checking every time.
- HttpConnectionParams.setStaleCheckingEnabled(params, false);
-
- HttpConnectionParams.setConnectionTimeout(params, SOCKET_OPERATION_TIMEOUT);
- HttpConnectionParams.setSoTimeout(params, SOCKET_OPERATION_TIMEOUT);
- HttpConnectionParams.setSocketBufferSize(params, 8192);
-
- // Don't handle redirects -- return them to the caller. Our code
- // often wants to re-POST after a redirect, which we must do ourselves.
- HttpClientParams.setRedirecting(params, false);
-
- Object sessionCache = null;
- // Use a session cache for SSL sockets -- Froyo only
- if ( null != context && null != sSslSessionCacheClass ) {
- Constructor<?> ct;
- try {
- ct = sSslSessionCacheClass.getConstructor(Context.class);
- sessionCache = ct.newInstance(context);
- } catch (SecurityException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (NoSuchMethodException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalArgumentException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InstantiationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- // Set the specified user agent and register standard protocols.
- HttpProtocolParams.setUserAgent(params, userAgent);
- SchemeRegistry schemeRegistry = new SchemeRegistry();
- schemeRegistry.register(new Scheme("http",
- PlainSocketFactory.getSocketFactory(), 80));
- SocketFactory sslCertificateSocketFactory = null;
- if ( null != sessionCache ) {
- Method getHttpSocketFactoryMethod;
- try {
- getHttpSocketFactoryMethod = SSLCertificateSocketFactory.class.getDeclaredMethod("getHttpSocketFactory",Integer.TYPE, sSslSessionCacheClass);
- sslCertificateSocketFactory = (SocketFactory)getHttpSocketFactoryMethod.invoke(null, SOCKET_OPERATION_TIMEOUT, sessionCache);
- } catch (SecurityException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (NoSuchMethodException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalArgumentException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- if ( null == sslCertificateSocketFactory ) {
- sslCertificateSocketFactory = SSLSocketFactory.getSocketFactory();
- }
- schemeRegistry.register(new Scheme("https",
- sslCertificateSocketFactory, 443));
-
- ClientConnectionManager manager =
- new ThreadSafeClientConnManager(params, schemeRegistry);
-
- // We use a factory method to modify superclass initialization
- // parameters without the funny call-a-static-method dance.
- return new AndroidHttpClient(manager, params);
- }
-
- /**
- * Create a new HttpClient with reasonable defaults (which you can update).
- * @param userAgent to report in your HTTP requests.
- * @return AndroidHttpClient for you to use for all your requests.
- */
- public static AndroidHttpClient newInstance(String userAgent) {
- return newInstance(userAgent, null /* session cache */);
- }
-
- private final HttpClient delegate;
-
- private RuntimeException mLeakedException = new IllegalStateException(
- "AndroidHttpClient created and never closed");
-
- private AndroidHttpClient(ClientConnectionManager ccm, HttpParams params) {
- this.delegate = new DefaultHttpClient(ccm, params) {
- @Override
- protected BasicHttpProcessor createHttpProcessor() {
- // Add interceptor to prevent making requests from main thread.
- BasicHttpProcessor processor = super.createHttpProcessor();
- processor.addRequestInterceptor(sThreadCheckInterceptor);
- processor.addRequestInterceptor(new CurlLogger());
-
- return processor;
- }
-
- @Override
- protected HttpContext createHttpContext() {
- // Same as DefaultHttpClient.createHttpContext() minus the
- // cookie store.
- HttpContext context = new BasicHttpContext();
- context.setAttribute(
- ClientContext.AUTHSCHEME_REGISTRY,
- getAuthSchemes());
- context.setAttribute(
- ClientContext.COOKIESPEC_REGISTRY,
- getCookieSpecs());
- context.setAttribute(
- ClientContext.CREDS_PROVIDER,
- getCredentialsProvider());
- return context;
- }
- };
- }
-
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
- if (mLeakedException != null) {
- Log.e(TAG, "Leak found", mLeakedException);
- mLeakedException = null;
- }
- }
-
- /**
- * Modifies a request to indicate to the server that we would like a
- * gzipped response. (Uses the "Accept-Encoding" HTTP header.)
- * @param request the request to modify
- * @see #getUngzippedContent
- */
- public static void modifyRequestToAcceptGzipResponse(HttpRequest request) {
- request.addHeader("Accept-Encoding", "gzip");
- }
-
- /**
- * Gets the input stream from a response entity. If the entity is gzipped
- * then this will get a stream over the uncompressed data.
- *
- * @param entity the entity whose content should be read
- * @return the input stream to read from
- * @throws IOException
- */
- public static InputStream getUngzippedContent(HttpEntity entity)
- throws IOException {
- InputStream responseStream = entity.getContent();
- if (responseStream == null) return responseStream;
- Header header = entity.getContentEncoding();
- if (header == null) return responseStream;
- String contentEncoding = header.getValue();
- if (contentEncoding == null) return responseStream;
- if (contentEncoding.contains("gzip")) responseStream
- = new GZIPInputStream(responseStream);
- return responseStream;
- }
-
- /**
- * Release resources associated with this client. You must call this,
- * or significant resources (sockets and memory) may be leaked.
- */
- public void close() {
- if (mLeakedException != null) {
- getConnectionManager().shutdown();
- mLeakedException = null;
- }
- }
-
- public HttpParams getParams() {
- return delegate.getParams();
- }
-
- public ClientConnectionManager getConnectionManager() {
- return delegate.getConnectionManager();
- }
-
- public HttpResponse execute(HttpUriRequest request) throws IOException {
- return delegate.execute(request);
- }
-
- public HttpResponse execute(HttpUriRequest request, HttpContext context)
- throws IOException {
- return delegate.execute(request, context);
- }
-
- public HttpResponse execute(HttpHost target, HttpRequest request)
- throws IOException {
- return delegate.execute(target, request);
- }
-
- public HttpResponse execute(HttpHost target, HttpRequest request,
- HttpContext context) throws IOException {
- return delegate.execute(target, request, context);
- }
-
- public <T> T execute(HttpUriRequest request,
- ResponseHandler<? extends T> responseHandler)
- throws IOException, ClientProtocolException {
- return delegate.execute(request, responseHandler);
- }
-
- public <T> T execute(HttpUriRequest request,
- ResponseHandler<? extends T> responseHandler, HttpContext context)
- throws IOException, ClientProtocolException {
- return delegate.execute(request, responseHandler, context);
- }
-
- public <T> T execute(HttpHost target, HttpRequest request,
- ResponseHandler<? extends T> responseHandler) throws IOException,
- ClientProtocolException {
- return delegate.execute(target, request, responseHandler);
- }
-
- public <T> T execute(HttpHost target, HttpRequest request,
- ResponseHandler<? extends T> responseHandler, HttpContext context)
- throws IOException, ClientProtocolException {
- return delegate.execute(target, request, responseHandler, context);
- }
-
- /**
- * Compress data to send to server.
- * Creates a Http Entity holding the gzipped data.
- * The data will not be compressed if it is too short.
- * @param data The bytes to compress
- * @return Entity holding the data
- */
- public static AbstractHttpEntity getCompressedEntity(byte data[], ContentResolver resolver)
- throws IOException {
- AbstractHttpEntity entity;
- if (data.length < getMinGzipSize(resolver)) {
- entity = new ByteArrayEntity(data);
- } else {
- ByteArrayOutputStream arr = new ByteArrayOutputStream();
- OutputStream zipper = new GZIPOutputStream(arr);
- zipper.write(data);
- zipper.close();
- entity = new ByteArrayEntity(arr.toByteArray());
- entity.setContentEncoding("gzip");
- }
- return entity;
- }
-
- /**
- * Retrieves the minimum size for compressing data.
- * Shorter data will not be compressed.
- */
- public static long getMinGzipSize(ContentResolver resolver) {
- return DEFAULT_SYNC_MIN_GZIP_BYTES; // For now, this is just a constant.
- }
-
- /* cURL logging support. */
-
- /**
- * Logging tag and level.
- */
- private static class LoggingConfiguration {
-
- private final String tag;
- private final int level;
-
- private LoggingConfiguration(String tag, int level) {
- this.tag = tag;
- this.level = level;
- }
-
- /**
- * Returns true if logging is turned on for this configuration.
- */
- private boolean isLoggable() {
- return Log.isLoggable(tag, level);
- }
-
- /**
- * Prints a message using this configuration.
- */
- private void println(String message) {
- Log.println(level, tag, message);
- }
- }
-
- /** cURL logging configuration. */
- private volatile LoggingConfiguration curlConfiguration;
-
- /**
- * Enables cURL request logging for this client.
- *
- * @param name to log messages with
- * @param level at which to log messages (see {@link android.util.Log})
- */
- public void enableCurlLogging(String name, int level) {
- if (name == null) {
- throw new NullPointerException("name");
- }
- if (level < Log.VERBOSE || level > Log.ASSERT) {
- throw new IllegalArgumentException("Level is out of range ["
- + Log.VERBOSE + ".." + Log.ASSERT + "]");
- }
-
- curlConfiguration = new LoggingConfiguration(name, level);
- }
-
- /**
- * Disables cURL logging for this client.
- */
- public void disableCurlLogging() {
- curlConfiguration = null;
- }
-
- /**
- * Logs cURL commands equivalent to requests.
- */
- private class CurlLogger implements HttpRequestInterceptor {
- public void process(HttpRequest request, HttpContext context)
- throws HttpException, IOException {
- LoggingConfiguration configuration = curlConfiguration;
- if (configuration != null
- && configuration.isLoggable()
- && request instanceof HttpUriRequest) {
- // Never print auth token -- we used to check ro.secure=0 to
- // enable that, but can't do that in unbundled code.
- configuration.println(toCurl((HttpUriRequest) request, false));
- }
- }
- }
-
- /**
- * Generates a cURL command equivalent to the given request.
- */
- private static String toCurl(HttpUriRequest request, boolean logAuthToken) throws IOException {
- StringBuilder builder = new StringBuilder();
-
- builder.append("curl ");
-
- for (Header header: request.getAllHeaders()) {
- if (!logAuthToken
- && (header.getName().equals("Authorization") ||
- header.getName().equals("Cookie"))) {
- continue;
- }
- builder.append("--header \"");
- builder.append(header.toString().trim());
- builder.append("\" ");
- }
-
- URI uri = request.getURI();
-
- // If this is a wrapped request, use the URI from the original
- // request instead. getURI() on the wrapper seems to return a
- // relative URI. We want an absolute URI.
- if (request instanceof RequestWrapper) {
- HttpRequest original = ((RequestWrapper) request).getOriginal();
- if (original instanceof HttpUriRequest) {
- uri = ((HttpUriRequest) original).getURI();
- }
- }
-
- builder.append("\"");
- builder.append(uri);
- builder.append("\"");
-
- if (request instanceof HttpEntityEnclosingRequest) {
- HttpEntityEnclosingRequest entityRequest =
- (HttpEntityEnclosingRequest) request;
- HttpEntity entity = entityRequest.getEntity();
- if (entity != null && entity.isRepeatable()) {
- if (entity.getContentLength() < 1024) {
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
- entity.writeTo(stream);
- String entityString = stream.toString();
-
- // TODO: Check the content type, too.
- builder.append(" --data-ascii \"")
- .append(entityString)
- .append("\"");
- } else {
- builder.append(" [TOO MUCH DATA TO INCLUDE]");
- }
- }
- }
-
- return builder.toString();
- }
-
- /**
- * Returns the date of the given HTTP date string. This method can identify
- * and parse the date formats emitted by common HTTP servers, such as
- * <a href="http://www.ietf.org/rfc/rfc0822.txt">RFC 822</a>,
- * <a href="http://www.ietf.org/rfc/rfc0850.txt">RFC 850</a>,
- * <a href="http://www.ietf.org/rfc/rfc1036.txt">RFC 1036</a>,
- * <a href="http://www.ietf.org/rfc/rfc1123.txt">RFC 1123</a> and
- * <a href="http://www.opengroup.org/onlinepubs/007908799/xsh/asctime.html">ANSI
- * C's asctime()</a>.
- *
- * @return the number of milliseconds since Jan. 1, 1970, midnight GMT.
- * @throws IllegalArgumentException if {@code dateString} is not a date or
- * of an unsupported format.
- */
- public static long parseDate(String dateString) {
- return HttpDateTime.parse(dateString);
- }
-} \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java
deleted file mode 100755
index b77af7e085..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader.impl;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.util.Log;
-
-/**
- * This service differs from IntentService in a few minor ways/ It will not
- * auto-stop itself after the intent is handled unless the target returns "true"
- * in should stop. Since the goal of this service is to handle a single kind of
- * intent, it does not queue up batches of intents of the same type.
- */
-public abstract class CustomIntentService extends Service {
- private String mName;
- private boolean mRedelivery;
- private volatile ServiceHandler mServiceHandler;
- private volatile Looper mServiceLooper;
- private static final String LOG_TAG = "CancellableIntentService";
- private static final int WHAT_MESSAGE = -10;
-
- public CustomIntentService(String paramString) {
- this.mName = paramString;
- }
-
- @Override
- public IBinder onBind(Intent paramIntent) {
- return null;
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- HandlerThread localHandlerThread = new HandlerThread("IntentService["
- + this.mName + "]");
- localHandlerThread.start();
- this.mServiceLooper = localHandlerThread.getLooper();
- this.mServiceHandler = new ServiceHandler(this.mServiceLooper);
- }
-
- @Override
- public void onDestroy() {
- Thread localThread = this.mServiceLooper.getThread();
- if ((localThread != null) && (localThread.isAlive())) {
- localThread.interrupt();
- }
- this.mServiceLooper.quit();
- Log.d(LOG_TAG, "onDestroy");
- }
-
- protected abstract void onHandleIntent(Intent paramIntent);
-
- protected abstract boolean shouldStop();
-
- @Override
- public void onStart(Intent paramIntent, int startId) {
- if (!this.mServiceHandler.hasMessages(WHAT_MESSAGE)) {
- Message localMessage = this.mServiceHandler.obtainMessage();
- localMessage.arg1 = startId;
- localMessage.obj = paramIntent;
- localMessage.what = WHAT_MESSAGE;
- this.mServiceHandler.sendMessage(localMessage);
- }
- }
-
- @Override
- public int onStartCommand(Intent paramIntent, int flags, int startId) {
- onStart(paramIntent, startId);
- return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
- }
-
- public void setIntentRedelivery(boolean enabled) {
- this.mRedelivery = enabled;
- }
-
- private final class ServiceHandler extends Handler {
- public ServiceHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message paramMessage) {
- CustomIntentService.this
- .onHandleIntent((Intent) paramMessage.obj);
- if (shouldStop()) {
- Log.d(LOG_TAG, "stopSelf");
- CustomIntentService.this.stopSelf(paramMessage.arg1);
- Log.d(LOG_TAG, "afterStopSelf");
- }
- }
- }
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomNotificationFactory.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomNotificationFactory.java
deleted file mode 100644
index 9a0ca02122..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomNotificationFactory.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader.impl;
-
-/**
- * Uses the class-loader model to utilize the updated notification builders in
- * Honeycomb while maintaining a compatible version for older devices.
- */
-public class CustomNotificationFactory {
- static public DownloadNotification.ICustomNotification createCustomNotification() {
- if (android.os.Build.VERSION.SDK_INT > 13)
- return new V14CustomNotification();
- else
- return new V3CustomNotification();
- }
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java
deleted file mode 100644
index 45111b16a3..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader.impl;
-
-import com.google.android.vending.expansion.downloader.Constants;
-import com.google.android.vending.expansion.downloader.Helpers;
-
-import android.util.Log;
-
-/**
- * Representation of information about an individual download from the database.
- */
-public class DownloadInfo {
- public String mUri;
- public final int mIndex;
- public final String mFileName;
- public String mETag;
- public long mTotalBytes;
- public long mCurrentBytes;
- public long mLastMod;
- public int mStatus;
- public int mControl;
- public int mNumFailed;
- public int mRetryAfter;
- public int mRedirectCount;
-
- boolean mInitialized;
-
- public int mFuzz;
-
- public DownloadInfo(int index, String fileName, String pkg) {
- mFuzz = Helpers.sRandom.nextInt(1001);
- mFileName = fileName;
- mIndex = index;
- }
-
- public void resetDownload() {
- mCurrentBytes = 0;
- mETag = "";
- mLastMod = 0;
- mStatus = 0;
- mControl = 0;
- mNumFailed = 0;
- mRetryAfter = 0;
- mRedirectCount = 0;
- }
-
- /**
- * Returns the time when a download should be restarted.
- */
- public long restartTime(long now) {
- if (mNumFailed == 0) {
- return now;
- }
- if (mRetryAfter > 0) {
- return mLastMod + mRetryAfter;
- }
- return mLastMod +
- Constants.RETRY_FIRST_DELAY *
- (1000 + mFuzz) * (1 << (mNumFailed - 1));
- }
-
- public void logVerboseInfo() {
- Log.v(Constants.TAG, "Service adding new entry");
- Log.v(Constants.TAG, "FILENAME: " + mFileName);
- Log.v(Constants.TAG, "URI : " + mUri);
- Log.v(Constants.TAG, "FILENAME: " + mFileName);
- Log.v(Constants.TAG, "CONTROL : " + mControl);
- Log.v(Constants.TAG, "STATUS : " + mStatus);
- Log.v(Constants.TAG, "FAILED_C: " + mNumFailed);
- Log.v(Constants.TAG, "RETRY_AF: " + mRetryAfter);
- Log.v(Constants.TAG, "REDIRECT: " + mRedirectCount);
- Log.v(Constants.TAG, "LAST_MOD: " + mLastMod);
- Log.v(Constants.TAG, "TOTAL : " + mTotalBytes);
- Log.v(Constants.TAG, "CURRENT : " + mCurrentBytes);
- Log.v(Constants.TAG, "ETAG : " + mETag);
- }
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java
deleted file mode 100644
index eef205d7b7..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader.impl;
-
-import com.android.vending.expansion.downloader.R;
-import com.google.android.vending.expansion.downloader.DownloadProgressInfo;
-import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller;
-import com.google.android.vending.expansion.downloader.Helpers;
-import com.google.android.vending.expansion.downloader.IDownloaderClient;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.os.Messenger;
-
-/**
- * This class handles displaying the notification associated with the download
- * queue going on in the download manager. It handles multiple status types;
- * Some require user interaction and some do not. Some of the user interactions
- * may be transient. (for example: the user is queried to continue the download
- * on 3G when it started on WiFi, but then the phone locks onto WiFi again so
- * the prompt automatically goes away)
- * <p/>
- * The application interface for the downloader also needs to understand and
- * handle these transient states.
- */
-public class DownloadNotification implements IDownloaderClient {
-
- private int mState;
- private final Context mContext;
- private final NotificationManager mNotificationManager;
- private String mCurrentTitle;
-
- private IDownloaderClient mClientProxy;
- final ICustomNotification mCustomNotification;
- private Notification mNotification;
- private Notification mCurrentNotification;
- private CharSequence mLabel;
- private String mCurrentText;
- private PendingIntent mContentIntent;
- private DownloadProgressInfo mProgressInfo;
-
- static final String LOGTAG = "DownloadNotification";
- static final int NOTIFICATION_ID = LOGTAG.hashCode();
-
- public PendingIntent getClientIntent() {
- return mContentIntent;
- }
-
- public void setClientIntent(PendingIntent mClientIntent) {
- this.mContentIntent = mClientIntent;
- }
-
- public void resendState() {
- if (null != mClientProxy) {
- mClientProxy.onDownloadStateChanged(mState);
- }
- }
-
- @Override
- public void onDownloadStateChanged(int newState) {
- if (null != mClientProxy) {
- mClientProxy.onDownloadStateChanged(newState);
- }
- if (newState != mState) {
- mState = newState;
- if (newState == IDownloaderClient.STATE_IDLE || null == mContentIntent) {
- return;
- }
- int stringDownloadID;
- int iconResource;
- boolean ongoingEvent;
-
- // get the new title string and paused text
- switch (newState) {
- case 0:
- iconResource = android.R.drawable.stat_sys_warning;
- stringDownloadID = R.string.state_unknown;
- ongoingEvent = false;
- break;
-
- case IDownloaderClient.STATE_DOWNLOADING:
- iconResource = android.R.drawable.stat_sys_download;
- stringDownloadID = Helpers.getDownloaderStringResourceIDFromState(newState);
- ongoingEvent = true;
- break;
-
- case IDownloaderClient.STATE_FETCHING_URL:
- case IDownloaderClient.STATE_CONNECTING:
- iconResource = android.R.drawable.stat_sys_download_done;
- stringDownloadID = Helpers.getDownloaderStringResourceIDFromState(newState);
- ongoingEvent = true;
- break;
-
- case IDownloaderClient.STATE_COMPLETED:
- case IDownloaderClient.STATE_PAUSED_BY_REQUEST:
- iconResource = android.R.drawable.stat_sys_download_done;
- stringDownloadID = Helpers.getDownloaderStringResourceIDFromState(newState);
- ongoingEvent = false;
- break;
-
- case IDownloaderClient.STATE_FAILED:
- case IDownloaderClient.STATE_FAILED_CANCELED:
- case IDownloaderClient.STATE_FAILED_FETCHING_URL:
- case IDownloaderClient.STATE_FAILED_SDCARD_FULL:
- case IDownloaderClient.STATE_FAILED_UNLICENSED:
- iconResource = android.R.drawable.stat_sys_warning;
- stringDownloadID = Helpers.getDownloaderStringResourceIDFromState(newState);
- ongoingEvent = false;
- break;
-
- default:
- iconResource = android.R.drawable.stat_sys_warning;
- stringDownloadID = Helpers.getDownloaderStringResourceIDFromState(newState);
- ongoingEvent = true;
- break;
- }
- mCurrentText = mContext.getString(stringDownloadID);
- mCurrentTitle = mLabel.toString();
- mCurrentNotification.tickerText = mLabel + ": " + mCurrentText;
- mCurrentNotification.icon = iconResource;
- mCurrentNotification.setLatestEventInfo(mContext, mCurrentTitle, mCurrentText,
- mContentIntent);
- if (ongoingEvent) {
- mCurrentNotification.flags |= Notification.FLAG_ONGOING_EVENT;
- } else {
- mCurrentNotification.flags &= ~Notification.FLAG_ONGOING_EVENT;
- mCurrentNotification.flags |= Notification.FLAG_AUTO_CANCEL;
- }
- mNotificationManager.notify(NOTIFICATION_ID, mCurrentNotification);
- }
- }
-
- @Override
- public void onDownloadProgress(DownloadProgressInfo progress) {
- mProgressInfo = progress;
- if (null != mClientProxy) {
- mClientProxy.onDownloadProgress(progress);
- }
- if (progress.mOverallTotal <= 0) {
- // we just show the text
- mNotification.tickerText = mCurrentTitle;
- mNotification.icon = android.R.drawable.stat_sys_download;
- mNotification.setLatestEventInfo(mContext, mLabel, mCurrentText, mContentIntent);
- mCurrentNotification = mNotification;
- } else {
- mCustomNotification.setCurrentBytes(progress.mOverallProgress);
- mCustomNotification.setTotalBytes(progress.mOverallTotal);
- mCustomNotification.setIcon(android.R.drawable.stat_sys_download);
- mCustomNotification.setPendingIntent(mContentIntent);
- mCustomNotification.setTicker(mLabel + ": " + mCurrentText);
- mCustomNotification.setTitle(mLabel);
- mCustomNotification.setTimeRemaining(progress.mTimeRemaining);
- mCurrentNotification = mCustomNotification.updateNotification(mContext);
- }
- mNotificationManager.notify(NOTIFICATION_ID, mCurrentNotification);
- }
-
- public interface ICustomNotification {
- void setTitle(CharSequence title);
-
- void setTicker(CharSequence ticker);
-
- void setPendingIntent(PendingIntent mContentIntent);
-
- void setTotalBytes(long totalBytes);
-
- void setCurrentBytes(long currentBytes);
-
- void setIcon(int iconResource);
-
- void setTimeRemaining(long timeRemaining);
-
- Notification updateNotification(Context c);
- }
-
- /**
- * Called in response to onClientUpdated. Creates a new proxy and notifies
- * it of the current state.
- *
- * @param msg the client Messenger to notify
- */
- public void setMessenger(Messenger msg) {
- mClientProxy = DownloaderClientMarshaller.CreateProxy(msg);
- if (null != mProgressInfo) {
- mClientProxy.onDownloadProgress(mProgressInfo);
- }
- if (mState != -1) {
- mClientProxy.onDownloadStateChanged(mState);
- }
- }
-
- /**
- * Constructor
- *
- * @param ctx The context to use to obtain access to the Notification
- * Service
- */
- DownloadNotification(Context ctx, CharSequence applicationLabel) {
- mState = -1;
- mContext = ctx;
- mLabel = applicationLabel;
- mNotificationManager = (NotificationManager)
- mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- mCustomNotification = CustomNotificationFactory
- .createCustomNotification();
- mNotification = new Notification();
- mCurrentNotification = mNotification;
-
- }
-
- @Override
- public void onServiceConnected(Messenger m) {
- }
-
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java
deleted file mode 100644
index 056d1eca0b..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java
+++ /dev/null
@@ -1,963 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader.impl;
-
-import com.google.android.vending.expansion.downloader.Constants;
-import com.google.android.vending.expansion.downloader.Helpers;
-import com.google.android.vending.expansion.downloader.IDownloaderClient;
-
-import org.apache.http.Header;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.conn.params.ConnRouteParams;
-
-import android.content.Context;
-import android.net.Proxy;
-import android.os.PowerManager;
-import android.os.Process;
-import android.util.Log;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.SyncFailedException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Locale;
-
-/**
- * Runs an actual download
- */
-public class DownloadThread {
-
- private Context mContext;
- private DownloadInfo mInfo;
- private DownloaderService mService;
- private final DownloadsDB mDB;
- private final DownloadNotification mNotification;
- private String mUserAgent;
-
- public DownloadThread(DownloadInfo info, DownloaderService service,
- DownloadNotification notification) {
- mContext = service;
- mInfo = info;
- mService = service;
- mNotification = notification;
- mDB = DownloadsDB.getDB(service);
- mUserAgent = "APKXDL (Linux; U; Android " + android.os.Build.VERSION.RELEASE + ";"
- + Locale.getDefault().toString() + "; " + android.os.Build.DEVICE + "/"
- + android.os.Build.ID + ")" +
- service.getPackageName();
- }
-
- /**
- * Returns the default user agent
- */
- private String userAgent() {
- return mUserAgent;
- }
-
- /**
- * State for the entire run() method.
- */
- private static class State {
- public String mFilename;
- public FileOutputStream mStream;
- public boolean mCountRetry = false;
- public int mRetryAfter = 0;
- public int mRedirectCount = 0;
- public String mNewUri;
- public boolean mGotData = false;
- public String mRequestUri;
-
- public State(DownloadInfo info, DownloaderService service) {
- mRedirectCount = info.mRedirectCount;
- mRequestUri = info.mUri;
- mFilename = service.generateTempSaveFileName(info.mFileName);
- }
- }
-
- /**
- * State within executeDownload()
- */
- private static class InnerState {
- public int mBytesSoFar = 0;
- public int mBytesThisSession = 0;
- public String mHeaderETag;
- public boolean mContinuingDownload = false;
- public String mHeaderContentLength;
- public String mHeaderContentDisposition;
- public String mHeaderContentLocation;
- public int mBytesNotified = 0;
- public long mTimeLastNotification = 0;
- }
-
- /**
- * Raised from methods called by run() to indicate that the current request
- * should be stopped immediately. Note the message passed to this exception
- * will be logged and therefore must be guaranteed not to contain any PII,
- * meaning it generally can't include any information about the request URI,
- * headers, or destination filename.
- */
- private class StopRequest extends Throwable {
- /**
- *
- */
- private static final long serialVersionUID = 6338592678988347973L;
- public int mFinalStatus;
-
- public StopRequest(int finalStatus, String message) {
- super(message);
- mFinalStatus = finalStatus;
- }
-
- public StopRequest(int finalStatus, String message, Throwable throwable) {
- super(message, throwable);
- mFinalStatus = finalStatus;
- }
- }
-
- /**
- * Raised from methods called by executeDownload() to indicate that the
- * download should be retried immediately.
- */
- private class RetryDownload extends Throwable {
-
- /**
- *
- */
- private static final long serialVersionUID = 6196036036517540229L;
- }
-
- /**
- * Returns the preferred proxy to be used by clients. This is a wrapper
- * around {@link android.net.Proxy#getHost()}. Currently no proxy will be
- * returned for localhost or if the active network is Wi-Fi.
- *
- * @param context the context which will be passed to
- * {@link android.net.Proxy#getHost()}
- * @param url the target URL for the request
- * @note Calling this method requires permission
- * android.permission.ACCESS_NETWORK_STATE
- * @return The preferred proxy to be used by clients, or null if there is no
- * proxy.
- */
- public HttpHost getPreferredHttpHost(Context context,
- String url) {
- if (!isLocalHost(url) && !mService.isWiFi()) {
- final String proxyHost = Proxy.getHost(context);
- if (proxyHost != null) {
- return new HttpHost(proxyHost, Proxy.getPort(context), "http");
- }
- }
-
- return null;
- }
-
- static final private boolean isLocalHost(String url) {
- if (url == null) {
- return false;
- }
-
- try {
- final URI uri = URI.create(url);
- final String host = uri.getHost();
- if (host != null) {
- // TODO: InetAddress.isLoopbackAddress should be used to check
- // for localhost. However no public factory methods exist which
- // can be used without triggering DNS lookup if host is not
- // localhost.
- if (host.equalsIgnoreCase("localhost") ||
- host.equals("127.0.0.1") ||
- host.equals("[::1]")) {
- return true;
- }
- }
- } catch (IllegalArgumentException iex) {
- // Ignore (URI.create)
- }
-
- return false;
- }
-
- /**
- * Executes the download in a separate thread
- */
- public void run() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-
- State state = new State(mInfo, mService);
- AndroidHttpClient client = null;
- PowerManager.WakeLock wakeLock = null;
- int finalStatus = DownloaderService.STATUS_UNKNOWN_ERROR;
-
- try {
- PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Constants.TAG);
- wakeLock.acquire();
-
- if (Constants.LOGV) {
- Log.v(Constants.TAG, "initiating download for " + mInfo.mFileName);
- Log.v(Constants.TAG, " at " + mInfo.mUri);
- }
-
- client = AndroidHttpClient.newInstance(userAgent(), mContext);
-
- boolean finished = false;
- while (!finished) {
- if (Constants.LOGV) {
- Log.v(Constants.TAG, "initiating download for " + mInfo.mFileName);
- Log.v(Constants.TAG, " at " + mInfo.mUri);
- }
- // Set or unset proxy, which may have changed since last GET
- // request.
- // setDefaultProxy() supports null as proxy parameter.
- ConnRouteParams.setDefaultProxy(client.getParams(),
- getPreferredHttpHost(mContext, state.mRequestUri));
- HttpGet request = new HttpGet(state.mRequestUri);
- try {
- executeDownload(state, client, request);
- finished = true;
- } catch (RetryDownload exc) {
- // fall through
- } finally {
- request.abort();
- request = null;
- }
- }
-
- if (Constants.LOGV) {
- Log.v(Constants.TAG, "download completed for " + mInfo.mFileName);
- Log.v(Constants.TAG, " at " + mInfo.mUri);
- }
- finalizeDestinationFile(state);
- finalStatus = DownloaderService.STATUS_SUCCESS;
- } catch (StopRequest error) {
- // remove the cause before printing, in case it contains PII
- Log.w(Constants.TAG,
- "Aborting request for download " + mInfo.mFileName + ": " + error.getMessage());
- error.printStackTrace();
- finalStatus = error.mFinalStatus;
- // fall through to finally block
- } catch (Throwable ex) { // sometimes the socket code throws unchecked
- // exceptions
- Log.w(Constants.TAG, "Exception for " + mInfo.mFileName + ": " + ex);
- finalStatus = DownloaderService.STATUS_UNKNOWN_ERROR;
- // falls through to the code that reports an error
- } finally {
- if (wakeLock != null) {
- wakeLock.release();
- wakeLock = null;
- }
- if (client != null) {
- client.close();
- client = null;
- }
- cleanupDestination(state, finalStatus);
- notifyDownloadCompleted(finalStatus, state.mCountRetry, state.mRetryAfter,
- state.mRedirectCount, state.mGotData, state.mFilename);
- }
- }
-
- /**
- * Fully execute a single download request - setup and send the request,
- * handle the response, and transfer the data to the destination file.
- */
- private void executeDownload(State state, AndroidHttpClient client, HttpGet request)
- throws StopRequest, RetryDownload {
- InnerState innerState = new InnerState();
- byte data[] = new byte[Constants.BUFFER_SIZE];
-
- checkPausedOrCanceled(state);
-
- setupDestinationFile(state, innerState);
- addRequestHeaders(innerState, request);
-
- // check just before sending the request to avoid using an invalid
- // connection at all
- checkConnectivity(state);
-
- mNotification.onDownloadStateChanged(IDownloaderClient.STATE_CONNECTING);
- HttpResponse response = sendRequest(state, client, request);
- handleExceptionalStatus(state, innerState, response);
-
- if (Constants.LOGV) {
- Log.v(Constants.TAG, "received response for " + mInfo.mUri);
- }
-
- processResponseHeaders(state, innerState, response);
- InputStream entityStream = openResponseEntity(state, response);
- mNotification.onDownloadStateChanged(IDownloaderClient.STATE_DOWNLOADING);
- transferData(state, innerState, data, entityStream);
- }
-
- /**
- * Check if current connectivity is valid for this request.
- */
- private void checkConnectivity(State state) throws StopRequest {
- switch (mService.getNetworkAvailabilityState(mDB)) {
- case DownloaderService.NETWORK_OK:
- return;
- case DownloaderService.NETWORK_NO_CONNECTION:
- throw new StopRequest(DownloaderService.STATUS_WAITING_FOR_NETWORK,
- "waiting for network to return");
- case DownloaderService.NETWORK_TYPE_DISALLOWED_BY_REQUESTOR:
- throw new StopRequest(
- DownloaderService.STATUS_QUEUED_FOR_WIFI_OR_CELLULAR_PERMISSION,
- "waiting for wifi or for download over cellular to be authorized");
- case DownloaderService.NETWORK_CANNOT_USE_ROAMING:
- throw new StopRequest(DownloaderService.STATUS_WAITING_FOR_NETWORK,
- "roaming is not allowed");
- case DownloaderService.NETWORK_UNUSABLE_DUE_TO_SIZE:
- throw new StopRequest(DownloaderService.STATUS_QUEUED_FOR_WIFI, "waiting for wifi");
- }
- }
-
- /**
- * Transfer as much data as possible from the HTTP response to the
- * destination file.
- *
- * @param data buffer to use to read data
- * @param entityStream stream for reading the HTTP response entity
- */
- private void transferData(State state, InnerState innerState, byte[] data,
- InputStream entityStream) throws StopRequest {
- for (;;) {
- int bytesRead = readFromResponse(state, innerState, data, entityStream);
- if (bytesRead == -1) { // success, end of stream already reached
- handleEndOfStream(state, innerState);
- return;
- }
-
- state.mGotData = true;
- writeDataToDestination(state, data, bytesRead);
- innerState.mBytesSoFar += bytesRead;
- innerState.mBytesThisSession += bytesRead;
- reportProgress(state, innerState);
-
- checkPausedOrCanceled(state);
- }
- }
-
- /**
- * Called after a successful completion to take any necessary action on the
- * downloaded file.
- */
- private void finalizeDestinationFile(State state) throws StopRequest {
- syncDestination(state);
- String tempFilename = state.mFilename;
- String finalFilename = Helpers.generateSaveFileName(mService, mInfo.mFileName);
- if (!state.mFilename.equals(finalFilename)) {
- File startFile = new File(tempFilename);
- File destFile = new File(finalFilename);
- if (mInfo.mTotalBytes != -1 && mInfo.mCurrentBytes == mInfo.mTotalBytes) {
- if (!startFile.renameTo(destFile)) {
- throw new StopRequest(DownloaderService.STATUS_FILE_ERROR,
- "unable to finalize destination file");
- }
- } else {
- throw new StopRequest(DownloaderService.STATUS_FILE_DELIVERED_INCORRECTLY,
- "file delivered with incorrect size. probably due to network not browser configured");
- }
- }
- }
-
- /**
- * Called just before the thread finishes, regardless of status, to take any
- * necessary action on the downloaded file.
- */
- private void cleanupDestination(State state, int finalStatus) {
- closeDestination(state);
- if (state.mFilename != null && DownloaderService.isStatusError(finalStatus)) {
- new File(state.mFilename).delete();
- state.mFilename = null;
- }
- }
-
- /**
- * Sync the destination file to storage.
- */
- private void syncDestination(State state) {
- FileOutputStream downloadedFileStream = null;
- try {
- downloadedFileStream = new FileOutputStream(state.mFilename, true);
- downloadedFileStream.getFD().sync();
- } catch (FileNotFoundException ex) {
- Log.w(Constants.TAG, "file " + state.mFilename + " not found: " + ex);
- } catch (SyncFailedException ex) {
- Log.w(Constants.TAG, "file " + state.mFilename + " sync failed: " + ex);
- } catch (IOException ex) {
- Log.w(Constants.TAG, "IOException trying to sync " + state.mFilename + ": " + ex);
- } catch (RuntimeException ex) {
- Log.w(Constants.TAG, "exception while syncing file: ", ex);
- } finally {
- if (downloadedFileStream != null) {
- try {
- downloadedFileStream.close();
- } catch (IOException ex) {
- Log.w(Constants.TAG, "IOException while closing synced file: ", ex);
- } catch (RuntimeException ex) {
- Log.w(Constants.TAG, "exception while closing file: ", ex);
- }
- }
- }
- }
-
- /**
- * Close the destination output stream.
- */
- private void closeDestination(State state) {
- try {
- // close the file
- if (state.mStream != null) {
- state.mStream.close();
- state.mStream = null;
- }
- } catch (IOException ex) {
- if (Constants.LOGV) {
- Log.v(Constants.TAG, "exception when closing the file after download : " + ex);
- }
- // nothing can really be done if the file can't be closed
- }
- }
-
- /**
- * Check if the download has been paused or canceled, stopping the request
- * appropriately if it has been.
- */
- private void checkPausedOrCanceled(State state) throws StopRequest {
- if (mService.getControl() == DownloaderService.CONTROL_PAUSED) {
- int status = mService.getStatus();
- switch (status) {
- case DownloaderService.STATUS_PAUSED_BY_APP:
- throw new StopRequest(mService.getStatus(),
- "download paused");
- }
- }
- }
-
- /**
- * Report download progress through the database if necessary.
- */
- private void reportProgress(State state, InnerState innerState) {
- long now = System.currentTimeMillis();
- if (innerState.mBytesSoFar - innerState.mBytesNotified
- > Constants.MIN_PROGRESS_STEP
- && now - innerState.mTimeLastNotification
- > Constants.MIN_PROGRESS_TIME) {
- // we store progress updates to the database here
- mInfo.mCurrentBytes = innerState.mBytesSoFar;
- mDB.updateDownloadCurrentBytes(mInfo);
-
- innerState.mBytesNotified = innerState.mBytesSoFar;
- innerState.mTimeLastNotification = now;
-
- long totalBytesSoFar = innerState.mBytesThisSession + mService.mBytesSoFar;
-
- if (Constants.LOGVV) {
- Log.v(Constants.TAG, "downloaded " + mInfo.mCurrentBytes + " out of "
- + mInfo.mTotalBytes);
- Log.v(Constants.TAG, " total " + totalBytesSoFar + " out of "
- + mService.mTotalLength);
- }
-
- mService.notifyUpdateBytes(totalBytesSoFar);
- }
- }
-
- /**
- * Write a data buffer to the destination file.
- *
- * @param data buffer containing the data to write
- * @param bytesRead how many bytes to write from the buffer
- */
- private void writeDataToDestination(State state, byte[] data, int bytesRead)
- throws StopRequest {
- for (;;) {
- try {
- if (state.mStream == null) {
- state.mStream = new FileOutputStream(state.mFilename, true);
- }
- state.mStream.write(data, 0, bytesRead);
- // we close after every write --- this may be too inefficient
- closeDestination(state);
- return;
- } catch (IOException ex) {
- if (!Helpers.isExternalMediaMounted()) {
- throw new StopRequest(DownloaderService.STATUS_DEVICE_NOT_FOUND_ERROR,
- "external media not mounted while writing destination file");
- }
-
- long availableBytes =
- Helpers.getAvailableBytes(Helpers.getFilesystemRoot(state.mFilename));
- if (availableBytes < bytesRead) {
- throw new StopRequest(DownloaderService.STATUS_INSUFFICIENT_SPACE_ERROR,
- "insufficient space while writing destination file", ex);
- }
- throw new StopRequest(DownloaderService.STATUS_FILE_ERROR,
- "while writing destination file: " + ex.toString(), ex);
- }
- }
- }
-
- /**
- * Called when we've reached the end of the HTTP response stream, to update
- * the database and check for consistency.
- */
- private void handleEndOfStream(State state, InnerState innerState) throws StopRequest {
- mInfo.mCurrentBytes = innerState.mBytesSoFar;
- // this should always be set from the market
- // if ( innerState.mHeaderContentLength == null ) {
- // mInfo.mTotalBytes = innerState.mBytesSoFar;
- // }
- mDB.updateDownload(mInfo);
-
- boolean lengthMismatched = (innerState.mHeaderContentLength != null)
- && (innerState.mBytesSoFar != Integer.parseInt(innerState.mHeaderContentLength));
- if (lengthMismatched) {
- if (cannotResume(innerState)) {
- throw new StopRequest(DownloaderService.STATUS_CANNOT_RESUME,
- "mismatched content length");
- } else {
- throw new StopRequest(getFinalStatusForHttpError(state),
- "closed socket before end of file");
- }
- }
- }
-
- private boolean cannotResume(InnerState innerState) {
- return innerState.mBytesSoFar > 0 && innerState.mHeaderETag == null;
- }
-
- /**
- * Read some data from the HTTP response stream, handling I/O errors.
- *
- * @param data buffer to use to read data
- * @param entityStream stream for reading the HTTP response entity
- * @return the number of bytes actually read or -1 if the end of the stream
- * has been reached
- */
- private int readFromResponse(State state, InnerState innerState, byte[] data,
- InputStream entityStream) throws StopRequest {
- try {
- return entityStream.read(data);
- } catch (IOException ex) {
- logNetworkState();
- mInfo.mCurrentBytes = innerState.mBytesSoFar;
- mDB.updateDownload(mInfo);
- if (cannotResume(innerState)) {
- String message = "while reading response: " + ex.toString()
- + ", can't resume interrupted download with no ETag";
- throw new StopRequest(DownloaderService.STATUS_CANNOT_RESUME,
- message, ex);
- } else {
- throw new StopRequest(getFinalStatusForHttpError(state),
- "while reading response: " + ex.toString(), ex);
- }
- }
- }
-
- /**
- * Open a stream for the HTTP response entity, handling I/O errors.
- *
- * @return an InputStream to read the response entity
- */
- private InputStream openResponseEntity(State state, HttpResponse response)
- throws StopRequest {
- try {
- return response.getEntity().getContent();
- } catch (IOException ex) {
- logNetworkState();
- throw new StopRequest(getFinalStatusForHttpError(state),
- "while getting entity: " + ex.toString(), ex);
- }
- }
-
- private void logNetworkState() {
- if (Constants.LOGX) {
- Log.i(Constants.TAG,
- "Net "
- + (mService.getNetworkAvailabilityState(mDB) == DownloaderService.NETWORK_OK ? "Up"
- : "Down"));
- }
- }
-
- /**
- * Read HTTP response headers and take appropriate action, including setting
- * up the destination file and updating the database.
- */
- private void processResponseHeaders(State state, InnerState innerState, HttpResponse response)
- throws StopRequest {
- if (innerState.mContinuingDownload) {
- // ignore response headers on resume requests
- return;
- }
-
- readResponseHeaders(state, innerState, response);
-
- try {
- state.mFilename = mService.generateSaveFile(mInfo.mFileName, mInfo.mTotalBytes);
- } catch (DownloaderService.GenerateSaveFileError exc) {
- throw new StopRequest(exc.mStatus, exc.mMessage);
- }
- try {
- state.mStream = new FileOutputStream(state.mFilename);
- } catch (FileNotFoundException exc) {
- // make sure the directory exists
- File pathFile = new File(Helpers.getSaveFilePath(mService));
- try {
- if (pathFile.mkdirs()) {
- state.mStream = new FileOutputStream(state.mFilename);
- }
- } catch (Exception ex) {
- throw new StopRequest(DownloaderService.STATUS_FILE_ERROR,
- "while opening destination file: " + exc.toString(), exc);
- }
- }
- if (Constants.LOGV) {
- Log.v(Constants.TAG, "writing " + mInfo.mUri + " to " + state.mFilename);
- }
-
- updateDatabaseFromHeaders(state, innerState);
- // check connectivity again now that we know the total size
- checkConnectivity(state);
- }
-
- /**
- * Update necessary database fields based on values of HTTP response headers
- * that have been read.
- */
- private void updateDatabaseFromHeaders(State state, InnerState innerState) {
- mInfo.mETag = innerState.mHeaderETag;
- mDB.updateDownload(mInfo);
- }
-
- /**
- * Read headers from the HTTP response and store them into local state.
- */
- private void readResponseHeaders(State state, InnerState innerState, HttpResponse response)
- throws StopRequest {
- Header header = response.getFirstHeader("Content-Disposition");
- if (header != null) {
- innerState.mHeaderContentDisposition = header.getValue();
- }
- header = response.getFirstHeader("Content-Location");
- if (header != null) {
- innerState.mHeaderContentLocation = header.getValue();
- }
- header = response.getFirstHeader("ETag");
- if (header != null) {
- innerState.mHeaderETag = header.getValue();
- }
- String headerTransferEncoding = null;
- header = response.getFirstHeader("Transfer-Encoding");
- if (header != null) {
- headerTransferEncoding = header.getValue();
- }
- String headerContentType = null;
- header = response.getFirstHeader("Content-Type");
- if (header != null) {
- headerContentType = header.getValue();
- if (!headerContentType.equals("application/vnd.android.obb")) {
- throw new StopRequest(DownloaderService.STATUS_FILE_DELIVERED_INCORRECTLY,
- "file delivered with incorrect Mime type");
- }
- }
-
- if (headerTransferEncoding == null) {
- header = response.getFirstHeader("Content-Length");
- if (header != null) {
- innerState.mHeaderContentLength = header.getValue();
- // this is always set from Market
- long contentLength = Long.parseLong(innerState.mHeaderContentLength);
- if (contentLength != -1 && contentLength != mInfo.mTotalBytes) {
- // we're most likely on a bad wifi connection -- we should
- // probably
- // also look at the mime type --- but the size mismatch is
- // enough
- // to tell us that something is wrong here
- Log.e(Constants.TAG, "Incorrect file size delivered.");
- }
- }
- } else {
- // Ignore content-length with transfer-encoding - 2616 4.4 3
- if (Constants.LOGVV) {
- Log.v(Constants.TAG,
- "ignoring content-length because of xfer-encoding");
- }
- }
- if (Constants.LOGVV) {
- Log.v(Constants.TAG, "Content-Disposition: " +
- innerState.mHeaderContentDisposition);
- Log.v(Constants.TAG, "Content-Length: " + innerState.mHeaderContentLength);
- Log.v(Constants.TAG, "Content-Location: " + innerState.mHeaderContentLocation);
- Log.v(Constants.TAG, "ETag: " + innerState.mHeaderETag);
- Log.v(Constants.TAG, "Transfer-Encoding: " + headerTransferEncoding);
- }
-
- boolean noSizeInfo = innerState.mHeaderContentLength == null
- && (headerTransferEncoding == null
- || !headerTransferEncoding.equalsIgnoreCase("chunked"));
- if (noSizeInfo) {
- throw new StopRequest(DownloaderService.STATUS_HTTP_DATA_ERROR,
- "can't know size of download, giving up");
- }
- }
-
- /**
- * Check the HTTP response status and handle anything unusual (e.g. not
- * 200/206).
- */
- private void handleExceptionalStatus(State state, InnerState innerState, HttpResponse response)
- throws StopRequest, RetryDownload {
- int statusCode = response.getStatusLine().getStatusCode();
- if (statusCode == 503 && mInfo.mNumFailed < Constants.MAX_RETRIES) {
- handleServiceUnavailable(state, response);
- }
- if (statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 307) {
- handleRedirect(state, response, statusCode);
- }
-
- int expectedStatus = innerState.mContinuingDownload ? 206
- : DownloaderService.STATUS_SUCCESS;
- if (statusCode != expectedStatus) {
- handleOtherStatus(state, innerState, statusCode);
- } else {
- // no longer redirected
- state.mRedirectCount = 0;
- }
- }
-
- /**
- * Handle a status that we don't know how to deal with properly.
- */
- private void handleOtherStatus(State state, InnerState innerState, int statusCode)
- throws StopRequest {
- int finalStatus;
- if (DownloaderService.isStatusError(statusCode)) {
- finalStatus = statusCode;
- } else if (statusCode >= 300 && statusCode < 400) {
- finalStatus = DownloaderService.STATUS_UNHANDLED_REDIRECT;
- } else if (innerState.mContinuingDownload && statusCode == DownloaderService.STATUS_SUCCESS) {
- finalStatus = DownloaderService.STATUS_CANNOT_RESUME;
- } else {
- finalStatus = DownloaderService.STATUS_UNHANDLED_HTTP_CODE;
- }
- throw new StopRequest(finalStatus, "http error " + statusCode);
- }
-
- /**
- * Handle a 3xx redirect status.
- */
- private void handleRedirect(State state, HttpResponse response, int statusCode)
- throws StopRequest, RetryDownload {
- if (Constants.LOGVV) {
- Log.v(Constants.TAG, "got HTTP redirect " + statusCode);
- }
- if (state.mRedirectCount >= Constants.MAX_REDIRECTS) {
- throw new StopRequest(DownloaderService.STATUS_TOO_MANY_REDIRECTS, "too many redirects");
- }
- Header header = response.getFirstHeader("Location");
- if (header == null) {
- return;
- }
- if (Constants.LOGVV) {
- Log.v(Constants.TAG, "Location :" + header.getValue());
- }
-
- String newUri;
- try {
- newUri = new URI(mInfo.mUri).resolve(new URI(header.getValue())).toString();
- } catch (URISyntaxException ex) {
- if (Constants.LOGV) {
- Log.d(Constants.TAG, "Couldn't resolve redirect URI " + header.getValue()
- + " for " + mInfo.mUri);
- }
- throw new StopRequest(DownloaderService.STATUS_HTTP_DATA_ERROR,
- "Couldn't resolve redirect URI");
- }
- ++state.mRedirectCount;
- state.mRequestUri = newUri;
- if (statusCode == 301 || statusCode == 303) {
- // use the new URI for all future requests (should a retry/resume be
- // necessary)
- state.mNewUri = newUri;
- }
- throw new RetryDownload();
- }
-
- /**
- * Add headers for this download to the HTTP request to allow for resume.
- */
- private void addRequestHeaders(InnerState innerState, HttpGet request) {
- if (innerState.mContinuingDownload) {
- if (innerState.mHeaderETag != null) {
- request.addHeader("If-Match", innerState.mHeaderETag);
- }
- request.addHeader("Range", "bytes=" + innerState.mBytesSoFar + "-");
- }
- }
-
- /**
- * Handle a 503 Service Unavailable status by processing the Retry-After
- * header.
- */
- private void handleServiceUnavailable(State state, HttpResponse response) throws StopRequest {
- if (Constants.LOGVV) {
- Log.v(Constants.TAG, "got HTTP response code 503");
- }
- state.mCountRetry = true;
- Header header = response.getFirstHeader("Retry-After");
- if (header != null) {
- try {
- if (Constants.LOGVV) {
- Log.v(Constants.TAG, "Retry-After :" + header.getValue());
- }
- state.mRetryAfter = Integer.parseInt(header.getValue());
- if (state.mRetryAfter < 0) {
- state.mRetryAfter = 0;
- } else {
- if (state.mRetryAfter < Constants.MIN_RETRY_AFTER) {
- state.mRetryAfter = Constants.MIN_RETRY_AFTER;
- } else if (state.mRetryAfter > Constants.MAX_RETRY_AFTER) {
- state.mRetryAfter = Constants.MAX_RETRY_AFTER;
- }
- state.mRetryAfter += Helpers.sRandom.nextInt(Constants.MIN_RETRY_AFTER + 1);
- state.mRetryAfter *= 1000;
- }
- } catch (NumberFormatException ex) {
- // ignored - retryAfter stays 0 in this case.
- }
- }
- throw new StopRequest(DownloaderService.STATUS_WAITING_TO_RETRY,
- "got 503 Service Unavailable, will retry later");
- }
-
- /**
- * Send the request to the server, handling any I/O exceptions.
- */
- private HttpResponse sendRequest(State state, AndroidHttpClient client, HttpGet request)
- throws StopRequest {
- try {
- return client.execute(request);
- } catch (IllegalArgumentException ex) {
- throw new StopRequest(DownloaderService.STATUS_HTTP_DATA_ERROR,
- "while trying to execute request: " + ex.toString(), ex);
- } catch (IOException ex) {
- logNetworkState();
- throw new StopRequest(getFinalStatusForHttpError(state),
- "while trying to execute request: " + ex.toString(), ex);
- }
- }
-
- private int getFinalStatusForHttpError(State state) {
- if (mService.getNetworkAvailabilityState(mDB) != DownloaderService.NETWORK_OK) {
- return DownloaderService.STATUS_WAITING_FOR_NETWORK;
- } else if (mInfo.mNumFailed < Constants.MAX_RETRIES) {
- state.mCountRetry = true;
- return DownloaderService.STATUS_WAITING_TO_RETRY;
- } else {
- Log.w(Constants.TAG, "reached max retries for " + mInfo.mNumFailed);
- return DownloaderService.STATUS_HTTP_DATA_ERROR;
- }
- }
-
- /**
- * Prepare the destination file to receive data. If the file already exists,
- * we'll set up appropriately for resumption.
- */
- private void setupDestinationFile(State state, InnerState innerState)
- throws StopRequest {
- if (state.mFilename != null) { // only true if we've already run a
- // thread for this download
- if (!Helpers.isFilenameValid(state.mFilename)) {
- // this should never happen
- throw new StopRequest(DownloaderService.STATUS_FILE_ERROR,
- "found invalid internal destination filename");
- }
- // We're resuming a download that got interrupted
- File f = new File(state.mFilename);
- if (f.exists()) {
- long fileLength = f.length();
- if (fileLength == 0) {
- // The download hadn't actually started, we can restart from
- // scratch
- f.delete();
- state.mFilename = null;
- } else if (mInfo.mETag == null) {
- // This should've been caught upon failure
- f.delete();
- throw new StopRequest(DownloaderService.STATUS_CANNOT_RESUME,
- "Trying to resume a download that can't be resumed");
- } else {
- // All right, we'll be able to resume this download
- try {
- state.mStream = new FileOutputStream(state.mFilename, true);
- } catch (FileNotFoundException exc) {
- throw new StopRequest(DownloaderService.STATUS_FILE_ERROR,
- "while opening destination for resuming: " + exc.toString(), exc);
- }
- innerState.mBytesSoFar = (int) fileLength;
- if (mInfo.mTotalBytes != -1) {
- innerState.mHeaderContentLength = Long.toString(mInfo.mTotalBytes);
- }
- innerState.mHeaderETag = mInfo.mETag;
- innerState.mContinuingDownload = true;
- }
- }
- }
-
- if (state.mStream != null) {
- closeDestination(state);
- }
- }
-
- /**
- * Stores information about the completed download, and notifies the
- * initiating application.
- */
- private void notifyDownloadCompleted(
- int status, boolean countRetry, int retryAfter, int redirectCount, boolean gotData,
- String filename) {
- updateDownloadDatabase(
- status, countRetry, retryAfter, redirectCount, gotData, filename);
- if (DownloaderService.isStatusCompleted(status)) {
- // TBD: send status update?
- }
- }
-
- private void updateDownloadDatabase(
- int status, boolean countRetry, int retryAfter, int redirectCount, boolean gotData,
- String filename) {
- mInfo.mStatus = status;
- mInfo.mRetryAfter = retryAfter;
- mInfo.mRedirectCount = redirectCount;
- mInfo.mLastMod = System.currentTimeMillis();
- if (!countRetry) {
- mInfo.mNumFailed = 0;
- } else if (gotData) {
- mInfo.mNumFailed = 1;
- } else {
- mInfo.mNumFailed++;
- }
- mDB.updateDownload(mInfo);
- }
-
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java
deleted file mode 100644
index 627bf3eedd..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java
+++ /dev/null
@@ -1,1341 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader.impl;
-
-import com.google.android.vending.expansion.downloader.Constants;
-import com.google.android.vending.expansion.downloader.DownloadProgressInfo;
-import com.google.android.vending.expansion.downloader.DownloaderServiceMarshaller;
-import com.google.android.vending.expansion.downloader.Helpers;
-import com.google.android.vending.expansion.downloader.IDownloaderClient;
-import com.google.android.vending.expansion.downloader.IDownloaderService;
-import com.google.android.vending.expansion.downloader.IStub;
-import com.google.android.vending.licensing.AESObfuscator;
-import com.google.android.vending.licensing.APKExpansionPolicy;
-import com.google.android.vending.licensing.LicenseChecker;
-import com.google.android.vending.licensing.LicenseCheckerCallback;
-import com.google.android.vending.licensing.Policy;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.wifi.WifiManager;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Messenger;
-import android.os.SystemClock;
-import android.provider.Settings.Secure;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-
-import java.io.File;
-
-/**
- * Performs the background downloads requested by applications that use the
- * Downloads provider. This service does not run as a foreground task, so
- * Android may kill it off at will, but it will try to restart itself if it can.
- * Note that Android by default will kill off any process that has an open file
- * handle on the shared (SD Card) partition if the partition is unmounted.
- */
-public abstract class DownloaderService extends CustomIntentService implements IDownloaderService {
-
- public DownloaderService() {
- super("LVLDownloadService");
- }
-
- private static final String LOG_TAG = "LVLDL";
-
- // the following NETWORK_* constants are used to indicates specific reasons
- // for disallowing a
- // download from using a network, since specific causes can require special
- // handling
-
- /**
- * The network is usable for the given download.
- */
- public static final int NETWORK_OK = 1;
-
- /**
- * There is no network connectivity.
- */
- public static final int NETWORK_NO_CONNECTION = 2;
-
- /**
- * The download exceeds the maximum size for this network.
- */
- public static final int NETWORK_UNUSABLE_DUE_TO_SIZE = 3;
-
- /**
- * The download exceeds the recommended maximum size for this network, the
- * user must confirm for this download to proceed without WiFi.
- */
- public static final int NETWORK_RECOMMENDED_UNUSABLE_DUE_TO_SIZE = 4;
-
- /**
- * The current connection is roaming, and the download can't proceed over a
- * roaming connection.
- */
- public static final int NETWORK_CANNOT_USE_ROAMING = 5;
-
- /**
- * The app requesting the download specific that it can't use the current
- * network connection.
- */
- public static final int NETWORK_TYPE_DISALLOWED_BY_REQUESTOR = 6;
-
- /**
- * For intents used to notify the user that a download exceeds a size
- * threshold, if this extra is true, WiFi is required for this download
- * size; otherwise, it is only recommended.
- */
- public static final String EXTRA_IS_WIFI_REQUIRED = "isWifiRequired";
- public static final String EXTRA_FILE_NAME = "downloadId";
-
- /**
- * Used with DOWNLOAD_STATUS
- */
- public static final String EXTRA_STATUS_STATE = "ESS";
- public static final String EXTRA_STATUS_TOTAL_SIZE = "ETS";
- public static final String EXTRA_STATUS_CURRENT_FILE_SIZE = "CFS";
- public static final String EXTRA_STATUS_TOTAL_PROGRESS = "TFP";
- public static final String EXTRA_STATUS_CURRENT_PROGRESS = "CFP";
-
- public static final String ACTION_DOWNLOADS_CHANGED = "downloadsChanged";
-
- /**
- * Broadcast intent action sent by the download manager when a download
- * completes.
- */
- public final static String ACTION_DOWNLOAD_COMPLETE = "lvldownloader.intent.action.DOWNLOAD_COMPLETE";
-
- /**
- * Broadcast intent action sent by the download manager when download status
- * changes.
- */
- public final static String ACTION_DOWNLOAD_STATUS = "lvldownloader.intent.action.DOWNLOAD_STATUS";
-
- /*
- * Lists the states that the download manager can set on a download to
- * notify applications of the download progress. The codes follow the HTTP
- * families:<br> 1xx: informational<br> 2xx: success<br> 3xx: redirects (not
- * used by the download manager)<br> 4xx: client errors<br> 5xx: server
- * errors
- */
-
- /**
- * Returns whether the status is informational (i.e. 1xx).
- */
- public static boolean isStatusInformational(int status) {
- return (status >= 100 && status < 200);
- }
-
- /**
- * Returns whether the status is a success (i.e. 2xx).
- */
- public static boolean isStatusSuccess(int status) {
- return (status >= 200 && status < 300);
- }
-
- /**
- * Returns whether the status is an error (i.e. 4xx or 5xx).
- */
- public static boolean isStatusError(int status) {
- return (status >= 400 && status < 600);
- }
-
- /**
- * Returns whether the status is a client error (i.e. 4xx).
- */
- public static boolean isStatusClientError(int status) {
- return (status >= 400 && status < 500);
- }
-
- /**
- * Returns whether the status is a server error (i.e. 5xx).
- */
- public static boolean isStatusServerError(int status) {
- return (status >= 500 && status < 600);
- }
-
- /**
- * Returns whether the download has completed (either with success or
- * error).
- */
- public static boolean isStatusCompleted(int status) {
- return (status >= 200 && status < 300)
- || (status >= 400 && status < 600);
- }
-
- /**
- * This download hasn't stated yet
- */
- public static final int STATUS_PENDING = 190;
-
- /**
- * This download has started
- */
- public static final int STATUS_RUNNING = 192;
-
- /**
- * This download has been paused by the owning app.
- */
- public static final int STATUS_PAUSED_BY_APP = 193;
-
- /**
- * This download encountered some network error and is waiting before
- * retrying the request.
- */
- public static final int STATUS_WAITING_TO_RETRY = 194;
-
- /**
- * This download is waiting for network connectivity to proceed.
- */
- public static final int STATUS_WAITING_FOR_NETWORK = 195;
-
- /**
- * This download is waiting for a Wi-Fi connection to proceed or for
- * permission to download over cellular.
- */
- public static final int STATUS_QUEUED_FOR_WIFI_OR_CELLULAR_PERMISSION = 196;
-
- /**
- * This download is waiting for a Wi-Fi connection to proceed.
- */
- public static final int STATUS_QUEUED_FOR_WIFI = 197;
-
- /**
- * This download has successfully completed. Warning: there might be other
- * status values that indicate success in the future. Use isSucccess() to
- * capture the entire category.
- *
- * @hide
- */
- public static final int STATUS_SUCCESS = 200;
-
- /**
- * The requested URL is no longer available
- */
- public static final int STATUS_FORBIDDEN = 403;
-
- /**
- * The file was delivered incorrectly
- */
- public static final int STATUS_FILE_DELIVERED_INCORRECTLY = 487;
-
- /**
- * The requested destination file already exists.
- */
- public static final int STATUS_FILE_ALREADY_EXISTS_ERROR = 488;
-
- /**
- * Some possibly transient error occurred, but we can't resume the download.
- */
- public static final int STATUS_CANNOT_RESUME = 489;
-
- /**
- * This download was canceled
- *
- * @hide
- */
- public static final int STATUS_CANCELED = 490;
-
- /**
- * This download has completed with an error. Warning: there will be other
- * status values that indicate errors in the future. Use isStatusError() to
- * capture the entire category.
- */
- public static final int STATUS_UNKNOWN_ERROR = 491;
-
- /**
- * This download couldn't be completed because of a storage issue.
- * Typically, that's because the filesystem is missing or full. Use the more
- * specific {@link #STATUS_INSUFFICIENT_SPACE_ERROR} and
- * {@link #STATUS_DEVICE_NOT_FOUND_ERROR} when appropriate.
- *
- * @hide
- */
- public static final int STATUS_FILE_ERROR = 492;
-
- /**
- * This download couldn't be completed because of an HTTP redirect response
- * that the download manager couldn't handle.
- *
- * @hide
- */
- public static final int STATUS_UNHANDLED_REDIRECT = 493;
-
- /**
- * This download couldn't be completed because of an unspecified unhandled
- * HTTP code.
- *
- * @hide
- */
- public static final int STATUS_UNHANDLED_HTTP_CODE = 494;
-
- /**
- * This download couldn't be completed because of an error receiving or
- * processing data at the HTTP level.
- *
- * @hide
- */
- public static final int STATUS_HTTP_DATA_ERROR = 495;
-
- /**
- * This download couldn't be completed because of an HttpException while
- * setting up the request.
- *
- * @hide
- */
- public static final int STATUS_HTTP_EXCEPTION = 496;
-
- /**
- * This download couldn't be completed because there were too many
- * redirects.
- *
- * @hide
- */
- public static final int STATUS_TOO_MANY_REDIRECTS = 497;
-
- /**
- * This download couldn't be completed due to insufficient storage space.
- * Typically, this is because the SD card is full.
- *
- * @hide
- */
- public static final int STATUS_INSUFFICIENT_SPACE_ERROR = 498;
-
- /**
- * This download couldn't be completed because no external storage device
- * was found. Typically, this is because the SD card is not mounted.
- *
- * @hide
- */
- public static final int STATUS_DEVICE_NOT_FOUND_ERROR = 499;
-
- /**
- * This download is allowed to run.
- *
- * @hide
- */
- public static final int CONTROL_RUN = 0;
-
- /**
- * This download must pause at the first opportunity.
- *
- * @hide
- */
- public static final int CONTROL_PAUSED = 1;
-
- /**
- * This download is visible but only shows in the notifications while it's
- * in progress.
- *
- * @hide
- */
- public static final int VISIBILITY_VISIBLE = 0;
-
- /**
- * This download is visible and shows in the notifications while in progress
- * and after completion.
- *
- * @hide
- */
- public static final int VISIBILITY_VISIBLE_NOTIFY_COMPLETED = 1;
-
- /**
- * This download doesn't show in the UI or in the notifications.
- *
- * @hide
- */
- public static final int VISIBILITY_HIDDEN = 2;
-
- /**
- * Bit flag for {@link #setAllowedNetworkTypes} corresponding to
- * {@link ConnectivityManager#TYPE_MOBILE}.
- */
- public static final int NETWORK_MOBILE = 1 << 0;
-
- /**
- * Bit flag for {@link #setAllowedNetworkTypes} corresponding to
- * {@link ConnectivityManager#TYPE_WIFI}.
- */
- public static final int NETWORK_WIFI = 1 << 1;
-
- private final static String TEMP_EXT = ".tmp";
-
- /**
- * Service thread status
- */
- private static boolean sIsRunning;
-
- @Override
- public IBinder onBind(Intent paramIntent) {
- Log.d(Constants.TAG, "Service Bound");
- return this.mServiceMessenger.getBinder();
- }
-
- /**
- * Network state.
- */
- private boolean mIsConnected;
- private boolean mIsFailover;
- private boolean mIsCellularConnection;
- private boolean mIsRoaming;
- private boolean mIsAtLeast3G;
- private boolean mIsAtLeast4G;
- private boolean mStateChanged;
-
- /**
- * Download state
- */
- private int mControl;
- private int mStatus;
-
- public boolean isWiFi() {
- return mIsConnected && !mIsCellularConnection;
- }
-
- /**
- * Bindings to important services
- */
- private ConnectivityManager mConnectivityManager;
- private WifiManager mWifiManager;
-
- /**
- * Package we are downloading for (defaults to package of application)
- */
- private PackageInfo mPackageInfo;
-
- /**
- * Byte counts
- */
- long mBytesSoFar;
- long mTotalLength;
- int mFileCount;
-
- /**
- * Used for calculating time remaining and speed
- */
- long mBytesAtSample;
- long mMillisecondsAtSample;
- float mAverageDownloadSpeed;
-
- /**
- * Our binding to the network state broadcasts
- */
- private BroadcastReceiver mConnReceiver;
- final private IStub mServiceStub = DownloaderServiceMarshaller.CreateStub(this);
- final private Messenger mServiceMessenger = mServiceStub.getMessenger();
- private Messenger mClientMessenger;
- private DownloadNotification mNotification;
- private PendingIntent mPendingIntent;
- private PendingIntent mAlarmIntent;
-
- /**
- * Updates the network type based upon the type and subtype returned from
- * the connectivity manager. Subtype is only used for cellular signals.
- *
- * @param type
- * @param subType
- */
- private void updateNetworkType(int type, int subType) {
- switch (type) {
- case ConnectivityManager.TYPE_WIFI:
- case ConnectivityManager.TYPE_ETHERNET:
- case ConnectivityManager.TYPE_BLUETOOTH:
- mIsCellularConnection = false;
- mIsAtLeast3G = false;
- mIsAtLeast4G = false;
- break;
- case ConnectivityManager.TYPE_WIMAX:
- mIsCellularConnection = true;
- mIsAtLeast3G = true;
- mIsAtLeast4G = true;
- break;
- case ConnectivityManager.TYPE_MOBILE:
- mIsCellularConnection = true;
- switch (subType) {
- case TelephonyManager.NETWORK_TYPE_1xRTT:
- case TelephonyManager.NETWORK_TYPE_CDMA:
- case TelephonyManager.NETWORK_TYPE_EDGE:
- case TelephonyManager.NETWORK_TYPE_GPRS:
- case TelephonyManager.NETWORK_TYPE_IDEN:
- mIsAtLeast3G = false;
- mIsAtLeast4G = false;
- break;
- case TelephonyManager.NETWORK_TYPE_HSDPA:
- case TelephonyManager.NETWORK_TYPE_HSUPA:
- case TelephonyManager.NETWORK_TYPE_HSPA:
- case TelephonyManager.NETWORK_TYPE_EVDO_0:
- case TelephonyManager.NETWORK_TYPE_EVDO_A:
- case TelephonyManager.NETWORK_TYPE_UMTS:
- mIsAtLeast3G = true;
- mIsAtLeast4G = false;
- break;
- case TelephonyManager.NETWORK_TYPE_LTE: // 4G
- case TelephonyManager.NETWORK_TYPE_EHRPD: // 3G ++ interop
- // with 4G
- case TelephonyManager.NETWORK_TYPE_HSPAP: // 3G ++ but
- // marketed as
- // 4G
- mIsAtLeast3G = true;
- mIsAtLeast4G = true;
- break;
- default:
- mIsCellularConnection = false;
- mIsAtLeast3G = false;
- mIsAtLeast4G = false;
- }
- }
- }
-
- private void updateNetworkState(NetworkInfo info) {
- boolean isConnected = mIsConnected;
- boolean isFailover = mIsFailover;
- boolean isCellularConnection = mIsCellularConnection;
- boolean isRoaming = mIsRoaming;
- boolean isAtLeast3G = mIsAtLeast3G;
- if (null != info) {
- mIsRoaming = info.isRoaming();
- mIsFailover = info.isFailover();
- mIsConnected = info.isConnected();
- updateNetworkType(info.getType(), info.getSubtype());
- } else {
- mIsRoaming = false;
- mIsFailover = false;
- mIsConnected = false;
- updateNetworkType(-1, -1);
- }
- mStateChanged = (mStateChanged || isConnected != mIsConnected
- || isFailover != mIsFailover
- || isCellularConnection != mIsCellularConnection
- || isRoaming != mIsRoaming || isAtLeast3G != mIsAtLeast3G);
- if (Constants.LOGVV) {
- if (mStateChanged) {
- Log.v(LOG_TAG, "Network state changed: ");
- Log.v(LOG_TAG, "Starting State: " +
- (isConnected ? "Connected " : "Not Connected ") +
- (isCellularConnection ? "Cellular " : "WiFi ") +
- (isRoaming ? "Roaming " : "Local ") +
- (isAtLeast3G ? "3G+ " : "<3G "));
- Log.v(LOG_TAG, "Ending State: " +
- (mIsConnected ? "Connected " : "Not Connected ") +
- (mIsCellularConnection ? "Cellular " : "WiFi ") +
- (mIsRoaming ? "Roaming " : "Local ") +
- (mIsAtLeast3G ? "3G+ " : "<3G "));
-
- if (isServiceRunning()) {
- if (mIsRoaming) {
- mStatus = STATUS_WAITING_FOR_NETWORK;
- mControl = CONTROL_PAUSED;
- } else if (mIsCellularConnection) {
- DownloadsDB db = DownloadsDB.getDB(this);
- int flags = db.getFlags();
- if (0 == (flags & FLAGS_DOWNLOAD_OVER_CELLULAR)) {
- mStatus = STATUS_QUEUED_FOR_WIFI;
- mControl = CONTROL_PAUSED;
- }
- }
- }
-
- }
- }
- }
-
- /**
- * Polls the network state, setting the flags appropriately.
- */
- void pollNetworkState() {
- if (null == mConnectivityManager) {
- mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
- }
- if (null == mWifiManager) {
- mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
- }
- if (mConnectivityManager == null) {
- Log.w(Constants.TAG,
- "couldn't get connectivity manager to poll network state");
- } else {
- NetworkInfo activeInfo = mConnectivityManager
- .getActiveNetworkInfo();
- updateNetworkState(activeInfo);
- }
- }
-
- public static final int NO_DOWNLOAD_REQUIRED = 0;
- public static final int LVL_CHECK_REQUIRED = 1;
- public static final int DOWNLOAD_REQUIRED = 2;
-
- public static final String EXTRA_PACKAGE_NAME = "EPN";
- public static final String EXTRA_PENDING_INTENT = "EPI";
- public static final String EXTRA_MESSAGE_HANDLER = "EMH";
-
- /**
- * Returns true if the LVL check is required
- *
- * @param db a downloads DB synchronized with the latest state
- * @param pi the package info for the project
- * @return returns true if the filenames need to be returned
- */
- private static boolean isLVLCheckRequired(DownloadsDB db, PackageInfo pi) {
- // we need to update the LVL check and get a successful status to
- // proceed
- if (db.mVersionCode != pi.versionCode) {
- return true;
- }
- return false;
- }
-
- /**
- * Careful! Only use this internally.
- *
- * @return whether we think the service is running
- */
- private static synchronized boolean isServiceRunning() {
- return sIsRunning;
- }
-
- private static synchronized void setServiceRunning(boolean isRunning) {
- sIsRunning = isRunning;
- }
-
- public static int startDownloadServiceIfRequired(Context context,
- Intent intent, Class<?> serviceClass) throws NameNotFoundException {
- final PendingIntent pendingIntent = (PendingIntent) intent
- .getParcelableExtra(EXTRA_PENDING_INTENT);
- return startDownloadServiceIfRequired(context, pendingIntent,
- serviceClass);
- }
-
- public static int startDownloadServiceIfRequired(Context context,
- PendingIntent pendingIntent, Class<?> serviceClass)
- throws NameNotFoundException
- {
- String packageName = context.getPackageName();
- String className = serviceClass.getName();
-
- return startDownloadServiceIfRequired(context, pendingIntent,
- packageName, className);
- }
-
- /**
- * Starts the download if necessary. This function starts a flow that does `
- * many things. 1) Checks to see if the APK version has been checked and the
- * metadata database updated 2) If the APK version does not match, checks
- * the new LVL status to see if a new download is required 3) If the APK
- * version does match, then checks to see if the download(s) have been
- * completed 4) If the downloads have been completed, returns
- * NO_DOWNLOAD_REQUIRED The idea is that this can be called during the
- * startup of an application to quickly ascertain if the application needs
- * to wait to hear about any updated APK expansion files. Note that this
- * does mean that the application MUST be run for the first time with a
- * network connection, even if Market delivers all of the files.
- *
- * @param context
- * @param thisIntent
- * @return true if the app should wait for more guidance from the
- * downloader, false if the app can continue
- * @throws NameNotFoundException
- */
- public static int startDownloadServiceIfRequired(Context context,
- PendingIntent pendingIntent, String classPackage, String className)
- throws NameNotFoundException {
- // first: do we need to do an LVL update?
- // we begin by getting our APK version from the package manager
- final PackageInfo pi = context.getPackageManager().getPackageInfo(
- context.getPackageName(), 0);
-
- int status = NO_DOWNLOAD_REQUIRED;
-
- // the database automatically reads the metadata for version code
- // and download status when the instance is created
- DownloadsDB db = DownloadsDB.getDB(context);
-
- // we need to update the LVL check and get a successful status to
- // proceed
- if (isLVLCheckRequired(db, pi)) {
- status = LVL_CHECK_REQUIRED;
- }
- // we don't have to update LVL. do we still have a download to start?
- if (db.mStatus == 0) {
- DownloadInfo[] infos = db.getDownloads();
- if (null != infos) {
- for (DownloadInfo info : infos) {
- if (!Helpers.doesFileExist(context, info.mFileName, info.mTotalBytes, true)) {
- status = DOWNLOAD_REQUIRED;
- db.updateStatus(-1);
- break;
- }
- }
- }
- } else {
- status = DOWNLOAD_REQUIRED;
- }
- switch (status) {
- case DOWNLOAD_REQUIRED:
- case LVL_CHECK_REQUIRED:
- Intent fileIntent = new Intent();
- fileIntent.setClassName(classPackage, className);
- fileIntent.putExtra(EXTRA_PENDING_INTENT, pendingIntent);
- context.startService(fileIntent);
- break;
- }
- return status;
- }
-
- @Override
- public void requestAbortDownload() {
- mControl = CONTROL_PAUSED;
- mStatus = STATUS_CANCELED;
- }
-
- @Override
- public void requestPauseDownload() {
- mControl = CONTROL_PAUSED;
- mStatus = STATUS_PAUSED_BY_APP;
- }
-
- @Override
- public void setDownloadFlags(int flags) {
- DownloadsDB.getDB(this).updateFlags(flags);
- }
-
- @Override
- public void requestContinueDownload() {
- if (mControl == CONTROL_PAUSED) {
- mControl = CONTROL_RUN;
- }
- Intent fileIntent = new Intent(this, this.getClass());
- fileIntent.putExtra(EXTRA_PENDING_INTENT, mPendingIntent);
- this.startService(fileIntent);
- }
-
- public abstract String getPublicKey();
-
- public abstract byte[] getSALT();
-
- public abstract String getAlarmReceiverClassName();
-
- private class LVLRunnable implements Runnable {
- LVLRunnable(Context context, PendingIntent intent) {
- mContext = context;
- mPendingIntent = intent;
- }
-
- final Context mContext;
-
- @Override
- public void run() {
- setServiceRunning(true);
- mNotification.onDownloadStateChanged(IDownloaderClient.STATE_FETCHING_URL);
- String deviceId = Secure.getString(mContext.getContentResolver(),
- Secure.ANDROID_ID);
-
- final APKExpansionPolicy aep = new APKExpansionPolicy(mContext,
- new AESObfuscator(getSALT(), mContext.getPackageName(), deviceId));
-
- // reset our policy back to the start of the world to force a
- // re-check
- aep.resetPolicy();
-
- // let's try and get the OBB file from LVL first
- // Construct the LicenseChecker with a Policy.
- final LicenseChecker checker = new LicenseChecker(mContext, aep,
- getPublicKey() // Your public licensing key.
- );
- checker.checkAccess(new LicenseCheckerCallback() {
-
- @Override
- public void allow(int reason) {
- try {
- int count = aep.getExpansionURLCount();
- DownloadsDB db = DownloadsDB.getDB(mContext);
- int status = 0;
- if (count != 0) {
- for (int i = 0; i < count; i++) {
- String currentFileName = aep
- .getExpansionFileName(i);
- if (null != currentFileName) {
- DownloadInfo di = new DownloadInfo(i,
- currentFileName, mContext.getPackageName());
-
- long fileSize = aep.getExpansionFileSize(i);
- if (handleFileUpdated(db, i, currentFileName,
- fileSize)) {
- status |= -1;
- di.resetDownload();
- di.mUri = aep.getExpansionURL(i);
- di.mTotalBytes = fileSize;
- di.mStatus = status;
- db.updateDownload(di);
- } else {
- // we need to read the download
- // information
- // from
- // the database
- DownloadInfo dbdi = db
- .getDownloadInfoByFileName(di.mFileName);
- if (null == dbdi) {
- // the file exists already and is
- // the
- // correct size
- // was delivered by Market or
- // through
- // another mechanism
- Log.d(LOG_TAG, "file " + di.mFileName
- + " found. Not downloading.");
- di.mStatus = STATUS_SUCCESS;
- di.mTotalBytes = fileSize;
- di.mCurrentBytes = fileSize;
- di.mUri = aep.getExpansionURL(i);
- db.updateDownload(di);
- } else if (dbdi.mStatus != STATUS_SUCCESS) {
- // we just update the URL
- dbdi.mUri = aep.getExpansionURL(i);
- db.updateDownload(dbdi);
- status |= -1;
- }
- }
- }
- }
- }
- // first: do we need to do an LVL update?
- // we begin by getting our APK version from the package
- // manager
- PackageInfo pi;
- try {
- pi = mContext.getPackageManager().getPackageInfo(
- mContext.getPackageName(), 0);
- db.updateMetadata(pi.versionCode, status);
- Class<?> serviceClass = DownloaderService.this.getClass();
- switch (startDownloadServiceIfRequired(mContext, mPendingIntent,
- serviceClass)) {
- case NO_DOWNLOAD_REQUIRED:
- mNotification
- .onDownloadStateChanged(IDownloaderClient.STATE_COMPLETED);
- break;
- case LVL_CHECK_REQUIRED:
- // DANGER WILL ROBINSON!
- Log.e(LOG_TAG, "In LVL checking loop!");
- mNotification
- .onDownloadStateChanged(IDownloaderClient.STATE_FAILED_UNLICENSED);
- throw new RuntimeException(
- "Error with LVL checking and database integrity");
- case DOWNLOAD_REQUIRED:
- // do nothing. the download will notify the
- // application
- // when things are done
- break;
- }
- } catch (NameNotFoundException e1) {
- e1.printStackTrace();
- throw new RuntimeException(
- "Error with getting information from package name");
- }
- } finally {
- setServiceRunning(false);
- }
- }
-
- @Override
- public void dontAllow(int reason) {
- try
- {
- switch (reason) {
- case Policy.NOT_LICENSED:
- mNotification
- .onDownloadStateChanged(IDownloaderClient.STATE_FAILED_UNLICENSED);
- break;
- case Policy.RETRY:
- mNotification
- .onDownloadStateChanged(IDownloaderClient.STATE_FAILED_FETCHING_URL);
- break;
- }
- } finally {
- setServiceRunning(false);
- }
-
- }
-
- @Override
- public void applicationError(int errorCode) {
- try {
- mNotification
- .onDownloadStateChanged(IDownloaderClient.STATE_FAILED_FETCHING_URL);
- } finally {
- setServiceRunning(false);
- }
- }
-
- });
-
- }
-
- };
-
- /**
- * Updates the LVL information from the server.
- *
- * @param context
- */
- public void updateLVL(final Context context) {
- Context c = context.getApplicationContext();
- Handler h = new Handler(c.getMainLooper());
- h.post(new LVLRunnable(c, mPendingIntent));
- }
-
- /**
- * The APK has been updated and a filename has been sent down from the
- * Market call. If the file has the same name as the previous file, we do
- * nothing as the file is guaranteed to be the same. If the file does not
- * have the same name, we download it if it hasn't already been delivered by
- * Market.
- *
- * @param index the index of the file from market (0 = main, 1 = patch)
- * @param filename the name of the new file
- * @param fileSize the size of the new file
- * @return
- */
- public boolean handleFileUpdated(DownloadsDB db, int index,
- String filename, long fileSize) {
- DownloadInfo di = db.getDownloadInfoByFileName(filename);
- if (null != di) {
- String oldFile = di.mFileName;
- // cleanup
- if (null != oldFile) {
- if (filename.equals(oldFile)) {
- return false;
- }
-
- // remove partially downloaded file if it is there
- String deleteFile = Helpers.generateSaveFileName(this, oldFile);
- File f = new File(deleteFile);
- if (f.exists())
- f.delete();
- }
- }
- return !Helpers.doesFileExist(this, filename, fileSize, true);
- }
-
- private void scheduleAlarm(long wakeUp) {
- AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
- if (alarms == null) {
- Log.e(Constants.TAG, "couldn't get alarm manager");
- return;
- }
-
- if (Constants.LOGV) {
- Log.v(Constants.TAG, "scheduling retry in " + wakeUp + "ms");
- }
-
- String className = getAlarmReceiverClassName();
- Intent intent = new Intent(Constants.ACTION_RETRY);
- intent.putExtra(EXTRA_PENDING_INTENT, mPendingIntent);
- intent.setClassName(this.getPackageName(),
- className);
- mAlarmIntent = PendingIntent.getBroadcast(this, 0, intent,
- PendingIntent.FLAG_ONE_SHOT);
- alarms.set(
- AlarmManager.RTC_WAKEUP,
- System.currentTimeMillis() + wakeUp, mAlarmIntent
- );
- }
-
- private void cancelAlarms() {
- if (null != mAlarmIntent) {
- AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
- if (alarms == null) {
- Log.e(Constants.TAG, "couldn't get alarm manager");
- return;
- }
- alarms.cancel(mAlarmIntent);
- mAlarmIntent = null;
- }
- }
-
- /**
- * We use this to track network state, such as when WiFi, Cellular, etc. is
- * enabled when downloads are paused or in progress.
- */
- private class InnerBroadcastReceiver extends BroadcastReceiver {
- final Service mService;
-
- InnerBroadcastReceiver(Service service) {
- mService = service;
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- pollNetworkState();
- if (mStateChanged
- && !isServiceRunning()) {
- Log.d(Constants.TAG, "InnerBroadcastReceiver Called");
- Intent fileIntent = new Intent(context, mService.getClass());
- fileIntent.putExtra(EXTRA_PENDING_INTENT, mPendingIntent);
- // send a new intent to the service
- context.startService(fileIntent);
- }
- }
- };
-
- /**
- * This is the main thread for the Downloader. This thread is responsible
- * for queuing up downloads and other goodness.
- */
- @Override
- protected void onHandleIntent(Intent intent) {
- setServiceRunning(true);
- try {
- // the database automatically reads the metadata for version code
- // and download status when the instance is created
- DownloadsDB db = DownloadsDB.getDB(this);
- final PendingIntent pendingIntent = (PendingIntent) intent
- .getParcelableExtra(EXTRA_PENDING_INTENT);
-
- if (null != pendingIntent)
- {
- mNotification.setClientIntent(pendingIntent);
- mPendingIntent = pendingIntent;
- } else if (null != mPendingIntent) {
- mNotification.setClientIntent(mPendingIntent);
- } else {
- Log.e(LOG_TAG, "Downloader started in bad state without notification intent.");
- return;
- }
-
- // when the LVL check completes, a successful response will update
- // the service
- if (isLVLCheckRequired(db, mPackageInfo)) {
- updateLVL(this);
- return;
- }
-
- // get each download
- DownloadInfo[] infos = db.getDownloads();
- mBytesSoFar = 0;
- mTotalLength = 0;
- mFileCount = infos.length;
- for (DownloadInfo info : infos) {
- // We do an (simple) integrity check on each file, just to make
- // sure
- if (info.mStatus == STATUS_SUCCESS) {
- // verify that the file matches the state
- if (!Helpers.doesFileExist(this, info.mFileName, info.mTotalBytes, true)) {
- info.mStatus = 0;
- info.mCurrentBytes = 0;
- }
- }
- // get aggregate data
- mTotalLength += info.mTotalBytes;
- mBytesSoFar += info.mCurrentBytes;
- }
-
- // loop through all downloads and fetch them
- pollNetworkState();
- if (null == mConnReceiver) {
-
- /**
- * We use this to track network state, such as when WiFi,
- * Cellular, etc. is enabled when downloads are paused or in
- * progress.
- */
- mConnReceiver = new InnerBroadcastReceiver(this);
- IntentFilter intentFilter = new IntentFilter(
- ConnectivityManager.CONNECTIVITY_ACTION);
- intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
- registerReceiver(mConnReceiver, intentFilter);
- }
-
- for (DownloadInfo info : infos) {
- long startingCount = info.mCurrentBytes;
-
- if (info.mStatus != STATUS_SUCCESS) {
- DownloadThread dt = new DownloadThread(info, this, mNotification);
- cancelAlarms();
- scheduleAlarm(Constants.ACTIVE_THREAD_WATCHDOG);
- dt.run();
- cancelAlarms();
- }
- db.updateFromDb(info);
- boolean setWakeWatchdog = false;
- int notifyStatus;
- switch (info.mStatus) {
- case STATUS_FORBIDDEN:
- // the URL is out of date
- updateLVL(this);
- return;
- case STATUS_SUCCESS:
- mBytesSoFar += info.mCurrentBytes - startingCount;
- db.updateMetadata(mPackageInfo.versionCode, 0);
- continue;
- case STATUS_FILE_DELIVERED_INCORRECTLY:
- // we may be on a network that is returning us a web
- // page on redirect
- notifyStatus = IDownloaderClient.STATE_PAUSED_NETWORK_SETUP_FAILURE;
- info.mCurrentBytes = 0;
- db.updateDownload(info);
- setWakeWatchdog = true;
- break;
- case STATUS_PAUSED_BY_APP:
- notifyStatus = IDownloaderClient.STATE_PAUSED_BY_REQUEST;
- break;
- case STATUS_WAITING_FOR_NETWORK:
- case STATUS_WAITING_TO_RETRY:
- notifyStatus = IDownloaderClient.STATE_PAUSED_NETWORK_UNAVAILABLE;
- setWakeWatchdog = true;
- break;
- case STATUS_QUEUED_FOR_WIFI_OR_CELLULAR_PERMISSION:
- case STATUS_QUEUED_FOR_WIFI:
- // look for more detail here
- if (null != mWifiManager) {
- if (!mWifiManager.isWifiEnabled()) {
- notifyStatus = IDownloaderClient.STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION;
- setWakeWatchdog = true;
- break;
- }
- }
- notifyStatus = IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION;
- setWakeWatchdog = true;
- break;
- case STATUS_CANCELED:
- notifyStatus = IDownloaderClient.STATE_FAILED_CANCELED;
- setWakeWatchdog = true;
- break;
-
- case STATUS_INSUFFICIENT_SPACE_ERROR:
- notifyStatus = IDownloaderClient.STATE_FAILED_SDCARD_FULL;
- setWakeWatchdog = true;
- break;
-
- case STATUS_DEVICE_NOT_FOUND_ERROR:
- notifyStatus = IDownloaderClient.STATE_PAUSED_SDCARD_UNAVAILABLE;
- setWakeWatchdog = true;
- break;
-
- default:
- notifyStatus = IDownloaderClient.STATE_FAILED;
- break;
- }
- if (setWakeWatchdog) {
- scheduleAlarm(Constants.WATCHDOG_WAKE_TIMER);
- } else {
- cancelAlarms();
- }
- // failure or pause state
- mNotification.onDownloadStateChanged(notifyStatus);
- return;
- }
-
- // all downloads complete
- mNotification.onDownloadStateChanged(IDownloaderClient.STATE_COMPLETED);
- } finally {
- setServiceRunning(false);
- }
- }
-
- @Override
- public void onDestroy() {
- if (null != mConnReceiver) {
- unregisterReceiver(mConnReceiver);
- mConnReceiver = null;
- }
- mServiceStub.disconnect(this);
- super.onDestroy();
- }
-
- public int getNetworkAvailabilityState(DownloadsDB db) {
- if (mIsConnected) {
- if (!mIsCellularConnection)
- return NETWORK_OK;
- int flags = db.mFlags;
- if (mIsRoaming)
- return NETWORK_CANNOT_USE_ROAMING;
- if (0 != (flags & FLAGS_DOWNLOAD_OVER_CELLULAR)) {
- return NETWORK_OK;
- } else {
- return NETWORK_TYPE_DISALLOWED_BY_REQUESTOR;
- }
- }
- return NETWORK_NO_CONNECTION;
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- try {
- mPackageInfo = getPackageManager().getPackageInfo(
- getPackageName(), 0);
- ApplicationInfo ai = getApplicationInfo();
- CharSequence applicationLabel = getPackageManager().getApplicationLabel(ai);
- mNotification = new DownloadNotification(this, applicationLabel);
-
- } catch (NameNotFoundException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Exception thrown from methods called by generateSaveFile() for any fatal
- * error.
- */
- public static class GenerateSaveFileError extends Exception {
- private static final long serialVersionUID = 3465966015408936540L;
- int mStatus;
- String mMessage;
-
- public GenerateSaveFileError(int status, String message) {
- mStatus = status;
- mMessage = message;
- }
- }
-
- /**
- * Returns the filename (where the file should be saved) from info about a
- * download
- */
- public String generateTempSaveFileName(String fileName) {
- String path = Helpers.getSaveFilePath(this)
- + File.separator + fileName + TEMP_EXT;
- return path;
- }
-
- /**
- * Creates a filename (where the file should be saved) from info about a
- * download.
- */
- public String generateSaveFile(String filename, long filesize)
- throws GenerateSaveFileError {
- String path = generateTempSaveFileName(filename);
- File expPath = new File(path);
- if (!Helpers.isExternalMediaMounted()) {
- Log.d(Constants.TAG, "External media not mounted: " + path);
- throw new GenerateSaveFileError(STATUS_DEVICE_NOT_FOUND_ERROR,
- "external media is not yet mounted");
-
- }
- if (expPath.exists()) {
- Log.d(Constants.TAG, "File already exists: " + path);
- throw new GenerateSaveFileError(STATUS_FILE_ALREADY_EXISTS_ERROR,
- "requested destination file already exists");
- }
- if (Helpers.getAvailableBytes(Helpers.getFilesystemRoot(path)) < filesize) {
- throw new GenerateSaveFileError(STATUS_INSUFFICIENT_SPACE_ERROR,
- "insufficient space on external storage");
- }
- return path;
- }
-
- /**
- * @return a non-localized string appropriate for logging corresponding to
- * one of the NETWORK_* constants.
- */
- public String getLogMessageForNetworkError(int networkError) {
- switch (networkError) {
- case NETWORK_RECOMMENDED_UNUSABLE_DUE_TO_SIZE:
- return "download size exceeds recommended limit for mobile network";
-
- case NETWORK_UNUSABLE_DUE_TO_SIZE:
- return "download size exceeds limit for mobile network";
-
- case NETWORK_NO_CONNECTION:
- return "no network connection available";
-
- case NETWORK_CANNOT_USE_ROAMING:
- return "download cannot use the current network connection because it is roaming";
-
- case NETWORK_TYPE_DISALLOWED_BY_REQUESTOR:
- return "download was requested to not use the current network type";
-
- default:
- return "unknown error with network connectivity";
- }
- }
-
- public int getControl() {
- return mControl;
- }
-
- public int getStatus() {
- return mStatus;
- }
-
- /**
- * Calculating a moving average for the speed so we don't get jumpy
- * calculations for time etc.
- */
- static private final float SMOOTHING_FACTOR = 0.005f;
-
- public void notifyUpdateBytes(long totalBytesSoFar) {
- long timeRemaining;
- long currentTime = SystemClock.uptimeMillis();
- if (0 != mMillisecondsAtSample) {
- // we have a sample.
- long timePassed = currentTime - mMillisecondsAtSample;
- long bytesInSample = totalBytesSoFar - mBytesAtSample;
- float currentSpeedSample = (float) bytesInSample / (float) timePassed;
- if (0 != mAverageDownloadSpeed) {
- mAverageDownloadSpeed = SMOOTHING_FACTOR * currentSpeedSample
- + (1 - SMOOTHING_FACTOR) * mAverageDownloadSpeed;
- } else {
- mAverageDownloadSpeed = currentSpeedSample;
- }
- timeRemaining = (long) ((mTotalLength - totalBytesSoFar) / mAverageDownloadSpeed);
- } else {
- timeRemaining = -1;
- }
- mMillisecondsAtSample = currentTime;
- mBytesAtSample = totalBytesSoFar;
- mNotification.onDownloadProgress(
- new DownloadProgressInfo(mTotalLength,
- totalBytesSoFar,
- timeRemaining,
- mAverageDownloadSpeed)
- );
-
- }
-
- @Override
- protected boolean shouldStop() {
- // the database automatically reads the metadata for version code
- // and download status when the instance is created
- DownloadsDB db = DownloadsDB.getDB(this);
- if (db.mStatus == 0) {
- return true;
- }
- return false;
- }
-
- @Override
- public void requestDownloadStatus() {
- mNotification.resendState();
- }
-
- @Override
- public void onClientUpdated(Messenger clientMessenger) {
- this.mClientMessenger = clientMessenger;
- mNotification.setMessenger(mClientMessenger);
- }
-
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java
deleted file mode 100755
index 250299c400..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader.impl;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteDoneException;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteStatement;
-import android.provider.BaseColumns;
-import android.util.Log;
-
-public class DownloadsDB {
- private static final String DATABASE_NAME = "DownloadsDB";
- private static final int DATABASE_VERSION = 7;
- public static final String LOG_TAG = DownloadsDB.class.getName();
- final SQLiteOpenHelper mHelper;
- SQLiteStatement mGetDownloadByIndex;
- SQLiteStatement mUpdateCurrentBytes;
- private static DownloadsDB mDownloadsDB;
- long mMetadataRowID = -1;
- int mVersionCode = -1;
- int mStatus = -1;
- int mFlags;
-
- static public synchronized DownloadsDB getDB(Context paramContext) {
- if (null == mDownloadsDB) {
- return new DownloadsDB(paramContext);
- }
- return mDownloadsDB;
- }
-
- private SQLiteStatement getDownloadByIndexStatement() {
- if (null == mGetDownloadByIndex) {
- mGetDownloadByIndex = mHelper.getReadableDatabase().compileStatement(
- "SELECT " + BaseColumns._ID + " FROM "
- + DownloadColumns.TABLE_NAME + " WHERE "
- + DownloadColumns.INDEX + " = ?");
- }
- return mGetDownloadByIndex;
- }
-
- private SQLiteStatement getUpdateCurrentBytesStatement() {
- if (null == mUpdateCurrentBytes) {
- mUpdateCurrentBytes = mHelper.getReadableDatabase().compileStatement(
- "UPDATE " + DownloadColumns.TABLE_NAME + " SET " + DownloadColumns.CURRENTBYTES
- + " = ?" +
- " WHERE " + DownloadColumns.INDEX + " = ?");
- }
- return mUpdateCurrentBytes;
- }
-
- private DownloadsDB(Context paramContext) {
- this.mHelper = new DownloadsContentDBHelper(paramContext);
- final SQLiteDatabase sqldb = mHelper.getReadableDatabase();
- // Query for the version code, the row ID of the metadata (for future
- // updating) the status and the flags
- Cursor cur = sqldb.rawQuery("SELECT " +
- MetadataColumns.APKVERSION + "," +
- BaseColumns._ID + "," +
- MetadataColumns.DOWNLOAD_STATUS + "," +
- MetadataColumns.FLAGS +
- " FROM "
- + MetadataColumns.TABLE_NAME + " LIMIT 1", null);
- if (null != cur && cur.moveToFirst()) {
- mVersionCode = cur.getInt(0);
- mMetadataRowID = cur.getLong(1);
- mStatus = cur.getInt(2);
- mFlags = cur.getInt(3);
- cur.close();
- }
- mDownloadsDB = this;
- }
-
- protected DownloadInfo getDownloadInfoByFileName(String fileName) {
- final SQLiteDatabase sqldb = mHelper.getReadableDatabase();
- Cursor itemcur = null;
- try {
- itemcur = sqldb.query(DownloadColumns.TABLE_NAME, DC_PROJECTION,
- DownloadColumns.FILENAME + " = ?",
- new String[] {
- fileName
- }, null, null, null);
- if (null != itemcur && itemcur.moveToFirst()) {
- return getDownloadInfoFromCursor(itemcur);
- }
- } finally {
- if (null != itemcur)
- itemcur.close();
- }
- return null;
- }
-
- public long getIDForDownloadInfo(final DownloadInfo di) {
- return getIDByIndex(di.mIndex);
- }
-
- public long getIDByIndex(int index) {
- SQLiteStatement downloadByIndex = getDownloadByIndexStatement();
- downloadByIndex.clearBindings();
- downloadByIndex.bindLong(1, index);
- try {
- return downloadByIndex.simpleQueryForLong();
- } catch (SQLiteDoneException e) {
- return -1;
- }
- }
-
- public void updateDownloadCurrentBytes(final DownloadInfo di) {
- SQLiteStatement downloadCurrentBytes = getUpdateCurrentBytesStatement();
- downloadCurrentBytes.clearBindings();
- downloadCurrentBytes.bindLong(1, di.mCurrentBytes);
- downloadCurrentBytes.bindLong(2, di.mIndex);
- downloadCurrentBytes.execute();
- }
-
- public void close() {
- this.mHelper.close();
- }
-
- protected static class DownloadsContentDBHelper extends SQLiteOpenHelper {
- DownloadsContentDBHelper(Context paramContext) {
- super(paramContext, DATABASE_NAME, null, DATABASE_VERSION);
- }
-
- private String createTableQueryFromArray(String paramString,
- String[][] paramArrayOfString) {
- StringBuilder localStringBuilder = new StringBuilder();
- localStringBuilder.append("CREATE TABLE ");
- localStringBuilder.append(paramString);
- localStringBuilder.append(" (");
- int i = paramArrayOfString.length;
- for (int j = 0;; j++) {
- if (j >= i) {
- localStringBuilder
- .setLength(localStringBuilder.length() - 1);
- localStringBuilder.append(");");
- return localStringBuilder.toString();
- }
- String[] arrayOfString = paramArrayOfString[j];
- localStringBuilder.append(' ');
- localStringBuilder.append(arrayOfString[0]);
- localStringBuilder.append(' ');
- localStringBuilder.append(arrayOfString[1]);
- localStringBuilder.append(',');
- }
- }
-
- /**
- * These two arrays must match and have the same order. For every Schema
- * there must be a corresponding table name.
- */
- static final private String[][][] sSchemas = {
- DownloadColumns.SCHEMA, MetadataColumns.SCHEMA
- };
-
- static final private String[] sTables = {
- DownloadColumns.TABLE_NAME, MetadataColumns.TABLE_NAME
- };
-
- /**
- * Goes through all of the tables in sTables and drops each table if it
- * exists. Altered to no longer make use of reflection.
- */
- private void dropTables(SQLiteDatabase paramSQLiteDatabase) {
- for (String table : sTables) {
- try {
- paramSQLiteDatabase.execSQL("DROP TABLE IF EXISTS " + table);
- } catch (Exception localException) {
- localException.printStackTrace();
- }
- }
- }
-
- /**
- * Goes through all of the tables in sTables and creates a database with
- * the corresponding schema described in sSchemas. Altered to no longer
- * make use of reflection.
- */
- public void onCreate(SQLiteDatabase paramSQLiteDatabase) {
- int numSchemas = sSchemas.length;
- for (int i = 0; i < numSchemas; i++) {
- try {
- String[][] schema = (String[][]) sSchemas[i];
- paramSQLiteDatabase.execSQL(createTableQueryFromArray(
- sTables[i], schema));
- } catch (Exception localException) {
- while (true)
- localException.printStackTrace();
- }
- }
- }
-
- public void onUpgrade(SQLiteDatabase paramSQLiteDatabase,
- int paramInt1, int paramInt2) {
- Log.w(DownloadsContentDBHelper.class.getName(),
- "Upgrading database from version " + paramInt1 + " to "
- + paramInt2 + ", which will destroy all old data");
- dropTables(paramSQLiteDatabase);
- onCreate(paramSQLiteDatabase);
- }
- }
-
- public static class MetadataColumns implements BaseColumns {
- public static final String APKVERSION = "APKVERSION";
- public static final String DOWNLOAD_STATUS = "DOWNLOADSTATUS";
- public static final String FLAGS = "DOWNLOADFLAGS";
-
- public static final String[][] SCHEMA = {
- {
- BaseColumns._ID, "INTEGER PRIMARY KEY"
- },
- {
- APKVERSION, "INTEGER"
- }, {
- DOWNLOAD_STATUS, "INTEGER"
- },
- {
- FLAGS, "INTEGER"
- }
- };
- public static final String TABLE_NAME = "MetadataColumns";
- public static final String _ID = "MetadataColumns._id";
- }
-
- public static class DownloadColumns implements BaseColumns {
- public static final String INDEX = "FILEIDX";
- public static final String URI = "URI";
- public static final String FILENAME = "FN";
- public static final String ETAG = "ETAG";
-
- public static final String TOTALBYTES = "TOTALBYTES";
- public static final String CURRENTBYTES = "CURRENTBYTES";
- public static final String LASTMOD = "LASTMOD";
-
- public static final String STATUS = "STATUS";
- public static final String CONTROL = "CONTROL";
- public static final String NUM_FAILED = "FAILCOUNT";
- public static final String RETRY_AFTER = "RETRYAFTER";
- public static final String REDIRECT_COUNT = "REDIRECTCOUNT";
-
- public static final String[][] SCHEMA = {
- {
- BaseColumns._ID, "INTEGER PRIMARY KEY"
- },
- {
- INDEX, "INTEGER UNIQUE"
- }, {
- URI, "TEXT"
- },
- {
- FILENAME, "TEXT UNIQUE"
- }, {
- ETAG, "TEXT"
- },
- {
- TOTALBYTES, "INTEGER"
- }, {
- CURRENTBYTES, "INTEGER"
- },
- {
- LASTMOD, "INTEGER"
- }, {
- STATUS, "INTEGER"
- },
- {
- CONTROL, "INTEGER"
- }, {
- NUM_FAILED, "INTEGER"
- },
- {
- RETRY_AFTER, "INTEGER"
- }, {
- REDIRECT_COUNT, "INTEGER"
- }
- };
- public static final String TABLE_NAME = "DownloadColumns";
- public static final String _ID = "DownloadColumns._id";
- }
-
- private static final String[] DC_PROJECTION = {
- DownloadColumns.FILENAME,
- DownloadColumns.URI, DownloadColumns.ETAG,
- DownloadColumns.TOTALBYTES, DownloadColumns.CURRENTBYTES,
- DownloadColumns.LASTMOD, DownloadColumns.STATUS,
- DownloadColumns.CONTROL, DownloadColumns.NUM_FAILED,
- DownloadColumns.RETRY_AFTER, DownloadColumns.REDIRECT_COUNT,
- DownloadColumns.INDEX
- };
-
- private static final int FILENAME_IDX = 0;
- private static final int URI_IDX = 1;
- private static final int ETAG_IDX = 2;
- private static final int TOTALBYTES_IDX = 3;
- private static final int CURRENTBYTES_IDX = 4;
- private static final int LASTMOD_IDX = 5;
- private static final int STATUS_IDX = 6;
- private static final int CONTROL_IDX = 7;
- private static final int NUM_FAILED_IDX = 8;
- private static final int RETRY_AFTER_IDX = 9;
- private static final int REDIRECT_COUNT_IDX = 10;
- private static final int INDEX_IDX = 11;
-
- /**
- * This function will add a new file to the database if it does not exist.
- *
- * @param di DownloadInfo that we wish to store
- * @return the row id of the record to be updated/inserted, or -1
- */
- public boolean updateDownload(DownloadInfo di) {
- ContentValues cv = new ContentValues();
- cv.put(DownloadColumns.INDEX, di.mIndex);
- cv.put(DownloadColumns.FILENAME, di.mFileName);
- cv.put(DownloadColumns.URI, di.mUri);
- cv.put(DownloadColumns.ETAG, di.mETag);
- cv.put(DownloadColumns.TOTALBYTES, di.mTotalBytes);
- cv.put(DownloadColumns.CURRENTBYTES, di.mCurrentBytes);
- cv.put(DownloadColumns.LASTMOD, di.mLastMod);
- cv.put(DownloadColumns.STATUS, di.mStatus);
- cv.put(DownloadColumns.CONTROL, di.mControl);
- cv.put(DownloadColumns.NUM_FAILED, di.mNumFailed);
- cv.put(DownloadColumns.RETRY_AFTER, di.mRetryAfter);
- cv.put(DownloadColumns.REDIRECT_COUNT, di.mRedirectCount);
- return updateDownload(di, cv);
- }
-
- public boolean updateDownload(DownloadInfo di, ContentValues cv) {
- long id = di == null ? -1 : getIDForDownloadInfo(di);
- try {
- final SQLiteDatabase sqldb = mHelper.getWritableDatabase();
- if (id != -1) {
- if (1 != sqldb.update(DownloadColumns.TABLE_NAME,
- cv, DownloadColumns._ID + " = " + id, null)) {
- return false;
- }
- } else {
- return -1 != sqldb.insert(DownloadColumns.TABLE_NAME,
- DownloadColumns.URI, cv);
- }
- } catch (android.database.sqlite.SQLiteException ex) {
- ex.printStackTrace();
- }
- return false;
- }
-
- public int getLastCheckedVersionCode() {
- return mVersionCode;
- }
-
- public boolean isDownloadRequired() {
- final SQLiteDatabase sqldb = mHelper.getReadableDatabase();
- Cursor cur = sqldb.rawQuery("SELECT Count(*) FROM "
- + DownloadColumns.TABLE_NAME + " WHERE "
- + DownloadColumns.STATUS + " <> 0", null);
- try {
- if (null != cur && cur.moveToFirst()) {
- return 0 == cur.getInt(0);
- }
- } finally {
- if (null != cur)
- cur.close();
- }
- return true;
- }
-
- public int getFlags() {
- return mFlags;
- }
-
- public boolean updateFlags(int flags) {
- if (mFlags != flags) {
- ContentValues cv = new ContentValues();
- cv.put(MetadataColumns.FLAGS, flags);
- if (updateMetadata(cv)) {
- mFlags = flags;
- return true;
- } else {
- return false;
- }
- } else {
- return true;
- }
- };
-
- public boolean updateStatus(int status) {
- if (mStatus != status) {
- ContentValues cv = new ContentValues();
- cv.put(MetadataColumns.DOWNLOAD_STATUS, status);
- if (updateMetadata(cv)) {
- mStatus = status;
- return true;
- } else {
- return false;
- }
- } else {
- return true;
- }
- };
-
- public boolean updateMetadata(ContentValues cv) {
- final SQLiteDatabase sqldb = mHelper.getWritableDatabase();
- if (-1 == this.mMetadataRowID) {
- long newID = sqldb.insert(MetadataColumns.TABLE_NAME,
- MetadataColumns.APKVERSION, cv);
- if (-1 == newID)
- return false;
- mMetadataRowID = newID;
- } else {
- if (0 == sqldb.update(MetadataColumns.TABLE_NAME, cv,
- BaseColumns._ID + " = " + mMetadataRowID, null))
- return false;
- }
- return true;
- }
-
- public boolean updateMetadata(int apkVersion, int downloadStatus) {
- ContentValues cv = new ContentValues();
- cv.put(MetadataColumns.APKVERSION, apkVersion);
- cv.put(MetadataColumns.DOWNLOAD_STATUS, downloadStatus);
- if (updateMetadata(cv)) {
- mVersionCode = apkVersion;
- mStatus = downloadStatus;
- return true;
- } else {
- return false;
- }
- };
-
- public boolean updateFromDb(DownloadInfo di) {
- final SQLiteDatabase sqldb = mHelper.getReadableDatabase();
- Cursor cur = null;
- try {
- cur = sqldb.query(DownloadColumns.TABLE_NAME, DC_PROJECTION,
- DownloadColumns.FILENAME + "= ?",
- new String[] {
- di.mFileName
- }, null, null, null);
- if (null != cur && cur.moveToFirst()) {
- setDownloadInfoFromCursor(di, cur);
- return true;
- }
- return false;
- } finally {
- if (null != cur) {
- cur.close();
- }
- }
- }
-
- public void setDownloadInfoFromCursor(DownloadInfo di, Cursor cur) {
- di.mUri = cur.getString(URI_IDX);
- di.mETag = cur.getString(ETAG_IDX);
- di.mTotalBytes = cur.getLong(TOTALBYTES_IDX);
- di.mCurrentBytes = cur.getLong(CURRENTBYTES_IDX);
- di.mLastMod = cur.getLong(LASTMOD_IDX);
- di.mStatus = cur.getInt(STATUS_IDX);
- di.mControl = cur.getInt(CONTROL_IDX);
- di.mNumFailed = cur.getInt(NUM_FAILED_IDX);
- di.mRetryAfter = cur.getInt(RETRY_AFTER_IDX);
- di.mRedirectCount = cur.getInt(REDIRECT_COUNT_IDX);
- }
-
- public DownloadInfo getDownloadInfoFromCursor(Cursor cur) {
- DownloadInfo di = new DownloadInfo(cur.getInt(INDEX_IDX),
- cur.getString(FILENAME_IDX), this.getClass().getPackage()
- .getName());
- setDownloadInfoFromCursor(di, cur);
- return di;
- }
-
- public DownloadInfo[] getDownloads() {
- final SQLiteDatabase sqldb = mHelper.getReadableDatabase();
- Cursor cur = null;
- try {
- cur = sqldb.query(DownloadColumns.TABLE_NAME, DC_PROJECTION, null,
- null, null, null, null);
- if (null != cur && cur.moveToFirst()) {
- DownloadInfo[] retInfos = new DownloadInfo[cur.getCount()];
- int idx = 0;
- do {
- DownloadInfo di = getDownloadInfoFromCursor(cur);
- retInfos[idx++] = di;
- } while (cur.moveToNext());
- return retInfos;
- }
- return null;
- } finally {
- if (null != cur) {
- cur.close();
- }
- }
- }
-
-}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java
deleted file mode 100644
index 3f440e9893..0000000000
--- a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.vending.expansion.downloader.impl;
-
-import android.text.format.Time;
-
-import java.util.Calendar;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Helper for parsing an HTTP date.
- */
-public final class HttpDateTime {
-
- /*
- * Regular expression for parsing HTTP-date. Wdy, DD Mon YYYY HH:MM:SS GMT
- * RFC 822, updated by RFC 1123 Weekday, DD-Mon-YY HH:MM:SS GMT RFC 850,
- * obsoleted by RFC 1036 Wdy Mon DD HH:MM:SS YYYY ANSI C's asctime() format
- * with following variations Wdy, DD-Mon-YYYY HH:MM:SS GMT Wdy, (SP)D Mon
- * YYYY HH:MM:SS GMT Wdy,DD Mon YYYY HH:MM:SS GMT Wdy, DD-Mon-YY HH:MM:SS
- * GMT Wdy, DD Mon YYYY HH:MM:SS -HHMM Wdy, DD Mon YYYY HH:MM:SS Wdy Mon
- * (SP)D HH:MM:SS YYYY Wdy Mon DD HH:MM:SS YYYY GMT HH can be H if the first
- * digit is zero. Mon can be the full name of the month.
- */
- private static final String HTTP_DATE_RFC_REGEXP =
- "([0-9]{1,2})[- ]([A-Za-z]{3,9})[- ]([0-9]{2,4})[ ]"
- + "([0-9]{1,2}:[0-9][0-9]:[0-9][0-9])";
-
- private static final String HTTP_DATE_ANSIC_REGEXP =
- "[ ]([A-Za-z]{3,9})[ ]+([0-9]{1,2})[ ]"
- + "([0-9]{1,2}:[0-9][0-9]:[0-9][0-9])[ ]([0-9]{2,4})";
-
- /**
- * The compiled version of the HTTP-date regular expressions.
- */
- private static final Pattern HTTP_DATE_RFC_PATTERN =
- Pattern.compile(HTTP_DATE_RFC_REGEXP);
- private static final Pattern HTTP_DATE_ANSIC_PATTERN =
- Pattern.compile(HTTP_DATE_ANSIC_REGEXP);
-
- private static class TimeOfDay {
- TimeOfDay(int h, int m, int s) {
- this.hour = h;
- this.minute = m;
- this.second = s;
- }
-
- int hour;
- int minute;
- int second;
- }
-
- public static long parse(String timeString)
- throws IllegalArgumentException {
-
- int date = 1;
- int month = Calendar.JANUARY;
- int year = 1970;
- TimeOfDay timeOfDay;
-
- Matcher rfcMatcher = HTTP_DATE_RFC_PATTERN.matcher(timeString);
- if (rfcMatcher.find()) {
- date = getDate(rfcMatcher.group(1));
- month = getMonth(rfcMatcher.group(2));
- year = getYear(rfcMatcher.group(3));
- timeOfDay = getTime(rfcMatcher.group(4));
- } else {
- Matcher ansicMatcher = HTTP_DATE_ANSIC_PATTERN.matcher(timeString);
- if (ansicMatcher.find()) {
- month = getMonth(ansicMatcher.group(1));
- date = getDate(ansicMatcher.group(2));
- timeOfDay = getTime(ansicMatcher.group(3));
- year = getYear(ansicMatcher.group(4));
- } else {
- throw new IllegalArgumentException();
- }
- }
-
- // FIXME: Y2038 BUG!
- if (year >= 2038) {
- year = 2038;
- month = Calendar.JANUARY;
- date = 1;
- }
-
- Time time = new Time(Time.TIMEZONE_UTC);
- time.set(timeOfDay.second, timeOfDay.minute, timeOfDay.hour, date,
- month, year);
- return time.toMillis(false /* use isDst */);
- }
-
- private static int getDate(String dateString) {
- if (dateString.length() == 2) {
- return (dateString.charAt(0) - '0') * 10
- + (dateString.charAt(1) - '0');
- } else {
- return (dateString.charAt(0) - '0');
- }
- }
-
- /*
- * jan = 9 + 0 + 13 = 22 feb = 5 + 4 + 1 = 10 mar = 12 + 0 + 17 = 29 apr = 0
- * + 15 + 17 = 32 may = 12 + 0 + 24 = 36 jun = 9 + 20 + 13 = 42 jul = 9 + 20
- * + 11 = 40 aug = 0 + 20 + 6 = 26 sep = 18 + 4 + 15 = 37 oct = 14 + 2 + 19
- * = 35 nov = 13 + 14 + 21 = 48 dec = 3 + 4 + 2 = 9
- */
- private static int getMonth(String monthString) {
- int hash = Character.toLowerCase(monthString.charAt(0)) +
- Character.toLowerCase(monthString.charAt(1)) +
- Character.toLowerCase(monthString.charAt(2)) - 3 * 'a';
- switch (hash) {
- case 22:
- return Calendar.JANUARY;
- case 10:
- return Calendar.FEBRUARY;
- case 29:
- return Calendar.MARCH;
- case 32:
- return Calendar.APRIL;
- case 36:
- return Calendar.MAY;
- case 42:
- return Calendar.JUNE;
- case 40:
- return Calendar.JULY;
- case 26:
- return Calendar.AUGUST;
- case 37:
- return Calendar.SEPTEMBER;
- case 35:
- return Calendar.OCTOBER;
- case 48:
- return Calendar.NOVEMBER;
- case 9:
- return Calendar.DECEMBER;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- private static int getYear(String yearString) {
- if (yearString.length() == 2) {
- int year = (yearString.charAt(0) - '0') * 10
- + (yearString.charAt(1) - '0');
- if (year >= 70) {
- return year + 1900;
- } else {
- return year + 2000;
- }
- } else if (yearString.length() == 3) {
- // According to RFC 2822, three digit years should be added to 1900.
- int year = (yearString.charAt(0) - '0') * 100
- + (yearString.charAt(1) - '0') * 10
- + (yearString.charAt(2) - '0');
- return year + 1900;
- } else if (yearString.length() == 4) {
- return (yearString.charAt(0) - '0') * 1000
- + (yearString.charAt(1) - '0') * 100
- + (yearString.charAt(2) - '0') * 10
- + (yearString.charAt(3) - '0');
- } else {
- return 1970;
- }
- }
-
- private static TimeOfDay getTime(String timeString) {
- // HH might be H
- int i = 0;
- int hour = timeString.charAt(i++) - '0';
- if (timeString.charAt(i) != ':')
- hour = hour * 10 + (timeString.charAt(i++) - '0');
- // Skip ':'
- i++;
-
- int minute = (timeString.charAt(i++) - '0') * 10
- + (timeString.charAt(i++) - '0');
- // Skip ':'
- i++;
-
- int second = (timeString.charAt(i++) - '0') * 10
- + (timeString.charAt(i++) - '0');
-
- return new TimeOfDay(hour, minute, second);
- }
-}
diff --git a/platform/android/libs/google_play_services/.classpath b/platform/android/libs/google_play_services/.classpath
deleted file mode 100644
index 7bc01d9a9c..0000000000
--- a/platform/android/libs/google_play_services/.classpath
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="src" path="gen"/>
- <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
- <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
- <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
- <classpathentry kind="output" path="bin/classes"/>
-</classpath>
diff --git a/platform/android/libs/google_play_services/AndroidManifest.xml b/platform/android/libs/google_play_services/AndroidManifest.xml
deleted file mode 100644
index aecd02b5d0..0000000000
--- a/platform/android/libs/google_play_services/AndroidManifest.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.google.android.gms"
- android:versionCode="4323030"
- android:versionName="4.3.23 (1069729-030)" >
-
- <uses-sdk android:minSdkVersion="9"/>
-
-</manifest>
diff --git a/platform/android/libs/google_play_services/README.txt b/platform/android/libs/google_play_services/README.txt
deleted file mode 100644
index 32f8d5eb85..0000000000
--- a/platform/android/libs/google_play_services/README.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Library Project including Google Play services client jar.
-
-This can be used by an Android project to use the API's provided
-by Google Play services.
-
-There is technically no source, but the src folder is necessary
-to ensure that the build system works. The content is actually
-located in the libs/ directory.
-
-
-USAGE:
-
-Make sure you import this Android library project into your IDE
-and set this project as a dependency.
-
-Note that if you use proguard, you will want to include the
-options from proguard.txt in your configuration. \ No newline at end of file
diff --git a/platform/android/libs/google_play_services/build.xml b/platform/android/libs/google_play_services/build.xml
deleted file mode 100644
index 22ccf3aaf4..0000000000
--- a/platform/android/libs/google_play_services/build.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="google_play_services" default="help">
-
- <!-- The local.properties file is created and updated by the 'android' tool.
- It contains the path to the SDK. It should *NOT* be checked into
- Version Control Systems. -->
- <property file="local.properties" />
-
- <!-- The ant.properties file can be created by you. It is only edited by the
- 'android' tool to add properties to it.
- This is the place to change some Ant specific build properties.
- Here are some properties you may want to change/update:
-
- source.dir
- The name of the source directory. Default is 'src'.
- out.dir
- The name of the output directory. Default is 'bin'.
-
- For other overridable properties, look at the beginning of the rules
- files in the SDK, at tools/ant/build.xml
-
- Properties related to the SDK location or the project target should
- be updated using the 'android' tool with the 'update' action.
-
- This file is an integral part of the build system for your
- application and should be checked into Version Control Systems.
-
- -->
- <property file="ant.properties" />
-
- <!-- if sdk.dir was not set from one of the property file, then
- get it from the ANDROID_HOME env var.
- This must be done before we load project.properties since
- the proguard config can use sdk.dir -->
- <property environment="env" />
- <condition property="sdk.dir" value="${env.ANDROID_HOME}">
- <isset property="env.ANDROID_HOME" />
- </condition>
-
- <!-- The project.properties file is created and updated by the 'android'
- tool, as well as ADT.
-
- This contains project specific properties such as project target, and library
- dependencies. Lower level build properties are stored in ant.properties
- (or in .classpath for Eclipse projects).
-
- This file is an integral part of the build system for your
- application and should be checked into Version Control Systems. -->
- <loadproperties srcFile="project.properties" />
-
- <!-- quick check on sdk.dir -->
- <fail
- message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
- unless="sdk.dir"
- />
-
- <!--
- Import per project custom build rules if present at the root of the project.
- This is the place to put custom intermediary targets such as:
- -pre-build
- -pre-compile
- -post-compile (This is typically used for code obfuscation.
- Compiled code location: ${out.classes.absolute.dir}
- If this is not done in place, override ${out.dex.input.absolute.dir})
- -post-package
- -post-build
- -pre-clean
- -->
- <import file="custom_rules.xml" optional="true" />
-
- <!-- Import the actual build file.
-
- To customize existing targets, there are two options:
- - Customize only one target:
- - copy/paste the target into this file, *before* the
- <import> task.
- - customize it to your needs.
- - Customize the whole content of build.xml
- - copy/paste the content of the rules files (minus the top node)
- into this file, replacing the <import> task.
- - customize to your needs.
-
- ***********************
- ****** IMPORTANT ******
- ***********************
- In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
- in order to avoid having your file be overridden by tools such as "android update project"
- -->
- <!-- version-tag: 1 -->
- <import file="${sdk.dir}/tools/ant/build.xml" />
-
-</project>
diff --git a/platform/android/libs/google_play_services/libs/google-play-services.jar b/platform/android/libs/google_play_services/libs/google-play-services.jar
deleted file mode 100644
index 67d56476b6..0000000000
--- a/platform/android/libs/google_play_services/libs/google-play-services.jar
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/libs/google-play-services.jar.properties b/platform/android/libs/google_play_services/libs/google-play-services.jar.properties
deleted file mode 100644
index 429687b792..0000000000
--- a/platform/android/libs/google_play_services/libs/google-play-services.jar.properties
+++ /dev/null
@@ -1 +0,0 @@
-doc=../../../docs/reference
diff --git a/platform/android/libs/google_play_services/proguard-project.txt b/platform/android/libs/google_play_services/proguard-project.txt
deleted file mode 100644
index f2fe1559a2..0000000000
--- a/platform/android/libs/google_play_services/proguard-project.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-# To enable ProGuard in your project, edit project.properties
-# to define the proguard.config property as described in that file.
-#
-# Add project specific ProGuard rules here.
-# By default, the flags in this file are appended to flags specified
-# in ${sdk.dir}/tools/proguard/proguard-android.txt
-# You can edit the include path and order by changing the ProGuard
-# include property in project.properties.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# Add any project specific keep options here:
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
diff --git a/platform/android/libs/google_play_services/proguard.txt b/platform/android/libs/google_play_services/proguard.txt
deleted file mode 100644
index 0c9693a2c0..0000000000
--- a/platform/android/libs/google_play_services/proguard.txt
+++ /dev/null
@@ -1,20 +0,0 @@
--keep class * extends java.util.ListResourceBundle {
- protected Object[][] getContents();
-}
-
-# Keep SafeParcelable value, needed for reflection. This is required to support backwards
-# compatibility of some classes.
--keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
- public static final *** NULL;
-}
-
-# Keep the names of classes/members we need for client functionality.
--keepnames @com.google.android.gms.common.annotation.KeepName class *
--keepclassmembernames class * {
- @com.google.android.gms.common.annotation.KeepName *;
-}
-
-# Needed for Parcelable/SafeParcelable Creators to not get stripped
--keepnames class * implements android.os.Parcelable {
- public static final ** CREATOR;
-} \ No newline at end of file
diff --git a/platform/android/libs/google_play_services/project.properties b/platform/android/libs/google_play_services/project.properties
deleted file mode 100644
index 36f15941e2..0000000000
--- a/platform/android/libs/google_play_services/project.properties
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system edit
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-#
-# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
-#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
-
-# Project target.
-target=android-15
-android.library=true
diff --git a/platform/android/libs/google_play_services/res/color/common_signin_btn_text_dark.xml b/platform/android/libs/google_play_services/res/color/common_signin_btn_text_dark.xml
deleted file mode 100644
index a615ba2747..0000000000
--- a/platform/android/libs/google_play_services/res/color/common_signin_btn_text_dark.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:state_pressed="true"
- android:color="@color/common_signin_btn_dark_text_pressed" />
- <item
- android:state_enabled="false"
- android:state_focused="true"
- android:color="@color/common_signin_btn_dark_text_disabled" />
- <item
- android:state_focused="true"
- android:color="@color/common_signin_btn_dark_text_focused" />
- <item
- android:state_enabled="false"
- android:color="@color/common_signin_btn_dark_text_disabled" />
- <item
- android:color="@color/common_signin_btn_dark_text_default" />
-</selector>
diff --git a/platform/android/libs/google_play_services/res/color/common_signin_btn_text_light.xml b/platform/android/libs/google_play_services/res/color/common_signin_btn_text_light.xml
deleted file mode 100644
index 662066899b..0000000000
--- a/platform/android/libs/google_play_services/res/color/common_signin_btn_text_light.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:state_pressed="true"
- android:color="@color/common_signin_btn_light_text_pressed" />
- <item
- android:state_enabled="false"
- android:state_focused="true"
- android:color="@color/common_signin_btn_light_text_disabled" />
- <item
- android:state_focused="true"
- android:color="@color/common_signin_btn_light_text_focused" />
- <item
- android:state_enabled="false"
- android:color="@color/common_signin_btn_light_text_disabled" />
- <item
- android:color="@color/common_signin_btn_light_text_default" />
-</selector>
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_dark.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_dark.9.png
deleted file mode 100644
index 0f9e7917e0..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_dark.9.png
deleted file mode 100644
index 570e432252..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_light.9.png
deleted file mode 100644
index 570e432252..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_light.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_light.9.png
deleted file mode 100644
index 0f9e7917e0..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_disabled_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_focus_dark.9.png
deleted file mode 100644
index f507b9f7da..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_focus_light.9.png
deleted file mode 100644
index d5625e5fc1..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_normal_dark.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_normal_dark.9.png
deleted file mode 100644
index aea3c0d168..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_normal_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_normal_light.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_normal_light.9.png
deleted file mode 100644
index 849e89f3aa..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_normal_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_pressed_dark.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_pressed_dark.9.png
deleted file mode 100644
index f4ab2f2a51..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_pressed_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_pressed_light.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_pressed_light.9.png
deleted file mode 100644
index 9fe611d684..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_icon_pressed_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_dark.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_dark.9.png
deleted file mode 100644
index bbcde39cf0..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_focus_dark.9.png
deleted file mode 100644
index 53957b698f..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_focus_light.9.png
deleted file mode 100644
index 53957b698f..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_light.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_light.9.png
deleted file mode 100644
index bbcde39cf0..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_disabled_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_focus_dark.9.png
deleted file mode 100644
index 000d12e8e3..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_focus_light.9.png
deleted file mode 100644
index d9279405c6..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_normal_dark.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_normal_dark.9.png
deleted file mode 100644
index 67f263c80e..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_normal_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_normal_light.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_normal_light.9.png
deleted file mode 100644
index 96324c52f9..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_normal_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_pressed_dark.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_pressed_dark.9.png
deleted file mode 100644
index e4503128f6..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_pressed_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_pressed_light.9.png b/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_pressed_light.9.png
deleted file mode 100644
index fb94b77616..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/common_signin_btn_text_pressed_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_medium_off_client.png b/platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_medium_off_client.png
deleted file mode 100644
index 894f1b9f93..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_medium_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_small_off_client.png b/platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_small_off_client.png
deleted file mode 100644
index ac777614e6..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_small_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_standard_off_client.png b/platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_standard_off_client.png
deleted file mode 100644
index f1c32d3b9e..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_standard_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_tall_off_client.png b/platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_tall_off_client.png
deleted file mode 100644
index 08a4670c47..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-hdpi/ic_plusone_tall_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_dark.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_dark.9.png
deleted file mode 100644
index dddcbebf12..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_dark.9.png
deleted file mode 100644
index 58b75bd7de..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_light.9.png
deleted file mode 100644
index 58b75bd7de..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_light.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_light.9.png
deleted file mode 100644
index dddcbebf12..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_disabled_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_focus_dark.9.png
deleted file mode 100644
index 7d9ed7834d..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_focus_light.9.png
deleted file mode 100644
index 0ca401d376..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_normal_dark.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_normal_dark.9.png
deleted file mode 100644
index f2c3f55717..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_normal_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_normal_light.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_normal_light.9.png
deleted file mode 100644
index 83b4fc9d6d..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_normal_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_pressed_dark.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_pressed_dark.9.png
deleted file mode 100644
index dd74fe8761..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_pressed_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_pressed_light.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_pressed_light.9.png
deleted file mode 100644
index b7dc7aac7e..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_icon_pressed_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_dark.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_dark.9.png
deleted file mode 100644
index efdfe2e616..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_focus_dark.9.png
deleted file mode 100644
index c7650b09e3..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_focus_light.9.png
deleted file mode 100644
index c7650b09e3..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_light.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_light.9.png
deleted file mode 100644
index efdfe2e616..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_disabled_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_focus_dark.9.png
deleted file mode 100644
index 8c76283e50..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_focus_light.9.png
deleted file mode 100644
index abd26bcd41..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_normal_dark.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_normal_dark.9.png
deleted file mode 100644
index 28181c338b..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_normal_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_normal_light.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_normal_light.9.png
deleted file mode 100644
index 34957fad5f..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_normal_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_pressed_dark.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_pressed_dark.9.png
deleted file mode 100644
index e923ee9c75..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_pressed_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_pressed_light.9.png b/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_pressed_light.9.png
deleted file mode 100644
index 34cf6bbad5..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/common_signin_btn_text_pressed_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_medium_off_client.png b/platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_medium_off_client.png
deleted file mode 100644
index d7e5777153..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_medium_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_small_off_client.png b/platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_small_off_client.png
deleted file mode 100644
index af301c2dc9..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_small_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_standard_off_client.png b/platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_standard_off_client.png
deleted file mode 100644
index f43e965fb8..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_standard_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_tall_off_client.png b/platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_tall_off_client.png
deleted file mode 100644
index 0b2b5c9a98..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-mdpi/ic_plusone_tall_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_dark.9.png
deleted file mode 100644
index 9044a118af..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_dark.9.png
deleted file mode 100644
index e94a49b0ae..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_light.9.png
deleted file mode 100644
index e94a49b0ae..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_light.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_light.9.png
deleted file mode 100644
index 9044a118af..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_disabled_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_focus_dark.9.png
deleted file mode 100644
index bfe4f04639..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_focus_light.9.png
deleted file mode 100644
index 876884fad7..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_normal_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_normal_dark.9.png
deleted file mode 100644
index b3e6dd5b40..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_normal_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_normal_light.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_normal_light.9.png
deleted file mode 100644
index 5a888f28f5..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_normal_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_pressed_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_pressed_dark.9.png
deleted file mode 100644
index d0f7b4cbf3..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_pressed_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_pressed_light.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_pressed_light.9.png
deleted file mode 100644
index 0db6b06450..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_icon_pressed_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_dark.9.png
deleted file mode 100644
index d182b5e2c3..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_dark.9.png
deleted file mode 100644
index 47e2aeaf32..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_light.9.png
deleted file mode 100644
index 47e2aeaf32..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_light.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_light.9.png
deleted file mode 100644
index d182b5e2c3..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_disabled_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_focus_dark.9.png
deleted file mode 100644
index 64e9706874..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_focus_light.9.png
deleted file mode 100644
index 0fd8cdda14..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_normal_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_normal_dark.9.png
deleted file mode 100644
index 3427b47681..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_normal_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_normal_light.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_normal_light.9.png
deleted file mode 100644
index 31e38c4c12..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_normal_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_pressed_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_pressed_dark.9.png
deleted file mode 100644
index e6a7880730..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_pressed_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_pressed_light.9.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_pressed_light.9.png
deleted file mode 100644
index 972962dcfd..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/common_signin_btn_text_pressed_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_medium_off_client.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_medium_off_client.png
deleted file mode 100644
index bb933092be..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_medium_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_small_off_client.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_small_off_client.png
deleted file mode 100644
index 6174fcd9b1..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_small_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_standard_off_client.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_standard_off_client.png
deleted file mode 100644
index 6a4c298e2d..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_standard_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_tall_off_client.png b/platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_tall_off_client.png
deleted file mode 100644
index f68e9133bb..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xhdpi/ic_plusone_tall_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_dark.9.png
deleted file mode 100644
index c97f349fae..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_dark.9.png
deleted file mode 100644
index 34cbff115c..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_light.9.png
deleted file mode 100644
index 34cbff115c..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_light.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_light.9.png
deleted file mode 100644
index c97f349fae..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_disabled_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_focus_dark.9.png
deleted file mode 100644
index 702c49b74c..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_focus_light.9.png
deleted file mode 100644
index 06ad5a5ae7..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_normal_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_normal_dark.9.png
deleted file mode 100644
index af160fc73b..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_normal_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_normal_light.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_normal_light.9.png
deleted file mode 100644
index c647fb4ce8..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_normal_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_pressed_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_pressed_dark.9.png
deleted file mode 100644
index fd0a4312b4..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_pressed_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_pressed_light.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_pressed_light.9.png
deleted file mode 100644
index f8ce5a6aca..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_icon_pressed_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_dark.9.png
deleted file mode 100644
index b491f629fd..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_dark.9.png
deleted file mode 100644
index 777c8d6408..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_light.9.png
deleted file mode 100644
index 777c8d6408..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_light.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_light.9.png
deleted file mode 100644
index b491f629fd..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_disabled_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_focus_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_focus_dark.9.png
deleted file mode 100644
index c8a8f1cbdf..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_focus_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_focus_light.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_focus_light.9.png
deleted file mode 100644
index bcd0d0caf4..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_focus_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_normal_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_normal_dark.9.png
deleted file mode 100644
index ac75dad52e..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_normal_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_normal_light.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_normal_light.9.png
deleted file mode 100644
index c19afad669..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_normal_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_pressed_dark.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_pressed_dark.9.png
deleted file mode 100644
index c49044185a..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_pressed_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_pressed_light.9.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_pressed_light.9.png
deleted file mode 100644
index c52be7455e..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/common_signin_btn_text_pressed_light.9.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_medium_off_client.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_medium_off_client.png
deleted file mode 100644
index 4f23739dc3..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_medium_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_small_off_client.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_small_off_client.png
deleted file mode 100644
index 8ffa1d72e6..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_small_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_standard_off_client.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_standard_off_client.png
deleted file mode 100644
index 4d81cf40cd..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_standard_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_tall_off_client.png b/platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_tall_off_client.png
deleted file mode 100644
index fab5a79b45..0000000000
--- a/platform/android/libs/google_play_services/res/drawable-xxhdpi/ic_plusone_tall_off_client.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/libs/google_play_services/res/drawable/common_signin_btn_icon_dark.xml b/platform/android/libs/google_play_services/res/drawable/common_signin_btn_icon_dark.xml
deleted file mode 100644
index dd1cf679fe..0000000000
--- a/platform/android/libs/google_play_services/res/drawable/common_signin_btn_icon_dark.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:state_pressed="true"
- android:drawable="@drawable/common_signin_btn_icon_pressed_dark" />
- <item
- android:state_enabled="false"
- android:state_focused="true"
- android:drawable="@drawable/common_signin_btn_icon_disabled_focus_dark" />
- <item
- android:state_focused="true"
- android:drawable="@drawable/common_signin_btn_icon_focus_dark" />
- <item
- android:state_enabled="false"
- android:drawable="@drawable/common_signin_btn_icon_disabled_dark" />
- <item
- android:drawable="@drawable/common_signin_btn_icon_normal_dark" />
-</selector>
diff --git a/platform/android/libs/google_play_services/res/drawable/common_signin_btn_icon_light.xml b/platform/android/libs/google_play_services/res/drawable/common_signin_btn_icon_light.xml
deleted file mode 100644
index abf412bda8..0000000000
--- a/platform/android/libs/google_play_services/res/drawable/common_signin_btn_icon_light.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:state_pressed="true"
- android:drawable="@drawable/common_signin_btn_icon_pressed_light" />
- <item
- android:state_enabled="false"
- android:state_focused="true"
- android:drawable="@drawable/common_signin_btn_icon_disabled_focus_light" />
- <item
- android:state_focused="true"
- android:drawable="@drawable/common_signin_btn_icon_focus_light" />
- <item
- android:state_enabled="false"
- android:drawable="@drawable/common_signin_btn_icon_disabled_light" />
- <item
- android:drawable="@drawable/common_signin_btn_icon_normal_light" />
-</selector>
diff --git a/platform/android/libs/google_play_services/res/drawable/common_signin_btn_text_dark.xml b/platform/android/libs/google_play_services/res/drawable/common_signin_btn_text_dark.xml
deleted file mode 100644
index 2d92217cdf..0000000000
--- a/platform/android/libs/google_play_services/res/drawable/common_signin_btn_text_dark.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:state_pressed="true"
- android:drawable="@drawable/common_signin_btn_text_pressed_dark" />
- <item
- android:state_enabled="false"
- android:state_focused="true"
- android:drawable="@drawable/common_signin_btn_text_disabled_focus_dark" />
- <item
- android:state_focused="true"
- android:drawable="@drawable/common_signin_btn_text_focus_dark" />
- <item
- android:state_enabled="false"
- android:drawable="@drawable/common_signin_btn_text_disabled_dark" />
- <item
- android:drawable="@drawable/common_signin_btn_text_normal_dark" />
-</selector>
diff --git a/platform/android/libs/google_play_services/res/drawable/common_signin_btn_text_light.xml b/platform/android/libs/google_play_services/res/drawable/common_signin_btn_text_light.xml
deleted file mode 100644
index 810c02112d..0000000000
--- a/platform/android/libs/google_play_services/res/drawable/common_signin_btn_text_light.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:state_pressed="true"
- android:drawable="@drawable/common_signin_btn_text_pressed_light" />
- <item
- android:state_enabled="false"
- android:state_focused="true"
- android:drawable="@drawable/common_signin_btn_text_disabled_focus_light" />
- <item
- android:state_focused="true"
- android:drawable="@drawable/common_signin_btn_text_focus_light" />
- <item
- android:state_enabled="false"
- android:drawable="@drawable/common_signin_btn_text_disabled_light" />
- <item
- android:drawable="@drawable/common_signin_btn_text_normal_light" />
-</selector>
diff --git a/platform/android/libs/google_play_services/res/values-af/strings.xml b/platform/android/libs/google_play_services/res/values-af/strings.xml
deleted file mode 100644
index 1b211f5076..0000000000
--- a/platform/android/libs/google_play_services/res/values-af/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Kry Google Play-dienste"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Hierdie program sal nie loop sonder Google Play-dienste nie, wat nie op jou foon is nie."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Hierdie program sal nie loop sonder Google Play-dienste nie, wat nie op jou tablet is nie."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Kry Google Play-dienste"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Aktiveer Google Play-dienste"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Hierdie program sal nie werk tensy jy Google Play-dienste aktiveer nie."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Aktiveer Google Play-dienste"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Dateer Google Play-dienste op"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Hierdie program sal nie loop nie, tensy jy Google Play-dienste opdateer."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Netwerkfout"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"\'n Dataverbinding is nodig om aan Google Play-dienste te koppel."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ongeldige rekening"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Die gespesifiseerde rekening bestaan nie op hierdie toestel nie. Kies asseblief \'n ander rekening."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Onbekende probleem met Google Play-dienste."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play-dienste"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play-dienste, waarop sommige van jou programme staatmaak, werk nie met jou toestel nie. Kontak asseblief die vervaardiger vir bystand."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Dit lyk of die datum op die toestel verkeerd is. Gaan asseblief die datum op die toestel na."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Dateer op"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Meld aan"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Meld aan met Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"\'n Program het probeer om \'n slegte weergawe van Google Play-dienste te gebruik."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"\'n Program vereis dat Google Play-dienste geaktiveer word."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"\'n Program vereis dat Google Play-dienste geïnstalleer word."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"\'n Program vereis \'n opdatering vir Google Play-dienste."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play-dienstefout"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Versoek deur <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-am/strings.xml b/platform/android/libs/google_play_services/res/values-am/strings.xml
deleted file mode 100644
index 2585210fe0..0000000000
--- a/platform/android/libs/google_play_services/res/values-am/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play አገልግሎቶችን አግኝ"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"ይህ መተግበሪያ ያለ Google Play አገልግሎቶች አይሰራም፣ እነሱ ደግሞ ስልክዎ ላይ የሉም።"</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"ይህ መተግበሪያ ያለ Google Play አገልግሎቶች አይሰራም፣ እነሱ ደግሞ ጡባዊዎ ላይ የሉም።"</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play አገልግሎቶችን አግኝ"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play አገልግሎቶችን አንቃ"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Google Play አገልግሎቶችን እስካላነቁ ድረስ ይህ መተግበሪያ አይሰራም።"</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play አገልግሎቶችን አንቃ"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play አገልግሎቶችን ያዘምኑ"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Google Play አገልግሎቶችን እስኪያዘምኑ ድረስ ይህ መተግበሪያ አይሰራም።"</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"የአውታረ መረብ ስህተት"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"ከGoogle Play አገልግሎቶች ጋር ለመገናኘት የውሂብ ግንኙነት ያስፈልጋል።"</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"ልክ ያልሆነ መለያ"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"የተገለጸው መለያ በዚህ መሣሪያ ላይ የለም። እባክው የተለየ መለያ ይምረጡ።"</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"በGoogle Play አገልግሎቶች ላይ ያልታወቀ ችግር።"</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play አገልግሎቶች"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"የGoogle Play አገልግሎቶች፣ አንዳንድ መተግበሪያዎችዎ በእሱ ላይ ጥገኛ የሆኑት፣ በመሣሪያዎ አይደገፍም። እባክዎ ለእርዳታ አምራቹን ያግኙ።"</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"በመሣሪያው ላይ ያለው ቀን ትክክል አይመስልም። እባክዎ በመሣሪያው ላይ ያለውን ቀን ያረጋግጡ።"</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"ያዘምኑ"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"ግባ"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"በGoogle ይግቡ"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"መተግበሪያው የGoogle Play አገልግሎቶችን መጥፎ ስሪት ለመጠቀም ሞክሯል።"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"መተግበሪያው Google Play አገልግሎቶች እንዲነቁ ይፈልጋል።"</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"መተግበሪያው Google Play አገልግሎቶች እንዲጫኑ ይፈልጋል።"</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"መተግበሪያው Google Play አገልግሎቶች እንዲዘምን ይፈልጋል።"</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"የGoogle Play አገልግሎቶች ስህተት"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"በ<xliff:g id="APP_NAME">%1$s</xliff:g> የተጠየቀ"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-ar/strings.xml b/platform/android/libs/google_play_services/res/values-ar/strings.xml
deleted file mode 100644
index 9451b37181..0000000000
--- a/platform/android/libs/google_play_services/res/values-ar/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"‏الحصول على خدمات Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"‏لن يتم تشغيل هذا التطبيق بدون خدمات Google Play، والتي لا تتوفر في هاتفك."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"‏لن يتم تشغيل هذا التطبيق بدون خدمات Google Play، والتي لا تتوفر في جهازك اللوحي."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"‏الحصول على خدمات Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"‏تمكين خدمات Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"‏لن يعمل هذا التطبيق ما لم يتم تمكين خدمات Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"‏تمكين خدمات Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"‏تحديث خدمات Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"‏لن يتم تشغيل هذا التطبيق ما لم تحدِّث خدمات Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"خطأ في الشبكة"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"‏يتطلب الاتصال بخدمات Google Play وجود اتصال بيانات."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"حساب غير صالح"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"الحساب الذي تمّ تحديده غير موجود على الجهاز. يُرجى اختيار حساب آخر."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"‏حدثت مشكلة غير معروفة في خدمات Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"‏خدمات Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"‏خدمات Google Play التي تستجيب لها بعض تطبيقاتك لا تعمل على جهازك. يُرجى الاتصال بجهة التصنيع للحصول على المساعدة."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"يبدو أن التاريخ على الجهاز غير صحيح. الرجاء التحقق من التاريخ على الجهاز."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"تحديث"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"تسجيل الدخول"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"‏تسجيل الدخول باستخدام Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"‏يحاول أحد التطبيقات استخدام إصدار غير صالح من خدمات Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"‏يتطلب أحد التطبيقات تمكين خدمات Google Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"‏يتطلب أحد التطبيقات تثبيت خدمات Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"‏يتطلب أحد التطبيقات تحديث خدمات Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"‏خطأ في خدمات Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"تم الطلب عن طريق <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-be/strings.xml b/platform/android/libs/google_play_services/res/values-be/strings.xml
deleted file mode 100644
index 81382d1c0f..0000000000
--- a/platform/android/libs/google_play_services/res/values-be/strings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Атрымаць службы Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Гэта прыкладанне не будзе працаваць без службаў Google Play, якіх няма ў вашым тэлефоне."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Гэта прыкладанне не будзе працаваць без службаў Google Play, якіх няма на вашым планшэце."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Атрымаць службы Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Уключыць службы Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Гэта прыкладанне не будзе працаваць, пакуль вы не ўключыце службы Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Уключыць службы Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Абнаўленне службаў Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Гэта прыкладанне не будзе працаваць падчас абнаўлення службаў Google Play."</string>
- <!-- no translation found for common_google_play_services_network_error_title (3827284619958211114) -->
- <skip />
- <!-- no translation found for common_google_play_services_network_error_text (9038847255613537209) -->
- <skip />
- <!-- no translation found for common_google_play_services_invalid_account_title (1066672360770936753) -->
- <skip />
- <!-- no translation found for common_google_play_services_invalid_account_text (4983316348021735578) -->
- <skip />
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Невядомая праблема са службамі Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Службы Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Службы Google Play, да якiх прывязаны некаторыя прыкладаннi, не падтрымлiваюцца на вашай прыладзе. Па дапамогу звярнiцеся да вытворцы."</string>
- <!-- no translation found for common_google_play_services_unsupported_date_text (4725396522367789365) -->
- <skip />
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Абнавіць"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Увайсцi"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Увайсці ў Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Прыкладанне паспрабавала скарыстацца сапсаванай версіяй службаў Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Прыкладанне патрабуе ўключэння службаў Google Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Прыкладанне патрабуе ўсталявання службаў Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Прыкладанне патрабуе абнаўлення службаў Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Памылка службаў Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Запытана прыкладаннем <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-bg/strings.xml b/platform/android/libs/google_play_services/res/values-bg/strings.xml
deleted file mode 100644
index bb8da3c105..0000000000
--- a/platform/android/libs/google_play_services/res/values-bg/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Изтегляне на услугите за Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Това приложение няма да се изпълнява без услугите за Google Play, които липсват в телефона ви."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Това приложение няма да се изпълнява без услугите за Google Play, които липсват в таблета ви."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Услуги за Google Play: Изтегл."</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Активиране на услугите за Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Това приложение няма да работи, освен ако не активирате услугите за Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Услуги за Google Play: Актив."</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Актуализиране на услугите за Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Това приложение няма да се изпълнява, освен ако не актуализирате услугите за Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Грешка в мрежата"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"За свързване с услугите за Google Play се изисква връзка за данни."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Невалиден профил"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Посоченият профил не съществува на това устройство. Моля, изберете друг."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Неизвестен проблем с услугите за Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Услуги за Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Услугите за Google Play, на които разчитат някои от приложенията ви, не се поддържат от устройството ви. Моля, свържете се с производителя за помощ."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Изглежда, че датата на устройството е неправилна. Моля, проверете я."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Актуализиране"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Вход"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Вход с Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Приложение опита да ползва неправилна версия на услуг. за Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Приложение изисква активирането на услугите за Google Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Приложение изисква инсталирането на услугите за Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Приложение изисква актуализирането на услугите за Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Грешка в услугите за Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Заявено от <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-ca/strings.xml b/platform/android/libs/google_play_services/res/values-ca/strings.xml
deleted file mode 100644
index 5b63e86af7..0000000000
--- a/platform/android/libs/google_play_services/res/values-ca/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Baixa els serveis de Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Aquesta aplicació no s\'executarà si el telèfon no té instal·lats els serveis de Google Play."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Aquesta aplicació no funcionarà si la tauleta no té instal·lats els serveis de Google Play."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Baixa els serveis de Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Activa els serveis de Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Aquesta aplicació no funcionarà si no actives els serveis de Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Activa els serveis de Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Actualitza els serveis de Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Aquesta aplicació no s\'executarà si no actualitzes els serveis de Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Error de xarxa"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Es requereix una connexió de dades per connectar amb els serveis de Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Compte no vàlid"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"El compte especificat no existeix en aquest dispositiu. Tria un compte diferent."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Error desconegut relacionat amb els serveis de Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Serveis de Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"El teu dispositiu no és compatible amb els serveis de Google Play, en què es basen les teves aplicacions. Per obtenir assistència, contacta amb el fabricant."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Sembla que la data del dispositiu no és correcta. Comprova-la."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Actualitza"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Inicia sessió"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Inicia sessió amb Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Una aplic. ha intentat utilitzar una versió errònia de serveis de Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Una aplicació requereix que s\'activin els serveis de Google Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Una aplicació requereix que s\'instal·lin els serveis de Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Una aplicació requereix que s\'actualitzin els serveis de Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Error dels serveis de Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Sol·licitada per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-cs/strings.xml b/platform/android/libs/google_play_services/res/values-cs/strings.xml
deleted file mode 100644
index 1b5423b039..0000000000
--- a/platform/android/libs/google_play_services/res/values-cs/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Instalovat služby Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ke spuštění této aplikace jsou potřeba služby Google Play, které v telefonu nemáte."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ke spuštění této aplikace jsou potřeba služby Google Play, které v tabletu nemáte."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Instalovat služby Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Aktivovat služby Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ke spuštění této aplikace je třeba aktivovat služby Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Aktivovat služby Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Aktualizace služeb Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ke spuštění této aplikace je třeba aktualizovat služby Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Chyba sítě"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Připojení ke službám Google Play vyžaduje datové připojení."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Neplatný účet"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Zadaný účet v tomto zařízení neexistuje. Zvolte prosím jiný účet."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Nastal neznámý problém se službami Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Služby Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Některé vaše aplikace vyžadují služby Google Play, které ve vašem zařízení nejsou podporovány. S žádostí o pomoc se prosím obraťte na výrobce."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Datum v zařízení není správně nastaveno. Zkontrolujte prosím datum."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Aktualizovat"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Přihlásit se"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Přihlásit se účtem Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Aplikace se pokusila použít nesprávnou verzi Služeb Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Aplikace vyžaduje aktivované Služby Google Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Aplikace vyžaduje instalaci Služeb Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Aplikace vyžaduje aktualizaci Služeb Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Chyba služeb Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Požadováno aplikací <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-da/strings.xml b/platform/android/libs/google_play_services/res/values-da/strings.xml
deleted file mode 100644
index daa2160d3b..0000000000
--- a/platform/android/libs/google_play_services/res/values-da/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Hent Google Play-tjenester"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Denne app kan ikke køre uden Google Play-tjenester, som mangler på din telefon."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Denne app kan ikke køre uden Google Play-tjenester, som mangler på din tablet."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Hent Google Play-tjenester"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Aktivér Google Play-tjenester"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Denne app virker ikke, medmindre du aktiverer Google Play-tjenester."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Aktivér Google Play-tjenester"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Opdater Google Play-tjenester"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Denne app kan ikke køre, medmindre du opdaterer Google Play-tjenester."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Netværksfejl"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Der kræves en dataforbindelse for at oprette forbindelse til Google Play-tjenester."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ugyldig konto"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Den angivne konto findes ikke på denne enhed. Vælg en anden konto."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Ukendt problem med Google Play-tjenester."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play-tjenester"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play-tjenester, som nogle af dine applikationer er afhængige af, understøttes ikke af din enhed. Kontakt producenten for at få hjælp."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Datoen på enheden ser ud til at være forkert. Husk at kontrollere datoen på enheden."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Opdater"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Log ind"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Log ind med Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"En applikation forsøgte at bruge en defekt version af Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"En applikation kræver, at Google Play er aktiveret."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"En applikation kræver, at Google Play er installeret."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"En applikation kræver en opdatering af Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Fejl i Google Play-tjenester"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Anmodning fra <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-de/strings.xml b/platform/android/libs/google_play_services/res/values-de/strings.xml
deleted file mode 100644
index df8e88e9e2..0000000000
--- a/platform/android/libs/google_play_services/res/values-de/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play-Dienste installieren"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Zur Nutzung dieser App sind Google Play-Dienste erforderlich, die auf Ihrem Telefon nicht installiert sind."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Zur Nutzung dieser App sind Google Play-Dienste erforderlich, die auf Ihrem Tablet nicht installiert sind."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play-Dienste installieren"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play-Dienste aktivieren"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Diese App funktioniert nur, wenn Sie die Google Play-Dienste aktivieren."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play-Dienste aktivieren"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play-Dienste aktualisieren"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Diese App wird nur ausgeführt, wenn Sie die Google Play-Dienste aktualisieren."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Netzwerkfehler"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Um eine Verbindung zu den Google Play-Diensten herzustellen, ist eine Datenverbindung erforderlich."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ungültiges Konto"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Das angegebene Konto ist auf diesem Gerät nicht vorhanden. Bitte wählen Sie ein anderes Konto aus."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Unbekanntes Problem mit Google Play-Diensten"</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play-Dienste"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play-Dienste, auf denen einige Ihrer Apps basieren, werden von diesem Gerät nicht unterstützt. Wenden Sie sich für weitere Informationen an den Hersteller."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Das Datum auf dem Gerät scheint falsch zu sein. Bitte überprüfen Sie das Datum auf dem Gerät."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Aktualisieren"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Anmelden"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Über Google anmelden"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"App versuchte, defekte Google Play-Dienste-Version zu verwenden"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"App erfordert aktivierte Google Play-Dienste"</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"App erfordert die Installation von Google Play-Diensten"</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"App erfordert ein Update für Google Play-Dienste"</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Fehler bei Google Play-Diensten"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Angefordert von <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-el/strings.xml b/platform/android/libs/google_play_services/res/values-el/strings.xml
deleted file mode 100644
index 13a5dc5ef3..0000000000
--- a/platform/android/libs/google_play_services/res/values-el/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Λήψη υπηρεσιών Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Αυτή η εφαρμογή δεν θα εκτελεστεί χωρίς τις υπηρεσίες Google Play, οι οποίες λείπουν από το τηλέφωνό σας."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Αυτή η εφαρμογή δεν θα εκτελεστεί χωρίς τις υπηρεσίες Google Play, οι οποίες λείπουν από το tablet σας."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Λήψη υπηρεσιών Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Ενεργοποίηση υπηρεσιών Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Αυτή η εφαρμογή δεν θα λειτουργήσει εάν δεν έχετε ενεργοποιήσει τις υπηρεσίες Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Ενεργοπ. υπηρεσιών Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Ενημέρωση υπηρεσιών Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Αυτή η εφαρμογή θα εκτελεστεί αφού ενημερώσετε τις υπηρεσίες Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Σφάλμα δικτύου"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Απαιτείται σύνδεση δεδομένων για να συνδεθείτε με τις Υπηρεσίες Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Μη έγκυρος λογαριασμός"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Ο συγκεκριμένος λογαριασμός δεν υπάρχει σε αυτήν τη συσκευή. Επιλέξτε έναν διαφορετικό λογαριασμό."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Άγνωστο πρόβλημα με τις υπηρεσίες Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Υπηρεσίες Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Οι υπηρεσίες Google Play, στις οποίες βασίζονται ορισμένες από τις εφαρμογές σας, δεν υποστηρίζονται στη συσκευή σας. Επικοινωνήστε με τον κατασκευαστή για υποστήριξη."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Η ημερομηνία στη συσκευή φαίνεται λανθασμένη. Ελέγξτε την ημερομηνία στη συσκευή."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Ενημέρωση"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Σύνδεση"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Συνδεθείτε στο Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Απόπειρα χρήσης ακατάλληλης έκδοσης Υπηρεσιών Google Play από εφαρμογή"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Μια εφαρμογή απαιτεί τις Υπηρεσίες Google Play για ενεργοποίηση."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Μια εφαρμογή απαιτεί την εγκατάσταση των Υπηρεσιών Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Μια εφαρμογή απαιτεί μια ενημέρωση για τις Υπηρεσίες Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Σφάλμα υπηρεσιών Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Υποβλήθηκε αίτημα από την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-en-rGB/strings.xml b/platform/android/libs/google_play_services/res/values-en-rGB/strings.xml
deleted file mode 100644
index 106d390b3e..0000000000
--- a/platform/android/libs/google_play_services/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Get Google Play services"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"This app won\'t run without Google Play services, which are missing from your phone."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"This app won\'t run without Google Play services, which are missing from your tablet."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Get Google Play services"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Enable Google Play services"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"This app won\'t work unless you enable Google Play services."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Enable Google Play services"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Update Google Play services"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"This app won\'t run unless you update Google Play services."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Network Error"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"A data connection is required to connect to Google Play services."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Invalid Account"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"The specified account does not exist on this device. Please choose a different account."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Unknown issue with Google Play services."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play services"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play services, which some of your applications rely on, is not supported by your device. Please contact the manufacturer for assistance."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"The date on the device appears to be incorrect. Please check the date on the device."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Update"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Sign in"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Sign in with Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"An application attempted to use a bad version of Google Play Services."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"An application requires Google Play Services to be enabled."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"An application requires installation of Google Play Services."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"An application requires an update for Google Play Services."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play services error"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Requested by <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-en-rIN/strings.xml b/platform/android/libs/google_play_services/res/values-en-rIN/strings.xml
deleted file mode 100644
index 106d390b3e..0000000000
--- a/platform/android/libs/google_play_services/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Get Google Play services"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"This app won\'t run without Google Play services, which are missing from your phone."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"This app won\'t run without Google Play services, which are missing from your tablet."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Get Google Play services"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Enable Google Play services"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"This app won\'t work unless you enable Google Play services."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Enable Google Play services"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Update Google Play services"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"This app won\'t run unless you update Google Play services."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Network Error"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"A data connection is required to connect to Google Play services."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Invalid Account"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"The specified account does not exist on this device. Please choose a different account."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Unknown issue with Google Play services."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play services"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play services, which some of your applications rely on, is not supported by your device. Please contact the manufacturer for assistance."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"The date on the device appears to be incorrect. Please check the date on the device."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Update"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Sign in"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Sign in with Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"An application attempted to use a bad version of Google Play Services."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"An application requires Google Play Services to be enabled."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"An application requires installation of Google Play Services."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"An application requires an update for Google Play Services."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play services error"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Requested by <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-es-rUS/strings.xml b/platform/android/libs/google_play_services/res/values-es-rUS/strings.xml
deleted file mode 100644
index 6be905908c..0000000000
--- a/platform/android/libs/google_play_services/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Obtener Google Play Services"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Esta aplicación no se ejecutará si no instalasGoogle Play Services en tu dispositivo."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Esta aplicación no se ejecutará si no instalas Google Play Services en tu tablet."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Descargar Google Play Services"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Activar Google Play Services"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Esta aplicación no funcionará si no activas Google Play Services."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Activar Google Play Services"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Actualizar Google Play Services"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Esta aplicación no se ejecutará si no actualizas Google Play Services."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Error de red"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Se necesita una conexión de datos para establecer conexión con Google Play Services."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Cuenta no válida"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"La cuenta especificada no existe en este dispositivo. Elige otra cuenta."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Error desconocido relacionado con Google Play Services"</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play Services"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play Services, del cual dependen algunas de tus aplicaciones, no es compatible con tu dispositivo. Comunícate con el fabricante para obtener ayuda."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Parece que la fecha del dispositivo es incorrecta. ¿Puedes revisarla?"</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Actualizar"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Acceder"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Acceder con Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Una aplic. intentó usar una versión no válida de Google Play Services"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Una aplicación requiere que se active Google Play Services"</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Una aplicación requiere que se instale Google Play Services"</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Una aplicación requiere que se actualice Google Play Services"</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Error de Google Play Services"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Solicitada por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-es/strings.xml b/platform/android/libs/google_play_services/res/values-es/strings.xml
deleted file mode 100644
index ed32995cf2..0000000000
--- a/platform/android/libs/google_play_services/res/values-es/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Descargar servicios de Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Esta aplicación no se ejecutará si tu teléfono no tiene instalados los servicios de Google Play."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Esta aplicación no se ejecutará si tu tablet no tiene instalados los servicios de Google Play."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Descargar servicios de Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Habilitar servicios de Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Esta aplicación no funcionará si no habilitas los servicios de Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Habilitar servicios de Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Actualizar servicios de Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Esta aplicación no se ejecutará si no actualizas los servicios de Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Error de red"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Se necesita una conexión de datos para establecer conexión con los servicios de Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Cuenta no válida"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"La cuenta especificada no existe en este dispositivo. Selecciona otra cuenta."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Error desconocido relacionado con los servicios de Google Play"</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Servicios de Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Tu dispositivo no es compatible con los servicios de Google Play, de los cuales dependen tus aplicaciones. Para obtener asistencia, ponte en contacto el fabricante."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Parece que la fecha del dispositivo es incorrecta. Compruébala."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Actualizar"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Iniciar sesión"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Iniciar sesión con Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Una aplicación intentó usar versión incorrecta de servicios de Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Una aplicación requiere que se habiliten los servicios de Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Una aplicación requiere que se instalen los servicios de Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Una aplicación requiere que se actualicen los servicios de Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Error de los servicios de Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Solicitada por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-et-rEE/strings.xml b/platform/android/libs/google_play_services/res/values-et-rEE/strings.xml
deleted file mode 100644
index 281caff497..0000000000
--- a/platform/android/libs/google_play_services/res/values-et-rEE/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Hankige Google Play teenused"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Selle rakenduse käitamiseks on vaja Google Play teenuseid, mida teie telefonis pole."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Selle rakenduse käitamiseks on vaja Google Play teenuseid, mida teie tahvelarvutis pole."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Hankige Google Play teenused"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Lubage Google Play teenused"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"See rakendus ei tööta, kui te ei luba Google Play teenuseid."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Lubage Google Play teenused"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Värskendage Google Play teenuseid"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Seda rakendust ei saa käitada, kui te ei värskenda Google Play teenuseid."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Võrgu viga"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play teenustega ühenduse loomiseks on vajalik andmesideühendus."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Vale konto"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Määratud kontot pole selles seadmes olemas. Valige muu konto."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play teenuste tundmatu probleem."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play teenused"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Teie seade ei toeta Google Play teenuseid, millele mõni teie rakendustest toetub. Abi saamiseks võtke ühendust tootjaga."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Seadme kuupäev paistab olevat vale. Kontrollige seadme kuupäeva."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Värskenda"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Logi sisse"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Logi sisse Google\'iga"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Rakendus püüdis kasutada Google Play teenuste sobimatut versiooni."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Rakenduse kasutamiseks peavad olema lubatud Google Play teenused."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Rakenduse kasutamiseks peavad olema installitud Google Play teenused."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Rakenduse kasutamiseks tuleb värskendada Google Play teenuseid."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Viga Google Play teenustes"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Päringu esitas: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-fa/strings.xml b/platform/android/libs/google_play_services/res/values-fa/strings.xml
deleted file mode 100644
index 87e10d189c..0000000000
--- a/platform/android/libs/google_play_services/res/values-fa/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"‏دریافت خدمات Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"‏این برنامه بدون خدمات Google Play اجرا نمی‌شود، این خدمات در تلفن شما وجود ندارد."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"‏این برنامه بدون خدمات Google Play اجرا نمی‌شود، این خدمات در رایانهٔ لوحی شما وجود ندارد."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"‏دریافت خدمات Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"‏فعال کردن خدمات Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"‏تا زمانی‌که خدمات Google Play را فعال نکنید این برنامه کار نمی‌کند."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"‏فعال کردن خدمات Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"‏به‌روزرسانی خدمات Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"‏تا زمانی‌که خدمات Google Play را به‌روز نکنید این برنامه کار نمی‌کند."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"خطای شبکه"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"‏برای اتصال به خدمات Google Play اتصال داده لازم است."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"حساب نامعتبر"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"حسابی که تعیین کردید در این دستگاه وجود ندارد. لطفاً حساب دیگری را انتخاب کنید."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"‏مشکل نامشخص در خدمات Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"‏خدمات Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"‏خدمات Google Play، که برخی از برنامه‌های شما به آن وابسته است، توسط دستگاه شما پشتیبانی نمی‌شود. لطفاً برای دریافت کمک با سازنده تماس بگیرید."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"تاریخ روی دستگاه ظاهراً اشتباه است. لطفاً تاریخ روی دستگاه را بررسی کنید."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"به‌روزرسانی"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"ورود به سیستم"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"‏ورود به سیستم با Google‎"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"‏برنامه‌ای تلاش کرد از نسخه نادرستی از خدمات Google Play استفاده کند."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"‏برنامه‌ای به فعال کردن خدمات Google Play نیاز دارد."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"‏برنامه‌ای به نصب خدمات Google Play نیاز دارد."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"‏برنامه‌ای به به‌روزرسانی خدمات Google Play نیاز دارد."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"‏خطا در خدمات Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"درخواست توسط <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-fi/strings.xml b/platform/android/libs/google_play_services/res/values-fi/strings.xml
deleted file mode 100644
index 00d3ceb215..0000000000
--- a/platform/android/libs/google_play_services/res/values-fi/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Asenna Google Play -palvelut"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Tämä sovellus ei toimi ilman Google Play -palveluita, jotka puuttuvat puhelimesta."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Tämä sovellus ei toimi ilman Google Play -palveluita, jotka puuttuvat tablet-laitteesta."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Asenna Google Play -palvelut"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Ota Google Play -palvelut käyttöön"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Tämä sovellus ei toimi, ellet ota Google Play -palveluita käyttöön."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Ota Google Play -palv. käyttöön"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Päivitä Google Play -palvelut"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Tämä sovellus ei toimi, ellet päivitä Google Play -palveluita."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Verkkovirhe"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play -palveluiden käyttöön tarvitaan tietoliikenneyhteys."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Tili ei kelpaa"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Kyseistä tiliä ei ole tällä laitteella. Valitse toinen tili."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Tuntematon ongelma käytettäessä Google Play -palveluita."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play -palvelut"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play -palveluita, joita osa sovelluksistasi käyttää, ei tueta laitteellasi. Pyydä ohjeita laitteen valmistajalta."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Laitteen päivämäärä vaikuttaa virheelliseltä. Tarkista laitteen päivämäärä."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Päivitä"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Kirjaudu"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Kirjaudu Google-tiliin"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Sovellus yritti käyttää virheellistä Google Play -palveluiden versiota"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Ota käyttöön Google Play -palvelut, jotta sovellus toimii."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Asenna Google Play -palvelut, jotta sovellus toimii."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Päivitä Google Play -palvelut, jotta sovellus toimii."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Virhe Google Play -palveluissa"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Pyynnön teki <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-fr-rCA/strings.xml b/platform/android/libs/google_play_services/res/values-fr-rCA/strings.xml
deleted file mode 100644
index e915fe4067..0000000000
--- a/platform/android/libs/google_play_services/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Installer les services Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Cette application ne fonctionnera pas sans les services Google Play, qui ne sont pas installés sur votre téléphone."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Cette application ne fonctionnera pas sans les services Google Play, qui ne sont pas installés sur votre tablette."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Installer les services Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Activer les services Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Cette application ne fonctionnera pas tant que vous n\'aurez pas activé les services Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Activer les services Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Mettre à jour les services Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Cette application ne fonctionnera pas tant que vous n\'aurez pas mis à jour les services Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Erreur réseau"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Vous devez disposer d\'une connexion de données pour utiliser les services Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Compte erroné"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Le compte indiqué n\'existe pas sur cet appareil. Veuillez sélectionner un autre compte."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Problème inconnu avec les services Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Services Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Les services Google Play, dont dépendent certaines de vos applications, ne sont pas compatibles avec votre appareil. Veuillez contacter le fabricant pour obtenir de l\'aide."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"La date sur l\'appareil semble incorrecte. Veuillez la vérifier."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Mettre à jour"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Connexion"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Se connecter via Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Une application requiert une version valide des services Google Play"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Une application requiert l\'activation des services Google Play"</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Une application requiert l\'installation des services Google Play"</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Une application requiert la mise à jour des services Google Play"</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Erreur liée aux services Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Demandée par <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-fr/strings.xml b/platform/android/libs/google_play_services/res/values-fr/strings.xml
deleted file mode 100644
index 321b28370b..0000000000
--- a/platform/android/libs/google_play_services/res/values-fr/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Installer les services Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Cette application ne fonctionnera pas sans les services Google Play, qui ne sont pas installés sur votre téléphone."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Cette application ne fonctionnera pas sans les services Google Play, qui ne sont pas installés sur votre tablette."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Installer services Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Activer les services Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Cette application ne fonctionnera pas tant que vous n\'aurez pas activé les services Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Activer services Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Mettre à jour les services Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Cette application ne fonctionnera pas tant que vous n\'aurez pas mis à jour les services Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Erreur réseau"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Vous devez disposer d\'une connexion de données pour utiliser les services Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Compte erroné"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Le compte indiqué n\'existe pas sur cet appareil. Veuillez sélectionner un autre compte."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Problème inconnu avec les services Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Services Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Les services Google Play, dont dépendent certaines de vos applications, ne sont pas compatibles avec votre appareil. Veuillez contacter le fabricant pour obtenir de l\'aide."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"La date sur l\'appareil semble incorrecte. Veuillez la vérifier."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Mettre à jour"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Connexion"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Se connecter avec Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Une application requiert une version valide des services Google Play"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Une application requiert l\'activation des services Google Play"</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Une application requiert l\'installation des services Google Play"</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Une application requiert la mise à jour des services Google Play"</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Erreur liée aux services Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Demandée par <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-hi/strings.xml b/platform/android/libs/google_play_services/res/values-hi/strings.xml
deleted file mode 100644
index b36feb00a7..0000000000
--- a/platform/android/libs/google_play_services/res/values-hi/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play सेवाएं पाएं"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"यह ऐप्स Google Play सेवाओं के बिना नहीं चलेगा, जो आपके फ़ोन में नहीं हैं."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"यह ऐप्स Google Play सेवाओं के बिना नहीं चलेगा, जो आपके टेबलेट में नहीं हैं."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play सेवाएं पाएं"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play सेवाएं सक्षम करें"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"जब तक आप Google Play सेवाएं सक्षम नहीं करते, तब तक यह ऐप्स कार्य नहीं करेगा."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play सेवाएं सक्षम करें"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play सेवाएं से नई जानकारी"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"जब तक आप Google Play सेवाओं से नई जानकारी नहीं लेते हैं, तब तक यह ऐप्स नहीं चलेगा."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"नेटवर्क त्रुटि"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play सेवाओं से कनेक्ट करने के लिए डेटा कनेक्शन की आवश्यकता है."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"अमान्य खाता"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"निर्दिष्ट खाता इस उपकरण पर मौजूद नहीं है. कृपया कोई भिन्न खाता चुनें."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play सेवाओं के साथ अज्ञात समस्या."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play सेवाएं"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play सेवाएं, जिन पर आपके कुछ ऐप्स निर्भर करते हैं, आपके उपकरण द्वारा समर्थित नहीं हैं. कृपया सहायता के लिए निर्माता से संपर्क करें."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"उपकरण का दिनांक गलत प्रतीत हो रहा है. कृपया उपकरण का दिनांक जांचें."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"नई जानकारी पाएं"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"प्रवेश करें"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google से प्रवेश करें"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"ऐप्स ने Google Play सेवाओं के खराब संस्करण के उपयोग का प्रयास किया."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"ऐप्स के लिए Google Play सेवाओं को सक्षम किए जाने की आवश्यकता है."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"ऐप्स के लिए Google Play सेवाओं के इंस्टॉलेशन की आवश्यकता है."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"ऐप्स के लिए Google Play सेवाओं में Google Play से नई जानकारी की आवश्यकता है."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play सेवाएं त्रुटि"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"<xliff:g id="APP_NAME">%1$s</xliff:g> द्वारा अनुरोधित"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-hr/strings.xml b/platform/android/libs/google_play_services/res/values-hr/strings.xml
deleted file mode 100644
index b7d462d882..0000000000
--- a/platform/android/libs/google_play_services/res/values-hr/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Preuzmi usluge za Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ova aplikacija neće funkcionirati bez usluga za Google Play, koje nisu instalirane na vašem telefonu."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ova aplikacija neće funkcionirati bez usluga za Google Play, koje nisu instalirane na vašem tabletnom računalu."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Preuzmi usluge za Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Omogući usluge za Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ova aplikacija neće raditi ako ne omogućite usluge za Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Omogući usluge za Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Ažuriraj usluge za Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ova se aplikacija neće pokrenuti ako ne ažurirate usluge za Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Mrežna pogreška"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Potrebna je podatkovna veza za povezivanje s uslugama Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Nevažeći račun"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Navedeni račun ne postoji na ovom uređaju. Odaberite neki drugi račun."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Nepoznata poteškoća s uslugama za Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Usluge za Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Usluge za Google Play, koje su potrebne za funkcioniranje nekih vaših aplikacija, nisu podržane na vašem uređaju. Pomoć potražite od proizvođača."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Čini se da datum na uređaju nije točan. Provjerite datum na uređaju."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Ažuriranje"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Prijava"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Prijava uslugom Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Aplikacija je pokušala upotrijebiti lošu verziju Usluga za Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Aplikacija zahtijeva omogućavanje Usluga za Google Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Aplikacija zahtijeva instaliranje Usluga za Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Aplikacija zahtijeva ažuriranje Usluga za Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Pogreška usluga za Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Zahtijeva aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-hu/strings.xml b/platform/android/libs/google_play_services/res/values-hu/strings.xml
deleted file mode 100644
index cd15ad328f..0000000000
--- a/platform/android/libs/google_play_services/res/values-hu/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Play Szolgáltatások telepítése"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Az alkalmazás működéséhez a Google Play Szolgáltatások szükségesek, ezek nincsenek telepítve a telefonon."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Az alkalmazás működéséhez a Google Play Szolgáltatások szükségesek, ezek nincsenek telepítve a táblagépen."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Play Szolgáltatások telepítése"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play Szolgáltatások aktiválása"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Az alkalmazás csak akkor fog működni, ha engedélyezi a Google Play Szolgáltatásokat."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Play Szolgáltatások aktiválása"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Play Szolgáltatások frissítése"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Az alkalmazás csak akkor fog működni, ha frissíti a Google Play Szolgáltatásokat."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Hálózati hiba"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"A Google Play Szolgáltatásokhoz történő kapcsolódáshoz adatkapcsolat szükséges."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Érvénytelen fiók"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"A megadott fiók nem létezik ezen az eszközön. Kérjük, válasszon másik fiókot."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Ismeretlen hiba a Google Play Szolgáltatásokban."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play Szolgáltatások"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"A Google Play Szolgáltatásokat, amelyre egyes alkalmazások támaszkodnak, nem támogatja az eszköz. Segítségért forduljon az eszköz gyártójához."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Az eszközön beállított dátum helytelen. Kérjük, ellenőrizze azt."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Frissítés"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Belépés"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google-bejelentkezés"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Egy alkalmazás a Play Szolgáltatások rossz verzióját akarta használni."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Egy alkalmazás kéri a Google Play Szolgáltatások engedélyezését."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Egy alkalmazás kéri a Google Play Szolgáltatások telepítését."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Egy alkalmazás kéri a Google Play Szolgáltatások frissítését."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play szolgáltatási hiba"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Igénylő: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-hy-rAM/strings.xml b/platform/android/libs/google_play_services/res/values-hy-rAM/strings.xml
deleted file mode 100644
index d89be9bf64..0000000000
--- a/platform/android/libs/google_play_services/res/values-hy-rAM/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Տեղադրեք Google Play ծառայությունները"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Այս հավելվածը չի գործարկվի առանց Google Play ծառայությունների, որոնք բացակայում են ձեր հեռախոսում:"</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Այս հավելվածը չի գործարկվի առանց Google Play ծառայությունների, որոնք բացակայում են ձեր գրասալիկում:"</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Տեղադրել Google Play ծառայությունները"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Միացնել Google Play ծառայությունները"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Այս ծրագիրը չի աշխատի, եթե դուք չմիացնեք Google Play ծառայությունները:"</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Միացնել Google Play ծառայությունները"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Նորացրեք Google Play ծառայությունները"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Այս ծրագիրը չի գործարկվի, եթե դուք չնորացնեք Google Play ծառայությունները:"</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Ցանցի սխալ կա"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Պահանջվում է տվյալների կապ` Google Play ծառայություններին միանալու համար:"</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Հաշիվն անվավեր է"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Նշված հաշիվը գոյություն չունի այս սարքում: Ընտրեք այլ հաշիվ:"</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Անհայտ խնդիր՝ Google Play ծառայություններում:"</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play ծառայություններ"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play ծառայությունները, որոնց ապավինում են ձեր ծրագրերից որոշները, չեն աջակցվում ձեր սարքի կողմից: Խնդրում ենք կապվել արտադրողի հետ օգնության համար:"</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Սարքի ամսաթիվը կարծես սխալ է: Ստուգեք սարքի ամսաթիվը:"</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Նորացնել"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Մուտք գործել"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Մուտք գործեք Google-ով"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Հավելվածը փորձել է կիրառել Google Play ծառայությունների վատ տարբերակը:"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Հավելվածը պահանջում է միացնել Google Play ծառայությունները:"</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Հավելվածը պահանջում է տեղադրել Google Play ծառայությունները:"</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Հավելվածը պահանջում է թարմացնել Google Play ծառայությունները:"</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play ծառայությունների սխալ"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ի հարցմամբ"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-in/strings.xml b/platform/android/libs/google_play_services/res/values-in/strings.xml
deleted file mode 100644
index 526b84a816..0000000000
--- a/platform/android/libs/google_play_services/res/values-in/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Dapatkan layanan Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Aplikasi ini tidak akan berjalan tanpa layanan Google Play, yang tidak ada di ponsel Anda."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Aplikasi ini tidak akan berjalan tanpa layanan Google Play, yang tidak ada di tablet Anda."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Dapatkan layanan Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Aktifkan layanan Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Aplikasi ini tidak akan bekerja sampai Anda mengaktifkan layanan Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Aktifkan layanan Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Perbarui layanan Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Aplikasi ini tidak akan berjalan sampai Anda memperbarui layanan Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Kesalahan Jaringan"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Sambungan data diperlukan untuk tersambung ke layanan Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Akun Tidak Valid"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Akun yang ditentukan tidak ada di perangkat ini. Pilih akun lain."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Masalah tidak diketahui pada layanan Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Layanan Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Layanan Google Play, yang diandalkan oleh beberapa aplikasi Anda, tidak didukung oleh perangkat Anda. Hubungi pabrikan untuk mendapatkan bantuan."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Tampaknya tanggal di perangkat salah. Periksa tanggal di perangkat."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Perbarui"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Masuk"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Masuk dengan Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Aplikasi mencoba menggunakan versi Layanan Google Play yang rusak."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Aplikasi membutuhkan Layanan Google Play untuk dapat diaktifkan."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Aplikasi membutuhkan pemasangan Layanan Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Aplikasi membutuhkan pembaruan untuk Layanan Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Kesalahan layanan Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Diminta oleh <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-it/strings.xml b/platform/android/libs/google_play_services/res/values-it/strings.xml
deleted file mode 100644
index f3c9f1fa5c..0000000000
--- a/platform/android/libs/google_play_services/res/values-it/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Installa Google Play Services"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"L\'app non funzionerà senza Google Play Services, non presente sul tuo telefono."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"L\'app non funzionerà senza Google Play Services, non presente sul tuo tablet."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Installa Google Play Services"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Attiva Google Play Services"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"L\'app non funzionerà se non attivi Google Play Services."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Attiva Google Play Services"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Aggiorna Google Play Services"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"L\'app non funzionerà se non aggiorni Google Play Services."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Errore di rete"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"È necessaria una connessione dati per connettersi a Google Play Services."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Account non valido"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"L\'account specificato non esiste su questo dispositivo. Scegli un altro account."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Problema sconosciuto con Google Play Services."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play Services"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"La piattaforma Google Play Services, su cui sono basate alcune delle tue applicazioni, non è supportata dal dispositivo in uso. Per assistenza, contatta il produttore."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"La data sul dispositivo sembra sbagliata. Controllala."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Aggiorna"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Accedi"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Accedi con Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Un\'app ha tentato di usare una versione non valida di Play Services."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Un\'applicazione richiede l\'attivazione di Google Play Services."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Un\'applicazione richiede l\'installazione di Google Play Services."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Un\'applicazione richiede un aggiornamento di Google Play Services."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Errore Google Play Services"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Richiesta da <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-iw/strings.xml b/platform/android/libs/google_play_services/res/values-iw/strings.xml
deleted file mode 100644
index 7474e53506..0000000000
--- a/platform/android/libs/google_play_services/res/values-iw/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"‏קבל את שירותי Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"‏אפליקציה זו לא תפעל ללא שירותי Google Play, החסרים בטלפון שלך."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"‏אפליקציה זו לא תפעל ללא שירותי Google Play, החסרים בטאבלט שלך."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"‏קבל את שירותי Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"‏הפעלת שירותי Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"‏אפליקציה זו לא תעבוד אם לא תפעיל את שירותי Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"‏הפעל את שירותי Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"‏עדכון שירותי Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"‏אפליקציה זו לא תפעל אם לא תעדכן את שירותי Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"שגיאת רשת."</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"‏דרוש חיבור נתונים כדי להתחבר לשירותי Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"חשבון לא חוקי"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"החשבון שצוין לא קיים במכשיר זה. בחר חשבון אחר."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"‏בעיה לא ידועה בשירותי Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"‏שירותי Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"‏שירותי Google Play, שחלק מהאפליקציות שלך מתבססות עליהם, אינם נתמכים על ידי המכשיר שברשותך. צור קשר עם היצרן לקבלת סיוע."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"נראה שהתאריך במכשיר שגוי. בדוק את התאריך במכשיר."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"עדכן"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"היכנס"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"‏היכנס באמצעות Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"‏יש אפליקציה שניסתה להשתמש בגרסה שגויה של שירותי Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"‏יש אפליקציה המחייבת הפעלה של שירותי Google Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"‏יש אפליקציה המחייבת התקנה של שירותי Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"‏יש אפליקציה המחייבת עדכון של שירותי Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"‏שגיאה בשירותי Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"התבקשה על ידי <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-ja/strings.xml b/platform/android/libs/google_play_services/res/values-ja/strings.xml
deleted file mode 100644
index 0d8b606230..0000000000
--- a/platform/android/libs/google_play_services/res/values-ja/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Play開発者サービスの入手"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"このアプリの実行にはGoogle Play開発者サービスが必要ですが、お使いの携帯端末にはインストールされていません。"</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"このアプリの実行にはGoogle Play開発者サービスが必要ですが、お使いのタブレットにはインストールされていません。"</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Play開発者サービスの入手"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Play開発者サービスの有効化"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"このアプリの実行には、Google Play開発者サービスの有効化が必要です。"</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Play開発者サービスの有効化"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Play開発者サービスの更新"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"このアプリの実行には、Google Play開発者サービスの更新が必要です。"</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"ネットワークエラー"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play開発者サービスに接続するには、データ接続が必要です。"</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"無効なアカウント"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"指定したアカウントはこの端末上に存在しません。別のアカウントを選択してください。"</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play開発者サービスで原因不明の問題が発生しました。"</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play開発者サービス"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"一部のアプリが使用しているGoogle Play開発者サービスは、お使いの端末ではサポートされていません。詳しくは、端末メーカーまでお問い合わせください。"</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"端末上の日付が正しくないようです。端末上の日付をご確認ください。"</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"更新"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"ログイン"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Googleでログイン"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"アプリはGoogle Play開発者サービスの不適切なバージョンを使用しようとしました。"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"アプリではGoogle Play開発者サービスを有効にする必要があります。"</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"アプリではGoogle Play開発者サービスをインストールする必要があります。"</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"アプリではGoogle Play開発者サービスをアップデートする必要があります。"</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play開発者サービスのエラー"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"<xliff:g id="APP_NAME">%1$s</xliff:g>によるリクエスト"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-ka-rGE/strings.xml b/platform/android/libs/google_play_services/res/values-ka-rGE/strings.xml
deleted file mode 100644
index 8a2c74aa98..0000000000
--- a/platform/android/libs/google_play_services/res/values-ka-rGE/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play სერვისების მიღება"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"ეს აპი ვერ გაეშვება Google Play სერვისების გარეშე, რაც თქვენს ტელეფონზე ვერ იძებნება."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"ეს აპი ვერ გაეშვება Google Play სერვისების გარეშე, რაც თქვენს ტელეფონზე ვერ იძებნება."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play სერვისების მიღება"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play სერვისების გააქტიურება"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"ეს აპი არ იმუშავებს, თუ არ გაააქტიურებთ Google Play სერვისებს."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play სერვისების გააქტიურება"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play სერვისების განახლება"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"ეს აპი ვერ გაეშვება, თუ Google Play სერვისებს არ განაახლებთ."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"ქსელის შეცდომა"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play Services-თან დასაკავშირებლად მონაცემთა გადაცემა აუცილებელია."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"ანგარიში არასწორია"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"მითითებული ანგარიში ამ მოწყობილობაზე არ არსებობს. გთხოვთ, აირჩიოთ სხვა ანგარიში."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play სერვისებთან დაკავშირებით უცნობი შეფერხება წარმოიშვა."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play სერვისები"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play სერვისები, რაც თქვენს ზოგიერთ აპს ჭირდება, თქვენს მოწყობილობაზე მხარდაჭერილი არ არის. გთხოვთ, დაუკავშირდეთ მწარმოებელს დახმარებისათვის."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"როგორც ჩანს, მოწყობილობის თარიღი არასწორია. გთხოვთ, შეამოწმოთ მოწყობილობის თარიღი."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"განახლება"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"შესვლა"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google-ით შესვლა"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"აპლიკაცია შეეცადა გამოეყენებინა Google Play სერვისების არასწორი ვერსია."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"აპლიკაცია საჭიროებს გააქტიურებულ Google Play Services."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"აპლიკაცია საჭიროებს Google Play Services-ის ინსტალაციას."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"აპლიკაცია საჭიროებს Google Play Services-ის განახლებას."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play სერვისების შეცდომა"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"მომთხოვნი: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-km-rKH/strings.xml b/platform/android/libs/google_play_services/res/values-km-rKH/strings.xml
deleted file mode 100644
index afebf30875..0000000000
--- a/platform/android/libs/google_play_services/res/values-km-rKH/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"ទទួល​សេវាកម្ម​កម្សាន្ត Google"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"កម្មវិធី​នេះ​នឹង​មិន​ដំណើរការ​​ទេ​បើ​គ្មាន​​សេវាកម្ម​កម្សាន្ត​ Google ដែល​ទូរស័ព្ទ​របស់​​អ្នក​មិន​មាន។"</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"​​កម្មវិធី​នេះ​នឹង​មិន​ដំណើរការ​​ទេ​បើ​គ្មាន​​សេវាកម្ម​កម្សាន្ត​ Google ដែល​​កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក​មិន​មាន។"</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"ទទួល​សេវាកម្ម​កម្សាន្ត Google"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"បើក​សេវាកម្ម​កម្សាន្ត Google"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"កម្ម​វិធី​នេះ​នឹង​មិន​ដំណើរការ​ទេ​ លុះត្រាតែ​អ្នក​បើក​សេវាកម្ម​​កម្សាន្ត​ Google ។"</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"បើក​សេវាកម្ម​កម្សាន្ត Google"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"ធ្វើ​បច្ចុប្បន្នភាព​សេវាកម្ម​កម្សាន្ត Google"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"កម្មវិធី​នេះ​នឹង​មិន​ដំណើរការ​ទេ​ លុះត្រាតែ​អ្នក​ធ្វើ​បច្ចុប្បន្នភាព​សេវាកម្ម​កម្សាន្ត Google ។"</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"កំហុស​​បណ្ដាញ"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"បាន​ទាមទារ​ការ​តភ្ជាប់​ទិន្នន័យ ដើម្បី​ភ្ជាប់​សេវាកម្ម​ឃ្លាំង​កម្មវិធី។"</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"គណនី​មិន​ត្រឹមត្រូវ"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"គណនី​ដែល​បាន​បញ្ជាក់​មិន​មាន​នៅ​លើ​ឧបករណ៍​នេះ​ទេ។ សូម​ជ្រើស​គណនី​ផ្សេង​។"</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"មិន​ស្គាល់​បញ្ហា​ជាមួយ​សេវាកម្ម​កម្សាន្ត Google ។"</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"សេវាកម្ម​កម្សាន្ត​ Google"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"សេវាកម្ម​កម្សាន្ត Google អាស្រ័យ​លើ​កម្មវិធី​របស់​អ្នក មិន​ត្រូវ​បាន​គាំទ្រ​ដោយ​ឧបករណ៍​របស់​អ្នក។ សូម​ទាក់ទង​ក្រុមហ៊ុន​ផលិត​សម្រាប់​ជំនួយ។"</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"កាលបរិច្ឆេទ​លើ​ឧបករណ៍​បង្ហាញ​ថា​មិន​ត្រឹមត្រូវ។ សូម​ពិនិត្យ​កាលបរិច្ឆេទ​លើ​ឧបករណ៍។"</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"ធ្វើ​បច្ចុប្បន្នភាព"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"ចូល"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"ចូល​ដោយ​ប្រើ​ Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"កម្មវិធី​​​ព្យាយាម​ប្រើ​កំណែ​មិនល្អ​របស់​សេវា​កម្ម​ឃ្លាំ​កម្មវិធី។"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"កម្មវិធី​ទាមទារ​​បើក​សេវាកម្ម​ឃ្លាំង​កម្មវិធី។"</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"កម្មវិធី​ទាមទារ​ការ​ដំឡើង​សេវាកម្ម​ឃ្លាំង​កម្មវិធី។"</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"កម្មវិធី​ទាមទារ​​ធ្វើ​បច្ចុប្បន្នភាព​សេវាកម្ម​ឃ្លាំង​កម្មវិធី។"</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"កំហុស​សេវា​កម្ម​កម្សាន្ត Google"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"បាន​ស្នើ​ដោយ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-ko/strings.xml b/platform/android/libs/google_play_services/res/values-ko/strings.xml
deleted file mode 100644
index e37f1fd02a..0000000000
--- a/platform/android/libs/google_play_services/res/values-ko/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play 서비스 설치"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"휴대전화에 Google Play 서비스가 설치되어 있어야 이 앱이 실행됩니다."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"태블릿에 Google Play 서비스가 설치되어 있어야 이 앱이 실행됩니다."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play 서비스 설치"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play 서비스 사용"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Google Play 서비스를 사용하도록 설정해야 이 앱이 작동합니다."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play 서비스 사용"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play 서비스 업데이트"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Google Play 서비스를 업데이트해야만 이 앱이 실행됩니다."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"네트워크 오류"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play 서비스에 연결하려면 데이터 연결이 필요합니다."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"올바르지 않은 계정"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"지정한 계정이 이 기기에 존재하지 않습니다. 다른 계정을 선택하세요."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play 서비스에 알 수 없는 문제가 발생했습니다."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play 서비스"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"일부 사용자 애플리케이션에 필요한 Google Play 서비스가 사용자 기기에서 지원되지 않습니다. 기기 제조업체에 문의하시기 바랍니다."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"기기의 날짜가 잘못된 것 같습니다. 기기의 날짜를 확인해 주세요."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"업데이트"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"로그인"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google 계정으로 로그인"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"애플리케이션에서 잘못된 버전의 Google Play 서비스를 사용하려고 했습니다."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Google Play 서비스를 사용하도록 설정해야 하는 애플리케이션입니다."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Google Play 서비스를 설치해야 하는 애플리케이션입니다."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Google Play 서비스를 업데이트해야 하는 애플리케이션입니다."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play 서비스 오류"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 요청"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-lo-rLA/strings.xml b/platform/android/libs/google_play_services/res/values-lo-rLA/strings.xml
deleted file mode 100644
index 32bcb0b92b..0000000000
--- a/platform/android/libs/google_play_services/res/values-lo-rLA/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"ຕິດຕັ້ງບໍລິການ Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"ແອັບຯນີ້ຈະບໍ່ສາມາດເຮັດວຽກໄດ້ໂດຍທີ່ບໍ່ມີບໍລິການ Google Play ເຊິ່ງຂາດຫາຍໄປໃນໂທລະສັບຂອງທ່ານ."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"ແອັບຯນີ້ຈະບໍ່ສາມາດເຮັດວຽກໄດ້ໂດຍທີ່ບໍ່ມີບໍລິການ Google Play ເຊິ່ງຂາດຫາຍໄປໃນແທັບເລັດຂອງທ່ານ."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"ຕິດຕັ້ງບໍລິການ Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"ເປີດໃຊ້ບໍລິການ Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"ແອັບຯນີ້ຈະບໍ່ສາມາດເຮັດວຽກໄດ້ຈົນກວ່າທ່ານຈະເປີດໃຊ້ບໍລິການ Google Play"</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"ເປີດໃຊ້ບໍລິການ Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"ອັບເດດບໍລິການ Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"ແອັບຯນີ້ຈະບໍ່ສາມາດເຮັດວຽກໄດ້ຈົນກວ່າທ່ານຈະອັບເດດບໍລິການ Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"ເຄືອຂ່າຍຜິດພາດ"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"ຕ້ອງໃຊ້ການເຊື່ອມຕໍ່ອິນເຕີເນັດເພື່ອໃຊ້ Google Play Services."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"ບັນຊີບໍ່ຖືກຕ້ອງ"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"ບັນຊີທີ່ເລືອກບໍ່ມີໃນອຸປະກອນນີ້. ກະລຸນາເລືອກບັນຊີອື່ນ."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"ມີປັນຫາທີ່ບໍ່ຄາດຄິດໃນບໍລິການ Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"ບໍລິການ Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"ບໍລິການ Google Play ທີ່ບາງແອັບພລິເຄຊັນຂອງທ່ານຕ້ອງອາໄສນັ້ນ ບໍ່ຖືກຮອງຮັບໃນອຸປະກອນຂອງທ່ານ. ກະລຸນາຕິດຕໍ່ຜູ້ຜະລິດສຳລັບການແນະນຳ."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"ວັນທີຂອງອຸປະກອນບໍ່ຖືກຕ້ອງ. ກະລຸນາກວດສອບວັນທີຂອງອຸປະກອນຂອງທ່ານ."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"ອັບເດດ"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"ເຂົ້າສູ່ລະບົບ"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"ເຂົ້າສູ່ລະບົບດ້ວຍ Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"ແອັບພລິເຄຊັນໄດ້ພະຍາຍາມໃຊ້ Google Play Services ເວີຊັນທີ່ບໍ່ສາມາດໃຊ້ໄດ້."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"ແອັບພລິເຄຊັນຕ້ອງການເປີດນຳໃຊ້ Google Play Services."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"ແອັບພລິເຄຊັນຕ້ອງການໃຫ້ຕິດຕັ້ງ Google Play Services."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"ແອັບພລິເຄຊັນຕ້ອງການອັບເດດ Google Play Services."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"ບໍລິການ Google Play ຜິດພາດ"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"ຮ້ອງຂໍໂດຍ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-lt/strings.xml b/platform/android/libs/google_play_services/res/values-lt/strings.xml
deleted file mode 100644
index 73de5fa9aa..0000000000
--- a/platform/android/libs/google_play_services/res/values-lt/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Gauti „Google Play“ paslaugų"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ši programa neveiks be „Google Play“ paslaugų, kurios neįdiegtos telefone."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ši programa neveiks be „Google Play“ paslaugų, kurios neįdiegtos planšetiniame kompiuteryje."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Gauti „Google Play“ paslaugų"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Įgalinti „Google Play“ paslaugas"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ši programa neveiks, jei neįgalinsite „Google Play“ paslaugų."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Įgal. „Google Play“ paslaugas"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Atnaujinti „Google Play“ paslaugas"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ši programa neveiks, jei neatnaujinsite „Google Play“ paslaugų."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Tinklo klaida"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Norint prisijungti prie „Google Play“ paslaugų reikia duomenų ryšio."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Netinkama paskyra"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Nurodytos paskyros šiame įrenginyje nėra. Pasirinkite kitą paskyrą."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Nežinoma „Google Play“ paslaugų problema."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"„Google Play“ paslaugos"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Jūsų įrenginys nepalaiko „Google Play“ paslaugų, kuriomis remiasi kai kurios programos. Jei reikia pagalbos, susisiekite su gamintoju."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Įrenginyje nurodyta data neteisinga. Patikrinkite įrenginyje nurodytą datą."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Atnaujinti"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Prisij."</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Prisij. naud. „Google“"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Programa bandė naudotis netinkama „Google Play“ paslaugų versija."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Norint naudoti programą būtina įgalinti „Google Play“ paslaugas."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Norint naudoti programą būtina įdiegti „Google Play“ paslaugas."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Norint naudoti programą būtina atnaujinti „Google Play“ paslaugas."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"„Google Play“ paslaugų klaida"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Užklausą pateikė „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-lv/strings.xml b/platform/android/libs/google_play_services/res/values-lv/strings.xml
deleted file mode 100644
index 9e4b6ee6bd..0000000000
--- a/platform/android/libs/google_play_services/res/values-lv/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play pakalpojumu iegūšana"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Lai šī lietotne darbotos, tālrunī ir jāinstalē Google Play pakalpojumi."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Lai šī lietotne darbotos, planšetdatorā ir jāinstalē Google Play pakalpojumi."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Iegūt Google Play pakalpojumus"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play pakalpojumu iespējošana"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Lai šī lietotne darbotos, iespējojiet Google Play pakalpojumus."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Iespējot Google Play pakalpojumus"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play pakalpojumu atjaunināšana"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Lai šī lietotne darbotos, atjauniniet Google Play pakalpojumus."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Tīkla kļūda"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Lai izveidotu savienojumu ar Google Play pakalpojumiem, ir nepieciešams datu savienojums."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Nederīgs konts"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Norādītais konts šajā ierīcē nepastāv. Lūdzu, izvēlieties citu kontu."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Nezināma problēma ar Google Play pakalpojumiem."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play pakalpojumi"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Jūsu ierīce neatbalsta Google Play pakalpojumus, kuri nepieciešami dažu jūsu lietojumprogrammu darbībai. Lūdzu, sazinieties ar ražotāju, lai saņemtu palīdzību."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Šķiet, ka ierīcē ir iestatīts nepareizs datums. Lūdzu, pārbaudiet ierīces datumu."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Atjaunināt"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Pierakst."</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Pierakstīties Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Lietojumpr. mēģināja izmantot nederīgu Google Play pakalp. versiju."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Lai lietojumprogramma darbotos, ir jāiespējo Google Play pakalpojumi."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Lai lietojumprogramma darbotos, ir jāinstalē Google Play pakalpojumi."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Lai lietojumprogramma darbotos, jāatjaunina Google Play pakalpojumi."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play pakalpojumu kļūda"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Pieprasījums no lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-mn-rMN/strings.xml b/platform/android/libs/google_play_services/res/values-mn-rMN/strings.xml
deleted file mode 100644
index 1743256a11..0000000000
--- a/platform/android/libs/google_play_services/res/values-mn-rMN/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play үйлчилгээ авах"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Таны утсанд байхгүй байгаа Google Play үйлчилгээг идэвхжүүлж байж энэ апп-г ажиллуулах боломжтой."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Таны таблетэд байхгүй Google Play үйлчилгээг идэвхжүүлж байж энэ апп-г ажиллуулах боломжтой."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play үйлчилгээ авах"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play үйлчилгээг идэвхжүүлэх"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Та Google Play үйлчилгээг идэвхжүүлж байж энэ апп-г ажиллуулах боломжтой."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play үйлчилгээг идэвхжүүлэх"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play үйлчилгээг шинэчлэх"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Та Google Play үйлчилгээг шинэчлэхгүй бол энэ апп ажиллах боломжгүй."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Сүлжээний алдаа"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play үйлчилгээнд холбогдохын тулд дата холболт шаардлагатай."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Буруу акаунт"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Заасан акаунт энэ төхөөрөмж дээр байхгүй байна. Өөр акаунт сонгоно уу."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play үйлчилгээтэй холбоотой тодорхойгүй алдаа."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play үйлчилгээ"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Таны зарим аппликешнүүдийн хамаардаг Google Play үйлчилгээ таны төхөөрөмжид дэмжигдэхгүй байна. Тусламж авахын тулд үйлдвэрлэгчтэй холбоо барина уу."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Төхөөрөмжийн огноо буруу байгаа бололтой. Төхөөрөмжийн огноог шалгана уу."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Шинэчлэх"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Нэвтрэх"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google-р нэвтрэх:"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Аппликешн Google Play Үйлчилгээний муу хувилбарыг ашиглахыг оролдлоо."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Аппликешн Google Play Үйлчилгээг идэвхжүүлсэн байхыг шаардана."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Аппликешн Google Play Үйлчилгээг суулгахыг шаардана."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Аппликешн Google Play Үйлчилгээг шинэчлэхийг шаардана."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play үйлчилгээний алдаа"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Хүсэлт гаргасан <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-ms-rMY/strings.xml b/platform/android/libs/google_play_services/res/values-ms-rMY/strings.xml
deleted file mode 100644
index 8e8a4b9b8a..0000000000
--- a/platform/android/libs/google_play_services/res/values-ms-rMY/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Dapatkan perkhidmatan Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Apl ini tidak akan berfungsi tanpa perkhidmatan Google Play dan apl ini tiada pada telefon anda."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Apl ini tidak akan berfungsi tanpa perkhidmatan Google Play dan apl ini tiada pada tablet anda."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Dapatkan perkhidmatan Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Dayakan perkhidmatan Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Apl ini tidak akan berfungsi kecuali anda mendayakan perkhidmatan Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Dayakan perkhidmatan Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Kemas kini perkhidmatan Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Apl ini tidak akan berfungsi kecuali anda mengemas kini perkhidmatan Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Ralat Rangkaian"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Sambungan data diperlukan untuk menyambung ke perkhidmatan Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Akaun Tidak Sah"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Akaun yang dinyatakan tidak wujud pada peranti ini. Sila pilih akaun yang lain."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Isu tidak diketahui dengan perkhidmatan Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Perkhidmatan Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Peranti anda tidak menyokong perkhidmatan Google Play, sedangkan sesetengah aplikasi anda memerlukannya. Sila hubungi pengilang untuk bantuan."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Tarikh pada peranti kelihatan tidak betul. Sila semak tarikh pada peranti."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Kemas kini"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Log masuk"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Log masuk dengan Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Aplikasi cuba menggunakan versi Perkhidmatan Google Play yang rosak."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Perkhidmatan Google Play perlu didayakan untuk menggunakan aplikasi."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Perkhidmatan Google Play perlu dipasang untuk mengguankan aplikasi."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Perkhidmatan Google Play perlu dikemas kini untuk menggunakan aplikasi."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Ralat perkhidmatan Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Diminta oleh <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-nb/strings.xml b/platform/android/libs/google_play_services/res/values-nb/strings.xml
deleted file mode 100644
index 1e16bbb6d2..0000000000
--- a/platform/android/libs/google_play_services/res/values-nb/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Installer Google Play Tjenester"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Denne appen kan ikke kjøres uten Google Play Tjenester, som ikke er installert på telefonen din."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Denne appen kan ikke kjøres uten Google Play Tjenester, som ikke er installert på nettbrettet ditt."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Installer Google Play Tjenester"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Aktiver Google Play Tjenester"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Denne appen fungerer ikke med mindre du aktiverer Google Play Tjenester."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Aktiver Google Play Tjenester"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Oppdater Google Play Tjenester"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Denne appen kan ikke kjøres før du oppdaterer Google Play Tjenester."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Nettverksfeil"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Du må ha datatilkobling for å koble deg til Google Play-tjenester."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ugyldig konto"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Den angitte kontoen finnes ikke på enheten. Velg en annen konto."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Det oppsto et ukjent problem med Google Play Tjenester."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play-tjenester"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play Tjenester, som noen av appene er avhengige av, støttes ikke av enheten. Ta kontakt med produsenten for å få hjelp."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Datoen på enheten ser ut til å være feil. Sjekk datoen på enheten."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Oppdater"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Logg på"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Logg inn med Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"En app prøvde å bruke en skadet versjon av Google Play Tjenester."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"En app krever Google Play Tjenester for å aktiveres."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"En app krever at Google Play Tjenester installeres."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"En app krever at Google Play Tjenester oppdateres."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play Tjenester-feil"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Forespurt av <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-nl/strings.xml b/platform/android/libs/google_play_services/res/values-nl/strings.xml
deleted file mode 100644
index f38db5fcdb..0000000000
--- a/platform/android/libs/google_play_services/res/values-nl/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play-services ophalen"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Deze app kan niet worden uitgevoerd zonder Google Play-services die ontbreken op uw telefoon."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Deze app kan niet worden uitgevoerd zonder Google Play-services die ontbreken op uw tablet."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play-services ophalen"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play-services inschakelen"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Deze app werkt niet, tenzij u Google Play-services inschakelt."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play-services inschak."</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play-services bijwerken"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Deze app kan niet worden uitgevoerd, tenzij u Google Play-services bijwerkt."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Netwerkfout"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Er is een gegevensverbinding nodig om verbinding te kunnen maken met Google Play-services."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ongeldig account"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Het gespecificeerde account bestaat niet op dit apparaat. Kies een ander account."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Onbekend probleem met Google Play-services."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play-services"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play-services, dat vereist is voor een aantal van uw applicaties, wordt niet ondersteund door uw apparaat. Neem contact op met de fabrikant voor ondersteuning."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"De datum op het apparaat lijkt onjuist. Controleer de datum op het apparaat."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Bijwerken"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Inloggen"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Inloggen met Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Onjuiste versie van Google Play-services wordt gebruikt."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Google Play-services moet zijn ingeschakeld voor een applicatie."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Google Play-services moet zijn geïnstalleerd voor een applicatie."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Google Play-services moet worden geüpdatet voor een applicatie."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Fout met Google Play-services"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Aangevraagd door <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-pl/strings.xml b/platform/android/libs/google_play_services/res/values-pl/strings.xml
deleted file mode 100644
index 5eba15ff3a..0000000000
--- a/platform/android/libs/google_play_services/res/values-pl/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Pobierz Usługi Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ta aplikacja nie będzie działać bez Usług Google Play, których nie masz na telefonie."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ta aplikacja nie będzie działać bez Usług Google Play, których nie masz na tablecie."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Pobierz Usługi Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Włącz Usługi Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ta aplikacja nie będzie działać, jeśli nie włączysz Usług Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Włącz Usługi Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Aktualizuj Usługi Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ta aplikacja nie będzie działać, jeśli nie zaktualizujesz Usług Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Błąd sieci"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Korzystanie z usług Google Play wymaga połączenia z internetem."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Nieprawidłowe konto"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Podanego konta nie ma na tym urządzeniu. Wybierz inne konto."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Nieznany problem z Usługami Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Usługi Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Usługi Google Play, od których zależy działanie niektórych aplikacji, nie są obsługiwane na Twoim urządzeniu. Skontaktuj się z producentem, by uzyskać pomoc."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Data ustawiona na urządzeniu wydaje się nieprawidłowa. Sprawdź datę ustawioną na urządzeniu."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Aktualizuj"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Zaloguj się"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Zaloguj się przez Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Aplikacja próbowała skorzystać z nieprawidłowej wersji Usług Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Aplikacja wymaga włączenia Usług Google Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Aplikacja wymaga zainstalowania Usług Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Aplikacja wymaga aktualizacji Usług Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Błąd usług Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Żądanie z aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-pt-rBR/strings.xml b/platform/android/libs/google_play_services/res/values-pt-rBR/strings.xml
deleted file mode 100644
index 6db462d709..0000000000
--- a/platform/android/libs/google_play_services/res/values-pt-rBR/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Instale o Google Play Services"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Este aplicativo não funciona sem o Google Play Services, que não está instalado em seu telefone."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Este aplicativo não funciona sem o Google Play Services, que não está instalado em seu tablet."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Instalar o Google Play Services"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Ative o Google Play Services"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Este aplicativo só funciona com o Google Play Services ativado."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Ativar o Google Play Services"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Atualize o Google Play Services"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Este aplicativo só funciona com uma versão atualizada do Google Play Services."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Erro na rede"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"É necessária uma conexão de dados para conectar ao Google Play Services."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Conta inválida"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"A conta especificada não existe no dispositivo. Escolha outra conta."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Problema desconhecido com o Google Play Services."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Play Services"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"O Google Play Services, necessário para alguns dos aplicativos, não é compatível com seu dispositivo. Entre em contato com o fabricante para obter assistência."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"A data no dispositivo parece incorreta. Verifique a data no dispositivo."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Atualizar"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Login"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Fazer login com o Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Um aplicativo tentou usar uma versão errada do Google Play Services."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Um aplicativo requer a ativação do Google Play Services."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Um aplicativo requer a instalação do Google Play Services."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Um aplicativo requer a atualização do Google Play Services."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Ocorreu um erro no Google Play Services"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Solicitado por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-pt-rPT/strings.xml b/platform/android/libs/google_play_services/res/values-pt-rPT/strings.xml
deleted file mode 100644
index 0ceafcb95f..0000000000
--- a/platform/android/libs/google_play_services/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Obter serviços do Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Esta aplicação não será executada sem os serviços do Google Play, que estão em falta no seu telemóvel."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Esta aplicação não será executada sem os serviços do Google Play, que estão em falta no seu tablet."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Obter serviços do Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Ativar serviços do Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Esta aplicação não funcionará enquanto não ativar os serviços do Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Ativar serviços do Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Atualizar serviços do Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Esta aplicação não será executada enquanto não atualizar os serviços do Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Erro de Rede"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"É necessária uma ligação de dados para se ligar aos Serviços do Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Conta Inválida"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"A conta especificada não existe neste dispositivo. Escolha uma conta diferente."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Problema desconhecido nos serviços do Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Serviços do Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Os serviços do Google Play, dos quais dependem algumas das suas aplicações, não são suportados pelo seu dispositivo. Contacte o fabricante para obter assistência."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"A data no dispositivo parece estar incorreta. Verifique a data no dispositivo."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Atualizar"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Inic. ses."</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Inic. sessão com o Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Aplicação tentou utiliz. versão incorreta dos Serviços do Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Uma aplicação necessita da ativação dos Serviços do Google Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Uma aplicação necessita da instalação dos Serviços do Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Uma aplicação necessita da atualização dos Serviços do Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Erro dos serviços do Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Solicitado por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-pt/strings.xml b/platform/android/libs/google_play_services/res/values-pt/strings.xml
deleted file mode 100644
index 6db462d709..0000000000
--- a/platform/android/libs/google_play_services/res/values-pt/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Instale o Google Play Services"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Este aplicativo não funciona sem o Google Play Services, que não está instalado em seu telefone."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Este aplicativo não funciona sem o Google Play Services, que não está instalado em seu tablet."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Instalar o Google Play Services"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Ative o Google Play Services"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Este aplicativo só funciona com o Google Play Services ativado."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Ativar o Google Play Services"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Atualize o Google Play Services"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Este aplicativo só funciona com uma versão atualizada do Google Play Services."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Erro na rede"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"É necessária uma conexão de dados para conectar ao Google Play Services."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Conta inválida"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"A conta especificada não existe no dispositivo. Escolha outra conta."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Problema desconhecido com o Google Play Services."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Play Services"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"O Google Play Services, necessário para alguns dos aplicativos, não é compatível com seu dispositivo. Entre em contato com o fabricante para obter assistência."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"A data no dispositivo parece incorreta. Verifique a data no dispositivo."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Atualizar"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Login"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Fazer login com o Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Um aplicativo tentou usar uma versão errada do Google Play Services."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Um aplicativo requer a ativação do Google Play Services."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Um aplicativo requer a instalação do Google Play Services."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Um aplicativo requer a atualização do Google Play Services."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Ocorreu um erro no Google Play Services"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Solicitado por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-ro/strings.xml b/platform/android/libs/google_play_services/res/values-ro/strings.xml
deleted file mode 100644
index eb428964ec..0000000000
--- a/platform/android/libs/google_play_services/res/values-ro/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Descărcaţi Servicii Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Această aplicaţie nu poate rula fără Servicii Google Play, care lipsesc de pe telefon."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Această aplicaţie nu poate rula fără Servicii Google Play, care lipsesc de pe tabletă."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Obţineţi Servicii Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Activaţi Servicii Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Această aplicaţie nu va funcţiona decât dacă activaţi Servicii Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Activaţi Servicii Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Actualizaţi Servicii Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Această aplicaţie nu poate rula decât dacă actualizaţi Servicii Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Eroare de reţea"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Este necesară o conexiune de date pentru a vă conecta la serviciile Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Cont nevalid"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Contul menționat nu există pe acest dispozitiv. Alegeți alt cont."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Problemă necunoscută privind Servicii Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Servicii Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Gadgetul nu acceptă serviciile Google Play, pe care se bazează unele dintre aplicații. Pentru asistență, contactați producătorul gadgetului."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Data de pe dispozitiv pare să fie incorectă. Verificați data de pe dispozitiv."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Actualizaţi"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Conectați"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Conectați-vă cu Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Aplicația a încercat să utilizeze o vers. Servicii Google Play greșită"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"O aplicație necesită activarea Serviciilor Google Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"O aplicație necesită instalarea Serviciilor Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"O aplicație necesită o actualizare pentru Servicii Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Eroare Servicii Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Solicitată de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-ru/strings.xml b/platform/android/libs/google_play_services/res/values-ru/strings.xml
deleted file mode 100644
index c784aae95c..0000000000
--- a/platform/android/libs/google_play_services/res/values-ru/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Установите Сервисы Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Для работы этого приложения требуется установить Сервисы Google Play."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Для работы этого приложения требуется установить Сервисы Google Play."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Установить"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Включите Сервисы Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Для работы этого приложения требуется включить Сервисы Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Включить"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Обновите Сервисы Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Для работы этого приложения требуется обновить Сервисы Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Ошибка сети"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Для работы с Google Play требуется подключение к сети."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Недействительный аккаунт"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Этого аккаунта нет на устройстве. Выберите другой."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Неизвестная ошибка с Сервисами Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Сервисы Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Сервисы Google Play, необходимые для работы некоторых приложений, не поддерживаются на вашем устройстве. Обратитесь к производителю."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Проверьте правильность даты, указанной на устройстве."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Обновить"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Войти"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Войти в аккаунт Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Версия сервисов Google Play неисправна"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Для работы приложения требуется включить сервисы Google Play"</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Для работы приложения требуется установить сервисы Google Play"</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Для работы приложения требуется обновить сервисы Google Play"</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Ошибка сервисов Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Запрос от приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-sk/strings.xml b/platform/android/libs/google_play_services/res/values-sk/strings.xml
deleted file mode 100644
index 125d87f6da..0000000000
--- a/platform/android/libs/google_play_services/res/values-sk/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Inštalovať služby Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Na spustenie tejto aplikácie sa vyžadujú služby Google Play, ktoré v telefóne nemáte."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Na spustenie tejto aplikácie sa vyžadujú služby Google Play, ktoré v tablete nemáte."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Inštalovať služby Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Povoliť služby Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Táto aplikácia bude fungovať až po povolení služieb Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Povoliť služby Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Aktualizovať služby Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Túto aplikáciu bude možné spustiť až po aktualizácii služieb Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Chyba siete"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Pripojenie k službám Google Play si vyžaduje dátové pripojenie."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Neplatný účet"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Zadaný účet v tomto zariadení neexistuje. Vyberte iný účet."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Neznámy problém so službami Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Služby Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Niektoré vaše aplikácie vyžadujú služby Google Play, ktoré vo vašom zariadení nie sú podporované. Ak potrebujete pomoc, kontaktujte výrobcu."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Dátum nastavený v zariadení sa zdá byť nesprávny. Skontrolujte ho."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Aktualizovať"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Prihlásiť sa"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Prihlásiť sa do účtu Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Aplikácia sa pokúsila použiť nesprávnu verziu služieb Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Aplikácia vyžaduje povolenie služieb Google Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Aplikácia vyžaduje inštaláciu služieb Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Aplikácia vyžaduje aktualizáciu služieb Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Chyba služieb Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Vyžiadané aplikáciou <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-sl/strings.xml b/platform/android/libs/google_play_services/res/values-sl/strings.xml
deleted file mode 100644
index df5821f94c..0000000000
--- a/platform/android/libs/google_play_services/res/values-sl/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Namestite storitve Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ta aplikacija ne deluje brez storitev Google Play, ki jih ni v telefonu."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ta aplikacija ne deluje brez storitev Google Play, ki jih ni v tabličnem računalniku."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Namestite storitve Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Omogočite storitve Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Aplikacija ne bo delovala, če ne omogočite storitev Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Omogočite storitve Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Posodobite storitve Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ta aplikacija ne deluje, če ne posodobite storitev Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Omrežna napaka"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Za povezavo s storitvami Google Play potrebujete internetno povezavo."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Neveljaven račun"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"V tej napravi ne obstaja navedeni račun. Izberite drugega."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Neznana težava s storitvami Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Storitve Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Vaša naprava na podpira storitev Google Play, ki jih potrebujejo nekatere od vaših aplikacij. Za pomoč se obrnite na izdelovalca."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Videti je, da je datum v napravi napačen. Preverite ga."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Posodobi"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Prijava"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Prijavite se v Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Aplikacija je poskusila uporabiti napačno različico Storitev Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Za delovanje aplikacije morate omogočiti Storitve Google Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Za delovanje aplikacije morate namestiti Storitve Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Za delovanje aplikacije morate posodobiti Storitve Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Napaka storitev Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Zahtevala aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-sr/strings.xml b/platform/android/libs/google_play_services/res/values-sr/strings.xml
deleted file mode 100644
index ad0b549547..0000000000
--- a/platform/android/libs/google_play_services/res/values-sr/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Преузимање Google Play услуга"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ова апликација не може да се покрене без Google Play услуга, које недостају на телефону."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ова апликација не може да се покрене без Google Play услуга, које недостају на таблету."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Преузми Google Play услуге"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Омогућавање Google Play услуга"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ова апликација неће функционисати ако не омогућите Google Play услуге."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Омогући Google Play услуге"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Ажурирање Google Play услуга"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ова апликација не може да се покрене ако не ажурирате Google Play услуге."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Грешка на мрежи"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"За повезивање са Google Play услугама потребна је веза за пренос података."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Неважећи налог"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Наведени налог не постоји на овом уређају. Одаберите други налог."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Непознат проблем са Google Play услугама."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play услуге"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play услуге, које су потребне за функционисање неких од апликација, нису подржане на уређају. Контактирајте произвођача да бисте добили помоћ."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Изгледа да су подаци на уређају нетачни. Проверите датум на уређају."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Ажурирај"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Пријави ме"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Пријави ме преко Google-а"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Апликација је покушала да користи лошу верзију Google Play услуга."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Апликација захтева да Google Play услуге буду омогућене."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Апликација захтева инсталирање Google Play услуга."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Апликација захтева ажурирање Google Play услуга."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Грешка Google Play услуга"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Захтева <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-sv/strings.xml b/platform/android/libs/google_play_services/res/values-sv/strings.xml
deleted file mode 100644
index 6a10395f4b..0000000000
--- a/platform/android/libs/google_play_services/res/values-sv/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Hämta Google Play Tjänster"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Den här appen kan inte köras utan Google Play Tjänster, som saknas på mobilen."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Den här appen kan inte köras utan Google Play Tjänster, som saknas på surfplattan."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Hämta Google Play Tjänster"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Aktivera Google Play Tjänster"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Du måste aktivera Google Play Tjänster för att den här appen ska fungera."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Aktivera Google Play Tjänster"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Uppdatera Google Play Tjänster"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Du måste uppdatera Google Play Tjänster innan du kan köra den här appen."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Nätverksfel"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"En dataanslutning krävs för att ansluta till Google Plays tjänster."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ogiltigt konto"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Det angivna kontot finns inte på den här enheten. Välj ett annat konto."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Okänt problem med Google Play Tjänster"</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play-tjänster"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Några av dina appar använder Google Play-tjänster som inte stöds av din enhet. Kontakta tillverkaren om du vill ha hjälp."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Datumet på enheten verkar inte vara rätt. Kontrollera datumet på enheten."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Uppdatera"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Logga in"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Logga in med Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"En olämplig version av Google Play Tjänster anropades av en app."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Google Play Tjänster måste aktiveras för en att app ska fungera."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Google Play Tjänster måste installeras för att en app ska fungera."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Google Play Tjänster måste uppdateras för en app ska fungera."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Fel på Google Play Tjänster"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Begärdes av <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-sw/strings.xml b/platform/android/libs/google_play_services/res/values-sw/strings.xml
deleted file mode 100644
index 7f29bf5f2e..0000000000
--- a/platform/android/libs/google_play_services/res/values-sw/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Pata huduma za Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Programu hii haiwezi kuendeshwa bila huduma za Google Play, ambazo hazipo kwenye simu yako."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Programu hii haiwezi kufanya kazi bila huduma za Google Play, ambazo hazipatikani kwenye kompyuta kibao yako."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Pata huduma za Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Wezesha huduma za Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Programu hii haitafanya kazi mpaka utakapowezesha huduma za Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Wezesha huduma za Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Sasisha huduma za Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Programu hii haiwezi kuendeshwa mpaka utakaposasisha huduma za Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Hitilafu ya Mtandao"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Muunganisho wa data unahitajika ili kuunganisha kwenye huduma za Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Akaunti Batili"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Akaunti iliyobainishwa haipo kwenye kifaa hiki. Tafadhali chagua akaunti tofauti."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Suala lisilojulikana na huduma za Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Huduma za Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Huduma za Google Play, ambazo baadhi ya programu zako zinategemea, si linganifu na kifaa chako. Tafadhali wasiliana na mtengenezaji kwa usaidizi."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Inaeonekana tarehe ya kifaa sio sahihi. Tafadhali angalia tarehe ya kifaa."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Sasisha"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Ingia"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Ingia ukitumia Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Programu ilijaribu kutumia toleo baya la Huduma za Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Programu inahitaji Huduma za Google Play ili kuwashwa."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Programu inahitaji usakinishaji wa Huduma za Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Programu inahitaji sasisho la Huduma za Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Hitilafu kwenye Huduma za Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Imeombwa na <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-th/strings.xml b/platform/android/libs/google_play_services/res/values-th/strings.xml
deleted file mode 100644
index 6f098fe801..0000000000
--- a/platform/android/libs/google_play_services/res/values-th/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"รับบริการ Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"แอปพลิเคชันนี้จะไม่ทำงานหากไม่มีบริการ Google Play ซึ่งไม่มีในโทรศัพท์ของคุณ"</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"แอปพลิเคชันนี้จะไม่ทำงานหากไม่มีบริการ Google Play ซึ่งไม่มีในแท็บเล็ตของคุณ"</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"รับบริการ Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"เปิดใช้งานบริการ Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"แอปพลิเคชันนี้จะไม่ทำงานจนกว่าคุณจะเปิดใช้งานบริการ Google Play"</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"เปิดใช้งานบริการ Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"อัปเดตบริการ Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"แอปพลิเคชันนี้จะไม่ทำงานจนกว่าคุณจะอัปเดตบริการ Google Play"</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"ข้อผิดพลาดของเครือข่าย"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"ต้องมีการเขื่อมต่อข้อมูลเพื่อเชื่อมต่อกับบริการ Google Play"</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"บัญชีไม่ถูกต้อง"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"บัญชีที่ระบุไม่มีอยู่บนอุปกรณ์นี้ โปรดเลือกบัญชีอื่น"</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"ปัญหาที่ไม่รู้จักของบริการ Google Play"</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"บริการ Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"บริการ Google Play ซึ่งใช้งานในบางแอปพลิเคชัน ไม่ได้รับการสนับสนุนโดยอุปกรณ์ของคุณ โปรดติดต่อผู้ผลิตเพื่อขอรับความช่วยเหลือ"</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"วันที่บนอุปกรณ์ไม่ถูกต้อง โปรดตรวจสอบวันที่บนอุปกรณ์"</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"อัปเดต"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"ลงชื่อใช้"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"ลงชื่อเข้าใช้ด้วย Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"แอปพลิเคชันหนึ่งพยายามใช้เวอร์ชันที่ไม่เหมาะสมของบริการ Google Play"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"แอปพลิเคชันหนึ่งจำเป็นต้องมีบริการ Google Play เพื่อเปิดใช้งาน"</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"แอปพลิเคชันหนึ่งจำเป็นต้องมีการติดตั้งบริการ Google Play"</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"แอปพลิเคชันหนึ่งจำเป็นต้องมีการอัปเดตสำหรับบริการ Google Play"</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"ข้อผิดพลาดของบริการ Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"ขอโดย <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-tl/strings.xml b/platform/android/libs/google_play_services/res/values-tl/strings.xml
deleted file mode 100644
index 337f73c0cd..0000000000
--- a/platform/android/libs/google_play_services/res/values-tl/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Kumuha ng mga serbisyo ng Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Hindi tatakbo ang app na ito nang wala ang mga serbisyo ng Google Play, na wala sa iyong telepono."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Hindi gagana ang app na ito nang wala ang mga serbisyo ng Google Play, na wala sa iyong tablet."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Kumuha ng Google Play services"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Paganahin ang Google Play services"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Hindi gagana ang app na ito maliban kung papaganahin mo ang mga serbisyo ng Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Enable Google Play services"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"I-update ang mga serbisyo ng Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Hindi gagana ang app na ito maliban kung i-a-update mo ang mga serbisyo ng Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"May Error sa Network"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Kailangan ng koneksyon ng data upang makakonekta sa mga serbisyo ng Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Di-wasto ang Account"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Hindi umiiral ang tinukoy na account sa device na ito. Mangyaring pumili ng ibang account."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"May hindi alam na isyu sa mga serbisyo ng Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Mga serbisyo ng Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Ang mga serbisyo ng Google Play, kung saan nakadepende ang ilan sa iyong mga application, ay hindi sinusuportahan ng iyong device. Mangyaring makipag-ugnay sa manufacturer para sa tulong."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Mukhang hindi tama ang petsa sa device. Pakisuri ang petsa sa device."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"I-update"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Sign in"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Mag-sign in sa Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"May app na sumubok ng maling bersyon ng Mga Serbisyo ng Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Kailangan ng application na na-enable ang Mga Serbisyo ng Google Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Kailangan ng application na ma-install ang Serbisyo ng Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Kailangan ng application na i-update ang Mga Serbisyo ng Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Error sa mga serbisyo ng Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Hiniling ng <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-tr/strings.xml b/platform/android/libs/google_play_services/res/values-tr/strings.xml
deleted file mode 100644
index 17e61e5fcb..0000000000
--- a/platform/android/libs/google_play_services/res/values-tr/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play hizmetlerini edinin"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Google Play Hizmetleri telefonunuzda yok ve bu uygulama Google Play Hizmetleri olmadan çalışmaz."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Google Play Hizmetleri tabletinizde yok ve bu uygulama Google Play Hizmetleri olmadan çalışmaz."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play hizmetlerini edin"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play hizmetlerini etkinleştir"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Bu uygulama, Google Play Hizmetleri etkinleştirilmeden çalışmaz"</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play hizmetlerini etkinleştir"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play hizmetlerini güncelle"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Bu uygulama Google Play Hizmetleri güncellenmeden çalışmaz."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Ağ Hatası"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play hizmetlerine bağlanmak için bir veri bağlantısı gerekiyor."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Geçersiz Hesap"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Belirtilen hesap bu cihazda mevcut değil. Lütfen farklı bir hesap seçin."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play hizmetleriyle ilgili bilinmeyen sorun."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play hizmetleri"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Cihazınız, uygulamalarınızdan bazıları için gerekli olan Google Play hizmetlerini desteklemiyor. Lütfen yardım için üreticiyle iletişim kurun."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Cihazdaki tarih doğru görünmüyor. Lütfen cihazda ayarlı tarihi kontrol edin."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Güncelle"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Oturum aç"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google\'da oturum aç"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Bir uygulama, Google Play Hizmetleri\'nin bozuk bir sürümünü kullanmayı denedi."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Bir uygulama, Google Play Hizmetleri\'nin etkin olmasını gerektiriyor."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Bir uygulama, Google Play Hizmetleri\'nin yüklenmesini gerektiriyor."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Bir uygulama, Google Play Hizmetleri için bir güncelleme gerektiriyor."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play hizmetleri hatası"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"İstekte bulunan: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-uk/strings.xml b/platform/android/libs/google_play_services/res/values-uk/strings.xml
deleted file mode 100644
index d657aea68d..0000000000
--- a/platform/android/libs/google_play_services/res/values-uk/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Установити Google Play Послуги"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ця програма не запуститься без Google Play Послуг, яких немає у вашому телефоні."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ця програма не запуститься без Google Play Послуг, яких немає на вашому планшетному ПК."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Установити Google Play Послуги"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Увімкнути Google Play Послуги"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ця програма не працюватиме, поки ви не ввімкнете Google Play Послуги."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Увімкнути Google Play Послуги"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Оновити Google Play Послуги"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ця програма не запуститься, поки ви не оновите Google Play Послуги."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Помилка мережі"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Для під’єднання до сервісів Google Play потрібне з’єднання з мережею."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Недійсний обліковий запис"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Указаний обліковий запис не існує на цьому пристрої. Виберіть інший обліковий запис."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play Послуги – невідома проблема."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Сервіси Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Ваш пристрій не підтримує Сервіси Google Play, від яких залежить робота деяких програм. Зверніться по допомогу до виробника."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Схоже, на пристрої вказано неправильну дату. Перевірте її."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Оновити"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Увійти"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Увійти в обл.запис Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Програма спробувала застосувати хибну версію Сервісів Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Щоб програма працювала, потрібно ввімкнути Сервіси Google Play."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Щоб програма працювала, потрібно встановити Сервіси Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Щоб програма працювала, потрібно оновити Сервіси Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Помилка Сервісів Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Запит від програми <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-vi/strings.xml b/platform/android/libs/google_play_services/res/values-vi/strings.xml
deleted file mode 100644
index a0434a08ac..0000000000
--- a/platform/android/libs/google_play_services/res/values-vi/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Cài đặt dịch vụ của Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ứng dụng này sẽ không chạy nếu không có dịch vụ của Google Play. Điện thoại của bạn bị thiếu dịch vụ này."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ứng dụng này sẽ không chạy nếu không có dịch vụ của Google Play. Máy tính bảng của bạn bị thiếu dịch vụ này."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Cài đặt dịch vụ của Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Bật dịch vụ của Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ứng dụng này sẽ không hoạt động trừ khi bạn bật dịch vụ của Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Bật dịch vụ của Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Cập nhật dịch vụ của Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ứng dụng này sẽ không chạy trừ khi bạn cập nhật dịch vụ của Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Lỗi mạng"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Cần có kết nối dữ liệu để kết nối với các dịch vụ của Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Tài khoản không hợp lệ"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Tài khoản đã chỉ định không tồn tại trên thiết bị này. Vui lòng chọn một tài khoản khác."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Sự cố không xác định với dịch vụ của Google Play."</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Dịch vụ của Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Các dịch vụ của Google Play mà một số ứng dụng của bạn dựa vào không được thiết bị của bạn hỗ trợ. Vui lòng liên hệ với nhà sản xuất để được hỗ trợ."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Ngày trên thiết bị có vẻ không chính xác. Vui lòng kiểm tra ngày trên thiết bị."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Cập nhật"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Đăng nhập"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Đăng nhập bằng Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Ứng dụng đã cố sử dụng phiên bản không đúng của Dịch vụ của Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Ứng dụng yêu cầu Dịch vụ của Google Play phải được bật."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Ứng dụng yêu cầu cài đặt Dịch vụ của Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Ứng dụng yêu cầu cập nhật dành cho Dịch vụ Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Lỗi dịch vụ của Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Được yêu cầu bởi <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-zh-rCN/strings.xml b/platform/android/libs/google_play_services/res/values-zh-rCN/strings.xml
deleted file mode 100644
index 4339e3eb01..0000000000
--- a/platform/android/libs/google_play_services/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"获取 Google Play 服务"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"您的手机中没有 Google Play 服务,您必须先安装该服务才能运行此应用。"</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"您的平板电脑中没有 Google Play 服务,您必须先安装该服务才能运行此应用。"</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"获取 Google Play 服务"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"启用 Google Play 服务"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"您必须先启用 Google Play 服务才能运行此应用。"</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"启用 Google Play 服务"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"更新 Google Play 服务"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"您必须先更新 Google Play 服务才能运行此应用。"</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"网络错误"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"您必须有数据网络连接才能接入 Google Play 服务。"</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"无效帐户"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"此设备上不存在指定的帐户,请选择其他帐户。"</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play 服务出现未知问题。"</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play 服务"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"您的设备不支持部分应用所依赖的 Google Play 服务。请与设备制造商联系,以寻求帮助。"</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"设备上的日期似乎不正确,请在设备上检查日期。"</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"更新"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"登录"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"使用 Google 帐户登录"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"某个应用尝试使用的 Google Play 服务版本有误。"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"某个应用要求启用 Google Play 服务。"</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"某个应用要求安装 Google Play 服务。"</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"某个应用要求更新 Google Play 服务。"</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play 服务出错"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"由“<xliff:g id="APP_NAME">%1$s</xliff:g>”发出"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-zh-rHK/strings.xml b/platform/android/libs/google_play_services/res/values-zh-rHK/strings.xml
deleted file mode 100644
index abe6cf1457..0000000000
--- a/platform/android/libs/google_play_services/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"取得 Google Play 服務"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"您的手機未安裝 Google Play 服務,安裝後才能執行這個應用程式。"</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"您的平板電腦未安裝 Google Play 服務,安裝後才能執行這個應用程式。"</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"取得 Google Play 服務"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"啟用 Google Play 服務"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"您必須啟用 Google Play 服務,才能執行這個應用程式。"</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"啟用 Google Play 服務"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"更新 Google Play 服務"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"您必須更新 Google Play 服務,才能執行這個應用程式。"</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"網絡錯誤"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"要連接 Google Play 服務,必需數據連線。"</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"無效的帳戶"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"這個裝置上沒有您指定的帳戶,請選擇其他帳戶。"</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play 服務出現不明問題。"</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play 服務"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"您的裝置不支援部分應用程式所需的 Google Play 服務。如需協助,請與您的裝置製造商聯絡。"</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"裝置上的日期看來不正確,請檢查裝置上的日期。"</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"更新"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"登入"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"登入 Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"應用程式嘗試使用錯誤版本的「Google Play 服務」。"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"必須啟用「Google Play 服務」,才能使用應用程式。"</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"必須安裝「Google Play 服務」,才能使用應用程式。"</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"必須更新「Google Play 服務」,才能使用應用程式。"</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play 服務錯誤"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」提出要求"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-zh-rTW/strings.xml b/platform/android/libs/google_play_services/res/values-zh-rTW/strings.xml
deleted file mode 100644
index a66018ab52..0000000000
--- a/platform/android/libs/google_play_services/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"取得 Google Play 服務"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"您的手機並未安裝 Google Play 服務,所以無法執行這個應用程式。"</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"您的平板電腦並未安裝 Google Play 服務,所以無法執行這個應用程式。"</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"取得 Google Play 服務"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"啟用 Google Play 服務"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"您必須啟用 Google Play 服務,這個應用程式才能運作。"</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"啟用 Google Play 服務"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"更新 Google Play 服務"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"您必須更新 Google Play 服務,才能執行這個應用程式。"</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"網路錯誤"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"需要數據連線才能連上 Google Play 服務。"</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"無效的帳戶"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"這個裝置上沒有您所指定的帳戶,請選擇其他帳戶。"</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play 服務發生不明問題。"</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play 服務"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"您的裝置不支援部分應用程式所需的 Google Play 服務。如需協助,請與您的裝置製造商聯絡。"</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"裝置上的日期似乎不正確,請檢查裝置上的日期。"</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"更新"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"登入"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"使用 Google 帳戶登入"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"應用程式嘗試使用的 Google Play 服務版本有誤。"</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"應用程式需要啟用 Google Play 服務。"</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"應用程式需要安裝 Google Play 服務。"</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"應用程式需要更新 Google Play 服務。"</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Google Play 服務錯誤"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"提出要求的應用程式:<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values-zu/strings.xml b/platform/android/libs/google_play_services/res/values-zu/strings.xml
deleted file mode 100644
index 572d9a52c4..0000000000
--- a/platform/android/libs/google_play_services/res/values-zu/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="common_google_play_services_install_title" msgid="26645092511305524">"Thola amasevisi e-Google Play"</string>
- <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Lolu hlelo lokusebenza ngeke lusebenze ngaphandle kwamasevisi e-Google Play, angekho efonini yakho."</string>
- <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Lolu hlelo lokusebenza ngeke lusebenze ngaphandle kwamasevisi e-Google Play, angekho kuthebulethi yakho."</string>
- <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Thola amasevisi e-Google Play"</string>
- <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Nika amandla amasevisi e-Google Play"</string>
- <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Lolu hlelo lokusebenza ngeke lusebenze ngaphandle nje kokuthi unike amandla amasevisi e-Google Play."</string>
- <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Nika amandla amasevisi e-Google Play"</string>
- <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Buyekeza amasevisi e-Google Play"</string>
- <string name="common_google_play_services_update_text" msgid="448354684997260580">"Lolu hlelo lokusebenza ngeke lusebenze ngaphandle nje kokuthi ubuyekeze amasevisi e-Google Play."</string>
- <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Iphutha lenethiwekhi"</string>
- <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Kudingeka ukuxhumeka kwedatha ukuze kuxhunyekwe kumasevisi we-Google Play."</string>
- <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"I-Akhawunti engavumelekile"</string>
- <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"I-Akhawunti ecacisiwe ayikho kule divayisi. Sicela ukhethe i-akhawunti ehlukile."</string>
- <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Indaba engaziwa yamasevisi we-Google Play"</string>
- <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Amasevisi we-Google Play"</string>
- <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Amasevisi we-Google Play, okungukuthi ezinye izinhlelo zakho zithembele kuwo, awasekelwe yidivayisi yakho. Sicela uxhumane nomkhiqizi ukuze uthole usizo."</string>
- <string name="common_google_play_services_unsupported_date_text" msgid="4725396522367789365">"Idethi kudivayisi ibonakala ingalungile. Sicela uhlole idethi kudivayisi."</string>
- <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Isibuyekezo"</string>
- <string name="common_signin_button_text" msgid="9071884888741449141">"Ngena ngemvume"</string>
- <string name="common_signin_button_text_long" msgid="2429381841831957106">"Ngena ngemvume nge-Google"</string>
-
- <string name="auth_client_using_bad_version_title" msgid="2534454398764507874">"Uhlelo lokusebenza luzame ukusebenzisa inguqulo embi yamasevisi we-Google Play."</string>
- <string name="auth_client_needs_enabling_title" msgid="3983201110833868073">"Uhlelo lokusebenza ludinga amasevisi we-Google Play ukuze anikwe amandla."</string>
- <string name="auth_client_needs_installation_title" msgid="7999585836145154206">"Uhlelo lokusebenza ludinga ukufakwa kwamasevisi we-Google Play."</string>
- <string name="auth_client_needs_update_title" msgid="6488605506794595966">"Uhlelo lokusebenza ludinga isibuyekezo samasevisi we-Google Play."</string>
- <string name="auth_client_play_services_err_notification_msg" msgid="3635065018897986478">"Iphutha lamasevisi we-Google Play"</string>
- <string name="auth_client_requested_by_msg" msgid="6304135633531965756">"Kucelwe yi-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values/ads_attrs.xml b/platform/android/libs/google_play_services/res/values/ads_attrs.xml
deleted file mode 100644
index 4e97a734a6..0000000000
--- a/platform/android/libs/google_play_services/res/values/ads_attrs.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2013 Google Inc. All Rights Reserved. -->
-<resources>
- <declare-styleable name="AdsAttrs">
- <!--
- The size of the ad. It must be one of BANNER, FULL_BANNER, LEADERBOARD,
- MEDIUM_RECTANGLE, SMART_BANNER, WIDE_SKYSCRAPER, or
- &lt;width&gt;x&lt;height&gt;.
- -->
- <attr name="adSize" format="string"/>
-
- <!--
- A comma-separated list of the supported ad sizes. The sizes must be one of
- BANNER, FULL_BANNER, LEADERBOARD, MEDIUM_RECTANGLE, SMART_BANNER,
- WIDE_SKYSCRAPER, or &lt;width&gt;x&lt;height&gt;.
- -->
- <attr name="adSizes" format="string"/>
-
- <!-- The ad unit ID. -->
- <attr name="adUnitId" format="string"/>
- </declare-styleable>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values/colors.xml b/platform/android/libs/google_play_services/res/values/colors.xml
deleted file mode 100644
index 6b2740a509..0000000000
--- a/platform/android/libs/google_play_services/res/values/colors.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources>
- <!-- Sign-in Button Colors -->
- <color name="common_signin_btn_dark_text_default">@android:color/white</color>
- <color name="common_signin_btn_dark_text_pressed">@android:color/white</color>
- <color name="common_signin_btn_dark_text_disabled">#FFAAAAAA</color>
- <color name="common_signin_btn_dark_text_focused">@android:color/white</color>
- <color name="common_signin_btn_light_text_default">#FF737373</color>
- <color name="common_signin_btn_light_text_pressed">@android:color/white</color>
- <color name="common_signin_btn_light_text_disabled">#FFAAAAAA</color>
- <color name="common_signin_btn_light_text_focused">#FF737373</color>
- <color name="common_signin_btn_default_background">#FFDD4B39</color>
- <color name="common_action_bar_splitter">#d2d2d2</color>
-</resources> \ No newline at end of file
diff --git a/platform/android/libs/google_play_services/res/values/maps_attrs.xml b/platform/android/libs/google_play_services/res/values/maps_attrs.xml
deleted file mode 100644
index aaf65c529e..0000000000
--- a/platform/android/libs/google_play_services/res/values/maps_attrs.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2012 Google Inc. All Rights Reserved. -->
-<resources>
- <declare-styleable name="MapAttrs">
- <attr name="mapType" format="enum">
- <enum name="none" value="0"/>
- <enum name="normal" value="1"/>
- <enum name="satellite" value="2"/>
- <enum name="terrain" value="3"/>
- <enum name="hybrid" value="4"/>
- </attr>
- <attr name="cameraBearing" format="float"/>
- <attr name="cameraTargetLat" format="float"/>
- <attr name="cameraTargetLng" format="float"/>
- <attr name="cameraTilt" format="float"/>
- <attr name="cameraZoom" format="float"/>
- <attr name="uiCompass" format="boolean"/>
- <attr name="uiRotateGestures" format="boolean"/>
- <attr name="uiScrollGestures" format="boolean"/>
- <attr name="uiTiltGestures" format="boolean"/>
- <attr name="uiZoomControls" format="boolean"/>
- <attr name="uiZoomGestures" format="boolean"/>
- <attr name="useViewLifecycle" format="boolean"/>
- <attr name="zOrderOnTop" format="boolean"/>
- </declare-styleable>
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values/strings.xml b/platform/android/libs/google_play_services/res/values/strings.xml
deleted file mode 100644
index 3e8731e056..0000000000
--- a/platform/android/libs/google_play_services/res/values/strings.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- Title of confirmation dialog informing user that they need to install
- Google Play services (from Play Store) [CHAR LIMIT=40] -->
- <string name="common_google_play_services_install_title" msgid="7215213145546190223">Get Google Play services</string>
-
- <!-- (For phones) Message in confirmation dialog informing user that
- they need to install Google Play services (from Play Store) [CHAR LIMIT=NONE] -->
- <string name="common_google_play_services_install_text_phone" msgid="2122112764540849864">This app won\'t run without Google Play services, which are missing from your phone.</string>
-
- <!-- (For tablets) Message in confirmation dialog informing user that
- they need to install Google Play services (from Play Store) [CHAR LIMIT=NONE] -->
- <string name="common_google_play_services_install_text_tablet" msgid="7351599665250191022">This app won\'t run without Google Play services, which are missing from your tablet.</string>
-
- <!-- Button in confirmation dialog for installing Google Play services [CHAR LIMIT=40] -->
- <string name="common_google_play_services_install_button" msgid="7153882981874058840">Get Google Play services</string>
-
- <!-- Title of confirmation dialog informing user they need to enable
- Google Play services in application settings [CHAR LIMIT=40] -->
- <string name="common_google_play_services_enable_title" msgid="5122002158466380389">Enable Google Play services</string>
-
- <!-- Message in confirmation dialog informing user they need to enable
- Google Play services in application settings [CHAR LIMIT=NONE] -->
- <string name="common_google_play_services_enable_text" msgid="227660514972886228">This app won\'t work unless you enable Google Play services.</string>
-
- <!-- Button in confirmation dialog to enable Google Play services. Clicking it
- will direct user to application settings of Google Play services where they
- can enable it [CHAR LIMIT=40] -->
- <string name="common_google_play_services_enable_button" msgid="2523291102206661146">Enable Google Play services</string>
-
- <!-- Title of confirmation dialog informing user that they need to update
- Google Play services (from Play Store) [CHAR LIMIT=40] -->
- <string name="common_google_play_services_update_title" msgid="1788179980625863495">Update Google Play services</string>
-
- <!-- Message in confirmation dialog informing user that they need to update
- Google Play services (from Play Store) [CHAR LIMIT=NONE] -->
- <string name="common_google_play_services_update_text" msgid="9053896323427875356">This app won\'t run unless you update Google Play services.</string>
-
- <!-- Title of confirmation dialog informing the user that a network error occurred. [CHAR LIMIT=40] -->
- <string name="common_google_play_services_network_error_title">Network Error</string>
-
- <!-- Message in confirmation dialog informing the user that a network error occurred. [CHAR LIMIT=NONE] -->
- <string name="common_google_play_services_network_error_text">A data connection is required to connect to Google Play services.</string>
-
- <!-- Title of confirmation dialog informing the user that they provided an invalid account. [CHAR LIMIT=40] -->
- <string name="common_google_play_services_invalid_account_title">Invalid Account</string>
-
- <!-- Message in confirmation dialog informing the user that they provided an invalid account. [CHAR LIMIT=NONE] -->
- <string name="common_google_play_services_invalid_account_text">The specified account does not exist on this device. Please choose a different account.</string>
-
- <!-- Message in confirmation dialog informing user there is an unknown issue in Google Play
- services [CHAR LIMIT=NONE] -->
- <string name="common_google_play_services_unknown_issue">Unknown issue with Google Play services.</string>
-
- <!-- Title of confirmation dialog informing user that Google Play services is not supported on their device [CHAR LIMIT=40] -->
- <string name="common_google_play_services_unsupported_title">Google Play services</string>
-
- <!-- Message in confirmation dialog informing user that Google Play services is not supported on their device [CHAR LIMIT=NONE] -->
- <string name="common_google_play_services_unsupported_text">Google Play services, which some of your applications rely on, is not supported by your device. Please contact the manufacturer for assistance.</string>
-
- <!-- Message in confirmation dialog informing user that date on the device is not correct,
- causing certificate checks to fail. [CHAR LIMIT=NONE] -->
- <string name="common_google_play_services_unsupported_date_text">The date on the device appears to be incorrect. Please check the date on the device.</string>
-
- <!-- Button in confirmation dialog for updating Google Play services [CHAR LIMIT=40] -->
- <string name="common_google_play_services_update_button" msgid="6556509956452265614">Update</string>
-
- <!-- Sign-in button text [CHAR LIMIT=15] -->
- <string name="common_signin_button_text">Sign in</string>
-
- <!-- Long form sign-in button text [CHAR LIMIT=30] -->
- <string name="common_signin_button_text_long">Sign in with Google</string>
-
-
- <!-- Auth client code resources (prefix with auth_client --><skip />
- <!-- Title for notification shown when a bad version of GooglePlayServices
- has been installed and needs correction for an application to work.
- [CHAR LIMIT=70] -->
- <string name="auth_client_using_bad_version_title">
- An application attempted to use a bad version of Google Play Services.
- </string>
- <!-- Title for notification shown when GooglePlayServices needs to be
- enabled for a application to work. [CHAR LIMIT=70] -->
- <string name="auth_client_needs_enabling_title">
- An application requires Google Play Services to be enabled.
- </string>
- <!-- Title for notification shown when GooglePlayServices needs to be
- installed for a application to work. [CHAR LIMIT=70] -->
- <string name="auth_client_needs_installation_title">
- An application requires installation of Google Play Services.
- </string>
- <!-- Title for notification shown when GooglePlayServices needs to be
- udpated for a application to work. [CHAR LIMIT=70] -->
- <string name="auth_client_needs_update_title">
- An application requires an update for Google Play Services.
- </string>
-
- <!-- Title for notification shown when GooglePlayServices is unavailable [CHAR LIMIT=42] -->
- <string name="auth_client_play_services_err_notification_msg">Google Play services error</string>
-
- <!-- Requested by string saying which app requested the notification. [CHAR LIMIT=42] -->
- <string name="auth_client_requested_by_msg">Requested by <xliff:g id="app_name">%1$s</xliff:g></string>
- <!-- End Auth client resources --><skip />
-
- <!-- Location client code resources (prefix with location_client) -->
-
- <string name="location_client_powered_by_google">Powered by Google</string>
-
- <!-- End location client resources -->
-</resources>
diff --git a/platform/android/libs/google_play_services/res/values/version.xml b/platform/android/libs/google_play_services/res/values/version.xml
deleted file mode 100644
index 1e7fd4e7ef..0000000000
--- a/platform/android/libs/google_play_services/res/values/version.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <integer name="google_play_services_version">4323000</integer>
-</resources>
diff --git a/platform/android/libs/google_play_services/src/android/UnusedStub.java b/platform/android/libs/google_play_services/src/android/UnusedStub.java
deleted file mode 100644
index d546b0ba9f..0000000000
--- a/platform/android/libs/google_play_services/src/android/UnusedStub.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android;
-
-// Stub java file to make inclusion into some IDE's work.
-public final class UnusedStub {
- private UnusedStub() { }
-}
diff --git a/platform/android/libs/play_licensing/AndroidManifest.xml b/platform/android/libs/play_licensing/AndroidManifest.xml
deleted file mode 100644
index c7849130c3..0000000000
--- a/platform/android/libs/play_licensing/AndroidManifest.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.google.android.vending.licensing"
- android:versionCode="2"
- android:versionName="1.5">
- <!-- Devices >= 3 have version of Android Market that supports licensing. -->
- <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="15" />
- <!-- Required permission to check licensing. -->
- <uses-permission android:name="com.android.vending.CHECK_LICENSE" />
-</manifest>
diff --git a/platform/android/libs/play_licensing/build.xml b/platform/android/libs/play_licensing/build.xml
deleted file mode 100644
index 0e800d6b9b..0000000000
--- a/platform/android/libs/play_licensing/build.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="play_licensing" default="help">
-
- <!-- The local.properties file is created and updated by the 'android' tool.
- It contains the path to the SDK. It should *NOT* be checked into
- Version Control Systems. -->
- <property file="local.properties" />
-
- <!-- The ant.properties file can be created by you. It is only edited by the
- 'android' tool to add properties to it.
- This is the place to change some Ant specific build properties.
- Here are some properties you may want to change/update:
-
- source.dir
- The name of the source directory. Default is 'src'.
- out.dir
- The name of the output directory. Default is 'bin'.
-
- For other overridable properties, look at the beginning of the rules
- files in the SDK, at tools/ant/build.xml
-
- Properties related to the SDK location or the project target should
- be updated using the 'android' tool with the 'update' action.
-
- This file is an integral part of the build system for your
- application and should be checked into Version Control Systems.
-
- -->
- <property file="ant.properties" />
-
- <!-- if sdk.dir was not set from one of the property file, then
- get it from the ANDROID_HOME env var.
- This must be done before we load project.properties since
- the proguard config can use sdk.dir -->
- <property environment="env" />
- <condition property="sdk.dir" value="${env.ANDROID_HOME}">
- <isset property="env.ANDROID_HOME" />
- </condition>
-
- <!-- The project.properties file is created and updated by the 'android'
- tool, as well as ADT.
-
- This contains project specific properties such as project target, and library
- dependencies. Lower level build properties are stored in ant.properties
- (or in .classpath for Eclipse projects).
-
- This file is an integral part of the build system for your
- application and should be checked into Version Control Systems. -->
- <loadproperties srcFile="project.properties" />
-
- <!-- quick check on sdk.dir -->
- <fail
- message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
- unless="sdk.dir"
- />
-
- <!--
- Import per project custom build rules if present at the root of the project.
- This is the place to put custom intermediary targets such as:
- -pre-build
- -pre-compile
- -post-compile (This is typically used for code obfuscation.
- Compiled code location: ${out.classes.absolute.dir}
- If this is not done in place, override ${out.dex.input.absolute.dir})
- -post-package
- -post-build
- -pre-clean
- -->
- <import file="custom_rules.xml" optional="true" />
-
- <!-- Import the actual build file.
-
- To customize existing targets, there are two options:
- - Customize only one target:
- - copy/paste the target into this file, *before* the
- <import> task.
- - customize it to your needs.
- - Customize the whole content of build.xml
- - copy/paste the content of the rules files (minus the top node)
- into this file, replacing the <import> task.
- - customize to your needs.
-
- ***********************
- ****** IMPORTANT ******
- ***********************
- In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
- in order to avoid having your file be overridden by tools such as "android update project"
- -->
- <!-- version-tag: 1 -->
- <import file="${sdk.dir}/tools/ant/build.xml" />
-
-</project>
diff --git a/platform/android/libs/play_licensing/proguard-project.txt b/platform/android/libs/play_licensing/proguard-project.txt
deleted file mode 100644
index f2fe1559a2..0000000000
--- a/platform/android/libs/play_licensing/proguard-project.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-# To enable ProGuard in your project, edit project.properties
-# to define the proguard.config property as described in that file.
-#
-# Add project specific ProGuard rules here.
-# By default, the flags in this file are appended to flags specified
-# in ${sdk.dir}/tools/proguard/proguard-android.txt
-# You can edit the include path and order by changing the ProGuard
-# include property in project.properties.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# Add any project specific keep options here:
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
diff --git a/platform/android/libs/play_licensing/project.properties b/platform/android/libs/play_licensing/project.properties
deleted file mode 100644
index f28bc833e1..0000000000
--- a/platform/android/libs/play_licensing/project.properties
+++ /dev/null
@@ -1,12 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system use,
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-
-android.library=true
-# Project target.
-target=android-15
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index e2ff128f0d..03177317af 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -141,6 +141,8 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_
}
+ rasterizer->set_force_16_bits_fbo(use_16bits_fbo);
+
visual_server = memnew( VisualServerRaster(rasterizer) );
if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
@@ -300,6 +302,14 @@ void OS_Android::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen)
p_list->push_back(default_videomode);
}
+void OS_Android::set_keep_screen_on(bool p_enabled) {
+ OS::set_keep_screen_on(p_enabled);
+
+ if (set_keep_screen_on_func) {
+ set_keep_screen_on_func(p_enabled);
+ }
+}
+
Size2 OS_Android::get_window_size() const {
return Vector2(default_videomode.width,default_videomode.height);
@@ -725,7 +735,14 @@ void OS_Android::native_video_stop() {
video_stop_func();
}
-OS_Android::OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id,GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func,bool p_use_apk_expansion) {
+void OS_Android::set_context_is_16_bits(bool p_is_16) {
+
+ use_16bits_fbo=p_is_16;
+ if (rasterizer)
+ rasterizer->set_force_16_bits_fbo(p_is_16);
+}
+
+OS_Android::OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id,GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, bool p_use_apk_expansion) {
use_apk_expansion=p_use_apk_expansion;
@@ -758,6 +775,7 @@ OS_Android::OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFu
hide_virtual_keyboard_func = p_hide_vk;
set_screen_orientation_func=p_screen_orient;
+ set_keep_screen_on_func = p_set_keep_screen_on_func;
use_reload_hooks=false;
}
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index dcaa1db654..1ae42e9cc7 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -73,6 +73,7 @@ typedef void (*VideoPlayFunc)(const String&);
typedef bool (*VideoIsPlayingFunc)();
typedef void (*VideoPauseFunc)();
typedef void (*VideoStopFunc)();
+typedef void (*SetKeepScreenOnFunc)(bool p_enabled);
class OS_Android : public OS_Unix {
public:
@@ -95,6 +96,8 @@ private:
bool use_reload_hooks;
bool use_apk_expansion;
+ bool use_16bits_fbo;
+
Rasterizer *rasterizer;
VisualServer *visual_server;
AudioServerSW *audio_server;
@@ -130,6 +133,7 @@ private:
VideoIsPlayingFunc video_is_playing_func;
VideoPauseFunc video_pause_func;
VideoStopFunc video_stop_func;
+ SetKeepScreenOnFunc set_keep_screen_on_func;
public:
@@ -173,7 +177,9 @@ public:
virtual void set_video_mode(const VideoMode& p_video_mode,int p_screen=0);
virtual VideoMode get_video_mode(int p_screen=0) const;
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const;
-
+
+ virtual void set_keep_screen_on(bool p_enabled);
+
virtual Size2 get_window_size() const;
virtual String get_name();
@@ -200,6 +206,7 @@ public:
void set_display_size(Size2 p_size);
void reload_gfx();
+ void set_context_is_16_bits(bool p_is_16);
void set_need_reload_hooks(bool p_needs_them);
virtual void set_screen_orientation(ScreenOrientation p_orientation);
@@ -225,7 +232,7 @@ public:
virtual void native_video_pause();
virtual void native_video_stop();
- OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id,GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func,bool p_use_apk_expansion);
+ OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id,GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, bool p_use_apk_expansion);
~OS_Android();
};
diff --git a/platform/android/platform_config.h b/platform/android/platform_config.h
index 1e7d066bb9..143f16c1fa 100644
--- a/platform/android/platform_config.h
+++ b/platform/android/platform_config.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/android/project.properties.template b/platform/android/project.properties.template
deleted file mode 100644
index 00cacd72bc..0000000000
--- a/platform/android/project.properties.template
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system edit
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-#
-# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
-#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
-
-# Project target.
-#android.library=true
-target=android-19
diff --git a/platform/android/thread_jandroid.cpp b/platform/android/thread_jandroid.cpp
index 9314a1c013..1425e23c73 100644
--- a/platform/android/thread_jandroid.cpp
+++ b/platform/android/thread_jandroid.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/android/thread_jandroid.h b/platform/android/thread_jandroid.h
index 051f4e2c3d..c8ad6c8735 100644
--- a/platform/android/thread_jandroid.h
+++ b/platform/android/thread_jandroid.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/bb10/audio_driver_bb10.cpp b/platform/bb10/audio_driver_bb10.cpp
index f12625d3b8..ef8adaf061 100644
--- a/platform/bb10/audio_driver_bb10.cpp
+++ b/platform/bb10/audio_driver_bb10.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/bb10/audio_driver_bb10.h b/platform/bb10/audio_driver_bb10.h
index 82774bc533..0148448511 100644
--- a/platform/bb10/audio_driver_bb10.h
+++ b/platform/bb10/audio_driver_bb10.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/bb10/bbutil.h b/platform/bb10/bbutil.h
index 8df513cb7d..bc422cd9b9 100644
--- a/platform/bb10/bbutil.h
+++ b/platform/bb10/bbutil.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/bb10/export/export.cpp b/platform/bb10/export/export.cpp
index 434aaff414..2acd920f31 100644
--- a/platform/bb10/export/export.cpp
+++ b/platform/bb10/export/export.cpp
@@ -275,10 +275,16 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu
EditorProgress ep("export","Exporting for BlackBerry 10",104);
- String template_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
-
- String src_template=custom_package!=""?custom_package:template_path.plus_file("bb10.zip");
-
+ String src_template=custom_package;
+
+ if (src_template=="") {
+ String err;
+ src_template = find_export_template("bb10.zip", &err);
+ if (src_template=="") {
+ EditorNode::add_io_error(err);
+ return ERR_FILE_NOT_FOUND;
+ }
+ }
FileAccess *src_f=NULL;
zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
@@ -733,9 +739,7 @@ bool EditorExportPlatformBB10::can_export(String *r_error) const {
err+="Blackberry host tools not configured in editor settings.\n";
}
- String exe_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
-
- if (!FileAccess::exists(exe_path+"bb10.zip")) {
+ if (!exists_export_template("bb10.zip")) {
valid=false;
err+="No export template found.\nDownload and install export templates.\n";
}
diff --git a/platform/bb10/godot_bb10.cpp b/platform/bb10/godot_bb10.cpp
index f7e154d647..cba9d200cb 100644
--- a/platform/bb10/godot_bb10.cpp
+++ b/platform/bb10/godot_bb10.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/bb10/os_bb10.cpp b/platform/bb10/os_bb10.cpp
index c8e7ae561e..d2a350cf83 100644
--- a/platform/bb10/os_bb10.cpp
+++ b/platform/bb10/os_bb10.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/bb10/os_bb10.h b/platform/bb10/os_bb10.h
index 28149c15b5..a0481d1190 100644
--- a/platform/bb10/os_bb10.h
+++ b/platform/bb10/os_bb10.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/bb10/payment_service.cpp b/platform/bb10/payment_service.cpp
index f01230796f..77ec122b3b 100644
--- a/platform/bb10/payment_service.cpp
+++ b/platform/bb10/payment_service.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/bb10/payment_service.h b/platform/bb10/payment_service.h
index 5036ca6660..856b8df306 100644
--- a/platform/bb10/payment_service.h
+++ b/platform/bb10/payment_service.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/bb10/platform_config.h b/platform/bb10/platform_config.h
index 38fc934ae4..143f16c1fa 100644
--- a/platform/bb10/platform_config.h
+++ b/platform/bb10/platform_config.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/flash/dir_access_flash.cpp b/platform/flash/dir_access_flash.cpp
index 4b8992f9d6..443242fd99 100644
--- a/platform/flash/dir_access_flash.cpp
+++ b/platform/flash/dir_access_flash.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/platform/flash/dir_access_flash.h b/platform/flash/dir_access_flash.h
index 1378a6e56f..482120775d 100644
--- a/platform/flash/dir_access_flash.h
+++ b/platform/flash/dir_access_flash.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/platform/flash/rasterizer_flash.cpp b/platform/flash/rasterizer_flash.cpp
index 121baa333c..a36890e3d8 100644
--- a/platform/flash/rasterizer_flash.cpp
+++ b/platform/flash/rasterizer_flash.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/platform/flash/rasterizer_flash.h b/platform/flash/rasterizer_flash.h
index 1a2c540faa..1caf7f2c44 100644
--- a/platform/flash/rasterizer_flash.h
+++ b/platform/flash/rasterizer_flash.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/platform/haiku/SCsub b/platform/haiku/SCsub
index 859095fa5a..1952e6b59b 100644
--- a/platform/haiku/SCsub
+++ b/platform/haiku/SCsub
@@ -10,7 +10,16 @@ common_haiku = [
'audio_driver_media_kit.cpp'
]
-env.Program(
+target = env.Program(
'#bin/godot',
['godot_haiku.cpp'] + common_haiku
)
+
+command = env.Command('#bin/godot.rsrc', '#platform/haiku/godot.rdef',
+ ['rc -o $TARGET $SOURCE'])
+
+def addResourcesAction(target = None, source = None, env = None):
+ return env.Execute('xres -o ' + File(target)[0].path + ' bin/godot.rsrc')
+
+env.AddPostAction(target, addResourcesAction)
+env.Depends(target, command)
diff --git a/platform/haiku/audio_driver_media_kit.cpp b/platform/haiku/audio_driver_media_kit.cpp
index 3fabe4f96f..c7eed1c7cd 100644
--- a/platform/haiku/audio_driver_media_kit.cpp
+++ b/platform/haiku/audio_driver_media_kit.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -118,8 +118,7 @@ void AudioDriverMediaKit::unlock() {
}
void AudioDriverMediaKit::finish() {
- if (player)
- delete player;
+ delete player;
if (samples_in) {
memdelete_arr(samples_in);
diff --git a/platform/haiku/audio_driver_media_kit.h b/platform/haiku/audio_driver_media_kit.h
index a23ec447f1..cdaf602831 100644
--- a/platform/haiku/audio_driver_media_kit.h
+++ b/platform/haiku/audio_driver_media_kit.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/haiku/detect.py b/platform/haiku/detect.py
index b5fd550442..637b42dc03 100644
--- a/platform/haiku/detect.py
+++ b/platform/haiku/detect.py
@@ -51,6 +51,7 @@ def configure(env):
env.Append(CCFLAGS=['-g2', '-Wall','-DDEBUG_ENABLED','-DDEBUG_MEMORY_ENABLED'])
#env.Append(CCFLAGS=['-DFREETYPE_ENABLED'])
+ env.Append(CPPFLAGS = ['-DPTHREAD_NO_RENAME']) # TODO: enable when we have pthread_setname_np
env.Append(CPPFLAGS = ['-DGLEW_ENABLED', '-DOPENGL_ENABLED', '-DMEDIA_KIT_ENABLED'])
env.Append(CPPFLAGS = ['-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DGLES_OVER_GL'])
env.Append(LIBS = ['be', 'game', 'media', 'network', 'bnetapi', 'z', 'GL', 'GLEW'])
diff --git a/platform/haiku/godot.rdef b/platform/haiku/godot.rdef
new file mode 100644
index 0000000000..a55cddbf0d
--- /dev/null
+++ b/platform/haiku/godot.rdef
@@ -0,0 +1,60 @@
+resource app_version {
+ major = 2,
+ middle = 0,
+ minor = 0,
+
+ variety = B_APPV_FINAL,
+ internal = 0,
+
+ short_info = "Godot Game Engine",
+ long_info = "An advanced, feature packed, multi-platform 2D and 3D game engine."
+};
+
+resource app_signature "application/x-vnd.godot";
+
+resource vector_icon {
+ $"6E6369660403A39F9F05FF03478CBF03414042090A04B37FB379CC26B379CC26"
+ $"CC20B37FCC200A09B5E9C41B2AC240B8E1BDFBBFA1BDA4C6A7BDFFCA1AC45CC9"
+ $"7AC607C01CC75BB6F4C65A062AFE9FFF9F69FE7FFEDFCF0FC95FC3D7C95FC51E"
+ $"C95FC51EC95FC53EC92BC565C94AC55BC92BC565C728C60BC728C60BC712C612"
+ $"C6E6C600C6F9C60EC6D3C5F2C6C7C5C4C6C7C5DCC6C7C5C4C460C4E5C4BCC4E5"
+ $"C626C4E5C626C4E5C64BC4A5C670C4CAC66BC4A5C670C1EDC6CFC1EDC6CFC1E9"
+ $"C6CFC1E2C6D0C1E6C6D0C1D1C6D0C1B2C6BEC1BFC6C9C1A2C6AFC19851C198C6"
+ $"9BC19851C505C031C507C507C016C507BFFCC507C507BE94C505BE9451BE9451"
+ $"BE94C69BBE7BC6BEBE8BC6AFBE6DC6C9BE4AC6D0BE5CC6D0BE47C6D0BE40C6CF"
+ $"BE44C6CFBE40C6CFBB87C670BB87C670BB63C66BBB47C626BB47C64BBB47C626"
+ $"C4BCB965C460B965C5C4B965C5C4B965C5DCB947C600B95AC5F2B934C60EB904"
+ $"C60BB91BC612B904C60BB701C565B701C565B6E3C55BB6CEC51EB6CEC53EB6CE"
+ $"C51EC3D7B590C36CB590C36CB581C3B0B578C43AB578C3F5B578C78FBFF8CA27"
+ $"BA2ACA22BFF8CA27BFFABFFCCA27BFFCCA27C5CACA22CA7CC43ACA7CC78FCA7C"
+ $"C3FBCA67C37ECA754ACA67C37E0639F6F97FFEF8E7FFF9F6FFFFFFFFFF03B67D"
+ $"BDEEC31FB730C35CB730C35CB74EC3662BC3A22BC3822BC3A2C4E8B8D1C55EB8"
+ $"D1C406B8D1C406B8D1C3F0B8ECC3CDB8DBC3DBB8FDC3BFB929C3BDB913C3B9B9"
+ $"29C3BDBB9FC436BB9FC436BBC2C43CBBDCC47EBBDCC45BBBDCC47EC5E6BE00C6"
+ $"31BE00C4BBBE00C4BBBE00C4A7BE16C486BE08C494BE24C479BE4AC471BE37C4"
+ $"71BE4AC471BE4BC016C473C1E2C471C1E2C471C1F6C471C217C486C209C479C2"
+ $"25C494C22DC4BBC22DC4A7C22DC4BBC631C451C5E6C451C47EC451C47EC451C4"
+ $"5BC48DC436C46AC43CC48DC436C704C3BDC704C3BDC719C3B9C741C3CDC730C3"
+ $"BF53C3DBC75CC406C75CC3F0C75CC406C55EC8CAC4E8C8CAC3A2C8CAC3A2C8CA"
+ $"C382C8FDC35CC8DFC366C8FDC35CC977C333BDEEC97ABDEEC97ABDEEC9F1BD56"
+ $"CAC9BC0BCA60BCB6CA3DBB1CC8D9B981C991BA47C82FB9D7C6EDBAA0C789BA38"
+ $"C69FBA52C5F0B9D0C647BA12C59BB98BC4E0B91FC53BB959C4FBB855C50EB6C0"
+ $"C509B78FC424B64AC22DB5C4C32AB5FCC1C8B66DC11BB7D9C16BB725C0BCB7C9"
+ $"BFFCB7C2C05CB7C3BFFCB7C2BFFCB7C2BFFCB7C2BFFBB7C2BFFAB7C2BFFAB7C2"
+ $"BFF9B7C2BFF8B7C2BFF9B7C2BFF8B7C2BFF8B7C2BFF8B7C2BF98B7C3BED9B7D9"
+ $"BF38B7C9BE88B725BDC7B5C4BE2CB66DBCCAB5FCBAE6B6C0BBD0B64ABAEBB78F"
+ $"BB13B91F34B855BAB8B959BA04B9D0BA59B98BB9ADBA12B907BAA0B955BA52B8"
+ $"6ABA38B71AB981B7C5B9D7B663BA47B52BBC0BB5B7BB1CB594BCB6B679BDEEB6"
+ $"02BD56B679BDEE0005BD3EC06CBD3EC06CBD3EC197BB2147BC4C47B9F647B904"
+ $"C06CB904C197B904BF41BB21BE4FB9F6BE4FBC4CBE4FBD3EC06CBD3EBF41BD3E"
+ $"C06C0005BCBC42BCBC42BCBCC153BB55C1F3BC1BC1F3BA8EC1F3B9ED42B9EDC1"
+ $"53B9EDBFC6BB55BF25BA8EBF25BC1BBF25BCBC42BCBCBFC6BCBC420007C01BC2"
+ $"BBC01BC2BBBFBAC2BBBF6CC21CBF6CC274BF6CC21CBF6CC02ABF6CC02ABF6CBF"
+ $"D3C01BBF8CBFBABF8CC07BBF8CC0C9C02AC0C9BFD3C0C9C02AC0C9C21CC0C9C2"
+ $"1CC0C9C274C01BC2BBC07BC2BBC01BC2BB0005C2F7C06CC2F7C06CC2F7C197C5"
+ $"1547C3E947C64047C732C06CC732C197C732BF41C515BE4FC640BE4FC3E9BE4F"
+ $"C2F7C06CC2F7BF41C2F7C06C0005C37942C37942C379C153C4E1C1F3C41AC1F3"
+ $"C5A7C1F3C64842C648C153C648BFC6C4E1BF25C5A7BF25C41ABF25C37942C379"
+ $"BFC6C37942090A0000000A010101000A020102000A020103000A010104000A03"
+ $"0105000A010106000A010107000A03010800"
+};
diff --git a/platform/haiku/haiku_application.cpp b/platform/haiku/haiku_application.cpp
index ea20d73729..180bd133fb 100644
--- a/platform/haiku/haiku_application.cpp
+++ b/platform/haiku/haiku_application.cpp
@@ -1,7 +1,7 @@
#include "haiku_application.h"
HaikuApplication::HaikuApplication()
- : BApplication("application/x-vnd.Godot")
+ : BApplication("application/x-vnd.godot")
{
}
diff --git a/platform/haiku/haiku_direct_window.cpp b/platform/haiku/haiku_direct_window.cpp
index 3914ee272a..184d64f840 100644
--- a/platform/haiku/haiku_direct_window.cpp
+++ b/platform/haiku/haiku_direct_window.cpp
@@ -16,9 +16,7 @@ HaikuDirectWindow::HaikuDirectWindow(BRect p_frame)
HaikuDirectWindow::~HaikuDirectWindow() {
- if (update_runner) {
- delete update_runner;
- }
+ delete update_runner;
}
void HaikuDirectWindow::SetHaikuGLView(HaikuGLView* p_view) {
diff --git a/platform/iphone/Appirater.h b/platform/iphone/Appirater.h
index f0bf2c01d5..6ff25532f7 100644
--- a/platform/iphone/Appirater.h
+++ b/platform/iphone/Appirater.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/app_delegate.h b/platform/iphone/app_delegate.h
index 0d20f886cc..54bfe78cf7 100644
--- a/platform/iphone/app_delegate.h
+++ b/platform/iphone/app_delegate.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm
index e5bd7a96b4..a3af8ff163 100644
--- a/platform/iphone/app_delegate.mm
+++ b/platform/iphone/app_delegate.mm
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -57,6 +57,7 @@
#endif
Error _shell_open(String);
+void _set_keep_screen_on(bool p_enabled);
Error _shell_open(String p_uri) {
NSString* url = [[NSString alloc] initWithUTF8String:p_uri.utf8().get_data()];
@@ -70,6 +71,10 @@ Error _shell_open(String p_uri) {
return OK;
};
+void _set_keep_screen_on(bool p_enabled) {
+ [[UIApplication sharedApplication] setIdleTimerDisabled:(BOOL)p_enabled];
+};
+
@implementation AppDelegate
@synthesize window;
@@ -212,8 +217,8 @@ static int frame_count = 0;
[application setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
// disable idle timer
- application.idleTimerDisabled = YES;
-
+ //application.idleTimerDisabled = YES;
+
//Create a full-screen window
window = [[UIWindow alloc] initWithFrame:rect];
//window.autoresizesSubviews = YES;
@@ -238,6 +243,7 @@ static int frame_count = 0;
view_controller.view = glView;
window.rootViewController = view_controller;
+ _set_keep_screen_on(bool(GLOBAL_DEF("display/keep_screen_on",true)) ? YES : NO);
glView.useCADisplayLink = bool(GLOBAL_DEF("display.iOS/use_cadisplaylink",true)) ? YES : NO;
printf("cadisaplylink: %d", glView.useCADisplayLink);
glView.animationInterval = 1.0 / kRenderingFrequency;
diff --git a/platform/iphone/audio_driver_iphone.cpp b/platform/iphone/audio_driver_iphone.cpp
index a95cb436a7..0916c31f36 100644
--- a/platform/iphone/audio_driver_iphone.cpp
+++ b/platform/iphone/audio_driver_iphone.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/audio_driver_iphone.h b/platform/iphone/audio_driver_iphone.h
index 5d406940a3..0b143adf94 100644
--- a/platform/iphone/audio_driver_iphone.h
+++ b/platform/iphone/audio_driver_iphone.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index 137fcc56f5..9472f05e16 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -59,11 +59,11 @@ def configure(env):
import string
if (env["bits"]=="64"):
#env['CCFLAGS'] = string.split('-arch arm64 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -Wno-trigraphs -fpascal-strings -O0 -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-return-type -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wunused-value -Wno-empty-body -Wno-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-constant-conversion -Wno-int-conversion -Wno-bool-conversion -Wno-enum-conversion -Wshorten-64-to-32 -Wno-newline-eof -Wno-c++11-extensions -fstrict-aliasing -Wdeprecated-declarations -Winvalid-offsetof -g -Wno-sign-conversion -miphoneos-version-min=5.1.1 -Wmost -Wno-four-char-constants -Wno-unknown-pragmas -Wno-invalid-offsetof -ffast-math -m64 -DDEBUG -D_DEBUG -MMD -MT dependencies -isysroot $IPHONESDK')
- env['CCFLAGS'] = string.split('-fno-objc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -MMD -MT dependencies -miphoneos-version-min=5.1.1 -isysroot $IPHONESDK')
+ env['CCFLAGS'] = string.split('-fno-objc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -fvisibility=hidden -Wno-sign-conversion -MMD -MT dependencies -miphoneos-version-min=5.1.1 -isysroot $IPHONESDK')
env.Append(CPPFLAGS=['-DNEED_LONG_INT'])
env.Append(CPPFLAGS=['-DLIBYUV_DISABLE_NEON'])
else:
- env['CCFLAGS'] = string.split('-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=5.1.1 -MMD -MT dependencies -isysroot $IPHONESDK')
+ env['CCFLAGS'] = string.split('-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk -fvisibility=hidden -Wno-sign-conversion -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=5.1.1 -MMD -MT dependencies -isysroot $IPHONESDK')
if (env["bits"]=="64"):
env.Append(LINKFLAGS=['-arch', 'arm64', '-Wl,-dead_strip', '-miphoneos-version-min=5.1.1',
@@ -116,12 +116,12 @@ def configure(env):
if (env["target"]=="release"):
- env.Append(CCFLAGS=['-O3', '-ffast-math', '-DNS_BLOCK_ASSERTIONS=1','-Wall'])
- env.Append(LINKFLAGS=['-O3', '-ffast-math'])
+ env.Append(CCFLAGS=['-O3', '-DNS_BLOCK_ASSERTIONS=1','-Wall', '-gdwarf-2']) # removed -ffast-math
+ env.Append(LINKFLAGS=['-O3']) #
elif env["target"] == "release_debug":
- env.Append(CCFLAGS=['-Os', '-ffast-math', '-DNS_BLOCK_ASSERTIONS=1','-Wall','-DDEBUG_ENABLED'])
- env.Append(LINKFLAGS=['-Os', '-ffast-math'])
+ env.Append(CCFLAGS=['-Os', '-DNS_BLOCK_ASSERTIONS=1','-Wall','-DDEBUG_ENABLED'])
+ env.Append(LINKFLAGS=['-Os'])
env.Append(CPPFLAGS=['-DDEBUG_MEMORY_ENABLED'])
elif (env["target"]=="debug"):
@@ -131,7 +131,7 @@ def configure(env):
elif (env["target"]=="profile"):
- env.Append(CCFLAGS=['-g','-pg', '-Os', '-ffast-math'])
+ env.Append(CCFLAGS=['-g','-pg', '-Os'])
env.Append(LINKFLAGS=['-pg'])
diff --git a/platform/iphone/game_center.h b/platform/iphone/game_center.h
index 8f180d1638..62477a0da2 100644
--- a/platform/iphone/game_center.h
+++ b/platform/iphone/game_center.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/game_center.mm b/platform/iphone/game_center.mm
index 4cb7a20a7f..3756b58699 100644
--- a/platform/iphone/game_center.mm
+++ b/platform/iphone/game_center.mm
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/gl_view.h b/platform/iphone/gl_view.h
index ca2d1d25ae..e69ddc839a 100755
--- a/platform/iphone/gl_view.h
+++ b/platform/iphone/gl_view.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm
index f19e16f3f6..88361e87e4 100755
--- a/platform/iphone/gl_view.mm
+++ b/platform/iphone/gl_view.mm
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/godot_iphone.cpp b/platform/iphone/godot_iphone.cpp
index f0cb929429..2ecfe1545e 100644
--- a/platform/iphone/godot_iphone.cpp
+++ b/platform/iphone/godot_iphone.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/icloud.h b/platform/iphone/icloud.h
index ca21f62ba1..c772555835 100644
--- a/platform/iphone/icloud.h
+++ b/platform/iphone/icloud.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/icloud.mm b/platform/iphone/icloud.mm
index 518385992d..449670667f 100644
--- a/platform/iphone/icloud.mm
+++ b/platform/iphone/icloud.mm
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/in_app_store.h b/platform/iphone/in_app_store.h
index 585cd19538..bd4215231e 100644
--- a/platform/iphone/in_app_store.h
+++ b/platform/iphone/in_app_store.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm
index f689123c81..fec007b7b6 100644
--- a/platform/iphone/in_app_store.mm
+++ b/platform/iphone/in_app_store.mm
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp
index 93f4d00e05..ec62cb5c26 100644
--- a/platform/iphone/os_iphone.cpp
+++ b/platform/iphone/os_iphone.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -226,6 +226,8 @@ void OSIPhone::mouse_button(int p_idx, int p_x, int p_y, bool p_pressed, bool p_
queue_event(ev);
};
+ mouse_list.pressed[p_idx] = p_pressed;
+
if (p_use_as_mouse) {
InputEvent ev;
@@ -240,13 +242,13 @@ void OSIPhone::mouse_button(int p_idx, int p_x, int p_y, bool p_pressed, bool p_
ev.mouse_button.x = ev.mouse_button.global_x = p_x;
ev.mouse_button.y = ev.mouse_button.global_y = p_y;
+ //mouse_list.pressed[p_idx] = p_pressed;
+
input->set_mouse_pos(Point2(ev.mouse_motion.x,ev.mouse_motion.y));
ev.mouse_button.button_index = BUTTON_LEFT;
ev.mouse_button.doubleclick = p_doubleclick;
ev.mouse_button.pressed = p_pressed;
- mouse_list.pressed[p_idx] = p_pressed;
-
queue_event(ev);
};
};
@@ -452,6 +454,7 @@ bool OSIPhone::has_virtual_keyboard() const {
extern void _show_keyboard(String p_existing);
extern void _hide_keyboard();
extern Error _shell_open(String p_uri);
+extern void _set_keep_screen_on(bool p_enabled);
void OSIPhone::show_virtual_keyboard(const String& p_existing_text,const Rect2& p_screen_rect) {
_show_keyboard(p_existing_text);
@@ -465,6 +468,10 @@ Error OSIPhone::shell_open(String p_uri) {
return _shell_open(p_uri);
};
+void OSIPhone::set_keep_screen_on(bool p_enabled) {
+ OS::set_keep_screen_on(p_enabled);
+ _set_keep_screen_on(p_enabled);
+};
void OSIPhone::set_cursor_shape(CursorShape p_shape) {
diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h
index 06a67b0cfd..abe797fed1 100644
--- a/platform/iphone/os_iphone.h
+++ b/platform/iphone/os_iphone.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -166,6 +166,8 @@ public:
virtual void set_video_mode(const VideoMode& p_video_mode,int p_screen=0);
virtual VideoMode get_video_mode(int p_screen=0) const;
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const;
+
+ virtual void set_keep_screen_on(bool p_enabled);
virtual bool can_draw() const;
diff --git a/platform/iphone/platform_config.h b/platform/iphone/platform_config.h
index 3cc74099c0..e40f670185 100644
--- a/platform/iphone/platform_config.h
+++ b/platform/iphone/platform_config.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,3 +31,5 @@
#define PLATFORM_REFCOUNT
+
+#define PTHREAD_RENAME_SELF
diff --git a/platform/iphone/rasterizer_iphone.cpp b/platform/iphone/rasterizer_iphone.cpp
index d2a0777af8..29364d091a 100644
--- a/platform/iphone/rasterizer_iphone.cpp
+++ b/platform/iphone/rasterizer_iphone.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/rasterizer_iphone.h b/platform/iphone/rasterizer_iphone.h
index 2a630e597a..add656b190 100644
--- a/platform/iphone/rasterizer_iphone.h
+++ b/platform/iphone/rasterizer_iphone.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/sem_iphone.cpp b/platform/iphone/sem_iphone.cpp
index 36baa40427..e9c54a002e 100644
--- a/platform/iphone/sem_iphone.cpp
+++ b/platform/iphone/sem_iphone.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/sem_iphone.h b/platform/iphone/sem_iphone.h
index 7a57b5dd99..bfeaf244e5 100644
--- a/platform/iphone/sem_iphone.h
+++ b/platform/iphone/sem_iphone.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/view_controller.h b/platform/iphone/view_controller.h
index 0cee2f6fbf..52c8ac9953 100644
--- a/platform/iphone/view_controller.h
+++ b/platform/iphone/view_controller.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/view_controller.mm b/platform/iphone/view_controller.mm
index f98fb7c355..647ded30a7 100644
--- a/platform/iphone/view_controller.mm
+++ b/platform/iphone/view_controller.mm
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/isim/detect.py b/platform/isim/detect.py
index bd0fd2fea3..0adbd9f413 100644
--- a/platform/isim/detect.py
+++ b/platform/isim/detect.py
@@ -21,8 +21,8 @@ def get_opts():
return [
('ISIMPLATFORM', 'name of the iphone platform', 'iPhoneSimulator'),
- ('ISIMPATH', 'the path to iphone toolchain', '/Applications/Xcode.app/Contents/Developer/Platforms/${ISIMPLATFORM}.platform'),
- ('ISIMSDK', 'path to the iphone SDK', '$ISIMPATH/Developer/SDKs/${ISIMPLATFORM}.sdk'),
+ ('ISIMPATH', 'the path to iphone toolchain', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain'),
+ ('ISIMSDK', 'path to the iphone SDK', '/Applications/Xcode.app/Contents/Developer/Platforms/${ISIMPLATFORM}.platform/Developer/SDKs/${ISIMPLATFORM}.sdk'),
('game_center', 'Support for game center', 'yes'),
('store_kit', 'Support for in-app store', 'yes'),
('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'),
@@ -46,9 +46,10 @@ def configure(env):
env['ENV']['PATH'] = env['ISIMPATH']+"/Developer/usr/bin/:"+env['ENV']['PATH']
- env['CC'] = '$ISIMPATH/Developer/usr/bin/gcc'
- env['CXX'] = '$ISIMPATH/Developer/usr/bin/g++'
- env['AR'] = 'ar'
+ env['CC'] = '$ISIMPATH/usr/bin/${ios_triple}clang'
+ env['CXX'] = '$ISIMPATH/usr/bin/${ios_triple}clang++'
+ env['AR'] = '$ISIMPATH/usr/bin/${ios_triple}ar'
+ env['RANLIB'] = '$ISIMPATH/usr/bin/${ios_triple}ranlib'
import string
env['CCFLAGS'] = string.split('-arch i386 -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fasm-blocks -Wall -D__IPHONE_OS_VERSION_MIN_REQUIRED=40100 -isysroot $ISIMSDK -mios-simulator-version-min=4.3 -DCUSTOM_MATRIX_TRANSFORM_H=\\\"build/iphone/matrix4_iphone.h\\\" -DCUSTOM_VECTOR3_TRANSFORM_H=\\\"build/iphone/vector3_iphone.h\\\"')
@@ -97,4 +98,8 @@ def configure(env):
env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate'
env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-fexceptions'])
+ import methods
+ env.Append( BUILDERS = { 'GLSL120' : env.Builder(action = methods.build_legacygl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
+ env.Append( BUILDERS = { 'GLSL' : env.Builder(action = methods.build_glsl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
+ env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
diff --git a/platform/javascript/audio_driver_javascript.cpp b/platform/javascript/audio_driver_javascript.cpp
index cc053cf136..1b949e64f9 100644
--- a/platform/javascript/audio_driver_javascript.cpp
+++ b/platform/javascript/audio_driver_javascript.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/javascript/audio_driver_javascript.h b/platform/javascript/audio_driver_javascript.h
index 0356ca87f9..c674a8566e 100644
--- a/platform/javascript/audio_driver_javascript.h
+++ b/platform/javascript/audio_driver_javascript.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/javascript/audio_server_javascript.cpp b/platform/javascript/audio_server_javascript.cpp
index a2c6740eaf..fbd5d2e1c0 100644
--- a/platform/javascript/audio_server_javascript.cpp
+++ b/platform/javascript/audio_server_javascript.cpp
@@ -33,7 +33,7 @@ void AudioServerJavascript::sample_set_description(RID p_sample, const String& p
}
-String AudioServerJavascript::sample_get_description(RID p_sample, const String& p_description) const{
+String AudioServerJavascript::sample_get_description(RID p_sample) const{
return String();
}
diff --git a/platform/javascript/audio_server_javascript.h b/platform/javascript/audio_server_javascript.h
index 450237d324..1dc90c48ee 100644
--- a/platform/javascript/audio_server_javascript.h
+++ b/platform/javascript/audio_server_javascript.h
@@ -95,7 +95,7 @@ public:
virtual RID sample_create(SampleFormat p_format, bool p_stereo, int p_length);
virtual void sample_set_description(RID p_sample, const String& p_description);
- virtual String sample_get_description(RID p_sample, const String& p_description) const;
+ virtual String sample_get_description(RID p_sample) const;
virtual SampleFormat sample_get_format(RID p_sample) const;
virtual bool sample_is_stereo(RID p_sample) const;
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index ec21bf6ee4..0a6c8b1457 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -80,7 +80,7 @@ def configure(env):
env.opus_fixed_point="yes"
env.Append(CPPFLAGS=["-fno-exceptions",'-DNO_SAFE_CAST','-fno-rtti'])
- env.Append(CPPFLAGS=['-DJAVASCRIPT_ENABLED', '-DUNIX_ENABLED', '-DNO_FCNTL','-DMPC_FIXED_POINT','-DTYPED_METHOD_BIND','-DNO_THREADS'])
+ env.Append(CPPFLAGS=['-DJAVASCRIPT_ENABLED', '-DUNIX_ENABLED', '-DPTHREAD_NO_RENAME', '-DNO_FCNTL','-DMPC_FIXED_POINT','-DTYPED_METHOD_BIND','-DNO_THREADS'])
env.Append(CPPFLAGS=['-DGLES2_ENABLED'])
env.Append(CPPFLAGS=['-DGLES_NO_CLIENT_ARRAYS'])
env.Append(CPPFLAGS=['-s','ASM_JS=1'])
@@ -98,3 +98,10 @@ def configure(env):
#print "CCCOM is:", env.subst('$CCCOM')
#print "P: ", env['p'], " Platofrm: ", env['platform']
+
+ import methods
+
+ env.Append( BUILDERS = { 'GLSL120' : env.Builder(action = methods.build_legacygl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
+ env.Append( BUILDERS = { 'GLSL' : env.Builder(action = methods.build_glsl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
+ env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
+ #env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } )
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index 9e2595f4a1..e055aeea56 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -50,6 +50,7 @@ class EditorExportPlatformJavaScript : public EditorExportPlatform {
PACK_MULTIPLE_FILES
};
+ void _fix_html(Vector<uint8_t>& p_html, const String& p_name, bool p_debug);
PackMode pack_mode;
@@ -58,6 +59,12 @@ class EditorExportPlatformJavaScript : public EditorExportPlatform {
int max_memory;
int version_code;
+ String html_title;
+ String html_head_include;
+ String html_font_family;
+ String html_style_include;
+ bool html_controls_enabled;
+
Ref<ImageTexture> logo;
protected:
@@ -101,6 +108,16 @@ bool EditorExportPlatformJavaScript::_set(const StringName& p_name, const Varian
show_run=p_value;
else if (n=="options/memory_size")
max_memory=p_value;
+ else if (n=="html/title")
+ html_title=p_value;
+ else if (n=="html/head_include")
+ html_head_include=p_value;
+ else if (n=="html/font_family")
+ html_font_family=p_value;
+ else if (n=="html/style_include")
+ html_style_include=p_value;
+ else if (n=="html/controls_enabled")
+ html_controls_enabled=p_value;
else
return false;
@@ -119,6 +136,16 @@ bool EditorExportPlatformJavaScript::_get(const StringName& p_name,Variant &r_re
r_ret=show_run;
else if (n=="options/memory_size")
r_ret=max_memory;
+ else if (n=="html/title")
+ r_ret=html_title;
+ else if (n=="html/head_include")
+ r_ret=html_head_include;
+ else if (n=="html/font_family")
+ r_ret=html_font_family;
+ else if (n=="html/style_include")
+ r_ret=html_style_include;
+ else if (n=="html/controls_enabled")
+ r_ret=html_controls_enabled;
else
return false;
@@ -130,39 +157,47 @@ void EditorExportPlatformJavaScript::_get_property_list( List<PropertyInfo> *p_l
p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE,"zip"));
p_list->push_back( PropertyInfo( Variant::INT, "options/memory_size",PROPERTY_HINT_ENUM,"32mb,64mb,128mb,256mb,512mb,1024mb"));
p_list->push_back( PropertyInfo( Variant::BOOL, "browser/enable_run"));
+ p_list->push_back( PropertyInfo( Variant::STRING, "html/title"));
+ p_list->push_back( PropertyInfo( Variant::STRING, "html/head_include",PROPERTY_HINT_MULTILINE_TEXT));
+ p_list->push_back( PropertyInfo( Variant::STRING, "html/font_family"));
+ p_list->push_back( PropertyInfo( Variant::STRING, "html/style_include",PROPERTY_HINT_MULTILINE_TEXT));
+ p_list->push_back( PropertyInfo( Variant::BOOL, "html/controls_enabled"));
+
//p_list->push_back( PropertyInfo( Variant::INT, "resources/pack_mode", PROPERTY_HINT_ENUM,"Copy,Single Exec.,Pack (.pck),Bundles (Optical)"));
}
-static void _fix_html(Vector<uint8_t>& html,const String& name,int max_memory) {
+void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t>& p_html, const String& p_name, bool p_debug) {
String str;
String strnew;
- str.parse_utf8((const char*)html.ptr(),html.size());
+ str.parse_utf8((const char*)p_html.ptr(),p_html.size());
Vector<String> lines=str.split("\n");
for(int i=0;i<lines.size();i++) {
- if (lines[i].find("$GODOTTMEM")!=-1) {
-
- strnew+=lines[i].replace("$GODOTTMEM",itos(max_memory*1024*1024))+"\n";
- } else if (lines[i].find("$GODOTFS")!=-1) {
- strnew+=lines[i].replace("$GODOTFS",name+"fs.js")+"\n";
- } else if (lines[i].find("$GODOTMEM")!=-1) {
- strnew+=lines[i].replace("$GODOTMEM",name+".mem")+"\n";
- } else if (lines[i].find("$GODOTJS")!=-1) {
- strnew+=lines[i].replace("$GODOTJS",name+".js")+"\n";
- } else {
- strnew+=lines[i]+"\n";
- }
+ String current_line = lines[i];
+ current_line = current_line.replace("$GODOT_TMEM",itos((1<<(max_memory+5))*1024*1024));
+ current_line = current_line.replace("$GODOT_FS",p_name+"fs.js");
+ current_line = current_line.replace("$GODOT_MEM",p_name+".mem");
+ current_line = current_line.replace("$GODOT_JS",p_name+".js");
+ current_line = current_line.replace("$GODOT_CANVAS_WIDTH",Globals::get_singleton()->get("display/width"));
+ current_line = current_line.replace("$GODOT_CANVAS_HEIGHT",Globals::get_singleton()->get("display/height"));
+ current_line = current_line.replace("$GODOT_HEAD_TITLE",!html_title.empty()?html_title:(String) Globals::get_singleton()->get("application/name"));
+ current_line = current_line.replace("$GODOT_HEAD_INCLUDE",html_head_include);
+ current_line = current_line.replace("$GODOT_STYLE_FONT_FAMILY",html_font_family);
+ current_line = current_line.replace("$GODOT_STYLE_INCLUDE",html_style_include);
+ current_line = current_line.replace("$GODOT_CONTROLS_ENABLED",html_controls_enabled?"true":"false");
+ current_line = current_line.replace("$GODOT_DEBUG_ENABLED",p_debug?"true":"false");
+ strnew += current_line+"\n";
}
CharString cs = strnew.utf8();
- html.resize(cs.size());
+ p_html.resize(cs.size());
for(int i=9;i<cs.size();i++) {
- html[i]=cs[i];
+ p_html[i]=cs[i];
}
}
@@ -205,18 +240,24 @@ Error EditorExportPlatformJavaScript::export_project(const String& p_path, bool
EditorProgress ep("export","Exporting for javascript",104);
- String template_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
-
- if (p_debug) {
-
- src_template=custom_debug_package!=""?custom_debug_package:template_path+"javascript_debug.zip";
- } else {
-
- src_template=custom_release_package!=""?custom_release_package:template_path+"javascript_release.zip";
+ if (p_debug)
+ src_template=custom_debug_package;
+ else
+ src_template=custom_release_package;
+ if (src_template=="") {
+ String err;
+ if (p_debug) {
+ src_template=find_export_template("javascript_debug.zip", &err);
+ } else {
+ src_template=find_export_template("javascript_release.zip", &err);
+ }
+ if (src_template=="") {
+ EditorNode::add_io_error(err);
+ return ERR_FILE_NOT_FOUND;
+ }
}
-
FileAccess *src_f=NULL;
zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
@@ -268,7 +309,7 @@ Error EditorExportPlatformJavaScript::export_project(const String& p_path, bool
if (file=="godot.html") {
- _fix_html(data,p_path.get_file().basename(),1<<(max_memory+5));
+ _fix_html(data,p_path.get_file().basename(), p_debug);
file=p_path.get_file();
}
if (file=="godotfs.js") {
@@ -329,6 +370,9 @@ EditorExportPlatformJavaScript::EditorExportPlatformJavaScript() {
logo = Ref<ImageTexture>( memnew( ImageTexture ));
logo->create_from_image(img);
max_memory=3;
+ html_title="";
+ html_font_family="arial,sans-serif";
+ html_controls_enabled=true;
pack_mode=PACK_SINGLE_FILE;
}
@@ -337,9 +381,8 @@ bool EditorExportPlatformJavaScript::can_export(String *r_error) const {
bool valid=true;
String err;
- String exe_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
- if (!FileAccess::exists(exe_path+"javascript_debug.zip") || !FileAccess::exists(exe_path+"javascript_release.zip")) {
+ if (!exists_export_template("javascript_debug.zip") || !exists_export_template("javascript_release.zip")) {
valid=false;
err+="No export templates found.\nDownload and install export templates.\n";
}
diff --git a/platform/javascript/export/export.h b/platform/javascript/export/export.h
index a126675983..2105141e58 100644
--- a/platform/javascript/export/export.h
+++ b/platform/javascript/export/export.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp
index fb87dc848e..e66110b655 100644
--- a/platform/javascript/javascript_main.cpp
+++ b/platform/javascript/javascript_main.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index ae97bf990b..562733ab89 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -76,6 +76,14 @@ void OS_JavaScript::set_opengl_extensions(const char* p_gl_extensions) {
gl_extensions=p_gl_extensions;
}
+static EM_BOOL joy_callback_func(int p_type, const EmscriptenGamepadEvent *p_event, void *p_user) {
+ OS_JavaScript *os = (OS_JavaScript*) OS::get_singleton();
+ if (os) {
+ return os->joy_connection_changed(p_type, p_event);
+ }
+ return false;
+}
+
void OS_JavaScript::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) {
print_line("Init OS");
@@ -142,6 +150,8 @@ void OS_JavaScript::initialize(const VideoMode& p_desired,int p_video_driver,int
input = memnew( InputDefault );
+ emscripten_set_gamepadconnected_callback(NULL, true, &joy_callback_func);
+ emscripten_set_gamepaddisconnected_callback(NULL, true, &joy_callback_func);
}
void OS_JavaScript::set_main_loop( MainLoop * p_main_loop ) {
@@ -296,7 +306,7 @@ bool OS_JavaScript::main_loop_iterate() {
}
-
+ process_joysticks();
return Main::iteration();
}
@@ -605,6 +615,62 @@ void OS_JavaScript::_close_notification_funcs(const String& p_file,int p_flags)
}
}
+void OS_JavaScript::process_joysticks() {
+
+ int joy_count = emscripten_get_num_gamepads();
+ for (int i = 0; i < joy_count; i++) {
+ EmscriptenGamepadEvent state;
+ emscripten_get_gamepad_status(i, &state);
+ if (state.connected) {
+
+ int num_buttons = MIN(state.numButtons, 18);
+ int num_axes = MIN(state.numAxes, 8);
+ for (int j = 0; j < num_buttons; j++) {
+
+ float value = state.analogButton[j];
+ if (String(state.mapping) == "standard" && (j == 6 || j == 7)) {
+ InputDefault::JoyAxis jx;
+ jx.min = 0;
+ jx.value = value;
+ last_id = input->joy_axis(last_id, i, j, jx);
+ }
+ else {
+ last_id = input->joy_button(last_id, i, j, value);
+ }
+ }
+ for (int j = 0; j < num_axes; j++) {
+
+ InputDefault::JoyAxis jx;
+ jx.min = -1;
+ jx.value = state.axis[j];
+ last_id = input->joy_axis(last_id, i, j, jx);
+ }
+ }
+ }
+}
+
+bool OS_JavaScript::joy_connection_changed(int p_type, const EmscriptenGamepadEvent *p_event) {
+ if (p_type == EMSCRIPTEN_EVENT_GAMEPADCONNECTED) {
+
+ String guid = "";
+ if (String(p_event->mapping) == "standard")
+ guid = "Default HTML5 Gamepad";
+ input->joy_connection_changed(p_event->index, true, String(p_event->id), guid);
+ }
+ else {
+ input->joy_connection_changed(p_event->index, false, "");
+ }
+ return true;
+}
+
+bool OS_JavaScript::is_joy_known(int p_device) {
+ return input->is_joy_mapped(p_device);
+}
+
+String OS_JavaScript::get_joy_guid(int p_device) const {
+ return input->get_joy_guid_remapped(p_device);
+}
+
OS_JavaScript::OS_JavaScript(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func) {
diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h
index 1e925fb8df..ec3a6cf911 100644
--- a/platform/javascript/os_javascript.h
+++ b/platform/javascript/os_javascript.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -41,6 +41,7 @@
#include "audio_server_javascript.h"
#include "audio_driver_javascript.h"
#include "main/input_default.h"
+#include "emscripten/html5.h"
typedef void (*GFXInitFunc)(void *ud,bool gl2,int w, int h, bool fs);
typedef int (*OpenURIFunc)(const String&);
@@ -90,6 +91,8 @@ private:
static void _close_notification_funcs(const String& p_file,int p_flags);
+ void process_joysticks();
+
public:
// functions used by main to initialize/deintialize the OS
@@ -163,6 +166,11 @@ public:
void process_accelerometer(const Vector3& p_accelerometer);
void process_touch(int p_what,int p_pointer, const Vector<TouchPos>& p_points);
void push_input(const InputEvent& p_ev);
+
+ virtual bool is_joy_known(int p_device);
+ virtual String get_joy_guid(int p_device) const;
+ bool joy_connection_changed(int p_type, const EmscriptenGamepadEvent *p_event);
+
OS_JavaScript(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func);
~OS_JavaScript();
diff --git a/platform/javascript/platform_config.h b/platform/javascript/platform_config.h
index 1e7d066bb9..143f16c1fa 100644
--- a/platform/javascript/platform_config.h
+++ b/platform/javascript/platform_config.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/nacl/audio_driver_nacl.cpp b/platform/nacl/audio_driver_nacl.cpp
index 27197ad2b2..dac9521487 100644
--- a/platform/nacl/audio_driver_nacl.cpp
+++ b/platform/nacl/audio_driver_nacl.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/nacl/audio_driver_nacl.h b/platform/nacl/audio_driver_nacl.h
index be5a4cba67..d14e60717a 100644
--- a/platform/nacl/audio_driver_nacl.h
+++ b/platform/nacl/audio_driver_nacl.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/nacl/context_gl_nacl.cpp b/platform/nacl/context_gl_nacl.cpp
index 8ba3fe49d2..ce2f25b69f 100644
--- a/platform/nacl/context_gl_nacl.cpp
+++ b/platform/nacl/context_gl_nacl.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/nacl/context_gl_nacl.h b/platform/nacl/context_gl_nacl.h
index 18da070e35..82b9ba0775 100644
--- a/platform/nacl/context_gl_nacl.h
+++ b/platform/nacl/context_gl_nacl.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/nacl/geturl_handler.cpp b/platform/nacl/geturl_handler.cpp
index 40583891a9..6be82f3f5a 100644
--- a/platform/nacl/geturl_handler.cpp
+++ b/platform/nacl/geturl_handler.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/nacl/geturl_handler.h b/platform/nacl/geturl_handler.h
index 901210febd..c310ed942d 100644
--- a/platform/nacl/geturl_handler.h
+++ b/platform/nacl/geturl_handler.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/nacl/godot_module.cpp b/platform/nacl/godot_module.cpp
index 490edf62cd..5c558f5ece 100644
--- a/platform/nacl/godot_module.cpp
+++ b/platform/nacl/godot_module.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/nacl/godot_nacl.cpp b/platform/nacl/godot_nacl.cpp
index 7302a0b5d5..d8447390c1 100644
--- a/platform/nacl/godot_nacl.cpp
+++ b/platform/nacl/godot_nacl.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/nacl/nacl_keycodes.h b/platform/nacl/nacl_keycodes.h
index b8ff5874cf..45dba075db 100644
--- a/platform/nacl/nacl_keycodes.h
+++ b/platform/nacl/nacl_keycodes.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/nacl/opengl_context.cpp b/platform/nacl/opengl_context.cpp
index 285e8df9ce..ae72e4ddbb 100644
--- a/platform/nacl/opengl_context.cpp
+++ b/platform/nacl/opengl_context.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/nacl/opengl_context.h b/platform/nacl/opengl_context.h
index 6c73873f4b..f03a4b3e53 100644
--- a/platform/nacl/opengl_context.h
+++ b/platform/nacl/opengl_context.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/nacl/os_nacl.cpp b/platform/nacl/os_nacl.cpp
index b282209d72..de6a15525b 100644
--- a/platform/nacl/os_nacl.cpp
+++ b/platform/nacl/os_nacl.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -144,8 +144,7 @@ void OSNacl::finalize_core() {
if (mempool_dynamic)
memdelete( mempool_dynamic );
- if (mempool_static)
- delete mempool_static;
+ delete mempool_static;
};
diff --git a/platform/nacl/os_nacl.h b/platform/nacl/os_nacl.h
index e033abb68d..689aa07e20 100644
--- a/platform/nacl/os_nacl.h
+++ b/platform/nacl/os_nacl.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/nacl/pepper_main.cpp b/platform/nacl/pepper_main.cpp
index 406d84419b..fe10db19a9 100644
--- a/platform/nacl/pepper_main.cpp
+++ b/platform/nacl/pepper_main.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/nacl/platform_config.h b/platform/nacl/platform_config.h
index 1e7d066bb9..143f16c1fa 100644
--- a/platform/nacl/platform_config.h
+++ b/platform/nacl/platform_config.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/osx/SCsub b/platform/osx/SCsub
index 4904636afd..3785eb3fb3 100644
--- a/platform/osx/SCsub
+++ b/platform/osx/SCsub
@@ -6,6 +6,7 @@ files = [
'audio_driver_osx.cpp',
'sem_osx.cpp',
# 'context_gl_osx.cpp',
+ 'dir_access_osx.mm',
]
env.Program('#bin/godot',files)
diff --git a/platform/osx/audio_driver_osx.cpp b/platform/osx/audio_driver_osx.cpp
index 6904b7a398..a74303e6c2 100644
--- a/platform/osx/audio_driver_osx.cpp
+++ b/platform/osx/audio_driver_osx.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/osx/audio_driver_osx.h b/platform/osx/audio_driver_osx.h
index bcf6b23864..92893c64dc 100644
--- a/platform/osx/audio_driver_osx.h
+++ b/platform/osx/audio_driver_osx.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/osx/context_gl_osx.cpp b/platform/osx/context_gl_osx.cpp
index f856e1e4a8..df1c14c643 100644
--- a/platform/osx/context_gl_osx.cpp
+++ b/platform/osx/context_gl_osx.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/osx/context_gl_osx.h b/platform/osx/context_gl_osx.h
index 770ec74737..4a94c20c00 100644
--- a/platform/osx/context_gl_osx.h
+++ b/platform/osx/context_gl_osx.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/osx/dir_access_osx.h b/platform/osx/dir_access_osx.h
new file mode 100644
index 0000000000..caeeaf643c
--- /dev/null
+++ b/platform/osx/dir_access_osx.h
@@ -0,0 +1,92 @@
+/*************************************************************************/
+/* dir_access_unix.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 Juan 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 DIR_ACCESS_OSX_H
+#define DIR_ACCESS_OSX_H
+
+#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include "os/dir_access.h"
+
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class DirAccessOSX : public DirAccess {
+
+ DIR *dir_stream;
+
+ static DirAccess *create_fs();
+
+ 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(); ///<
+
+ virtual int get_drive_count();
+ virtual String get_drive(int p_drive);
+
+ virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
+ virtual String get_current_dir(); ///< return current dir location
+ virtual Error make_dir(String p_dir);
+
+ virtual bool file_exists(String p_file);
+ virtual bool dir_exists(String p_dir);
+
+ virtual uint64_t get_modified_time(String p_file);
+
+
+
+ virtual Error rename(String p_from, String p_to);
+ virtual Error remove(String p_name);
+
+ virtual size_t get_space_left();
+
+
+ DirAccessOSX();
+ ~DirAccessOSX();
+
+};
+
+
+
+#endif //UNIX ENABLED
+#endif
diff --git a/platform/osx/dir_access_osx.mm b/platform/osx/dir_access_osx.mm
new file mode 100644
index 0000000000..e345bea60a
--- /dev/null
+++ b/platform/osx/dir_access_osx.mm
@@ -0,0 +1,350 @@
+/*************************************************************************/
+/* dir_access_unix.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 Juan 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 "dir_access_osx.h"
+
+#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+
+#ifndef ANDROID_ENABLED
+#include <sys/statvfs.h>
+#endif
+
+#include <stdio.h>
+#include "os/memory.h"
+#include "print_string.h"
+#include <errno.h>
+
+#include <Foundation/NSString.h>
+
+DirAccess *DirAccessOSX::create_fs() {
+
+ return memnew( DirAccessOSX );
+}
+
+bool DirAccessOSX::list_dir_begin() {
+
+ list_dir_end(); //close any previous dir opening!
+
+
+// char real_current_dir_name[2048]; //is this enough?!
+ //getcwd(real_current_dir_name,2048);
+ //chdir(curent_path.utf8().get_data());
+ dir_stream = opendir(current_dir.utf8().get_data());
+ //chdir(real_current_dir_name);
+ if (!dir_stream)
+ return true; //error!
+
+ return false;
+}
+
+bool DirAccessOSX::file_exists(String p_file) {
+
+ GLOBAL_LOCK_FUNCTION
+
+
+ if (p_file.is_rel_path())
+ p_file=current_dir+"/"+p_file;
+ else
+ p_file=fix_path(p_file);
+
+ struct stat flags;
+ bool success = (stat(p_file.utf8().get_data(),&flags)==0);
+
+ if (success && S_ISDIR(flags.st_mode)) {
+ success=false;
+ }
+
+ return success;
+
+}
+
+bool DirAccessOSX::dir_exists(String p_dir) {
+
+ GLOBAL_LOCK_FUNCTION
+
+
+ if (p_dir.is_rel_path())
+ p_dir=get_current_dir().plus_file(p_dir);
+ else
+ p_dir=fix_path(p_dir);
+
+ struct stat flags;
+ bool success = (stat(p_dir.utf8().get_data(),&flags)==0);
+
+ if (success && S_ISDIR(flags.st_mode))
+ return true;
+
+ return false;
+
+}
+
+uint64_t DirAccessOSX::get_modified_time(String p_file) {
+
+ if (p_file.is_rel_path())
+ p_file=current_dir+"/"+p_file;
+ else
+ p_file=fix_path(p_file);
+
+ struct stat flags;
+ bool success = (stat(p_file.utf8().get_data(),&flags)==0);
+
+ if (success) {
+ return flags.st_mtime;
+ } else {
+
+ ERR_FAIL_V(0);
+ };
+ return 0;
+};
+
+
+String DirAccessOSX::get_next() {
+
+ if (!dir_stream)
+ return "";
+ dirent *entry;
+
+ entry=readdir(dir_stream);
+
+ if (entry==NULL) {
+
+ list_dir_end();
+ return "";
+ }
+
+ //typedef struct stat Stat;
+ struct stat flags;
+
+ String fname;
+ NSString* nsstr = [[NSString stringWithUTF8String: entry->d_name] precomposedStringWithCanonicalMapping];
+
+ fname.parse_utf8([nsstr UTF8String]);
+
+ //[nsstr autorelease];
+
+ String f=current_dir+"/"+fname;
+
+ if (stat(f.utf8().get_data(),&flags)==0) {
+
+ if (S_ISDIR(flags.st_mode)) {
+
+ _cisdir=true;
+
+ } else {
+
+ _cisdir=false;
+ }
+
+ } else {
+
+ _cisdir=false;
+
+ }
+
+ _cishidden=(fname!="." && fname!=".." && fname.begins_with("."));
+
+
+
+ return fname;
+
+}
+
+bool DirAccessOSX::current_is_dir() const {
+
+ return _cisdir;
+}
+
+bool DirAccessOSX::current_is_hidden() const {
+
+ return _cishidden;
+}
+
+
+void DirAccessOSX::list_dir_end() {
+
+ if (dir_stream)
+ closedir(dir_stream);
+ dir_stream=0;
+ _cisdir=false;
+}
+
+int DirAccessOSX::get_drive_count() {
+
+ return 0;
+}
+String DirAccessOSX::get_drive(int p_drive) {
+
+ return "";
+}
+
+Error DirAccessOSX::make_dir(String p_dir) {
+
+ GLOBAL_LOCK_FUNCTION
+
+ p_dir=fix_path(p_dir);
+
+ char real_current_dir_name[2048];
+ getcwd(real_current_dir_name,2048);
+ chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants
+
+ bool success=(mkdir(p_dir.utf8().get_data(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)==0);
+ int err = errno;
+
+ chdir(real_current_dir_name);
+
+ if (success) {
+ return OK;
+ };
+
+ if (err == EEXIST) {
+ return ERR_ALREADY_EXISTS;
+ };
+
+ return ERR_CANT_CREATE;
+}
+
+
+Error DirAccessOSX::change_dir(String p_dir) {
+
+ GLOBAL_LOCK_FUNCTION
+ p_dir=fix_path(p_dir);
+
+
+ char real_current_dir_name[2048];
+ getcwd(real_current_dir_name,2048);
+ String prev_dir;
+ if (prev_dir.parse_utf8(real_current_dir_name))
+ prev_dir=real_current_dir_name; //no utf8, maybe latin?
+
+ chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants
+ bool worked=(chdir(p_dir.utf8().get_data())==0); // we can only give this utf8
+#ifndef IPHONE_ENABLED
+ String base = _get_root_path();
+ if (base!="") {
+
+ getcwd(real_current_dir_name,2048);
+ String new_dir;
+ new_dir.parse_utf8(real_current_dir_name);
+ if (!new_dir.begins_with(base))
+ worked=false;
+ }
+#endif
+ if (worked) {
+
+ getcwd(real_current_dir_name,2048);
+ if (current_dir.parse_utf8(real_current_dir_name))
+ current_dir=real_current_dir_name; //no utf8, maybe latin?
+ }
+
+ chdir(prev_dir.utf8().get_data());
+ return worked?OK:ERR_INVALID_PARAMETER;
+
+}
+
+String DirAccessOSX::get_current_dir() {
+
+ String base = _get_root_path();
+ if (base!="") {
+
+ String bd = current_dir.replace_first(base,"");
+ if (bd.begins_with("/"))
+ return _get_root_string()+bd.substr(1,bd.length());
+ else
+ return _get_root_string()+bd;
+
+ }
+ return current_dir;
+}
+
+Error DirAccessOSX::rename(String p_path,String p_new_path) {
+
+ if (p_path.is_rel_path())
+ p_path=get_current_dir().plus_file(p_path);
+ else
+ p_path=fix_path(p_path);
+
+ if (p_new_path.is_rel_path())
+ p_new_path=get_current_dir().plus_file(p_new_path);
+ else
+ p_new_path=fix_path(p_new_path);
+
+ return ::rename(p_path.utf8().get_data(),p_new_path.utf8().get_data())==0?OK:FAILED;
+}
+Error DirAccessOSX::remove(String p_path) {
+
+ p_path=fix_path(p_path);
+
+ struct stat flags;
+ if ((stat(p_path.utf8().get_data(),&flags)!=0))
+ return FAILED;
+
+ if (S_ISDIR(flags.st_mode))
+ return ::rmdir(p_path.utf8().get_data())==0?OK:FAILED;
+ else
+ return ::unlink(p_path.utf8().get_data())==0?OK:FAILED;
+}
+
+
+size_t DirAccessOSX::get_space_left() {
+
+#ifndef NO_STATVFS
+ struct statvfs vfs;
+ if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) {
+
+ return -1;
+ };
+
+ return vfs.f_bfree * vfs.f_bsize;
+#else
+#warning THIS IS BROKEN
+ return 0;
+#endif
+};
+
+
+
+DirAccessOSX::DirAccessOSX() {
+
+ dir_stream=0;
+ current_dir=".";
+ _cisdir=false;
+
+ /* determine drive count */
+
+ change_dir(current_dir);
+
+}
+
+
+DirAccessOSX::~DirAccessOSX() {
+
+ list_dir_end();
+}
+
+
+#endif //posix_enabled
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 79ee91bc61..0bece6ec76 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -251,15 +251,19 @@ Error EditorExportPlatformOSX::export_project(const String& p_path, bool p_debug
EditorProgress ep("export","Exporting for OSX",104);
- String pkg_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/osx.zip";
-
- if (p_debug) {
-
- src_pkg=custom_debug_package!=""?custom_debug_package:pkg_path;
- } else {
-
- src_pkg=custom_release_package!=""?custom_release_package:pkg_path;
+ if (p_debug)
+ src_pkg=custom_debug_package;
+ else
+ src_pkg=custom_release_package;
+
+ if (src_pkg=="") {
+ String err;
+ src_pkg=find_export_template("osx.zip", &err);
+ if (src_pkg=="") {
+ EditorNode::add_io_error(err);
+ return ERR_FILE_NOT_FOUND;
+ }
}
@@ -464,9 +468,8 @@ bool EditorExportPlatformOSX::can_export(String *r_error) const {
bool valid=true;
String err;
- String exe_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
- if (!FileAccess::exists(exe_path+"osx.zip")) {
+ if (!exists_export_template("osx.zip")) {
valid=false;
err+="No export templates found.\nDownload and install export templates.\n";
}
diff --git a/platform/osx/godot_main_osx.mm b/platform/osx/godot_main_osx.mm
index 92fa6ddbc2..391fd1f74a 100644
--- a/platform/osx/godot_main_osx.mm
+++ b/platform/osx/godot_main_osx.mm
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/osx/godot_osx.h b/platform/osx/godot_osx.h
index 270ba9966f..de363d8483 100644
--- a/platform/osx/godot_osx.h
+++ b/platform/osx/godot_osx.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/osx/godot_osx.mm b/platform/osx/godot_osx.mm
index 39119393ff..0c32016216 100644
--- a/platform/osx/godot_osx.mm
+++ b/platform/osx/godot_osx.mm
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index e8277688ac..a1fd34def7 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 4990d04ab6..2690ee3ba9 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -47,6 +47,7 @@
#include "servers/visual/visual_server_wrap_mt.h"
#include "main/main.h"
#include "os/keyboard.h"
+#include "dir_access_osx.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -849,6 +850,11 @@ OS::VideoMode OS_OSX::get_default_video_mode() const {
void OS_OSX::initialize_core() {
OS_Unix::initialize_core();
+
+ DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_RESOURCES);
+ DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_USERDATA);
+ DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_FILESYSTEM);
+
SemaphoreOSX::make_default();
}
@@ -1050,6 +1056,33 @@ void OS_OSX::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
void OS_OSX::finalize() {
CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), NULL, kTISNotifySelectedKeyboardInputSourceChanged, NULL);
+ delete_main_loop();
+
+ spatial_sound_server->finish();
+ memdelete(spatial_sound_server);
+ spatial_sound_2d_server->finish();
+ memdelete(spatial_sound_2d_server);
+
+
+ memdelete(input);
+
+ memdelete(sample_manager);
+
+ audio_server->finish();
+ memdelete(audio_server);
+
+ visual_server->finish();
+ memdelete(visual_server);
+ memdelete(rasterizer);
+
+ physics_server->finish();
+ memdelete(physics_server);
+
+ physics_2d_server->finish();
+ memdelete(physics_2d_server);
+
+ screens.clear();
+
}
@@ -1062,6 +1095,8 @@ void OS_OSX::set_main_loop( MainLoop * p_main_loop ) {
void OS_OSX::delete_main_loop() {
+ if (!main_loop)
+ return;
memdelete(main_loop);
main_loop=NULL;
}
diff --git a/platform/osx/platform_config.h b/platform/osx/platform_config.h
index 285d8d0c02..085f13df73 100644
--- a/platform/osx/platform_config.h
+++ b/platform/osx/platform_config.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,3 +29,4 @@
#include <alloca.h>
#define GLES2_INCLUDE_H "gl_context/glew.h"
#define GLES1_INCLUDE_H "gl_context/glew.h"
+#define PTHREAD_RENAME_SELF
diff --git a/platform/osx/sem_osx.cpp b/platform/osx/sem_osx.cpp
index be70bedf84..6909097fec 100644
--- a/platform/osx/sem_osx.cpp
+++ b/platform/osx/sem_osx.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/osx/sem_osx.h b/platform/osx/sem_osx.h
index 65bed7397f..ec5ddac4e0 100644
--- a/platform/osx/sem_osx.h
+++ b/platform/osx/sem_osx.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/server/godot_server.cpp b/platform/server/godot_server.cpp
index 41e48302c4..db6c13633d 100644
--- a/platform/server/godot_server.cpp
+++ b/platform/server/godot_server.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp
index 8b831140d6..f042318f78 100644
--- a/platform/server/os_server.cpp
+++ b/platform/server/os_server.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/server/os_server.h b/platform/server/os_server.h
index b3410f7955..2487c7b3fb 100644
--- a/platform/server/os_server.h
+++ b/platform/server/os_server.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/server/platform_config.h b/platform/server/platform_config.h
index 43dda9e64e..72b10a0fb2 100644
--- a/platform/server/platform_config.h
+++ b/platform/server/platform_config.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/windows/SCsub b/platform/windows/SCsub
index f98c1b01ff..914cee0fa1 100644
--- a/platform/windows/SCsub
+++ b/platform/windows/SCsub
@@ -9,6 +9,7 @@ common_win=[
"tcp_server_winsock.cpp",
"packet_peer_udp_winsock.cpp",
"stream_peer_winsock.cpp",
+ "joystick.cpp",
]
restarget="godot_res"+env["OBJSUFFIX"]
@@ -23,4 +24,4 @@ env.Program('#bin/godot',['godot_win.cpp']+common_win,PROGSUFFIX=env["PROGSUFFIX
if (env['vsproj'])=="yes":
env.vs_srcs = env.vs_srcs + ["platform/windows/godot_win.cpp"]
for x in common_win:
- env.vs_srcs = env.vs_srcs + ["platform/windows/" + x]
+ env.vs_srcs = env.vs_srcs + ["platform/windows/" + str(x)]
diff --git a/platform/windows/context_gl_win.cpp b/platform/windows/context_gl_win.cpp
index 5a9c8edc63..e671101432 100644
--- a/platform/windows/context_gl_win.cpp
+++ b/platform/windows/context_gl_win.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/windows/context_gl_win.h b/platform/windows/context_gl_win.h
index 5397676c8e..af15ad2659 100644
--- a/platform/windows/context_gl_win.h
+++ b/platform/windows/context_gl_win.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/windows/ctxgl_procaddr.cpp b/platform/windows/ctxgl_procaddr.cpp
index 6e5f53eb96..1072197f89 100644
--- a/platform/windows/ctxgl_procaddr.cpp
+++ b/platform/windows/ctxgl_procaddr.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/windows/ctxgl_procaddr.h b/platform/windows/ctxgl_procaddr.h
index 916b480639..2118e20e02 100644
--- a/platform/windows/ctxgl_procaddr.h
+++ b/platform/windows/ctxgl_procaddr.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 4ec4b054db..81247db388 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -170,7 +170,6 @@ def get_flags():
return [
('freetype','builtin'), #use builtin freetype
('openssl','builtin'), #use builtin openssl
- ('theora','no'),
]
def build_res_file( target, source, env ):
@@ -244,7 +243,7 @@ def configure(env):
env.Append(CCFLAGS=['/DGLES2_ENABLED'])
env.Append(CCFLAGS=['/DGLEW_ENABLED'])
- LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI','Shlwapi', 'wsock32', 'shell32','advapi32']
+ LIBS=['winmm','opengl32','dsound','kernel32','ole32','oleaut32','user32','gdi32', 'IPHLPAPI','Shlwapi', 'wsock32', 'shell32','advapi32','dinput8','dxguid']
env.Append(LINKFLAGS=[p+env["LIBSUFFIX"] for p in LIBS])
env.Append(LIBPATH=[os.getenv("WindowsSdkDir")+"/Lib"])
@@ -263,7 +262,7 @@ def configure(env):
env.Append(CCFLAGS=["/I"+DIRECTX_PATH+"/Include"])
env.Append(LIBPATH=[DIRECTX_PATH+"/Lib/x86"])
env['ENV'] = os.environ;
- env["x86_opt_vc"]=True
+ env["x86_opt_vc"]=env["bits"]!="64"
else:
# Workaround for MinGW. See:
@@ -340,7 +339,13 @@ def configure(env):
if (env["target"]=="release"):
- env.Append(CCFLAGS=['-O3','-ffast-math','-fomit-frame-pointer','-msse2'])
+ env.Append(CCFLAGS=['-ffast-math','-fomit-frame-pointer','-msse2'])
+
+ if (env["bits"]=="64"):
+ env.Append(CCFLAGS=['-O3'])
+ else:
+ env.Append(CCFLAGS=['-O2'])
+
env.Append(LINKFLAGS=['-Wl,--subsystem,windows'])
elif (env["target"]=="release_debug"):
@@ -370,7 +375,7 @@ 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','shlwapi','wsock32','kernel32'])
+ env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','iphlpapi','shlwapi','wsock32','kernel32', 'oleaut32', 'dinput8', 'dxguid'])
# if (env["bits"]=="32"):
# env.Append(LIBS=['gcc_s'])
@@ -383,7 +388,7 @@ def configure(env):
#'d3dx9d'
env.Append(CPPFLAGS=['-DMINGW_ENABLED'])
- env.Append(LINKFLAGS=['-g'])
+ #env.Append(LINKFLAGS=['-g'])
# resrc
env['is_mingw']=True
diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp
index 9cfd475091..899edde087 100644
--- a/platform/windows/export/export.cpp
+++ b/platform/windows/export/export.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/windows/godot_res.rc b/platform/windows/godot_res.rc
index f77182f909..5f1e951e0f 100644
--- a/platform/windows/godot_res.rc
+++ b/platform/windows/godot_res.rc
@@ -7,8 +7,8 @@
GODOT_ICON ICON platform/windows/godot.ico
1 VERSIONINFO
-FILEVERSION VERSION_MAJOR,VERSION_MINOR,0
-PRODUCTVERSION VERSION_MAJOR,VERSION_MINOR,0
+FILEVERSION VERSION_MAJOR,VERSION_MINOR,0,0
+PRODUCTVERSION VERSION_MAJOR,VERSION_MINOR,0,0
FILEOS 4
FILETYPE 1
BEGIN
@@ -30,4 +30,4 @@ BEGIN
BEGIN
VALUE "Translation", 0x409, 1200
END
-END \ No newline at end of file
+END
diff --git a/platform/windows/godot_win.cpp b/platform/windows/godot_win.cpp
index fe39051670..fa7989c726 100644
--- a/platform/windows/godot_win.cpp
+++ b/platform/windows/godot_win.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/windows/joystick.cpp b/platform/windows/joystick.cpp
new file mode 100644
index 0000000000..f4fb09820f
--- /dev/null
+++ b/platform/windows/joystick.cpp
@@ -0,0 +1,536 @@
+/*************************************************************************/
+/* joystick.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 Juan 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. */
+/*************************************************************************/
+//author: Andreas Haas <hondres, liugam3@gmail.com>
+#include "joystick.h"
+#include <iostream>
+#include <wbemidl.h>
+#include <oleauto.h>
+
+#ifndef __GNUC__
+#define __builtin_bswap32 _byteswap_ulong
+#endif
+
+DWORD WINAPI _xinput_get_state(DWORD dwUserIndex, XINPUT_STATE* pState) { return ERROR_DEVICE_NOT_CONNECTED; }
+
+joystick_windows::joystick_windows() {
+
+}
+
+joystick_windows::joystick_windows(InputDefault* _input, HWND* hwnd) {
+
+ input = _input;
+ hWnd = hwnd;
+ joystick_count = 0;
+ dinput = NULL;
+ xinput_dll = NULL;
+ xinput_get_state = NULL;
+
+ load_xinput();
+
+ for (int i = 0; i < JOYSTICKS_MAX; i++)
+ attached_joysticks[i] = false;
+
+
+ HRESULT result;
+ result = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&dinput, NULL);
+ if (FAILED(result)) {
+ printf("failed init DINPUT: %ld\n", result);
+ }
+ probe_joysticks();
+}
+
+joystick_windows::~joystick_windows() {
+
+ close_joystick();
+ dinput->Release();
+ unload_xinput();
+}
+
+
+bool joystick_windows::have_device(const GUID &p_guid) {
+
+ for (int i = 0; i < JOYSTICKS_MAX; i++) {
+
+ if (d_joysticks[i].guid == p_guid) {
+
+ d_joysticks[i].confirmed = true;
+ return true;
+ }
+ }
+ return false;
+}
+
+int joystick_windows::check_free_joy_slot() const {
+
+ for (int i = 0; i < JOYSTICKS_MAX; i++) {
+
+ if (!attached_joysticks[i])
+ return i;
+ }
+ return -1;
+}
+
+
+// adapted from SDL2, works a lot better than the MSDN version
+bool joystick_windows::is_xinput_device(const GUID *p_guid) {
+
+ static GUID IID_ValveStreamingGamepad = { MAKELONG(0x28DE, 0x11FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+ static GUID IID_X360WiredGamepad = { MAKELONG(0x045E, 0x02A1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+ static GUID IID_X360WirelessGamepad = { MAKELONG(0x045E, 0x028E), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+
+ if (p_guid == &IID_ValveStreamingGamepad || p_guid == &IID_X360WiredGamepad || p_guid == &IID_X360WirelessGamepad)
+ return true;
+
+ PRAWINPUTDEVICELIST dev_list = NULL;
+ unsigned int dev_list_count = 0;
+
+ if (GetRawInputDeviceList(NULL, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == -1) {
+ return false;
+ }
+ dev_list = (PRAWINPUTDEVICELIST) malloc(sizeof(RAWINPUTDEVICELIST) * dev_list_count);
+ if (!dev_list) return false;
+
+ if (GetRawInputDeviceList(dev_list, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == -1) {
+ free(dev_list);
+ return false;
+ }
+ for (int i = 0; i < dev_list_count; i++) {
+
+ RID_DEVICE_INFO rdi;
+ char dev_name[128];
+ UINT rdiSize = sizeof(rdi);
+ UINT nameSize = sizeof(dev_name);
+
+ rdi.cbSize = rdiSize;
+ if ( (dev_list[i].dwType == RIM_TYPEHID) &&
+ (GetRawInputDeviceInfoA(dev_list[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != (UINT)-1) &&
+ (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == (LONG)p_guid->Data1) &&
+ (GetRawInputDeviceInfoA(dev_list[i].hDevice, RIDI_DEVICENAME, &dev_name, &nameSize) != (UINT)-1) &&
+ (strstr(dev_name, "IG_") != NULL)) {
+
+ free(dev_list);
+ return true;
+ }
+ }
+ free(dev_list);
+ return false;
+}
+
+bool joystick_windows::setup_dinput_joystick(const DIDEVICEINSTANCE* instance) {
+
+ HRESULT hr;
+ int num = check_free_joy_slot();
+
+ if (have_device(instance->guidInstance) || num == -1)
+ return false;
+
+ d_joysticks[joystick_count] = dinput_gamepad();
+ dinput_gamepad* joy = &d_joysticks[joystick_count];
+
+ const DWORD devtype = (instance->dwDevType & 0xFF);
+
+ if ((devtype != DI8DEVTYPE_JOYSTICK) && (devtype != DI8DEVTYPE_GAMEPAD) && (devtype != DI8DEVTYPE_1STPERSON)) {
+ //printf("ignore device %s, type %x\n", instance->tszProductName, devtype);
+ return false;
+ }
+
+ hr = dinput->CreateDevice(instance->guidInstance, &joy->di_joy, NULL);
+
+ if (FAILED(hr)) {
+
+ //std::wcout << "failed to create device: " << instance->tszProductName << std::endl;
+ return false;
+ }
+
+ const GUID &guid = instance->guidProduct;
+ char uid[128];
+ sprintf(uid, "%08lx%04hx%04hx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
+ __builtin_bswap32(guid.Data1), guid.Data2, guid.Data3,
+ guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
+ guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
+
+ id_to_change = joystick_count;
+
+ joy->di_joy->SetDataFormat(&c_dfDIJoystick2);
+ joy->di_joy->SetCooperativeLevel(*hWnd, DISCL_FOREGROUND);
+ joy->di_joy->EnumObjects(objectsCallback, this, NULL);
+ joy->joy_axis.sort();
+
+ joy->guid = instance->guidInstance;
+ input->joy_connection_changed(num, true, instance->tszProductName, uid);
+ joy->attached = true;
+ joy->id = num;
+ attached_joysticks[num] = true;
+ joy->confirmed = true;
+ joystick_count++;
+ return true;
+}
+
+void joystick_windows::setup_joystick_object(const DIDEVICEOBJECTINSTANCE *ob, int p_joy_id) {
+
+ if (ob->dwType & DIDFT_AXIS) {
+
+ HRESULT res;
+ DIPROPRANGE prop_range;
+ DIPROPDWORD dilong;
+ DWORD ofs;
+ if (ob->guidType == GUID_XAxis)
+ ofs = DIJOFS_X;
+ else if (ob->guidType == GUID_YAxis)
+ ofs = DIJOFS_Y;
+ else if (ob->guidType == GUID_ZAxis)
+ ofs = DIJOFS_Z;
+ else if (ob->guidType == GUID_RxAxis)
+ ofs = DIJOFS_RX;
+ else if (ob->guidType == GUID_RyAxis)
+ ofs = DIJOFS_RY;
+ else if (ob->guidType == GUID_RzAxis)
+ ofs = DIJOFS_RZ;
+ else if (ob->guidType == GUID_Slider)
+ ofs = DIJOFS_SLIDER(0);
+ else
+ return;
+ prop_range.diph.dwSize = sizeof(DIPROPRANGE);
+ prop_range.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+ prop_range.diph.dwObj = ob->dwType;
+ prop_range.diph.dwHow = DIPH_BYID;
+ prop_range.lMin = -MAX_JOY_AXIS;
+ prop_range.lMax = +MAX_JOY_AXIS;
+
+ dinput_gamepad &joy = d_joysticks[p_joy_id];
+
+
+ res = IDirectInputDevice8_SetProperty(joy.di_joy, DIPROP_RANGE, &prop_range.diph);
+ if (FAILED(res))
+ return;
+
+ dilong.diph.dwSize = sizeof(dilong);
+ dilong.diph.dwHeaderSize = sizeof(dilong.diph);
+ dilong.diph.dwObj = ob->dwType;
+ dilong.diph.dwHow = DIPH_BYID;
+ dilong.dwData = 0;
+
+ res = IDirectInputDevice8_SetProperty(joy.di_joy, DIPROP_DEADZONE, &dilong.diph);
+ if (FAILED(res))
+ return;
+
+ joy.joy_axis.push_back(ofs);
+ }
+}
+
+BOOL CALLBACK joystick_windows::enumCallback(const DIDEVICEINSTANCE* instance, void* pContext) {
+
+
+ joystick_windows* self = (joystick_windows*)pContext;
+ if (self->is_xinput_device(&instance->guidProduct)) {;
+ return DIENUM_CONTINUE;
+ }
+ self->setup_dinput_joystick(instance);
+ return DIENUM_CONTINUE;
+}
+
+BOOL CALLBACK joystick_windows::objectsCallback(const DIDEVICEOBJECTINSTANCE *instance, void *context) {
+
+ joystick_windows* self = (joystick_windows*)context;
+ self->setup_joystick_object(instance, self->id_to_change);
+
+ return DIENUM_CONTINUE;
+}
+
+void joystick_windows::close_joystick(int id) {
+
+ if (id == -1) {
+
+ for (int i = 0; i < JOYSTICKS_MAX; i++) {
+
+ close_joystick(i);
+ }
+ return;
+ }
+
+ if (!d_joysticks[id].attached) return;
+
+ d_joysticks[id].di_joy->Unacquire();
+ d_joysticks[id].di_joy->Release();
+ d_joysticks[id].attached = false;
+ attached_joysticks[d_joysticks[id].id] = false;
+ d_joysticks[id].guid.Data1 = d_joysticks[id].guid.Data2 = d_joysticks[id].guid.Data3 = 0;
+ input->joy_connection_changed(id, false, "");
+ joystick_count--;
+}
+
+void joystick_windows::probe_joysticks() {
+
+ DWORD dwResult;
+ for (DWORD i = 0; i < XUSER_MAX_COUNT; i++) {
+
+ ZeroMemory(&x_joysticks[i].state, sizeof(XINPUT_STATE));
+
+ dwResult = xinput_get_state(i, &x_joysticks[i].state);
+ if ( dwResult == ERROR_SUCCESS) {
+
+ int id = check_free_joy_slot();
+ if (id != -1 && !x_joysticks[i].attached) {
+
+ x_joysticks[i].attached = true;
+ x_joysticks[i].id = id;
+ attached_joysticks[id] = true;
+ input->joy_connection_changed(id, true, "XInput Gamepad","__XINPUT_DEVICE__");
+ }
+ }
+ else if (x_joysticks[i].attached) {
+
+ x_joysticks[i].attached = false;
+ attached_joysticks[x_joysticks[i].id] = false;
+ input->joy_connection_changed(x_joysticks[i].id, false, "");
+ }
+ }
+
+ for (int i = 0; i < joystick_count; i++) {
+
+ d_joysticks[i].confirmed = false;
+ }
+
+ dinput->EnumDevices(DI8DEVCLASS_GAMECTRL, enumCallback, this, DIEDFL_ATTACHEDONLY);
+
+ for (int i = 0; i < joystick_count; i++) {
+
+ if (!d_joysticks[i].confirmed) {
+
+ close_joystick(i);
+ }
+ }
+}
+
+unsigned int joystick_windows::process_joysticks(unsigned int p_last_id) {
+
+ HRESULT hr;
+
+ for (int i = 0; i < XUSER_MAX_COUNT; i++) {
+
+ xinput_gamepad &joy = x_joysticks[i];
+ if (!joy.attached) {
+ continue;
+ }
+ ZeroMemory(&joy.state, sizeof(XINPUT_STATE));
+
+ xinput_get_state(i, &joy.state);
+ if (joy.state.dwPacketNumber != joy.last_packet) {
+
+ int button_mask = XINPUT_GAMEPAD_DPAD_UP;
+ for (int i = 0; i <= 16; i++) {
+
+ p_last_id = input->joy_button(p_last_id, joy.id, i, joy.state.Gamepad.wButtons & button_mask);
+ button_mask = button_mask * 2;
+ }
+
+ p_last_id = input->joy_axis(p_last_id, joy.id, JOY_AXIS_0, axis_correct(joy.state.Gamepad.sThumbLX, true));
+ p_last_id = input->joy_axis(p_last_id, joy.id, JOY_AXIS_1, axis_correct(joy.state.Gamepad.sThumbLY, true, false, true));
+ p_last_id = input->joy_axis(p_last_id, joy.id, JOY_AXIS_2, axis_correct(joy.state.Gamepad.sThumbRX, true));
+ p_last_id = input->joy_axis(p_last_id, joy.id, JOY_AXIS_3, axis_correct(joy.state.Gamepad.sThumbRY, true, false, true));
+ p_last_id = input->joy_axis(p_last_id, joy.id, JOY_AXIS_4, axis_correct(joy.state.Gamepad.bLeftTrigger, true, true));
+ p_last_id = input->joy_axis(p_last_id, joy.id, JOY_AXIS_5, axis_correct(joy.state.Gamepad.bRightTrigger, true, true));
+ joy.last_packet = joy.state.dwPacketNumber;
+ }
+ }
+
+ for (int i = 0; i < JOYSTICKS_MAX; i++) {
+
+ dinput_gamepad* joy = &d_joysticks[i];
+
+ if (!joy->attached)
+ continue;
+
+ DIJOYSTATE2 js;
+ hr = joy->di_joy->Poll();
+ if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED) {
+ IDirectInputDevice8_Acquire(joy->di_joy);
+ joy->di_joy->Poll();
+ }
+ if (FAILED(hr = joy->di_joy->GetDeviceState(sizeof(DIJOYSTATE2), &js))) {
+
+ //printf("failed to read joy #%d\n", i);
+ continue;
+ }
+
+ p_last_id = post_hat(p_last_id, joy->id, js.rgdwPOV[0]);
+
+ for (int j = 0; j < 128; j++) {
+
+ if (js.rgbButtons[j] & 0x80) {
+
+ if (!joy->last_buttons[j]) {
+
+ p_last_id = input->joy_button(p_last_id, joy->id, j, true);
+ joy->last_buttons[j] = true;
+ }
+ }
+ else {
+
+ if (joy->last_buttons[j]) {
+
+ p_last_id = input->joy_button(p_last_id, joy->id, j, false);
+ joy->last_buttons[j] = false;
+ }
+ }
+ }
+
+ // on mingw, these constants are not constants
+ int count = 6;
+ int axes[] = { DIJOFS_X, DIJOFS_Y, DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ };
+ int values[] = { js.lX, js.lY, js.lZ, js.lRx, js.lRy, js.lRz };
+
+ for (int j = 0; j < joy->joy_axis.size(); j++) {
+
+ for (int k=0; k<count; k++) {
+ if (joy->joy_axis[j] == axes[k]) {
+ p_last_id = input->joy_axis(p_last_id, joy->id, j, axis_correct(values[k]));
+ break;
+ };
+ };
+ };
+ }
+ return p_last_id;
+}
+
+unsigned int joystick_windows::post_hat(unsigned int p_last_id, int p_device, DWORD p_dpad) {
+
+ int dpad_val = 0;
+
+ if (p_dpad == -1) {
+ dpad_val = InputDefault::HAT_MASK_CENTER;
+ }
+ if (p_dpad == 0) {
+
+ dpad_val = InputDefault::HAT_MASK_UP;
+
+ }
+ else if (p_dpad == 4500) {
+
+ dpad_val = (InputDefault::HAT_MASK_UP | InputDefault::HAT_MASK_RIGHT);
+
+ }
+ else if (p_dpad == 9000) {
+
+ dpad_val = InputDefault::HAT_MASK_RIGHT;
+
+ }
+ else if (p_dpad == 13500) {
+
+ dpad_val = (InputDefault::HAT_MASK_RIGHT | InputDefault::HAT_MASK_DOWN);
+
+ }
+ else if (p_dpad == 18000) {
+
+ dpad_val = InputDefault::HAT_MASK_DOWN;
+
+ }
+ else if (p_dpad == 22500) {
+
+ dpad_val = (InputDefault::HAT_MASK_DOWN | InputDefault::HAT_MASK_LEFT);
+
+ }
+ else if (p_dpad == 27000) {
+
+ dpad_val = InputDefault::HAT_MASK_LEFT;
+
+ }
+ else if (p_dpad == 31500) {
+
+ dpad_val = (InputDefault::HAT_MASK_LEFT | InputDefault::HAT_MASK_UP);
+ }
+ return input->joy_hat(p_last_id, p_device, dpad_val);
+};
+
+InputDefault::JoyAxis joystick_windows::axis_correct(int p_val, bool p_xinput, bool p_trigger, bool p_negate) const {
+
+ InputDefault::JoyAxis jx;
+ if (Math::abs(p_val) < MIN_JOY_AXIS) {
+ jx.min = -1;
+ jx.value = 0.0f;
+ return jx;
+ }
+ if (p_xinput) {
+
+ if (p_trigger) {
+ jx.min = 0;
+ jx.value = (float)p_val / MAX_TRIGGER;
+ return jx;
+ }
+ jx.min = -1;
+ if (p_val < 0) {
+ jx.value = (float)p_val / MAX_JOY_AXIS;
+ }
+ else {
+ jx.value = (float)p_val / (MAX_JOY_AXIS - 1);
+ }
+ if (p_negate) {
+ jx.value = -jx.value;
+ }
+ return jx;
+ }
+ jx.min = -1;
+ jx.value = (float)p_val / MAX_JOY_AXIS;
+ return jx;
+}
+
+void joystick_windows::load_xinput() {
+
+ xinput_get_state = &_xinput_get_state;
+ xinput_dll = LoadLibrary( "XInput1_4.dll" );
+ if (!xinput_dll) {
+ xinput_dll = LoadLibrary("XInput1_3.dll");
+ if (!xinput_dll) {
+ xinput_dll = LoadLibrary("XInput9_1_0.dll");
+ }
+ }
+
+ if (!xinput_dll) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ print_line("Could not find XInput, using DirectInput only");
+ }
+ return;
+ }
+
+ XInputGetState_t func = (XInputGetState_t)GetProcAddress((HMODULE)xinput_dll, "XInputGetState");
+ if (!func) {
+ unload_xinput();
+ return;
+ }
+ xinput_get_state = func;
+ return;
+}
+
+void joystick_windows::unload_xinput() {
+
+ if (xinput_dll) {
+
+ FreeLibrary((HMODULE)xinput_dll);
+ }
+}
diff --git a/platform/windows/joystick.h b/platform/windows/joystick.h
new file mode 100644
index 0000000000..332e86fbb8
--- /dev/null
+++ b/platform/windows/joystick.h
@@ -0,0 +1,142 @@
+/*************************************************************************/
+/* joystick.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 Juan 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. */
+/*************************************************************************/
+//author: Andreas Haas <hondres, liugam3@gmail.com>
+#ifndef JOYSTICK_H
+#define JOYSTICK_H
+
+#include "os_windows.h"
+#define DIRECTINPUT_VERSION 0x0800
+#include <dinput.h>
+#include <xinput.h> // on unix the file is called "xinput.h", on windows I'm sure it won't mind
+
+#ifndef SAFE_RELEASE // when Windows Media Device M? is not present
+#define SAFE_RELEASE(x) \
+if(x != NULL) \
+{ \
+ x->Release(); \
+ x = NULL; \
+}
+#endif
+
+#ifndef XUSER_MAX_COUNT
+#define XUSER_MAX_COUNT 4
+#endif
+
+class joystick_windows
+{
+public:
+ joystick_windows();
+ joystick_windows(InputDefault* _input, HWND* hwnd);
+ ~joystick_windows();
+
+ void probe_joysticks();
+ unsigned int process_joysticks(unsigned int p_last_id);
+private:
+
+ enum {
+ JOYSTICKS_MAX = 16,
+ JOY_AXIS_COUNT = 6,
+ MIN_JOY_AXIS = 10,
+ MAX_JOY_AXIS = 32768,
+ MAX_JOY_BUTTONS = 128,
+ KEY_EVENT_BUFFER_SIZE = 512,
+ MAX_TRIGGER = 255
+ };
+
+ struct dinput_gamepad {
+
+ int id;
+ bool attached;
+ bool confirmed;
+ bool last_buttons[MAX_JOY_BUTTONS];
+ DWORD last_pad;
+
+ LPDIRECTINPUTDEVICE8 di_joy;
+ List<DWORD> joy_axis;
+ GUID guid;
+
+ dinput_gamepad() {
+ id = -1;
+ last_pad = -1;
+ attached = false;
+ confirmed = false;
+
+ for (int i = 0; i < MAX_JOY_BUTTONS; i++)
+ last_buttons[i] = false;
+ }
+ };
+
+ struct xinput_gamepad {
+
+ int id;
+ bool attached;
+ DWORD last_packet;
+ XINPUT_STATE state;
+
+ xinput_gamepad() {
+ attached = false;
+ last_packet = 0;
+ }
+ };
+
+ typedef DWORD (WINAPI *XInputGetState_t) (DWORD dwUserIndex, XINPUT_STATE* pState);
+
+ HWND* hWnd;
+ HANDLE xinput_dll;
+ LPDIRECTINPUT8 dinput;
+ InputDefault* input;
+
+ int id_to_change;
+ int joystick_count;
+ bool attached_joysticks[JOYSTICKS_MAX];
+ dinput_gamepad d_joysticks[JOYSTICKS_MAX];
+ xinput_gamepad x_joysticks[XUSER_MAX_COUNT];
+
+ static BOOL CALLBACK enumCallback(const DIDEVICEINSTANCE* p_instance, void* p_context);
+ static BOOL CALLBACK objectsCallback(const DIDEVICEOBJECTINSTANCE* instance, void* context);
+
+ void setup_joystick_object(const DIDEVICEOBJECTINSTANCE* ob, int p_joy_id);
+ void close_joystick(int id = -1);
+ void load_xinput();
+ void unload_xinput();
+
+ int check_free_joy_slot() const;
+ unsigned int post_hat(unsigned int p_last_id, int p_device, DWORD p_dpad);
+
+ bool have_device(const GUID &p_guid);
+ bool is_xinput_device(const GUID* p_guid);
+ bool setup_dinput_joystick(const DIDEVICEINSTANCE* instance);
+
+ InputDefault::JoyAxis axis_correct(int p_val, bool p_xinput = false, bool p_trigger = false, bool p_negate = false) const;
+ XInputGetState_t xinput_get_state;
+};
+
+#endif
+
+
diff --git a/platform/windows/key_mapping_win.cpp b/platform/windows/key_mapping_win.cpp
index f07b7c6eaa..07d5f32253 100644
--- a/platform/windows/key_mapping_win.cpp
+++ b/platform/windows/key_mapping_win.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/windows/key_mapping_win.h b/platform/windows/key_mapping_win.h
index 288fcdd8de..da649d0115 100644
--- a/platform/windows/key_mapping_win.h
+++ b/platform/windows/key_mapping_win.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/windows/lang_table.h b/platform/windows/lang_table.h
index bfdf2b6ebe..c9551b2d38 100644
--- a/platform/windows/lang_table.h
+++ b/platform/windows/lang_table.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 1fb8e6dbd0..6f19f8bdfe 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -52,6 +52,7 @@
#include "os/memory_pool_dynamic_prealloc.h"
#include "globals.h"
#include "io/marshalls.h"
+#include "joystick.h"
#include "shlobj.h"
#include <regstr.h>
@@ -148,7 +149,7 @@ const char * OS_Windows::get_video_driver_name(int p_driver) const {
OS::VideoMode OS_Windows::get_default_video_mode() const {
- return VideoMode(800,600,false);
+ return VideoMode(1280,720,false);
}
int OS_Windows::get_audio_driver_count() const {
@@ -682,6 +683,10 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
} break;
#endif
+ case WM_DEVICECHANGE: {
+
+ joystick->probe_joysticks();
+ } break;
default: {
@@ -706,108 +711,6 @@ LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
}
-
-String OS_Windows::get_joystick_name(int id, JOYCAPS jcaps)
-{
- char buffer [256];
- char OEM [256];
- HKEY hKey;
- DWORD sz;
- int res;
-
- _snprintf(buffer, sizeof(buffer), "%s\\%s\\%s",
- REGSTR_PATH_JOYCONFIG, jcaps.szRegKey,
- REGSTR_KEY_JOYCURR );
- res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey);
- if (res != ERROR_SUCCESS)
- {
- res = RegOpenKeyEx(HKEY_CURRENT_USER, buffer, 0, KEY_QUERY_VALUE, &hKey);
- if (res != ERROR_SUCCESS)
- return "";
- }
-
- sz = sizeof(OEM);
- _snprintf( buffer, sizeof(buffer), "Joystick%d%s", id + 1, REGSTR_VAL_JOYOEMNAME);
- res = RegQueryValueEx ( hKey, buffer, 0, 0, (LPBYTE) OEM, &sz);
- RegCloseKey ( hKey );
- if (res != ERROR_SUCCESS)
- return "";
-
- _snprintf( buffer, sizeof(buffer), "%s\\%s", REGSTR_PATH_JOYOEM, OEM);
- res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey);
- if (res != ERROR_SUCCESS)
- {
- res = RegOpenKeyEx(HKEY_CURRENT_USER, buffer, 0, KEY_QUERY_VALUE, &hKey);
- if (res != ERROR_SUCCESS)
- return "";
- }
-
-
- sz = sizeof(buffer);
- res = RegQueryValueEx(hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) buffer,
- &sz);
- RegCloseKey(hKey);
- if (res != ERROR_SUCCESS)
- return "";
-
- return String(buffer);
-}
-
-void OS_Windows::probe_joysticks() {
-
- static uint32_t last_attached = 0;
-
- int device_count = joyGetNumDevs();
-
- JOYINFOEX jinfo;
- jinfo.dwSize = sizeof(JOYINFOEX);
- jinfo.dwFlags = JOY_RETURNALL;
-
- for (int i=0; i<JOYSTICKS_MAX; i++) {
-
- Joystick joy;
- joy.id = i;
- joy.attached = (device_count > 0) && (joyGetPosEx(JOYSTICKID1 + i, &jinfo) == JOYERR_NOERROR);
-
- if (joy.attached == (last_attached & (1 << i) != 0)) {
- continue;
- };
-
- // there's been a change since last call
-
- if (joy.attached)
- last_attached = last_attached | (1 << i);
- else
- last_attached &= ~(1 << i);
-
- if (joy.attached) {
-
- joy.last_buttons = jinfo.dwButtons;
-
- joy.last_axis[0] = jinfo.dwXpos;
- joy.last_axis[1] = jinfo.dwYpos;
- joy.last_axis[2] = jinfo.dwZpos;
- joy.last_axis[3] = jinfo.dwRpos;
- joy.last_axis[4] = jinfo.dwUpos;
- joy.last_axis[5] = jinfo.dwVpos;
-
- JOYCAPS jcaps;
- MMRESULT res = joyGetDevCaps(JOYSTICKID1 + i, &jcaps, sizeof(jcaps));
- if (res == JOYERR_NOERROR) {
- String name = get_joystick_name(JOYSTICKID1 + i, jcaps);
- if ( name == "")
- joy.name = jcaps.szPname;
- else
- joy.name = name;
-
-
- };
- };
-
- joystick_change_queue.push_back(joy);
- };
-};
-
void OS_Windows::process_key_events() {
for(int i=0;i<key_event_pos;i++) {
@@ -879,154 +782,6 @@ void OS_Windows::process_key_events() {
key_event_pos=0;
}
-void OS_Windows::_post_dpad(DWORD p_dpad, int p_device, bool p_pressed) {
-
- InputEvent ievent;
- ievent.device = p_device;
- ievent.type = InputEvent::JOYSTICK_BUTTON;
- ievent.joy_button.pressed = p_pressed;
- ievent.joy_button.pressure = p_pressed ? 1.0 : 0.0;
-
- if (p_dpad == 0) {
-
- ievent.joy_button.button_index = JOY_DPAD_UP;
- ievent.ID = ++last_id;
- input->parse_input_event(ievent);
-
- } else if (p_dpad == 4500) {
-
- ievent.joy_button.button_index = JOY_DPAD_UP;
- ievent.ID = ++last_id;
- input->parse_input_event(ievent);
-
- ievent.joy_button.button_index = JOY_DPAD_RIGHT;
- ievent.ID = ++last_id;
- input->parse_input_event(ievent);
-
- } else if (p_dpad == 9000) {
-
- ievent.joy_button.button_index = JOY_DPAD_RIGHT;
- ievent.ID = ++last_id;
- input->parse_input_event(ievent);
-
- } else if (p_dpad == 13500) {
-
- ievent.joy_button.button_index = JOY_DPAD_RIGHT;
- ievent.ID = ++last_id;
- input->parse_input_event(ievent);
-
- ievent.joy_button.button_index = JOY_DPAD_DOWN;
- ievent.ID = ++last_id;
- input->parse_input_event(ievent);
-
- } else if (p_dpad == 18000) {
-
- ievent.joy_button.button_index = JOY_DPAD_DOWN;
- ievent.ID = ++last_id;
- input->parse_input_event(ievent);
-
- } else if (p_dpad == 22500) {
-
- ievent.joy_button.button_index = JOY_DPAD_DOWN;
- ievent.ID = ++last_id;
- input->parse_input_event(ievent);
-
- ievent.joy_button.button_index = JOY_DPAD_LEFT;
- ievent.ID = ++last_id;
- input->parse_input_event(ievent);
-
- } else if (p_dpad == 27000) {
-
- ievent.joy_button.button_index = JOY_DPAD_LEFT;
- ievent.ID = ++last_id;
- input->parse_input_event(ievent);
-
- } else if (p_dpad == 31500) {
-
- ievent.joy_button.button_index = JOY_DPAD_LEFT;
- ievent.ID = ++last_id;
- input->parse_input_event(ievent);
-
- ievent.joy_button.button_index = JOY_DPAD_UP;
- ievent.ID = ++last_id;
- input->parse_input_event(ievent);
- };
-};
-
-void OS_Windows::process_joysticks() {
-
- if (!main_loop) {
- return;
- };
-
- InputEvent ievent;
-
- JOYINFOEX jinfo;
- jinfo.dwSize = sizeof(JOYINFOEX);
- jinfo.dwFlags = JOY_RETURNALL;
-
- for (int i=0; i<JOYSTICKS_MAX; i++) {
-
- if (!joysticks[i].attached) {
- continue;
- };
-
- if (joyGetPosEx(JOYSTICKID1 + i, &jinfo) != JOYERR_NOERROR) {
-
- continue;
- };
-
- ievent.device = i;
-
- #define CHECK_AXIS(n, var) \
- if (joysticks[i].last_axis[n] != var) {\
- ievent.type = InputEvent::JOYSTICK_MOTION;\
- ievent.ID = ++last_id;\
- ievent.joy_motion.axis = n;\
- ievent.joy_motion.axis_value = (float)((int)var - MAX_JOY_AXIS) / (float)MAX_JOY_AXIS;\
- joysticks[i].last_axis[n] = var;\
- input->parse_input_event(ievent);\
- };
-
- CHECK_AXIS(0, jinfo.dwXpos);
- CHECK_AXIS(1, jinfo.dwYpos);
- CHECK_AXIS(2, jinfo.dwZpos);
- CHECK_AXIS(3, jinfo.dwRpos);
- CHECK_AXIS(4, jinfo.dwUpos);
- CHECK_AXIS(5, jinfo.dwVpos);
-
- if (joysticks[i].last_pov != jinfo.dwPOV) {
-
- if (joysticks[i].last_pov != JOY_POVCENTERED)
- _post_dpad(joysticks[i].last_pov, i, false);
-
- if (jinfo.dwPOV != JOY_POVCENTERED)
- _post_dpad(jinfo.dwPOV, i, true);
-
- joysticks[i].last_pov = jinfo.dwPOV;
- };
-
- if (joysticks[i].last_buttons == jinfo.dwButtons) {
- continue;
- };
-
- ievent.type = InputEvent::JOYSTICK_BUTTON;
- for (int j=0; j<32; j++) {
-
- if ( (joysticks[i].last_buttons & (1<<j)) != (jinfo.dwButtons & (1<<j)) ) {
-
- ievent.joy_button.button_index = j; //_pc_joystick_get_native_button(j);
- ievent.joy_button.pressed = jinfo.dwButtons & 1<<j;
- ievent.ID = ++last_id;
- input->parse_input_event(ievent);
- };
- };
-
- joysticks[i].last_buttons = jinfo.dwButtons;
- };
-};
-
-
BOOL CALLBACK OS_Windows::MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
OS_Windows *self=(OS_Windows*)OS::get_singleton();
MonitorInfo minfo;
@@ -1213,6 +968,7 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_
visual_server->init();
input = memnew( InputDefault );
+ joystick = memnew (joystick_windows(input, &hWnd));
AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
@@ -1231,14 +987,6 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_
spatial_sound_2d_server = memnew( SpatialSound2DServerSW );
spatial_sound_2d_server->init();
- probe_joysticks(); // todo: move this to a thread
- while (joystick_change_queue.size() > 0) {
- Joystick joy = joystick_change_queue.front()->get();
- joystick_change_queue.pop_front();
- joysticks[joy.id] = joy;
- input->joy_connection_changed(joy.id, joy.attached, joy.name);
- };
-
TRACKMOUSEEVENT tme;
tme.cbSize=sizeof(TRACKMOUSEEVENT);
tme.dwFlags=TME_LEAVE;
@@ -1351,6 +1099,7 @@ void OS_Windows::finalize() {
main_loop=NULL;
+ memdelete(joystick);
memdelete(input);
visual_server->finish();
@@ -1386,7 +1135,6 @@ void OS_Windows::finalize() {
physics_2d_server->finish();
memdelete(physics_2d_server);
- joystick_change_queue.clear();
monitor_info.clear();
}
@@ -1396,8 +1144,7 @@ void OS_Windows::finalize_core() {
if (mempool_dynamic)
memdelete( mempool_dynamic );
- if (mempool_static)
- delete mempool_static;
+ delete mempool_static;
TCPServerWinsock::cleanup();
@@ -1933,10 +1680,16 @@ uint64_t OS_Windows::get_unix_time() const {
return (*(uint64_t*)&ft - *(uint64_t*)&fep) / 10000000;
};
-uint64_t OS_Windows::get_system_time_msec() const {
+uint64_t OS_Windows::get_system_time_secs() const {
SYSTEMTIME st;
GetSystemTime(&st);
- return st.wMilliseconds;
+ FILETIME ft;
+ SystemTimeToFileTime(&st,&ft);
+ uint64_t ret;
+ ret=ft.dwHighDateTime;
+ ret<<=32;
+ ret|=ft.dwLowDateTime;
+ return ret;
}
void OS_Windows::delay_usec(uint32_t p_usec) const {
@@ -1967,7 +1720,7 @@ void OS_Windows::process_events() {
MSG msg;
- process_joysticks();
+ last_id = joystick->process_joysticks(last_id);
while(PeekMessageW(&msg,NULL,0,0,PM_REMOVE)) {
@@ -2351,6 +2104,13 @@ String OS_Windows::get_data_dir() const {
}
+bool OS_Windows::is_joy_known(int p_device) {
+ return input->is_joy_mapped(p_device);
+}
+
+String OS_Windows::get_joy_guid(int p_device) const {
+ return input->get_joy_guid_remapped(p_device);
+}
OS_Windows::OS_Windows(HINSTANCE _hInstance) {
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 026b50c33d..e433d5cc11 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -60,13 +60,11 @@
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
+class joystick_windows;
class OS_Windows : public OS {
- enum {
- JOYSTICKS_MAX = 8,
- JOY_AXIS_COUNT = 6,
- MAX_JOY_AXIS = 32768, // I've no idea
- KEY_EVENT_BUFFER_SIZE=512
+ enum {
+ KEY_EVENT_BUFFER_SIZE=512
};
FILE *stdo;
@@ -106,32 +104,6 @@ class OS_Windows : public OS {
HINSTANCE hInstance; // Holds The Instance Of The Application
HWND hWnd;
- struct Joystick {
-
- int id;
- bool attached;
-
- DWORD last_axis[JOY_AXIS_COUNT];
- DWORD last_buttons;
- DWORD last_pov;
- String name;
-
- Joystick() {
- id = -1;
- attached = false;
- for (int i=0; i<JOY_AXIS_COUNT; i++) {
-
- last_axis[i] = 0;
- };
- last_buttons = 0;
- last_pov = 0;
- };
- };
-
- List<Joystick> joystick_change_queue;
- int joystick_count;
- Joystick joysticks[JOYSTICKS_MAX];
-
Size2 window_rect;
VideoMode video_mode;
@@ -156,13 +128,12 @@ class OS_Windows : public OS {
CursorShape cursor_shape;
InputDefault *input;
+ joystick_windows *joystick;
#ifdef RTAUDIO_ENABLED
AudioDriverRtAudio driver_rtaudio;
#endif
- void _post_dpad(DWORD p_dpad, int p_device, bool p_pressed);
-
void _drag_event(int p_x, int p_y, int idx);
void _touch_event(bool p_pressed, int p_x, int p_y, int idx);
@@ -186,11 +157,7 @@ protected:
virtual void finalize_core();
void process_events();
-
- void probe_joysticks();
- void process_joysticks();
void process_key_events();
- String get_joystick_name( int id, JOYCAPS jcaps);
struct ProcessInfo {
@@ -264,7 +231,7 @@ public:
virtual Time get_time(bool utc) const;
virtual TimeZoneInfo get_time_zone_info() const;
virtual uint64_t get_unix_time() const;
- virtual uint64_t get_system_time_msec() const;
+ virtual uint64_t get_system_time_secs() const;
virtual bool can_draw() const;
virtual Error set_cwd(const String& p_cwd);
@@ -303,6 +270,9 @@ public:
virtual bool get_swap_ok_cancel() { return true; }
+ virtual bool is_joy_known(int p_device);
+ virtual String get_joy_guid(int p_device) const;
+
OS_Windows(HINSTANCE _hInstance);
~OS_Windows();
diff --git a/platform/windows/platform_config.h b/platform/windows/platform_config.h
index e6b561552e..55f6b5547e 100644
--- a/platform/windows/platform_config.h
+++ b/platform/windows/platform_config.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp
index e8245c92e5..fcf0cb1640 100644
--- a/platform/windows/stream_peer_winsock.cpp
+++ b/platform/windows/stream_peer_winsock.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -342,6 +342,14 @@ void StreamPeerWinsock::set_nodelay(bool p_enabled) {
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(int));
}
+int StreamPeerWinsock::get_available_bytes() const {
+
+ unsigned long len;
+ int ret = ioctlsocket(sockfd,FIONREAD,&len);
+ ERR_FAIL_COND_V(ret==-1,0)
+ return len;
+
+}
IP_Address StreamPeerWinsock::get_connected_host() const {
diff --git a/platform/windows/stream_peer_winsock.h b/platform/windows/stream_peer_winsock.h
index 373b502d2c..bbff661490 100644
--- a/platform/windows/stream_peer_winsock.h
+++ b/platform/windows/stream_peer_winsock.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -66,6 +66,8 @@ public:
virtual Error get_data(uint8_t* p_buffer, int p_bytes);
virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received);
+ virtual int get_available_bytes() const;
+
void set_socket(int p_sockfd, IP_Address p_host, int p_port);
virtual IP_Address get_connected_host() const;
diff --git a/platform/windows/tcp_server_winsock.cpp b/platform/windows/tcp_server_winsock.cpp
index cc689d9dcf..dd1cf43f3b 100644
--- a/platform/windows/tcp_server_winsock.cpp
+++ b/platform/windows/tcp_server_winsock.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/windows/tcp_server_winsock.h b/platform/windows/tcp_server_winsock.h
index 2516123908..bd6a05c74d 100644
--- a/platform/windows/tcp_server_winsock.h
+++ b/platform/windows/tcp_server_winsock.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/winrt/os_winrt.cpp b/platform/winrt/os_winrt.cpp
index 24be2f47e7..f507c1aae7 100644
--- a/platform/winrt/os_winrt.cpp
+++ b/platform/winrt/os_winrt.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -345,8 +345,7 @@ void OSWinrt::finalize_core() {
if (mempool_dynamic)
memdelete( mempool_dynamic );
- if (mempool_static)
- delete mempool_static;
+ delete mempool_static;
}
diff --git a/platform/winrt/os_winrt.h b/platform/winrt/os_winrt.h
index 5719426f9f..3fbb4a4c1b 100644
--- a/platform/winrt/os_winrt.h
+++ b/platform/winrt/os_winrt.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/x11/SCsub b/platform/x11/SCsub
index 7a6f02daa5..80fd347ded 100644
--- a/platform/x11/SCsub
+++ b/platform/x11/SCsub
@@ -5,6 +5,7 @@ common_x11=[\
"context_gl_x11.cpp",\
"os_x11.cpp",\
"key_mapping_x11.cpp",\
+ "joystick_linux.cpp",\
]
env.Program('#bin/godot',['godot_x11.cpp']+common_x11)
diff --git a/platform/x11/context_gl_x11.cpp b/platform/x11/context_gl_x11.cpp
index 3db1f6da25..89bd5f58ff 100644
--- a/platform/x11/context_gl_x11.cpp
+++ b/platform/x11/context_gl_x11.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/x11/context_gl_x11.h b/platform/x11/context_gl_x11.h
index 8b81db9160..56404d0fae 100644
--- a/platform/x11/context_gl_x11.h
+++ b/platform/x11/context_gl_x11.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index d996587864..e035c72993 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -1,6 +1,7 @@
import os
import sys
+import platform
def is_active():
@@ -44,7 +45,7 @@ def can_build():
print("xinerama not found.. x11 disabled.")
return False
-
+
return True # X11 enabled
def get_opts():
@@ -54,6 +55,7 @@ def get_opts():
('use_sanitizer','Use llvm compiler sanitize address','no'),
('use_leak_sanitizer','Use llvm compiler sanitize memory leaks','no'),
('pulseaudio','Detect & Use pulseaudio','yes'),
+ ('gamepad','Gamepad support, requires libudev and libevdev','yes'),
('new_wm_api', 'Use experimental window management API','no'),
('debug_release', 'Add debug symbols to release version','no'),
]
@@ -144,10 +146,33 @@ def configure(env):
env.Append(CPPPATH=['#tools/freetype/freetype/include'])
-
-
env.Append(CPPFLAGS=['-DOPENGL_ENABLED','-DGLEW_ENABLED'])
- env.Append(CPPFLAGS=["-DALSA_ENABLED"])
+
+ if os.system("pkg-config --exists alsa")==0:
+ print("Enabling ALSA")
+ env.Append(CPPFLAGS=["-DALSA_ENABLED"])
+ env.Append(LIBS=['asound'])
+ else:
+ print("ALSA libraries not found, disabling driver")
+
+ if (env["gamepad"]=="yes" and platform.system() == "Linux"):
+ # pkg-config returns 0 when the lib exists...
+ found_udev = not os.system("pkg-config --exists libudev")
+ found_evdev = not os.system("pkg-config --exists libevdev")
+
+ if (found_udev and found_evdev):
+ print("Enabling gamepad support with udev/evdev")
+ env.Append(CPPFLAGS=["-DJOYDEV_ENABLED"])
+ env.ParseConfig('pkg-config libudev --cflags --libs')
+ env.ParseConfig('pkg-config libevdev --cflags --libs')
+ else:
+ if (not found_udev):
+ print("libudev development libraries not found")
+ if (not found_evdev):
+ print("libevdev development libraries not found")
+ print("Some libraries are missing for the required gamepad support, aborting!")
+ print("Install the mentioned libraries or build with 'gamepad=no' to disable gamepad support.")
+ sys.exit(255)
if (env["pulseaudio"]=="yes"):
if not os.system("pkg-config --exists libpulse-simple"):
@@ -158,7 +183,7 @@ def configure(env):
print("PulseAudio development libraries not found, disabling driver")
env.Append(CPPFLAGS=['-DX11_ENABLED','-DUNIX_ENABLED','-DGLES2_ENABLED','-DGLES_OVER_GL'])
- env.Append(LIBS=['GL', 'GLU', 'pthread','asound','z']) #TODO detect linux/BSD!
+ env.Append(LIBS=['GL', 'GLU', 'pthread', 'z'])
#env.Append(CPPFLAGS=['-DMPC_FIXED_POINT'])
#host compiler is default..
diff --git a/platform/x11/godot_x11.cpp b/platform/x11/godot_x11.cpp
index f90d40fa5c..ee83da25c1 100644
--- a/platform/x11/godot_x11.cpp
+++ b/platform/x11/godot_x11.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/x11/joystick_linux.cpp b/platform/x11/joystick_linux.cpp
new file mode 100644
index 0000000000..6eb3671bc0
--- /dev/null
+++ b/platform/x11/joystick_linux.cpp
@@ -0,0 +1,416 @@
+/*************************************************************************/
+/* joystick_linux.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 Juan 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. */
+/*************************************************************************/
+
+//author: Andreas Haas <hondres, liugam3@gmail.com>
+#ifdef JOYDEV_ENABLED
+
+#include "joystick_linux.h"
+#include "print_string.h"
+
+#include <libevdev/libevdev.h>
+#include <libudev.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <cstring>
+
+static const char* ignore_str = "/dev/input/js";
+
+joystick_linux::Joystick::Joystick() {
+ fd = -1;
+ dpad = 0;
+ dev = NULL;
+ devpath = "";
+}
+
+void joystick_linux::Joystick::reset() {
+ dpad = 0;
+ fd = -1;
+
+ InputDefault::JoyAxis jx;
+ jx.min = -1;
+ jx.value = 0.0f;
+ for (int i=0; i < MAX_ABS; i++) {
+ abs_map[i] = -1;
+ curr_axis[i] = jx;
+ }
+}
+
+joystick_linux::joystick_linux(InputDefault *in)
+{
+ exit_udev = false;
+ input = in;
+ joy_mutex = Mutex::create();
+ joy_thread = Thread::create(joy_thread_func, this);
+}
+
+joystick_linux::~joystick_linux() {
+ exit_udev = true;
+ Thread::wait_to_finish(joy_thread);
+ close_joystick();
+}
+
+void joystick_linux::joy_thread_func(void *p_user) {
+
+ if (p_user) {
+ joystick_linux* joy = (joystick_linux*) p_user;
+ joy->run_joystick_thread();
+ }
+ return;
+}
+
+void joystick_linux::run_joystick_thread() {
+
+ udev *_udev = udev_new();
+ ERR_FAIL_COND(!_udev);
+ enumerate_joysticks(_udev);
+ monitor_joysticks(_udev);
+ udev_unref(_udev);
+}
+
+void joystick_linux::enumerate_joysticks(udev *p_udev) {
+
+ udev_enumerate *enumerate;
+ udev_list_entry *devices, *dev_list_entry;
+ udev_device *dev;
+
+ enumerate = udev_enumerate_new(p_udev);
+ udev_enumerate_add_match_subsystem(enumerate,"input");
+ udev_enumerate_add_match_property(enumerate, "ID_INPUT_JOYSTICK", "1");
+
+ udev_enumerate_scan_devices(enumerate);
+ devices = udev_enumerate_get_list_entry(enumerate);
+ udev_list_entry_foreach(dev_list_entry, devices) {
+
+ const char* path = udev_list_entry_get_name(dev_list_entry);
+ dev = udev_device_new_from_syspath(p_udev, path);
+ const char* devnode = udev_device_get_devnode(dev);
+
+ if (devnode != NULL && strstr(devnode, ignore_str) == NULL) {
+ joy_mutex->lock();
+ open_joystick(devnode);
+ joy_mutex->unlock();
+ }
+ udev_device_unref(dev);
+ }
+ udev_enumerate_unref(enumerate);
+}
+
+void joystick_linux::monitor_joysticks(udev *p_udev) {
+
+ udev_device *dev = NULL;
+ udev_monitor *mon = udev_monitor_new_from_netlink(p_udev, "udev");
+ udev_monitor_filter_add_match_subsystem_devtype(mon, "input", NULL);
+ udev_monitor_enable_receiving(mon);
+ int fd = udev_monitor_get_fd(mon);
+
+ while (!exit_udev) {
+
+ fd_set fds;
+ struct timeval tv;
+ int ret;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ ret = select(fd+1, &fds, NULL, NULL, &tv);
+
+ /* Check if our file descriptor has received data. */
+ if (ret > 0 && FD_ISSET(fd, &fds)) {
+ /* Make the call to receive the device.
+ select() ensured that this will not block. */
+ dev = udev_monitor_receive_device(mon);
+
+ if (dev && udev_device_get_devnode(dev) != 0) {
+
+ joy_mutex->lock();
+ const char* action = udev_device_get_action(dev);
+ const char* devnode = udev_device_get_devnode(dev);
+
+ if (strstr(devnode, ignore_str) == NULL) {
+
+ if (strcmp(action, "add") == 0)
+ open_joystick(devnode);
+
+ else if (strcmp(action, "remove") == 0)
+ close_joystick(get_joy_from_path(devnode));
+ }
+
+ udev_device_unref(dev);
+ joy_mutex->unlock();
+ }
+ }
+ usleep(50000);
+ }
+ //printf("exit udev\n");
+ udev_monitor_unref(mon);
+}
+
+int joystick_linux::get_free_joy_slot() const {
+
+ for (int i = 0; i < JOYSTICKS_MAX; i++) {
+
+ if (joysticks[i].fd == -1) return i;
+ }
+ return -1;
+}
+
+int joystick_linux::get_joy_from_path(String p_path) const {
+
+ for (int i = 0; i < JOYSTICKS_MAX; i++) {
+
+ if (joysticks[i].devpath == p_path) {
+ return i;
+ }
+ }
+ return -2;
+}
+
+void joystick_linux::close_joystick(int p_id) {
+ if (p_id == -1) {
+ for (int i=0; i<JOYSTICKS_MAX; i++) {
+
+ close_joystick(i);
+ };
+ return;
+ }
+ else if (p_id < 0) return;
+
+ Joystick &joy = joysticks[p_id];
+
+ if (joy.fd != -1) {
+
+ libevdev_free(joy.dev);
+ close(joy.fd);
+ joy.fd = -1;
+ input->joy_connection_changed(p_id, false, "");
+ };
+};
+
+static String _hex_str(uint8_t p_byte) {
+
+ static const char* dict = "0123456789abcdef";
+ char ret[3];
+ ret[2] = 0;
+
+ ret[0] = dict[p_byte>>4];
+ ret[1] = dict[p_byte & 0xF];
+
+ return ret;
+};
+
+void joystick_linux::setup_joystick_properties(int p_id) {
+
+ Joystick* joy = &joysticks[p_id];
+ libevdev* dev = joy->dev;
+
+ int num_buttons = 0;
+ int num_axes = 0;
+
+ for (int i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
+
+ if (libevdev_has_event_code(dev, EV_KEY, i)) {
+
+ joy->key_map[i] = num_buttons++;
+ }
+ }
+ for (int i = BTN_MISC; i < BTN_JOYSTICK; ++i) {
+
+ if (libevdev_has_event_code(dev, EV_KEY, i)) {
+
+ joy->key_map[i] = num_buttons++;
+ }
+ }
+ for (int i = 0; i < ABS_MISC; ++i) {
+ /* Skip hats */
+ if (i == ABS_HAT0X) {
+ i = ABS_HAT3Y;
+ continue;
+ }
+ if (libevdev_has_event_code(dev, EV_ABS, i)) {
+
+ joy->abs_map[i] = num_axes++;
+ }
+ }
+}
+
+void joystick_linux::open_joystick(const char *p_path) {
+
+ int joy_num = get_free_joy_slot();
+ int fd = open(p_path, O_RDONLY | O_NONBLOCK);
+ if (fd != -1 && joy_num != -1) {
+
+ int rc = libevdev_new_from_fd(fd, &joysticks[joy_num].dev);
+ if (rc < 0) {
+
+ fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc));
+ return;
+ }
+
+ libevdev *dev = joysticks[joy_num].dev;
+
+ //check if the device supports basic gamepad events, prevents certain keyboards from
+ //being detected as joysticks
+ if (libevdev_has_event_type(dev, EV_ABS) && libevdev_has_event_type(dev, EV_KEY) &&
+ (libevdev_has_event_code(dev, EV_KEY, BTN_A) || libevdev_has_event_code(dev, EV_KEY, BTN_THUMBL) || libevdev_has_event_code(dev, EV_KEY, BTN_TOP))) {
+
+ char uid[128];
+ String name = libevdev_get_name(dev);
+ uint16_t bus = __bswap_16(libevdev_get_id_bustype(dev));
+ uint16_t vendor = __bswap_16(libevdev_get_id_vendor(dev));
+ uint16_t product = __bswap_16(libevdev_get_id_product(dev));
+ uint16_t version = __bswap_16(libevdev_get_id_version(dev));
+
+ joysticks[joy_num].reset();
+
+ Joystick &joy = joysticks[joy_num];
+ joy.fd = fd;
+ joy.devpath = String(p_path);
+ setup_joystick_properties(joy_num);
+ sprintf(uid, "%04x%04x", bus, 0);
+ if (vendor && product && version) {
+
+ sprintf(uid + String(uid).length(), "%04x%04x%04x%04x%04x%04x", vendor,0,product,0,version,0);
+ input->joy_connection_changed(joy_num, true, name, uid);
+ }
+ else {
+ String uidname = uid;
+ int uidlen = MIN(name.length(), 11);
+ for (int i=0; i<uidlen; i++) {
+
+ uidname = uidname + _hex_str(name[i]);
+ }
+ uidname += "00";
+ input->joy_connection_changed(joy_num, true, name, uidname);
+
+ }
+ }
+ else {
+ //device is not a gamepad, clean up
+ libevdev_free(dev);
+ close(fd);
+ }
+ }
+}
+
+InputDefault::JoyAxis joystick_linux::axis_correct(const input_absinfo *p_abs, int p_value) const {
+
+ int min = p_abs->minimum;
+ int max = p_abs->maximum;
+ InputDefault::JoyAxis jx;
+
+ if (min < 0) {
+ jx.min = -1;
+ if (p_value < 0) {
+ jx.value = (float) -p_value / min;
+ }
+ jx.value = (float) p_value / max;
+ }
+ if (min == 0) {
+ jx.min = 0;
+ jx.value = 0.0f + (float) p_value / max;
+ }
+ return jx;
+}
+
+uint32_t joystick_linux::process_joysticks(uint32_t p_event_id) {
+
+ if (joy_mutex->try_lock() != OK) {
+ return p_event_id;
+ }
+ for (int i=0; i<JOYSTICKS_MAX; i++) {
+
+ if (joysticks[i].fd == -1) continue;
+
+ input_event ev;
+ Joystick* joy = &joysticks[i];
+ libevdev* dev = joy->dev;
+ int rc = 1;
+
+ rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
+
+ if (rc < 0 && rc != -EAGAIN) {
+ continue;
+ }
+
+ while (rc == LIBEVDEV_READ_STATUS_SYNC || rc == LIBEVDEV_READ_STATUS_SUCCESS) {
+
+ switch (ev.type) {
+ case EV_KEY:
+ p_event_id = input->joy_button(p_event_id, i, joy->key_map[ev.code], ev.value);
+ break;
+
+ case EV_ABS:
+
+ switch (ev.code) {
+ case ABS_HAT0X:
+ if (ev.value != 0) {
+ if (ev.value < 0) joy->dpad |= InputDefault::HAT_MASK_LEFT;
+ else joy->dpad |= InputDefault::HAT_MASK_RIGHT;
+
+ }
+ else joy->dpad &= ~(InputDefault::HAT_MASK_LEFT | InputDefault::HAT_MASK_RIGHT);
+
+ p_event_id = input->joy_hat(p_event_id, i, joy->dpad);
+ break;
+
+ case ABS_HAT0Y:
+ if (ev.value != 0) {
+ if (ev.value < 0) joy->dpad |= InputDefault::HAT_MASK_UP;
+ else joy->dpad |= InputDefault::HAT_MASK_DOWN;
+ }
+ else joy->dpad &= ~(InputDefault::HAT_MASK_UP | InputDefault::HAT_MASK_DOWN);
+
+ p_event_id = input->joy_hat(p_event_id, i, joy->dpad);
+ break;
+
+ default:
+ if (joy->abs_map[ev.code] != -1) {
+ InputDefault::JoyAxis value = axis_correct(libevdev_get_abs_info(dev, ev.code), ev.value);
+ joy->curr_axis[joy->abs_map[ev.code]] = value;
+ }
+ break;
+ }
+ break;
+ }
+ rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
+ }
+ for (int j = 0; j < MAX_ABS; j++) {
+ int index = joy->abs_map[j];
+ if (index != -1) {
+ p_event_id = input->joy_axis(p_event_id, i, index, joy->curr_axis[index]);
+ }
+ }
+ }
+ joy_mutex->unlock();
+ return p_event_id;
+}
+#endif
diff --git a/platform/x11/joystick_linux.h b/platform/x11/joystick_linux.h
new file mode 100644
index 0000000000..ee9bd0352a
--- /dev/null
+++ b/platform/x11/joystick_linux.h
@@ -0,0 +1,92 @@
+/*************************************************************************/
+/* joystick_linux.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 Juan 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. */
+/*************************************************************************/
+
+//author: Andreas Haas <hondres, liugam3@gmail.com>
+#ifndef JOYSTICK_LINUX_H
+#define JOYSTICK_LINUX_H
+#ifdef JOYDEV_ENABLED
+#include "main/input_default.h"
+#include "os/thread.h"
+#include "os/mutex.h"
+
+struct input_absinfo;
+
+class joystick_linux
+{
+public:
+ joystick_linux(InputDefault *in);
+ ~joystick_linux();
+ uint32_t process_joysticks(uint32_t p_event_id);
+private:
+
+ enum {
+ JOYSTICKS_MAX = 16,
+ MAX_ABS = 63,
+ MAX_KEY = 767, // Hack because <linux/input.h> can't be included here
+ BT_MISC = 256,
+ HAT_MAX = 4,
+ };
+
+ struct Joystick {
+ InputDefault::JoyAxis curr_axis[MAX_ABS];
+ int key_map[MAX_KEY - BT_MISC];
+ int abs_map[MAX_ABS];
+ int dpad;
+ int fd;
+
+ String devpath;
+ struct libevdev *dev;
+
+ Joystick();
+ void reset();
+ };
+
+ bool exit_udev;
+ Mutex *joy_mutex;
+ Thread *joy_thread;
+ InputDefault *input;
+ Joystick joysticks[JOYSTICKS_MAX];
+
+ static void joy_thread_func(void *p_user);
+
+ int get_joy_from_path(String path) const;
+ int get_free_joy_slot() const;
+
+ void setup_joystick_properties(int p_id);
+ void close_joystick(int p_id = -1);
+ void enumerate_joysticks(struct udev *_udev);
+ void monitor_joysticks(struct udev *_udev);
+ void run_joystick_thread();
+ void open_joystick(const char* path);
+
+ InputDefault::JoyAxis axis_correct(const input_absinfo *abs, int value) const;
+};
+
+#endif
+#endif // JOYSTICK_LINUX_H
diff --git a/platform/x11/key_mapping_x11.cpp b/platform/x11/key_mapping_x11.cpp
index 9c68ac1a2c..48f415a730 100644
--- a/platform/x11/key_mapping_x11.cpp
+++ b/platform/x11/key_mapping_x11.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/x11/key_mapping_x11.h b/platform/x11/key_mapping_x11.h
index 7ab883878f..979d8a112f 100644
--- a/platform/x11/key_mapping_x11.h
+++ b/platform/x11/key_mapping_x11.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 74ebad748a..82df8dff60 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,6 +32,7 @@
#include "key_mapping_x11.h"
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "print_string.h"
#include "servers/physics/physics_server_sw.h"
#include "errno.h"
@@ -57,10 +58,6 @@
#include <fcntl.h>
#include <unistd.h>
-#ifdef __linux__
-#include <linux/joystick.h>
-#endif
-
//stupid linux.h
#ifdef KEY_TAB
#undef KEY_TAB
@@ -81,7 +78,7 @@ const char * OS_X11::get_video_driver_name(int p_driver) const {
}
OS::VideoMode OS_X11::get_default_video_mode() const {
- return OS::VideoMode(800,600,false);
+ return OS::VideoMode(1280,720,false);
}
int OS_X11::get_audio_driver_count() const {
@@ -98,8 +95,6 @@ const char *OS_X11::get_audio_driver_name(int p_driver) const {
void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) {
last_button_state=0;
- dpad_last[0]=0;
- dpad_last[1]=0;
xmbstring=NULL;
event_id=0;
@@ -431,9 +426,9 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
physics_2d_server->init();
input = memnew( InputDefault );
-
- probe_joystick();
-
+#ifdef JOYDEV_ENABLED
+ joystick = memnew( joystick_linux(input));
+#endif
_ensure_data_dir();
}
@@ -452,6 +447,11 @@ void OS_X11::finalize() {
// memdelete(debugger_connection_console);
//}
+#ifdef JOYDEV_ENABLED
+ memdelete(joystick);
+#endif
+ memdelete(input);
+
memdelete(sample_manager);
audio_server->finish();
@@ -467,8 +467,6 @@ void OS_X11::finalize() {
physics_2d_server->finish();
memdelete(physics_2d_server);
- memdelete(input);
-
XUnmapWindow( x11_display, x11_window );
XDestroyWindow( x11_display, x11_window );
@@ -621,6 +619,7 @@ void OS_X11::set_wm_fullscreen(bool p_enabled) {
xev.xclient.data.l[2] = 0;
XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+
}
int OS_X11::get_screen_count() const {
@@ -889,7 +888,16 @@ void OS_X11::set_window_maximized(bool p_enabled) {
XGetWindowAttributes(x11_display,DefaultRootWindow(x11_display),&xwa);
current_videomode.width = xwa.width;
current_videomode.height = xwa.height;
-*/
+//*/
+
+// current_videomode.width = wm_max_horz;
+// current_videomode.height = wm_max_vert;
+
+ //Size2 ss = get_screen_size(get_current_screen());
+ //current_videomode.width=ss.width;
+ //current_videomode.height=ss.height;
+
+
maximized = p_enabled;
}
@@ -1652,193 +1660,11 @@ String OS_X11::get_system_dir(SystemDir p_dir) const {
return pipe.strip_edges();
}
-
-void OS_X11::close_joystick(int p_id) {
-
- if (p_id == -1) {
- for (int i=0; i<JOYSTICKS_MAX; i++) {
-
- close_joystick(i);
- };
- return;
- };
-
-
- if (joysticks[p_id].fd != -1) {
- close(joysticks[p_id].fd);
- joysticks[p_id].fd = -1;
- };
- input->joy_connection_changed(p_id, false, "");
-};
-
-void OS_X11::probe_joystick(int p_id) {
- #ifndef __FreeBSD__
-
- if (p_id == -1) {
-
- for (int i=0; i<JOYSTICKS_MAX; i++) {
-
- probe_joystick(i);
- };
- return;
- };
-
- if (joysticks[p_id].fd != -1)
- close_joystick(p_id);
-
- const char *joy_names[] = {
- "/dev/input/js%d",
- "/dev/js%d",
- NULL
- };
-
- int i=0;
- while(joy_names[i]) {
-
- char fname[64];
- sprintf(fname, joy_names[i], p_id);
- int fd = open(fname, O_RDONLY|O_NONBLOCK);
- if (fd != -1) {
-
- //fcntl( fd, F_SETFL, O_NONBLOCK );
- joysticks[p_id] = Joystick(); // this will reset the axis array
- joysticks[p_id].fd = fd;
-
- String name;
- char namebuf[255] = {0};
- if (ioctl(fd, JSIOCGNAME(sizeof(namebuf)), namebuf) >= 0) {
- name = namebuf;
- } else {
- name = "error";
- };
-
- input->joy_connection_changed(p_id, true, name);
- break; // don't try the next name
- };
-
- ++i;
- };
- #endif
-};
-
void OS_X11::move_window_to_foreground() {
XRaiseWindow(x11_display,x11_window);
}
-void OS_X11::process_joysticks() {
- #ifndef __FreeBSD__
- int bytes;
- js_event events[32];
- InputEvent ievent;
- for (int i=0; i<JOYSTICKS_MAX; i++) {
-
- if (joysticks[i].fd == -1) {
- probe_joystick(i);
- if (joysticks[i].fd == -1)
- continue;
- };
- ievent.device = i;
-
- while ( (bytes = read(joysticks[i].fd, &events, sizeof(events))) > 0) {
-
- int ev_count = bytes / sizeof(js_event);
- for (int j=0; j<ev_count; j++) {
-
- js_event& event = events[j];
-
- //printf("got event on joystick %i, %i, %i, %i, %i\n", i, joysticks[i].fd, event.type, event.number, event.value);
- if (event.type & JS_EVENT_INIT)
- continue;
-
- switch (event.type & ~JS_EVENT_INIT) {
-
- case JS_EVENT_AXIS:
-
- //if (joysticks[i].last_axis[event.number] != event.value) {
-
- /*
- if (event.number==5 || event.number==6) {
-
- int axis=event.number-5;
- int val = event.value;
- if (val<0)
- val=-1;
- if (val>0)
- val=+1;
-
- InputEvent ev;
- ev.type = InputEvent::JOYSTICK_BUTTON;
- ev.ID = ++event_id;
-
-
- if (val!=dpad_last[axis]) {
-
- int prev_val = dpad_last[axis];
- if (prev_val!=0) {
-
- ev.joy_button.pressed=false;
- ev.joy_button.pressure=0.0;
- if (event.number==5)
- ev.joy_button.button_index=JOY_DPAD_LEFT+(prev_val+1)/2;
- if (event.number==6)
- ev.joy_button.button_index=JOY_DPAD_UP+(prev_val+1)/2;
-
- input->parse_input_event( ev );
- }
- }
-
- if (val!=0) {
-
- ev.joy_button.pressed=true;
- ev.joy_button.pressure=1.0;
- if (event.number==5)
- ev.joy_button.button_index=JOY_DPAD_LEFT+(val+1)/2;
- if (event.number==6)
- ev.joy_button.button_index=JOY_DPAD_UP+(val+1)/2;
-
- input->parse_input_event( ev );
- }
-
-
- dpad_last[axis]=val;
-
- }
- */
- //print_line("ev: "+itos(event.number)+" val: "+ rtos((float)event.value / (float)MAX_JOY_AXIS));
- //if (event.number >= JOY_AXIS_MAX)
- // break;
- //ERR_FAIL_COND(event.number >= JOY_AXIS_MAX);
- ievent.type = InputEvent::JOYSTICK_MOTION;
- ievent.ID = ++event_id;
- ievent.joy_motion.axis = event.number; //_pc_joystick_get_native_axis(event.number);
- ievent.joy_motion.axis_value = (float)event.value / (float)MAX_JOY_AXIS;
- if (event.number < JOY_AXIS_MAX)
- joysticks[i].last_axis[event.number] = event.value;
- input->parse_input_event( ievent );
- //};
- break;
-
- case JS_EVENT_BUTTON:
-
-
- ievent.type = InputEvent::JOYSTICK_BUTTON;
- ievent.ID = ++event_id;
- ievent.joy_button.button_index = event.number; // _pc_joystick_get_native_button(event.number);
- ievent.joy_button.pressed = event.value;
- input->parse_input_event( ievent );
- break;
- };
- };
- };
- if (bytes == 0 || (bytes < 0 && errno != EAGAIN)) {
- close_joystick(i);
- };
- };
- #endif
-};
-
-
void OS_X11::set_cursor_shape(CursorShape p_shape) {
ERR_FAIL_INDEX(p_shape,CURSOR_MAX);
@@ -1938,7 +1764,9 @@ void OS_X11::run() {
while (!force_quit) {
process_xevents(); // get rid of pending events
- process_joysticks();
+#ifdef JOYDEV_ENABLED
+ event_id = joystick->process_joysticks(event_id);
+#endif
if (Main::iteration()==true)
break;
};
@@ -1946,6 +1774,14 @@ void OS_X11::run() {
main_loop->finish();
}
+bool OS_X11::is_joy_known(int p_device) {
+ return input->is_joy_mapped(p_device);
+}
+
+String OS_X11::get_joy_guid(int p_device) const {
+ return input->get_joy_guid_remapped(p_device);
+}
+
OS_X11::OS_X11() {
#ifdef RTAUDIO_ENABLED
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index ed61df8f0e..91dbeac284 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -47,6 +47,7 @@
#include "servers/physics_2d/physics_2d_server_sw.h"
#include "servers/physics_2d/physics_2d_server_wrap_mt.h"
#include "main/input_default.h"
+#include "joystick_linux.h"
#include <X11/keysym.h>
#include <X11/Xlib.h>
@@ -113,7 +114,6 @@ class OS_X11 : public OS_Unix {
bool force_quit;
bool minimized;
- int dpad_last[2];
bool do_mouse_warp;
@@ -126,6 +126,10 @@ class OS_X11 : public OS_Unix {
InputDefault *input;
+#ifdef JOYDEV_ENABLED
+ joystick_linux *joystick;
+#endif
+
#ifdef RTAUDIO_ENABLED
AudioDriverRtAudio driver_rtaudio;
#endif
@@ -138,26 +142,7 @@ class OS_X11 : public OS_Unix {
AudioDriverPulseAudio driver_pulseaudio;
#endif
- enum {
- JOYSTICKS_MAX = 8,
- MAX_JOY_AXIS = 32768, // I've no idea
- };
-
- struct Joystick {
-
- int fd;
- int last_axis[JOY_AXIS_MAX];
-
- Joystick() {
- fd = -1;
- for (int i=0; i<JOY_AXIS_MAX; i++) {
-
- last_axis[i] = 0;
- };
- };
- };
- int joystick_count;
- Joystick joysticks[JOYSTICKS_MAX];
+ Atom net_wm_icon;
int audio_driver_index;
unsigned int capture_idle;
@@ -180,10 +165,6 @@ protected:
virtual void set_main_loop( MainLoop * p_main_loop );
- void probe_joystick(int p_id = -1);
- void process_joysticks();
- void close_joystick(int p_id = -1);
-
public:
@@ -241,6 +222,10 @@ public:
virtual void move_window_to_foreground();
virtual void alert(const String& p_alert,const String& p_title="ALERT!");
+
+ virtual bool is_joy_known(int p_device);
+ virtual String get_joy_guid(int p_device) const;
+
void run();
OS_X11();
diff --git a/platform/x11/platform_config.h b/platform/x11/platform_config.h
index c01d0aa380..aac50c27c2 100644
--- a/platform/x11/platform_config.h
+++ b/platform/x11/platform_config.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,8 +29,9 @@
#ifdef __linux__
#include <alloca.h>
#endif
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
#include <stdlib.h>
+#define PTHREAD_BSD_SET_NAME
#endif
#define GLES2_INCLUDE_H "gl_context/glew.h"
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp
index 458246671c..1ed508aed3 100644
--- a/scene/2d/animated_sprite.cpp
+++ b/scene/2d/animated_sprite.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h
index 425f516b14..da4f1b99af 100644
--- a/scene/2d/animated_sprite.h
+++ b/scene/2d/animated_sprite.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index c44b46adbf..50a115174d 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -383,7 +383,11 @@ void Area2D::_clear_monitoring() {
Object *obj = ObjectDB::get_instance(E->key());
Node *node = obj ? obj->cast_to<Node>() : NULL;
- ERR_CONTINUE(!node);
+
+ if (!node) //node may have been deleted in previous frame, this should not be an error
+ continue;
+ //ERR_CONTINUE(!node);
+
if (!E->get().in_tree)
continue;
@@ -416,13 +420,13 @@ void Area2D::_notification(int p_what) {
void Area2D::set_enable_monitoring(bool p_enable) {
- if (locked) {
- ERR_EXPLAIN("This function can't be used during the in/out signal.");
- }
- ERR_FAIL_COND(locked);
if (p_enable==monitoring)
return;
+ if (locked) {
+ ERR_EXPLAIN("Function blocked during in/out signal. Use call_deferred(\"set_enable_monitoring\",true/false)");
+ }
+ ERR_FAIL_COND(locked);
monitoring=p_enable;
@@ -652,7 +656,7 @@ void Area2D::_bind_methods() {
ADD_SIGNAL( MethodInfo("area_exit",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D")));
- ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"space_override",PROPERTY_HINT_ENUM,"Disabled,Combine,Replace"),_SCS("set_space_override_mode"),_SCS("get_space_override_mode"));
+ ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"space_override",PROPERTY_HINT_ENUM,"Disabled,Combine,Combine-Replace,Replace,Replace-Combine"),_SCS("set_space_override_mode"),_SCS("get_space_override_mode"));
ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"gravity_point"),_SCS("set_gravity_is_point"),_SCS("is_gravity_a_point"));
ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"gravity_distance_scale", PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_gravity_distance_scale"),_SCS("get_gravity_distance_scale"));
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"gravity_vec"),_SCS("set_gravity_vector"),_SCS("get_gravity_vector"));
diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h
index f5a88390e7..7f3f9c93cf 100644
--- a/scene/2d/area_2d.h
+++ b/scene/2d/area_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -40,7 +40,9 @@ public:
enum SpaceOverride {
SPACE_OVERRIDE_DISABLED,
SPACE_OVERRIDE_COMBINE,
- SPACE_OVERRIDE_REPLACE
+ SPACE_OVERRIDE_COMBINE_REPLACE,
+ SPACE_OVERRIDE_REPLACE,
+ SPACE_OVERRIDE_REPLACE_COMBINE
};
private:
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 52ae5d2954..67c1733759 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -118,10 +118,10 @@ Matrix32 Camera2D::get_camera_transform() {
- if (smoothing>0.0) {
+ if (smoothing_enabled) {
float c = smoothing*get_fixed_process_delta_time();
- smoothed_camera_pos = ((new_camera_pos-smoothed_camera_pos)*c)+smoothed_camera_pos;
+ smoothed_camera_pos = ((camera_pos-smoothed_camera_pos)*c)+smoothed_camera_pos;
ret_camera_pos=smoothed_camera_pos;
// camera_pos=camera_pos*(1.0-smoothing)+new_camera_pos*smoothing;
} else {
@@ -440,6 +440,27 @@ float Camera2D::get_h_offset() const{
}
+void Camera2D::_set_old_smoothing(float p_val) {
+ //compatibility
+ if (p_val>0) {
+ smoothing_enabled=true;
+ set_follow_smoothing(p_val);
+ }
+
+}
+
+void Camera2D::set_enable_follow_smoothing(bool p_enabled) {
+
+ smoothing_enabled=p_enabled;
+
+}
+
+bool Camera2D::is_follow_smoothing_enabled() const {
+
+ return smoothing_enabled;
+}
+
+
void Camera2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_offset","offset"),&Camera2D::set_offset);
@@ -482,21 +503,24 @@ void Camera2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_camera_pos"),&Camera2D::get_camera_pos);
ObjectTypeDB::bind_method(_MD("get_camera_screen_center"),&Camera2D::get_camera_screen_center);
- ObjectTypeDB::bind_method(_MD("set_zoom"),&Camera2D::set_zoom);
+ ObjectTypeDB::bind_method(_MD("set_zoom","zoom"),&Camera2D::set_zoom);
ObjectTypeDB::bind_method(_MD("get_zoom"),&Camera2D::get_zoom);
ObjectTypeDB::bind_method(_MD("set_follow_smoothing","follow_smoothing"),&Camera2D::set_follow_smoothing);
ObjectTypeDB::bind_method(_MD("get_follow_smoothing"),&Camera2D::get_follow_smoothing);
+ ObjectTypeDB::bind_method(_MD("set_enable_follow_smoothing","follow_smoothing"),&Camera2D::set_enable_follow_smoothing);
+ ObjectTypeDB::bind_method(_MD("is_follow_smoothing_enabled"),&Camera2D::is_follow_smoothing_enabled);
+
ObjectTypeDB::bind_method(_MD("force_update_scroll"),&Camera2D::force_update_scroll);
+ ObjectTypeDB::bind_method(_MD("_set_old_smoothing","follow_smoothing"),&Camera2D::_set_old_smoothing);
ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_offset"),_SCS("get_offset"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"anchor_mode",PROPERTY_HINT_ENUM,"Fixed TopLeft,Drag Center"),_SCS("set_anchor_mode"),_SCS("get_anchor_mode"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"rotating"),_SCS("set_rotating"),_SCS("is_rotating"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"current"),_SCS("_set_current"),_SCS("is_current"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"smoothing"),_SCS("set_follow_smoothing"),_SCS("get_follow_smoothing") );
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"zoom"),_SCS("set_zoom"),_SCS("get_zoom") );
ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit/left"),_SCS("set_limit"),_SCS("get_limit"),MARGIN_LEFT);
@@ -507,6 +531,12 @@ void Camera2D::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"drag_margin/h_enabled"),_SCS("set_h_drag_enabled"),_SCS("is_h_drag_enabled") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"drag_margin/v_enabled"),_SCS("set_v_drag_enabled"),_SCS("is_v_drag_enabled") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"smoothing/enable"),_SCS("set_enable_follow_smoothing"),_SCS("is_follow_smoothing_enabled") );
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"smoothing/speed"),_SCS("set_follow_smoothing"),_SCS("get_follow_smoothing") );
+
+ //compatibility
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"smoothing",PROPERTY_HINT_NONE,"",0),_SCS("_set_old_smoothing"),_SCS("get_follow_smoothing") );
+
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"drag_margin/left",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_drag_margin"),_SCS("get_drag_margin"),MARGIN_LEFT);
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"drag_margin/top",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_drag_margin"),_SCS("get_drag_margin"),MARGIN_TOP);
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"drag_margin/right",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_drag_margin"),_SCS("get_drag_margin"),MARGIN_RIGHT);
@@ -535,8 +565,9 @@ Camera2D::Camera2D() {
drag_margin[MARGIN_BOTTOM]=0.2;
camera_pos=Vector2();
first=true;
+ smoothing_enabled=false;
- smoothing=0.0;
+ smoothing=5.0;
zoom = Vector2(1, 1);
h_drag_enabled=true;
diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h
index 79d84f48d0..3c51bbf220 100644
--- a/scene/2d/camera_2d.h
+++ b/scene/2d/camera_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -59,6 +59,7 @@ protected:
bool rotating;
bool current;
float smoothing;
+ bool smoothing_enabled;
int limit[4];
float drag_margin[4];
@@ -73,6 +74,8 @@ protected:
void _make_current(Object *p_which);
void _set_current(bool p_current);
+
+ void _set_old_smoothing(float p_enable);
protected:
virtual Matrix32 get_camera_transform();
@@ -108,6 +111,9 @@ public:
void set_h_offset(float p_offset);
float get_h_offset() const;
+ void set_enable_follow_smoothing(bool p_enabled);
+ bool is_follow_smoothing_enabled() const;
+
void set_follow_smoothing(float p_speed);
float get_follow_smoothing() const;
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 357aaa225b..35b453d71d 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -309,6 +309,15 @@ void CanvasItem::hide() {
_change_notify("visibility/visible");
}
+void CanvasItem::set_hidden(bool p_hidden) {
+
+ if (hidden == p_hidden) {
+ return;
+ }
+
+ _set_visible_(!p_hidden);
+}
+
Variant CanvasItem::edit_get_state() const {
@@ -380,8 +389,8 @@ Matrix32 CanvasItem::get_global_transform_with_canvas() const {
if (last_valid->canvas_layer)
return last_valid->canvas_layer->get_transform() * xform;
- else
- return xform;
+ else if (is_inside_tree())
+ return get_viewport()->get_canvas_transform() * xform;
}
Matrix32 CanvasItem::get_global_transform() const {
@@ -539,6 +548,7 @@ void CanvasItem::_notification(int p_what) {
get_parent()->cast_to<CanvasItem>()->children_items.erase(C);
C=NULL;
}
+ global_invalid=true;
} break;
case NOTIFICATION_DRAW: {
@@ -700,7 +710,7 @@ void CanvasItem::draw_circle(const Point2& p_pos, float p_radius, const Color& p
}
-void CanvasItem::draw_texture(const Ref<Texture>& p_texture,const Point2& p_pos) {
+void CanvasItem::draw_texture(const Ref<Texture>& p_texture,const Point2& p_pos,const Color& p_modulate) {
if (!drawing) {
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
@@ -709,7 +719,7 @@ void CanvasItem::draw_texture(const Ref<Texture>& p_texture,const Point2& p_pos)
ERR_FAIL_COND(p_texture.is_null());
- p_texture->draw(canvas_item,p_pos);
+ p_texture->draw(canvas_item,p_pos,p_modulate);
}
void CanvasItem::draw_texture_rect(const Ref<Texture>& p_texture,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) {
@@ -764,7 +774,7 @@ void CanvasItem::draw_set_transform(const Point2& p_offset, float p_rot, const S
Matrix32 xform(p_rot,p_offset);
xform.scale_basis(p_scale);
- VisualServer::get_singleton()->canvas_item_set_transform(canvas_item,xform);
+ VisualServer::get_singleton()->canvas_item_add_set_transform(canvas_item,xform);
}
void CanvasItem::draw_polygon(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, Ref<Texture> p_texture) {
@@ -1043,6 +1053,7 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_hidden"),&CanvasItem::is_hidden);
ObjectTypeDB::bind_method(_MD("show"),&CanvasItem::show);
ObjectTypeDB::bind_method(_MD("hide"),&CanvasItem::hide);
+ ObjectTypeDB::bind_method(_MD("set_hidden","hidden"),&CanvasItem::set_hidden);
ObjectTypeDB::bind_method(_MD("update"),&CanvasItem::update);
@@ -1070,7 +1081,7 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("draw_line","from","to","color","width"),&CanvasItem::draw_line,DEFVAL(1.0));
ObjectTypeDB::bind_method(_MD("draw_rect","rect","color"),&CanvasItem::draw_rect);
ObjectTypeDB::bind_method(_MD("draw_circle","pos","radius","color"),&CanvasItem::draw_circle);
- ObjectTypeDB::bind_method(_MD("draw_texture","texture:Texture","pos"),&CanvasItem::draw_texture);
+ ObjectTypeDB::bind_method(_MD("draw_texture","texture:Texture","pos","modulate"),&CanvasItem::draw_texture,DEFVAL(Color(1,1,1,1)));
ObjectTypeDB::bind_method(_MD("draw_texture_rect","texture:Texture","rect","tile","modulate","transpose"),&CanvasItem::draw_texture_rect,DEFVAL(Color(1,1,1)),DEFVAL(false));
ObjectTypeDB::bind_method(_MD("draw_texture_rect_region","texture:Texture","rect","src_rect","modulate","transpose"),&CanvasItem::draw_texture_rect_region,DEFVAL(Color(1,1,1)),DEFVAL(false));
ObjectTypeDB::bind_method(_MD("draw_style_box","style_box:StyleBox","rect"),&CanvasItem::draw_style_box);
@@ -1146,6 +1157,8 @@ Matrix32 CanvasItem::get_canvas_transform() const {
if (canvas_layer)
return canvas_layer->get_transform();
+ else if (get_parent()->cast_to<CanvasItem>())
+ return get_parent()->cast_to<CanvasItem>()->get_canvas_transform();
else
return get_viewport()->get_canvas_transform();
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 4885256c64..5d10523261 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -190,13 +190,14 @@ public:
bool is_hidden() const;
void show();
void hide();
+ void set_hidden(bool p_hidden);
void update();
void set_blend_mode(BlendMode p_blend_mode);
BlendMode get_blend_mode() const;
- void set_light_mask(int p_light_mask);
+ virtual void set_light_mask(int p_light_mask);
int get_light_mask() const;
void set_opacity(float p_opacity);
@@ -210,7 +211,7 @@ public:
void draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width=1.0);
void draw_rect(const Rect2& p_rect, const Color& p_color);
void draw_circle(const Point2& p_pos, float p_radius, const Color& p_color);
- void draw_texture(const Ref<Texture>& p_texture,const Point2& p_pos);
+ void draw_texture(const Ref<Texture>& p_texture, const Point2& p_pos, const Color &p_modulate=Color(1,1,1,1));
void draw_texture_rect(const Ref<Texture>& p_texture, const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1), bool p_transpose=false);
void draw_texture_rect_region(const Ref<Texture>& p_texture,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1), bool p_transpose=false);
void draw_style_box(const Ref<StyleBox>& p_style_box,const Rect2& p_rect);
diff --git a/scene/2d/canvas_modulate.cpp b/scene/2d/canvas_modulate.cpp
index 82dd8012a5..77203a7110 100644
--- a/scene/2d/canvas_modulate.cpp
+++ b/scene/2d/canvas_modulate.cpp
@@ -5,10 +5,19 @@ void CanvasModulate::_notification(int p_what) {
if (p_what==NOTIFICATION_ENTER_CANVAS) {
- VS::get_singleton()->canvas_set_modulate(get_canvas(),color);
+ if (is_visible())
+ VS::get_singleton()->canvas_set_modulate(get_canvas(),color);
} else if (p_what==NOTIFICATION_EXIT_CANVAS) {
- VS::get_singleton()->canvas_set_modulate(get_canvas(),Color(1,1,1,1));
+ if (is_visible())
+ VS::get_singleton()->canvas_set_modulate(get_canvas(),Color(1,1,1,1));
+ } else if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+
+ if (is_visible()) {
+ VS::get_singleton()->canvas_set_modulate(get_canvas(),color);
+ } else {
+ VS::get_singleton()->canvas_set_modulate(get_canvas(),Color(1,1,1,1));
+ }
}
}
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index 809d2a95fa..3a45b0c84e 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h
index 473f13d0ff..fc50c5c7cd 100644
--- a/scene/2d/collision_object_2d.h
+++ b/scene/2d/collision_object_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index 1479cb7881..2a40a6207d 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,7 +30,7 @@
#include "collision_object_2d.h"
#include "scene/resources/concave_polygon_shape_2d.h"
#include "scene/resources/convex_polygon_shape_2d.h"
-
+#include "triangulator.h"
void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
if (unparenting || !can_update_body)
@@ -48,7 +48,7 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
//here comes the sun, lalalala
//decompose concave into multiple convex polygons and add them
- Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon);
+ Vector< Vector<Vector2> > decomp = _decompose_in_convex();
shape_from=co->get_shape_count();
for(int i=0;i<decomp.size();i++) {
Ref<ConvexPolygonShape2D> convex = memnew( ConvexPolygonShape2D );
@@ -106,6 +106,51 @@ void CollisionPolygon2D::_update_parent() {
co->_update_shapes_from_children();
}
+Vector< Vector<Vector2> > CollisionPolygon2D::_decompose_in_convex() {
+
+ Vector< Vector<Vector2> > decomp;
+#if 0
+ //fast but imprecise triangulator, gave us problems
+ decomp = Geometry::decompose_polygon(polygon);
+#else
+
+ List<TriangulatorPoly> in_poly,out_poly;
+
+ TriangulatorPoly inp;
+ inp.Init(polygon.size());
+ for(int i=0;i<polygon.size();i++) {
+ inp.GetPoint(i)=polygon[i];
+ }
+ inp.SetOrientation(TRIANGULATOR_CCW);
+ in_poly.push_back(inp);
+ TriangulatorPartition tpart;
+ if (tpart.ConvexPartition_HM(&in_poly,&out_poly)==0) { //failed!
+ ERR_PRINT("Convex decomposing failed!");
+ return decomp;
+ }
+
+ decomp.resize(out_poly.size());
+ int idx=0;
+
+ for(List<TriangulatorPoly>::Element*I = out_poly.front();I;I=I->next()) {
+
+ TriangulatorPoly& tp = I->get();
+
+ decomp[idx].resize(tp.GetNumPoints());
+
+ for(int i=0;i<tp.GetNumPoints();i++) {
+
+ decomp[idx][i]=tp.GetPoint(i);
+ }
+
+ idx++;
+ }
+
+#endif
+
+ return decomp;
+}
+
void CollisionPolygon2D::_notification(int p_what) {
@@ -113,6 +158,12 @@ void CollisionPolygon2D::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
unparenting=false;
can_update_body=get_tree()->is_editor_hint();
+ if (!get_tree()->is_editor_hint()) {
+ //display above all else
+ set_z_as_relative(false);
+ set_z(VS::CANVAS_ITEM_Z_MAX-1);
+ }
+
} break;
case NOTIFICATION_EXIT_TREE: {
can_update_body=false;
@@ -146,10 +197,11 @@ void CollisionPolygon2D::_notification(int p_what) {
Vector2 n = polygon[(i+1)%polygon.size()];
draw_line(p,n,Color(0.9,0.2,0.0,0.8),3);
}
-//#define DEBUG_DECOMPOSE
+#define DEBUG_DECOMPOSE
#if defined(TOOLS_ENABLED) && defined (DEBUG_DECOMPOSE)
- Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon);
+ Vector< Vector<Vector2> > decomp = _decompose_in_convex();
+
Color c(0.4,0.9,0.1);
for(int i=0;i<decomp.size();i++) {
@@ -251,10 +303,10 @@ void CollisionPolygon2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&CollisionPolygon2D::set_polygon);
ObjectTypeDB::bind_method(_MD("get_polygon"),&CollisionPolygon2D::get_polygon);
- ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon2D::set_build_mode);
+ ObjectTypeDB::bind_method(_MD("set_build_mode","build_mode"),&CollisionPolygon2D::set_build_mode);
ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon2D::get_build_mode);
- ObjectTypeDB::bind_method(_MD("set_trigger"),&CollisionPolygon2D::set_trigger);
+ ObjectTypeDB::bind_method(_MD("set_trigger","trigger"),&CollisionPolygon2D::set_trigger);
ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionPolygon2D::is_trigger);
ObjectTypeDB::bind_method(_MD("_set_shape_range","shape_range"),&CollisionPolygon2D::_set_shape_range);
diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h
index 4bc9713c8a..b2bd4d189d 100644
--- a/scene/2d/collision_polygon_2d.h
+++ b/scene/2d/collision_polygon_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -63,6 +63,7 @@ protected:
void _set_shape_range(const Vector2& p_range);
Vector2 _get_shape_range() const;
+ Vector< Vector<Vector2> > _decompose_in_convex();
protected:
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp
index 85751fc735..405310450b 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/collision_shape_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -77,6 +77,11 @@ void CollisionShape2D::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
unparenting=false;
can_update_body=get_tree()->is_editor_hint();
+ if (!get_tree()->is_editor_hint()) {
+ //display above all else
+ set_z_as_relative(false);
+ set_z(VS::CANVAS_ITEM_Z_MAX-1);
+ }
} break;
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
@@ -120,6 +125,7 @@ void CollisionShape2D::_notification(int p_what) {
rect=Rect2();
+
Color draw_col=get_tree()->get_debug_collisions_color();
shape->draw(get_canvas_item(),draw_col);
diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h
index 82e1137174..b14dad73ba 100644
--- a/scene/2d/collision_shape_2d.h
+++ b/scene/2d/collision_shape_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp
index 1df936535f..053fc2c9c2 100644
--- a/scene/2d/joints_2d.cpp
+++ b/scene/2d/joints_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -111,6 +111,19 @@ real_t Joint2D::get_bias() const{
return bias;
}
+void Joint2D::set_exclude_nodes_from_collision(bool p_enable) {
+
+ if (exclude_from_collision==p_enable)
+ return;
+ exclude_from_collision=p_enable;
+ _update_joint();
+}
+
+bool Joint2D::get_exclude_nodes_from_collision() const{
+
+ return exclude_from_collision;
+}
+
void Joint2D::_bind_methods() {
@@ -124,9 +137,14 @@ void Joint2D::_bind_methods() {
ObjectTypeDB::bind_method( _MD("set_bias","bias"), &Joint2D::set_bias );
ObjectTypeDB::bind_method( _MD("get_bias"), &Joint2D::get_bias );
+ ObjectTypeDB::bind_method( _MD("set_exclude_nodes_from_collision","enable"), &Joint2D::set_exclude_nodes_from_collision );
+ ObjectTypeDB::bind_method( _MD("get_exclude_nodes_from_collision"), &Joint2D::get_exclude_nodes_from_collision );
+
ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "node_a"), _SCS("set_node_a"),_SCS("get_node_a") );
ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "node_b"), _SCS("set_node_b"),_SCS("get_node_b") );
ADD_PROPERTY( PropertyInfo( Variant::REAL, "bias/bias",PROPERTY_HINT_RANGE,"0,0.9,0.001"), _SCS("set_bias"),_SCS("get_bias") );
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "collision/exclude_nodes"), _SCS("set_exclude_nodes_from_collision"),_SCS("get_exclude_nodes_from_collision") );
+
}
@@ -135,6 +153,7 @@ void Joint2D::_bind_methods() {
Joint2D::Joint2D() {
bias=0;
+ exclude_from_collision=true;
}
///////////////////////////////////////////////////////////////////////////////
@@ -145,11 +164,17 @@ void PinJoint2D::_notification(int p_what) {
switch(p_what) {
case NOTIFICATION_DRAW: {
- if (is_inside_tree() && get_tree()->is_editor_hint()) {
- draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3);
- draw_line(Point2(0,-10),Point2(0,+10),Color(0.7,0.6,0.0,0.5),3);
+ if (!is_inside_tree())
+ break;
+
+ if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
+ break;
}
+
+
+ draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3);
+ draw_line(Point2(0,-10),Point2(0,+10),Color(0.7,0.6,0.0,0.5),3);
} break;
}
@@ -173,7 +198,10 @@ RID PinJoint2D::_configure_joint() {
SWAP(body_a,body_b);
} else if (body_b) {
//add a collision exception between both
- Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(),body_b->get_rid());
+ if (get_exclude_nodes_from_collision())
+ Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(),body_b->get_rid());
+ else
+ Physics2DServer::get_singleton()->body_remove_collision_exception(body_a->get_rid(),body_b->get_rid());
}
RID pj = Physics2DServer::get_singleton()->pin_joint_create(get_global_transform().get_origin(),body_a->get_rid(),body_b?body_b->get_rid():RID());
Physics2DServer::get_singleton()->pin_joint_set_param(pj, Physics2DServer::PIN_JOINT_SOFTNESS, softness);
@@ -219,13 +247,17 @@ void GrooveJoint2D::_notification(int p_what) {
switch(p_what) {
case NOTIFICATION_DRAW: {
- if (is_inside_tree() && get_tree()->is_editor_hint()) {
+ if (!is_inside_tree())
+ break;
- draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3);
- draw_line(Point2(-10,length),Point2(+10,length),Color(0.7,0.6,0.0,0.5),3);
- draw_line(Point2(0,0),Point2(0,length),Color(0.7,0.6,0.0,0.5),3);
- draw_line(Point2(-10,initial_offset),Point2(+10,initial_offset),Color(0.8,0.8,0.9,0.5),5);
+ if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
+ break;
}
+
+ draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3);
+ draw_line(Point2(-10,length),Point2(+10,length),Color(0.7,0.6,0.0,0.5),3);
+ draw_line(Point2(0,0),Point2(0,length),Color(0.7,0.6,0.0,0.5),3);
+ draw_line(Point2(-10,initial_offset),Point2(+10,initial_offset),Color(0.8,0.8,0.9,0.5),5);
} break;
}
}
@@ -245,7 +277,11 @@ RID GrooveJoint2D::_configure_joint(){
if (!body_a || !body_b)
return RID();
- Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(),body_b->get_rid());
+
+ if (get_exclude_nodes_from_collision())
+ Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(),body_b->get_rid());
+ else
+ Physics2DServer::get_singleton()->body_remove_collision_exception(body_a->get_rid(),body_b->get_rid());
Matrix32 gt = get_global_transform();
Vector2 groove_A1 = gt.get_origin();
@@ -313,12 +349,17 @@ void DampedSpringJoint2D::_notification(int p_what) {
switch(p_what) {
case NOTIFICATION_DRAW: {
- if (is_inside_tree() && get_tree()->is_editor_hint()) {
- draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3);
- draw_line(Point2(-10,length),Point2(+10,length),Color(0.7,0.6,0.0,0.5),3);
- draw_line(Point2(0,0),Point2(0,length),Color(0.7,0.6,0.0,0.5),3);
+ if (!is_inside_tree())
+ break;
+
+ if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
+ break;
}
+
+ draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3);
+ draw_line(Point2(-10,length),Point2(+10,length),Color(0.7,0.6,0.0,0.5),3);
+ draw_line(Point2(0,0),Point2(0,length),Color(0.7,0.6,0.0,0.5),3);
} break;
}
}
@@ -338,7 +379,10 @@ RID DampedSpringJoint2D::_configure_joint(){
if (!body_a || !body_b)
return RID();
- Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(),body_b->get_rid());
+ if (get_exclude_nodes_from_collision())
+ Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(),body_b->get_rid());
+ else
+ Physics2DServer::get_singleton()->body_remove_collision_exception(body_a->get_rid(),body_b->get_rid());
Matrix32 gt = get_global_transform();
Vector2 anchor_A = gt.get_origin();
diff --git a/scene/2d/joints_2d.h b/scene/2d/joints_2d.h
index 908e3a158e..52ffd86e7c 100644
--- a/scene/2d/joints_2d.h
+++ b/scene/2d/joints_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,6 +42,8 @@ class Joint2D : public Node2D {
NodePath b;
real_t bias;
+ bool exclude_from_collision;
+
protected:
@@ -62,6 +64,9 @@ public:
void set_bias(real_t p_bias);
real_t get_bias() const;
+ void set_exclude_nodes_from_collision(bool p_enable);
+ bool get_exclude_nodes_from_collision() const;
+
RID get_joint() const { return joint; }
Joint2D();
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 852a6fb46b..9715afeaa4 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -34,10 +34,19 @@ Rect2 Light2D::get_item_rect() const {
}
+void Light2D::_update_light_visibility() {
+
+ if (!is_inside_tree())
+ return;
+
+ VS::get_singleton()->canvas_light_set_enabled(canvas_light,enabled && is_visible());
+}
+
void Light2D::set_enabled( bool p_enabled) {
- VS::get_singleton()->canvas_light_set_enabled(canvas_light,p_enabled);
+
enabled=p_enabled;
+ _update_light_visibility();
}
bool Light2D::is_enabled() const {
@@ -253,16 +262,22 @@ void Light2D::_notification(int p_what) {
if (p_what==NOTIFICATION_ENTER_TREE) {
VS::get_singleton()->canvas_light_attach_to_canvas( canvas_light, get_canvas() );
+ _update_light_visibility();
}
if (p_what==NOTIFICATION_TRANSFORM_CHANGED) {
VS::get_singleton()->canvas_light_set_transform( canvas_light, get_global_transform());
}
+ if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+
+ _update_light_visibility();
+ }
if (p_what==NOTIFICATION_EXIT_TREE) {
VS::get_singleton()->canvas_light_attach_to_canvas( canvas_light, RID() );
+ _update_light_visibility();
}
}
@@ -333,7 +348,7 @@ void Light2D::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::REAL,"scale",PROPERTY_HINT_RANGE,"0.01,4096,0.01"),_SCS("set_texture_scale"),_SCS("get_texture_scale"));
ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"energy"),_SCS("set_energy"),_SCS("get_energy"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Add,Sub,Mix"),_SCS("set_mode"),_SCS("get_mode"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Add,Sub,Mix,Mask"),_SCS("set_mode"),_SCS("get_mode"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"range/height"),_SCS("set_height"),_SCS("get_height"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max"));
@@ -349,6 +364,7 @@ void Light2D::_bind_methods() {
BIND_CONSTANT( MODE_ADD );
BIND_CONSTANT( MODE_SUB );
BIND_CONSTANT( MODE_MIX );
+ BIND_CONSTANT( MODE_MASK );
}
diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h
index bf61868bac..ca437769e7 100644
--- a/scene/2d/light_2d.h
+++ b/scene/2d/light_2d.h
@@ -11,6 +11,7 @@ public:
MODE_ADD,
MODE_SUB,
MODE_MIX,
+ MODE_MASK,
};
private:
@@ -34,6 +35,7 @@ private:
Ref<Texture> texture;
Vector2 texture_offset;
+ void _update_light_visibility();
protected:
void _notification(int p_what);
diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp
index 6ebd499f71..d98bed0ea3 100644
--- a/scene/2d/light_occluder_2d.cpp
+++ b/scene/2d/light_occluder_2d.cpp
@@ -93,12 +93,17 @@ void LightOccluder2D::_notification(int p_what) {
VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder,get_canvas());
VS::get_singleton()->canvas_light_occluder_set_transform(occluder,get_global_transform());
+ VS::get_singleton()->canvas_light_occluder_set_enabled(occluder,is_visible());
}
if (p_what==NOTIFICATION_TRANSFORM_CHANGED) {
VS::get_singleton()->canvas_light_occluder_set_transform(occluder,get_global_transform());
}
+ if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+
+ VS::get_singleton()->canvas_light_occluder_set_enabled(occluder,is_visible());
+ }
if (p_what==NOTIFICATION_DRAW) {
diff --git a/scene/2d/navigation2d.cpp b/scene/2d/navigation2d.cpp
index b7d51730a0..fe1760b84a 100644
--- a/scene/2d/navigation2d.cpp
+++ b/scene/2d/navigation2d.cpp
@@ -494,7 +494,29 @@ Vector<Vector2> Navigation2D::get_simple_path(const Vector2& p_start, const Vect
open_list.erase(least_cost_poly);
}
-
+#if 0
+debug path
+ {
+ Polygon *p=end_poly;
+ int idx=0;
+
+ while(true) {
+ int prev = p->prev_edge;
+ int prev_n = (p->prev_edge+1)%p->edges.size();
+ Vector2 point = (_get_vertex(p->edges[prev].point) + _get_vertex(p->edges[prev_n].point))*0.5;
+ String points;
+ for(int i=0;i<p->edges.size();i++) {
+ if (i>0)
+ points+=", ";
+ points+=_get_vertex(p->edges[i].point);
+ }
+ //print_line("poly "+itos(idx++)+" - "+points);
+ p = p->edges[prev].C;
+ if (p==begin_poly)
+ break;
+ }
+ }
+#endif
if (found_route) {
Vector<Vector2> path;
@@ -538,22 +560,29 @@ Vector<Vector2> Navigation2D::get_simple_path(const Vector2& p_start, const Vect
bool skip=false;
- /* print_line("-----\nAPEX: "+(apex_point-end_point));
+ /*
+ print_line("-----\nAPEX: "+(apex_point-end_point));
print_line("LEFT:");
print_line("\tPortal: "+(portal_left-end_point));
print_line("\tPoint: "+(left-end_point));
- print_line("\tFree: "+itos(CLOCK_TANGENT(apex_point,portal_left,left) >= 0));
+ print_line("\tLeft Tangent: "+rtos(CLOCK_TANGENT(apex_point,portal_left,left)));
+ print_line("\tLeft Distance: "+rtos(portal_left.distance_squared_to(apex_point)));
+ print_line("\tLeft Test: "+rtos(CLOCK_TANGENT(apex_point,left,portal_right)));
print_line("RIGHT:");
print_line("\tPortal: "+(portal_right-end_point));
print_line("\tPoint: "+(right-end_point));
- print_line("\tFree: "+itos(CLOCK_TANGENT(apex_point,portal_right,right) <= 0));
-*/
+ print_line("\tRight Tangent: "+rtos(CLOCK_TANGENT(apex_point,portal_right,right)));
+ print_line("\tRight Distance: "+rtos(portal_right.distance_squared_to(apex_point)));
+ print_line("\tRight Test: "+rtos(CLOCK_TANGENT(apex_point,right,portal_left)));
+ */
+
if (CLOCK_TANGENT(apex_point,portal_left,left) >= 0){
//process
if (portal_left.distance_squared_to(apex_point)<CMP_EPSILON || CLOCK_TANGENT(apex_point,left,portal_right) > 0) {
left_poly=p;
portal_left=left;
+ //print_line("***ADVANCE LEFT");
} else {
//_clip_path(path,apex_poly,portal_right,right_poly);
@@ -568,6 +597,7 @@ Vector<Vector2> Navigation2D::get_simple_path(const Vector2& p_start, const Vect
path.push_back(apex_point);
skip=true;
//print_line("addpoint left");
+ //print_line("***CLIP LEFT");
}
}
@@ -576,6 +606,7 @@ Vector<Vector2> Navigation2D::get_simple_path(const Vector2& p_start, const Vect
if (portal_right.distance_squared_to(apex_point)<CMP_EPSILON || CLOCK_TANGENT(apex_point,right,portal_left) < 0) {
right_poly=p;
portal_right=right;
+ //print_line("***ADVANCE RIGHT");
} else {
//_clip_path(path,apex_poly,portal_left,left_poly);
@@ -589,6 +620,7 @@ Vector<Vector2> Navigation2D::get_simple_path(const Vector2& p_start, const Vect
if (path[path.size()-1].distance_to(apex_point)>CMP_EPSILON)
path.push_back(apex_point);
//print_line("addpoint right");
+ //print_line("***CLIP RIGHT");
}
}
diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp
index 792f079ab0..4c00d8cec9 100644
--- a/scene/2d/navigation_polygon.cpp
+++ b/scene/2d/navigation_polygon.cpp
@@ -273,7 +273,7 @@ void NavigationPolygonInstance::set_enabled(bool p_enabled) {
if (navpoly.is_valid()) {
- nav_id = navigation->navpoly_create(navpoly,get_relative_transform(navigation),this);
+ nav_id = navigation->navpoly_create(navpoly,get_relative_transform_to_parent(navigation),this);
}
}
@@ -309,7 +309,7 @@ void NavigationPolygonInstance::_notification(int p_what) {
if (enabled && navpoly.is_valid()) {
- nav_id = navigation->navpoly_create(navpoly,get_relative_transform(navigation),this);
+ nav_id = navigation->navpoly_create(navpoly,get_relative_transform_to_parent(navigation),this);
}
break;
}
@@ -321,7 +321,7 @@ void NavigationPolygonInstance::_notification(int p_what) {
case NOTIFICATION_TRANSFORM_CHANGED: {
if (navigation && nav_id!=-1) {
- navigation->navpoly_set_transform(nav_id,get_relative_transform(navigation));
+ navigation->navpoly_set_transform(nav_id,get_relative_transform_to_parent(navigation));
}
} break;
@@ -409,7 +409,7 @@ void NavigationPolygonInstance::set_navigation_polygon(const Ref<NavigationPolyg
}
if (navigation && navpoly.is_valid() && enabled) {
- nav_id = navigation->navpoly_create(navpoly,get_relative_transform(navigation),this);
+ nav_id = navigation->navpoly_create(navpoly,get_relative_transform_to_parent(navigation),this);
}
//update_gizmo();
_change_notify("navpoly");
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 52b112f090..7ef81306b6 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -333,17 +333,18 @@ int Node2D::get_z() const{
return z;
}
-Matrix32 Node2D::get_relative_transform(const Node *p_parent) const {
+Matrix32 Node2D::get_relative_transform_to_parent(const Node *p_parent) const {
if (p_parent==this)
return Matrix32();
Node2D *parent_2d = get_parent()->cast_to<Node2D>();
+
ERR_FAIL_COND_V(!parent_2d,Matrix32());
if (p_parent==parent_2d)
return get_transform();
else
- return parent_2d->get_relative_transform(p_parent) * get_transform();
+ return parent_2d->get_relative_transform_to_parent(p_parent) * get_transform();
}
@@ -394,9 +395,9 @@ void Node2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_z_as_relative","enable"),&Node2D::set_z_as_relative);
ObjectTypeDB::bind_method(_MD("is_z_relative"),&Node2D::is_z_relative);
- ObjectTypeDB::bind_method(_MD("edit_set_pivot"),&Node2D::edit_set_pivot);
+ ObjectTypeDB::bind_method(_MD("edit_set_pivot","pivot"),&Node2D::edit_set_pivot);
- ObjectTypeDB::bind_method(_MD("get_relative_transform"),&Node2D::get_relative_transform);
+ ObjectTypeDB::bind_method(_MD("get_relative_transform_to_parent","parent"),&Node2D::get_relative_transform_to_parent);
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"transform/pos"),_SCS("set_pos"),_SCS("get_pos"));
ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"transform/rot",PROPERTY_HINT_RANGE,"-1440,1440,0.1"),_SCS("_set_rotd"),_SCS("_get_rotd"));
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index 8efce33cda..49d616fc1f 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -99,7 +99,7 @@ public:
void set_z_as_relative(bool p_enabled);
bool is_z_relative() const;
- Matrix32 get_relative_transform(const Node *p_parent) const;
+ Matrix32 get_relative_transform_to_parent(const Node *p_parent) const;
diff --git a/scene/2d/node_2d_singleton.cpp b/scene/2d/node_2d_singleton.cpp
index 361edf7587..b26804fedf 100644
--- a/scene/2d/node_2d_singleton.cpp
+++ b/scene/2d/node_2d_singleton.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/node_2d_singleton.h b/scene/2d/node_2d_singleton.h
index 6a21db2221..0aa6bbf992 100644
--- a/scene/2d/node_2d_singleton.h
+++ b/scene/2d/node_2d_singleton.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/parallax_background.cpp b/scene/2d/parallax_background.cpp
index 8bb4eb55ba..7f2e9efd96 100644
--- a/scene/2d/parallax_background.cpp
+++ b/scene/2d/parallax_background.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -193,7 +193,7 @@ void ParallaxBackground::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_limit_begin"),&ParallaxBackground::get_limit_begin);
ObjectTypeDB::bind_method(_MD("set_limit_end","ofs"),&ParallaxBackground::set_limit_end);
ObjectTypeDB::bind_method(_MD("get_limit_end"),&ParallaxBackground::get_limit_end);
- ObjectTypeDB::bind_method(_MD("set_ignore_camera_zoom"), &ParallaxBackground::set_ignore_camera_zoom);
+ ObjectTypeDB::bind_method(_MD("set_ignore_camera_zoom","ignore"), &ParallaxBackground::set_ignore_camera_zoom);
ObjectTypeDB::bind_method(_MD("is_ignore_camera_zoom"), &ParallaxBackground::is_ignore_camera_zoom);
diff --git a/scene/2d/parallax_background.h b/scene/2d/parallax_background.h
index 8dede07a16..bdaf7d241f 100644
--- a/scene/2d/parallax_background.h
+++ b/scene/2d/parallax_background.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp
index 70612d7c9a..7a898e43c9 100644
--- a/scene/2d/parallax_layer.cpp
+++ b/scene/2d/parallax_layer.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/parallax_layer.h b/scene/2d/parallax_layer.h
index 8fe2846897..6c24a9b9f7 100644
--- a/scene/2d/parallax_layer.h
+++ b/scene/2d/parallax_layer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp
index 8f805ceba2..5b13c32d93 100644
--- a/scene/2d/particles_2d.cpp
+++ b/scene/2d/particles_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -697,7 +697,7 @@ bool Particles2D::is_emitting() const {
void Particles2D::set_amount(int p_amount) {
- ERR_FAIL_INDEX(p_amount,1024);
+ ERR_FAIL_INDEX(p_amount,1024+1);
particles.resize(p_amount);
}
@@ -719,7 +719,7 @@ float Particles2D::get_emit_timeout() const {
void Particles2D::set_lifetime(float p_lifetime) {
- ERR_FAIL_INDEX(p_lifetime,3600);
+ ERR_FAIL_INDEX(p_lifetime,3600+1);
lifetime=p_lifetime;
}
@@ -994,6 +994,15 @@ DVector<Vector2> Particles2D::get_emission_points() const{
return emission_points;
}
+void Particles2D::reset() {
+
+ for(int i=0;i<particles.size();i++) {
+ particles[i].active=false;
+ }
+ time=0;
+ active_count=0;
+}
+
void Particles2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_emitting","active"),&Particles2D::set_emitting);
@@ -1057,6 +1066,7 @@ void Particles2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_color_phase_pos","phase"),&Particles2D::get_color_phase_pos);
ObjectTypeDB::bind_method(_MD("pre_process","time"),&Particles2D::pre_process);
+ ObjectTypeDB::bind_method(_MD("reset"),&Particles2D::reset);
ObjectTypeDB::bind_method(_MD("set_use_local_space","enable"),&Particles2D::set_use_local_space);
ObjectTypeDB::bind_method(_MD("is_using_local_space"),&Particles2D::is_using_local_space);
diff --git a/scene/2d/particles_2d.h b/scene/2d/particles_2d.h
index 4ee0fcf8da..101395589e 100644
--- a/scene/2d/particles_2d.h
+++ b/scene/2d/particles_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -248,6 +248,7 @@ public:
DVector<Vector2> get_emission_points() const;
void pre_process(float p_delta);
+ void reset();
Particles2D();
};
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index 8f110b3931..bd7415aa04 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,9 +31,13 @@
void Path2D::_notification(int p_what) {
- if (p_what==NOTIFICATION_DRAW && curve.is_valid() && is_inside_tree() && get_tree()->is_editor_hint()) {
+ if (p_what==NOTIFICATION_DRAW && curve.is_valid()) {
//draw the curve!!
+ if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_navigation_hint()) {
+ return;
+ }
+
for(int i=0;i<curve->get_point_count();i++) {
Vector2 prev_p=curve->get_point_pos(i);
@@ -70,6 +74,8 @@ void Path2D::set_curve(const Ref<Curve2D>& p_curve) {
curve->connect("changed",this,"_curve_changed");
}
+ _curve_changed();
+
}
Ref<Curve2D> Path2D::get_curve() const{
diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h
index c9114c5d7d..486a8ac9ac 100644
--- a/scene/2d/path_2d.h
+++ b/scene/2d/path_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index c30921eb69..cc2e5c0d72 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -310,14 +310,20 @@ void RigidBody2D::_body_enter_tree(ObjectID p_id) {
ERR_FAIL_COND(!E);
ERR_FAIL_COND(E->get().in_scene);
+ contact_monitor->locked=true;
+
E->get().in_scene=true;
emit_signal(SceneStringNames::get_singleton()->body_enter,node);
+
for(int i=0;i<E->get().shapes.size();i++) {
emit_signal(SceneStringNames::get_singleton()->body_enter_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].local_shape);
}
+ contact_monitor->locked=false;
+
+
}
void RigidBody2D::_body_exit_tree(ObjectID p_id) {
@@ -329,11 +335,18 @@ void RigidBody2D::_body_exit_tree(ObjectID p_id) {
ERR_FAIL_COND(!E);
ERR_FAIL_COND(!E->get().in_scene);
E->get().in_scene=false;
+
+ contact_monitor->locked=true;
+
emit_signal(SceneStringNames::get_singleton()->body_exit,node);
+
for(int i=0;i<E->get().shapes.size();i++) {
emit_signal(SceneStringNames::get_singleton()->body_exit_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].local_shape);
}
+
+ contact_monitor->locked=false;
+
}
void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shape,int p_local_shape) {
@@ -439,6 +452,8 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
if (contact_monitor) {
+ contact_monitor->locked=true;
+
//untag all
int rc=0;
for( Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
@@ -520,6 +535,8 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
_body_inout(1,toadd[i].id,toadd[i].shape,toadd[i].local_shape);
}
+ contact_monitor->locked=false;
+
}
set_block_transform_notify(true); // don't want notify (would feedback loop)
@@ -803,6 +820,11 @@ void RigidBody2D::set_contact_monitor(bool p_enabled) {
if (!p_enabled) {
+ if (contact_monitor->locked) {
+ ERR_EXPLAIN("Can't disable contact monitoring during in/out callback. Use call_deferred(\"set_contact_monitor\",false) instead");
+ }
+ ERR_FAIL_COND(contact_monitor->locked);
+
for(Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
//clean up mess
@@ -813,6 +835,7 @@ void RigidBody2D::set_contact_monitor(bool p_enabled) {
} else {
contact_monitor = memnew( ContactMonitor );
+ contact_monitor->locked=false;
}
}
@@ -1250,7 +1273,7 @@ void KinematicBody2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_collider_velocity"),&KinematicBody2D::get_collider_velocity);
ObjectTypeDB::bind_method(_MD("get_collider:Object"),&KinematicBody2D::_get_collider);
ObjectTypeDB::bind_method(_MD("get_collider_shape"),&KinematicBody2D::get_collider_shape);
- ObjectTypeDB::bind_method(_MD("get_collider_metadata"),&KinematicBody2D::get_collider_metadata);
+ ObjectTypeDB::bind_method(_MD("get_collider_metadata:Variant"),&KinematicBody2D::get_collider_metadata);
ObjectTypeDB::bind_method(_MD("set_collision_margin","pixels"),&KinematicBody2D::set_collision_margin);
ObjectTypeDB::bind_method(_MD("get_collision_margin","pixels"),&KinematicBody2D::get_collision_margin);
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index b70fdd59cf..999e63dd5d 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -190,7 +190,7 @@ private:
struct ContactMonitor {
-
+ bool locked;
Map<ObjectID,BodyState> body_map;
};
diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp
index f1591b5242..c293305cb2 100644
--- a/scene/2d/position_2d.cpp
+++ b/scene/2d/position_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/position_2d.h b/scene/2d/position_2d.h
index 16404e6ce8..23821e62d4 100644
--- a/scene/2d/position_2d.h
+++ b/scene/2d/position_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp
index 4a199e3418..4a774b0198 100644
--- a/scene/2d/ray_cast_2d.cpp
+++ b/scene/2d/ray_cast_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h
index 8c3ce8b3b3..54ec42c53e 100644
--- a/scene/2d/ray_cast_2d.h
+++ b/scene/2d/ray_cast_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp
index 0fbd140cfb..6dcd980822 100644
--- a/scene/2d/remote_transform_2d.cpp
+++ b/scene/2d/remote_transform_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/remote_transform_2d.h b/scene/2d/remote_transform_2d.h
index 506bde8cd8..4a5f5f72ea 100644
--- a/scene/2d/remote_transform_2d.h
+++ b/scene/2d/remote_transform_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/sample_player_2d.cpp b/scene/2d/sample_player_2d.cpp
index ec17ffc55e..bf09130238 100644
--- a/scene/2d/sample_player_2d.cpp
+++ b/scene/2d/sample_player_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/sample_player_2d.h b/scene/2d/sample_player_2d.h
index c0f2734ad1..eddf84f77b 100644
--- a/scene/2d/sample_player_2d.h
+++ b/scene/2d/sample_player_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp
index 0c3987e6b1..fac94f19dc 100644
--- a/scene/2d/screen_button.cpp
+++ b/scene/2d/screen_button.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -102,6 +102,10 @@ void TouchScreenButton::_notification(int p_what) {
action_id=-1;
}
} break;
+ case NOTIFICATION_EXIT_TREE: {
+ if (is_pressed())
+ Input::get_singleton()->action_release(action);
+ } break;
}
}
@@ -161,7 +165,7 @@ void TouchScreenButton::_input(const InputEvent& p_event) {
if (finger_pressed==-1 || p_event.screen_touch.index==finger_pressed) {
- Point2 coord = (get_global_transform()).affine_inverse().xform(Point2(p_event.screen_touch.x,p_event.screen_touch.y));
+ Point2 coord = (get_global_transform_with_canvas()).affine_inverse().xform(Point2(p_event.screen_touch.x,p_event.screen_touch.y));
bool touched=false;
if (bitmask.is_valid()) {
@@ -238,7 +242,7 @@ void TouchScreenButton::_input(const InputEvent& p_event) {
if (finger_pressed!=-1)
return; //already fingering
- Point2 coord = (get_global_transform()).affine_inverse().xform(Point2(p_event.screen_touch.x,p_event.screen_touch.y));
+ Point2 coord = (get_global_transform_with_canvas()).affine_inverse().xform(Point2(p_event.screen_touch.x,p_event.screen_touch.y));
bool touched=false;
if (bitmask.is_valid()) {
diff --git a/scene/2d/screen_button.h b/scene/2d/screen_button.h
index 159b829079..ff3b50bf5e 100644
--- a/scene/2d/screen_button.h
+++ b/scene/2d/screen_button.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/sound_player_2d.cpp b/scene/2d/sound_player_2d.cpp
index 0eb18866af..41ce87faf9 100644
--- a/scene/2d/sound_player_2d.cpp
+++ b/scene/2d/sound_player_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/sound_player_2d.h b/scene/2d/sound_player_2d.h
index a376cdbed7..0e75887235 100644
--- a/scene/2d/sound_player_2d.h
+++ b/scene/2d/sound_player_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index 89d9966958..001a1366a9 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h
index ad782e746b..cbcaec9aeb 100644
--- a/scene/2d/sprite.h
+++ b/scene/2d/sprite.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 167b637bdc..179d1f451a 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,6 +32,8 @@
#include "method_bind_ext.inc"
#include "os/os.h"
+
+
int TileMap::_get_quadrant_size() const {
if (y_sort_mode)
@@ -116,7 +118,7 @@ void TileMap::_update_quadrant_transform() {
Matrix32 nav_rel;
if (navigation)
- nav_rel = get_relative_transform(navigation);
+ nav_rel = get_relative_transform_to_parent(navigation);
for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
@@ -221,6 +223,14 @@ void TileMap::_fix_cell_transform(Matrix32& xform,const Cell& p_cell, const Vect
Size2 s=p_sc;
Vector2 offset = p_offset;
+ if (s.y > s.x) {
+ if ((p_cell.flip_h && (p_cell.flip_v || p_cell.transpose)) || (p_cell.flip_v && !p_cell.transpose))
+ offset.y += s.y - s.x;
+ } else if (s.y < s.x) {
+ if ((p_cell.flip_v && (p_cell.flip_h || p_cell.transpose)) || (p_cell.flip_h && !p_cell.transpose))
+ offset.x += s.x - s.y;
+ }
+
if (p_cell.transpose) {
SWAP(xform.elements[0].x, xform.elements[0].y);
SWAP(xform.elements[1].x, xform.elements[1].y);
@@ -259,7 +269,7 @@ void TileMap::_update_dirty_quadrants() {
Vector2 tcenter = cell_size/2;
Matrix32 nav_rel;
if (navigation)
- nav_rel = get_relative_transform(navigation);
+ nav_rel = get_relative_transform_to_parent(navigation);
Vector2 qofs;
@@ -299,6 +309,7 @@ void TileMap::_update_dirty_quadrants() {
q.occluder_instances.clear();
Ref<CanvasItemMaterial> prev_material;
RID prev_canvas_item;
+ RID prev_debug_canvas_item;
for(int i=0;i<q.cells.size();i++) {
@@ -319,6 +330,7 @@ void TileMap::_update_dirty_quadrants() {
Ref<CanvasItemMaterial> mat = tile_set->tile_get_material(c.id);
RID canvas_item;
+ RID debug_canvas_item;
if (prev_canvas_item==RID() || prev_material!=mat) {
@@ -329,13 +341,28 @@ void TileMap::_update_dirty_quadrants() {
Matrix32 xform;
xform.set_origin( q.pos );
vs->canvas_item_set_transform( canvas_item, xform );
+ vs->canvas_item_set_light_mask(canvas_item,get_light_mask());
+
q.canvas_items.push_back(canvas_item);
+ if (debug_shapes) {
+
+ debug_canvas_item=vs->canvas_item_create();
+ vs->canvas_item_set_parent( debug_canvas_item, canvas_item );
+ vs->canvas_item_set_z_as_relative_to_parent(debug_canvas_item,false);
+ vs->canvas_item_set_z(debug_canvas_item,VS::CANVAS_ITEM_Z_MAX-1);
+ q.canvas_items.push_back(debug_canvas_item);
+ prev_debug_canvas_item=debug_canvas_item;
+ }
+
prev_canvas_item=canvas_item;
prev_material=mat;
} else {
canvas_item=prev_canvas_item;
+ if (debug_shapes) {
+ debug_canvas_item=prev_debug_canvas_item;
+ }
}
@@ -357,13 +384,28 @@ void TileMap::_update_dirty_quadrants() {
rect.pos=offset.floor();
rect.size=s;
+ if (rect.size.y > rect.size.x) {
+ if ((c.flip_h && (c.flip_v || c.transpose)) || (c.flip_v && !c.transpose))
+ tile_ofs.y += rect.size.y - rect.size.x;
+ } else if (rect.size.y < rect.size.x) {
+ if ((c.flip_v && (c.flip_h || c.transpose)) || (c.flip_h && !c.transpose))
+ tile_ofs.x += rect.size.x - rect.size.y;
+ }
+
/* rect.size.x+=fp_adjust;
rect.size.y+=fp_adjust;*/
- if (c.flip_h)
+ if (c.transpose)
+ SWAP(tile_ofs.x, tile_ofs.y);
+
+ if (c.flip_h) {
rect.size.x=-rect.size.x;
- if (c.flip_v)
+ tile_ofs.x=-tile_ofs.x;
+ }
+ if (c.flip_v) {
rect.size.y=-rect.size.y;
+ tile_ofs.y=-tile_ofs.y;
+ }
Vector2 center_ofs;
@@ -407,9 +449,8 @@ void TileMap::_update_dirty_quadrants() {
_fix_cell_transform(xform,c,shape_ofs+center_ofs,s);
- if (debug_shapes) {
- vs->canvas_item_add_set_transform(canvas_item,xform);
- shape->draw(canvas_item,debug_collision_color);
+ if (debug_canvas_item) {
+ shape->draw(debug_canvas_item,debug_collision_color);
}
ps->body_add_shape(q.body,shape->get_rid(),xform);
@@ -417,9 +458,6 @@ void TileMap::_update_dirty_quadrants() {
}
}
- if (debug_shapes) {
- vs->canvas_item_add_set_transform(canvas_item,Matrix32());
- }
if (navigation) {
Ref<NavigationPolygon> navpoly = tile_set->tile_get_navigation_polygon(c.id);
@@ -452,6 +490,7 @@ void TileMap::_update_dirty_quadrants() {
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());
+ VS::get_singleton()->canvas_light_occluder_set_light_mask(orid,occluder_light_mask);
Quadrant::Occluder oc;
oc.xform=xform;
oc.id=orid;
@@ -1075,6 +1114,33 @@ Array TileMap::get_used_cells() const {
return a;
}
+void TileMap::set_occluder_light_mask(int p_mask) {
+
+ occluder_light_mask=p_mask;
+ for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
+
+ for (Map<PosKey,Quadrant::Occluder>::Element *F=E->get().occluder_instances.front();F;F=F->next()) {
+ VisualServer::get_singleton()->canvas_light_occluder_set_light_mask(F->get().id,occluder_light_mask);
+ }
+ }
+}
+
+int TileMap::get_occluder_light_mask() const{
+
+ return occluder_light_mask;
+}
+
+void TileMap::set_light_mask(int p_light_mask) {
+
+ CanvasItem::set_light_mask(p_light_mask);
+ for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
+
+ for (List<RID>::Element *F=E->get().canvas_items.front();F;F=F->next()) {
+ VisualServer::get_singleton()->canvas_item_set_light_mask(F->get(),get_light_mask());
+ }
+ }
+}
+
void TileMap::_bind_methods() {
@@ -1126,6 +1192,9 @@ void TileMap::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_collision_bounce","value"),&TileMap::set_collision_bounce);
ObjectTypeDB::bind_method(_MD("get_collision_bounce"),&TileMap::get_collision_bounce);
+ ObjectTypeDB::bind_method(_MD("set_occluder_light_mask","mask"),&TileMap::set_occluder_light_mask);
+ ObjectTypeDB::bind_method(_MD("get_occluder_light_mask"),&TileMap::get_occluder_light_mask);
+
ObjectTypeDB::bind_method(_MD("set_cell","x","y","tile","flip_x","flip_y","transpose"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false),DEFVAL(false));
ObjectTypeDB::bind_method(_MD("set_cellv","pos","tile","flip_x","flip_y","transpose"),&TileMap::set_cellv,DEFVAL(false),DEFVAL(false),DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_cell","x","y"),&TileMap::get_cell);
@@ -1160,6 +1229,7 @@ void TileMap::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_bounce"),_SCS("get_collision_bounce"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_layer"),_SCS("get_collision_layer"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_mask"),_SCS("get_collision_mask"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"occluder/light_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_occluder_light_mask"),_SCS("get_occluder_light_mask"));
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_tile_data"),_SCS("_get_tile_data"));
@@ -1197,6 +1267,7 @@ TileMap::TileMap() {
use_kinematic=false;
navigation=NULL;
y_sort_mode=false;
+ occluder_light_mask=1;
fp_adjust=0.00001;
tile_origin=TILE_ORIGIN_TOP_LEFT;
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 60534cce15..14cb52b736 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -150,6 +150,8 @@ private:
TileOrigin tile_origin;
+ int occluder_light_mask;
+
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);
@@ -187,6 +189,7 @@ public:
INVALID_CELL=-1
};
+
void set_tileset(const Ref<TileSet>& p_tileset);
Ref<TileSet> get_tileset() const;
@@ -247,6 +250,11 @@ public:
void set_y_sort_mode(bool p_enable);
bool is_y_sort_mode_enabled() const;
+ void set_occluder_light_mask(int p_mask);
+ int get_occluder_light_mask() const;
+
+ virtual void set_light_mask(int p_light_mask);
+
void clear();
TileMap();
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index dc72c9a267..60fa7f69c8 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h
index 1f7e4c6d45..6ec24fd4d0 100644
--- a/scene/2d/visibility_notifier_2d.h
+++ b/scene/2d/visibility_notifier_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp
index ff35837bc0..7d4235e051 100644
--- a/scene/3d/area.cpp
+++ b/scene/3d/area.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -579,7 +579,7 @@ void Area::_bind_methods() {
ADD_SIGNAL( MethodInfo("area_enter",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area")));
ADD_SIGNAL( MethodInfo("area_exit",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area")));
- ADD_PROPERTY( 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::INT,"space_override",PROPERTY_HINT_ENUM,"Disabled,Combine,Combine-Replace,Replace,Replace-Combine"),_SCS("set_space_override_mode"),_SCS("get_space_override_mode"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gravity_point"),_SCS("set_gravity_is_point"),_SCS("is_gravity_a_point"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_distance_scale", PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_gravity_distance_scale"),_SCS("get_gravity_distance_scale"));
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"gravity_vec"),_SCS("set_gravity_vector"),_SCS("get_gravity_vector"));
diff --git a/scene/3d/area.h b/scene/3d/area.h
index f03955d1e7..c250d27fb1 100644
--- a/scene/3d/area.h
+++ b/scene/3d/area.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -40,7 +40,9 @@ public:
enum SpaceOverride {
SPACE_OVERRIDE_DISABLED,
SPACE_OVERRIDE_COMBINE,
- SPACE_OVERRIDE_REPLACE
+ SPACE_OVERRIDE_COMBINE_REPLACE,
+ SPACE_OVERRIDE_REPLACE,
+ SPACE_OVERRIDE_REPLACE_COMBINE
};
private:
diff --git a/scene/3d/body_shape.cpp b/scene/3d/body_shape.cpp
index b54cbfe0f9..3a47371de3 100644
--- a/scene/3d/body_shape.cpp
+++ b/scene/3d/body_shape.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -402,7 +402,7 @@ int CollisionShape::_get_update_shape_index() const{
void CollisionShape::_bind_methods() {
//not sure if this should do anything
- ObjectTypeDB::bind_method(_MD("resource_changed"),&CollisionShape::resource_changed);
+ ObjectTypeDB::bind_method(_MD("resource_changed","resource"),&CollisionShape::resource_changed);
ObjectTypeDB::bind_method(_MD("set_shape","shape"),&CollisionShape::set_shape);
ObjectTypeDB::bind_method(_MD("get_shape"),&CollisionShape::get_shape);
ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionShape::_add_to_collision_object);
diff --git a/scene/3d/body_shape.h b/scene/3d/body_shape.h
index 6c0b89da56..dd005c0edd 100644
--- a/scene/3d/body_shape.h
+++ b/scene/3d/body_shape.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/bone_attachment.cpp b/scene/3d/bone_attachment.cpp
index 9cc1719f94..1628ccc15e 100644
--- a/scene/3d/bone_attachment.cpp
+++ b/scene/3d/bone_attachment.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/bone_attachment.h b/scene/3d/bone_attachment.h
index ca36cc3694..f1c27a9650 100644
--- a/scene/3d/bone_attachment.h
+++ b/scene/3d/bone_attachment.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index dce5060a44..3e78fef147 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -125,7 +125,7 @@ bool Camera::_get(const StringName& p_name,Variant &r_ret) const {
r_ret= int(keep_aspect);
else if (p_name=="current") {
- if (is_inside_tree() && get_tree()->is_editor_hint()) {
+ if (is_inside_tree() && get_tree()->is_node_being_edited(this)) {
r_ret=current;
} else {
r_ret=is_current();
@@ -192,12 +192,11 @@ void Camera::_update_camera() {
// here goes listener stuff
// if (viewport_ptr && is_inside_scene() && is_current())
-// viewport_ptr->_camera_transform_changed_notify();
+// get_viewport()->_camera_transform_changed_notify();
if (is_inside_tree() && is_current()) {
- if (viewport_ptr) {
- viewport_ptr->_camera_transform_changed_notify();
- }
+ get_viewport()->_camera_transform_changed_notify();
+
}
if (is_current() && get_world().is_valid()) {
@@ -213,29 +212,10 @@ void Camera::_notification(int p_what) {
case NOTIFICATION_ENTER_WORLD: {
- viewport_ptr=NULL;
-
- { //find viewport stuff
- Node *parent=get_parent();
- while(parent) {
-
- Viewport* viewport = parent->cast_to<Viewport>();
-
- if (viewport) {
- viewport_ptr=viewport;
- break;
- }
- parent=parent->get_parent();
- }
-
- }
-
- camera_group = "_vp_cameras"+itos(get_viewport()->get_instance_ID());
- add_to_group(camera_group);
- if (viewport_ptr)
- viewport_ptr->cameras.insert(this);
- if (current)
+ bool first_camera = get_viewport()->cameras.size()==0;
+ get_viewport()->cameras.insert(this);
+ if (!get_tree()->is_node_being_edited(this) && (current || first_camera))
make_current();
@@ -246,17 +226,17 @@ void Camera::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_WORLD: {
- if (is_current()) {
- clear_current();
- current=true; //keep it true
+ if (!get_tree()->is_node_being_edited(this)) {
+ if (is_current()) {
+ clear_current();
+ current=true; //keep it true
- } else {
- current=false;
+ } else {
+ current=false;
+ }
}
- if (viewport_ptr)
- viewport_ptr->cameras.erase(this);
- viewport_ptr=NULL;
- remove_from_group(camera_group);
+
+ get_viewport()->cameras.erase(this);
} break;
@@ -324,25 +304,12 @@ void Camera::make_current() {
if (!is_inside_tree())
return;
- if (viewport_ptr) {
- viewport_ptr->_set_camera(this);
- }
+ get_viewport()->_set_camera(this);
//get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this);
}
-void Camera::_camera_make_next_current(Node *p_exclude) {
-
- if (this==p_exclude)
- return;
- if (!is_inside_tree())
- return;
- if (get_viewport()->get_camera()!=NULL)
- return;
-
- make_current();
-}
void Camera::clear_current() {
@@ -351,12 +318,20 @@ void Camera::clear_current() {
if (!is_inside_tree())
return;
- if (viewport_ptr) {
- if (viewport_ptr->get_camera()==this) {
- viewport_ptr->_set_camera(NULL);
- //a group is used beause this needs to be in order to be deterministic
- get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,camera_group,"_camera_make_next_current",this);
+ if (get_viewport()->get_camera()==this) {
+ get_viewport()->_set_camera(NULL);
+ //a group is used beause this needs to be in order to be deterministic
+
+ for (Set<Camera*>::Element *E=get_viewport()->cameras.front();E;E=E->next()) {
+ if (this==E->get())
+ continue;
+ if (!E->get()->is_inside_tree())
+ continue;
+ if (get_viewport()->get_camera()!=NULL)
+ return;
+
+ E->get()->make_current();
}
}
@@ -364,9 +339,9 @@ void Camera::clear_current() {
bool Camera::is_current() const {
- if (is_inside_tree()) {
- if (viewport_ptr)
- return viewport_ptr->get_camera()==this;
+ if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) {
+
+ return get_viewport()->get_camera()==this;
} else
return current;
@@ -481,12 +456,12 @@ Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const {
#if 0
- Size2 viewport_size = viewport_ptr->get_visible_rect().size;
+ Size2 viewport_size = get_viewport()->get_visible_rect().size;
Vector2 cpos = p_pos;
#else
- Size2 viewport_size = viewport_ptr->get_camera_rect_size();
- Vector2 cpos = viewport_ptr->get_camera_coords(p_pos);
+ Size2 viewport_size = get_viewport()->get_camera_rect_size();
+ Vector2 cpos = get_viewport()->get_camera_coords(p_pos);
#endif
Vector3 ray;
@@ -514,12 +489,12 @@ Vector3 Camera::project_ray_origin(const Point2& p_pos) const {
}
#if 0
- Size2 viewport_size = viewport_ptr->get_visible_rect().size;
+ Size2 viewport_size = get_viewport()->get_visible_rect().size;
Vector2 cpos = p_pos;
#else
- Size2 viewport_size = viewport_ptr->get_camera_rect_size();
- Vector2 cpos = viewport_ptr->get_camera_coords(p_pos);
+ Size2 viewport_size = get_viewport()->get_camera_rect_size();
+ Vector2 cpos = get_viewport()->get_camera_coords(p_pos);
#endif
ERR_FAIL_COND_V( viewport_size.y == 0, Vector3() );
@@ -566,7 +541,7 @@ Point2 Camera::unproject_position(const Vector3& p_pos) const {
ERR_FAIL_COND_V(!is_inside_tree(),Vector2());
}
- Size2 viewport_size = viewport_ptr->get_visible_rect().size;
+ Size2 viewport_size = get_viewport()->get_visible_rect().size;
CameraMatrix cm;
@@ -597,7 +572,7 @@ Vector3 Camera::project_position(const Point2& p_point) const {
ERR_FAIL_COND_V(!is_inside_tree(),Vector3());
}
- Size2 viewport_size = viewport_ptr->get_visible_rect().size;
+ Size2 viewport_size = get_viewport()->get_visible_rect().size;
CameraMatrix cm;
@@ -692,7 +667,6 @@ void Camera::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_environment:Environment"),&Camera::get_environment);
ObjectTypeDB::bind_method(_MD("set_keep_aspect_mode","mode"),&Camera::set_keep_aspect_mode);
ObjectTypeDB::bind_method(_MD("get_keep_aspect_mode"),&Camera::get_keep_aspect_mode);
- ObjectTypeDB::bind_method(_MD("_camera_make_next_current"),&Camera::_camera_make_next_current);
//ObjectTypeDB::bind_method( _MD("_camera_make_current"),&Camera::_camera_make_current );
BIND_CONSTANT( PROJECTION_PERSPECTIVE );
@@ -745,7 +719,7 @@ Vector<Plane> Camera::get_frustum() const {
ERR_FAIL_COND_V(!is_inside_world(),Vector<Plane>());
- Size2 viewport_size = viewport_ptr->get_visible_rect().size;
+ Size2 viewport_size = get_viewport()->get_visible_rect().size;
CameraMatrix cm;
if (mode==PROJECTION_PERSPECTIVE)
cm.set_perspective(fov,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH);
@@ -789,7 +763,6 @@ Camera::Camera() {
near=0;
far=0;
current=false;
- viewport_ptr=NULL;
force_change=false;
mode=PROJECTION_PERSPECTIVE;
set_perspective(60.0,0.1,100.0);
diff --git a/scene/3d/camera.h b/scene/3d/camera.h
index e21f4865ec..02ca6ffb9a 100644
--- a/scene/3d/camera.h
+++ b/scene/3d/camera.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -68,18 +68,15 @@ private:
RID camera;
RID scenario_id;
- String camera_group;
+ //String camera_group;
uint32_t layers;
- Viewport *viewport_ptr;
Ref<Environment> environment;
virtual bool _can_gizmo_scale() const;
virtual RES _get_gizmo_geometry() const;
- void _camera_make_next_current(Node *p_exclude);
-
//void _camera_make_current(Node *p_camera);
friend class Viewport;
diff --git a/scene/3d/character_camera.cpp b/scene/3d/character_camera.cpp
index 19332bd056..2b22026fe9 100644
--- a/scene/3d/character_camera.cpp
+++ b/scene/3d/character_camera.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/character_camera.h b/scene/3d/character_camera.h
index 99b41c6eda..d636b4b1a5 100644
--- a/scene/3d/character_camera.h
+++ b/scene/3d/character_camera.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp
index 5a89423e5a..373c356a45 100644
--- a/scene/3d/collision_object.cpp
+++ b/scene/3d/collision_object.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/collision_object.h b/scene/3d/collision_object.h
index 548c9fb85b..f8daeb3ed2 100644
--- a/scene/3d/collision_object.h
+++ b/scene/3d/collision_object.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp
index bb0a1fca12..3b14e1d767 100644
--- a/scene/3d/collision_polygon.cpp
+++ b/scene/3d/collision_polygon.cpp
@@ -236,7 +236,7 @@ void CollisionPolygon::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon::_add_to_collision_object);
- ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon::set_build_mode);
+ ObjectTypeDB::bind_method(_MD("set_build_mode","build_mode"),&CollisionPolygon::set_build_mode);
ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon::get_build_mode);
ObjectTypeDB::bind_method(_MD("set_depth","depth"),&CollisionPolygon::set_depth);
diff --git a/scene/3d/interpolated_camera.cpp b/scene/3d/interpolated_camera.cpp
index f44713e8a0..96306d1180 100644
--- a/scene/3d/interpolated_camera.cpp
+++ b/scene/3d/interpolated_camera.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/interpolated_camera.h b/scene/3d/interpolated_camera.h
index a8ed649c42..dbe84327fb 100644
--- a/scene/3d/interpolated_camera.h
+++ b/scene/3d/interpolated_camera.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp
index 9f9c87b675..18463742c6 100644
--- a/scene/3d/light.cpp
+++ b/scene/3d/light.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -487,9 +487,9 @@ bool Light::is_editor_only() const{
void Light::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_parameter","variable","value"), &Light::set_parameter );
- ObjectTypeDB::bind_method(_MD("get_parameter"), &Light::get_parameter );
+ ObjectTypeDB::bind_method(_MD("get_parameter","variable"), &Light::get_parameter );
ObjectTypeDB::bind_method(_MD("set_color","color","value"), &Light::set_color );
- ObjectTypeDB::bind_method(_MD("get_color"), &Light::get_color );
+ ObjectTypeDB::bind_method(_MD("get_color","color"), &Light::get_color );
ObjectTypeDB::bind_method(_MD("set_project_shadows","enable"), &Light::set_project_shadows );
ObjectTypeDB::bind_method(_MD("has_project_shadows"), &Light::has_project_shadows );
ObjectTypeDB::bind_method(_MD("set_projector","projector:Texture"), &Light::set_projector );
diff --git a/scene/3d/light.h b/scene/3d/light.h
index fb77ac9e64..b74085b7a9 100644
--- a/scene/3d/light.h
+++ b/scene/3d/light.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp
index 62b32729c3..997d2dea7c 100644
--- a/scene/3d/mesh_instance.cpp
+++ b/scene/3d/mesh_instance.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h
index 76a0eeea60..f26ef52000 100644
--- a/scene/3d/mesh_instance.h
+++ b/scene/3d/mesh_instance.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/multimesh_instance.cpp b/scene/3d/multimesh_instance.cpp
index cd620ff447..0e97a97943 100644
--- a/scene/3d/multimesh_instance.cpp
+++ b/scene/3d/multimesh_instance.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/multimesh_instance.h b/scene/3d/multimesh_instance.h
index be6b3677e2..7cd9a8ea82 100644
--- a/scene/3d/multimesh_instance.h
+++ b/scene/3d/multimesh_instance.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/optimized_spatial_scene.cpp b/scene/3d/optimized_spatial_scene.cpp
index 85c1b79a9a..27631c7a74 100644
--- a/scene/3d/optimized_spatial_scene.cpp
+++ b/scene/3d/optimized_spatial_scene.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/optimized_spatial_scene.h b/scene/3d/optimized_spatial_scene.h
index a55b5235da..e1e6e14f73 100644
--- a/scene/3d/optimized_spatial_scene.h
+++ b/scene/3d/optimized_spatial_scene.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp
index 6868646c48..dfd5c38266 100644
--- a/scene/3d/particles.cpp
+++ b/scene/3d/particles.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -422,14 +422,14 @@ void Particles::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_variable","variable","value"),&Particles::set_variable);
ObjectTypeDB::bind_method(_MD("get_variable","variable"),&Particles::get_variable);
ObjectTypeDB::bind_method(_MD("set_randomness","variable","randomness"),&Particles::set_randomness);
- ObjectTypeDB::bind_method(_MD("get_randomness"),&Particles::get_randomness);
+ ObjectTypeDB::bind_method(_MD("get_randomness","variable"),&Particles::get_randomness);
ObjectTypeDB::bind_method(_MD("set_color_phase_pos","phase","pos"),&Particles::set_color_phase_pos);
ObjectTypeDB::bind_method(_MD("get_color_phase_pos","phase"),&Particles::get_color_phase_pos);
ObjectTypeDB::bind_method(_MD("set_color_phase_color","phase","color"),&Particles::set_color_phase_color);
ObjectTypeDB::bind_method(_MD("get_color_phase_color","phase"),&Particles::get_color_phase_color);
ObjectTypeDB::bind_method(_MD("set_material","material:Material"),&Particles::set_material);
ObjectTypeDB::bind_method(_MD("get_material:Material"),&Particles::get_material);
- ObjectTypeDB::bind_method(_MD("set_emit_timeout"),&Particles::set_emit_timeout);
+ ObjectTypeDB::bind_method(_MD("set_emit_timeout","timeout"),&Particles::set_emit_timeout);
ObjectTypeDB::bind_method(_MD("get_emit_timeout"),&Particles::get_emit_timeout);
ObjectTypeDB::bind_method(_MD("set_height_from_velocity","enable"),&Particles::set_height_from_velocity);
ObjectTypeDB::bind_method(_MD("has_height_from_velocity"),&Particles::has_height_from_velocity);
diff --git a/scene/3d/particles.h b/scene/3d/particles.h
index 260573fe5f..b9cae332e2 100644
--- a/scene/3d/particles.h
+++ b/scene/3d/particles.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp
index 9cd41b25f6..d6cd3da7c3 100644
--- a/scene/3d/path.cpp
+++ b/scene/3d/path.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/path.h b/scene/3d/path.h
index 1b40ec413d..2e3573df3e 100644
--- a/scene/3d/path.h
+++ b/scene/3d/path.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index d61859a3d0..1a2665b6ad 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -207,6 +207,9 @@ void RigidBody::_body_enter_tree(ObjectID p_id) {
ERR_FAIL_COND(E->get().in_tree);
E->get().in_tree=true;
+
+ contact_monitor->locked=true;
+
emit_signal(SceneStringNames::get_singleton()->body_enter,node);
for(int i=0;i<E->get().shapes.size();i++) {
@@ -214,6 +217,9 @@ void RigidBody::_body_enter_tree(ObjectID p_id) {
emit_signal(SceneStringNames::get_singleton()->body_enter_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].local_shape);
}
+ contact_monitor->locked=false;
+
+
}
void RigidBody::_body_exit_tree(ObjectID p_id) {
@@ -225,11 +231,18 @@ void RigidBody::_body_exit_tree(ObjectID p_id) {
ERR_FAIL_COND(!E);
ERR_FAIL_COND(!E->get().in_tree);
E->get().in_tree=false;
+
+ contact_monitor->locked=true;
+
emit_signal(SceneStringNames::get_singleton()->body_exit,node);
+
for(int i=0;i<E->get().shapes.size();i++) {
emit_signal(SceneStringNames::get_singleton()->body_exit_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].local_shape);
}
+
+ contact_monitor->locked=false;
+
}
void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape,int p_local_shape) {
@@ -317,6 +330,8 @@ void RigidBody::_direct_state_changed(Object *p_state) {
if (contact_monitor) {
+ contact_monitor->locked=true;
+
//untag all
int rc=0;
for( Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
@@ -396,6 +411,8 @@ void RigidBody::_direct_state_changed(Object *p_state) {
_body_inout(1,toadd[i].id,toadd[i].shape,toadd[i].local_shape);
}
+ contact_monitor->locked=false;
+
}
set_ignore_transform_notification(true);
@@ -648,6 +665,11 @@ void RigidBody::set_contact_monitor(bool p_enabled) {
if (!p_enabled) {
+ if (contact_monitor->locked) {
+ ERR_EXPLAIN("Can't disable contact monitoring during in/out callback. Use call_deferred(\"set_contact_monitor\",false) instead");
+ }
+ ERR_FAIL_COND(contact_monitor->locked);
+
for(Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
//clean up mess
@@ -658,6 +680,8 @@ void RigidBody::set_contact_monitor(bool p_enabled) {
} else {
contact_monitor = memnew( ContactMonitor );
+ contact_monitor->locked=false;
+
}
}
@@ -1073,7 +1097,7 @@ Vector3 KinematicBody::move_to(const Vector3& p_position) {
return move(p_position-get_global_transform().origin);
}
-bool KinematicBody::can_move_to(const Vector3& p_position, bool p_discrete) {
+bool KinematicBody::can_teleport_to(const Vector3& p_position) {
ERR_FAIL_COND_V(!is_inside_tree(),false);
PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(get_world()->get_space());
@@ -1089,25 +1113,18 @@ bool KinematicBody::can_move_to(const Vector3& p_position, bool p_discrete) {
if (collide_character)
mask|=PhysicsDirectSpaceState::TYPE_MASK_CHARACTER_BODY;
- Vector3 motion = p_position-get_global_transform().origin;
Transform xform=get_global_transform();
-
- if (true || p_discrete) {
-
- xform.origin+=motion;
- motion=Vector3();
- }
+ xform.origin=p_position;
Set<RID> exclude;
exclude.insert(get_rid());
- //fill exclude list..
for(int i=0;i<get_shape_count();i++) {
if (is_shape_set_as_trigger(i))
continue;
- bool col = dss->intersect_shape(get_shape(i)->get_rid(), xform * get_shape_transform(i),0,NULL,0,exclude,get_layer_mask(),mask);
+ bool col = dss->intersect_shape(get_shape(i)->get_rid(), xform * get_shape_transform(i),0,NULL,1,exclude,get_layer_mask(),mask);
if (col)
return false;
}
@@ -1205,7 +1222,7 @@ void KinematicBody::_bind_methods() {
ObjectTypeDB::bind_method(_MD("move","rel_vec"),&KinematicBody::move);
ObjectTypeDB::bind_method(_MD("move_to","position"),&KinematicBody::move_to);
- ObjectTypeDB::bind_method(_MD("can_move_to","position"),&KinematicBody::can_move_to);
+ ObjectTypeDB::bind_method(_MD("can_teleport_to","position"),&KinematicBody::can_teleport_to);
ObjectTypeDB::bind_method(_MD("is_colliding"),&KinematicBody::is_colliding);
diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h
index 66490ba925..da79d63f00 100644
--- a/scene/3d/physics_body.h
+++ b/scene/3d/physics_body.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -175,7 +175,7 @@ private:
struct ContactMonitor {
-
+ bool locked;
Map<ObjectID,BodyState> body_map;
};
@@ -304,7 +304,7 @@ public:
Vector3 move(const Vector3& p_motion);
Vector3 move_to(const Vector3& p_position);
- bool can_move_to(const Vector3& p_position,bool p_discrete=false);
+ bool can_teleport_to(const Vector3& p_position);
bool is_colliding() const;
Vector3 get_collision_pos() const;
Vector3 get_collision_normal() const;
diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp
index 0cc72b28e5..3f03b2aab3 100644
--- a/scene/3d/physics_joint.cpp
+++ b/scene/3d/physics_joint.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,8 +34,15 @@ void Joint::_update_joint(bool p_only_free) {
if (joint.is_valid()) {
- if (ba.is_valid() && bb.is_valid())
- PhysicsServer::get_singleton()->body_remove_collision_exception(ba,bb);
+ if (ba.is_valid() && bb.is_valid()) {
+
+ if (exclude_from_collision)
+ PhysicsServer::get_singleton()->body_add_collision_exception(ba,bb);
+ else
+ PhysicsServer::get_singleton()->body_remove_collision_exception(ba,bb);
+
+ }
+
PhysicsServer::get_singleton()->free(joint);
joint=RID();
ba=RID();
@@ -134,7 +141,7 @@ void Joint::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: {
if (joint.is_valid()) {
_update_joint(true);
- PhysicsServer::get_singleton()->free(joint);
+ //PhysicsServer::get_singleton()->free(joint);
joint=RID();
}
} break;
@@ -144,6 +151,19 @@ void Joint::_notification(int p_what) {
}
+void Joint::set_exclude_nodes_from_collision(bool p_enable) {
+
+ if (exclude_from_collision==p_enable)
+ return;
+ exclude_from_collision=p_enable;
+ _update_joint();
+}
+
+bool Joint::get_exclude_nodes_from_collision() const{
+
+ return exclude_from_collision;
+}
+
void Joint::_bind_methods() {
@@ -156,10 +176,16 @@ void Joint::_bind_methods() {
ObjectTypeDB::bind_method( _MD("set_solver_priority","priority"), &Joint::set_solver_priority );
ObjectTypeDB::bind_method( _MD("get_solver_priority"), &Joint::get_solver_priority );
+ ObjectTypeDB::bind_method( _MD("set_exclude_nodes_from_collision","enable"), &Joint::set_exclude_nodes_from_collision );
+ ObjectTypeDB::bind_method( _MD("get_exclude_nodes_from_collision"), &Joint::get_exclude_nodes_from_collision );
+
ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "nodes/node_a"), _SCS("set_node_a"),_SCS("get_node_a") );
ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "nodes/node_b"), _SCS("set_node_b"),_SCS("get_node_b") );
ADD_PROPERTY( PropertyInfo( Variant::INT, "solver/priority",PROPERTY_HINT_RANGE,"1,8,1"), _SCS("set_solver_priority"),_SCS("get_solver_priority") );
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "collision/exclude_nodes"), _SCS("set_exclude_nodes_from_collision"),_SCS("get_exclude_nodes_from_collision") );
+
+
}
@@ -167,6 +193,7 @@ void Joint::_bind_methods() {
Joint::Joint() {
+ exclude_from_collision=true;
solver_priority=1;
}
diff --git a/scene/3d/physics_joint.h b/scene/3d/physics_joint.h
index a5f4ea4bdb..55c26f296e 100644
--- a/scene/3d/physics_joint.h
+++ b/scene/3d/physics_joint.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -45,6 +45,7 @@ class Joint : public Spatial {
NodePath b;
int solver_priority;
+ bool exclude_from_collision;
protected:
@@ -67,6 +68,9 @@ public:
void set_solver_priority(int p_priority);
int get_solver_priority() const;
+ void set_exclude_nodes_from_collision(bool p_enable);
+ bool get_exclude_nodes_from_collision() const;
+
RID get_joint() const { return joint; }
Joint();
diff --git a/scene/3d/portal.cpp b/scene/3d/portal.cpp
index 34499578aa..84f94402d5 100644
--- a/scene/3d/portal.cpp
+++ b/scene/3d/portal.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/portal.h b/scene/3d/portal.h
index 14c1275312..388eac4dd3 100644
--- a/scene/3d/portal.h
+++ b/scene/3d/portal.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/position_3d.cpp b/scene/3d/position_3d.cpp
index d692c0f249..27130cbe6a 100644
--- a/scene/3d/position_3d.cpp
+++ b/scene/3d/position_3d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/position_3d.h b/scene/3d/position_3d.h
index 265c0b48c7..6bac540fcb 100644
--- a/scene/3d/position_3d.h
+++ b/scene/3d/position_3d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/proximity_group.cpp b/scene/3d/proximity_group.cpp
index 334246b033..a2182302a0 100644
--- a/scene/3d/proximity_group.cpp
+++ b/scene/3d/proximity_group.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/proximity_group.h b/scene/3d/proximity_group.h
index 35e3f3dd98..6d5c703827 100644
--- a/scene/3d/proximity_group.h
+++ b/scene/3d/proximity_group.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/quad.cpp b/scene/3d/quad.cpp
index 43bde8dc61..1a7eeef180 100644
--- a/scene/3d/quad.cpp
+++ b/scene/3d/quad.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/quad.h b/scene/3d/quad.h
index 5ef4af8b81..be55b0d1c9 100644
--- a/scene/3d/quad.h
+++ b/scene/3d/quad.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp
index 5f2c8e0ba3..ab2c4fc8dc 100644
--- a/scene/3d/ray_cast.cpp
+++ b/scene/3d/ray_cast.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/ray_cast.h b/scene/3d/ray_cast.h
index 06e9e31396..520b4d5313 100644
--- a/scene/3d/ray_cast.h
+++ b/scene/3d/ray_cast.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/room_instance.cpp b/scene/3d/room_instance.cpp
index 2ae75b8b68..e358da136b 100644
--- a/scene/3d/room_instance.cpp
+++ b/scene/3d/room_instance.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/room_instance.h b/scene/3d/room_instance.h
index 09fccc5ebc..c7df4ceadd 100644
--- a/scene/3d/room_instance.h
+++ b/scene/3d/room_instance.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/scenario_fx.cpp b/scene/3d/scenario_fx.cpp
index 59c8b5e0df..2e22ab36d3 100644
--- a/scene/3d/scenario_fx.cpp
+++ b/scene/3d/scenario_fx.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/scenario_fx.h b/scene/3d/scenario_fx.h
index b877cccc19..a3c13e03a1 100644
--- a/scene/3d/scenario_fx.h
+++ b/scene/3d/scenario_fx.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp
index cb81228dff..64133f67b5 100644
--- a/scene/3d/skeleton.cpp
+++ b/scene/3d/skeleton.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h
index 6678722d12..033f212a58 100644
--- a/scene/3d/skeleton.h
+++ b/scene/3d/skeleton.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index a65f68ed2c..0c1e1e2d1c 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -594,6 +594,15 @@ bool Spatial::is_hidden() const{
return !data.visible;
}
+void Spatial::set_hidden(bool p_hidden) {
+
+ if (data.visible != p_hidden) {
+ return;
+ }
+
+ _set_visible_(!p_hidden);
+}
+
void Spatial::_set_visible_(bool p_visible) {
if (p_visible)
@@ -742,6 +751,7 @@ void Spatial::_bind_methods() {
ObjectTypeDB::bind_method(_MD("hide"), &Spatial::hide);
ObjectTypeDB::bind_method(_MD("is_visible"), &Spatial::is_visible);
ObjectTypeDB::bind_method(_MD("is_hidden"), &Spatial::is_hidden);
+ ObjectTypeDB::bind_method(_MD("set_hidden","hidden"), &Spatial::set_hidden);
ObjectTypeDB::bind_method(_MD("_set_visible_"), &Spatial::_set_visible_);
ObjectTypeDB::bind_method(_MD("_is_visible_"), &Spatial::_is_visible_);
diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h
index 7fa6099d7a..23f1c6d103 100644
--- a/scene/3d/spatial.h
+++ b/scene/3d/spatial.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -191,6 +191,7 @@ public:
void hide();
bool is_visible() const;
bool is_hidden() const;
+ void set_hidden(bool p_hidden);
#ifdef TOOLS_ENABLED
void set_import_transform(const Transform& p_transform) ;
diff --git a/scene/3d/spatial_indexer.cpp b/scene/3d/spatial_indexer.cpp
index 2f7aee5c67..d5be36b2cb 100644
--- a/scene/3d/spatial_indexer.cpp
+++ b/scene/3d/spatial_indexer.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/spatial_indexer.h b/scene/3d/spatial_indexer.h
index bc19b54d8f..13ce8badea 100644
--- a/scene/3d/spatial_indexer.h
+++ b/scene/3d/spatial_indexer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/spatial_player.cpp b/scene/3d/spatial_player.cpp
index 5948c01ff8..c7cf03e284 100644
--- a/scene/3d/spatial_player.cpp
+++ b/scene/3d/spatial_player.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/spatial_player.h b/scene/3d/spatial_player.h
index 2f54497847..5a8687b854 100644
--- a/scene/3d/spatial_player.h
+++ b/scene/3d/spatial_player.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/spatial_sample_player.cpp b/scene/3d/spatial_sample_player.cpp
index 28b8fdd01e..7114fd4b77 100644
--- a/scene/3d/spatial_sample_player.cpp
+++ b/scene/3d/spatial_sample_player.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/spatial_sample_player.h b/scene/3d/spatial_sample_player.h
index 1d7bb8e238..9b3220458e 100644
--- a/scene/3d/spatial_sample_player.h
+++ b/scene/3d/spatial_sample_player.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/spatial_stream_player.cpp b/scene/3d/spatial_stream_player.cpp
index 7ed2335fcb..dfef0faf4b 100644
--- a/scene/3d/spatial_stream_player.cpp
+++ b/scene/3d/spatial_stream_player.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -60,7 +60,7 @@ void SpatialStreamPlayer::sp_set_mix_rate(int p_rate){
bool SpatialStreamPlayer::sp_mix(int32_t *p_buffer,int p_frames) {
- if (resampler.is_ready()) {
+ if (resampler.is_ready() && !paused) {
return resampler.mix(p_buffer,p_frames);
}
@@ -332,7 +332,7 @@ void SpatialStreamPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_stream","stream:Stream"),&SpatialStreamPlayer::set_stream);
ObjectTypeDB::bind_method(_MD("get_stream:Stream"),&SpatialStreamPlayer::get_stream);
- ObjectTypeDB::bind_method(_MD("play"),&SpatialStreamPlayer::play,DEFVAL(0));
+ ObjectTypeDB::bind_method(_MD("play","offset"),&SpatialStreamPlayer::play,DEFVAL(0));
ObjectTypeDB::bind_method(_MD("stop"),&SpatialStreamPlayer::stop);
ObjectTypeDB::bind_method(_MD("is_playing"),&SpatialStreamPlayer::is_playing);
diff --git a/scene/3d/spatial_stream_player.h b/scene/3d/spatial_stream_player.h
index f2775a4982..0732b3fc10 100644
--- a/scene/3d/spatial_stream_player.h
+++ b/scene/3d/spatial_stream_player.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/test_cube.cpp b/scene/3d/test_cube.cpp
index 0acd1b3351..6440d95d55 100644
--- a/scene/3d/test_cube.cpp
+++ b/scene/3d/test_cube.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/test_cube.h b/scene/3d/test_cube.h
index 2dbd7c9856..21f2b3c794 100644
--- a/scene/3d/test_cube.h
+++ b/scene/3d/test_cube.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp
index ad62f6d809..60097ad482 100644
--- a/scene/3d/visibility_notifier.cpp
+++ b/scene/3d/visibility_notifier.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/visibility_notifier.h b/scene/3d/visibility_notifier.h
index 85c26bec94..a4709b7cf4 100644
--- a/scene/3d/visibility_notifier.h
+++ b/scene/3d/visibility_notifier.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp
index 41e8b6bf54..723b0a9af5 100644
--- a/scene/3d/visual_instance.cpp
+++ b/scene/3d/visual_instance.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h
index 3c69f09978..e49f4fb82f 100644
--- a/scene/3d/visual_instance.h
+++ b/scene/3d/visual_instance.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/animation/animation_cache.cpp b/scene/animation/animation_cache.cpp
index b1d6da7294..b1123897b2 100644
--- a/scene/animation/animation_cache.cpp
+++ b/scene/animation/animation_cache.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/animation/animation_cache.h b/scene/animation/animation_cache.h
index e94530d924..c9b4ff298c 100644
--- a/scene/animation/animation_cache.h
+++ b/scene/animation/animation_cache.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index c2ea1c8bb6..f6d058c2fd 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -268,6 +268,7 @@ void AnimationPlayer::_generate_node_caches(AnimationData* p_anim) {
TrackNodeCacheKey key;
key.id=id;
key.bone_idx=bone_idx;
+
if (node_cache_map.has(key)) {
@@ -278,6 +279,7 @@ void AnimationPlayer::_generate_node_caches(AnimationData* p_anim) {
node_cache_map[key]=TrackNodeCache();
p_anim->node_cache[i]=&node_cache_map[key];
+ p_anim->node_cache[i]->path=a->track_get_path(i);
p_anim->node_cache[i]->node=child;
p_anim->node_cache[i]->resource=resource;
p_anim->node_cache[i]->node_2d=child->cast_to<Node2D>();
@@ -320,6 +322,7 @@ void AnimationPlayer::_generate_node_caches(AnimationData* p_anim) {
pa.prop=property;
pa.object=resource.is_valid()?(Object*)resource.ptr():(Object*)child;
pa.special=SP_NONE;
+ pa.owner=p_anim->node_cache[i];
if (false && p_anim->node_cache[i]->node_2d) {
if (pa.prop==SceneStringNames::get_singleton()->transform_pos)
@@ -410,7 +413,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData* p_anim,float p
TrackNodeCache::PropertyAnim *pa = &E->get();
- if (a->value_track_is_continuous(i) || p_delta==0) {
+ if (a->value_track_is_continuous(i) || p_delta==0) { //delta == 0 means seek
Variant value=a->value_track_interpolate(i,p_time);
@@ -436,10 +439,42 @@ void AnimationPlayer::_animation_process_animation(AnimationData* p_anim,float p
Variant value=a->track_get_key_value(i,F->get());
switch(pa->special) {
- case SP_NONE: pa->object->set(pa->prop,value); break; //you are not speshul
- case SP_NODE2D_POS: static_cast<Node2D*>(pa->object)->set_pos(value); break;
- case SP_NODE2D_ROT: static_cast<Node2D*>(pa->object)->set_rot(Math::deg2rad(value)); break;
- case SP_NODE2D_SCALE: static_cast<Node2D*>(pa->object)->set_scale(value); break;
+ case SP_NONE: {
+ bool valid;
+ pa->object->set(pa->prop,value,&valid); //you are not speshul
+#ifdef DEBUG_ENABLED
+ if (!valid) {
+ ERR_PRINTS("Failed setting track value '"+String(pa->owner->path)+"'. Check if property exists or the type of key is valid");
+ }
+#endif
+
+ } break;
+ case SP_NODE2D_POS: {
+#ifdef DEBUG_ENABLED
+ if (value.get_type()!=Variant::VECTOR2) {
+ ERR_PRINTS("Position key at time "+rtos(p_time)+" in Animation Track '"+String(pa->owner->path)+"' not of type Vector2()");
+ }
+#endif
+ static_cast<Node2D*>(pa->object)->set_pos(value);
+ } break;
+ case SP_NODE2D_ROT: {
+#ifdef DEBUG_ENABLED
+ if (value.is_num()) {
+ ERR_PRINTS("Rotation key at time "+rtos(p_time)+" in Animation Track '"+String(pa->owner->path)+"' not numerical");
+ }
+#endif
+
+ static_cast<Node2D*>(pa->object)->set_rot(Math::deg2rad(value));
+ } break;
+ case SP_NODE2D_SCALE: {
+#ifdef DEBUG_ENABLED
+ if (value.get_type()!=Variant::VECTOR2) {
+ ERR_PRINTS("Scale key at time "+rtos(p_time)+" in Animation Track '"+String(pa->owner->path)+"' not of type Vector2()");
+ }
+#endif
+
+ static_cast<Node2D*>(pa->object)->set_scale(value);
+ } break;
}
}
@@ -607,13 +642,53 @@ void AnimationPlayer::_animation_update_transforms() {
ERR_CONTINUE( pa->accum_pass!=accum_pass );
#if 1
- switch(pa->special) {
+/* switch(pa->special) {
case SP_NONE: pa->object->set(pa->prop,pa->value_accum); break; //you are not speshul
case SP_NODE2D_POS: static_cast<Node2D*>(pa->object)->set_pos(pa->value_accum); break;
case SP_NODE2D_ROT: static_cast<Node2D*>(pa->object)->set_rot(Math::deg2rad(pa->value_accum)); break;
case SP_NODE2D_SCALE: static_cast<Node2D*>(pa->object)->set_scale(pa->value_accum); break;
+ }*/
+
+ switch(pa->special) {
+
+ case SP_NONE: {
+ bool valid;
+ pa->object->set(pa->prop,pa->value_accum,&valid); //you are not speshul
+#ifdef DEBUG_ENABLED
+ if (!valid) {
+ ERR_PRINTS("Failed setting key at time "+rtos(playback.current.pos)+" in Animation '"+get_current_animation()+"', Track '"+String(pa->owner->path)+"'. Check if property exists or the type of key is right for the property");
+ }
+#endif
+
+ } break;
+ case SP_NODE2D_POS: {
+#ifdef DEBUG_ENABLED
+ if (pa->value_accum.get_type()!=Variant::VECTOR2) {
+ ERR_PRINTS("Position key at time "+rtos(playback.current.pos)+" in Animation '"+get_current_animation()+"', Track '"+String(pa->owner->path)+"' not of type Vector2()");
+ }
+#endif
+ static_cast<Node2D*>(pa->object)->set_pos(pa->value_accum);
+ } break;
+ case SP_NODE2D_ROT: {
+#ifdef DEBUG_ENABLED
+ if (pa->value_accum.is_num()) {
+ ERR_PRINTS("Rotation key at time "+rtos(playback.current.pos)+" in Animation '"+get_current_animation()+"', Track '"+String(pa->owner->path)+"' not numerical");
+ }
+#endif
+
+ static_cast<Node2D*>(pa->object)->set_rot(Math::deg2rad(pa->value_accum));
+ } break;
+ case SP_NODE2D_SCALE: {
+#ifdef DEBUG_ENABLED
+ if (pa->value_accum.get_type()!=Variant::VECTOR2) {
+ ERR_PRINTS("Scale key at time "+rtos(playback.current.pos)+" in Animation '"+get_current_animation()+"', Track '"+String(pa->owner->path)+"' not of type Vector2()");
+ }
+#endif
+
+ static_cast<Node2D*>(pa->object)->set_scale(pa->value_accum);
+ } break;
}
#else
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index 1e3c37c4d6..853526c80a 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -68,6 +68,7 @@ private:
struct TrackNodeCache {
+ NodePath path;
uint32_t id;
RES resource;
Node *node;
@@ -84,6 +85,7 @@ private:
struct PropertyAnim {
+ TrackNodeCache *owner;
SpecialProperty special; //small optimization
StringName prop;
Object *object;
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index c7e259c3c6..77d9f77bb5 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -432,7 +432,7 @@ void AnimationTreePlayer::_notification(int p_what) {
}
-float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode **r_prev_anim,float p_weight, float p_time, bool p_seek,const HashMap<NodePath,bool> *p_filter, float p_reverse_weight) {
+float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode **r_prev_anim,float p_weight, float p_time, bool switched, bool p_seek,const HashMap<NodePath,bool> *p_filter, float p_reverse_weight) {
ERR_FAIL_COND_V(!node_map.has(p_node), 0);
NodeBase *nb=node_map[p_node];
@@ -445,7 +445,7 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
case NODE_OUTPUT: {
NodeOut *on = static_cast<NodeOut*>(nb);
- return _process_node(on->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek);
+ return _process_node(on->inputs[0].node,r_prev_anim,p_weight,p_time,switched,p_seek);
} break;
case NODE_ANIMATION: {
@@ -479,6 +479,9 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
an->time=anim_size;
}
+ if (switched && an->time >= anim_size) {
+ an->time = 0.0;
+ }
an->skip=true;
for (List<AnimationNode::TrackRef>::Element *E=an->tref.front();E;E=E->next()) {
@@ -520,7 +523,7 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
if (!osn->active) {
//make it as if this node doesn't exist, pass input 0 by.
- return _process_node(osn->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek,p_filter,p_reverse_weight);
+ return _process_node(osn->inputs[0].node,r_prev_anim,p_weight,p_time,switched,p_seek,p_filter,p_reverse_weight);
}
if (p_seek)
@@ -551,13 +554,13 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
if (!osn->filter.empty()) {
- main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,p_seek,&osn->filter,p_weight);
- os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,p_seek,&osn->filter,-1);
+ main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,switched,p_seek,&osn->filter,p_weight);
+ os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,osn->start,p_seek,&osn->filter,-1);
} else {
- main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,p_seek);
- os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,p_seek);
+ main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,switched,p_seek);
+ os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,osn->start,p_seek);
}
if (osn->start) {
@@ -578,8 +581,8 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
MixNode *mn = static_cast<MixNode*>(nb);
- float rem = _process_node(mn->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek,p_filter,p_reverse_weight);
- _process_node(mn->inputs[1].node,r_prev_anim,p_weight*mn->amount,p_time,p_seek,p_filter,p_reverse_weight);
+ float rem = _process_node(mn->inputs[0].node,r_prev_anim,p_weight,p_time,switched,p_seek,p_filter,p_reverse_weight);
+ _process_node(mn->inputs[1].node,r_prev_anim,p_weight*mn->amount,p_time,switched,p_seek,p_filter,p_reverse_weight);
return rem;
} break;
@@ -590,12 +593,12 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
float rem;
if (!bn->filter.empty()) {
- rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,p_seek,&bn->filter,p_weight);
- _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value,p_time,p_seek,&bn->filter,-1);
+ rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,switched,p_seek,&bn->filter,p_weight);
+ _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value,p_time,switched,p_seek,&bn->filter,-1);
} else {
- rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,p_seek,p_filter,p_reverse_weight*(1.0-bn->value));
- _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value,p_time,p_seek,p_filter,p_reverse_weight*bn->value);
+ rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,switched,p_seek,p_filter,p_reverse_weight*(1.0-bn->value));
+ _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value,p_time,switched,p_seek,p_filter,p_reverse_weight*bn->value);
}
return rem;
@@ -606,16 +609,16 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
float rem;
if (bn->value==0) {
- rem = _process_node(bn->inputs[1].node,r_prev_anim,p_weight,p_time,p_seek,p_filter,p_reverse_weight);
+ rem = _process_node(bn->inputs[1].node,r_prev_anim,p_weight,p_time,switched,p_seek,p_filter,p_reverse_weight);
} else if (bn->value>0) {
- rem = _process_node(bn->inputs[1].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,p_seek,p_filter,p_reverse_weight*(1.0-bn->value));
- _process_node(bn->inputs[2].node,r_prev_anim,p_weight*bn->value,p_time,p_seek,p_filter,p_reverse_weight*bn->value);
+ rem = _process_node(bn->inputs[1].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,switched,p_seek,p_filter,p_reverse_weight*(1.0-bn->value));
+ _process_node(bn->inputs[2].node,r_prev_anim,p_weight*bn->value,p_time,switched,p_seek,p_filter,p_reverse_weight*bn->value);
} else {
- rem = _process_node(bn->inputs[1].node,r_prev_anim,p_weight*(1.0+bn->value),p_time,p_seek,p_filter,p_reverse_weight*(1.0+bn->value));
- _process_node(bn->inputs[0].node,r_prev_anim,p_weight*-bn->value,p_time,p_seek,p_filter,p_reverse_weight*-bn->value);
+ rem = _process_node(bn->inputs[1].node,r_prev_anim,p_weight*(1.0+bn->value),p_time,switched,p_seek,p_filter,p_reverse_weight*(1.0+bn->value));
+ _process_node(bn->inputs[0].node,r_prev_anim,p_weight*-bn->value,p_time,switched,p_seek,p_filter,p_reverse_weight*-bn->value);
}
return rem;
@@ -623,10 +626,10 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
case NODE_BLEND4: {
Blend4Node *bn = static_cast<Blend4Node*>(nb);
- float rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value.x),p_time,p_seek,p_filter,p_reverse_weight*(1.0-bn->value.x));
- _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value.x,p_time,p_seek,p_filter,p_reverse_weight*bn->value.x);
- float rem2 = _process_node(bn->inputs[2].node,r_prev_anim,p_weight*(1.0-bn->value.y),p_time,p_seek,p_filter,p_reverse_weight*(1.0-bn->value.y));
- _process_node(bn->inputs[3].node,r_prev_anim,p_weight*bn->value.y,p_time,p_seek,p_filter,p_reverse_weight*bn->value.y);
+ float rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value.x),p_time,switched,p_seek,p_filter,p_reverse_weight*(1.0-bn->value.x));
+ _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value.x,p_time,switched,p_seek,p_filter,p_reverse_weight*bn->value.x);
+ float rem2 = _process_node(bn->inputs[2].node,r_prev_anim,p_weight*(1.0-bn->value.y),p_time,switched,p_seek,p_filter,p_reverse_weight*(1.0-bn->value.y));
+ _process_node(bn->inputs[3].node,r_prev_anim,p_weight*bn->value.y,p_time,switched,p_seek,p_filter,p_reverse_weight*bn->value.y);
return MAX(rem,rem2);
@@ -634,9 +637,9 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
case NODE_TIMESCALE: {
TimeScaleNode *tsn = static_cast<TimeScaleNode*>(nb);
if (p_seek)
- return _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,true,p_filter,p_reverse_weight);
+ return _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,switched,true,p_filter,p_reverse_weight);
else
- return _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time*tsn->scale,false,p_filter,p_reverse_weight);
+ return _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time*tsn->scale,switched,false,p_filter,p_reverse_weight);
} break;
case NODE_TIMESEEK: {
@@ -644,12 +647,12 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
TimeSeekNode *tsn = static_cast<TimeSeekNode*>(nb);
if (tsn->seek_pos>=0) {
- float res = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,tsn->seek_pos,true,p_filter,p_reverse_weight);
+ float res = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,tsn->seek_pos,switched,true,p_filter,p_reverse_weight);
tsn->seek_pos=-1;
return res;
} else
- return _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek);
+ return _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,switched,p_seek);
} break;
case NODE_TRANSITION: {
@@ -658,7 +661,7 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
if (tn->prev<0) {
- float rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight,p_time,p_seek,p_filter,p_reverse_weight);
+ float rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight,p_time,switched,p_seek,p_filter,p_reverse_weight);
if (p_seek)
tn->time=p_time;
else
@@ -687,10 +690,10 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
if (!p_seek && tn->switched) { //just switched
- rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight*(1.0-blend),0,true,p_filter,p_reverse_weight*(1.0-blend));
+ rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight*(1.0-blend),0,true,true,p_filter,p_reverse_weight*(1.0-blend));
} else {
- rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight*(1.0-blend),p_time,p_seek,p_filter,p_reverse_weight*(1.0-blend));
+ rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight*(1.0-blend),p_time,switched,p_seek,p_filter,p_reverse_weight*(1.0-blend));
}
@@ -700,10 +703,10 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
if (p_seek) {
- _process_node(tn->inputs[tn->prev].node,r_prev_anim,p_weight*blend,0,false,p_filter,p_reverse_weight*blend);
+ _process_node(tn->inputs[tn->prev].node,r_prev_anim,p_weight*blend,0,true,false,p_filter,p_reverse_weight*blend);
tn->time=p_time;
} else {
- _process_node(tn->inputs[tn->prev].node,r_prev_anim,p_weight*blend,p_time,false,p_filter,p_reverse_weight*blend);
+ _process_node(tn->inputs[tn->prev].node,r_prev_anim,p_weight*blend,p_time,switched,false,p_filter,p_reverse_weight*blend);
tn->time+=p_time;
tn->prev_xfading-=p_time;
if (tn->prev_xfading<0) {
@@ -740,10 +743,10 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
AnimationNode *prev=NULL;
if (reset_request) {
- _process_node(out_name,&prev, 1.0, 0, true );
+ _process_node(out_name,&prev, 1.0, 0, true, true );
reset_request=false;
} else
- _process_node(out_name,&prev, 1.0, p_delta, false );
+ _process_node(out_name,&prev, 1.0, p_delta, false, false );
if (dirty_caches) {
//some animation changed.. ignore this pass
@@ -834,7 +837,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
StringName method = a->method_track_get_name(tr.local_track,E->get());
Vector<Variant> args=a->method_track_get_params(tr.local_track,E->get());
- ERR_CONTINUE(args.size()!=VARIANT_ARG_MAX);
+ args.resize(VARIANT_ARG_MAX);
tr.track->node->call(method,args[0],args[1],args[2],args[3],args[4]);
}
} break;
diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h
index 9ea5ccf330..0fec9a9551 100644
--- a/scene/animation/animation_tree_player.h
+++ b/scene/animation/animation_tree_player.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -267,7 +267,7 @@ private:
Map<StringName,NodeBase*> node_map;
// return time left to finish animation
- float _process_node(const StringName& p_node,AnimationNode **r_prev_anim, float p_weight,float p_step, bool p_seek=false,const HashMap<NodePath,bool> *p_filter=NULL, float p_reverse_weight=0);
+ float _process_node(const StringName& p_node,AnimationNode **r_prev_anim, float p_weight,float p_step, bool switched, bool p_seek=false,const HashMap<NodePath,bool> *p_filter=NULL, float p_reverse_weight=0);
void _process_animation(float p_delta);
bool reset_request;
diff --git a/scene/animation/transitioner.cpp b/scene/animation/transitioner.cpp
index d210f29db0..adcf73d489 100644
--- a/scene/animation/transitioner.cpp
+++ b/scene/animation/transitioner.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/animation/transitioner.h b/scene/animation/transitioner.h
index dba83cddd8..8b7ec4f3fa 100644
--- a/scene/animation/transitioner.h
+++ b/scene/animation/transitioner.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 73d93e50ec..31f30dd1d9 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/animation/tween.h b/scene/animation/tween.h
index d504c63d8a..f06ca1e9e7 100644
--- a/scene/animation/tween.h
+++ b/scene/animation/tween.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/animation/tween_interpolaters.cpp b/scene/animation/tween_interpolaters.cpp
index 9128d220de..80588d643e 100644
--- a/scene/animation/tween_interpolaters.cpp
+++ b/scene/animation/tween_interpolaters.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/audio/event_player.cpp b/scene/audio/event_player.cpp
index 1bd692431d..eabe84a8ee 100644
--- a/scene/audio/event_player.cpp
+++ b/scene/audio/event_player.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -312,16 +312,14 @@ void EventPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_pos"),&EventPlayer::get_pos);
ObjectTypeDB::bind_method(_MD("seek_pos","time"),&EventPlayer::seek_pos);
- ObjectTypeDB::bind_method(_MD("set_autoplay","enabled"),&EventPlayer::set_autoplay);
- ObjectTypeDB::bind_method(_MD("has_autoplay"),&EventPlayer::has_autoplay);
-
- ObjectTypeDB::bind_method(_MD("set_channel_volume","idx","channel_volume"),&EventPlayer::set_channel_volume);
- ObjectTypeDB::bind_method(_MD("get_channel_volume""idx"),&EventPlayer::get_channel_volume);
-
ObjectTypeDB::bind_method(_MD("get_length"),&EventPlayer::get_length);
+ ObjectTypeDB::bind_method(_MD("set_autoplay","enabled"),&EventPlayer::set_autoplay);
+ ObjectTypeDB::bind_method(_MD("has_autoplay"),&EventPlayer::has_autoplay);
- ObjectTypeDB::bind_method(_MD("get_channel_last_note_time"),&EventPlayer::get_channel_last_note_time);
+ ObjectTypeDB::bind_method(_MD("set_channel_volume","channel","channel_volume"),&EventPlayer::set_channel_volume);
+ ObjectTypeDB::bind_method(_MD("get_channel_volume","channel"),&EventPlayer::get_channel_volume);
+ ObjectTypeDB::bind_method(_MD("get_channel_last_note_time","channel"),&EventPlayer::get_channel_last_note_time);
ObjectTypeDB::bind_method(_MD("_set_play","play"),&EventPlayer::_set_play);
ObjectTypeDB::bind_method(_MD("_get_play"),&EventPlayer::_get_play);
diff --git a/scene/audio/event_player.h b/scene/audio/event_player.h
index 05e78040d2..c04e85fe77 100644
--- a/scene/audio/event_player.h
+++ b/scene/audio/event_player.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/audio/sample_player.cpp b/scene/audio/sample_player.cpp
index 7c0a926324..d7605ed1a9 100644
--- a/scene/audio/sample_player.cpp
+++ b/scene/audio/sample_player.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/audio/sample_player.h b/scene/audio/sample_player.h
index 75a01aff86..1821c671dc 100644
--- a/scene/audio/sample_player.h
+++ b/scene/audio/sample_player.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/audio/sound_room_params.cpp b/scene/audio/sound_room_params.cpp
index 8886113e03..bb2285c97f 100644
--- a/scene/audio/sound_room_params.cpp
+++ b/scene/audio/sound_room_params.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/audio/sound_room_params.h b/scene/audio/sound_room_params.h
index 8af2ae8c12..4ca1eae2ce 100644
--- a/scene/audio/sound_room_params.h
+++ b/scene/audio/sound_room_params.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/audio/stream_player.cpp b/scene/audio/stream_player.cpp
index 4cfca0492a..f7cfc31b03 100644
--- a/scene/audio/stream_player.cpp
+++ b/scene/audio/stream_player.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -58,7 +58,7 @@ void StreamPlayer::sp_set_mix_rate(int p_rate){
bool StreamPlayer::sp_mix(int32_t *p_buffer,int p_frames) {
- if (resampler.is_ready()) {
+ if (resampler.is_ready() && !paused) {
return resampler.mix(p_buffer,p_frames);
}
@@ -75,7 +75,10 @@ void StreamPlayer::sp_update() {
//check that all this audio has been flushed before stopping the stream
int to_mix = resampler.get_total() - resampler.get_todo();
if (to_mix==0) {
- stop();
+ if (!stop_request) {
+ stop_request=true;
+ call_deferred("stop");
+ }
return;
}
@@ -164,8 +167,10 @@ void StreamPlayer::stop() {
//_THREAD_SAFE_METHOD_
AudioServer::get_singleton()->stream_set_active(stream_rid,false);
+ stop_request=false;
playback->stop();
resampler.flush();
+ emit_signal("finished");
//set_idle_process(false);
}
@@ -329,7 +334,7 @@ void StreamPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_stream","stream:Stream"),&StreamPlayer::set_stream);
ObjectTypeDB::bind_method(_MD("get_stream:Stream"),&StreamPlayer::get_stream);
- ObjectTypeDB::bind_method(_MD("play"),&StreamPlayer::play,DEFVAL(0));
+ ObjectTypeDB::bind_method(_MD("play","offset"),&StreamPlayer::play,DEFVAL(0));
ObjectTypeDB::bind_method(_MD("stop"),&StreamPlayer::stop);
ObjectTypeDB::bind_method(_MD("is_playing"),&StreamPlayer::is_playing);
@@ -374,6 +379,8 @@ void StreamPlayer::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/paused"), _SCS("set_paused"), _SCS("is_paused") );
ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/loop_restart_time"), _SCS("set_loop_restart_time"), _SCS("get_loop_restart_time") );
ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/buffering_ms"), _SCS("set_buffering_msec"), _SCS("get_buffering_msec") );
+
+ ADD_SIGNAL(MethodInfo("finished"));
}
@@ -389,6 +396,7 @@ StreamPlayer::StreamPlayer() {
stream_rid=AudioServer::get_singleton()->audio_stream_create(&internal_stream);
buffering_ms=500;
loop_point=0;
+ stop_request=false;
}
diff --git a/scene/audio/stream_player.h b/scene/audio/stream_player.h
index be090f50e1..30840137e2 100644
--- a/scene/audio/stream_player.h
+++ b/scene/audio/stream_player.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -66,6 +66,7 @@ class StreamPlayer : public Node {
float volume;
float loop_point;
int buffering_ms;
+ volatile bool stop_request;
AudioRBResampler resampler;
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 0c63a3bc74..698dbce2b5 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h
index e187a85eae..83c66326c5 100644
--- a/scene/gui/base_button.h
+++ b/scene/gui/base_button.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp
index b63b3de530..6fff90809e 100644
--- a/scene/gui/box_container.cpp
+++ b/scene/gui/box_container.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/box_container.h b/scene/gui/box_container.h
index c357814baf..6e63e8bdac 100644
--- a/scene/gui/box_container.h
+++ b/scene/gui/box_container.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index edeb18bfc1..b9ce46d738 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -137,8 +137,10 @@ void Button::_notification(int p_what) {
text_ofs.y+=font->get_ascent();
font->draw( ci, text_ofs.floor(), text, color,clip_text?text_clip:-1);
if (!_icon.is_null()) {
+
+ int valign = size.height-style->get_minimum_size().y;
- _icon->draw(ci,Point2(style->get_offset().x, Math::floor( (size.height-_icon->get_height())/2.0 ) ),is_disabled()?Color(1,1,1,0.4):Color(1,1,1) );
+ _icon->draw(ci,style->get_offset()+Point2(0, Math::floor( (valign-_icon->get_height())/2.0 ) ),is_disabled()?Color(1,1,1,0.4):Color(1,1,1) );
}
diff --git a/scene/gui/button.h b/scene/gui/button.h
index 690179b90c..bd244f5087 100644
--- a/scene/gui/button.h
+++ b/scene/gui/button.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/button_array.cpp b/scene/gui/button_array.cpp
index b86e32dda7..9e3476899f 100644
--- a/scene/gui/button_array.cpp
+++ b/scene/gui/button_array.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/button_array.h b/scene/gui/button_array.h
index ea2c1e4968..39661eaabd 100644
--- a/scene/gui/button_array.h
+++ b/scene/gui/button_array.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/button_group.cpp b/scene/gui/button_group.cpp
index c92d7f2696..04ba5fc06d 100644
--- a/scene/gui/button_group.cpp
+++ b/scene/gui/button_group.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/button_group.h b/scene/gui/button_group.h
index 74e847e937..38c61991b7 100644
--- a/scene/gui/button_group.h
+++ b/scene/gui/button_group.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/center_container.cpp b/scene/gui/center_container.cpp
index 8a22a38980..844175e4c1 100644
--- a/scene/gui/center_container.cpp
+++ b/scene/gui/center_container.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/center_container.h b/scene/gui/center_container.h
index 4d8d06ac8c..dc95533525 100644
--- a/scene/gui/center_container.h
+++ b/scene/gui/center_container.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp
index 2aa82bc5f5..1381d6eb60 100644
--- a/scene/gui/check_box.cpp
+++ b/scene/gui/check_box.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/check_box.h b/scene/gui/check_box.h
index 171fd55351..95dd4891d4 100644
--- a/scene/gui/check_box.h
+++ b/scene/gui/check_box.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp
index d765aefe5e..ecaea251a5 100644
--- a/scene/gui/check_button.cpp
+++ b/scene/gui/check_button.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/check_button.h b/scene/gui/check_button.h
index b90bb31c2d..022ade2193 100644
--- a/scene/gui/check_button.h
+++ b/scene/gui/check_button.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index c30d473610..8685ec1c99 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -28,25 +28,43 @@
/*************************************************************************/
#include "color_picker.h"
+#include "scene/gui/separator.h"
+#include "scene/main/viewport.h"
+#include "os/os.h"
+#include "os/input.h"
+#include "os/keyboard.h"
+void update_material(Ref<CanvasItemMaterial>mat,const Color& p_color) {
+ if (!mat.is_valid())
+ return;
+ Ref<Shader> sdr = mat->get_shader();
+ if (!sdr.is_valid())
+ return;
+ mat->set_shader_param("R",p_color.r);
+ mat->set_shader_param("G",p_color.g);
+ mat->set_shader_param("B",p_color.b);
+ mat->set_shader_param("H",p_color.get_h());
+ mat->set_shader_param("S",p_color.get_s());
+ mat->set_shader_param("V",p_color.get_v());
+ mat->set_shader_param("A",p_color.a);
+}
void ColorPicker::_notification(int p_what) {
switch(p_what) {
case NOTIFICATION_THEME_CHANGED: {
-
+ uv_material->set_shader(get_shader("uv_editor"));
+ w_material->set_shader(get_shader("w_editor"));
+ update_material(uv_material,color);
+ update_material(w_material,color);
_update_controls();
} break;
-/* case NOTIFICATION_DRAW: {
-
- int w = get_constant("color_width");
- int h = ms.height;
- VisualServer::get_singleton()->canvas_item_add_rect(get_canvas_item(),Rect2(0,0,w,h),color);
-
- } break;*/
+ case NOTIFICATION_ENTER_TREE: {
+ btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
+ }
}
}
@@ -64,10 +82,16 @@ void ColorPicker::_update_controls() {
}
-
void ColorPicker::set_color(const Color& p_color) {
color=p_color;
+ h=color.get_h();
+ s=color.get_s();
+ v=color.get_v();
+ update_material(uv_material, color);
+ update_material(w_material, color);
+ uv_edit->get_child(0)->cast_to<Control>()->update();
+ w_edit->get_child(0)->cast_to<Control>()->update();
_update_color();
}
@@ -77,7 +101,7 @@ void ColorPicker::set_edit_alpha(bool p_show) {
edit_alpha=p_show;
_update_controls();
_update_color();
- color_box->update();
+ sample->update();
}
bool ColorPicker::is_editing_alpha() const {
@@ -90,35 +114,17 @@ void ColorPicker::_value_changed(double) {
if (updating)
return;
- switch(mode) {
-
- case MODE_RGB: {
-
- for(int i=0;i<4;i++) {
- color.components[i] = scroll[i]->get_val() / 255.0;
- }
-
- } break;
- case MODE_HSV: {
-
- color.set_hsv( CLAMP(scroll[0]->get_val()/359,0,0.9972), scroll[1]->get_val()/100, scroll[2]->get_val()/100 );
- color.a=scroll[3]->get_val()/100.0;
-
- } break;
- case MODE_RAW: {
-
- for(int i=0;i<4;i++) {
- color.components[i] = scroll[i]->get_val();
- }
-
- } break;
-
+ for(int i=0;i<3;i++) {
+ color.components[i] = scroll[i]->get_val()/(raw_mode_enabled?1.0:255.0);
}
+ color.components[3] = scroll[3]->get_val()/255.0;
+ update_material(uv_material,color);
+ update_material(w_material,color);
html->set_text(color.to_html(edit_alpha && color.a<1));
- color_box->update();
+ sample->update();
emit_signal("color_changed",color);
@@ -138,144 +144,325 @@ void ColorPicker::_update_color() {
updating=true;
- switch(mode) {
-
- case MODE_RAW: {
-
- static const char*_lt[4]={"R","G","B","A"};
-
- for(int i=0;i<4;i++) {
- scroll[i]->set_max(255);
- scroll[i]->set_step(0.01);
- scroll[i]->set_val(color.components[i]);
- labels[i]->set_text(_lt[i]);
- }
- } break;
- case MODE_RGB: {
-
- static const char*_lt[4]={"R","G","B","A"};
-
- for(int i=0;i<4;i++) {
- scroll[i]->set_max(255);
- scroll[i]->set_step(1);
- scroll[i]->set_val(color.components[i]*255);
- labels[i]->set_text(_lt[i]);
- }
-
- } break;
- case MODE_HSV: {
-
- static const char*_lt[4]={"H","S","V","A"};
+ for(int i=0;i<4;i++) {
+ scroll[i]->set_max(255);
+ scroll[i]->set_step(0.01);
+ if (raw_mode_enabled && i != 3)
+ scroll[i]->set_val(color.components[i]);
+ else
+ scroll[i]->set_val(color.components[i]*255);
+ }
- for(int i=0;i<4;i++) {
- labels[i]->set_text(_lt[i]);
- }
+ html->set_text(color.to_html(edit_alpha && color.a<1));
- scroll[0]->set_max(359);
- scroll[0]->set_step(0.01);
- scroll[0]->set_val( color.get_h()*359 );
+ sample->update();
+ updating=false;
+}
- scroll[1]->set_max(100);
- scroll[1]->set_step(0.01);
- scroll[1]->set_val( color.get_s()*100 );
+void ColorPicker::_update_presets()
+{
+ Size2 size=bt_add_preset->get_size();
+ preset->set_custom_minimum_size(Size2(size.width*presets.size(),size.height));
+ Image i(size.x*presets.size(),size.y, false, Image::FORMAT_RGB);
+ for (int y=0;y<size.y;y++)
+ for (int x=0;x<size.x*presets.size();x++)
+ i.put_pixel(x,y,presets[(int)x/size.x]);
+ Ref<ImageTexture> t;
+ t.instance();
+ t->create_from_image(i);
+ preset->set_texture(t);
+}
- scroll[2]->set_max(100);
- scroll[2]->set_step(0.01);
- scroll[2]->set_val( color.get_v()*100 );
+Color ColorPicker::get_color() const {
- scroll[3]->set_max(100);
- scroll[3]->set_step(0.01);
- scroll[3]->set_val( color.a*100);
+ return color;
+}
- } break;
+void ColorPicker::add_preset(const Color &p_color)
+{
+ if (presets.find(p_color)) {
+ presets.move_to_back(presets.find(p_color));
+ } else {
+ presets.push_back(p_color);
}
+ _update_presets();
+ if (presets.size()==10)
+ bt_add_preset->hide();
+}
- html->set_text(color.to_html(edit_alpha && color.a<1));
+void ColorPicker::set_raw_mode(bool p_enabled) {
- color_box->update();
- updating=false;
+ if (raw_mode_enabled==p_enabled)
+ return;
+ raw_mode_enabled=p_enabled;
+ if (btn_mode->is_pressed()!=p_enabled)
+ btn_mode->set_pressed(p_enabled);
+
+ _update_controls();
+ _update_color();
}
-Color ColorPicker::get_color() const {
+bool ColorPicker::is_raw_mode() const {
- return color;
+ return raw_mode_enabled;
}
+void ColorPicker::_sample_draw() {
+ sample->draw_rect(Rect2(Point2(),Size2(256,20)),color);
+}
-void ColorPicker::set_mode(Mode p_mode) {
+void ColorPicker::_hsv_draw(int p_wich,Control* c)
+{
+ if (!c)
+ return;
+ if (p_wich==0) {
+ int x=c->get_size().x*color.get_s();
+ int y=c->get_size().y-c->get_size().y*color.get_v();
+ c->draw_line(Point2(x,0),Point2(x,c->get_size().y),color.inverted());
+ c->draw_line(Point2(0,y),Point2(c->get_size().x,y),color.inverted());
+ c->draw_line(Point2(x,y),Point2(x,y),Color(1,1,1),2);
+ } else if (p_wich==1) {
+ int y=c->get_size().y-c->get_size().y*color.get_h();
+ Color col=Color();
+ col.set_hsv(color.get_h(),1,1);
+ c->draw_line(Point2(0,y),Point2(c->get_size().x,y),col.inverted());
+ }
+}
- ERR_FAIL_INDEX(p_mode,3);
- mode=p_mode;
- if (mode_box->get_selected()!=p_mode)
- mode_box->select(p_mode);
+void ColorPicker::_uv_input(const InputEvent &ev) {
+ if (ev.type == InputEvent::MOUSE_BUTTON) {
+ const InputEventMouseButton &bev = ev.mouse_button;
+ if (bev.pressed) {
+ changing_color = true;
+ float x = CLAMP((float)bev.x,0,256);
+ float y = CLAMP((float)bev.y,0,256);
+ s=x/256;
+ v=1.0-y/256.0;
+ color.set_hsv(h,s,v,color.a);
+ set_color(color);
+ _update_color();
+ emit_signal("color_changed", color);
+ } else {
+ changing_color = false;
+ }
+ } else if (ev.type == InputEvent::MOUSE_MOTION) {
+ const InputEventMouse &bev = ev.mouse_motion;
+ if (!changing_color)
+ return;
+ float x = CLAMP((float)bev.x,0,256);
+ float y = CLAMP((float)bev.y,0,256);
+ s=x/256;
+ v=1.0-y/256.0;
+ color.set_hsv(h,s,v,color.a);
+ set_color(color);
+ _update_color();
+ emit_signal("color_changed", color);
+ }
+}
- _update_controls();
- _update_color();
+void ColorPicker::_w_input(const InputEvent &ev) {
+ if (ev.type == InputEvent::MOUSE_BUTTON) {
+ const InputEventMouseButton &bev = ev.mouse_button;
+ if (bev.pressed) {
+ changing_color = true;
+ h=1-((float)bev.y)/256.0;
+
+ } else {
+ changing_color = false;
+ }
+ color.set_hsv(h,s,v,color.a);
+ set_color(color);
+ _update_color();
+ emit_signal("color_changed", color);
+ } else if (ev.type == InputEvent::MOUSE_MOTION) {
+ const InputEventMouse &bev = ev.mouse_motion;
+ if (!changing_color)
+ return;
+ float y = CLAMP((float)bev.y,0,256);
+ h=1.0-y/256.0;
+ color.set_hsv(h,s,v,color.a);
+ set_color(color);
+ _update_color();
+ emit_signal("color_changed", color);
+ }
}
-ColorPicker::Mode ColorPicker::get_mode() const {
+void ColorPicker::_preset_input(const InputEvent &ev) {
+ if (ev.type == InputEvent::MOUSE_BUTTON) {
+ const InputEventMouseButton &bev = ev.mouse_button;
+ if (bev.pressed && bev.button_index==BUTTON_LEFT) {
+ int index = bev.x/(preset->get_size().x/presets.size());
+ set_color(presets[index]);
+ } else if (bev.pressed && bev.button_index==BUTTON_RIGHT) {
+ int index = bev.x/(preset->get_size().x/presets.size());
+ presets.erase(presets[index]);
+ _update_presets();
+ bt_add_preset->show();
+ }
+ _update_color();
+ emit_signal("color_changed", color);
+ } else if (ev.type == InputEvent::MOUSE_MOTION) {
+ const InputEventMouse &mev = ev.mouse_motion;
+ int index = mev.x/(preset->get_size().x/presets.size());
+ if (index<0 || index >= presets.size())
+ return;
+ preset->set_tooltip("Color: #"+presets[index].to_html(presets[index].a<1)+"\n"
+ "LMB: Set color\n"
+ "RMB: Remove preset");
+ }
+}
- return mode;
+void ColorPicker::_screen_input(const InputEvent &ev)
+{
+ if (ev.type==InputEvent::MOUSE_BUTTON) {
+ const InputEventMouseButton &bev = ev.mouse_button;
+ if (bev.button_index==BUTTON_LEFT&&!bev.pressed) {
+ emit_signal("color_changed", color);
+ screen->hide();
+ }
+ } else if (ev.type==InputEvent::MOUSE_MOTION) {
+ const InputEventMouse &mev = ev.mouse_motion;
+ Viewport *r=get_tree()->get_root();
+ if (!r->get_rect().has_point(Point2(mev.global_x,mev.global_y)))
+ return;
+ Image img =r->get_screen_capture();
+ if (!img.empty())
+ last_capture=img;
+ r->queue_screen_capture();
+ if (!last_capture.empty())
+ set_color(last_capture.get_pixel(mev.global_x,mev.global_y));
+ }
}
-void ColorPicker::_color_box_draw() {
+void ColorPicker::_add_preset_pressed() {
+ add_preset(color);
+}
- color_box->draw_rect( Rect2( Point2(), color_box->get_size()), color);
+void ColorPicker::_screen_pick_pressed()
+{
+ Viewport *r=get_tree()->get_root();
+ if (!screen) {
+ screen=memnew( Control );
+ r->add_child(screen);
+ screen->set_area_as_parent_rect();
+ screen->connect("input_event",this,"_screen_input");
+ }
+ screen->raise();
+ screen->show();
+ r->queue_screen_capture();
}
void ColorPicker::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_color","color"),&ColorPicker::set_color);
ObjectTypeDB::bind_method(_MD("get_color"),&ColorPicker::get_color);
- ObjectTypeDB::bind_method(_MD("set_mode","mode"),&ColorPicker::set_mode);
- ObjectTypeDB::bind_method(_MD("get_mode"),&ColorPicker::get_mode);
+ ObjectTypeDB::bind_method(_MD("set_raw_mode","mode"),&ColorPicker::set_raw_mode);
+ ObjectTypeDB::bind_method(_MD("is_raw_mode"),&ColorPicker::is_raw_mode);
ObjectTypeDB::bind_method(_MD("set_edit_alpha","show"),&ColorPicker::set_edit_alpha);
ObjectTypeDB::bind_method(_MD("is_editing_alpha"),&ColorPicker::is_editing_alpha);
+ ObjectTypeDB::bind_method(_MD("add_preset"), &ColorPicker::add_preset);
ObjectTypeDB::bind_method(_MD("_value_changed"),&ColorPicker::_value_changed);
ObjectTypeDB::bind_method(_MD("_html_entered"),&ColorPicker::_html_entered);
- ObjectTypeDB::bind_method(_MD("_color_box_draw"),&ColorPicker::_color_box_draw);
+ ObjectTypeDB::bind_method(_MD("_add_preset_pressed"), &ColorPicker::_add_preset_pressed);
+ ObjectTypeDB::bind_method(_MD("_screen_pick_pressed"), &ColorPicker::_screen_pick_pressed);
+ ObjectTypeDB::bind_method(_MD("_sample_draw"),&ColorPicker::_sample_draw);
+ ObjectTypeDB::bind_method(_MD("_hsv_draw"),&ColorPicker::_hsv_draw);
+ ObjectTypeDB::bind_method(_MD("_uv_input"),&ColorPicker::_uv_input);
+ ObjectTypeDB::bind_method(_MD("_w_input"),&ColorPicker::_w_input);
+ ObjectTypeDB::bind_method(_MD("_preset_input"),&ColorPicker::_preset_input);
+ ObjectTypeDB::bind_method(_MD("_screen_input"),&ColorPicker::_screen_input);
ADD_SIGNAL( MethodInfo("color_changed",PropertyInfo(Variant::COLOR,"color")));
}
+ColorPicker::ColorPicker() :
+ BoxContainer(true) {
-
-
-ColorPicker::ColorPicker() {
-
-
- //edit_alpha=false;
updating=true;
edit_alpha=true;
+ raw_mode_enabled=false;
+ changing_color=false;
+ screen=NULL;
+
+ HBoxContainer *hb_smpl = memnew( HBoxContainer );
+ btn_pick = memnew( ToolButton );
+ btn_pick->connect("pressed",this,"_screen_pick_pressed");
+
+ sample = memnew( TextureFrame );
+ sample->set_h_size_flags(SIZE_EXPAND_FILL);
+ sample->connect("draw",this,"_sample_draw");
+
+ hb_smpl->add_child(sample);
+ hb_smpl->add_child(btn_pick);
+ add_child(hb_smpl);
+
+ HBoxContainer *hb_edit = memnew( HBoxContainer );
+
+ uv_edit= memnew ( TextureFrame );
+ Image i(256, 256, false, Image::FORMAT_RGB);
+ for (int y=0;y<256;y++)
+ for (int x=0;x<256;x++)
+ i.put_pixel(x,y,Color());
+ Ref<ImageTexture> t;
+ t.instance();
+ t->create_from_image(i);
+ uv_edit->set_texture(t);
+ uv_edit->set_ignore_mouse(false);
+ uv_edit->set_custom_minimum_size(Size2(256,256));
+ uv_edit->connect("input_event", this, "_uv_input");
+ Control *c= memnew( Control );
+ uv_edit->add_child(c);
+ c->set_area_as_parent_rect();
+ c->set_stop_mouse(false);
+ c->set_material(memnew ( CanvasItemMaterial ));
+ Vector<Variant> args=Vector<Variant>();
+ args.push_back(0);
+ args.push_back(c);
+ c->connect("draw",this,"_hsv_draw",args);
+
+ add_child(hb_edit);
+ w_edit= memnew( TextureFrame );
+ i = Image(15, 256, false, Image::FORMAT_RGB);
+ for (int y=0;y<256;y++)
+ for (int x=0;x<15;x++)
+ i.put_pixel(x,y,Color());
+ Ref<ImageTexture> tw;
+ tw.instance();
+ tw->create_from_image(i);
+ w_edit->set_texture(tw);
+ w_edit->set_ignore_mouse(false);
+ w_edit->set_custom_minimum_size(Size2(15,256));
+ w_edit->connect("input_event", this, "_w_input");
+ c= memnew( Control );
+ w_edit->add_child(c);
+ c->set_area_as_parent_rect();
+ c->set_stop_mouse(false);
+ c->set_material(memnew ( CanvasItemMaterial ));
+ args.clear();
+ args.push_back(1);
+ args.push_back(c);
+ c->connect("draw",this,"_hsv_draw",args);
+
+ hb_edit->add_child(uv_edit);
+ hb_edit->add_child(memnew( VSeparator ));
+ hb_edit->add_child(w_edit);
VBoxContainer *vbl = memnew( VBoxContainer );
add_child(vbl);
- mode_box = memnew( OptionButton );
- mode_box->add_item("RGB");
- mode_box->add_item("HSV");
- mode_box->add_item("RAW");
- mode_box->connect("item_selected",this,"set_mode");
-
- color_box=memnew( Control );
- color_box->set_v_size_flags(SIZE_EXPAND_FILL);
- vbl->add_child(color_box);
- color_box->connect("draw",this,"_color_box_draw");
-
- vbl->add_child(mode_box);
-
+ add_child(memnew( HSeparator ));
VBoxContainer *vbr = memnew( VBoxContainer );
add_child(vbr);
vbr->set_h_size_flags(SIZE_EXPAND_FILL);
-
+ const char* lt[4] = {"R","G","B","A"};
for(int i=0;i<4;i++) {
HBoxContainer *hbc = memnew( HBoxContainer );
- labels[i]=memnew( Label );
+ labels[i]=memnew( Label(lt[i]) );
hbc->add_child(labels[i]);
scroll[i]=memnew( HSlider );
@@ -294,10 +481,14 @@ ColorPicker::ColorPicker() {
vbr->add_child(hbc);
-
}
HBoxContainer *hhb = memnew( HBoxContainer );
+
+ btn_mode = memnew( CheckButton );
+ btn_mode->set_text("RAW Mode");
+ btn_mode->connect("toggled", this, "set_raw_mode");
+ hhb->add_child(btn_mode);
vbr->add_child(hhb);
html_num = memnew( Label );
hhb->add_child(html_num);
@@ -309,11 +500,49 @@ ColorPicker::ColorPicker() {
html->set_h_size_flags(SIZE_EXPAND_FILL);
- mode=MODE_RGB;
_update_controls();
_update_color();
updating=false;
+ uv_material.instance();
+ Ref<Shader> s_uv = get_shader("uv_editor");
+ uv_material->set_shader(s_uv);
+
+ w_material.instance();
+
+ Ref<Shader> s_w = get_shader("w_editor");
+ w_material->set_shader(s_w);
+
+ uv_edit->set_material(uv_material);
+ w_edit->set_material(w_material);
+
+ set_color(Color(1,1,1));
+
+ i.create(256,20,false,Image::FORMAT_RGB);
+ for (int y=0;y<20;y++)
+ for(int x=0;x<256;x++)
+ if ((x/4+y/4)%2)
+ i.put_pixel(x,y,Color(1,1,1));
+ else
+ i.put_pixel(x,y,Color(0.6,0.6,0.6));
+ Ref<ImageTexture> t_smpl;
+ t_smpl.instance();
+ t_smpl->create_from_image(i);
+ sample->set_texture(t_smpl);
+
+ HBoxContainer *bbc = memnew( HBoxContainer );
+ add_child(bbc);
+
+ preset = memnew( TextureFrame );
+ bbc->add_child(preset);
+ preset->set_ignore_mouse(false);
+ preset->connect("input_event", this, "_preset_input");
+
+ bt_add_preset = memnew ( Button );
+ bt_add_preset->set_icon(get_icon("add_preset"));
+ bt_add_preset->set_tooltip("Add current color as a preset");
+ bt_add_preset->connect("pressed", this, "_add_preset_pressed");
+ bbc->add_child(bt_add_preset);
}
@@ -331,7 +560,7 @@ void ColorPickerButton::_color_changed(const Color& p_color) {
void ColorPickerButton::pressed() {
- Size2 ms = Size2(350, picker->get_combined_minimum_size().height+10);
+ Size2 ms = Size2(300, picker->get_combined_minimum_size().height+10);
popup->set_pos(get_global_pos()-Size2(0,ms.height));
popup->set_size(ms);
popup->popup();
@@ -347,7 +576,6 @@ void ColorPickerButton::_notification(int p_what) {
}
}
-
void ColorPickerButton::set_color(const Color& p_color){
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 0756e88cf2..c6c7fe537d 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,25 +36,29 @@
#include "scene/gui/button.h"
#include "scene/gui/popup.h"
#include "scene/gui/box_container.h"
-#include "scene/gui/option_button.h"
+#include "scene/gui/texture_frame.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/check_button.h"
+#include "scene/resources/material.h"
-class ColorPicker : public HBoxContainer {
+class ColorPicker : public BoxContainer {
- OBJ_TYPE(ColorPicker,HBoxContainer);
-public:
+ OBJ_TYPE(ColorPicker,BoxContainer);
- enum Mode {
- MODE_RGB,
- MODE_HSV,
- MODE_RAW
- };
private:
- Mode mode;
-
- OptionButton *mode_box;
-
- Control *color_box;
+ Control *screen;
+ Image last_capture;
+ TextureFrame *uv_edit;
+ TextureFrame *w_edit;
+ TextureFrame *sample;
+ TextureFrame *preset;
+ Button *bt_add_preset;
+ List<Color> presets;
+ ToolButton *btn_pick;
+ CheckButton *btn_mode;
+ Ref<CanvasItemMaterial> uv_material;
+ Ref<CanvasItemMaterial> w_material;
HSlider *scroll[4];
SpinBox *values[4];
Label *labels[4];
@@ -64,13 +68,25 @@ private:
Size2i ms;
Color color;
+ bool raw_mode_enabled;
bool updating;
+ bool changing_color;
+ float h,s,v;
void _html_entered(const String& p_html);
void _value_changed(double);
void _update_controls();
void _update_color();
- void _color_box_draw();
+ void _update_presets();
+ void _sample_draw();
+ void _hsv_draw(int p_wich,Control *c);
+
+ void _uv_input(const InputEvent& p_input);
+ void _w_input(const InputEvent& p_input);
+ void _preset_input(const InputEvent& p_input);
+ void _screen_input(const InputEvent& p_input);
+ void _add_preset_pressed();
+ void _screen_pick_pressed();
protected:
void _notification(int);
@@ -83,15 +99,14 @@ public:
void set_color(const Color& p_color);
Color get_color() const;
- void set_mode(Mode p_mode);
- Mode get_mode() const;
+ void add_preset(const Color& p_color);
+ void set_raw_mode(bool p_enabled);
+ bool is_raw_mode() const;
ColorPicker();
};
-VARIANT_ENUM_CAST( ColorPicker::Mode );
-
class ColorPickerButton : public Button {
OBJ_TYPE(ColorPickerButton,Button);
diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp
index 8cdf4dd039..920c6bf1e6 100644
--- a/scene/gui/container.cpp
+++ b/scene/gui/container.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -105,6 +105,8 @@ void Container::fit_child_in_rect(Control *p_child,const Rect2& p_rect) {
p_child->set_pos(r.pos);
p_child->set_size(r.size);
+ p_child->set_rotation(0);
+ p_child->set_scale(Vector2(1,1));
}
void Container::queue_sort() {
diff --git a/scene/gui/container.h b/scene/gui/container.h
index 04d5d6ab36..1c7587c155 100644
--- a/scene/gui/container.h
+++ b/scene/gui/container.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index bd6b8078ff..dce0a4ac0e 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,37 +42,6 @@
#include <stdio.h>
-class TooltipPanel : public Panel {
-
- OBJ_TYPE(TooltipPanel,Panel)
-public:
- TooltipPanel() {};
-
-};
-
-class TooltipLabel : public Label {
-
- OBJ_TYPE(TooltipLabel,Label)
-public:
- TooltipLabel() {};
-
-};
-
-Control::Window::Window() {
-
-
- mouse_focus=NULL;
- mouse_focus_button=-1;
- key_focus=NULL;
- mouse_over=NULL;
- disable_input=false;
-
- cancelled_input_ID=0;
- tooltip=NULL;
- tooltip_popup=NULL;
- tooltip_label=NULL;
- subwindow_order_dirty=false;
-}
Variant Control::edit_get_state() const {
@@ -140,6 +109,11 @@ bool Control::_set(const StringName& p_name, const Variant& p_value) {
data.icon_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
update();
+ } else if (name.begins_with("custom_shaders/")) {
+ String dname = name.get_slicec('/',1);
+ data.shader_override.erase(dname);
+ notification(NOTIFICATION_THEME_CHANGED);
+ update();
} else if (name.begins_with("custom_styles/")) {
String dname = name.get_slicec('/',1);
data.style_override.erase(dname);
@@ -168,6 +142,10 @@ bool Control::_set(const StringName& p_name, const Variant& p_value) {
String dname = name.get_slicec('/',1);
notification(NOTIFICATION_THEME_CHANGED);
add_icon_override(dname,p_value);
+ } else if (name.begins_with("custom_shaders/")) {
+ String dname = name.get_slicec('/',1);
+ add_shader_override(dname,p_value);
+ notification(NOTIFICATION_THEME_CHANGED);
} else if (name.begins_with("custom_styles/")) {
String dname = name.get_slicec('/',1);
add_style_override(dname,p_value);
@@ -220,6 +198,10 @@ bool Control::_get(const StringName& p_name,Variant &r_ret) const {
String name = sname.get_slicec('/',1);
r_ret= data.icon_override.has(name)?Variant(data.icon_override[name]):Variant();
+ } else if (sname.begins_with("custom_shaders/")) {
+ String name = sname.get_slicec('/',1);
+
+ r_ret= data.shader_override.has(name)?Variant(data.shader_override[name]):Variant();
} else if (sname.begins_with("custom_styles/")) {
String name = sname.get_slicec('/',1);
@@ -269,6 +251,18 @@ void Control::_get_property_list( List<PropertyInfo> *p_list) const {
}
{
List<StringName> names;
+ theme->get_shader_list(get_type_name(),&names);
+ for(List<StringName>::Element *E=names.front();E;E=E->next()) {
+
+ uint32_t hint= PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_CHECKABLE;
+ if (data.shader_override.has(E->get()))
+ hint|=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_CHECKED;
+
+ p_list->push_back( PropertyInfo(Variant::OBJECT,"custom_shaders/"+E->get(),PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemShader,CanvasItemShaderGraph",hint) );
+ }
+ }
+ {
+ List<StringName> names;
theme->get_stylebox_list(get_type_name(),&names);
for(List<StringName>::Element *E=names.front();E;E=E->next()) {
@@ -325,19 +319,6 @@ Control *Control::get_parent_control() const {
return data.parent;
}
-void Control::_input_text(const String& p_text) {
-
- if (!window)
- return;
- if (window->key_focus)
- window->key_focus->call("set_text",p_text);
-
-}
-
-void Control::_gui_input(const InputEvent& p_event) {
-
- _window_input_event(p_event);
-}
void Control::_resize(const Size2& p_size) {
@@ -353,79 +334,12 @@ void Control::_notification(int p_notification) {
case NOTIFICATION_ENTER_TREE: {
- if (data.window==this) {
-
- window = memnew( Window );
- add_to_group("_vp_gui_input"+itos(get_viewport()->get_instance_ID()));
- add_to_group("windows");
-
- window->tooltip_timer = memnew( Timer );
- add_child(window->tooltip_timer);
- window->tooltip_timer->force_parent_owned();
- window->tooltip_timer->set_wait_time( GLOBAL_DEF("display/tooltip_delay",0.7));
- window->tooltip_timer->connect("timeout",this,"_window_show_tooltip");
- window->tooltip=NULL;
- window->tooltip_popup = memnew( TooltipPanel );
- add_child(window->tooltip_popup);
- window->tooltip_popup->force_parent_owned();
- window->tooltip_label = memnew( TooltipLabel );
- window->tooltip_popup->add_child(window->tooltip_label);
- window->tooltip_popup->set_as_toplevel(true);
- window->tooltip_popup->hide();
- window->drag_attempted=false;
- window->drag_preview=NULL;
-
- if (get_tree()->is_editor_hint()) {
-
- Node *n = this;
- while(n) {
-
- if (n->has_meta("_editor_disable_input")) {
- window->disable_input=true;
- break;
- }
- n=n->get_parent();
- }
- }
-
- } else {
- window=NULL;
- }
-
_size_changed();
} break;
case NOTIFICATION_EXIT_TREE: {
- if (data.window) {
-
- if (data.window->window->mouse_focus == this)
- data.window->window->mouse_focus=NULL;
- if (data.window->window->key_focus == this)
- data.window->window->key_focus=NULL;
- if (data.window->window->mouse_over == this)
- data.window->window->mouse_over=NULL;
- if (data.window->window->tooltip == this)
- data.window->window->tooltip=NULL;
- }
-
- if (window) {
-
- remove_from_group("_vp_gui_input"+itos(get_viewport()->get_instance_ID()));
- remove_from_group("windows");
- if (window->tooltip_timer)
- memdelete(window->tooltip_timer);
- window->tooltip_timer=NULL;
- window->tooltip=NULL;
- if (window->tooltip_popup)
- memdelete(window->tooltip_popup);
- window->tooltip_popup=NULL;
-
- memdelete(window);
- window=NULL;
-
- }
-
+ get_viewport()->_gui_remove_control(this);
} break;
@@ -433,112 +347,94 @@ void Control::_notification(int p_notification) {
case NOTIFICATION_ENTER_CANVAS: {
- data.window=NULL;
- data.viewport=NULL;
- data.parent=NULL;
-
- Control *_window=this;
- bool gap=false;
- bool gap_valid=true;
- bool window_found=false;
+ data.parent=get_parent()->cast_to<Control>();
- Node *parent=_window->get_parent();
- if (parent && parent->cast_to<Control>()) {
+ if (is_set_as_toplevel()) {
+ data.SI=get_viewport()->_gui_add_subwindow_control(this);
+ } else {
- data.parent=parent->cast_to<Control>();
- }
- Viewport *viewport=NULL;
+ Node *parent=this; //meh
+ Node *parent_control=NULL;
+ bool subwindow=false;
- parent=this; //meh
+ while(parent) {
- while(parent) {
+ parent=parent->get_parent();
- Control *c=parent->cast_to<Control>();
+ if (!parent)
+ break;
- if (!window_found && c) {
- if (!gap && c!=this) {
- gap_valid=false;
+ CanvasItem *ci =parent->cast_to<CanvasItem>();
+ if (ci && ci->is_set_as_toplevel()) {
+ subwindow=true;
+ break;
}
- _window = c;
- }
-
- CanvasItem *ci =parent->cast_to<CanvasItem>();
+ if (parent->cast_to<Control>()) {
+ parent_control=parent->cast_to<Control>();
+ break;
+ } else if (ci) {
- if ((ci && ci->is_set_as_toplevel()) || !ci) {
- gap=true;
+ } else {
+ break;
+ }
}
- if (parent->cast_to<CanvasLayer>()) {
- window_found=true; //don't go beyond canvas layer
- }
- viewport =parent->cast_to<Viewport>();
- if (viewport) {
- break; //no go beyond viewport either
+ if (parent_control) {
+ //do nothing, has a parent control
+ } else if (subwindow) {
+ //is a subwindow (process input before other controls for that canvas)
+ data.SI=get_viewport()->_gui_add_subwindow_control(this);
+ } else {
+ //is a regular root control
+ data.RI=get_viewport()->_gui_add_root_control(this);
}
- parent=parent->get_parent();
- }
-
- data.window=_window;
- data.viewport=viewport;
- data.parent_canvas_item=get_parent_item();
+ data.parent_canvas_item=get_parent_item();
- if (data.parent_canvas_item) {
-
- data.parent_canvas_item->connect("item_rect_changed",this,"_size_changed");
- } else if (data.viewport) {
-
- //connect viewport
- data.viewport->connect("size_changed",this,"_size_changed");
- } else {
+ if (data.parent_canvas_item) {
+ data.parent_canvas_item->connect("item_rect_changed",this,"_size_changed");
+ } else {
+ //connect viewport
+ get_viewport()->connect("size_changed",this,"_size_changed");
+ }
}
- if (gap && gap_valid && data.window!=this) {
- //is a subwindow, conditions to meet subwindow status are quite complex..
- data.SI = data.window->window->subwindows.push_back(this);
- data.window->window->subwindow_order_dirty=true;
-
- }
-
} break;
case NOTIFICATION_EXIT_CANVAS: {
-
if (data.parent_canvas_item) {
data.parent_canvas_item->disconnect("item_rect_changed",this,"_size_changed");
data.parent_canvas_item=NULL;
- } else if (data.viewport) {
-
+ } else if (!is_set_as_toplevel()) {
//disconnect viewport
- data.viewport->disconnect("size_changed",this,"_size_changed");
- } else {
+ get_viewport()->disconnect("size_changed",this,"_size_changed");
}
if (data.MI) {
-
- if (data.window && data.window->window)
- data.window->window->modal_stack.erase(data.MI);
+ get_viewport()->_gui_remove_modal_control(data.MI);
data.MI=NULL;
}
if (data.SI) {
- //erase from subwindows
- if (data.window && data.window->window)
- data.window->window->subwindows.erase(data.SI);
+ get_viewport()->_gui_remove_subwindow_control(data.SI);
data.SI=NULL;
}
- data.viewport=NULL;
- data.window=NULL;
+ if (data.RI) {
+ get_viewport()->_gui_remove_root_control(data.RI);
+ data.RI=NULL;
+ }
+
data.parent=NULL;
+ data.parent_canvas_item=NULL;
} break;
@@ -569,8 +465,11 @@ void Control::_notification(int p_notification) {
data.parent->update();
update();
- if (data.SI && data.window) {
- data.window->window->subwindow_order_dirty=true;
+ if (data.SI) {
+ get_viewport()->_gui_set_subwindow_order_dirty();
+ }
+ if (data.RI) {
+ get_viewport()->_gui_set_root_order_dirty();
}
} break;
@@ -580,8 +479,8 @@ void Control::_notification(int p_notification) {
} break;
case NOTIFICATION_DRAW: {
- Matrix32 xform;
- xform.set_origin(get_pos());
+ Matrix32 xform=Matrix32(data.rotation,get_pos());
+ xform.scale_basis(data.scale);
VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(),xform);
VisualServer::get_singleton()->canvas_item_set_custom_rect( get_canvas_item(),true, Rect2(Point2(),get_size()));
//emit_signal(SceneStringNames::get_singleton()->draw);
@@ -610,30 +509,16 @@ void Control::_notification(int p_notification) {
update();
} break;
+ case NOTIFICATION_MODAL_CLOSE: {
+
+ emit_signal("modal_close");
+ } break;
case NOTIFICATION_VISIBILITY_CHANGED: {
if (!is_visible()) {
- if (data.window->window->mouse_focus == this) {
- data.window->window->mouse_focus=NULL;
- }
- if (data.window==this) {
- window->drag_data=Variant();
- if (window->drag_preview) {
- memdelete( window->drag_preview);
- window->drag_preview=NULL;
- }
- }
-
- if (data.window->window->key_focus == this)
- data.window->window->key_focus=NULL;
- if (data.window->window->mouse_over == this)
- data.window->window->mouse_over=NULL;
- if (data.window->window->tooltip == this)
- data.window->window->tooltip=NULL;
- if (data.window->window->tooltip == this)
- data.window->window->tooltip=NULL;
+ get_viewport()->_gui_hid_control(this);
_modal_stack_remove();
minimum_size_changed();
@@ -647,10 +532,7 @@ void Control::_notification(int p_notification) {
} break;
case SceneTree::NOTIFICATION_WM_UNFOCUS_REQUEST: {
- if (!window)
- return;
- if (window->key_focus)
- window->key_focus->release_focus();
+ get_viewport()->_gui_unfocus_control(this);
} break;
@@ -726,605 +608,30 @@ void Control::drop_data(const Point2& p_point,const Variant& p_data){
void Control::force_drag(const Variant& p_data,Control *p_control) {
ERR_FAIL_COND(!is_inside_tree());
- ERR_FAIL_COND(!data.window);
ERR_FAIL_COND(p_data.get_type()==Variant::NIL);
+ get_viewport()->_gui_force_drag(this,p_data,p_control);
-
- data.window->window->drag_data=p_data;
- data.window->window->mouse_focus=NULL;
-
- if (p_control) {
- data.window->set_drag_preview(p_control);
- }
}
void Control::set_drag_preview(Control *p_control) {
- ERR_FAIL_NULL(p_control);
- ERR_FAIL_COND( !((Object*)p_control)->cast_to<Control>());
- ERR_FAIL_COND(!is_inside_tree() || !data.window);
- ERR_FAIL_COND(p_control->is_inside_tree());
- ERR_FAIL_COND(p_control->get_parent()!=NULL);
-
- if (data.window->window->drag_preview) {
- memdelete(data.window->window->drag_preview);
- }
- p_control->set_as_toplevel(true);
- p_control->set_pos(data.window->window->last_mouse_pos);
- data.window->add_child(p_control);
- if (data.window->window->drag_preview) {
- memdelete( data.window->window->drag_preview );
- }
-
- data.window->window->drag_preview=p_control;
-
-}
-
-
-Control* Control::_find_next_visible_control_at_pos(Node* p_node,const Point2& p_global,Matrix32& r_xform) const {
-
- return NULL;
+ ERR_FAIL_COND(!is_inside_tree());
+ get_viewport()->_gui_set_drag_preview(this,p_control);
}
-Control* Control::_find_control_at_pos(CanvasItem* p_node,const Point2& p_global,const Matrix32& p_xform,Matrix32& r_inv_xform) {
-
- if (p_node->cast_to<Viewport>())
- return NULL;
-
- Control *c=p_node->cast_to<Control>();
-
- if (c) {
- // print_line("at "+String(c->get_path())+" POS "+c->get_pos()+" bt "+p_xform);
- }
-
- if (c==data.window) {
- //try subwindows first!!
-
- c->_window_sort_subwindows(); // sort them
-
- for (List<Control*>::Element *E=c->window->subwindows.back();E;E=E->prev()) {
-
- Control *sw = E->get();
- if (!sw->is_visible())
- continue;
-
- Matrix32 xform;
- CanvasItem *pci = sw->get_parent_item();
- if (pci)
- xform=pci->get_global_transform();
- Control *ret = _find_control_at_pos(sw,p_global,xform,r_inv_xform);
- if (ret)
- return ret;
-
- }
- }
-
- if (p_node->is_hidden()) {
- //return _find_next_visible_control_at_pos(p_node,p_global,r_inv_xform);
- return NULL; //canvas item hidden, discard
- }
-
- Matrix32 matrix = p_xform * p_node->get_transform();
-
- if (!c || !c->clips_input() || c->has_point(matrix.affine_inverse().xform(p_global))) {
-
- for(int i=p_node->get_child_count()-1;i>=0;i--) {
-
- if (p_node==data.window->window->tooltip_popup)
- continue;
-
- CanvasItem *ci = p_node->get_child(i)->cast_to<CanvasItem>();
- if (!ci || ci->is_set_as_toplevel())
- continue;
-
- Control *ret=_find_control_at_pos(ci,p_global,matrix,r_inv_xform);;
- if (ret)
- return ret;
- }
- }
-
- if (!c)
- return NULL;
-
- matrix.affine_invert();
-
- //conditions for considering this as a valid control for return
- if (!c->data.ignore_mouse && c->has_point(matrix.xform(p_global)) && (!window->drag_preview || (c!=window->drag_preview && !window->drag_preview->is_a_parent_of(c)))) {
- r_inv_xform=matrix;
- return c;
- } else
- return NULL;
-}
-
-void Control::_window_cancel_input_ID(int p_input) {
-
- window->cancelled_input_ID=(unsigned int)p_input;
-}
-
-void Control::_window_remove_focus() {
-
- if (window->key_focus) {
- Node *f=window->key_focus;
- window->key_focus=NULL;
- f->notification( NOTIFICATION_FOCUS_EXIT,true );
-
- }
-}
-bool Control::window_has_modal_stack() const {
+bool Control::is_window_modal_on_top() const {
- if (!data.window)
+ if (!is_inside_tree())
return false;
- return data.window->window->modal_stack.size();
-}
-
-void Control::_window_cancel_tooltip() {
-
- window->tooltip=NULL;
- if (window->tooltip_timer)
- window->tooltip_timer->stop();
- if (window->tooltip_popup)
- window->tooltip_popup->hide();
-
-}
-
-void Control::_window_show_tooltip() {
-
- if (!window->tooltip) {
- return;
- }
-
- String tooltip = window->tooltip->get_tooltip( window->tooltip->get_global_transform().xform_inv(window->tooltip_pos) );
- if (tooltip.length()==0)
- return; // bye
-
-
- if (!window->tooltip_label) {
- return;
- }
- Ref<StyleBox> ttp = get_stylebox("panel","TooltipPanel");
-
- window->tooltip_label->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,ttp->get_margin(MARGIN_LEFT));
- window->tooltip_label->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,ttp->get_margin(MARGIN_TOP));
- window->tooltip_label->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,ttp->get_margin(MARGIN_RIGHT));
- window->tooltip_label->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,ttp->get_margin(MARGIN_BOTTOM));
- window->tooltip_label->set_text(tooltip);
- Rect2 r(window->tooltip_pos+Point2(10,10),window->tooltip_label->get_combined_minimum_size()+ttp->get_minimum_size());
- Rect2 vr = get_viewport_rect();
- if (r.size.x+r.pos.x>vr.size.x)
- r.pos.x=vr.size.x-r.size.x;
- else if (r.pos.x<0)
- r.pos.x=0;
-
- if (r.size.y+r.pos.y>vr.size.y)
- r.pos.y=vr.size.y-r.size.y;
- else if (r.pos.y<0)
- r.pos.y=0;
-
- window->tooltip_popup->set_pos(r.pos);
- window->tooltip_popup->set_size(r.size);
-
- window->tooltip_popup->raise();
-
- window->tooltip_popup->show();
-}
-
-
-void Control::_window_call_input(Control *p_control,const InputEvent& p_input) {
-
-
- while(p_control) {
-
- p_control->call_multilevel(SceneStringNames::get_singleton()->_input_event,p_input);
- if (window->key_event_accepted)
- break;
- p_control->emit_signal(SceneStringNames::get_singleton()->input_event,p_input);
- if (p_control->is_set_as_toplevel()) {
- break;
- }
- if (window->key_event_accepted)
- break;
- if (p_control->data.stop_mouse && (p_input.type==InputEvent::MOUSE_BUTTON || p_input.type==InputEvent::MOUSE_MOTION))
- break;
- p_control=p_control->data.parent;
- }
-}
-
-void Control::_window_input_event(InputEvent p_event) {
-
-
-
- if (!window)
- return;
-
- if (window->disable_input)
- return;
-
- if (p_event.ID==window->cancelled_input_ID) {
- return;
- }
- if (!is_visible()) {
- return; //simple and plain
- }
- switch(p_event.type) {
-
- case InputEvent::MOUSE_BUTTON: {
-
-
- 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) {
-
-
-
- Size2 pos = mpos;
- if (window->mouse_focus && p_event.mouse_button.button_index!=window->mouse_focus_button) {
-
- //do not steal mouse focus and stuff
-
- } else {
-
-
- _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))) {
-
- 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;
- }
- }
-
-
-
- Matrix32 parent_xform;
-
- 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;
-
- 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();
- }
-
-
- }
-
- p_event.mouse_button.global_x = pos.x;
- p_event.mouse_button.global_y = pos.y;
-
- pos = window->focus_inv_xform.xform(pos);
- p_event.mouse_button.x = pos.x;
- p_event.mouse_button.y = pos.y;
-
-#ifdef DEBUG_ENABLED
- if (ScriptDebugger::get_singleton()) {
-
- Array arr;
- arr.push_back(window->mouse_focus->get_path());
- arr.push_back(window->mouse_focus->get_type());
- ScriptDebugger::get_singleton()->send_message("click_ctrl",arr);
- }
-
- /*if (bool(GLOBAL_DEF("debug/print_clicked_control",false))) {
-
- 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) {
- // also get keyboard focus
- window->mouse_focus->grab_focus();
- }
-
-
- 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) {
- memdelete( window->drag_preview );
- window->drag_preview=NULL;
- }
-
- if (!window->mouse_focus) {
-
- if (window->mouse_over && window->drag_data.get_type()!=Variant::NIL && p_event.mouse_button.button_index==BUTTON_LEFT) {
-
- Size2 pos = mpos;
- pos = window->focus_inv_xform.xform(pos);
- window->mouse_over->drop_data(pos,window->drag_data);
- window->drag_data=Variant();
- //change mouse accordingly
- }
-
- break;
- }
-
- Size2 pos = mpos;
- p_event.mouse_button.global_x = pos.x;
- p_event.mouse_button.global_y = pos.y;
- pos = window->focus_inv_xform.xform(pos);
- p_event.mouse_button.x = pos.x;
- p_event.mouse_button.y = pos.y;
-
- if (window->mouse_focus->can_process()) {
- _window_call_input(window->mouse_focus,p_event);
- }
-
- if (p_event.mouse_button.button_index==window->mouse_focus_button) {
- window->mouse_focus=NULL;
- window->mouse_focus_button=-1;
- }
-
- if (window->drag_data.get_type()!=Variant::NIL && p_event.mouse_button.button_index==BUTTON_LEFT) {
- window->drag_data=Variant(); //always clear
- }
-
-
- get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
- get_tree()->set_input_as_handled();
-
- }
- } break;
- case InputEvent::MOUSE_MOTION: {
-
- window->key_event_accepted=false;
-
- Matrix32 localizer = (get_canvas_transform()).affine_inverse();
- Size2 pos = localizer.xform(Size2(p_event.mouse_motion.x,p_event.mouse_motion.y));
- Vector2 speed = localizer.basis_xform(Point2(p_event.mouse_motion.speed_x,p_event.mouse_motion.speed_y));
- Vector2 rel = localizer.basis_xform(Point2(p_event.mouse_motion.relative_x,p_event.mouse_motion.relative_y));
-
- window->last_mouse_pos=pos;
-
- Control *over = NULL;
-
- Matrix32 parent_xform;
- if (data.parent_canvas_item)
- parent_xform=data.parent_canvas_item->get_global_transform();
-
- // D&D
- if (!window->drag_attempted && window->mouse_focus && p_event.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
-
- window->drag_accum+=rel;
- float len = window->drag_accum.length();
- if (len>10) {
- window->drag_data=window->mouse_focus->get_drag_data(window->focus_inv_xform.xform(pos)-window->drag_accum);
- if (window->drag_data.get_type()!=Variant::NIL) {
-
- window->mouse_focus=NULL;
- }
- window->drag_attempted=true;
- }
- }
-
-
- if (window->mouse_focus) {
- over=window->mouse_focus;
- //recompute focus_inv_xform again here
-
- } else {
-
- over = _find_control_at_pos(this,pos,parent_xform,window->focus_inv_xform);
- }
-
-
- if (window->drag_data.get_type()==Variant::NIL && over && !window->modal_stack.empty()) {
-
- Control *top = window->modal_stack.back()->get();
- if (over!=top && !top->is_a_parent_of(over)) {
-
- break; // don't send motion event to anything below modal stack top
- }
- }
-
- if (over!=window->mouse_over) {
-
- if (window->mouse_over)
- window->mouse_over->notification(NOTIFICATION_MOUSE_EXIT);
-
- if (over)
- over->notification(NOTIFICATION_MOUSE_ENTER);
-
- }
-
- window->mouse_over=over;
-
- get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_tooltip");
-
- if (window->drag_preview) {
- window->drag_preview->set_pos(pos);
- }
-
- if (!over) {
- OS::get_singleton()->set_cursor_shape(OS::CURSOR_ARROW);
- break;
- }
-
- p_event.mouse_motion.global_x = pos.x;
- p_event.mouse_motion.global_y = pos.y;
- p_event.mouse_motion.speed_x=speed.x;
- p_event.mouse_motion.speed_y=speed.y;
- p_event.mouse_motion.relative_x=rel.x;
- p_event.mouse_motion.relative_y=rel.y;
-
- if (p_event.mouse_motion.button_mask==0 && window->tooltip_timer) {
- //nothing pressed
-
- bool can_tooltip=true;
-
- if (!window->modal_stack.empty()) {
- if (window->modal_stack.back()->get()!=over && !window->modal_stack.back()->get()->is_a_parent_of(over))
- can_tooltip=false;
-
- }
-
-
- if (can_tooltip) {
-
- window->tooltip=over;
- window->tooltip_pos=(parent_xform * get_transform()).affine_inverse().xform(pos);
- window->tooltip_timer->start();
- }
- }
-
-
- pos = window->focus_inv_xform.xform(pos);
-
-
- p_event.mouse_motion.x = pos.x;
- p_event.mouse_motion.y = pos.y;
-
-
- CursorShape cursor_shape = over->get_cursor_shape(pos);
- OS::get_singleton()->set_cursor_shape( (OS::CursorShape)cursor_shape );
-
-
- if (over->can_process()) {
- _window_call_input(over,p_event);
- }
-
-
-
- get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
- get_tree()->set_input_as_handled();
-
-
- if (window->drag_data.get_type()!=Variant::NIL && p_event.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
-
- /*bool can_drop =*/ over->can_drop_data(pos,window->drag_data);
- //change mouse accordingly i guess
- }
-
- } break;
- case InputEvent::ACTION:
- case InputEvent::JOYSTICK_BUTTON:
- case InputEvent::KEY: {
-
- if (window->key_focus) {
-
- window->key_event_accepted=false;
- if (window->key_focus->can_process()) {
- window->key_focus->call_multilevel("_input_event",p_event);
- if (window->key_focus) //maybe lost it
- window->key_focus->emit_signal(SceneStringNames::get_singleton()->input_event,p_event);
- }
-
-
- if (window->key_event_accepted) {
-
- get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
- break;
- }
- }
-
-
- if (p_event.is_pressed() && p_event.is_action("ui_cancel") && !window->modal_stack.empty()) {
-
- _window_sort_modal_stack();
- Control *top = window->modal_stack.back()->get();
- if (!top->data.modal_exclusive) {
-
- top->notification(NOTIFICATION_MODAL_CLOSE);
- top->_modal_stack_remove();
- top->hide();
- }
- }
-
-
- Control * from = window->key_focus ? window->key_focus : NULL; //hmm
-
- //keyboard focus
- //if (from && p_event.key.pressed && !p_event.key.mod.alt && !p_event.key.mod.meta && !p_event.key.mod.command) {
-
- if (from && p_event.is_pressed()) {
- Control * next=NULL;
-
- if (p_event.is_action("ui_focus_next")) {
-
- next = from->find_next_valid_focus();
- }
-
- if (p_event.is_action("ui_focus_prev")) {
-
- next = from->find_prev_valid_focus();
- }
-
- if (p_event.is_action("ui_up")) {
-
- next = from->_get_focus_neighbour(MARGIN_TOP);
- }
-
- if (p_event.is_action("ui_left")) {
-
- next = from->_get_focus_neighbour(MARGIN_LEFT);
- }
-
- if (p_event.is_action("ui_right")) {
-
- next = from->_get_focus_neighbour(MARGIN_RIGHT);
- }
- if (p_event.is_action("ui_down")) {
-
- next = from->_get_focus_neighbour(MARGIN_BOTTOM);
- }
-
-
- if (next) {
- next->grab_focus();
- get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
- }
- }
-
- } break;
- }
-}
-
-Control *Control::get_window() const {
-
- return data.window;
+ return get_viewport()->_gui_is_modal_on_top(this);
}
-bool Control::is_window() const {
-
- return (is_inside_tree() && window);
-}
Size2 Control::get_minimum_size() const {
@@ -1372,6 +679,35 @@ Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type
}
+Ref<Shader> Control::get_shader(const StringName& p_name,const StringName& p_type) const {
+ if (p_type==StringName()) {
+
+ const Ref<Shader>* sdr = data.shader_override.getptr(p_name);
+ if (sdr)
+ return *sdr;
+ }
+
+ StringName type = p_type?p_type:get_type_name();
+
+ // try with custom themes
+ Control *theme_owner = data.theme_owner;
+
+ while(theme_owner) {
+
+ if (theme_owner->data.theme->has_shader(p_name, type))
+ return data.theme_owner->data.theme->get_shader(p_name, type );
+ Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL;
+
+ if (parent)
+ theme_owner=parent->data.theme_owner;
+ else
+ theme_owner=NULL;
+
+ }
+
+ return Theme::get_default()->get_shader( p_name, type );
+}
+
Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p_type) const {
if (p_type==StringName()) {
@@ -1518,7 +854,37 @@ bool Control::has_icon(const StringName& p_name,const StringName& p_type) const
}
return Theme::get_default()->has_icon( p_name, type );
+
+}
+
+bool Control::has_shader(const StringName &p_name, const StringName &p_type) const
+{
+ if (p_type==StringName()) {
+ const Ref<Shader>* sdr = data.shader_override.getptr(p_name);
+ if (sdr)
+ return true;
+ }
+
+ StringName type = p_type?p_type:get_type_name();
+
+ // try with custom themes
+ Control *theme_owner = data.theme_owner;
+
+ while(theme_owner) {
+
+ if (theme_owner->data.theme->has_shader(p_name, type))
+ return true;
+ Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL;
+
+ if (parent)
+ theme_owner=parent->data.theme_owner;
+ else
+ theme_owner=NULL;
+
+ }
+ return Theme::get_default()->has_shader( p_name, type );
+
}
bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) const {
@@ -1650,9 +1016,9 @@ Size2 Control::get_parent_area_size() const {
if (data.parent_canvas_item) {
parent_size=data.parent_canvas_item->get_item_rect().size;
- } else if (data.viewport) {
+ } else {
- parent_size=data.viewport->get_visible_rect().size;
+ parent_size=get_viewport()->get_visible_rect().size;
}
return parent_size;
@@ -1720,8 +1086,8 @@ float Control::_get_parent_range(int p_idx) const {
} if (data.parent_canvas_item) {
return data.parent_canvas_item->get_item_rect().size[p_idx&1];
- } else if (data.viewport) {
- return data.viewport->get_visible_rect().size[p_idx&1];
+ } else {
+ return get_viewport()->get_visible_rect().size[p_idx&1];
}
return 1.0;
@@ -1927,6 +1293,7 @@ void Control::set_size(const Size2& p_size) {
data.margin[3] = _s2a( y+h, data.anchor[3], ph );
_size_changed();
+
}
@@ -1946,10 +1313,9 @@ Rect2 Control::get_global_rect() const {
}
Rect2 Control::get_window_rect() const {
-
+ ERR_FAIL_COND_V(!is_inside_tree(),Rect2());
Rect2 gr = get_global_rect();
- if (data.viewport)
- gr.pos+=data.viewport->get_visible_rect().pos;
+ gr.pos+=get_viewport()->get_visible_rect().pos;
return gr;
}
@@ -1983,7 +1349,14 @@ void Control::add_icon_override(const StringName& p_name, const Ref<Texture>& p_
data.icon_override[p_name]=p_icon;
notification(NOTIFICATION_THEME_CHANGED);
update();
+
+}
+void Control::add_shader_override(const StringName &p_name, const Ref<Shader> &p_shader) {
+ ERR_FAIL_COND(p_shader.is_null());
+ data.shader_override[p_name]=p_shader;
+ notification(NOTIFICATION_THEME_CHANGED);
+ update();
}
void Control::add_style_override(const StringName& p_name, const Ref<StyleBox>& p_style) {
@@ -2091,7 +1464,17 @@ Control *Control::find_next_valid_focus() const {
}
if (!next_child) {
- next_child=get_window();
+
+ next_child=const_cast<Control*>(this);;
+ while(next_child) {
+
+ if (next_child->data.SI || next_child->data.RI)
+ break;
+ next_child=next_child->get_parent_control();
+
+ }
+
+
}
}
@@ -2209,128 +1592,69 @@ Control::FocusMode Control::get_focus_mode() const {
}
bool Control::has_focus() const {
- return (data.window && data.window->window->key_focus==this);
+ return is_inside_tree() && get_viewport()->_gui_control_has_focus(this);
}
void Control::grab_focus() {
ERR_FAIL_COND(!is_inside_tree());
- ERR_FAIL_COND(!data.window);
-
if (data.focus_mode==FOCUS_NONE)
return;
-
- //no need for change
- if (data.window->window->key_focus && data.window->window->key_focus==this)
- return;
-
- get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_window_remove_focus");
- data.window->window->key_focus=this;
- notification(NOTIFICATION_FOCUS_ENTER);
-#ifdef DEBUG_ENABLED
- if (GLOBAL_DEF("debug/print_clicked_control", false)) {
- print_line(String(get_path())+" - focus");
- };
-#endif
- update();
+
+ get_viewport()->_gui_control_grab_focus(this);
}
void Control::release_focus() {
ERR_FAIL_COND(!is_inside_tree());
- ERR_FAIL_COND(!data.window);
if (!has_focus())
return;
- get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_window_remove_focus");
- //data.window->window->key_focus=this;
- //notification(NOTIFICATION_FOCUS_ENTER);
+ get_viewport()->_gui_remove_focus();
update();
}
bool Control::is_toplevel_control() const {
- return is_inside_tree() && (!data.parent_canvas_item && !window && is_set_as_toplevel());
+ return is_inside_tree() && (!data.parent_canvas_item && !data.RI && is_set_as_toplevel());
}
void Control::show_modal(bool p_exclusive) {
ERR_FAIL_COND(!is_inside_tree());
- ERR_FAIL_COND(!data.SI && data.window!=this);
- ERR_FAIL_COND(!data.window);
+ ERR_FAIL_COND(!data.SI);
if (is_visible())
hide();
- ERR_FAIL_COND( data.MI );
+ ERR_FAIL_COND( data.MI!=NULL );
show();
raise();
-
- data.window->window->modal_stack.push_back(this);
- data.MI = data.window->window->modal_stack.back();
data.modal_exclusive=p_exclusive;
- if (data.window->window->key_focus)
- data.modal_prev_focus_owner = data.window->window->key_focus->get_instance_ID();
- else
- data.modal_prev_focus_owner=0;
+ data.MI=get_viewport()->_gui_show_modal(this);
}
-void Control::_window_sort_subwindows() {
-
- if (!window->subwindow_order_dirty)
- return;
-
-
- window->modal_stack.sort_custom<CComparator>();
- window->subwindows.sort_custom<CComparator>();
-
- window->subwindow_order_dirty=false;
-
-}
-
-void Control::_window_sort_modal_stack() {
-
- window->modal_stack.sort_custom<CComparator>();
+void Control::_modal_set_prev_focus_owner(ObjectID p_prev) {
+ data.modal_prev_focus_owner=p_prev;
}
void Control::_modal_stack_remove() {
- List<Control*>::Element *next=NULL; //transfer the focus stack to the next
-
-
- if (data.window && data.MI) {
-
- next = data.MI->next();
-
-
- data.window->window->modal_stack.erase(data.MI);
- data.MI=NULL;
- }
-
- if (data.modal_prev_focus_owner) {
-
- if (!next) { //top of stack
+ ERR_FAIL_COND(!is_inside_tree());
- Object *pfo = ObjectDB::get_instance(data.modal_prev_focus_owner);
- Control *pfoc = pfo->cast_to<Control>();
- if (!pfoc)
- return;
+ if (!data.MI)
+ return;
- if (!pfoc->is_inside_tree() || !pfoc->is_visible())
- return;
- pfoc->grab_focus();
- } else {
+ get_viewport()->_gui_remove_from_modal_stack(data.MI,data.modal_prev_focus_owner);
- next->get()->data.modal_prev_focus_owner=data.modal_prev_focus_owner;
- }
+ data.MI=NULL;
+ data.modal_prev_focus_owner=0;
- data.modal_prev_focus_owner=0;
- }
}
void Control::_propagate_theme_changed(Control *p_owner) {
@@ -2368,17 +1692,11 @@ void Control::set_theme(const Ref<Theme>& p_theme) {
}
-void Control::_window_accept_event() {
+void Control::accept_event() {
- window->key_event_accepted=true;
if (is_inside_tree())
- get_tree()->set_input_as_handled();
+ get_viewport()->_gui_accept_event();
-}
-void Control::accept_event() {
-
- if (is_inside_tree() && get_window())
- get_window()->_window_accept_event();
}
@@ -2412,9 +1730,9 @@ Control::CursorShape Control::get_cursor_shape(const Point2& p_pos) const {
Matrix32 Control::get_transform() const {
- Matrix32 xf;
- xf.set_origin(get_pos());
- return xf;
+ Matrix32 xform=Matrix32(data.rotation,get_pos());
+ xform.scale_basis(data.scale);
+ return xform;
}
String Control::_get_tooltip() const {
@@ -2507,7 +1825,7 @@ Control *Control::_get_focus_neighbour(Margin p_margin,int p_count) {
if (c) {
if (c->data.SI)
break;
- if (c==data.window)
+ if (c->data.RI)
break;
}
base=base->get_parent();
@@ -2626,35 +1944,8 @@ void Control::grab_click_focus() {
ERR_FAIL_COND(!is_inside_tree());
- if (data.window && data.window->window->mouse_focus) {
-
- Window *w=data.window->window;
- if (w->mouse_focus==this)
- return;
- InputEvent ie;
- ie.type=InputEvent::MOUSE_BUTTON;
- InputEventMouseButton &mb=ie.mouse_button;
-
- //send unclic
-
- Point2 click =w->mouse_focus->get_global_transform().affine_inverse().xform(w->last_mouse_pos);
- mb.x=click.x;
- mb.y=click.y;
- mb.button_index=w->mouse_focus_button;
- mb.pressed=false;
- w->mouse_focus->call_deferred("_input_event",ie);
-
-
- w->mouse_focus=this;
- w->focus_inv_xform=w->mouse_focus->get_global_transform().affine_inverse();
- click =w->mouse_focus->get_global_transform().affine_inverse().xform(w->last_mouse_pos);
- mb.x=click.x;
- mb.y=click.y;
- mb.button_index=w->mouse_focus_button;
- mb.pressed=true;
- w->mouse_focus->call_deferred("_input_event",ie);
+ get_viewport()->_gui_grab_click_focus(this);
- }
}
void Control::minimum_size_changed() {
@@ -2703,8 +1994,7 @@ bool Control::is_stopping_mouse() const {
Control *Control::get_focus_owner() const {
ERR_FAIL_COND_V(!is_inside_tree(),NULL);
- ERR_FAIL_COND_V(!data.window,NULL);
- return data.window->window->key_focus;
+ return get_viewport()->_gui_get_focus_owner();
}
@@ -2728,24 +2018,69 @@ bool Control::is_text_field() const {
return false;
}
+
+void Control::_set_rotation_deg(float p_rot) {
+ set_rotation(Math::deg2rad(p_rot));
+}
+
+float Control::_get_rotation_deg() const {
+ return Math::rad2deg(get_rotation());
+}
+
+void Control::set_rotation(float p_rotation) {
+
+ data.rotation=p_rotation;
+ update();
+ _notify_transform();
+}
+
+float Control::get_rotation() const{
+
+ return data.rotation;
+}
+
+void Control::set_scale(const Vector2& p_scale){
+
+ data.scale=p_scale;
+ update();
+ _notify_transform();
+}
+Vector2 Control::get_scale() const{
+
+ return data.scale;
+}
+
+Control *Control::get_root_parent_control() const {
+
+ const CanvasItem *ci=this;
+ const Control *root=this;
+
+ while(ci) {
+
+ const Control *c = ci->cast_to<Control>();
+ if (c) {
+ root=c;
+
+ if (c->data.RI || c->data.MI || c->is_toplevel_control())
+ break;
+ }
+
+ ci=ci->get_parent_item();
+ }
+
+ return const_cast<Control*>(root);
+}
+
void Control::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("_window_input_event"),&Control::_window_input_event);
- ObjectTypeDB::bind_method(_MD("_gui_input"),&Control::_gui_input);
- ObjectTypeDB::bind_method(_MD("_input_text"),&Control::_input_text);
+
// ObjectTypeDB::bind_method(_MD("_window_resize_event"),&Control::_window_resize_event);
- ObjectTypeDB::bind_method(_MD("_window_remove_focus"),&Control::_window_remove_focus);
- ObjectTypeDB::bind_method(_MD("_cancel_input_ID"),&Control::_window_cancel_input_ID);
- ObjectTypeDB::bind_method(_MD("_cancel_tooltip"),&Control::_window_cancel_tooltip);
- ObjectTypeDB::bind_method(_MD("_window_show_tooltip"),&Control::_window_show_tooltip);
ObjectTypeDB::bind_method(_MD("_size_changed"),&Control::_size_changed);
ObjectTypeDB::bind_method(_MD("_update_minimum_size"),&Control::_update_minimum_size);
ObjectTypeDB::bind_method(_MD("accept_event"),&Control::accept_event);
ObjectTypeDB::bind_method(_MD("get_minimum_size"),&Control::get_minimum_size);
ObjectTypeDB::bind_method(_MD("get_combined_minimum_size"),&Control::get_combined_minimum_size);
- ObjectTypeDB::bind_method(_MD("is_window"),&Control::is_window);
- ObjectTypeDB::bind_method(_MD("get_window"),&Control::get_window);
ObjectTypeDB::bind_method(_MD("set_anchor","margin","anchor_mode"),&Control::set_anchor);
ObjectTypeDB::bind_method(_MD("get_anchor","margin"),&Control::get_anchor);
ObjectTypeDB::bind_method(_MD("set_margin","margin","offset"),&Control::set_margin);
@@ -2756,15 +2091,21 @@ void Control::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_size","size"),&Control::set_size);
ObjectTypeDB::bind_method(_MD("set_custom_minimum_size","size"),&Control::set_custom_minimum_size);
ObjectTypeDB::bind_method(_MD("set_global_pos","pos"),&Control::set_global_pos);
+ ObjectTypeDB::bind_method(_MD("set_rotation","rotation"),&Control::set_rotation);
+ ObjectTypeDB::bind_method(_MD("_set_rotation_deg","rotation"),&Control::_set_rotation_deg);
+ ObjectTypeDB::bind_method(_MD("set_scale","scale"),&Control::set_scale);
ObjectTypeDB::bind_method(_MD("get_margin","margin"),&Control::get_margin);
ObjectTypeDB::bind_method(_MD("get_begin"),&Control::get_begin);
ObjectTypeDB::bind_method(_MD("get_end"),&Control::get_end);
ObjectTypeDB::bind_method(_MD("get_pos"),&Control::get_pos);
ObjectTypeDB::bind_method(_MD("get_size"),&Control::get_size);
+ ObjectTypeDB::bind_method(_MD("get_rotation"),&Control::get_rotation);
+ ObjectTypeDB::bind_method(_MD("get_scale"),&Control::get_scale);
ObjectTypeDB::bind_method(_MD("get_custom_minimum_size"),&Control::get_custom_minimum_size);
ObjectTypeDB::bind_method(_MD("get_parent_area_size"),&Control::get_size);
ObjectTypeDB::bind_method(_MD("get_global_pos"),&Control::get_global_pos);
ObjectTypeDB::bind_method(_MD("get_rect"),&Control::get_rect);
+ ObjectTypeDB::bind_method(_MD("_get_rotation_deg"),&Control::_get_rotation_deg);
ObjectTypeDB::bind_method(_MD("get_global_rect"),&Control::get_global_rect);
ObjectTypeDB::bind_method(_MD("set_area_as_parent_rect","margin"),&Control::set_area_as_parent_rect,DEFVAL(0));
ObjectTypeDB::bind_method(_MD("show_modal","exclusive"),&Control::show_modal,DEFVAL(false));
@@ -2785,8 +2126,9 @@ void Control::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_theme","theme:Theme"),&Control::set_theme);
ObjectTypeDB::bind_method(_MD("get_theme:Theme"),&Control::get_theme);
-
+
ObjectTypeDB::bind_method(_MD("add_icon_override","name","texture:Texture"),&Control::add_icon_override);
+ ObjectTypeDB::bind_method(_MD("add_shader_override","name","shader:Shader"),&Control::add_shader_override);
ObjectTypeDB::bind_method(_MD("add_style_override","name","stylebox:StyleBox"),&Control::add_style_override);
ObjectTypeDB::bind_method(_MD("add_font_override","name","font:Font"),&Control::add_font_override);
ObjectTypeDB::bind_method(_MD("add_color_override","name","color"),&Control::add_color_override);
@@ -2846,6 +2188,8 @@ void Control::_bind_methods() {
ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect/pos", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_EDITOR), _SCS("set_pos"),_SCS("get_pos") );
ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect/size", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_EDITOR), _SCS("set_size"),_SCS("get_size") );
ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect/min_size"), _SCS("set_custom_minimum_size"),_SCS("get_custom_minimum_size") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"rect/rotation",PROPERTY_HINT_RANGE,"-1080,1080,0.01"), _SCS("_set_rotation_deg"),_SCS("_get_rotation_deg") );
+ ADD_PROPERTYNO( PropertyInfo(Variant::VECTOR2,"rect/scale"), _SCS("set_scale"),_SCS("get_scale") );
ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"hint/tooltip", PROPERTY_HINT_MULTILINE_TEXT), _SCS("set_tooltip"),_SCS("_get_tooltip") );
ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/left" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_LEFT );
ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/top" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_TOP );
@@ -2906,20 +2250,21 @@ void Control::_bind_methods() {
ADD_SIGNAL( MethodInfo("focus_exit") );
ADD_SIGNAL( MethodInfo("size_flags_changed") );
ADD_SIGNAL( MethodInfo("minimum_size_changed") );
+ ADD_SIGNAL( MethodInfo("modal_close") );
}
Control::Control() {
- data.parent=NULL;
- data.window=NULL;
- data.viewport=NULL;
+ data.parent=NULL;
+
data.ignore_mouse=false;
data.stop_mouse=true;
- window=NULL;
+
data.SI=NULL;
data.MI=NULL;
+ data.RI=NULL;
data.modal=false;
data.theme_owner=NULL;
data.modal_exclusive=false;
@@ -2928,6 +2273,9 @@ Control::Control() {
data.v_size_flags=SIZE_FILL;
data.expand=1;
data.pending_min_size_update=false;
+ data.rotation=0;
+ data.parent_canvas_item=NULL;
+ data.scale=Vector2(1,1);
for (int i=0;i<4;i++) {
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 4311b299c8..a16d88a6df 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -107,7 +107,10 @@ private:
float margin[4];
AnchorType anchor[4];
- FocusMode focus_mode;
+ FocusMode focus_mode;
+
+ float rotation;
+ Vector2 scale;
bool pending_resize;
@@ -121,7 +124,6 @@ private:
bool stop_mouse;
Control *parent;
- Control *window;
bool modal;
bool modal_exclusive;
Ref<Theme> theme;
@@ -131,91 +133,55 @@ private:
List<Control*>::Element *MI; //modal item
List<Control*>::Element *SI;
+ List<Control*>::Element *RI;
CanvasItem *parent_canvas_item;
- Viewport *viewport;
-
ObjectID modal_prev_focus_owner;
NodePath focus_neighbour[4];
HashMap<StringName, Ref<Texture>, StringNameHasher > icon_override;
+ HashMap<StringName, Ref<Shader>, StringNameHasher > shader_override;
HashMap<StringName, Ref<StyleBox>, StringNameHasher > style_override;
HashMap<StringName, Ref<Font>, StringNameHasher > font_override;
HashMap<StringName, Color, StringNameHasher > color_override;
HashMap<StringName, int, StringNameHasher > constant_override;
} data;
-
- struct Window {
- // info used when this is a window
-
- bool key_event_accepted;
- Control *mouse_focus;
- int mouse_focus_button;
- Control *key_focus;
- Control *mouse_over;
- Control *tooltip;
- Panel *tooltip_popup;
- Label *tooltip_label;
- Point2 tooltip_pos;
- Point2 last_mouse_pos;
- Point2 drag_accum;
- bool drag_attempted;
- Variant drag_data;
- Control *drag_preview;
- Timer *tooltip_timer;
- List<Control*> modal_stack;
- unsigned int cancelled_input_ID;
- Matrix32 focus_inv_xform;
- bool subwindow_order_dirty;
- List<Control*> subwindows;
- bool disable_input;
-
- Window();
- };
-
- Window *window;
-
+
// used internally
- Control* _find_next_visible_control_at_pos(Node* p_node,const Point2& p_global,Matrix32& r_xform) const;
Control* _find_control_at_pos(CanvasItem* p_node,const Point2& p_pos,const Matrix32& p_xform,Matrix32& r_inv_xform);
- void _window_sort_subwindows();
- void _window_accept_event();
- void _window_remove_focus();
- void _window_cancel_input_ID(int p_input);
- void _window_sort_modal_stack();
void _window_find_focus_neighbour(const Vector2& p_dir, Node *p_at, const Point2* p_points ,float p_min,float &r_closest_dist,Control **r_closest);
Control *_get_focus_neighbour(Margin p_margin,int p_count=0);
- void _window_call_input(Control *p_control,const InputEvent& p_input);
+
float _get_parent_range(int p_idx) const;
float _get_range(int p_idx) const;
float _s2a(float p_val, AnchorType p_anchor,float p_range) const;
float _a2s(float p_val, AnchorType p_anchor,float p_range) const;
- void _modal_stack_remove();
void _propagate_theme_changed(Control *p_owner);
void _change_notify_margins();
- void _window_cancel_tooltip();
- void _window_show_tooltip();
void _update_minimum_size();
void _update_scroll();
- void _gui_input(const InputEvent& p_event); //used by scene main loop
- void _input_text(const String& p_text);
void _resize(const Size2& p_size);
void _size_changed();
String _get_tooltip() const;
+ void _set_rotation_deg(float p_rot);
+ float _get_rotation_deg() const;
+
+friend class Viewport;
+ void _modal_stack_remove();
+ void _modal_set_prev_focus_owner(ObjectID p_prev);
protected:
- bool window_has_modal_stack() const;
- virtual void _window_input_event(InputEvent p_event);
+ //virtual void _window_input_event(InputEvent p_event);
bool _set(const StringName& p_name, const Variant& p_value);
bool _get(const StringName& p_name,Variant &r_ret) const;
@@ -265,8 +231,8 @@ public:
void set_custom_minimum_size(const Size2& p_custom);
Size2 get_custom_minimum_size() const;
- bool is_window() const;
- Control *get_window() const;
+ bool is_window_modal_on_top() const;
+
Control *get_parent_control() const;
@@ -299,6 +265,13 @@ public:
Rect2 get_rect() const;
Rect2 get_global_rect() const;
Rect2 get_window_rect() const; ///< use with care, as it blocks waiting for the visual server
+
+ void set_rotation(float p_rotation);
+ float get_rotation() const;
+
+ void set_scale(const Vector2& p_scale);
+ Vector2 get_scale() const;
+
void set_area_as_parent_rect(int p_margin=0);
@@ -343,18 +316,21 @@ public:
/* SKINNING */
void add_icon_override(const StringName& p_name, const Ref<Texture>& p_icon);
+ void add_shader_override(const StringName& p_name, const Ref<Shader>& p_shader);
void add_style_override(const StringName& p_name, const Ref<StyleBox>& p_style);
void add_font_override(const StringName& p_name, const Ref<Font>& p_font);
void add_color_override(const StringName& p_name, const Color& p_color);
void add_constant_override(const StringName& p_name, int p_constant);
Ref<Texture> get_icon(const StringName& p_name,const StringName& p_type=StringName()) const;
+ Ref<Shader> get_shader(const StringName &p_name, const StringName &p_type=StringName()) const;
Ref<StyleBox> get_stylebox(const StringName& p_name,const StringName& p_type=StringName()) const;
Ref<Font> get_font(const StringName& p_name,const StringName& p_type=StringName()) const;
Color get_color(const StringName& p_name,const StringName& p_type=StringName()) const;
int get_constant(const StringName& p_name,const StringName& p_type=StringName()) const;
bool has_icon(const StringName& p_name,const StringName& p_type=StringName()) const;
+ bool has_shader(const StringName& p_name,const StringName& p_type=StringName()) const;
bool has_stylebox(const StringName& p_name,const StringName& p_type=StringName()) const;
bool has_font(const StringName& p_name,const StringName& p_type=StringName()) const;
bool has_color(const StringName& p_name,const StringName& p_type=StringName()) const;
@@ -382,11 +358,13 @@ public:
void warp_mouse(const Point2& p_to_pos);
- virtual bool is_text_field() const;
+ virtual bool is_text_field() const;
+
+ Control *get_root_parent_control() const;
Control();
~Control();
-
+
};
VARIANT_ENUM_CAST(Control::AnchorType);
diff --git a/scene/gui/custom_button.cpp b/scene/gui/custom_button.cpp
index 53a3bf0914..a70af05418 100644
--- a/scene/gui/custom_button.cpp
+++ b/scene/gui/custom_button.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/custom_button.h b/scene/gui/custom_button.h
index 49fcf7408f..2492750489 100644
--- a/scene/gui/custom_button.h
+++ b/scene/gui/custom_button.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index efda8a66e1..9f08b6f845 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h
index 67c574a420..7c06ded866 100644
--- a/scene/gui/dialogs.h
+++ b/scene/gui/dialogs.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 8e428fd71c..56b9260837 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -46,12 +46,56 @@ VBoxContainer *FileDialog::get_vbox() {
}
void FileDialog::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ refresh->set_icon(get_icon("reload"));
+ }
if (p_what==NOTIFICATION_DRAW) {
//RID ci = get_canvas_item();
//get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size()));
- }
+ }
+
+ if (p_what==NOTIFICATION_POPUP_HIDE) {
+
+ set_process_unhandled_input(false);
+ }
+}
+
+void FileDialog::_unhandled_input(const InputEvent& p_event) {
+
+ if (p_event.type==InputEvent::KEY && is_window_modal_on_top()) {
+
+ const InputEventKey &k=p_event.key;
+
+ if (k.pressed) {
+
+ bool handled=true;
+
+ switch (k.scancode) {
+
+ case KEY_H: {
+
+ if (k.mod.command) {
+ set_show_hidden_files(!show_hidden_files);
+ } else {
+ handled=false;
+ }
+
+ } break;
+ case KEY_F5: {
+
+ invalidate();
+ } break;
+ default: { handled=false; }
+ }
+
+ if (handled)
+ accept_event();
+ }
+ }
}
void FileDialog::set_enable_multiple_selection(bool p_enable) {
@@ -109,6 +153,8 @@ void FileDialog::_post_popup() {
else
tree->grab_focus();
+ set_process_unhandled_input(true);
+
}
void FileDialog::_action_pressed() {
@@ -618,11 +664,13 @@ void FileDialog::_update_drives() {
}
}
-bool FileDialog::default_show_hidden_files=true;
+bool FileDialog::default_show_hidden_files=false;
void FileDialog::_bind_methods() {
+ ObjectTypeDB::bind_method(_MD("_unhandled_input"),&FileDialog::_unhandled_input);
+
ObjectTypeDB::bind_method(_MD("_tree_selected"),&FileDialog::_tree_selected);
ObjectTypeDB::bind_method(_MD("_tree_db_selected"),&FileDialog::_tree_dc_selected);
ObjectTypeDB::bind_method(_MD("_dir_entered"),&FileDialog::_dir_entered);
@@ -645,7 +693,7 @@ void FileDialog::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_vbox:VBoxContainer"),&FileDialog::get_vbox);
ObjectTypeDB::bind_method(_MD("set_access","access"),&FileDialog::set_access);
ObjectTypeDB::bind_method(_MD("get_access"),&FileDialog::get_access);
- ObjectTypeDB::bind_method(_MD("set_show_hidden_files"),&FileDialog::set_show_hidden_files);
+ ObjectTypeDB::bind_method(_MD("set_show_hidden_files","show"),&FileDialog::set_show_hidden_files);
ObjectTypeDB::bind_method(_MD("is_showing_hidden_files"),&FileDialog::is_showing_hidden_files);
ObjectTypeDB::bind_method(_MD("_select_drive"),&FileDialog::_select_drive);
ObjectTypeDB::bind_method(_MD("_make_dir"),&FileDialog::_make_dir);
@@ -700,6 +748,10 @@ FileDialog::FileDialog() {
pathhb->add_child(dir);
dir->set_h_size_flags(SIZE_EXPAND_FILL);
+ refresh = memnew( ToolButton );
+ refresh->connect("pressed",this,"_update_file_list");
+ pathhb->add_child(refresh);
+
drives = memnew( OptionButton );
pathhb->add_child(drives);
drives->connect("item_selected",this,"_select_drive");
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index ec42c7744a..b71a157fa7 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,6 +34,7 @@
#include "scene/gui/line_edit.h"
#include "scene/gui/option_button.h"
#include "scene/gui/dialogs.h"
+#include "scene/gui/tool_button.h"
#include "os/dir_access.h"
#include "box_container.h"
/**
@@ -86,6 +87,8 @@ private:
OptionButton *filter;
DirAccess *dir_access;
ConfirmationDialog *confirm_save;
+
+ ToolButton *refresh;
Vector<String> filters;
@@ -114,6 +117,8 @@ private:
void _update_drives();
+ void _unhandled_input(const InputEvent& p_event);
+
virtual void _post_popup();
protected:
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index deb3151798..9472c589ca 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -1,6 +1,9 @@
#include "graph_edit.h"
#include "os/input.h"
#include "os/keyboard.h"
+#include "scene/gui/box_container.h"
+
+
bool GraphEditFilter::has_point(const Point2& p_point) const {
return ge->_filter_input(p_point);
@@ -42,7 +45,6 @@ bool GraphEdit::is_node_connected(const StringName& p_from, int p_from_port,cons
void GraphEdit::disconnect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port){
-
for(List<Connection>::Element *E=connections.front();E;E=E->next()) {
if (E->get().from==p_from && E->get().from_port==p_from_port && E->get().to==p_to && E->get().to_port==p_to_port) {
@@ -54,14 +56,22 @@ void GraphEdit::disconnect_node(const StringName& p_from, int p_from_port,const
}
}
+bool GraphEdit::clips_input() const {
+
+ return true;
+}
+
void GraphEdit::get_connection_list(List<Connection> *r_connections) const {
*r_connections=connections;
}
+Vector2 GraphEdit::get_scroll_ofs() const{
-void GraphEdit::_scroll_moved(double) {
+ return Vector2(h_scroll->get_val(),v_scroll->get_val());
+}
+void GraphEdit::_scroll_moved(double) {
_update_scroll_offset();
top_layer->update();
@@ -149,6 +159,7 @@ void GraphEdit::add_child_notify(Node *p_child) {
top_layer->call_deferred("raise"); //top layer always on top!
GraphNode *gn = p_child->cast_to<GraphNode>();
if (gn) {
+ gn->set_scale(Vector2(zoom,zoom));
gn->connect("offset_changed",this,"_graph_node_moved",varray(gn));
gn->connect("raise_request",this,"_graph_node_raised",varray(gn));
_graph_node_moved(gn);
@@ -182,6 +193,8 @@ void GraphEdit::_notification(int p_what) {
h_scroll->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,hmin.height);
h_scroll->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0);
+ zoom_icon->set_texture( get_icon("Zoom", "EditorIcons"));
+
}
if (p_what==NOTIFICATION_DRAW) {
VS::get_singleton()->canvas_item_set_clip(get_canvas_item(),true);
@@ -382,8 +395,6 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) {
}
-
-
}
void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color) {
@@ -523,7 +534,9 @@ void GraphEdit::_input_event(const InputEvent& p_ev) {
if (!gn)
continue;
- bool in_box = gn->get_rect().intersects(box_selecting_rect);
+ Rect2 r = gn->get_rect();
+ r.size*=zoom;
+ bool in_box = r.intersects(box_selecting_rect);
if (in_box)
gn->set_selected(box_selection_mode_aditive);
@@ -552,7 +565,12 @@ void GraphEdit::_input_event(const InputEvent& p_ev) {
}
top_layer->update();
} else {
- emit_signal("popup_request", Vector2(b.global_x, b.global_y));
+ if (connecting) {
+ connecting = false;
+ top_layer->update();
+ } else {
+ emit_signal("popup_request", Vector2(b.global_x, b.global_y));
+ }
}
}
@@ -562,8 +580,12 @@ void GraphEdit::_input_event(const InputEvent& p_ev) {
for(int i=get_child_count()-1;i>=0;i--) {
GraphNode *gn=get_child(i)->cast_to<GraphNode>();
- if (gn && gn->get_rect().has_point(get_local_mouse_pos()))
- gn->set_selected(false);
+ if (gn) {
+ Rect2 r = gn->get_rect();
+ r.size*=zoom;
+ if (r.has_point(get_local_mouse_pos()))
+ gn->set_selected(false);
+ }
}
}
@@ -592,8 +614,12 @@ void GraphEdit::_input_event(const InputEvent& p_ev) {
gn=get_child(i)->cast_to<GraphNode>();
- if (gn && gn->get_rect().has_point(get_local_mouse_pos()))
- break;
+ if (gn) {
+ Rect2 r = gn->get_rect();
+ r.size*=zoom;
+ if (r.has_point(get_local_mouse_pos()))
+ break;
+ }
}
if (gn) {
@@ -622,6 +648,9 @@ void GraphEdit::_input_event(const InputEvent& p_ev) {
}
} else {
+ if (_filter_input(Vector2(b.x,b.y)))
+ return;
+
box_selecting = true;
box_selecting_from = get_local_mouse_pos();
if (b.mod.control) {
@@ -666,6 +695,14 @@ void GraphEdit::_input_event(const InputEvent& p_ev) {
previus_selected.clear();
top_layer->update();
}
+
+ if (b.button_index==BUTTON_WHEEL_UP && b.pressed) {
+ sl_zoom->set_val(zoom/0.9);
+ }
+
+ if (b.button_index==BUTTON_WHEEL_DOWN && b.pressed) {
+ sl_zoom->set_val(zoom*0.9);
+ }
}
if (p_ev.type==InputEvent::KEY && p_ev.key.scancode==KEY_D && p_ev.key.pressed && p_ev.key.mod.command) {
@@ -686,6 +723,29 @@ void GraphEdit::clear_connections() {
update();
}
+void GraphEdit::set_zoom(float p_zoom) {
+
+ if (p_zoom<0.01) p_zoom=0.01;
+ if (p_zoom>4) p_zoom=4;
+ if (zoom == p_zoom)
+ return;
+
+ float prev_zoom = zoom;
+ zoom = p_zoom;
+ for (int i = 0; i < get_child_count(); i++) {
+ GraphNode *child = get_child(i)->cast_to<GraphNode>();
+ if (!child)
+ continue;
+ Point2 ofs = child->get_offset() / prev_zoom * zoom;
+ child->set_scale(Vector2(zoom,zoom));
+ child->set_offset(ofs);
+ }
+ update();
+}
+
+float GraphEdit::get_zoom() const {
+ return zoom;
+}
void GraphEdit::set_right_disconnects(bool p_enable) {
@@ -718,6 +778,10 @@ void GraphEdit::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_node_connected","from","from_port","to","to_port"),&GraphEdit::is_node_connected);
ObjectTypeDB::bind_method(_MD("disconnect_node","from","from_port","to","to_port"),&GraphEdit::disconnect_node);
ObjectTypeDB::bind_method(_MD("get_connection_list"),&GraphEdit::_get_connection_list);
+ ObjectTypeDB::bind_method(_MD("get_scroll_ofs"),&GraphEdit::get_scroll_ofs);
+
+ ObjectTypeDB::bind_method(_MD("set_zoom","p_zoom"),&GraphEdit::set_zoom);
+ ObjectTypeDB::bind_method(_MD("get_zoom"),&GraphEdit::get_zoom);
ObjectTypeDB::bind_method(_MD("set_right_disconnects","enable"),&GraphEdit::set_right_disconnects);
ObjectTypeDB::bind_method(_MD("is_right_disconnects_enabled"),&GraphEdit::is_right_disconnects_enabled);
@@ -770,4 +834,21 @@ GraphEdit::GraphEdit() {
h_scroll->connect("value_changed", this,"_scroll_moved");
v_scroll->connect("value_changed", this,"_scroll_moved");
+
+ zoom = 1;
+
+ HBoxContainer* tools = memnew( HBoxContainer );
+ add_child(tools);
+
+ zoom_icon = memnew( TextureFrame );
+ tools->add_child(zoom_icon);
+
+ sl_zoom = memnew( HSlider );
+ sl_zoom->set_min(0.01);
+ sl_zoom->set_max(4);
+ sl_zoom->set_val(1);
+ sl_zoom->set_step(0.01);
+ sl_zoom->connect("value_changed", this, "set_zoom");
+ tools->add_child(sl_zoom);
+ sl_zoom->set_custom_minimum_size(Size2(200,0));
}
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index 44f5a369c2..fe9c36cee4 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -3,7 +3,8 @@
#include "scene/gui/graph_node.h"
#include "scene/gui/scroll_bar.h"
-
+#include "scene/gui/slider.h"
+#include "texture_frame.h"
class GraphEdit;
class GraphEditFilter : public Control {
@@ -34,6 +35,8 @@ public:
};
private:
+ TextureFrame* zoom_icon;
+ HSlider* sl_zoom;
HScrollBar* h_scroll;
VScrollBar* v_scroll;
@@ -53,6 +56,8 @@ private:
bool just_selected;
Vector2 drag_accum;
+ float zoom;
+
bool box_selecting;
bool box_selection_mode_aditive;
Point2 box_selecting_from;
@@ -88,7 +93,7 @@ protected:
virtual void add_child_notify(Node *p_child);
virtual void remove_child_notify(Node *p_child);
void _notification(int p_what);
-
+ virtual bool clips_input() const;
public:
Error connect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port);
@@ -96,11 +101,16 @@ public:
void disconnect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port);
void clear_connections();
+ void set_zoom(float p_zoom);
+ float get_zoom() const;
+
GraphEditFilter *get_top_layer() const { return top_layer; }
void get_connection_list(List<Connection> *r_connections) const;
void set_right_disconnects(bool p_enable);
bool is_right_disconnects_enabled() const;
+
+ Vector2 get_scroll_ofs() const;
GraphEdit();
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 5efc9757b7..762afb158a 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -474,7 +474,10 @@ Vector2 GraphNode::get_connection_input_pos(int p_idx) {
_connpos_update();
ERR_FAIL_INDEX_V(p_idx,conn_input_cache.size(),Vector2());
- return conn_input_cache[p_idx].pos;
+ Vector2 pos = conn_input_cache[p_idx].pos;
+ pos.x *= get_scale().x;
+ pos.y *= get_scale().y;
+ return pos;
}
int GraphNode::get_connection_input_type(int p_idx) {
@@ -501,8 +504,10 @@ Vector2 GraphNode::get_connection_output_pos(int p_idx){
_connpos_update();
ERR_FAIL_INDEX_V(p_idx,conn_output_cache.size(),Vector2());
- return conn_output_cache[p_idx].pos;
-
+ Vector2 pos = conn_output_cache[p_idx].pos;
+ pos.x *= get_scale().x;
+ pos.y *= get_scale().y;
+ return pos;
}
int GraphNode::get_connection_output_type(int p_idx) {
diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h
index 201529380d..dc407a6809 100644
--- a/scene/gui/graph_node.h
+++ b/scene/gui/graph_node.h
@@ -49,6 +49,7 @@ class GraphNode : public Container {
bool selected;
protected:
+
void _input_event(const InputEvent& p_ev);
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp
index 105f66f368..a514f1b3d7 100644
--- a/scene/gui/grid_container.cpp
+++ b/scene/gui/grid_container.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/grid_container.h b/scene/gui/grid_container.h
index 8d8bc27293..588bb17fa1 100644
--- a/scene/gui/grid_container.h
+++ b/scene/gui/grid_container.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index 002e49cbcf..e8097c79a4 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/label.h b/scene/gui/label.h
index 4ea9f5d377..3c14add60d 100644
--- a/scene/gui/label.h
+++ b/scene/gui/label.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 18de8ed568..fdced3f62f 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -245,12 +245,26 @@ void LineEdit::_input_event(InputEvent p_event) {
delete_char();
}
} break;
+ case KEY_KP_4: {
+ if (k.unicode != 0) {
+ handled = false;
+ break;
+ }
+ // numlock disabled. fallthrough to key_left
+ }
case KEY_LEFT: {
shift_selection_check_pre(k.mod.shift);
set_cursor_pos(get_cursor_pos()-1);
shift_selection_check_post(k.mod.shift);
} break;
+ case KEY_KP_6: {
+ if (k.unicode != 0) {
+ handled = false;
+ break;
+ }
+ // numlock disabled. fallthrough to key_right
+ }
case KEY_RIGHT: {
shift_selection_check_pre(k.mod.shift);
@@ -271,12 +285,26 @@ void LineEdit::_input_event(InputEvent p_event) {
}
} break;
+ case KEY_KP_7: {
+ if (k.unicode != 0) {
+ handled = false;
+ break;
+ }
+ // numlock disabled. fallthrough to key_home
+ }
case KEY_HOME: {
shift_selection_check_pre(k.mod.shift);
set_cursor_pos(0);
shift_selection_check_post(k.mod.shift);
} break;
+ case KEY_KP_1: {
+ if (k.unicode != 0) {
+ handled = false;
+ break;
+ }
+ // numlock disabled. fallthrough to key_end
+ }
case KEY_END: {
shift_selection_check_pre(k.mod.shift);
@@ -287,26 +315,29 @@ void LineEdit::_input_event(InputEvent p_event) {
default: {
- if (k.unicode>=32 && k.scancode!=KEY_DELETE) {
-
- if (editable) {
- selection_delete();
- CharType ucodestr[2]={(CharType)k.unicode,0};
- append_at_cursor(ucodestr);
- emit_signal("text_changed",text);
- _change_notify("text");
- }
-
- } else {
- handled=false;
- }
+ handled=false;
} break;
}
- if (handled)
+ if (handled) {
accept_event();
- else
- return;
+ } else {
+ if (k.unicode>=32 && k.scancode!=KEY_DELETE) {
+
+ if (editable) {
+ selection_delete();
+ CharType ucodestr[2]={(CharType)k.unicode,0};
+ append_at_cursor(ucodestr);
+ emit_signal("text_changed",text);
+ _change_notify("text");
+
+ accept_event();
+ }
+
+ } else {
+ return;
+ }
+ }
selection.old_shift=k.mod.shift;
@@ -568,7 +599,7 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) {
int char_w = 0;
if (font != NULL) {
- int char_w = font->get_char_size(text[ofs]).width;
+ char_w = font->get_char_size(text[ofs]).width;
}
pixel_ofs+=char_w;
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index f28136d66e..bf6459361a 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp
index f10ca6353a..fde5df6b72 100644
--- a/scene/gui/margin_container.cpp
+++ b/scene/gui/margin_container.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/margin_container.h b/scene/gui/margin_container.h
index 56f2344ea7..df9a5c9361 100644
--- a/scene/gui/margin_container.h
+++ b/scene/gui/margin_container.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index be7a6b468a..26540843de 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h
index 47e7382d34..2df632811f 100644
--- a/scene/gui/menu_button.h
+++ b/scene/gui/menu_button.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index ff94a37be0..5c8e5a7381 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -77,9 +77,14 @@ void OptionButton::_selected(int p_which) {
}
}
- ERR_FAIL_COND(selid==-1);
+ if (selid==-1 && p_which>=0 && p_which<popup->get_item_count()) {
+ _select(p_which,true);
+ } else {
- _select(selid,true);
+ ERR_FAIL_COND(selid==-1);
+
+ _select(selid,true);
+ }
}
@@ -299,7 +304,7 @@ void OptionButton::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_item_count"),&OptionButton::get_item_count);
ObjectTypeDB::bind_method(_MD("add_separator"),&OptionButton::add_separator);
ObjectTypeDB::bind_method(_MD("clear"),&OptionButton::clear);
- ObjectTypeDB::bind_method(_MD("select"),&OptionButton::select);
+ ObjectTypeDB::bind_method(_MD("select","idx"),&OptionButton::select);
ObjectTypeDB::bind_method(_MD("get_selected"),&OptionButton::get_selected);
ObjectTypeDB::bind_method(_MD("get_selected_ID"),&OptionButton::get_selected_ID);
ObjectTypeDB::bind_method(_MD("get_selected_metadata"),&OptionButton::get_selected_metadata);
diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h
index 7d850479aa..34e2bdd384 100644
--- a/scene/gui/option_button.h
+++ b/scene/gui/option_button.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/panel.cpp b/scene/gui/panel.cpp
index d9ba20810b..d40daa972c 100644
--- a/scene/gui/panel.cpp
+++ b/scene/gui/panel.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/panel.h b/scene/gui/panel.h
index 7e6be62923..ee4bcd139e 100644
--- a/scene/gui/panel.h
+++ b/scene/gui/panel.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/panel_container.cpp b/scene/gui/panel_container.cpp
index 5ee061356e..bcf75b79f8 100644
--- a/scene/gui/panel_container.cpp
+++ b/scene/gui/panel_container.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/panel_container.h b/scene/gui/panel_container.h
index c09479241c..a40519c9f2 100644
--- a/scene/gui/panel_container.h
+++ b/scene/gui/panel_container.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index 5ce7e2e0d3..1f04985ec6 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -45,12 +45,20 @@ void Popup::_notification(int p_what) {
emit_signal("popup_hide");
}
}
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ //small helper to make editing of these easier in editor
+#ifdef TOOLS_ENABLED
+ if (get_tree()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
+ set_as_toplevel(false);
+ }
+#endif
+ }
+
}
void Popup::_fix_size() {
- Control *window = get_window();
- ERR_FAIL_COND(!window);
#if 0
Point2 pos = get_pos();
@@ -172,14 +180,12 @@ void Popup::popup_centered_minsize(const Size2& p_minsize) {
void Popup::popup_centered(const Size2& p_size) {
- Control *window = get_window();
- ERR_FAIL_COND(!window);
-
+ Point2 window_size = get_viewport_rect().size;
emit_signal("about_to_show");
Rect2 rect;
rect.size = p_size==Size2()?get_size():p_size;
- Point2 window_size = window==this ? get_parent_area_size() :window->get_size();
+
rect.pos = ((window_size-rect.size)/2.0).floor();
set_pos( rect.pos );
set_size( rect.size );
@@ -199,13 +205,11 @@ void Popup::popup_centered(const Size2& p_size) {
void Popup::popup_centered_ratio(float p_screen_ratio) {
- Control *window = get_window();
- ERR_FAIL_COND(!window);
emit_signal("about_to_show");
Rect2 rect;
- Point2 window_size = window==this ? get_parent_area_size() :window->get_size();
+ Point2 window_size = get_viewport_rect().size;
rect.size = (window_size * p_screen_ratio).floor();
rect.pos = ((window_size-rect.size)/2.0).floor();
set_pos( rect.pos );
diff --git a/scene/gui/popup.h b/scene/gui/popup.h
index 6c72a3c82b..9c66e6d7bd 100644
--- a/scene/gui/popup.h
+++ b/scene/gui/popup.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 20f28ecf10..a93d8e524f 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -370,7 +370,7 @@ void PopupMenu::_input_event(const InputEvent &p_event) {
}
int over=_get_mouse_over(Point2(m.x,m.y));
- int id = (over<0 || items[over].separator || items[over].disabled)?-1:items[over].ID;
+ int id = (over<0 || items[over].separator || items[over].disabled)?-1:(items[over].ID>=0?items[over].ID:over);
if (id<0) {
mouse_over=-1;
@@ -524,7 +524,7 @@ void PopupMenu::add_icon_item(const Ref<Texture>& p_icon,const String& p_label,i
item.icon=p_icon;
item.text=p_label;
item.accel=p_accel;
- item.ID=(p_ID<0)?idcount++:p_ID;
+ item.ID=p_ID;
items.push_back(item);
update();
}
@@ -533,7 +533,7 @@ void PopupMenu::add_item(const String& p_label,int p_ID,uint32_t p_accel) {
Item item;
item.text=XL_MESSAGE(p_label);
item.accel=p_accel;
- item.ID=(p_ID<0)?idcount++:p_ID;
+ item.ID=p_ID;
items.push_back(item);
update();
}
@@ -542,7 +542,7 @@ void PopupMenu::add_submenu_item(const String& p_label, const String& p_submenu,
Item item;
item.text=XL_MESSAGE(p_label);
- item.ID=(p_ID<0)?idcount++:p_ID;
+ item.ID=p_ID;
item.submenu=p_submenu;
items.push_back(item);
update();
@@ -554,7 +554,7 @@ void PopupMenu::add_icon_check_item(const Ref<Texture>& p_icon,const String& p_l
item.icon=p_icon;
item.text=XL_MESSAGE(p_label);
item.accel=p_accel;
- item.ID=(p_ID<0)?idcount++:p_ID;
+ item.ID=p_ID;
item.checkable=true;
items.push_back(item);
update();
@@ -564,7 +564,7 @@ void PopupMenu::add_check_item(const String& p_label,int p_ID,uint32_t p_accel)
Item item;
item.text=XL_MESSAGE(p_label);
item.accel=p_accel;
- item.ID=(p_ID<0)?idcount++:p_ID;
+ item.ID=p_ID;
item.checkable=true;
items.push_back(item);
update();
@@ -753,9 +753,11 @@ int PopupMenu::find_item_by_accelerator(uint32_t p_accel) const {
void PopupMenu::activate_item(int p_item) {
+
ERR_FAIL_INDEX(p_item,items.size());
ERR_FAIL_COND(items[p_item].separator);
- emit_signal("item_pressed",items[p_item].ID);
+ int id = items[p_item].ID>=0?items[p_item].ID:p_item;
+ emit_signal("item_pressed",id);
//hide all parent PopupMenue's
Node *next = get_parent();
@@ -789,7 +791,7 @@ void PopupMenu::clear() {
items.clear();
mouse_over=-1;
update();
- idcount=0;
+
}
@@ -896,7 +898,7 @@ void PopupMenu::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_item_icon","idx","icon"),&PopupMenu::set_item_icon);
ObjectTypeDB::bind_method(_MD("set_item_accelerator","idx","accel"),&PopupMenu::set_item_accelerator);
ObjectTypeDB::bind_method(_MD("set_item_metadata","idx","metadata"),&PopupMenu::set_item_metadata);
- ObjectTypeDB::bind_method(_MD("set_item_checked","idx"),&PopupMenu::set_item_checked);
+ ObjectTypeDB::bind_method(_MD("set_item_checked","idx","checked"),&PopupMenu::set_item_checked);
ObjectTypeDB::bind_method(_MD("set_item_disabled","idx","disabled"),&PopupMenu::set_item_disabled);
ObjectTypeDB::bind_method(_MD("set_item_submenu","idx","submenu"),&PopupMenu::set_item_submenu);
ObjectTypeDB::bind_method(_MD("set_item_as_separator","idx","enable"),&PopupMenu::set_item_as_separator);
@@ -937,7 +939,7 @@ void PopupMenu::set_invalidate_click_until_motion() {
PopupMenu::PopupMenu() {
- idcount=0;
+
mouse_over=-1;
set_focus_mode(FOCUS_ALL);
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index ed78fe6738..624f4f542a 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -59,7 +59,6 @@ class PopupMenu : public Popup {
Timer *submenu_timer;
List<Rect2> autohide_areas;
Vector<Item> items;
- int idcount;
int mouse_over;
int submenu_over;
Rect2 parent_rect;
diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp
index e7e2c88f4a..fc0e7be34f 100644
--- a/scene/gui/progress_bar.cpp
+++ b/scene/gui/progress_bar.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/progress_bar.h b/scene/gui/progress_bar.h
index 33b0d5c185..f50df346ac 100644
--- a/scene/gui/progress_bar.h
+++ b/scene/gui/progress_bar.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp
index 7103ee651f..ffcdf98519 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -48,20 +48,20 @@ void Range::Shared::emit_value_changed() {
}
}
-void Range::_changed_notify() {
+void Range::_changed_notify(const char *p_what) {
emit_signal("changed",shared->val);
update();
- _change_notify();
+ _change_notify(p_what);
}
-void Range::Shared::emit_changed() {
+void Range::Shared::emit_changed(const char *p_what) {
for (Set<Range*>::Element *E=owners.front();E;E=E->next()) {
Range *r=E->get();
if (!r->is_inside_tree())
continue;
- r->_changed_notify();
+ r->_changed_notify(p_what);
}
}
@@ -77,7 +77,11 @@ void Range::set_val(double p_val) {
if (p_val<shared->min)
p_val=shared->min;
-
+
+ //avoid to set -0
+ if (p_val == 0)
+ p_val = 0;
+
if (shared->val==p_val)
return;
@@ -90,20 +94,20 @@ void Range::set_min(double p_min) {
shared->min=p_min;
set_val(shared->val);
- shared->emit_changed();
+ shared->emit_changed("range/min");
}
void Range::set_max(double p_max) {
shared->max=p_max;
set_val(shared->val);
- shared->emit_changed();
+ shared->emit_changed("range/max");
}
void Range::set_step(double p_step) {
shared->step=p_step;
- shared->emit_changed();
+ shared->emit_changed("range/step");
}
void Range::set_page(double p_page) {
@@ -111,7 +115,7 @@ void Range::set_page(double p_page) {
shared->page=p_page;
set_val(shared->val);
- shared->emit_changed();
+ shared->emit_changed("range/page");
}
double Range::get_val() const {
@@ -216,11 +220,10 @@ void Range::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_val"),&Range::get_val);
ObjectTypeDB::bind_method(_MD("get_value"),&Range::get_val);
ObjectTypeDB::bind_method(_MD("get_min"),&Range::get_min);
- ObjectTypeDB::bind_method(_MD("get_max"),&Range::get_max);
- ObjectTypeDB::bind_method(_MD("get_step"),&Range::get_step);
- ObjectTypeDB::bind_method(_MD("get_page"),&Range::get_page);
- ObjectTypeDB::bind_method(_MD("get_unit_value"),&Range::get_unit_value);
- ObjectTypeDB::bind_method(_MD("get_rounded_values"),&Range::get_rounded_values);
+ ObjectTypeDB::bind_method(_MD("get_max"),&Range::get_max);
+ ObjectTypeDB::bind_method(_MD("get_step"),&Range::get_step);
+ ObjectTypeDB::bind_method(_MD("get_page"),&Range::get_page);
+ ObjectTypeDB::bind_method(_MD("get_unit_value"),&Range::get_unit_value);
ObjectTypeDB::bind_method(_MD("set_val","value"),&Range::set_val);
ObjectTypeDB::bind_method(_MD("set_value","value"),&Range::set_val);
ObjectTypeDB::bind_method(_MD("set_min","minimum"),&Range::set_min);
@@ -228,7 +231,8 @@ void Range::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_step","step"),&Range::set_step);
ObjectTypeDB::bind_method(_MD("set_page","pagesize"),&Range::set_page);
ObjectTypeDB::bind_method(_MD("set_unit_value","value"),&Range::set_unit_value);
- ObjectTypeDB::bind_method(_MD("set_rounded_values"),&Range::set_rounded_values);
+ ObjectTypeDB::bind_method(_MD("set_rounded_values","enabled"),&Range::set_rounded_values);
+ ObjectTypeDB::bind_method(_MD("is_rounded_values"),&Range::is_rounded_values);
ObjectTypeDB::bind_method(_MD("set_exp_unit_value","enabled"),&Range::set_exp_unit_value);
ObjectTypeDB::bind_method(_MD("is_unit_value_exp"),&Range::is_unit_value_exp);
@@ -244,16 +248,18 @@ void Range::_bind_methods() {
ADD_PROPERTY( PropertyInfo( Variant::REAL, "range/page" ), _SCS("set_page"), _SCS("get_page") );
ADD_PROPERTY( PropertyInfo( Variant::REAL, "range/value" ), _SCS("set_val"), _SCS("get_val") );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "range/exp_edit" ), _SCS("set_exp_unit_value"), _SCS("is_unit_value_exp") );
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "rounded_values" ), _SCS("set_rounded_values"), _SCS("get_rounded_values") );
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "range/rounded" ), _SCS("set_rounded_values"), _SCS("is_rounded_values") );
}
-void Range::set_rounded_values(bool p){
- _rounded_values = p;
+void Range::set_rounded_values(bool p_enable) {
+
+ _rounded_values = p_enable;
}
-bool Range::get_rounded_values() const{
- return _rounded_values;
+bool Range::is_rounded_values() const {
+
+ return _rounded_values;
}
void Range::set_exp_unit_value(bool p_enable) {
diff --git a/scene/gui/range.h b/scene/gui/range.h
index 48361ddb0e..d96ecdfb0b 100644
--- a/scene/gui/range.h
+++ b/scene/gui/range.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -44,7 +44,7 @@ class Range : public Control {
bool exp_unit_value;
Set<Range*> owners;
void emit_value_changed();
- void emit_changed();
+ void emit_changed(const char *p_what="");
};
Shared *shared;
@@ -55,7 +55,7 @@ class Range : public Control {
void _share(Node *p_range);
void _value_changed_notify();
- void _changed_notify();
+ void _changed_notify(const char *p_what="");
protected:
@@ -72,22 +72,23 @@ public:
void set_step(double p_step);
void set_page(double p_page);
void set_unit_value(double p_value);
- void set_rounded_values(bool);
-
+
double get_val() const;
double get_min() const;
double get_max() const;
double get_step() const;
double get_page() const;
double get_unit_value() const;
- bool get_rounded_values() const;
+
+ void set_rounded_values(bool p_enable);
+ bool is_rounded_values() const;
void set_exp_unit_value(bool p_enable);
bool is_unit_value_exp() const;
void share(Range *p_range);
void unshare();
-
+
Range();
~Range();
diff --git a/scene/gui/reference_frame.cpp b/scene/gui/reference_frame.cpp
index b90ea8292d..d037664a62 100644
--- a/scene/gui/reference_frame.cpp
+++ b/scene/gui/reference_frame.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/reference_frame.h b/scene/gui/reference_frame.h
index 8915b1df0c..5d3694e6e8 100644
--- a/scene/gui/reference_frame.h
+++ b/scene/gui/reference_frame.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 3b0425b223..d4ac2652dc 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,35 +30,62 @@
#include "scene/scene_string_names.h"
#include "os/keyboard.h"
#include "os/os.h"
-RichTextLabel::Item *RichTextLabel::_get_next_item(Item* p_item) {
+RichTextLabel::Item *RichTextLabel::_get_next_item(Item* p_item,bool p_free) {
- if (p_item->subitems.size()) {
+ if (p_free) {
- return p_item->subitems.front()->get();
- } else if (!p_item->parent) {
- return NULL;
- } else if (p_item->E->next()) {
+ if (p_item->subitems.size()) {
+
+ return p_item->subitems.front()->get();
+ } else if (!p_item->parent) {
+ return NULL;
+ } else if (p_item->E->next()) {
+
+ return p_item->E->next()->get();
+ } else {
+ //go up until something with a next is found
+ while (p_item->parent && !p_item->E->next()) {
+ p_item=p_item->parent;
+ }
+
+
+ if (p_item->parent)
+ return p_item->E->next()->get();
+ else
+ return NULL;
- return p_item->E->next()->get();
- } else {
- //go up until something with a next is found
- while (p_item->parent && !p_item->E->next()) {
- p_item=p_item->parent;
}
+ } else {
+ if (p_item->subitems.size() && p_item->type!=ITEM_TABLE) {
- if (p_item && p_item->parent)
- return p_item->E->next()->get();
- else
+ return p_item->subitems.front()->get();
+ } else if (p_item->type==ITEM_FRAME) {
return NULL;
+ } else if (p_item->E->next()) {
+ return p_item->E->next()->get();
+ } else {
+ //go up until something with a next is found
+ while (p_item->type!=ITEM_FRAME && !p_item->E->next()) {
+ p_item=p_item->parent;
+ }
+
+
+ if (p_item->type!=ITEM_FRAME)
+ return p_item->E->next()->get();
+ else
+ return NULL;
+
+ }
}
return NULL;
}
-void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p_mode,const Ref<Font> &p_base_font,const Color &p_base_color,const Point2i& p_click_pos,Item **r_click_item,int *r_click_char,bool *r_outside,int p_char_count) {
+
+void RichTextLabel::_process_line(ItemFrame *p_frame,const Vector2& p_ofs,int &y, int p_width, int p_line, ProcessMode p_mode,const Ref<Font> &p_base_font,const Color &p_base_color,const Point2i& p_click_pos,Item **r_click_item,int *r_click_char,bool *r_outside,int p_char_count) {
RID ci;
if (r_outside)
@@ -70,7 +97,7 @@ void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p
*r_click_item=NULL;
}
- Line &l = lines[p_line];
+ Line &l = p_frame->lines[p_line];
Item *it = l.from;
@@ -91,10 +118,13 @@ void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p
l.offset_caches.clear();
l.height_caches.clear();
l.char_count=0;
+ l.minimum_width=0;
}
int wofs=margin;
int spaces_size=0;
+ int align_ofs=0;
+
if (p_mode!=PROCESS_CACHE && align!=ALIGN_FILL)
wofs+=line_ofs;
@@ -125,7 +155,7 @@ void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p
case ALIGN_LEFT: l.offset_caches.push_back(0); break;\
case ALIGN_CENTER: l.offset_caches.push_back(((p_width-margin)-used)/2); break;\
case ALIGN_RIGHT: l.offset_caches.push_back(((p_width-margin)-used)); break;\
- case ALIGN_FILL: l.offset_caches.push_back((p_width-margin)-used+spaces_size); break;\
+ case ALIGN_FILL: l.offset_caches.push_back((p_width-margin)-used/*+spaces_size*/); break;\
}\
l.height_caches.push_back(line_height);\
l.space_caches.push_back(spaces);\
@@ -135,10 +165,11 @@ void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p
spaces=0;\
spaces_size=0;\
wofs=begin;\
+ align_ofs=0;\
if (p_mode!=PROCESS_CACHE) {\
lh=line<l.height_caches.size()?l.height_caches[line]:1;\
}\
- if (p_mode==PROCESS_POINTER && r_click_item && p_click_pos.y>=y && p_click_pos.y<=y+lh && p_click_pos.x<wofs) {\
+ if (p_mode==PROCESS_POINTER && r_click_item && p_click_pos.y>=p_ofs.y+y && p_click_pos.y<=p_ofs.y+y+lh && p_click_pos.x<p_ofs.x+wofs) {\
if (r_outside) *r_outside=true;\
*r_click_item=it;\
*r_click_char=rchar;\
@@ -148,12 +179,15 @@ void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p
#define ENSURE_WIDTH(m_width) \
+ if (p_mode==PROCESS_CACHE) { \
+ l.minimum_width=MAX(l.minimum_width,wofs+m_width);\
+ }\
if (wofs + m_width > p_width) {\
if (p_mode==PROCESS_CACHE) {\
if (spaces>0) \
spaces-=1;\
}\
- if (p_mode==PROCESS_POINTER && r_click_item && p_click_pos.y>=y && p_click_pos.y<=y+lh && p_click_pos.x>wofs) {\
+ if (p_mode==PROCESS_POINTER && r_click_item && p_click_pos.y>=p_ofs.y+y && p_click_pos.y<=p_ofs.y+y+lh && p_click_pos.x>p_ofs.x+wofs) {\
if (r_outside) *r_outside=true; \
*r_click_item=it;\
*r_click_char=rchar;\
@@ -165,7 +199,7 @@ void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p
#define ADVANCE(m_width) \
{\
- if (p_mode==PROCESS_POINTER && r_click_item && p_click_pos.y>=y && p_click_pos.y<=y+lh && p_click_pos.x>=wofs && p_click_pos.x<wofs+m_width) {\
+ if (p_mode==PROCESS_POINTER && r_click_item && p_click_pos.y>=p_ofs.y+y && p_click_pos.y<=p_ofs.y+y+lh && p_click_pos.x>=p_ofs.x+wofs && p_click_pos.x<p_ofs.x+wofs+m_width) {\
if (r_outside) *r_outside=false; \
*r_click_item=it;\
*r_click_char=rchar;\
@@ -218,8 +252,10 @@ if (m_height > line_height) {\
underline=true;
}
+
} else if (p_mode==PROCESS_CACHE) {
l.char_count+=text->text.length();
+
}
rchar=0;
@@ -246,6 +282,8 @@ if (m_height > line_height) {\
if (c[end]==' ') {
+ fw+=cw;
+ /*
if (p_mode==PROCESS_CACHE) {
fw+=cw;
} else if (align==ALIGN_FILL && line<l.space_caches.size() && l.space_caches[line]>0) {
@@ -254,7 +292,7 @@ if (m_height > line_height) {\
found_space=true;
} else {
fw+=cw;
- }
+ }*/
} else {
fw+=cw;
}
@@ -262,23 +300,26 @@ if (m_height > line_height) {\
end++;
}
-
-
ENSURE_WIDTH(w);
-
//print_line("END: "+String::chr(c[end])+".");
if (end && c[end-1]==' ') {
- spaces++;
if (p_mode==PROCESS_CACHE) {
spaces_size+=font->get_char_size(' ').width;
+ } else if (align==ALIGN_FILL) {
+ int ln = MIN(l.offset_caches.size()-1,line);
+ if (l.space_caches[ln]) {
+ align_ofs = spaces * l.offset_caches[ln] / l.space_caches[ln];
+ }
}
+ spaces++;
+ /*
if (found_space) {
int ln = MIN(l.offset_caches.size()-1,line);
fw+=l.offset_caches[ln]/l.space_caches[ln];
- }
+ }*/
}
@@ -294,7 +335,7 @@ if (m_height > line_height) {\
- if (p_mode==PROCESS_POINTER && r_click_char && p_click_pos.y>=y && p_click_pos.y<=y+lh) {
+ if (p_mode==PROCESS_POINTER && r_click_char && p_click_pos.y>=p_ofs.y+y && p_click_pos.y<=p_ofs.y+y+lh) {
//int o = (wofs+w)-p_click_pos.x;
@@ -303,7 +344,7 @@ if (m_height > line_height) {\
cw=tab_size*font->get_char_size(' ').width;
}
- if (p_click_pos.x-cw/2>pofs) {
+ if (p_click_pos.x-cw/2>p_ofs.x+align_ofs+pofs) {
rchar=int((&c[i])-cf);
//print_line("GOT: "+itos(rchar));
@@ -337,13 +378,13 @@ if (m_height > line_height) {\
if (selected) {
cw = font->get_char_size(c[i],c[i+1]).x;
- draw_rect(Rect2(pofs,y,cw,lh),selection_bg);
+ draw_rect(Rect2(p_ofs.x+pofs,p_ofs.y+y,cw,lh),selection_bg);
if (visible)
- font->draw_char(ci,Point2(pofs,y+lh-(fh-ascent)),c[i],c[i+1],selection_fg);
+ font->draw_char(ci,p_ofs+Point2(align_ofs+pofs,y+lh-(fh-ascent)),c[i],c[i+1],selection_fg);
} else {
if (visible)
- cw=font->draw_char(ci,Point2(pofs,y+lh-(fh-ascent)),c[i],c[i+1],color);
+ cw=font->draw_char(ci,p_ofs+Point2(align_ofs+pofs,y+lh-(fh-ascent)),c[i],c[i+1],color);
}
p_char_count++;
@@ -359,7 +400,7 @@ if (m_height > line_height) {\
uc.a*=0.5;
//VS::get_singleton()->canvas_item_add_line(ci,Point2(pofs,y+ascent+2),Point2(pofs+cw,y+ascent+2),uc);
int uy = y+lh-fh+ascent+2;
- VS::get_singleton()->canvas_item_add_line(ci,Point2(pofs,uy),Point2(pofs+cw,uy),uc);
+ VS::get_singleton()->canvas_item_add_line(ci,p_ofs+Point2(align_ofs+pofs,uy),p_ofs+Point2(align_ofs+pofs+cw,uy),uc);
}
ofs+=cw;
}
@@ -397,7 +438,7 @@ if (m_height > line_height) {\
bool visible = visible_characters<0 || p_char_count<visible_characters;
if (p_mode==PROCESS_DRAW && visible) {
- img->image->draw(ci,Point2(wofs,y+lh-font->get_descent()-img->image->get_height()));
+ img->image->draw(ci,p_ofs+Point2(align_ofs+wofs,y+lh-font->get_descent()-img->image->get_height()));
}
p_char_count++;
@@ -435,6 +476,148 @@ if (m_height > line_height) {\
#endif
} break;
+ case ITEM_TABLE: {
+
+ lh=0;
+ ItemTable *table = static_cast<ItemTable*>(it);
+ int hseparation=get_constant("table_hseparation");
+ int vseparation=get_constant("table_vseparation");
+ Color ccolor = _find_color(table,p_base_color);
+ Vector2 draw_ofs = Point2(wofs,y);
+ int max_y=get_size().height;
+
+ if (p_mode==PROCESS_CACHE) {
+
+ int idx=0;
+ //set minimums to zero
+ for(int i=0;i<table->columns.size();i++) {
+ table->columns[i].min_width=0;
+ table->columns[i].width=0;
+ }
+ //compute minimum width for each cell
+ for (List<Item*>::Element *E=table->subitems.front();E;E=E->next()) {
+ ERR_CONTINUE(E->get()->type!=ITEM_FRAME); //children should all be frames
+ ItemFrame *frame = static_cast<ItemFrame*>(E->get());
+
+ int column = idx % table->columns.size();
+
+ int ly=0;
+
+
+ for(int i=0;i<frame->lines.size();i++) {
+
+ _process_line(frame,Point2(),ly,p_width,i,PROCESS_CACHE,cfont,Color());
+ table->columns[column].min_width=MAX( table->columns[i].min_width, frame->lines[i].minimum_width );
+ }
+ idx++;
+ }
+
+ //compute available width and total radio (for expanders)
+
+
+ int total_ratio=0;
+ int available_width=p_width - hseparation * (table->columns.size() -1);
+ table->total_width=hseparation;
+
+ for(int i=0;i<table->columns.size();i++) {
+ available_width-=table->columns[i].min_width;
+ if (table->columns[i].expand)
+ total_ratio+=table->columns[i].expand_ratio;
+ }
+
+ //assign actual widths
+
+ for(int i=0;i<table->columns.size();i++) {
+ table->columns[i].width = table->columns[i].min_width;
+ if (table->columns[i].expand)
+ table->columns[i].width+=table->columns[i].expand_ratio*available_width/total_ratio;
+ table->total_width+=table->columns[i].width+hseparation;
+ }
+
+ //compute caches properly again with the right width
+ idx=0;
+ for (List<Item*>::Element *E=table->subitems.front();E;E=E->next()) {
+ ERR_CONTINUE(E->get()->type!=ITEM_FRAME); //children should all be frames
+ ItemFrame *frame = static_cast<ItemFrame*>(E->get());
+
+ int column = idx % table->columns.size();
+
+
+ for(int i=0;i<frame->lines.size();i++) {
+
+ int ly=0;
+ _process_line(frame,Point2(),ly,table->columns[column].width,i,PROCESS_CACHE,cfont,Color());
+ frame->lines[i].height_cache=ly; //actual height
+ frame->lines[i].height_accum_cache=ly; //actual height
+ }
+ idx++;
+ }
+
+ }
+
+
+
+ Point2 offset(align_ofs+hseparation,vseparation);
+
+ int row_height=0;
+ //draw using computed caches
+ int idx=0;
+ for (List<Item*>::Element *E=table->subitems.front();E;E=E->next()) {
+ ERR_CONTINUE(E->get()->type!=ITEM_FRAME); //children should all be frames
+ ItemFrame *frame = static_cast<ItemFrame*>(E->get());
+
+ int column = idx % table->columns.size();
+
+ int ly=0;
+ int yofs=0;
+
+
+ int lines_h = frame->lines[frame->lines.size()-1].height_accum_cache - (frame->lines[0].height_accum_cache - frame->lines[0].height_cache);
+ int lines_ofs = p_ofs.y+offset.y+draw_ofs.y;
+
+ bool visible = lines_ofs < get_size().height && lines_ofs+lines_h >=0;
+
+ for(int i=0;i<frame->lines.size();i++) {
+
+
+ if (visible) {
+ if (p_mode==PROCESS_DRAW) {
+ _process_line(frame,p_ofs+offset+draw_ofs+Vector2(0,yofs),ly,table->columns[column].width,i,PROCESS_DRAW,cfont,ccolor);
+ } else if (p_mode==PROCESS_POINTER) {
+ _process_line(frame,p_ofs+offset+draw_ofs+Vector2(0,yofs),ly,table->columns[column].width,i,PROCESS_POINTER,cfont,ccolor,p_click_pos,r_click_item,r_click_char,r_outside);
+ }
+ }
+
+ yofs+=frame->lines[i].height_cache;
+ if (p_mode==PROCESS_CACHE) {
+ frame->lines[i].height_accum_cache=offset.y+draw_ofs.y+frame->lines[i].height_cache;
+ }
+
+ }
+
+ row_height=MAX(yofs,row_height);
+ offset.x+=table->columns[column].width+hseparation;
+
+ if (column==table->columns.size()-1) {
+
+ offset.y+=row_height+vseparation;
+ offset.x=hseparation;
+ row_height=0;
+ }
+ idx++;
+ }
+
+ int total_height = offset.y;
+ if (row_height) {
+ total_height=row_height+vseparation;
+ }
+
+
+
+ ADVANCE( table->total_width );
+ CHECK_HEIGHT( total_height );
+
+ } break;
default: {}
@@ -445,7 +628,7 @@ if (m_height > line_height) {\
it = _get_next_item(it);
- if (p_mode == PROCESS_POINTER && r_click_item && itp && !it && p_click_pos.y>y+lh) {
+ if (p_mode == PROCESS_POINTER && r_click_item && itp && !it && p_click_pos.y>p_ofs.y+y+lh) {
//at the end of all, return this
if (r_outside) *r_outside=true;
*r_click_item=itp;
@@ -453,9 +636,9 @@ if (m_height > line_height) {\
return;
}
- if (it && (p_line+1 < lines.size()) && lines[p_line+1].from==it) {
+ if (it && (p_line+1 < p_frame->lines.size()) && p_frame->lines[p_line+1].from==it) {
- if (p_mode==PROCESS_POINTER && r_click_item && p_click_pos.y>=y && p_click_pos.y<=y+lh) {
+ if (p_mode==PROCESS_POINTER && r_click_item && p_click_pos.y>=p_ofs.y+y && p_click_pos.y<=p_ofs.y+y+lh) {
//went to next line, but pointer was on the previous one
if (r_outside) *r_outside=true;
*r_click_item=itp;
@@ -493,8 +676,8 @@ void RichTextLabel::_scroll_changed(double) {
void RichTextLabel::_update_scroll() {
int total_height=0;
- if (lines.size())
- total_height=lines[lines.size()-1].height_accum_cache;
+ if (main->lines.size())
+ total_height=main->lines[main->lines.size()-1].height_accum_cache;
bool exceeds = total_height > get_size().height && scroll_active;
@@ -503,18 +686,18 @@ void RichTextLabel::_update_scroll() {
if (exceeds) {
scroll_visible=true;
- first_invalid_line=0;
+ main->first_invalid_line=0;
scroll_w=vscroll->get_combined_minimum_size().width;
vscroll->show();
vscroll->set_anchor_and_margin( MARGIN_LEFT, ANCHOR_END,scroll_w);
- _validate_line_caches();
+ _validate_line_caches(main);
} else {
scroll_visible=false;
vscroll->hide();
scroll_w=0;
- _validate_line_caches();
+ _validate_line_caches(main);
}
}
@@ -527,7 +710,7 @@ void RichTextLabel::_notification(int p_what) {
case NOTIFICATION_RESIZED: {
- first_invalid_line=0; //invalidate ALL
+ main->first_invalid_line=0; //invalidate ALL
update();
} break;
@@ -535,7 +718,7 @@ void RichTextLabel::_notification(int p_what) {
if (use_bbcode)
parse_bbcode(bbcode);
- first_invalid_line=0; //invalidate ALL
+ main->first_invalid_line=0; //invalidate ALL
update();
} break;
@@ -550,7 +733,7 @@ void RichTextLabel::_notification(int p_what) {
} break;
case NOTIFICATION_DRAW: {
- _validate_line_caches();
+ _validate_line_caches(main);
_update_scroll();
@@ -571,25 +754,25 @@ void RichTextLabel::_notification(int p_what) {
int from_line = 0;
int total_chars = 0;
- while (from_line<lines.size()) {
+ while (from_line<main->lines.size()) {
- if (lines[from_line].height_accum_cache>=ofs)
+ if (main->lines[from_line].height_accum_cache>=ofs)
break;
from_line++;
- total_chars+=lines[from_line].char_count;
+ total_chars+=main->lines[from_line].char_count;
}
- if (from_line>=lines.size())
+ if (from_line>=main->lines.size())
break; //nothing to draw
- int y = (lines[from_line].height_accum_cache - lines[from_line].height_cache) - ofs;
+ int y = (main->lines[from_line].height_accum_cache - main->lines[from_line].height_cache) - ofs;
Ref<Font> base_font=get_font("normal_font");
Color base_color=get_color("default_color");
- while (y<size.height && from_line<lines.size()) {
+ while (y<size.height && from_line<main->lines.size()) {
- _process_line(y,size.width-scroll_w,from_line,PROCESS_DRAW,base_font,base_color,Point2i(),NULL,NULL,NULL,total_chars);
- total_chars+=lines[from_line].char_count;
+ _process_line(main,Point2(),y,size.width-scroll_w,from_line,PROCESS_DRAW,base_font,base_color,Point2i(),NULL,NULL,NULL,total_chars);
+ total_chars+=main->lines[from_line].char_count;
from_line++;
}
}
@@ -597,7 +780,7 @@ void RichTextLabel::_notification(int p_what) {
}
-void RichTextLabel::_find_click(const Point2i& p_click,Item **r_click_item,int *r_click_char,bool *r_outside) {
+void RichTextLabel::_find_click(ItemFrame* p_frame,const Point2i& p_click,Item **r_click_item,int *r_click_char,bool *r_outside) {
if (r_click_item)
*r_click_item=NULL;
@@ -609,26 +792,26 @@ void RichTextLabel::_find_click(const Point2i& p_click,Item **r_click_item,int *
//todo, change to binary search
int from_line = 0;
- while (from_line<lines.size()) {
+ while (from_line<p_frame->lines.size()) {
- if (lines[from_line].height_accum_cache>=ofs)
+ if (p_frame->lines[from_line].height_accum_cache>=ofs)
break;
from_line++;
}
- if (from_line>=lines.size())
+ if (from_line>=p_frame->lines.size())
return;
- int y = (lines[from_line].height_accum_cache - lines[from_line].height_cache) - ofs;
+ int y = (p_frame->lines[from_line].height_accum_cache - p_frame->lines[from_line].height_cache) - ofs;
Ref<Font> base_font=get_font("normal_font");
Color base_color=get_color("default_color");
- while (y<size.height && from_line<lines.size()) {
+ while (y<size.height && from_line<p_frame->lines.size()) {
- _process_line(y,size.width-scroll_w,from_line,PROCESS_POINTER,base_font,base_color,p_click,r_click_item,r_click_char,r_outside);
+ _process_line(p_frame,Point2(),y,size.width-scroll_w,from_line,PROCESS_POINTER,base_font,base_color,p_click,r_click_item,r_click_char,r_outside);
if (r_click_item && *r_click_item)
return;
from_line++;
@@ -643,13 +826,13 @@ Control::CursorShape RichTextLabel::get_cursor_shape(const Point2& p_pos) const
if (!underline_meta || selection.click)
return CURSOR_ARROW;
- if (first_invalid_line<lines.size())
+ if (main->first_invalid_line<main->lines.size())
return CURSOR_ARROW; //invalid
int line=0;
Item *item=NULL;
- ((RichTextLabel*)(this))->_find_click(p_pos,&item,&line);
+ ((RichTextLabel*)(this))->_find_click(main,p_pos,&item,&line);
if (item && ((RichTextLabel*)(this))->_find_meta(item,NULL))
@@ -665,7 +848,7 @@ void RichTextLabel::_input_event(InputEvent p_event) {
case InputEvent::MOUSE_BUTTON: {
- if (first_invalid_line<lines.size())
+ if (main->first_invalid_line<main->lines.size())
return;
const InputEventMouseButton& b = p_event.mouse_button;
@@ -680,7 +863,7 @@ void RichTextLabel::_input_event(InputEvent p_event) {
Item *item=NULL;
bool outside;
- _find_click(Point2i(b.x,b.y),&item,&line,&outside);
+ _find_click(main,Point2i(b.x,b.y),&item,&line,&outside);
if (item) {
@@ -719,7 +902,7 @@ void RichTextLabel::_input_event(InputEvent p_event) {
case InputEvent::KEY: {
const InputEventKey &k=p_event.key;
- if (k.pressed && !k.mod.alt && !k.mod.shift && !k.mod.command && !k.mod.meta) {
+ if (k.pressed && !k.mod.alt && !k.mod.shift && !k.mod.meta) {
bool handled=true;
switch(k.scancode) {
case KEY_PAGEUP: {
@@ -773,7 +956,7 @@ void RichTextLabel::_input_event(InputEvent p_event) {
} break;
case InputEvent::MOUSE_MOTION: {
- if (first_invalid_line<lines.size())
+ if (main->first_invalid_line<main->lines.size())
return;
const InputEventMouseMotion& m = p_event.mouse_motion;
@@ -782,7 +965,7 @@ void RichTextLabel::_input_event(InputEvent p_event) {
int line=0;
Item *item=NULL;
- _find_click(Point2i(m.x,m.y),&item,&line);
+ _find_click(main,Point2i(m.x,m.y),&item,&line);
if (!item)
return; // do not update
@@ -950,9 +1133,9 @@ bool RichTextLabel::_find_meta(Item *p_item,Variant *r_meta) {
}
-void RichTextLabel::_validate_line_caches() {
+void RichTextLabel::_validate_line_caches(ItemFrame* p_frame) {
- if (first_invalid_line==lines.size())
+ if (p_frame->first_invalid_line==p_frame->lines.size())
return;
//validate invalid lines!s
@@ -960,24 +1143,24 @@ void RichTextLabel::_validate_line_caches() {
Ref<Font> base_font=get_font("normal_font");
- for(int i=first_invalid_line;i<lines.size();i++) {
+ for(int i=p_frame->first_invalid_line;i<p_frame->lines.size();i++) {
int y=0;
- _process_line(y,size.width-scroll_w,i,PROCESS_CACHE,base_font,Color());
- lines[i].height_cache=y;
- lines[i].height_accum_cache=y;
+ _process_line(p_frame,Point2(),y,size.width-scroll_w,i,PROCESS_CACHE,base_font,Color());
+ p_frame->lines[i].height_cache=y;
+ p_frame->lines[i].height_accum_cache=y;
if (i>0)
- lines[i].height_accum_cache+=lines[i-1].height_accum_cache;
+ p_frame->lines[i].height_accum_cache+=p_frame->lines[i-1].height_accum_cache;
}
int total_height=0;
- if (lines.size())
- total_height=lines[lines.size()-1].height_accum_cache;
+ if (p_frame->lines.size())
+ total_height=p_frame->lines[p_frame->lines.size()-1].height_accum_cache;
- first_invalid_line=lines.size();
+ main->first_invalid_line=p_frame->lines.size();
updating_scroll=true;
vscroll->set_max(total_height);
@@ -990,17 +1173,20 @@ void RichTextLabel::_validate_line_caches() {
}
-void RichTextLabel::_invalidate_current_line() {
+void RichTextLabel::_invalidate_current_line(ItemFrame* p_frame) {
- if (lines.size()-1 <= first_invalid_line) {
+ if (p_frame->lines.size()-1 <= p_frame->first_invalid_line) {
- first_invalid_line=lines.size()-1;
+ p_frame->first_invalid_line=p_frame->lines.size()-1;
update();
}
}
void RichTextLabel::add_text(const String& p_text) {
+ if (current->type==ITEM_TABLE)
+ return; //can't add anything here
+
int pos=0;
while (pos<p_text.length()) {
@@ -1027,7 +1213,7 @@ void RichTextLabel::add_text(const String& p_text) {
//append text condition!
ItemText *ti = static_cast<ItemText*>(current->subitems.back()->get());
ti->text+=line;
- _invalidate_current_line();
+ _invalidate_current_line(main);
} else {
//append item condition
@@ -1043,11 +1229,11 @@ void RichTextLabel::add_text(const String& p_text) {
if (eol) {
ItemNewline *item = memnew( ItemNewline );
- item->line=lines.size();
+ item->line=current_frame->lines.size();
_add_item(item,false);
- lines.resize(lines.size()+1);
- lines[lines.size()-1].from=item;
- _invalidate_current_line();
+ current_frame->lines.resize(current_frame->lines.size()+1);
+ current_frame->lines[current_frame->lines.size()-1].from=item;
+ _invalidate_current_line(current_frame);
}
@@ -1055,25 +1241,38 @@ void RichTextLabel::add_text(const String& p_text) {
}
}
-void RichTextLabel::_add_item(Item *p_item, bool p_enter) {
+void RichTextLabel::_add_item(Item *p_item, bool p_enter, bool p_ensure_newline) {
+
+
p_item->parent=current;
p_item->E=current->subitems.push_back(p_item);
p_item->index=current_idx++;
+
if (p_enter)
current=p_item;
- if (lines[lines.size()-1].from==NULL) {
- lines[lines.size()-1].from=p_item;
+ if (p_ensure_newline && current_frame->lines[current_frame->lines.size()-1].from) {
+ _invalidate_current_line(current_frame);
+ current_frame->lines.resize( current_frame->lines.size() +1 );
+
+ }
+
+ if (current_frame->lines[current_frame->lines.size()-1].from==NULL) {
+ current_frame->lines[current_frame->lines.size()-1].from=p_item;
}
+ p_item->line=current_frame->lines.size()-1;
- _invalidate_current_line();
+ _invalidate_current_line(current_frame);
}
void RichTextLabel::add_image(const Ref<Texture>& p_image) {
+ if (current->type==ITEM_TABLE)
+ return;
+
ERR_FAIL_COND(p_image.is_null());
ItemImage *item = memnew( ItemImage );
@@ -1084,15 +1283,18 @@ void RichTextLabel::add_image(const Ref<Texture>& p_image) {
void RichTextLabel::add_newline() {
+ if (current->type==ITEM_TABLE)
+ return;
ItemNewline *item = memnew( ItemNewline );
- item->line=lines.size();
- lines.resize(lines.size()+1);
+ item->line=current_frame->lines.size();
+ current_frame->lines.resize(current_frame->lines.size()+1);
_add_item(item,false);
}
void RichTextLabel::push_font(const Ref<Font>& p_font) {
+ ERR_FAIL_COND(current->type==ITEM_TABLE);
ERR_FAIL_COND(p_font.is_null());
ItemFont *item = memnew( ItemFont );
@@ -1102,6 +1304,7 @@ void RichTextLabel::push_font(const Ref<Font>& p_font) {
}
void RichTextLabel::push_color(const Color& p_color) {
+ ERR_FAIL_COND(current->type==ITEM_TABLE);
ItemColor *item = memnew( ItemColor );
item->color=p_color;
@@ -1110,6 +1313,7 @@ void RichTextLabel::push_color(const Color& p_color) {
}
void RichTextLabel::push_underline() {
+ ERR_FAIL_COND(current->type==ITEM_TABLE);
ItemUnderline *item = memnew( ItemUnderline );
_add_item(item,true);
@@ -1118,47 +1322,40 @@ void RichTextLabel::push_underline() {
void RichTextLabel::push_align(Align p_align) {
- lines.resize(lines.size()+1);
+ ERR_FAIL_COND(current->type==ITEM_TABLE);
ItemAlign *item = memnew( ItemAlign );
item->align=p_align;
- _add_item(item,true);
-
- ItemNewline *itemnl = memnew( ItemNewline );
- itemnl->line=lines.size()-1;
- _add_item(itemnl,false);
+ _add_item(item,true,true);
}
void RichTextLabel::push_indent(int p_level) {
+ ERR_FAIL_COND(current->type==ITEM_TABLE);
ERR_FAIL_COND(p_level<0);
- lines.resize(lines.size()+1);
-
ItemIndent *item = memnew( ItemIndent );
item->level=p_level;
- _add_item(item,true);
-
- ItemNewline *itemnl = memnew( ItemNewline );
- itemnl->line=lines.size()-1;
- _add_item(itemnl,false);
+ _add_item(item,true,true);
}
void RichTextLabel::push_list(ListType p_list) {
+ ERR_FAIL_COND(current->type==ITEM_TABLE);
ERR_FAIL_INDEX(p_list,3);
ItemList *item = memnew( ItemList );
item->list_type=p_list;
- _add_item(item,true);
+ _add_item(item,true,true);
}
void RichTextLabel::push_meta(const Variant& p_meta) {
+ ERR_FAIL_COND(current->type==ITEM_TABLE);
ItemMeta *item = memnew( ItemMeta );
item->meta=p_meta;
@@ -1166,9 +1363,62 @@ void RichTextLabel::push_meta(const Variant& p_meta) {
}
+void RichTextLabel::push_table(int p_columns) {
+
+ ERR_FAIL_COND( p_columns < 1);
+ ItemTable *item = memnew( ItemTable );
+
+ item->columns.resize(p_columns);
+ item->total_width=0;
+ for(int i=0;i<item->columns.size();i++) {
+ item->columns[i].expand=false;
+ item->columns[i].expand_ratio=1;
+ }
+ _add_item(item,true,true);
+
+}
+
+void RichTextLabel::set_table_column_expand(int p_column,bool p_expand,int p_ratio) {
+
+ ERR_FAIL_COND(current->type!=ITEM_TABLE);
+ ItemTable *table = static_cast<ItemTable*>(current);
+ ERR_FAIL_INDEX(p_column,table->columns.size());
+ table->columns[p_column].expand=p_expand;
+ table->columns[p_column].expand_ratio=p_ratio;
+}
+
+void RichTextLabel::push_cell(){
+
+ ERR_FAIL_COND(current->type!=ITEM_TABLE);
+
+ ItemFrame *item = memnew( ItemFrame );
+ item->parent_frame=current_frame;
+ _add_item(item,true);
+ current_frame=item;
+ item->cell=true;
+ item->parent_line=item->parent_frame->lines.size()-1;
+ item->lines.resize(1);
+ item->lines[0].from=NULL;
+ item->first_invalid_line=0;
+
+}
+
+int RichTextLabel::get_current_table_column() const {
+
+ ERR_FAIL_COND_V(current->type!=ITEM_TABLE,-1);
+
+ ItemTable *table = static_cast<ItemTable*>(current);
+
+ return table->subitems.size() % table->columns.size();
+
+}
+
void RichTextLabel::pop() {
ERR_FAIL_COND(!current->parent);
+ if (current->type==ITEM_FRAME) {
+ current_frame = static_cast<ItemFrame*>(current)->parent_frame;
+ }
current=current->parent;
}
@@ -1176,9 +1426,10 @@ void RichTextLabel::clear() {
main->_clear_children();
current=main;
- lines.clear();
- lines.resize(1);
- first_invalid_line=0;
+ current_frame=main;
+ main->lines.clear();
+ main->lines.resize(1);
+ main->first_invalid_line=0;
update();
selection.click=NULL;
selection.active=false;
@@ -1189,7 +1440,7 @@ void RichTextLabel::clear() {
void RichTextLabel::set_tab_size(int p_spaces) {
tab_size=p_spaces;
- first_invalid_line=0;
+ main->first_invalid_line=0;
update();
}
@@ -1345,6 +1596,30 @@ Error RichTextLabel::append_bbcode(const String& p_bbcode) {
push_font(mono_font);
pos=brk_end+1;
tag_stack.push_front(tag);
+ } else if (tag.begins_with("table=")) {
+
+ int columns = tag.substr(6,tag.length()).to_int();
+ if (columns<1)
+ columns=1;
+ //use monospace font
+ push_table(columns);
+ pos=brk_end+1;
+ tag_stack.push_front("table");
+ } else if (tag=="cell") {
+
+ push_cell();
+ pos=brk_end+1;
+ tag_stack.push_front(tag);
+ } else if (tag.begins_with("cell=")) {
+
+ int ratio = tag.substr(6,tag.length()).to_int();
+ if (ratio<1)
+ ratio=1;
+ //use monospace font
+ set_table_column_expand(get_current_table_column(),true,ratio);
+ push_cell();
+ pos=brk_end+1;
+ tag_stack.push_front("cell");
} else if (tag=="u") {
//use underline
@@ -1504,16 +1779,15 @@ Error RichTextLabel::append_bbcode(const String& p_bbcode) {
void RichTextLabel::scroll_to_line(int p_line) {
- p_line -= 1;
- ERR_FAIL_INDEX(p_line,lines.size());
- _validate_line_caches();
- vscroll->set_val(lines[p_line].height_accum_cache-lines[p_line].height_cache);
+ ERR_FAIL_INDEX(p_line,main->lines.size());
+ _validate_line_caches(main);
+ vscroll->set_val(main->lines[p_line].height_accum_cache-main->lines[p_line].height_cache);
}
int RichTextLabel::get_line_count() const {
- return lines.size();
+ return current_frame->lines.size();
}
void RichTextLabel::set_selection_enabled(bool p_enabled) {
@@ -1557,32 +1831,31 @@ bool RichTextLabel::search(const String& p_string,bool p_from_selection) {
selection.active=true;
update();
- if (line==-1) {
+ _validate_line_caches(main);
- while(it) {
+ int fh = _find_font(t).is_valid()?_find_font(t)->get_height():get_font("normal_font")->get_height();
- if (it->type==ITEM_NEWLINE) {
+ float offset =0;
- line=static_cast<ItemNewline*>(it)->line;
- break;
+ int line = t->line;
+ Item *item =t;
+ while(item) {
+ if (item->type==ITEM_FRAME) {
+ ItemFrame *frame = static_cast<ItemFrame*>(item);
+ if (line>=0 && line<frame->lines.size()) {
+ offset+=frame->lines[line].height_accum_cache-frame->lines[line].height_cache;
+ line=frame->line;
}
-
- it=_get_next_item(it);
}
-
- }
-
- if (line > 1) {
- line-=1;
+ item=item->parent;
}
-
- scroll_to_line(line);
+ vscroll->set_val(offset-fh);
return true;
}
}
- it=_get_next_item(it);
+ it=_get_next_item(it,true);
charidx=0;
}
@@ -1621,7 +1894,7 @@ void RichTextLabel::selection_copy() {
if (item==selection.to)
break;
- item=_get_next_item(item);
+ item=_get_next_item(item,true);
}
if (text!="") {
@@ -1674,6 +1947,9 @@ void RichTextLabel::_bind_methods() {
ObjectTypeDB::bind_method(_MD("push_list","type"),&RichTextLabel::push_list);
ObjectTypeDB::bind_method(_MD("push_meta","data"),&RichTextLabel::push_meta);
ObjectTypeDB::bind_method(_MD("push_underline"),&RichTextLabel::push_underline);
+ ObjectTypeDB::bind_method(_MD("push_table","columns"),&RichTextLabel::push_table);
+ ObjectTypeDB::bind_method(_MD("set_table_column_expand","column","expand","ratio"),&RichTextLabel::set_table_column_expand);
+ ObjectTypeDB::bind_method(_MD("push_cell"),&RichTextLabel::push_cell);
ObjectTypeDB::bind_method(_MD("pop"),&RichTextLabel::pop);
ObjectTypeDB::bind_method(_MD("clear"),&RichTextLabel::clear);
@@ -1689,7 +1965,7 @@ void RichTextLabel::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_v_scroll"),&RichTextLabel::get_v_scroll);
- ObjectTypeDB::bind_method(_MD("scroll_to_line"),&RichTextLabel::scroll_to_line);
+ ObjectTypeDB::bind_method(_MD("scroll_to_line","line"),&RichTextLabel::scroll_to_line);
ObjectTypeDB::bind_method(_MD("set_tab_size","spaces"),&RichTextLabel::set_tab_size);
ObjectTypeDB::bind_method(_MD("get_tab_size"),&RichTextLabel::get_tab_size);
@@ -1726,7 +2002,7 @@ void RichTextLabel::_bind_methods() {
BIND_CONSTANT( LIST_LETTERS );
BIND_CONSTANT( LIST_DOTS );
- BIND_CONSTANT( ITEM_MAIN );
+ BIND_CONSTANT( ITEM_FRAME );
BIND_CONSTANT( ITEM_TEXT );
BIND_CONSTANT( ITEM_IMAGE );
BIND_CONSTANT( ITEM_NEWLINE );
@@ -1754,8 +2030,8 @@ int RichTextLabel::get_visible_characters() const {
int RichTextLabel::get_total_character_count() const {
int tc=0;
- for(int i=0;i<lines.size();i++)
- tc+=lines[i].char_count;
+ for(int i=0;i<current_frame->lines.size();i++)
+ tc+=current_frame->lines[i].char_count;
return tc;
}
@@ -1764,12 +2040,13 @@ int RichTextLabel::get_total_character_count() const {
RichTextLabel::RichTextLabel() {
- main = memnew( ItemMain );
+ main = memnew( ItemFrame );
main->index=0;
current=main;
- lines.resize(1);
- lines[0].from=main;
- first_invalid_line=0;
+ main->lines.resize(1);
+ main->lines[0].from=main;
+ main->first_invalid_line=0;
+ current_frame=main;
tab_size=4;
default_align=ALIGN_LEFT;
underline_meta=true;
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index eaa8d5d60a..635fe87ad4 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -54,7 +54,7 @@ public:
enum ItemType {
- ITEM_MAIN,
+ ITEM_FRAME,
ITEM_TEXT,
ITEM_IMAGE,
ITEM_NEWLINE,
@@ -64,6 +64,7 @@ public:
ITEM_ALIGN,
ITEM_INDENT,
ITEM_LIST,
+ ITEM_TABLE,
ITEM_META
};
@@ -72,6 +73,24 @@ protected:
static void _bind_methods();
private:
+ struct Item;
+
+ struct Line {
+
+ Item *from;
+ Vector<int> offset_caches;
+ Vector<int> height_caches;
+ Vector<int> space_caches;
+ int height_cache;
+ int height_accum_cache;
+ int char_count;
+ int minimum_width;
+
+ Line() { from=NULL; char_count=0; }
+ };
+
+
+
struct Item {
int index;
@@ -79,18 +98,26 @@ private:
ItemType type;
List<Item*> subitems;
List<Item*>::Element *E;
+ int line;
void _clear_children() { while (subitems.size()) { memdelete(subitems.front()->get()); subitems.pop_front(); } }
- Item() { parent=NULL; E=NULL; }
+ Item() { parent=NULL; E=NULL; line=0;}
virtual ~Item() { _clear_children(); }
};
- struct ItemMain : public Item {
+ struct ItemFrame : public Item{
+
+ int parent_line;
+ bool cell;
+ Vector<Line> lines;
+ int first_invalid_line;
+ ItemFrame *parent_frame;
- ItemMain() { type=ITEM_MAIN; }
+ ItemFrame() { type=ITEM_FRAME; parent_frame=NULL; cell=false; parent_line=0; }
};
+
struct ItemText : public Item {
String text;
@@ -150,11 +177,28 @@ private:
ItemNewline() { type=ITEM_NEWLINE; }
};
- ItemMain *main;
+
+ struct ItemTable : public Item{
+
+ struct Column {
+ bool expand;
+ int expand_ratio;
+ int min_width;
+ int width;
+ };
+
+ Vector<Column> columns;
+ int total_width;
+ ItemTable() { type=ITEM_TABLE; }
+ };
+
+ ItemFrame *main;
Item *current;
+ ItemFrame *current_frame;
VScrollBar *vscroll;
+
bool scroll_visible;
bool scroll_follow;
bool scroll_following;
@@ -163,34 +207,16 @@ private:
bool updating_scroll;
int current_idx;
- struct Line {
-
- Item *from;
- Vector<int> offset_caches;
- Vector<int> height_caches;
- Vector<int> space_caches;
- int height_cache;
- int height_accum_cache;
- int char_count;
-
- Line() { from=NULL; char_count=0; }
- };
-
-
-
-
- Vector<Line> lines;
- int first_invalid_line;
int tab_size;
bool underline_meta;
Align default_align;
- void _invalidate_current_line();
- void _validate_line_caches();
+ void _invalidate_current_line(ItemFrame *p_frame);
+ void _validate_line_caches(ItemFrame *p_frame);
- void _add_item(Item *p_item, bool p_enter=false);
+ void _add_item(Item *p_item, bool p_enter=false,bool p_ensure_newline=false);
@@ -227,8 +253,8 @@ private:
int visible_characters;
- void _process_line(int &y, int p_width, int p_line, ProcessMode p_mode,const Ref<Font> &p_base_font,const Color &p_base_color,const Point2i& p_click_pos=Point2i(),Item **r_click_item=NULL,int *r_click_char=NULL,bool *r_outside=NULL,int p_char_count=0);
- void _find_click(const Point2i& p_click,Item **r_click_item=NULL,int *r_click_char=NULL,bool *r_outside=NULL);
+ void _process_line(ItemFrame *p_frame,const Vector2& p_ofs,int &y, int p_width, int p_line, ProcessMode p_mode,const Ref<Font> &p_base_font,const Color &p_base_color,const Point2i& p_click_pos=Point2i(),Item **r_click_item=NULL,int *r_click_char=NULL,bool *r_outside=NULL,int p_char_count=0);
+ void _find_click(ItemFrame *p_frame, const Point2i& p_click,Item **r_click_item=NULL,int *r_click_char=NULL,bool *r_outside=NULL);
Ref<Font> _find_font(Item *p_item);
@@ -242,12 +268,12 @@ private:
void _scroll_changed(double);
void _input_event(InputEvent p_event);
- Item *_get_next_item(Item* p_item);
+ Item *_get_next_item(Item* p_item, bool p_free=false);
bool use_bbcode;
String bbcode;
-
+ void _update_all_lines();
protected:
void _notification(int p_what);
@@ -264,6 +290,10 @@ public:
void push_indent(int p_level);
void push_list(ListType p_list);
void push_meta(const Variant& p_data);
+ void push_table(int p_columns);
+ void set_table_column_expand(int p_column, bool p_expand, int p_ratio=1);
+ int get_current_table_column() const;
+ void push_cell();
void pop();
void clear();
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index b1fd914fcd..0fd4286f38 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h
index 367bc3eb53..a629ddc56c 100644
--- a/scene/gui/scroll_bar.h
+++ b/scene/gui/scroll_bar.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index e5b5d531a0..a2fc038f9e 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h
index b8d37be08c..50ae236714 100644
--- a/scene/gui/scroll_container.h
+++ b/scene/gui/scroll_container.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/separator.cpp b/scene/gui/separator.cpp
index 5e822a10ad..626b093a2f 100644
--- a/scene/gui/separator.cpp
+++ b/scene/gui/separator.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/separator.h b/scene/gui/separator.h
index 17e9c11e34..7a7dc92b93 100644
--- a/scene/gui/separator.h
+++ b/scene/gui/separator.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index b6292c544b..7ef9d4216b 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -50,9 +50,9 @@ void Slider::_input_event(InputEvent p_event) {
grab.pos=orientation==VERTICAL?mb.y:mb.x;
double max = orientation==VERTICAL ? get_size().height : get_size().width ;
if (orientation==VERTICAL)
- set_val( ( ( -(double)grab.pos / max) * ( get_max() - get_min() ) ) + get_max() );
+ set_unit_value( 1 - ((double)grab.pos / max) );
else
- set_val( ( ( (double)grab.pos / max) * ( get_max() - get_min() ) ) + get_min() );
+ set_unit_value((double)grab.pos / max);
grab.active=true;
grab.uvalue=get_unit_value();
} else {
diff --git a/scene/gui/slider.h b/scene/gui/slider.h
index 5850c48ce3..f85e6d1807 100644
--- a/scene/gui/slider.h
+++ b/scene/gui/slider.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index a48136f541..2b64d36a81 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -68,6 +68,24 @@ void SpinBox::_line_edit_input(const InputEvent& p_event) {
}
+void SpinBox::_range_click_timeout() {
+
+ if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
+
+ bool up = get_local_mouse_pos().y < (get_size().height/2);
+ set_val( get_val() + (up?get_step():-get_step()));
+
+ if (range_click_timer->is_one_shot()) {
+ range_click_timer->set_wait_time(0.075);
+ range_click_timer->set_one_shot(false);
+ range_click_timer->start();
+ }
+
+ } else {
+ range_click_timer->stop();
+ }
+}
+
void SpinBox::_input_event(const InputEvent& p_event) {
@@ -85,6 +103,10 @@ void SpinBox::_input_event(const InputEvent& p_event) {
set_val( get_val() + (up?get_step():-get_step()));
+ range_click_timer->set_wait_time(0.6);
+ range_click_timer->set_one_shot(true);
+ range_click_timer->start();
+
} break;
case BUTTON_RIGHT: {
@@ -112,6 +134,8 @@ void SpinBox::_input_event(const InputEvent& p_event) {
if (p_event.type==InputEvent::MOUSE_BUTTON && !p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) {
//set_default_cursor_shape(CURSOR_ARROW);
+ range_click_timer->stop();
+
if (drag.enabled) {
drag.enabled=false;
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
@@ -167,6 +191,7 @@ void SpinBox::_notification(int p_what) {
Size2i size = get_size();
updown->draw(ci,Point2i(size.width-updown->get_width(),(size.height-updown->get_height())/2));
+
} else if (p_what==NOTIFICATION_FOCUS_EXIT) {
@@ -227,6 +252,7 @@ void SpinBox::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_line_edit_focus_exit"),&SpinBox::_line_edit_focus_exit);
ObjectTypeDB::bind_method(_MD("get_line_edit"),&SpinBox::get_line_edit);
ObjectTypeDB::bind_method(_MD("_line_edit_input"),&SpinBox::_line_edit_input);
+ ObjectTypeDB::bind_method(_MD("_range_click_timeout"),&SpinBox::_range_click_timeout);
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"editable"),_SCS("set_editable"),_SCS("is_editable"));
@@ -248,4 +274,8 @@ SpinBox::SpinBox() {
line_edit->connect("focus_exit",this,"_line_edit_focus_exit",Vector<Variant>(),CONNECT_DEFERRED);
line_edit->connect("input_event",this,"_line_edit_input");
drag.enabled=false;
+
+ range_click_timer = memnew( Timer );
+ range_click_timer->connect("timeout",this,"_range_click_timeout");
+ add_child(range_click_timer);
}
diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h
index 4c8cb8432a..acaea822ab 100644
--- a/scene/gui/spin_box.h
+++ b/scene/gui/spin_box.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,6 +31,7 @@
#include "scene/gui/line_edit.h"
#include "scene/gui/range.h"
+#include "scene/main/timer.h"
class SpinBox : public Range {
@@ -39,6 +40,9 @@ class SpinBox : public Range {
LineEdit *line_edit;
int last_w;
+ Timer *range_click_timer;
+ void _range_click_timeout();
+
void _text_entered(const String& p_string);
virtual void _value_changed(double);
String prefix;
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index 49067bb3a0..d22f6a0229 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -109,7 +109,7 @@ void SplitContainer::_resort() {
int sep=get_constant("separation");
Ref<Texture> g = get_icon("grabber");
- if (collapsed || !dragger_visible) {
+ if (dragger_visibility==DRAGGER_HIDDEN_COLLAPSED) {
sep=0;
} else {
sep=MAX(sep,vertical?g->get_height():g->get_width());
@@ -221,7 +221,7 @@ Size2 SplitContainer::get_minimum_size() const {
Size2i minimum;
int sep=get_constant("separation");
Ref<Texture> g = get_icon("grabber");
- sep=dragger_visible?MAX(sep,vertical?g->get_height():g->get_width()):0;
+ sep=(dragger_visibility!=DRAGGER_HIDDEN_COLLAPSED)?MAX(sep,vertical?g->get_height():g->get_width()):0;
for(int i=0;i<2;i++) {
@@ -278,19 +278,19 @@ void SplitContainer::_notification(int p_what) {
if (collapsed || (!mouse_inside && get_constant("autohide")))
return;
- int sep=dragger_visible?get_constant("separation"):0;
+ int sep=dragger_visibility!=DRAGGER_HIDDEN_COLLAPSED?get_constant("separation"):0;
Ref<Texture> tex = get_icon("grabber");
Size2 size=get_size();
if (vertical) {
//draw_style_box( get_stylebox("bg"), Rect2(0,middle_sep,get_size().width,sep));
- if (dragger_visible)
+ if (dragger_visibility==DRAGGER_VISIBLE)
draw_texture(tex,Point2i((size.x-tex->get_width())/2,middle_sep+(sep-tex->get_height())/2));
} else {
//draw_style_box( get_stylebox("bg"), Rect2(middle_sep,0,sep,get_size().height));
- if (dragger_visible)
+ if (dragger_visibility==DRAGGER_VISIBLE)
draw_texture(tex,Point2i(middle_sep+(sep-tex->get_width())/2,(size.y-tex->get_height())/2));
}
@@ -301,7 +301,7 @@ void SplitContainer::_notification(int p_what) {
void SplitContainer::_input_event(const InputEvent& p_event) {
- if (collapsed || !_getch(0) || !_getch(1) || !dragger_visible)
+ if (collapsed || !_getch(0) || !_getch(1) || dragger_visibility!=DRAGGER_VISIBLE)
return;
if (p_event.type==InputEvent::MOUSE_BUTTON) {
@@ -400,19 +400,19 @@ void SplitContainer::set_collapsed(bool p_collapsed) {
}
-void SplitContainer::set_dragger_visible(bool p_true) {
+void SplitContainer::set_dragger_visibility(DraggerVisibility p_visibility) {
- dragger_visible=p_true;
+ dragger_visibility=p_visibility;
queue_sort();
update();
}
-bool SplitContainer::is_dragger_visible() const{
+SplitContainer::DraggerVisibility SplitContainer::get_dragger_visibility() const {
-
- return dragger_visible;
+ return dragger_visibility;
}
+
bool SplitContainer::is_collapsed() const {
@@ -429,15 +429,18 @@ void SplitContainer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_collapsed","collapsed"),&SplitContainer::set_collapsed);
ObjectTypeDB::bind_method(_MD("is_collapsed"),&SplitContainer::is_collapsed);
- ObjectTypeDB::bind_method(_MD("set_dragger_visible","visible"),&SplitContainer::set_dragger_visible);
- ObjectTypeDB::bind_method(_MD("is_dragger_visible"),&SplitContainer::is_dragger_visible);
+ ObjectTypeDB::bind_method(_MD("set_dragger_visibility","mode"),&SplitContainer::set_dragger_visibility);
+ ObjectTypeDB::bind_method(_MD("get_dragger_visibility"),&SplitContainer::get_dragger_visibility);
ADD_SIGNAL( MethodInfo("dragged",PropertyInfo(Variant::INT,"offset")));
ADD_PROPERTY( PropertyInfo(Variant::INT,"split/offset"),_SCS("set_split_offset"),_SCS("get_split_offset"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"split/collapsed"),_SCS("set_collapsed"),_SCS("is_collapsed"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"split/dragger_visible"),_SCS("set_dragger_visible"),_SCS("is_dragger_visible"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"split/dragger_visibility",PROPERTY_HINT_ENUM,"Visible,Hidden,Hidden & Collapsed"),_SCS("set_dragger_visibility"),_SCS("get_dragger_visibility"));
+ BIND_CONSTANT( DRAGGER_VISIBLE );
+ BIND_CONSTANT( DRAGGER_HIDDEN );
+ BIND_CONSTANT( DRAGGER_HIDDEN_COLLAPSED );
}
@@ -450,7 +453,8 @@ SplitContainer::SplitContainer(bool p_vertical) {
vertical=p_vertical;
dragging=false;
collapsed=false;
- dragger_visible=true;
+ dragger_visibility=DRAGGER_VISIBLE;
+
}
diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h
index d7f56c6fb4..f721d16310 100644
--- a/scene/gui/split_container.h
+++ b/scene/gui/split_container.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,7 +35,13 @@
class SplitContainer : public Container {
OBJ_TYPE(SplitContainer,Container);
-
+public:
+ enum DraggerVisibility {
+ DRAGGER_VISIBLE,
+ DRAGGER_HIDDEN,
+ DRAGGER_HIDDEN_COLLAPSED
+ };
+private:
bool vertical;
int expand_ofs;
int middle_sep;
@@ -43,7 +49,7 @@ class SplitContainer : public Container {
int drag_from;
int drag_ofs;
bool collapsed;
- bool dragger_visible;
+ DraggerVisibility dragger_visibility;
bool mouse_inside;
@@ -66,8 +72,8 @@ public:
void set_collapsed(bool p_collapsed);
bool is_collapsed() const;
- void set_dragger_visible(bool p_true);
- bool is_dragger_visible() const;
+ void set_dragger_visibility(DraggerVisibility p_visibility);
+ DraggerVisibility get_dragger_visibility() const;
virtual CursorShape get_cursor_shape(const Point2& p_pos=Point2i());
@@ -76,6 +82,7 @@ public:
SplitContainer(bool p_vertical=false);
};
+VARIANT_ENUM_CAST(SplitContainer::DraggerVisibility);
class HSplitContainer : public SplitContainer {
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 6fa701340d..91d0fc157e 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h
index 602d248b46..979ce927a0 100644
--- a/scene/gui/tab_container.h
+++ b/scene/gui/tab_container.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index 47a55e0716..ecce71bdbd 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -65,8 +65,8 @@ Size2 Tabs::get_minimum_size() const {
ms.height=MAX(bms.height+tab_bg->get_minimum_size().height,ms.height);
}
- if (tabs[i].close_button.is_valid()) {
- Ref<Texture> cb=tabs[i].close_button;
+ if (cb_displaypolicy==CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy==CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i==current)) {
+ Ref<Texture> cb=get_icon("close");
Size2 bms = cb->get_size();//+get_stylebox("button")->get_minimum_size();
bms.width+=get_constant("hseparation");
ms.width+=bms.width;
@@ -74,6 +74,7 @@ Size2 Tabs::get_minimum_size() const {
}
}
+ ms.width=0; //should make this optional
return ms;
}
@@ -85,19 +86,28 @@ void Tabs::_input_event(const InputEvent& p_event) {
Point2 pos( p_event.mouse_motion.x, p_event.mouse_motion.y );
+ hilite_arrow=-1;
+ if (buttons_visible) {
+
+ Ref<Texture> incr = get_icon("increment");
+ Ref<Texture> decr = get_icon("decrement");
+
+ int limit=get_size().width-incr->get_width()-decr->get_width();
+
+ if (pos.x>limit+decr->get_width()) {
+ hilite_arrow=1;
+ } else if (pos.x>limit) {
+ hilite_arrow=0;
+ }
+ }
+
+
+
int hover_buttons=-1;
hover=-1;
for(int i=0;i<tabs.size();i++) {
// test hovering tab to display close button if policy says so
- if (cb_displaypolicy == SHOW_HOVER) {
- int ofs=tabs[i].ofs_cache;
- int size = tabs[i].ofs_cache;
- if (pos.x >=tabs[i].ofs_cache && pos.x<tabs[i].ofs_cache+tabs[i].size_cache) {
- hover=i;
- }
- }
-
// test hovering right button and close button
if (tabs[i].rb_rect.has_point(pos)) {
@@ -163,9 +173,34 @@ void Tabs::_input_event(const InputEvent& p_event) {
// clicks
Point2 pos( p_event.mouse_button.x, p_event.mouse_button.y );
+ if (buttons_visible) {
+
+ Ref<Texture> incr = get_icon("increment");
+ Ref<Texture> decr = get_icon("decrement");
+
+ int limit=get_size().width-incr->get_width()-decr->get_width();
+
+ if (pos.x>limit+decr->get_width()) {
+ if (missing_right) {
+ offset++;
+ update();
+ }
+ return;
+ } else if (pos.x>limit) {
+ if (offset>0) {
+ offset--;
+ update();
+ }
+ return;
+ }
+ }
+
+
int found=-1;
for(int i=0;i<tabs.size();i++) {
+ if (i<offset)
+ continue;
if (tabs[i].rb_rect.has_point(pos)) {
rb_pressing=true;
update();
@@ -208,6 +243,10 @@ void Tabs::_notification(int p_what) {
hover=-1;
update();
} break;
+ case NOTIFICATION_RESIZED: {
+
+ _ensure_no_over_offset();
+ } break;
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
@@ -217,15 +256,36 @@ void Tabs::_notification(int p_what) {
Ref<Font> font = get_font("font");
Color color_fg = get_color("font_color_fg");
Color color_bg = get_color("font_color_bg");
+ Ref<Texture> close=get_icon("close");
int h = get_size().height;
int label_valign_fg = get_constant("label_valign_fg");
int label_valign_bg = get_constant("label_valign_bg");
+
int w=0;
- int mw = get_minimum_size().width;
+ int mw = 0;
+
+ {
+
+
+ // h+=MIN( get_constant("label_valign_fg"), get_constant("label_valign_bg") );
+
+ for(int i=0;i<tabs.size();i++) {
+
+ int sz = get_tab_width(i);
+
+ tabs[i].ofs_cache=mw;
+ mw+=sz;
+
+
+ }
+
+ }
+
+
if (tab_align==ALIGN_CENTER) {
w=(get_size().width-mw)/2;
@@ -238,8 +298,19 @@ void Tabs::_notification(int p_what) {
w=0;
}
+ Ref<Texture> incr = get_icon("increment");
+ Ref<Texture> decr = get_icon("decrement");
+ Ref<Texture> incr_hl = get_icon("increment_hilite");
+ Ref<Texture> decr_hl = get_icon("decrement_hilite");
+
+ int limit=get_size().width - incr->get_size().width - decr->get_size().width;
+
+ missing_right=false;
+
for(int i=0;i<tabs.size();i++) {
+ if (i<offset)
+ continue;
tabs[i].ofs_cache=w;
String s = tabs[i].text;
@@ -247,6 +318,8 @@ void Tabs::_notification(int p_what) {
int slen=font->get_string_size(s).width;
lsize+=slen;
+
+
Ref<Texture> icon;
if (tabs[i].icon.is_valid()) {
icon = tabs[i].icon;
@@ -269,56 +342,25 @@ void Tabs::_notification(int p_what) {
}
- // Close button
- switch (cb_displaypolicy) {
- case SHOW_ALWAYS: {
- if (tabs[i].close_button.is_valid()) {
- Ref<StyleBox> style = get_stylebox("button");
- Ref<Texture> rb=tabs[i].close_button;
-
- lsize+=get_constant("hseparation");
- //lsize+=style->get_margin(MARGIN_LEFT);
- lsize+=rb->get_width();
- //lsize+=style->get_margin(MARGIN_RIGHT);
- }
- } break;
- case SHOW_ACTIVE_ONLY: {
- if (i==current) {
- if (tabs[i].close_button.is_valid()) {
- Ref<StyleBox> style = get_stylebox("button");
- Ref<Texture> rb=tabs[i].close_button;
-
- lsize+=get_constant("hseparation");
- //lsize+=style->get_margin(MARGIN_LEFT);
- lsize+=rb->get_width();
- //lsize+=style->get_margin(MARGIN_RIGHT);
-
- }
- }
- } break;
- case SHOW_HOVER: {
- if (i==current || i==hover) {
- if (tabs[i].close_button.is_valid()) {
- Ref<StyleBox> style = get_stylebox("button");
- Ref<Texture> rb=tabs[i].close_button;
+ if (cb_displaypolicy==CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy==CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i==current)) {
- lsize+=get_constant("hseparation");
- //lsize+=style->get_margin(MARGIN_LEFT);
- lsize+=rb->get_width();
- //lsize+=style->get_margin(MARGIN_RIGHT);
-
- }
- }
- } break;
- case SHOW_NEVER: // by default, never show close button
- default: {
- // do nothing
- } break;
+ lsize+=get_constant("hseparation");
+ //lsize+=style->get_margin(MARGIN_LEFT);
+ lsize+=close->get_width();
+ //lsize+=style->get_margin(MARGIN_RIGHT);
+ }
+ if (w+lsize > limit) {
+ max_drawn_tab=i-1;
+ missing_right=true;
+ break;
+ } else {
+ max_drawn_tab=i;
}
+
Ref<StyleBox> sb;
int va;
Color col;
@@ -382,100 +424,31 @@ void Tabs::_notification(int p_what) {
}
+ if (cb_displaypolicy==CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy==CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i==current)) {
+ Ref<StyleBox> style = get_stylebox("button");
+ Ref<Texture> cb=close;
- // Close button
- switch (cb_displaypolicy) {
- case SHOW_ALWAYS: {
- if (tabs[i].close_button.is_valid()) {
- Ref<StyleBox> style = get_stylebox("button");
- Ref<Texture> cb=tabs[i].close_button;
-
- w+=get_constant("hseparation");
-
- Rect2 cb_rect;
- cb_rect.size=style->get_minimum_size()+cb->get_size();
- cb_rect.pos.x=w;
- cb_rect.pos.y=sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-(cb_rect.size.y))/2;
-
- if (cb_hover==i) {
- if (cb_pressing)
- get_stylebox("button_pressed")->draw(ci,cb_rect);
- else
- style->draw(ci,cb_rect);
- }
+ w+=get_constant("hseparation");
- //w+=style->get_margin(MARGIN_LEFT);
+ Rect2 cb_rect;
+ cb_rect.size=style->get_minimum_size()+cb->get_size();
+ cb_rect.pos.x=w;
+ cb_rect.pos.y=sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-(cb_rect.size.y))/2;
- cb->draw(ci,Point2i( w,cb_rect.pos.y+style->get_margin(MARGIN_TOP) ));
- w+=cb->get_width();
- //w+=style->get_margin(MARGIN_RIGHT);
- tabs[i].cb_rect=cb_rect;
- }
- } break;
- case SHOW_ACTIVE_ONLY: {
- if (current==i) {
- if (tabs[i].close_button.is_valid()) {
- Ref<StyleBox> style = get_stylebox("button");
- Ref<Texture> cb=tabs[i].close_button;
-
- w+=get_constant("hseparation");
-
- Rect2 cb_rect;
- cb_rect.size=style->get_minimum_size()+cb->get_size();
- cb_rect.pos.x=w;
- cb_rect.pos.y=sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-(cb_rect.size.y))/2;
-
- if (cb_hover==i) {
- if (cb_pressing)
- get_stylebox("button_pressed")->draw(ci,cb_rect);
- else
- style->draw(ci,cb_rect);
- }
-
- //w+=style->get_margin(MARGIN_LEFT);
-
- cb->draw(ci,Point2i( w,cb_rect.pos.y+style->get_margin(MARGIN_TOP) ));
- w+=cb->get_width();
- //w+=style->get_margin(MARGIN_RIGHT);
- tabs[i].cb_rect=cb_rect;
- }
- }
- } break;
- case SHOW_HOVER: {
- if (current==i || hover==i) {
- if (tabs[i].close_button.is_valid()) {
- Ref<StyleBox> style = get_stylebox("button");
- Ref<Texture> cb=tabs[i].close_button;
-
- w+=get_constant("hseparation");
-
- Rect2 cb_rect;
- cb_rect.size=style->get_minimum_size()+cb->get_size();
- cb_rect.pos.x=w;
- cb_rect.pos.y=sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-(cb_rect.size.y))/2;
-
- if (cb_hover==i) {
- if (cb_pressing)
- get_stylebox("button_pressed")->draw(ci,cb_rect);
- else
- style->draw(ci,cb_rect);
- }
-
- //w+=style->get_margin(MARGIN_LEFT);
-
- cb->draw(ci,Point2i( w,cb_rect.pos.y+style->get_margin(MARGIN_TOP) ));
- w+=cb->get_width();
- //w+=style->get_margin(MARGIN_RIGHT);
- tabs[i].cb_rect=cb_rect;
- }
+ if (cb_hover==i) {
+ if (cb_pressing)
+ get_stylebox("button_pressed")->draw(ci,cb_rect);
+ else
+ style->draw(ci,cb_rect);
}
- } break;
- case SHOW_NEVER:
- default: {
- // show nothing
- } break;
+ //w+=style->get_margin(MARGIN_LEFT);
+
+ cb->draw(ci,Point2i( w,cb_rect.pos.y+style->get_margin(MARGIN_TOP) ));
+ w+=cb->get_width();
+ //w+=style->get_margin(MARGIN_RIGHT);
+ tabs[i].cb_rect=cb_rect;
}
w+=sb->get_margin(MARGIN_RIGHT);
@@ -484,6 +457,25 @@ void Tabs::_notification(int p_what) {
}
+ if (offset>0 || missing_right) {
+
+ int vofs = (get_size().height-incr->get_size().height)/2;
+
+ if (offset>0)
+ draw_texture(hilite_arrow==0?decr_hl:decr,Point2(limit,vofs));
+ else
+ draw_texture(decr,Point2(limit,vofs),Color(1,1,1,0.5));
+
+ if (missing_right)
+ draw_texture(hilite_arrow==1?incr_hl:incr,Point2(limit+decr->get_size().width,vofs));
+ else
+ draw_texture(incr,Point2(limit+decr->get_size().width,vofs),Color(1,1,1,0.5));
+
+ buttons_visible=true;
+ } else {
+ buttons_visible=false;
+ }
+
} break;
}
@@ -563,20 +555,6 @@ Ref<Texture> Tabs::get_tab_right_button(int p_tab) const{
}
-void Tabs::set_tab_close_button(int p_tab, const Ref<Texture>& p_close_button) {
- ERR_FAIL_INDEX(p_tab, tabs.size());
- tabs[p_tab].close_button=p_close_button;
- update();
- minimum_size_changed();
-}
-
-
-Ref<Texture> Tabs::get_tab_close_button(int p_tab) const{
-
- ERR_FAIL_INDEX_V(p_tab,tabs.size(),Ref<Texture>());
- return tabs[p_tab].close_button;
-
-}
void Tabs::add_tab(const String& p_str,const Ref<Texture>& p_icon) {
@@ -584,8 +562,6 @@ void Tabs::add_tab(const String& p_str,const Ref<Texture>& p_icon) {
t.text=p_str;
t.icon=p_icon;
- t.close_button = get_icon("Close","EditorIcons");
-
tabs.push_back(t);
update();
@@ -615,10 +591,8 @@ void Tabs::remove_tab(int p_idx) {
//emit_signal("tab_changed",current);
-}
+ _ensure_no_over_offset();
-void Tabs::set_tab_close_display_policy(CloseButtonDisplayPolicy p_cb_displaypolicy) {
- cb_displaypolicy = p_cb_displaypolicy;
}
@@ -633,6 +607,129 @@ Tabs::TabAlign Tabs::get_tab_align() const {
return tab_align;
}
+int Tabs::get_tab_width(int p_idx) const {
+
+ ERR_FAIL_INDEX_V(p_idx,tabs.size(),0);
+
+ Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
+ Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
+ Ref<Font> font = get_font("font");
+ Ref<Texture> close=get_icon("close");
+
+ int x=0;
+
+ Ref<Texture> tex = tabs[p_idx].icon;
+ if (tex.is_valid()) {
+ if (tabs[p_idx].text!="")
+ x+=get_constant("hseparation");
+
+ }
+
+
+ x+=font->get_string_size(tabs[p_idx].text).width;
+ if (current==p_idx)
+ x+=tab_fg->get_minimum_size().width;
+ else
+ x+=tab_bg->get_minimum_size().width;
+
+ if (tabs[p_idx].right_button.is_valid()) {
+ print_line("has right");
+ Ref<Texture> rb=tabs[p_idx].right_button;
+ Size2 bms = rb->get_size();//+get_stylebox("button")->get_minimum_size();
+ bms.width+=get_constant("hseparation");
+
+ x+=bms.width;
+ }
+
+ if (cb_displaypolicy==CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy==CLOSE_BUTTON_SHOW_ACTIVE_ONLY && p_idx==current)) {
+
+ Size2 bms = close->get_size();//+get_stylebox("button")->get_minimum_size();
+ bms.width+=get_constant("hseparation");
+ x+=bms.width;
+ }
+
+ return x;
+}
+
+
+void Tabs::_ensure_no_over_offset() {
+
+ if (!is_inside_tree())
+ return;
+
+ Ref<Texture> incr = get_icon("increment");
+ Ref<Texture> decr = get_icon("decrement");
+
+ int limit=get_size().width-incr->get_width()-decr->get_width();
+
+ while(offset>0) {
+
+ int total_w=0;
+ for(int i=0;i<tabs.size();i++) {
+
+ if (i<offset-1)
+ continue;
+
+ total_w+=get_tab_width(i);
+ }
+
+ if (total_w < limit) {
+ offset--;
+ update();
+ } else {
+ break;
+ }
+ }
+
+}
+
+
+void Tabs::ensure_tab_visible(int p_idx) {
+
+ if (!is_inside_tree())
+ return;
+
+ ERR_FAIL_INDEX(p_idx,tabs.size());
+
+ _ensure_no_over_offset();
+
+ if (p_idx<=offset) {
+ offset=p_idx;
+ update();
+ return;
+ }
+
+ Ref<Texture> incr = get_icon("increment");
+ Ref<Texture> decr = get_icon("decrement");
+
+ int limit=get_size().width-incr->get_width()-decr->get_width();
+
+
+
+ int x=0;
+ for(int i=0;i<tabs.size();i++) {
+
+ if (i<offset)
+ continue;
+
+ int sz = get_tab_width(i);
+ tabs[i].x_cache=x;
+ tabs[i].x_size_cache=sz;
+ x+=sz;
+
+ }
+
+ while(offset<tabs.size() && ( (tabs[p_idx].x_cache + tabs[p_idx].x_size_cache) - tabs[offset].x_cache) > limit) {
+ offset++;
+ }
+
+ update();
+}
+
+void Tabs::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) {
+ cb_displaypolicy=p_policy;
+ update();
+}
void Tabs::_bind_methods() {
@@ -648,6 +745,7 @@ void Tabs::_bind_methods() {
ObjectTypeDB::bind_method(_MD("add_tab","title","icon:Texture"),&Tabs::add_tab);
ObjectTypeDB::bind_method(_MD("set_tab_align","align"),&Tabs::set_tab_align);
ObjectTypeDB::bind_method(_MD("get_tab_align"),&Tabs::get_tab_align);
+ ObjectTypeDB::bind_method(_MD("ensure_tab_visible","idx"),&Tabs::ensure_tab_visible);
ADD_SIGNAL(MethodInfo("tab_changed",PropertyInfo(Variant::INT,"tab")));
ADD_SIGNAL(MethodInfo("right_button_pressed",PropertyInfo(Variant::INT,"tab")));
@@ -660,10 +758,10 @@ void Tabs::_bind_methods() {
BIND_CONSTANT( ALIGN_CENTER );
BIND_CONSTANT( ALIGN_RIGHT );
- BIND_CONSTANT( SHOW_ACTIVE_ONLY );
- BIND_CONSTANT( SHOW_ALWAYS );
- BIND_CONSTANT( SHOW_HOVER );
- BIND_CONSTANT( SHOW_NEVER );
+ BIND_CONSTANT( CLOSE_BUTTON_SHOW_ACTIVE_ONLY );
+ BIND_CONSTANT( CLOSE_BUTTON_SHOW_ALWAYS );
+ BIND_CONSTANT( CLOSE_BUTTON_SHOW_NEVER );
+
}
@@ -673,8 +771,13 @@ Tabs::Tabs() {
tab_align=ALIGN_CENTER;
rb_hover=-1;
rb_pressing=false;
+ hilite_arrow=-1;
cb_hover=-1;
cb_pressing=false;
- cb_displaypolicy = SHOW_NEVER; // Default : no close button
+ cb_displaypolicy = CLOSE_BUTTON_SHOW_NEVER; // Default : no close button
+ offset=0;
+ max_drawn_tab=0;
+
+
}
diff --git a/scene/gui/tabs.h b/scene/gui/tabs.h
index 1a8352bc93..5a4533c3d2 100644
--- a/scene/gui/tabs.h
+++ b/scene/gui/tabs.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -45,10 +45,9 @@ public:
enum CloseButtonDisplayPolicy {
- SHOW_ALWAYS,
- SHOW_ACTIVE_ONLY,
- SHOW_HOVER,
- SHOW_NEVER
+ CLOSE_BUTTON_SHOW_NEVER,
+ CLOSE_BUTTON_SHOW_ACTIVE_ONLY,
+ CLOSE_BUTTON_SHOW_ALWAYS,
};
private:
@@ -59,12 +58,21 @@ private:
Ref<Texture> icon;
int ofs_cache;
int size_cache;
+ int x_cache;
+ int x_size_cache;
+
Ref<Texture> right_button;
Rect2 rb_rect;
- Ref<Texture> close_button;
Rect2 cb_rect;
+
};
+
+ int offset;
+ int max_drawn_tab;
+ int hilite_arrow;
+ bool buttons_visible;
+ bool missing_right;
Vector<Tab> tabs;
int current;
Control *_get_tab(int idx) const;
@@ -79,6 +87,9 @@ private:
int hover; // hovered tab
+ int get_tab_width(int p_idx) const;
+ void _ensure_no_over_offset();
+
protected:
void _input_event(const InputEvent& p_event);
@@ -98,13 +109,11 @@ public:
void set_tab_right_button(int p_tab,const Ref<Texture>& p_right_button);
Ref<Texture> get_tab_right_button(int p_tab) const;
- void set_tab_close_button(int p_tab, const Ref<Texture>& p_close_button);
- Ref<Texture> get_tab_close_button(int p_tab) const;
- void set_tab_close_display_policy(CloseButtonDisplayPolicy p_cb_displaypolicy);
-
void set_tab_align(TabAlign p_align);
TabAlign get_tab_align() const;
+ void set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy);
+
int get_tab_count() const;
void set_current_tab(int p_current);
int get_current_tab() const;
@@ -113,6 +122,8 @@ public:
void clear_tabs();
+ void ensure_tab_visible(int p_idx);
+
Size2 get_minimum_size() const;
Tabs();
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 78792dc785..7f7c8c023c 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,6 +29,7 @@
#include "text_edit.h"
#include "os/keyboard.h"
+#include "os/input.h"
#include "os/os.h"
#include "globals.h"
@@ -349,6 +350,29 @@ void TextEdit::_update_scrollbars() {
updating_scrolls=false;
}
+void TextEdit::_click_selection_held() {
+
+ if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && selection.selecting_mode!=Selection::MODE_NONE) {
+
+ Point2 mp = Input::get_singleton()->get_mouse_pos()-get_global_pos();
+
+ int row,col;
+ _get_mouse_pos(Point2i(mp.x,mp.y), row,col);
+
+ select(selection.selecting_line,selection.selecting_column,row,col);
+
+ cursor_set_line( row );
+ cursor_set_column( col );
+ update();
+
+ click_select_held->start();
+
+ } else {
+
+ click_select_held->stop();
+ }
+}
+
void TextEdit::_notification(int p_what) {
@@ -815,7 +839,7 @@ void TextEdit::_notification(int p_what) {
}
- if (cursor.column==str.length() && cursor.line==line) {
+ if (cursor.column==str.length() && cursor.line==line && (char_ofs+char_margin)>=xmargin_beg) {
cursor_pos=Point2i( char_ofs+char_margin, ofs_y );
VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.font_color);
@@ -1292,6 +1316,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
update();
}
} else {
+
+ if (mb.button_index==BUTTON_LEFT)
+ click_select_held->stop();
// notify to show soft keyboard
notification(NOTIFICATION_FOCUS_ENTER);
@@ -1304,16 +1331,18 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
if (mm.button_mask&BUTTON_MASK_LEFT) {
- int row,col;
- _get_mouse_pos(Point2i(mm.x,mm.y), row,col);
-
if (selection.selecting_mode!=Selection::MODE_NONE) {
+
+ int row,col;
+ _get_mouse_pos(Point2i(mm.x,mm.y), row,col);
select(selection.selecting_line,selection.selecting_column,row,col);
cursor_set_line( row );
cursor_set_column( col );
update();
+
+ click_select_held->start();
}
@@ -1711,6 +1740,13 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
}
} break;
+ case KEY_KP_4: {
+ if (k.unicode != 0) {
+ scancode_handled = false;
+ break;
+ }
+ // numlock disabled. fallthrough to key_left
+ }
case KEY_LEFT: {
if (k.mod.shift)
@@ -1757,6 +1793,13 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
_post_shift_selection();
} break;
+ case KEY_KP_6: {
+ if (k.unicode != 0) {
+ scancode_handled = false;
+ break;
+ }
+ // numlock disabled. fallthrough to key_right
+ }
case KEY_RIGHT: {
if (k.mod.shift)
@@ -1800,6 +1843,13 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
_post_shift_selection();
} break;
+ case KEY_KP_8: {
+ if (k.unicode != 0) {
+ scancode_handled = false;
+ break;
+ }
+ // numlock disabled. fallthrough to key_up
+ }
case KEY_UP: {
if (k.mod.shift)
@@ -1820,6 +1870,13 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
_cancel_code_hint();
} break;
+ case KEY_KP_2: {
+ if (k.unicode != 0) {
+ scancode_handled = false;
+ break;
+ }
+ // numlock disabled. fallthrough to key_down
+ }
case KEY_DOWN: {
if (k.mod.shift)
@@ -1908,6 +1965,13 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
update();
} break;
+ case KEY_KP_7: {
+ if (k.unicode != 0) {
+ scancode_handled = false;
+ break;
+ }
+ // numlock disabled. fallthrough to key_home
+ }
#ifdef APPLE_STYLE_KEYS
case KEY_HOME: {
@@ -1921,18 +1985,6 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
_post_shift_selection();
} break;
- case KEY_END: {
-
- if (k.mod.shift)
- _pre_shift_selection();
-
- cursor_set_line(text.size()-1);
-
- if (k.mod.shift)
- _post_shift_selection();
-
- } break;
-
#else
case KEY_HOME: {
@@ -1963,6 +2015,27 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
completion_hint="";
} break;
+#endif
+ case KEY_KP_1: {
+ if (k.unicode != 0) {
+ scancode_handled = false;
+ break;
+ }
+ // numlock disabled. fallthrough to key_end
+ }
+#ifdef APPLE_STYLE_KEYS
+ case KEY_END: {
+
+ if (k.mod.shift)
+ _pre_shift_selection();
+
+ cursor_set_line(text.size()-1);
+
+ if (k.mod.shift)
+ _post_shift_selection();
+
+ } break;
+#else
case KEY_END: {
if (k.mod.shift)
@@ -1980,6 +2053,13 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
} break;
#endif
+ case KEY_KP_9: {
+ if (k.unicode != 0) {
+ scancode_handled = false;
+ break;
+ }
+ // numlock disabled. fallthrough to key_pageup
+ }
case KEY_PAGEUP: {
if (k.mod.shift)
@@ -1995,6 +2075,13 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
} break;
+ case KEY_KP_3: {
+ if (k.unicode != 0) {
+ scancode_handled = false;
+ break;
+ }
+ // numlock disabled. fallthrough to key_pageup
+ }
case KEY_PAGEDOWN: {
if (k.mod.shift)
@@ -3697,6 +3784,7 @@ void TextEdit::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_cursor_changed_emit"),&TextEdit::_cursor_changed_emit);
ObjectTypeDB::bind_method(_MD("_text_changed_emit"),&TextEdit::_text_changed_emit);
ObjectTypeDB::bind_method(_MD("_push_current_op"),&TextEdit::_push_current_op);
+ ObjectTypeDB::bind_method(_MD("_click_selection_held"),&TextEdit::_click_selection_held);
BIND_CONSTANT( SEARCH_MATCH_CASE );
BIND_CONSTANT( SEARCH_WHOLE_WORDS );
@@ -3712,10 +3800,10 @@ void TextEdit::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_line_count"),&TextEdit::get_line_count);
ObjectTypeDB::bind_method(_MD("get_text"),&TextEdit::get_text);
- ObjectTypeDB::bind_method(_MD("get_line"),&TextEdit::get_line);
+ ObjectTypeDB::bind_method(_MD("get_line","line"),&TextEdit::get_line);
- ObjectTypeDB::bind_method(_MD("cursor_set_column","column"),&TextEdit::cursor_set_column);
- ObjectTypeDB::bind_method(_MD("cursor_set_line","line"),&TextEdit::cursor_set_line);
+ ObjectTypeDB::bind_method(_MD("cursor_set_column","column","adjust_viewport"),&TextEdit::cursor_set_column,DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("cursor_set_line","line","adjust_viewport"),&TextEdit::cursor_set_line,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("cursor_get_column"),&TextEdit::cursor_get_column);
ObjectTypeDB::bind_method(_MD("cursor_get_line"),&TextEdit::cursor_get_line);
@@ -3811,6 +3899,11 @@ TextEdit::TextEdit() {
idle_detect->set_one_shot(true);
idle_detect->set_wait_time(GLOBAL_DEF("display/text_edit_idle_detect_sec",3));
idle_detect->connect("timeout", this,"_push_current_op");
+
+ click_select_held = memnew( Timer );
+ add_child(click_select_held);
+ click_select_held->set_wait_time(0.05);
+ click_select_held->connect("timeout", this,"_click_selection_held");
#if 0
syntax_coloring=true;
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 91369309cf..2ca5ab054a 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -219,6 +219,7 @@ class TextEdit : public Control {
uint64_t last_dblclk;
Timer *idle_detect;
+ Timer *click_select_held;
HScrollBar *h_scroll;
VScrollBar *v_scroll;
bool updating_scrolls;
@@ -240,6 +241,7 @@ class TextEdit : public Control {
void adjust_viewport_to_cursor();
void _scroll_moved(double);
void _update_scrollbars();
+ void _click_selection_held();
void _pre_shift_selection();
void _post_shift_selection();
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index 5b2caecb5b..c885b2d73e 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,22 +42,22 @@ Size2 TextureButton::get_minimum_size() const {
else
rscale= hover->get_size();
} else
- rscale= pressed->get_size()*scale;
+ rscale=pressed->get_size();
} else
rscale= normal->get_size();
- return rscale*scale;
+ return rscale*scale.abs();
}
bool TextureButton::has_point(const Point2& p_point) const {
- if (scale[0] <= 0 || scale[1] <= 0) {
+ if (scale[0] == 0 || scale[1] == 0) {
return false;
}
- Point2 ppos = p_point/scale;
+ Point2 ppos = p_point/scale.abs();
if (click_mask.is_valid()) {
@@ -145,7 +145,7 @@ void TextureButton::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_disabled_texture","texture:Texture"),&TextureButton::set_disabled_texture);
ObjectTypeDB::bind_method(_MD("set_focused_texture","texture:Texture"),&TextureButton::set_focused_texture);
ObjectTypeDB::bind_method(_MD("set_click_mask","mask:BitMap"),&TextureButton::set_click_mask);
- ObjectTypeDB::bind_method(_MD("set_scale","scale"),&TextureButton::set_scale);
+ ObjectTypeDB::bind_method(_MD("set_texture_scale","scale"),&TextureButton::set_texture_scale);
ObjectTypeDB::bind_method(_MD("set_modulate","color"),&TextureButton::set_modulate);
ObjectTypeDB::bind_method(_MD("get_normal_texture:Texture"),&TextureButton::get_normal_texture);
@@ -154,7 +154,7 @@ void TextureButton::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_disabled_texture:Texture"),&TextureButton::get_disabled_texture);
ObjectTypeDB::bind_method(_MD("get_focused_texture:Texture"),&TextureButton::get_focused_texture);
ObjectTypeDB::bind_method(_MD("get_click_mask:BitMap"),&TextureButton::get_click_mask);
- ObjectTypeDB::bind_method(_MD("get_scale"),&TextureButton::get_scale);
+ ObjectTypeDB::bind_method(_MD("get_texture_scale"),&TextureButton::get_texture_scale);
ObjectTypeDB::bind_method(_MD("get_modulate"),&TextureButton::get_modulate);
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"textures/normal",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_normal_texture"), _SCS("get_normal_texture"));
@@ -163,7 +163,7 @@ void TextureButton::_bind_methods() {
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"textures/disabled",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_disabled_texture"), _SCS("get_disabled_texture"));
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"textures/focused",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_focused_texture"), _SCS("get_focused_texture"));
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"textures/click_mask",PROPERTY_HINT_RESOURCE_TYPE,"BitMap"), _SCS("set_click_mask"), _SCS("get_click_mask")) ;
- ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2,"params/scale",PROPERTY_HINT_RANGE,"0.01,1024,0.01"), _SCS("set_scale"), _SCS("get_scale"));
+ ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2,"params/scale",PROPERTY_HINT_RANGE,"0.01,1024,0.01"), _SCS("set_texture_scale"), _SCS("get_texture_scale"));
ADD_PROPERTYNO(PropertyInfo(Variant::COLOR,"params/modulate"), _SCS("set_modulate"), _SCS("get_modulate"));
}
@@ -232,14 +232,14 @@ void TextureButton::set_focused_texture(const Ref<Texture>& p_focused) {
focused = p_focused;
};
-void TextureButton::set_scale(Size2 p_scale) {
+void TextureButton::set_texture_scale(Size2 p_scale) {
scale=p_scale;
minimum_size_changed();
update();
}
-Size2 TextureButton::get_scale() const{
+Size2 TextureButton::get_texture_scale() const{
return scale;
}
diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h
index 01924c1c15..0556df8061 100644
--- a/scene/gui/texture_button.h
+++ b/scene/gui/texture_button.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -68,8 +68,8 @@ public:
Ref<Texture> get_focused_texture() const;
Ref<BitMap> get_click_mask() const;
- void set_scale(Size2 p_scale);
- Size2 get_scale() const;
+ void set_texture_scale(Size2 p_scale);
+ Size2 get_texture_scale() const;
void set_modulate(const Color& p_modulate);
Color get_modulate() const;
diff --git a/scene/gui/texture_frame.cpp b/scene/gui/texture_frame.cpp
index 5a6bc86638..73fecf591a 100644
--- a/scene/gui/texture_frame.cpp
+++ b/scene/gui/texture_frame.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/texture_frame.h b/scene/gui/texture_frame.h
index 0ccbf5a591..f6fe6ae89d 100644
--- a/scene/gui/texture_frame.h
+++ b/scene/gui/texture_frame.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp
index c8930add6e..e05d35a81d 100644
--- a/scene/gui/texture_progress.cpp
+++ b/scene/gui/texture_progress.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/texture_progress.h b/scene/gui/texture_progress.h
index 7187fd5f07..a4bbd71e94 100644
--- a/scene/gui/texture_progress.h
+++ b/scene/gui/texture_progress.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/tool_button.cpp b/scene/gui/tool_button.cpp
index d5bcb73476..fd27800384 100644
--- a/scene/gui/tool_button.cpp
+++ b/scene/gui/tool_button.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/tool_button.h b/scene/gui/tool_button.h
index 648d776b51..f48d7d413c 100644
--- a/scene/gui/tool_button.h
+++ b/scene/gui/tool_button.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 16a12fe407..e81c08dbea 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -672,7 +672,7 @@ void TreeItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("clear_custom_bg_color","column"),&TreeItem::clear_custom_bg_color);
ObjectTypeDB::bind_method(_MD("get_custom_bg_color","column"),&TreeItem::get_custom_bg_color);
- ObjectTypeDB::bind_method(_MD("add_button","column","button:Texture"),&TreeItem::add_button);
+ ObjectTypeDB::bind_method(_MD("add_button","column","button:Texture","button_idx"),&TreeItem::add_button);
ObjectTypeDB::bind_method(_MD("get_button_count","column"),&TreeItem::get_button_count);
ObjectTypeDB::bind_method(_MD("get_button:Texture","column","button_idx"),&TreeItem::get_button);
ObjectTypeDB::bind_method(_MD("erase_button","column","button_idx"),&TreeItem::erase_button);
@@ -1369,7 +1369,40 @@ Rect2 Tree::search_item_rect(TreeItem *p_from, TreeItem *p_item) {
}
+void Tree::_range_click_timeout() {
+ if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
+
+ Point2 pos = get_local_mouse_pos()-cache.bg->get_offset();
+ if (show_column_titles) {
+ pos.y-=_get_title_button_height();
+
+ if (pos.y<0) {
+ range_click_timer->stop();
+ return;
+ }
+ }
+
+ click_handled=false;
+ InputModifierState mod = InputModifierState(); // should be irrelevant..
+
+ blocked++;
+ propagate_mouse_event(pos+cache.offset, 0, 0, false, root, BUTTON_LEFT, mod);
+ blocked--;
+
+ if (range_click_timer->is_one_shot()) {
+ range_click_timer->set_wait_time(0.05);
+ range_click_timer->set_one_shot(false);
+ range_click_timer->start();
+ }
+
+ if (!click_handled)
+ range_click_timer->stop();
+
+ } else {
+ range_click_timer->stop();
+ }
+}
int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_doubleclick,TreeItem *p_item,int p_button,const InputModifierState& p_mod) {
@@ -1381,6 +1414,10 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
if (!skip && p_pos.y<item_h) {
// check event!
+ if (range_click_timer->get_time_left() > 0 && p_item != range_item_last) {
+ return -1;
+ }
+
if (!hide_folding && (p_pos.x >=x_ofs && p_pos.x < (x_ofs+cache.item_margin) )) {
@@ -1564,9 +1601,25 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
bool up=p_pos.y < (item_h /2);
if (p_button==BUTTON_LEFT) {
+
+ if (range_click_timer->get_time_left() == 0) {
+
+ range_item_last=p_item;
+ range_up_last=up;
+
+ range_click_timer->set_wait_time(0.6);
+ range_click_timer->set_one_shot(true);
+ range_click_timer->start();
+
+ } else if (up != range_up_last) {
+
+ return -1; // break. avoid changing direction on mouse held
+ }
+
p_item->set_range( col, c.val + (up?1.0:-1.0) * c.step );
item_edited(col,p_item);
+
} else if (p_button==BUTTON_RIGHT) {
p_item->set_range( col, (up?c.max:c.min) );
@@ -1668,10 +1721,25 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
}
+void Tree::_text_editor_modal_close() {
+
+ if ( Input::get_singleton()->is_key_pressed(KEY_ESCAPE) ||
+ Input::get_singleton()->is_key_pressed(KEY_ENTER) ||
+ Input::get_singleton()->is_key_pressed(KEY_RETURN) ) {
+
+ return;
+ }
+
+
+ text_editor_enter(text_editor->get_text());
+}
+
+
void Tree::text_editor_enter(String p_text) {
text_editor->hide();
+ value_editor->hide();
if (!popup_edited_item)
return;
@@ -2031,7 +2099,6 @@ void Tree::_input_event(InputEvent p_event) {
Cache::ClickType old_hover = cache.hover_type;
int old_index = cache.hover_index;
-
cache.hover_type=Cache::CLICK_NONE;
cache.hover_index=0;
if (show_column_titles) {
@@ -2077,8 +2144,7 @@ void Tree::_input_event(InputEvent p_event) {
float diff_y = -b.relative_y;
diff_y=Math::pow(ABS(diff_y),1.8)*SGN(diff_y);
diff_y*=0.1;
- range_drag_base=CLAMP(range_drag_base + c.step * diff_y, c.min, c.max);
-
+ range_drag_base=CLAMP(range_drag_base + c.step * diff_y, c.min, c.max);
popup_edited_item->set_range(popup_edited_item_col,range_drag_base);
item_edited(popup_edited_item_col,popup_edited_item);
@@ -2108,6 +2174,8 @@ void Tree::_input_event(InputEvent p_event) {
if (b.button_index==BUTTON_LEFT) {
+ range_click_timer->stop();
+
if (pressing_for_editor) {
if (range_drag_enabled) {
@@ -2115,18 +2183,9 @@ void Tree::_input_event(InputEvent p_event) {
range_drag_enabled=false;
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
warp_mouse(range_drag_capture_pos);
- } else {
- text_editor->set_pos(pressing_item_rect.pos);
- text_editor->set_size(pressing_item_rect.size);
+ } else
+ edit_selected();
- text_editor->clear();
- text_editor->set_text( pressing_for_editor_text );
- text_editor->select_all();
-
- text_editor->show_modal();
- text_editor->grab_focus();
-
- }
pressing_for_editor=false;
}
@@ -2228,6 +2287,7 @@ void Tree::_input_event(InputEvent p_event) {
} break;
case BUTTON_WHEEL_UP: {
+
v_scroll->set_val( v_scroll->get_val()-v_scroll->get_page()/8 );
} break;
case BUTTON_WHEEL_DOWN: {
@@ -3135,9 +3195,11 @@ bool Tree::is_folding_hidden() const {
void Tree::_bind_methods() {
+ ObjectTypeDB::bind_method(_MD("_range_click_timeout"),&Tree::_range_click_timeout);
ObjectTypeDB::bind_method(_MD("_input_event"),&Tree::_input_event);
ObjectTypeDB::bind_method(_MD("_popup_select"),&Tree::popup_select);
ObjectTypeDB::bind_method(_MD("_text_editor_enter"),&Tree::text_editor_enter);
+ ObjectTypeDB::bind_method(_MD("_text_editor_modal_close"),&Tree::_text_editor_modal_close);
ObjectTypeDB::bind_method(_MD("_value_editor_changed"),&Tree::value_editor_changed);
ObjectTypeDB::bind_method(_MD("_scroll_moved"),&Tree::_scroll_moved);
@@ -3145,11 +3207,11 @@ void Tree::_bind_methods() {
ObjectTypeDB::bind_method(_MD("create_item:TreeItem","parent:TreeItem"),&Tree::_create_item,DEFVAL((Object*)NULL));
ObjectTypeDB::bind_method(_MD("get_root:TreeItem"),&Tree::get_root);
- ObjectTypeDB::bind_method(_MD("set_column_min_width"),&Tree::set_column_min_width);
- ObjectTypeDB::bind_method(_MD("set_column_expand"),&Tree::set_column_expand);
- ObjectTypeDB::bind_method(_MD("get_column_width"),&Tree::get_column_width);
+ ObjectTypeDB::bind_method(_MD("set_column_min_width","column","min_width"),&Tree::set_column_min_width);
+ ObjectTypeDB::bind_method(_MD("set_column_expand","column","expand"),&Tree::set_column_expand);
+ ObjectTypeDB::bind_method(_MD("get_column_width","column"),&Tree::get_column_width);
- ObjectTypeDB::bind_method(_MD("set_hide_root"),&Tree::set_hide_root);
+ ObjectTypeDB::bind_method(_MD("set_hide_root","enable"),&Tree::set_hide_root);
ObjectTypeDB::bind_method(_MD("get_next_selected:TreeItem","from:TreeItem"),&Tree::_get_next_selected);
ObjectTypeDB::bind_method(_MD("get_selected:TreeItem"),&Tree::get_selected);
ObjectTypeDB::bind_method(_MD("get_selected_column"),&Tree::get_selected_column);
@@ -3229,9 +3291,14 @@ Tree::Tree() {
add_child(h_scroll);
add_child(v_scroll);
+ range_click_timer = memnew( Timer );
+ range_click_timer->connect("timeout",this,"_range_click_timeout");
+ add_child(range_click_timer);
+
h_scroll->connect("value_changed", this,"_scroll_moved");
v_scroll->connect("value_changed", this,"_scroll_moved");
text_editor->connect("text_entered", this,"_text_editor_enter");
+ text_editor->connect("modal_close", this,"_text_editor_modal_close");
popup_menu->connect("item_pressed", this,"_popup_select");
value_editor->connect("value_changed", this,"_value_editor_changed");
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 8fb9b802a1..e4d349978c 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -127,7 +127,7 @@ friend class Tree;
- TreeItem(Tree *p_tree);
+ TreeItem(Tree *p_tree);
void _changed_notify(int p_cell);
@@ -301,6 +301,11 @@ friend class TreeItem;
Vector<ColumnInfo> columns;
+ Timer *range_click_timer;
+ TreeItem *range_item_last;
+ bool range_up_last;
+ void _range_click_timeout();
+
int compute_item_height(TreeItem *p_item) const;
int get_item_height(TreeItem *p_item) const;
// void draw_item_text(String p_text,const Ref<Texture>& p_icon,int p_icon_max_w,bool p_tool,Rect2i p_rect,const Color& p_color);
@@ -309,6 +314,7 @@ friend class TreeItem;
void select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col,TreeItem *p_prev=NULL,bool *r_in_range=NULL);
int propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_doubleclick,TreeItem *p_item,int p_button,const InputModifierState& p_mod);
void text_editor_enter(String p_text);
+ void _text_editor_modal_close();
void value_editor_changed(double p_value);
void popup_select(int p_option);
diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp
index d99da5e906..517cd414c5 100644
--- a/scene/gui/video_player.cpp
+++ b/scene/gui/video_player.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -117,8 +117,9 @@ void VideoPlayer::_notification(int p_notification) {
case NOTIFICATION_ENTER_TREE: {
//set_idle_process(false); //don't annoy
- if (stream.is_valid() && autoplay && !get_tree()->is_editor_hint())
+ if (stream.is_valid() && autoplay && !get_tree()->is_editor_hint()) {
play();
+ }
} break;
case NOTIFICATION_PROCESS: {
@@ -270,6 +271,7 @@ void VideoPlayer::set_paused(bool p_paused) {
playback->set_paused(p_paused);
set_process(!p_paused);
};
+ last_audio_time = 0;
};
bool VideoPlayer::is_paused() const {
@@ -338,6 +340,13 @@ float VideoPlayer::get_stream_pos() const {
return playback->get_pos();
};
+Ref<Texture> VideoPlayer::get_video_texture() {
+
+ if (playback.is_valid())
+ return playback->get_texture();
+
+ return Ref<Texture> ();
+}
void VideoPlayer::set_autoplay(bool p_enable) {
@@ -384,6 +393,8 @@ void VideoPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_buffering_msec","msec"),&VideoPlayer::set_buffering_msec);
ObjectTypeDB::bind_method(_MD("get_buffering_msec"),&VideoPlayer::get_buffering_msec);
+ ObjectTypeDB::bind_method(_MD("get_video_texutre:Texture"), &VideoPlayer::get_video_texture );
+
ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/audio_track",PROPERTY_HINT_RANGE,"0,128,1"), _SCS("set_audio_track"), _SCS("get_audio_track") );
ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream/stream", PROPERTY_HINT_RESOURCE_TYPE,"VideoStream"), _SCS("set_stream"), _SCS("get_stream") );
// ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/loop"), _SCS("set_loop"), _SCS("has_loop") );
diff --git a/scene/gui/video_player.h b/scene/gui/video_player.h
index c485e3d6b6..9ce1ba78f4 100644
--- a/scene/gui/video_player.h
+++ b/scene/gui/video_player.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -88,6 +88,8 @@ public:
bool has_expand() const;
+ Ref<Texture> get_video_texture();
+
void set_stream(const Ref<VideoStream> &p_stream);
Ref<VideoStream> get_stream() const;
@@ -110,8 +112,8 @@ public:
void set_autoplay(bool p_vol);
bool has_autoplay() const;
- void set_audio_track(int p_track);
- int get_audio_track() const;
+ void set_audio_track(int p_track);
+ int get_audio_track() const;
void set_buffering_msec(int p_msec);
int get_buffering_msec() const;
diff --git a/scene/io/resource_format_image.cpp b/scene/io/resource_format_image.cpp
index f67d50b56c..c80975dbfe 100644
--- a/scene/io/resource_format_image.cpp
+++ b/scene/io/resource_format_image.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/io/resource_format_image.h b/scene/io/resource_format_image.h
index b5ec5a1200..6388aa641f 100644
--- a/scene/io/resource_format_image.h
+++ b/scene/io/resource_format_image.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/io/resource_format_wav.cpp b/scene/io/resource_format_wav.cpp
index 00b800b28b..9cf349eb7b 100644
--- a/scene/io/resource_format_wav.cpp
+++ b/scene/io/resource_format_wav.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/io/resource_format_wav.h b/scene/io/resource_format_wav.h
index a74da041c1..4918d5c2e7 100644
--- a/scene/io/resource_format_wav.h
+++ b/scene/io/resource_format_wav.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index ee3d7f5afd..e921795628 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h
index edd00c1a7a..809b3fae7f 100644
--- a/scene/main/canvas_layer.h
+++ b/scene/main/canvas_layer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/main/instance_placeholder.cpp b/scene/main/instance_placeholder.cpp
index 12f6086bf0..f822107918 100644
--- a/scene/main/instance_placeholder.cpp
+++ b/scene/main/instance_placeholder.cpp
@@ -14,11 +14,24 @@ bool InstancePlaceholder::_set(const StringName& p_name, const Variant& p_value)
bool InstancePlaceholder::_get(const StringName& p_name,Variant &r_ret) const{
+ for (const List<PropSet>::Element *E=stored_values.front();E;E=E->next()) {
+ if (E->get().name==p_name) {
+ r_ret=E->get().value;
+ return true;
+ }
+ }
return false;
}
void InstancePlaceholder::_get_property_list( List<PropertyInfo> *p_list) const{
+ for (const List<PropSet>::Element *E=stored_values.front();E;E=E->next()) {
+ PropertyInfo pi;
+ pi.name=E->get().name;
+ pi.type=E->get().value.get_type();
+ pi.usage=PROPERTY_USAGE_STORAGE;
+ p_list->push_back(pi);
+ }
}
diff --git a/scene/main/misc.cpp b/scene/main/misc.cpp
index 108621baa5..35d8b4cdfb 100644
--- a/scene/main/misc.cpp
+++ b/scene/main/misc.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/main/misc.h b/scene/main/misc.h
index e7894aa68d..1c5bc7208e 100644
--- a/scene/main/misc.h
+++ b/scene/main/misc.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 97c36ff71b..450578a241 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,6 +33,7 @@
#include "scene/resources/packed_scene.h"
#include "io/resource_loader.h"
#include "viewport.h"
+#include "instance_placeholder.h"
VARIANT_ENUM_CAST(Node::PauseMode);
@@ -628,11 +629,11 @@ String Node::validate_child_name(const String& p_name) const {
}
-void Node::_validate_child_name(Node *p_child) {
+void Node::_validate_child_name(Node *p_child, bool p_force_human_readable) {
/* Make sure the name is unique */
- if (node_hrcr) {
+ if (node_hrcr || p_force_human_readable) {
//this approach to autoset node names is human readable but very slow
//it's turned on while running in the editor
@@ -700,11 +701,7 @@ void Node::_validate_child_name(Node *p_child) {
if (!unique) {
node_hrcr_count.ref();
-#ifdef DEBUG_ENABLED
- String name = "@"+String(p_child->get_type_name())+itos(node_hrcr_count.get());
-#else
- String name = "@"+itos(node_hrcr_count.get());
-#endif
+ String name = "@"+String(p_child->get_name())+"@"+itos(node_hrcr_count.get());
p_child->data.name=name;
}
}
@@ -732,24 +729,27 @@ void Node::_add_child_nocheck(Node* p_child,const StringName& p_name) {
}
-void Node::add_child(Node *p_child) {
+void Node::add_child(Node *p_child, bool p_legible_unique_name) {
ERR_FAIL_NULL(p_child);
/* Fail if node has a parent */
- ERR_EXPLAIN("Can't add child "+p_child->get_name()+" to itself.")
- ERR_FAIL_COND( p_child==this ); // adding to itself!
+ if (p_child==this) {
+ ERR_EXPLAIN("Can't add child "+p_child->get_name()+" to itself.")
+ ERR_FAIL_COND( p_child==this ); // adding to itself!
+ }
ERR_EXPLAIN("Can't add child, already has a parent");
ERR_FAIL_COND( p_child->data.parent );
ERR_EXPLAIN("Can't add child while a notification is happening");
ERR_FAIL_COND( data.blocked > 0 );
/* Validate name */
- _validate_child_name(p_child);
+ _validate_child_name(p_child,p_legible_unique_name);
_add_child_nocheck(p_child,p_child->data.name);
}
+
void Node::_propagate_validate_owner() {
if (data.owner) {
@@ -803,6 +803,7 @@ void Node::remove_child(Node *p_child) {
}
ERR_FAIL_COND( idx==-1 );
+ //ERR_FAIL_COND( p_child->data.blocked > 0 );
//if (data.scene) { does not matter
@@ -857,7 +858,10 @@ Node *Node::_get_child_by_name(const StringName& p_name) const {
Node *Node::_get_node(const NodePath& p_path) const {
- ERR_FAIL_COND_V( !data.inside_tree && p_path.is_absolute(), NULL );
+ if (!data.inside_tree && p_path.is_absolute()) {
+ ERR_EXPLAIN("Can't use get_node() with absolute paths from outside the active scene tree.");
+ ERR_FAIL_V(NULL);
+ }
Node *current=NULL;
Node *root=NULL;
@@ -1468,7 +1472,14 @@ Node *Node::duplicate(bool p_use_instancing) const {
bool instanced=false;
- if (p_use_instancing && get_filename()!=String()) {
+ if (cast_to<InstancePlaceholder>()) {
+
+ const InstancePlaceholder *ip = cast_to<const InstancePlaceholder>();
+ InstancePlaceholder *nip = memnew( InstancePlaceholder );
+ nip->set_instance_path( ip->get_instance_path() );
+ node=nip;
+
+ } else if (p_use_instancing && get_filename()!=String()) {
Ref<PackedScene> res = ResourceLoader::load(get_filename());
ERR_FAIL_COND_V(res.is_null(),NULL);
@@ -1507,6 +1518,15 @@ Node *Node::duplicate(bool p_use_instancing) const {
node->set_name(get_name());
+ List<GroupInfo> gi;
+ get_groups(&gi);
+ for (List<GroupInfo>::Element *E=gi.front();E;E=E->next()) {
+
+ node->add_to_group(E->get().name, E->get().persistent);
+ }
+
+ _duplicate_signals(this, node);
+
for(int i=0;i<get_child_count();i++) {
if (get_child(i)->data.parent_owned)
@@ -1984,7 +2004,7 @@ void Node::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_name","name"),&Node::set_name);
ObjectTypeDB::bind_method(_MD("get_name"),&Node::get_name);
- ObjectTypeDB::bind_method(_MD("add_child","node:Node"),&Node::add_child);
+ ObjectTypeDB::bind_method(_MD("add_child","node:Node","legible_unique_name"),&Node::add_child,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("remove_child","node:Node"),&Node::remove_child);
//ObjectTypeDB::bind_method(_MD("remove_and_delete_child","node:Node"),&Node::remove_and_delete_child);
ObjectTypeDB::bind_method(_MD("get_child_count"),&Node::get_child_count);
@@ -2002,7 +2022,7 @@ void Node::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_greater_than","node:Node"),&Node::is_greater_than);
ObjectTypeDB::bind_method(_MD("get_path"),&Node::get_path);
ObjectTypeDB::bind_method(_MD("get_path_to","node:Node"),&Node::get_path_to);
- ObjectTypeDB::bind_method(_MD("add_to_group","group"),&Node::add_to_group,DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("add_to_group","group","persistent"),&Node::add_to_group,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("remove_from_group","group"),&Node::remove_from_group);
ObjectTypeDB::bind_method(_MD("is_in_group","group"),&Node::is_in_group);
ObjectTypeDB::bind_method(_MD("move_child","child_node:Node","to_pos"),&Node::move_child);
@@ -2064,6 +2084,8 @@ void Node::_bind_methods() {
BIND_CONSTANT( NOTIFICATION_UNPARENTED );
BIND_CONSTANT( NOTIFICATION_PAUSED );
BIND_CONSTANT( NOTIFICATION_UNPAUSED );
+ BIND_CONSTANT( NOTIFICATION_INSTANCED );
+
BIND_CONSTANT( PAUSE_MODE_INHERIT );
diff --git a/scene/main/node.h b/scene/main/node.h
index 87fa4dd6ca..4d05dd381c 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -122,7 +122,7 @@ private:
- void _validate_child_name(Node *p_name);
+ void _validate_child_name(Node *p_name, bool p_force_human_readable=false);
void _propagate_reverse_notification(int p_notification);
void _propagate_deferred_notification(int p_notification, bool p_reverse);
@@ -187,7 +187,7 @@ public:
StringName get_name() const;
void set_name(const String& p_name);
- void add_child(Node *p_child);
+ void add_child(Node *p_child,bool p_legible_unique_name=false);
void remove_child(Node *p_child);
int get_child_count() const;
diff --git a/scene/main/resource_preloader.cpp b/scene/main/resource_preloader.cpp
index f49f626e78..219eea770a 100644
--- a/scene/main/resource_preloader.cpp
+++ b/scene/main/resource_preloader.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/main/resource_preloader.h b/scene/main/resource_preloader.h
index b3e7496fb7..b06e558b59 100644
--- a/scene/main/resource_preloader.h
+++ b/scene/main/resource_preloader.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp
index adf053f5c9..8e2d6aa669 100644
--- a/scene/main/scene_main_loop.cpp
+++ b/scene/main/scene_main_loop.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -330,7 +330,8 @@ void SceneTree::input_text( const String& p_text ) {
root_lock++;
- call_group(GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"input",p_text);
+ call_group(GROUP_CALL_REALTIME,"_viewports","_vp_input_text",p_text); //special one for GUI, as controls use their own process check
+
root_lock--;
}
@@ -620,6 +621,14 @@ void SceneTree::set_editor_hint(bool p_enabled) {
editor_hint=p_enabled;
}
+bool SceneTree::is_node_being_edited(const Node* p_node) const {
+#ifdef TOOLS_ENABLED
+ return editor_hint && edited_scene_root && edited_scene_root->is_a_parent_of(p_node);
+#else
+ return false;
+#endif
+}
+
bool SceneTree::is_editor_hint() const {
return editor_hint;
@@ -965,6 +974,10 @@ Array SceneTree::_get_nodes_in_group(const StringName& p_group) {
return ret;
}
+bool SceneTree::has_group(const StringName& p_identifier) const {
+
+ return group_map.has(p_identifier);
+}
void SceneTree::get_nodes_in_group(const StringName& p_group,List<Node*> *p_list) {
@@ -1586,9 +1599,10 @@ void SceneTree::_bind_methods() {
ObjectTypeDB::bind_method(_MD("notify_group","call_flags","group","notification"),&SceneTree::notify_group);
ObjectTypeDB::bind_method(_MD("set_group","call_flags","group","property","value"),&SceneTree::set_group);
- ObjectTypeDB::bind_method(_MD("get_nodes_in_group"),&SceneTree::_get_nodes_in_group);
+ ObjectTypeDB::bind_method(_MD("get_nodes_in_group","group"),&SceneTree::_get_nodes_in_group);
ObjectTypeDB::bind_method(_MD("get_root:Viewport"),&SceneTree::get_root);
+ ObjectTypeDB::bind_method(_MD("has_group","name"),&SceneTree::has_group);
ObjectTypeDB::bind_method(_MD("set_auto_accept_quit","enabled"),&SceneTree::set_auto_accept_quit);
diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h
index 8d9021d24e..c6fc124345 100644
--- a/scene/main/scene_main_loop.h
+++ b/scene/main/scene_main_loop.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -279,6 +279,8 @@ public:
void set_editor_hint(bool p_enabled);
bool is_editor_hint() const;
+ bool is_node_being_edited(const Node* p_node) const;
+
void set_pause(bool p_enabled);
bool is_paused() const;
@@ -318,6 +320,8 @@ public:
void queue_delete(Object *p_object);
void get_nodes_in_group(const StringName& p_group,List<Node*> *p_list);
+ bool has_group(const StringName& p_identifier) const;
+
void set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect,const Size2 p_minsize);
diff --git a/scene/main/scene_singleton.cpp b/scene/main/scene_singleton.cpp
index 69eb6e24d9..3dcc6b1204 100644
--- a/scene/main/scene_singleton.cpp
+++ b/scene/main/scene_singleton.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/main/scene_singleton.h b/scene/main/scene_singleton.h
index 25157a26ac..0b209f7944 100644
--- a/scene/main/scene_singleton.h
+++ b/scene/main/scene_singleton.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp
index 1bd22a9db1..2c23b62b12 100644
--- a/scene/main/timer.cpp
+++ b/scene/main/timer.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/main/timer.h b/scene/main/timer.h
index 4b9cecba84..0baea76fad 100644
--- a/scene/main/timer.h
+++ b/scene/main/timer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index d19b5767c2..9297d49e2b 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -43,6 +43,13 @@
#include "scene/2d/collision_object_2d.h"
+#include "scene/gui/panel.h"
+#include "scene/gui/label.h"
+#include "scene/main/timer.h"
+#include "scene/scene_string_names.h"
+
+#include "globals.h"
+
int RenderTargetTexture::get_width() const {
ERR_FAIL_COND_V(!vp,0);
@@ -92,8 +99,42 @@ RenderTargetTexture::RenderTargetTexture(Viewport *p_vp){
flags=0;
}
+/////////////////////////////////////
+
+class TooltipPanel : public Panel {
+
+ OBJ_TYPE(TooltipPanel,Panel)
+public:
+ TooltipPanel() {};
+
+};
+
+class TooltipLabel : public Label {
+
+ OBJ_TYPE(TooltipLabel,Label)
+public:
+ TooltipLabel() {};
+
+};
+
+
+Viewport::GUI::GUI() {
+
+
+ mouse_focus=NULL;
+ mouse_focus_button=-1;
+ key_focus=NULL;
+ mouse_over=NULL;
+
+ cancelled_input_ID=0;
+ tooltip=NULL;
+ tooltip_popup=NULL;
+ tooltip_label=NULL;
+ subwindow_order_dirty=false;
+}
+/////////////////////////////////////
void Viewport::_update_stretch_transform() {
if (size_override_stretch && size_override) {
@@ -121,11 +162,10 @@ void Viewport::_update_rect() {
if (!is_inside_tree())
return;
- Node *parent = get_parent();
- if (!render_target && parent && parent->cast_to<Control>()) {
+ if (!render_target && parent_control) {
- Control *c = parent->cast_to<Control>();
+ Control *c = parent_control;
rect.pos=Point2();
rect.size=c->get_size();
@@ -134,6 +174,7 @@ void Viewport::_update_rect() {
VisualServer::ViewportRect vr;
vr.x=rect.pos.x;
vr.y=rect.pos.y;
+
if (render_target) {
vr.x=0;
vr.y=0;
@@ -165,11 +206,10 @@ void Viewport::_parent_draw() {
void Viewport::_parent_visibility_changed() {
- Node *parent = get_parent();
- if (parent && parent->cast_to<Control>()) {
+ if (parent_control) {
- Control *c = parent->cast_to<Control>();
+ Control *c = parent_control;
VisualServer::get_singleton()->canvas_item_set_visible(canvas_item,c->is_visible());
_update_listener();
@@ -182,11 +222,9 @@ void Viewport::_parent_visibility_changed() {
void Viewport::_vp_enter_tree() {
- Node *parent = get_parent();
- //none?
- if (parent && parent->cast_to<Control>()) {
+ if (parent_control) {
- Control *cparent=parent->cast_to<Control>();
+ Control *cparent=parent_control;
RID parent_ci = cparent->get_canvas_item();
ERR_FAIL_COND(!parent_ci.is_valid());
canvas_item = VisualServer::get_singleton()->canvas_item_create();
@@ -194,8 +232,8 @@ void Viewport::_vp_enter_tree() {
VisualServer::get_singleton()->canvas_item_set_parent(canvas_item,parent_ci);
VisualServer::get_singleton()->canvas_item_set_visible(canvas_item,false);
VisualServer::get_singleton()->canvas_item_attach_viewport(canvas_item,viewport);
- parent->connect("resized",this,"_parent_resized");
- parent->connect("visibility_changed",this,"_parent_visibility_changed");
+ parent_control->connect("resized",this,"_parent_resized");
+ parent_control->connect("visibility_changed",this,"_parent_visibility_changed");
} else if (!parent){
VisualServer::get_singleton()->viewport_attach_to_screen(viewport,0);
@@ -207,15 +245,14 @@ void Viewport::_vp_enter_tree() {
void Viewport::_vp_exit_tree() {
- Node *parent = get_parent();
- if (parent && parent->cast_to<Control>()) {
+ if (parent_control) {
- parent->disconnect("resized",this,"_parent_resized");
+ parent_control->disconnect("resized",this,"_parent_resized");
}
- if (parent && parent->cast_to<Control>()) {
+ if (parent_control) {
- parent->disconnect("visibility_changed",this,"_parent_visibility_changed");
+ parent_control->disconnect("visibility_changed",this,"_parent_visibility_changed");
}
if (canvas_item.is_valid()) {
@@ -287,22 +324,32 @@ void Viewport::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
+ if (get_parent()) {
+ Node *parent=get_parent();
+ if (parent) {
+ parent_control=parent->cast_to<Control>();
+ }
+ }
- if (!render_target)
- _vp_enter_tree();
- this->parent=NULL;
- Node *parent=get_parent();
+ parent=NULL;
+ Node *parent_node=get_parent();
- if (parent) {
+ while(parent_node) {
- while(parent && !(this->parent=parent->cast_to<Viewport>())) {
+ parent = parent_node->cast_to<Viewport>();
+ if (parent)
+ break;
- parent=parent->get_parent();
- }
+ parent_node=parent_node->get_parent();
}
+
+ if (!render_target)
+ _vp_enter_tree();
+
+
current_canvas=find_world_2d()->get_canvas();
VisualServer::get_singleton()->viewport_set_scenario(viewport,find_world()->get_scenario());
VisualServer::get_singleton()->viewport_attach_canvas(viewport,current_canvas);
@@ -382,6 +429,7 @@ void Viewport::_notification(int p_what) {
}
remove_from_group("_viewports");
+ parent_control=NULL;
} break;
case NOTIFICATION_FIXED_PROCESS: {
@@ -577,7 +625,7 @@ void Viewport::_notification(int p_what) {
PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space());
if (space) {
- bool col = space->intersect_ray(from,from+dir*10000,result,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF);
+ bool col = space->intersect_ray(from,from+dir*10000,result,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF,true);
ObjectID new_collider=0;
if (col) {
@@ -617,7 +665,7 @@ void Viewport::_notification(int p_what) {
PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space());
if (space) {
- bool col = space->intersect_ray(from,from+dir*10000,result,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF);
+ bool col = space->intersect_ray(from,from+dir*10000,result,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF,true);
ObjectID new_collider=0;
if (col) {
if (result.collider) {
@@ -1223,15 +1271,34 @@ void Viewport::_make_input_local(InputEvent& ev) {
}
+void Viewport::_vp_input_text(const String& p_text) {
+
+ if (gui.key_focus) {
+ gui.key_focus->call("set_text",p_text);
+ }
+}
void Viewport::_vp_input(const InputEvent& p_ev) {
+ if (disable_input)
+ return;
+
+#ifdef TOOLS_ENABLED
+ if (get_tree()->is_editor_hint() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
+ return;
+ }
+#endif
+
+ if (parent_control && !parent_control->is_visible())
+ return;
+
if (render_target && to_screen_rect==Rect2())
return; //if render target, can't get input events
//this one handles system input, p_ev are in system coordinates
//they are converted to viewport coordinates
+
InputEvent ev = p_ev;
_make_input_local(ev);
input(ev);
@@ -1240,6 +1307,17 @@ void Viewport::_vp_input(const InputEvent& p_ev) {
void Viewport::_vp_unhandled_input(const InputEvent& p_ev) {
+ if (disable_input)
+ return;
+
+#ifdef TOOLS_ENABLED
+ if (get_tree()->is_editor_hint() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
+ return;
+ }
+#endif
+
+ if (parent_control && !parent_control->is_visible())
+ return;
if (render_target && to_screen_rect==Rect2())
return; //if render target, can't get input events
@@ -1264,17 +1342,850 @@ void Viewport::warp_mouse(const Vector2& p_pos) {
Input::get_singleton()->warp_mouse_pos(gpos);
}
+
+
+void Viewport::_gui_sort_subwindows() {
+
+ if (!gui.subwindow_order_dirty)
+ return;
+
+
+ gui.modal_stack.sort_custom<Control::CComparator>();
+ gui.subwindows.sort_custom<Control::CComparator>();
+
+ gui.subwindow_order_dirty=false;
+}
+
+void Viewport::_gui_sort_modal_stack() {
+
+ gui.modal_stack.sort_custom<Control::CComparator>();
+}
+
+
+void Viewport::_gui_sort_roots() {
+
+ if (!gui.roots_order_dirty)
+ return;
+
+ gui.roots.sort_custom<Control::CComparator>();
+
+ gui.roots_order_dirty=false;
+}
+
+
+void Viewport::_gui_cancel_tooltip() {
+
+ gui.tooltip=NULL;
+ if (gui.tooltip_timer)
+ gui.tooltip_timer->stop();
+ if (gui.tooltip_popup)
+ gui.tooltip_popup->hide();
+
+}
+
+void Viewport::_gui_show_tooltip() {
+
+ if (!gui.tooltip) {
+ return;
+ }
+
+ String tooltip = gui.tooltip->get_tooltip( gui.tooltip->get_global_transform().xform_inv(gui.tooltip_pos) );
+ if (tooltip.length()==0)
+ return; // bye
+
+
+ if (!gui.tooltip_label) {
+ return;
+ }
+ Ref<StyleBox> ttp = gui.tooltip_label->get_stylebox("panel","TooltipPanel");
+
+ gui.tooltip_label->set_anchor_and_margin(MARGIN_LEFT,Control::ANCHOR_BEGIN,ttp->get_margin(MARGIN_LEFT));
+ gui.tooltip_label->set_anchor_and_margin(MARGIN_TOP,Control::ANCHOR_BEGIN,ttp->get_margin(MARGIN_TOP));
+ gui.tooltip_label->set_anchor_and_margin(MARGIN_RIGHT,Control::ANCHOR_END,ttp->get_margin(MARGIN_RIGHT));
+ gui.tooltip_label->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_END,ttp->get_margin(MARGIN_BOTTOM));
+ gui.tooltip_label->set_text(tooltip);
+ Rect2 r(gui.tooltip_pos+Point2(10,10),gui.tooltip_label->get_combined_minimum_size()+ttp->get_minimum_size());
+ Rect2 vr = gui.tooltip_label->get_viewport_rect();
+ if (r.size.x+r.pos.x>vr.size.x)
+ r.pos.x=vr.size.x-r.size.x;
+ else if (r.pos.x<0)
+ r.pos.x=0;
+
+ if (r.size.y+r.pos.y>vr.size.y)
+ r.pos.y=vr.size.y-r.size.y;
+ else if (r.pos.y<0)
+ r.pos.y=0;
+
+ gui.tooltip_popup->set_pos(r.pos);
+ gui.tooltip_popup->set_size(r.size);
+
+ gui.tooltip_popup->raise();
+
+ gui.tooltip_popup->show();
+}
+
+
+void Viewport::_gui_call_input(Control *p_control,const InputEvent& p_input) {
+
+// _block();
+
+ while(p_control) {
+
+ p_control->call_multilevel(SceneStringNames::get_singleton()->_input_event,p_input);
+ if (gui.key_event_accepted)
+ break;
+ if (!p_control->is_inside_tree())
+ break;
+ p_control->emit_signal(SceneStringNames::get_singleton()->input_event,p_input);
+ if (!p_control->is_inside_tree() || p_control->is_set_as_toplevel()) {
+ break;
+ }
+ if (gui.key_event_accepted)
+ break;
+ if (p_control->data.stop_mouse && (p_input.type==InputEvent::MOUSE_BUTTON || p_input.type==InputEvent::MOUSE_MOTION))
+ break;
+ p_control=p_control->data.parent;
+ }
+
+ //_unblock();
+
+}
+
+Control* Viewport::_gui_find_control(const Point2& p_global) {
+
+ _gui_sort_subwindows();
+
+ for (List<Control*>::Element *E=gui.subwindows.back();E;E=E->prev()) {
+
+ Control *sw = E->get();
+ if (!sw->is_visible())
+ continue;
+
+ Matrix32 xform;
+ CanvasItem *pci = sw->get_parent_item();
+ if (pci)
+ xform=pci->get_global_transform_with_canvas();
+
+
+ Control *ret = _gui_find_control_at_pos(sw,p_global,xform,gui.focus_inv_xform);
+ if (ret)
+ return ret;
+ }
+
+ for (List<Control*>::Element *E=gui.roots.back();E;E=E->prev()) {
+
+ Control *sw = E->get();
+ if (!sw->is_visible())
+ continue;
+
+ Matrix32 xform;
+ CanvasItem *pci = sw->get_parent_item();
+ if (pci)
+ xform=pci->get_global_transform_with_canvas();
+
+
+ Control *ret = _gui_find_control_at_pos(sw,p_global,xform,gui.focus_inv_xform);
+ if (ret)
+ return ret;
+ }
+
+ return NULL;
+
+}
+
+
+Control* Viewport::_gui_find_control_at_pos(CanvasItem* p_node,const Point2& p_global,const Matrix32& p_xform,Matrix32& r_inv_xform) {
+
+ if (p_node->cast_to<Viewport>())
+ return NULL;
+
+ Control *c=p_node->cast_to<Control>();
+
+ if (c) {
+ // print_line("at "+String(c->get_path())+" POS "+c->get_pos()+" bt "+p_xform);
+ }
+
+ //subwindows first!!
+
+ if (p_node->is_hidden()) {
+ //return _find_next_visible_control_at_pos(p_node,p_global,r_inv_xform);
+ return NULL; //canvas item hidden, discard
+ }
+
+ Matrix32 matrix = p_xform * p_node->get_transform();
+
+ if (!c || !c->clips_input() || c->has_point(matrix.affine_inverse().xform(p_global))) {
+
+ for(int i=p_node->get_child_count()-1;i>=0;i--) {
+
+ if (p_node==gui.tooltip_popup)
+ continue;
+
+ CanvasItem *ci = p_node->get_child(i)->cast_to<CanvasItem>();
+ if (!ci || ci->is_set_as_toplevel())
+ continue;
+
+ Control *ret=_gui_find_control_at_pos(ci,p_global,matrix,r_inv_xform);;
+ if (ret)
+ return ret;
+ }
+ }
+
+ if (!c)
+ return NULL;
+
+ matrix.affine_invert();
+
+ //conditions for considering this as a valid control for return
+ if (!c->data.ignore_mouse && c->has_point(matrix.xform(p_global)) && (!gui.drag_preview || (c!=gui.drag_preview && !gui.drag_preview->is_a_parent_of(c)))) {
+ r_inv_xform=matrix;
+ return c;
+ } else
+ return NULL;
+}
+
+void Viewport::_gui_input_event(InputEvent p_event) {
+
+
+
+ if (p_event.ID==gui.cancelled_input_ID) {
+ return;
+ }
+ //?
+// if (!is_visible()) {
+// return; //simple and plain
+// }
+
+
+ switch(p_event.type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+
+ gui.key_event_accepted=false;
+
+ Point2 mpos=Point2(p_event.mouse_button.x,p_event.mouse_button.y);
+ if (p_event.mouse_button.pressed) {
+
+
+
+ Size2 pos = mpos;
+ if (gui.mouse_focus && p_event.mouse_button.button_index!=gui.mouse_focus_button) {
+
+ //do not steal mouse focus and stuff
+
+ } else {
+
+
+ _gui_sort_modal_stack();
+ while (!gui.modal_stack.empty()) {
+
+ Control *top = gui.modal_stack.back()->get();
+ Vector2 pos = top->get_global_transform_with_canvas().affine_inverse().xform(mpos);
+ if (!top->has_point(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
+ }
+
+ top->notification(Control::NOTIFICATION_MODAL_CLOSE);
+ top->_modal_stack_remove();
+ top->hide();
+ } else {
+ break;
+ }
+ }
+
+
+
+ Matrix32 parent_xform;
+
+ //if (data.parent_canvas_item)
+ // parent_xform=data.parent_canvas_item->get_global_transform();
+
+
+
+ gui.mouse_focus = _gui_find_control(pos);
+ //print_line("has mf "+itos(gui.mouse_focus!=NULL));
+ gui.mouse_focus_button=p_event.mouse_button.button_index;
+
+ if (!gui.mouse_focus) {
+ break;
+ }
+
+ if (p_event.mouse_button.button_index==BUTTON_LEFT) {
+ gui.drag_accum=Vector2();
+ gui.drag_attempted=false;
+ gui.drag_data=Variant();
+ }
+
+
+ }
+
+ p_event.mouse_button.global_x = pos.x;
+ p_event.mouse_button.global_y = pos.y;
+
+ pos = gui.focus_inv_xform.xform(pos);
+ p_event.mouse_button.x = pos.x;
+ p_event.mouse_button.y = pos.y;
+
+#ifdef DEBUG_ENABLED
+ if (ScriptDebugger::get_singleton()) {
+
+ Array arr;
+ arr.push_back(gui.mouse_focus->get_path());
+ arr.push_back(gui.mouse_focus->get_type());
+ ScriptDebugger::get_singleton()->send_message("click_ctrl",arr);
+ }
+
+ /*if (bool(GLOBAL_DEF("debug/print_clicked_control",false))) {
+
+ print_line(String(gui.mouse_focus->get_path())+" - "+pos);
+ }*/
+#endif
+
+ if (gui.mouse_focus->get_focus_mode()!=Control::FOCUS_NONE && gui.mouse_focus!=gui.key_focus && p_event.mouse_button.button_index==BUTTON_LEFT) {
+ // also get keyboard focus
+ gui.mouse_focus->grab_focus();
+ }
+
+
+ if (gui.mouse_focus->can_process()) {
+ _gui_call_input(gui.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();
+
+ gui.tooltip_popup->hide();
+
+ } else {
+
+ if (gui.drag_preview && p_event.mouse_button.button_index==BUTTON_LEFT) {
+ memdelete( gui.drag_preview );
+ gui.drag_preview=NULL;
+ }
+
+ if (!gui.mouse_focus) {
+
+ if (gui.mouse_over && gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_button.button_index==BUTTON_LEFT) {
+
+ Size2 pos = mpos;
+ pos = gui.focus_inv_xform.xform(pos);
+
+ gui.mouse_over->drop_data(pos,gui.drag_data);
+ gui.drag_data=Variant();
+ //change mouse accordingly
+ }
+
+ break;
+ }
+
+ Size2 pos = mpos;
+ p_event.mouse_button.global_x = pos.x;
+ p_event.mouse_button.global_y = pos.y;
+ pos = gui.focus_inv_xform.xform(pos);
+ p_event.mouse_button.x = pos.x;
+ p_event.mouse_button.y = pos.y;
+
+ if (gui.mouse_focus->can_process()) {
+ _gui_call_input(gui.mouse_focus,p_event);
+ }
+
+ if (p_event.mouse_button.button_index==gui.mouse_focus_button) {
+ gui.mouse_focus=NULL;
+ gui.mouse_focus_button=-1;
+ }
+
+ if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_button.button_index==BUTTON_LEFT) {
+ gui.drag_data=Variant(); //always clear
+ }
+
+
+ get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
+ get_tree()->set_input_as_handled();
+
+ }
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+ gui.key_event_accepted=false;
+ Point2 mpos=Point2(p_event.mouse_motion.x,p_event.mouse_motion.y);
+
+ gui.last_mouse_pos=mpos;
+
+ Control *over = NULL;
+
+
+ // D&D
+ if (!gui.drag_attempted && gui.mouse_focus && p_event.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
+
+ gui.drag_accum+=Point2(p_event.mouse_motion.relative_x,p_event.mouse_motion.relative_y);;
+ float len = gui.drag_accum.length();
+ if (len>10) {
+ gui.drag_data=gui.mouse_focus->get_drag_data(gui.focus_inv_xform.xform(mpos)-gui.drag_accum);
+ if (gui.drag_data.get_type()!=Variant::NIL) {
+
+ gui.mouse_focus=NULL;
+ }
+ gui.drag_attempted=true;
+ }
+ }
+
+
+ if (gui.mouse_focus) {
+ over=gui.mouse_focus;
+ //recompute focus_inv_xform again here
+
+ } else {
+
+ over = _gui_find_control(mpos);
+ }
+
+
+ if (gui.drag_data.get_type()==Variant::NIL && over && !gui.modal_stack.empty()) {
+
+ Control *top = gui.modal_stack.back()->get();
+ if (over!=top && !top->is_a_parent_of(over)) {
+
+ break; // don't send motion event to anything below modal stack top
+ }
+ }
+
+ if (over!=gui.mouse_over) {
+
+ if (gui.mouse_over)
+ gui.mouse_over->notification(Control::NOTIFICATION_MOUSE_EXIT);
+
+ if (over)
+ over->notification(Control::NOTIFICATION_MOUSE_ENTER);
+
+ }
+
+ gui.mouse_over=over;
+
+ _gui_cancel_tooltip();
+
+ if (gui.drag_preview) {
+ gui.drag_preview->set_pos(mpos);
+ }
+
+ if (!over) {
+ OS::get_singleton()->set_cursor_shape(OS::CURSOR_ARROW);
+ break;
+ }
+
+
+ Matrix32 localizer = over->get_canvas_transform().affine_inverse();
+ Size2 pos = localizer.xform(mpos);
+ Vector2 speed = localizer.basis_xform(Point2(p_event.mouse_motion.speed_x,p_event.mouse_motion.speed_y));
+ Vector2 rel = localizer.basis_xform(Point2(p_event.mouse_motion.relative_x,p_event.mouse_motion.relative_y));
+
+
+ p_event.mouse_motion.global_x = mpos.x;
+ p_event.mouse_motion.global_y = mpos.y;
+ p_event.mouse_motion.speed_x=speed.x;
+ p_event.mouse_motion.speed_y=speed.y;
+ p_event.mouse_motion.relative_x=rel.x;
+ p_event.mouse_motion.relative_y=rel.y;
+
+ if (p_event.mouse_motion.button_mask==0 && gui.tooltip_timer) {
+ //nothing pressed
+
+ bool can_tooltip=true;
+
+ if (!gui.modal_stack.empty()) {
+ if (gui.modal_stack.back()->get()!=over && !gui.modal_stack.back()->get()->is_a_parent_of(over))
+ can_tooltip=false;
+
+ }
+
+
+ if (can_tooltip) {
+
+ gui.tooltip=over;
+ gui.tooltip_pos=mpos;//(parent_xform * get_transform()).affine_inverse().xform(pos);
+ gui.tooltip_timer->start();
+ }
+ }
+
+
+ pos = gui.focus_inv_xform.xform(pos);
+
+
+ p_event.mouse_motion.x = pos.x;
+ p_event.mouse_motion.y = pos.y;
+
+
+ Control::CursorShape cursor_shape = over->get_cursor_shape(pos);
+ OS::get_singleton()->set_cursor_shape( (OS::CursorShape)cursor_shape );
+
+
+ if (over->can_process()) {
+ _gui_call_input(over,p_event);
+ }
+
+
+
+ //get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
+ get_tree()->set_input_as_handled();
+
+
+ if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
+
+ /*bool can_drop =*/ over->can_drop_data(pos,gui.drag_data);
+ //change mouse accordingly i guess
+ }
+
+ } break;
+ case InputEvent::ACTION:
+ case InputEvent::JOYSTICK_BUTTON:
+ case InputEvent::KEY: {
+
+ if (gui.key_focus) {
+
+ gui.key_event_accepted=false;
+ if (gui.key_focus->can_process()) {
+ gui.key_focus->call_multilevel("_input_event",p_event);
+ if (gui.key_focus) //maybe lost it
+ gui.key_focus->emit_signal(SceneStringNames::get_singleton()->input_event,p_event);
+ }
+
+
+ if (gui.key_event_accepted) {
+
+ get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
+ break;
+ }
+ }
+
+
+ if (p_event.is_pressed() && p_event.is_action("ui_cancel") && !gui.modal_stack.empty()) {
+
+ _gui_sort_modal_stack();
+ Control *top = gui.modal_stack.back()->get();
+ if (!top->data.modal_exclusive) {
+
+ top->notification(Control::NOTIFICATION_MODAL_CLOSE);
+ top->_modal_stack_remove();
+ top->hide();
+ }
+ }
+
+
+ Control * from = gui.key_focus ? gui.key_focus : NULL; //hmm
+
+ //keyboard focus
+ //if (from && p_event.key.pressed && !p_event.key.mod.alt && !p_event.key.mod.meta && !p_event.key.mod.command) {
+
+ if (from && p_event.is_pressed()) {
+ Control * next=NULL;
+
+ if (p_event.is_action("ui_focus_next")) {
+
+ next = from->find_next_valid_focus();
+ }
+
+ if (p_event.is_action("ui_focus_prev")) {
+
+ next = from->find_prev_valid_focus();
+ }
+
+ if (p_event.is_action("ui_up")) {
+
+ next = from->_get_focus_neighbour(MARGIN_TOP);
+ }
+
+ if (p_event.is_action("ui_left")) {
+
+ next = from->_get_focus_neighbour(MARGIN_LEFT);
+ }
+
+ if (p_event.is_action("ui_right")) {
+
+ next = from->_get_focus_neighbour(MARGIN_RIGHT);
+ }
+
+ if (p_event.is_action("ui_down")) {
+
+ next = from->_get_focus_neighbour(MARGIN_BOTTOM);
+ }
+
+
+ if (next) {
+ next->grab_focus();
+ get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
+ }
+ }
+
+ } break;
+ }
+}
+
+
+List<Control*>::Element* Viewport::_gui_add_root_control(Control* p_control) {
+
+ gui.roots_order_dirty=true;
+ return gui.roots.push_back(p_control);
+}
+
+List<Control*>::Element* Viewport::_gui_add_subwindow_control(Control* p_control) {
+
+ gui.subwindow_order_dirty=true;
+ return gui.subwindows.push_back(p_control);
+
+}
+
+void Viewport::_gui_set_subwindow_order_dirty() {
+ gui.subwindow_order_dirty=true;
+}
+
+void Viewport::_gui_set_root_order_dirty() {
+ gui.roots_order_dirty=true;
+}
+
+void Viewport::_gui_remove_modal_control(List<Control*>::Element *MI) {
+
+ gui.modal_stack.erase(MI);
+}
+
+void Viewport::_gui_remove_from_modal_stack(List<Control*>::Element *MI,ObjectID p_prev_focus_owner) {
+
+ //transfer the focus stack to the next
+
+ List<Control*>::Element *next = MI->next();
+
+ gui.modal_stack.erase(MI);
+ MI=NULL;
+
+ if (p_prev_focus_owner) {
+
+ // for previous window in stack, pass the focus so it feels more
+ // natural
+
+ if (!next) { //top of stack
+
+ Object *pfo = ObjectDB::get_instance(p_prev_focus_owner);
+ Control *pfoc = pfo->cast_to<Control>();
+ if (!pfoc)
+ return;
+
+ if (!pfoc->is_inside_tree() || !pfoc->is_visible())
+ return;
+ pfoc->grab_focus();
+ } else {
+
+ next->get()->_modal_set_prev_focus_owner(p_prev_focus_owner);
+ }
+ }
+}
+
+void Viewport::_gui_force_drag(Control *p_base, const Variant& p_data, Control *p_control) {
+
+ gui.drag_data=p_data;
+ gui.mouse_focus=NULL;
+
+ if (p_control) {
+ _gui_set_drag_preview(p_base,p_control);
+ }
+}
+
+void Viewport::_gui_set_drag_preview(Control *p_base, Control *p_control) {
+
+ ERR_FAIL_NULL(p_control);
+ ERR_FAIL_COND( !((Object*)p_control)->cast_to<Control>());
+ ERR_FAIL_COND(p_control->is_inside_tree());
+ ERR_FAIL_COND(p_control->get_parent()!=NULL);
+
+ if (gui.drag_preview) {
+ memdelete(gui.drag_preview);
+ }
+ p_control->set_as_toplevel(true);
+ p_control->set_pos(gui.last_mouse_pos);
+ p_base->get_root_parent_control()->add_child(p_control); //add as child of viewport
+ p_control->raise();
+ if (gui.drag_preview) {
+ memdelete( gui.drag_preview );
+ }
+ gui.drag_preview=p_control;
+}
+
+
+void Viewport::_gui_remove_root_control(List<Control*>::Element *RI) {
+
+ gui.roots.erase(RI);
+}
+
+void Viewport::_gui_remove_subwindow_control(List<Control*>::Element* SI){
+
+ gui.subwindows.erase(SI);
+}
+
+void Viewport::_gui_unfocus_control(Control *p_control) {
+
+ if (gui.key_focus==p_control) {
+ gui.key_focus->release_focus();
+ }
+}
+
+void Viewport::_gui_hid_control(Control *p_control) {
+
+ if (gui.mouse_focus == p_control) {
+ gui.mouse_focus=NULL;
+ }
+
+ /* ???
+ if (data.window==p_control) {
+ window->drag_data=Variant();
+ if (window->drag_preview) {
+ memdelete( window->drag_preview);
+ window->drag_preview=NULL;
+ }
+ }
+ */
+
+ if (gui.key_focus == p_control)
+ gui.key_focus=NULL;
+ if (gui.mouse_over == p_control)
+ gui.mouse_over=NULL;
+ if (gui.tooltip == p_control)
+ gui.tooltip=NULL;
+ if (gui.tooltip == p_control)
+ gui.tooltip=NULL;
+
+}
+
+void Viewport::_gui_remove_control(Control *p_control) {
+
+
+ if (gui.mouse_focus == p_control)
+ gui.mouse_focus=NULL;
+ if (gui.key_focus == p_control)
+ gui.key_focus=NULL;
+ if (gui.mouse_over == p_control)
+ gui.mouse_over=NULL;
+ if (gui.tooltip == p_control)
+ gui.tooltip=NULL;
+
+
+}
+
+void Viewport::_gui_remove_focus() {
+
+ if (gui.key_focus) {
+ Node *f=gui.key_focus;
+ gui.key_focus=NULL;
+ f->notification( Control::NOTIFICATION_FOCUS_EXIT,true );
+
+
+ }
+}
+
+bool Viewport::_gui_is_modal_on_top(const Control* p_control) {
+
+ return (gui.modal_stack.size() && gui.modal_stack.back()->get()==p_control);
+
+}
+
+bool Viewport::_gui_control_has_focus(const Control* p_control) {
+
+ return gui.key_focus==p_control;
+}
+
+void Viewport::_gui_control_grab_focus(Control* p_control) {
+
+
+ //no need for change
+ if (gui.key_focus && gui.key_focus==p_control)
+ return;
+
+ _gui_remove_focus();
+ get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_gui_remove_focus");
+ gui.key_focus=p_control;
+ p_control->notification(Control::NOTIFICATION_FOCUS_ENTER);
+ p_control->update();
+
+}
+
+void Viewport::_gui_accept_event() {
+
+ gui.key_event_accepted=true;
+ if (is_inside_tree())
+ get_tree()->set_input_as_handled();
+}
+
+
+List<Control*>::Element* Viewport::_gui_show_modal(Control* p_control) {
+
+ gui.modal_stack.push_back(p_control);
+ if (gui.key_focus)
+ p_control->_modal_set_prev_focus_owner(gui.key_focus->get_instance_ID());
+ else
+ p_control->_modal_set_prev_focus_owner(0);
+
+ return gui.modal_stack.back();
+}
+
+Control *Viewport::_gui_get_focus_owner() {
+
+ return gui.key_focus;
+}
+
+void Viewport::_gui_grab_click_focus(Control *p_control) {
+
+ if (gui.mouse_focus) {
+
+
+ if (gui.mouse_focus==p_control)
+ return;
+ InputEvent ie;
+ ie.type=InputEvent::MOUSE_BUTTON;
+ InputEventMouseButton &mb=ie.mouse_button;
+
+ //send unclic
+
+ Point2 click =gui.mouse_focus->get_global_transform().affine_inverse().xform(gui.last_mouse_pos);
+ mb.x=click.x;
+ mb.y=click.y;
+ mb.button_index=gui.mouse_focus_button;
+ mb.pressed=false;
+ gui.mouse_focus->call_deferred("_input_event",ie);
+
+
+ gui.mouse_focus=p_control;
+ gui.focus_inv_xform=gui.mouse_focus->get_global_transform().affine_inverse();
+ click =gui.mouse_focus->get_global_transform().affine_inverse().xform(gui.last_mouse_pos);
+ mb.x=click.x;
+ mb.y=click.y;
+ mb.button_index=gui.mouse_focus_button;
+ mb.pressed=true;
+ gui.mouse_focus->call_deferred("_input_event",ie);
+
+ }
+}
+
+
+///////////////////////////////
+
+
void Viewport::input(const InputEvent& p_event) {
ERR_FAIL_COND(!is_inside_tree());
- get_tree()->_call_input_pause(input_group,"_input",p_event);
- get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",p_event); //special one for GUI, as controls use their own process check
+
+
+ get_tree()->_call_input_pause(input_group,"_input",p_event);
+ _gui_input_event(p_event);
+ //get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",p_event); //special one for GUI, as controls use their own process check
}
void Viewport::unhandled_input(const InputEvent& p_event) {
ERR_FAIL_COND(!is_inside_tree());
+
get_tree()->_call_input_pause(unhandled_input_group,"_unhandled_input",p_event);
//call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_input","_unhandled_input",ev);
if (!get_tree()->input_handled && p_event.type==InputEvent::KEY) {
@@ -1377,6 +2288,19 @@ bool Viewport::get_physics_object_picking() {
return physics_object_picking;
}
+bool Viewport::gui_has_modal_stack() const {
+
+ return gui.modal_stack.size();
+}
+
+void Viewport::set_disable_input(bool p_disable) {
+ disable_input=p_disable;
+}
+
+bool Viewport::is_input_disabled() const {
+
+ return disable_input;
+}
void Viewport::_bind_methods() {
@@ -1405,6 +2329,7 @@ void Viewport::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_parent_resized"), &Viewport::_parent_resized);
ObjectTypeDB::bind_method(_MD("_vp_input"), &Viewport::_vp_input);
+ ObjectTypeDB::bind_method(_MD("_vp_input_text","text"), &Viewport::_vp_input_text);
ObjectTypeDB::bind_method(_MD("_vp_unhandled_input"), &Viewport::_vp_unhandled_input);
ObjectTypeDB::bind_method(_MD("set_size_override","enable","size","margin"), &Viewport::set_size_override,DEFVAL(Size2(-1,-1)),DEFVAL(Size2(0,0)));
@@ -1456,11 +2381,18 @@ void Viewport::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_as_audio_listener_2d","enable"), &Viewport::set_as_audio_listener_2d);
ObjectTypeDB::bind_method(_MD("is_audio_listener_2d","enable"), &Viewport::is_audio_listener_2d);
- ObjectTypeDB::bind_method(_MD("set_render_target_to_screen_rect"), &Viewport::set_render_target_to_screen_rect);
+ ObjectTypeDB::bind_method(_MD("set_render_target_to_screen_rect","rect"), &Viewport::set_render_target_to_screen_rect);
ObjectTypeDB::bind_method(_MD("get_mouse_pos"), &Viewport::get_mouse_pos);
ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"), &Viewport::warp_mouse);
+ ObjectTypeDB::bind_method(_MD("gui_has_modal_stack"), &Viewport::gui_has_modal_stack);
+
+ ObjectTypeDB::bind_method(_MD("set_disable_input","disable"), &Viewport::set_disable_input);
+ ObjectTypeDB::bind_method(_MD("is_input_disabled"), &Viewport::is_input_disabled);
+
+ ObjectTypeDB::bind_method(_MD("_gui_show_tooltip"), &Viewport::_gui_show_tooltip);
+
ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"), _SCS("set_rect"), _SCS("get_rect") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"own_world"), _SCS("set_use_own_world"), _SCS("is_using_own_world") );
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"world",PROPERTY_HINT_RESOURCE_TYPE,"World"), _SCS("set_world"), _SCS("get_world") );
@@ -1475,6 +2407,7 @@ void Viewport::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener/enable_2d"), _SCS("set_as_audio_listener_2d"), _SCS("is_audio_listener_2d") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener/enable_3d"), _SCS("set_as_audio_listener"), _SCS("is_audio_listener") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"physics/object_picking"), _SCS("set_physics_object_picking"), _SCS("get_physics_object_picking") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gui/disable_input"), _SCS("set_disable_input"), _SCS("is_input_disabled") );
ADD_SIGNAL(MethodInfo("size_changed"));
@@ -1491,6 +2424,7 @@ void Viewport::_bind_methods() {
Viewport::Viewport() {
+
world_2d = Ref<World2D>( memnew( World2D ));
viewport = VisualServer::get_singleton()->viewport_create();
@@ -1524,7 +2458,26 @@ Viewport::Viewport() {
unhandled_input_group = "_vp_unhandled_input"+id;
unhandled_key_input_group = "_vp_unhandled_key_input"+id;
-
+ disable_input=false;
+
+ //window tooltip
+ gui.tooltip_timer = memnew( Timer );
+ add_child(gui.tooltip_timer);
+ gui.tooltip_timer->force_parent_owned();
+ gui.tooltip_timer->set_wait_time( GLOBAL_DEF("display/tooltip_delay",0.7));
+ gui.tooltip_timer->connect("timeout",this,"_gui_show_tooltip");
+ gui.tooltip=NULL;
+ gui.tooltip_popup = memnew( TooltipPanel );
+ add_child(gui.tooltip_popup);
+ gui.tooltip_popup->force_parent_owned();
+ gui.tooltip_label = memnew( TooltipLabel );
+ gui.tooltip_popup->add_child(gui.tooltip_label);
+ gui.tooltip_popup->set_as_toplevel(true);
+ gui.tooltip_popup->hide();
+ gui.drag_attempted=false;
+ gui.drag_preview=NULL;
+
+ parent_control=NULL;
}
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 843a1fd9b7..89e053d607 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -39,6 +39,11 @@
*/
class Camera;
+class Control;
+class CanvasItem;
+class Panel;
+class Label;
+class Timer;
class Viewport;
class RenderTargetTexture : public Texture {
@@ -82,6 +87,9 @@ public:
private:
friend class RenderTargetTexture;
+
+
+ Control *parent_control;
Viewport *parent;
Camera *camera;
@@ -162,6 +170,48 @@ friend class RenderTargetTexture;
Ref<RenderTargetTexture> render_target_texture;
+ struct GUI {
+ // info used when this is a window
+
+ bool key_event_accepted;
+ Control *mouse_focus;
+ int mouse_focus_button;
+ Control *key_focus;
+ Control *mouse_over;
+ Control *tooltip;
+ Panel *tooltip_popup;
+ Label *tooltip_label;
+ Point2 tooltip_pos;
+ Point2 last_mouse_pos;
+ Point2 drag_accum;
+ bool drag_attempted;
+ Variant drag_data;
+ Control *drag_preview;
+ Timer *tooltip_timer;
+ List<Control*> modal_stack;
+ unsigned int cancelled_input_ID;
+ Matrix32 focus_inv_xform;
+ bool subwindow_order_dirty;
+ List<Control*> subwindows;
+ bool roots_order_dirty;
+ List<Control*> roots;
+
+
+ GUI();
+ } gui;
+
+ bool disable_input;
+
+ void _gui_call_input(Control *p_control,const InputEvent& p_input);
+ void _gui_sort_subwindows();
+ void _gui_sort_roots();
+ void _gui_sort_modal_stack();
+ Control* _gui_find_control(const Point2& p_global);
+ Control* _gui_find_control_at_pos(CanvasItem* p_node,const Point2& p_global,const Matrix32& p_xform,Matrix32& r_inv_xform);
+
+ void _gui_input_event(InputEvent p_event);
+
+
void update_worlds();
_FORCE_INLINE_ Matrix32 _get_input_pre_xform() const;
@@ -170,9 +220,47 @@ friend class RenderTargetTexture;
void _vp_exit_tree();
void _vp_input(const InputEvent& p_ev);
+ void _vp_input_text(const String& p_text);
void _vp_unhandled_input(const InputEvent& p_ev);
void _make_input_local(InputEvent& ev);
+
+friend class Control;
+
+ List<Control*>::Element* _gui_add_root_control(Control* p_control);
+ List<Control*>::Element* _gui_add_subwindow_control(Control* p_control);
+
+ void _gui_set_subwindow_order_dirty();
+ void _gui_set_root_order_dirty();
+
+
+ void _gui_remove_modal_control(List<Control*>::Element *MI);
+ void _gui_remove_from_modal_stack(List<Control*>::Element *MI,ObjectID p_prev_focus_owner);
+ void _gui_remove_root_control(List<Control*>::Element *RI);
+ void _gui_remove_subwindow_control(List<Control*>::Element* SI);
+
+ void _gui_cancel_tooltip();
+ void _gui_show_tooltip();
+
+
+ void _gui_remove_control(Control *p_control);
+ void _gui_hid_control(Control *p_control);
+
+ void _gui_force_drag(Control *p_base,const Variant& p_data,Control *p_control);
+ void _gui_set_drag_preview(Control *p_base,Control *p_control);
+
+ bool _gui_is_modal_on_top(const Control* p_control);
+ List<Control*>::Element* _gui_show_modal(Control* p_control);
+
+ void _gui_remove_focus();
+ void _gui_unfocus_control(Control *p_control);
+ bool _gui_control_has_focus(const Control* p_control);
+ void _gui_control_grab_focus(Control* p_control);
+ void _gui_grab_click_focus(Control *p_control);
+ void _gui_accept_event();
+
+ Control *_gui_get_focus_owner();
+
friend class Camera;
void _camera_transform_changed_notify();
void _set_camera(Camera* p_camera);
@@ -254,6 +342,9 @@ public:
void input(const InputEvent& p_event);
void unhandled_input(const InputEvent& p_event);
+ void set_disable_input(bool p_disable);
+ bool is_input_disabled() const;
+
void set_render_target_to_screen_rect(const Rect2& p_rect);
Rect2 get_render_target_to_screen_rect() const;
@@ -263,6 +354,9 @@ public:
void set_physics_object_picking(bool p_enable);
bool get_physics_object_picking();
+ bool gui_has_modal_stack() const;
+
+
Viewport();
~Viewport();
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index b3a9ab922e..3c1b5268fc 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -221,7 +221,7 @@
static ResourceFormatLoaderImage *resource_loader_image=NULL;
static ResourceFormatLoaderWAV *resource_loader_wav=NULL;
-static ResourceFormatLoaderBitMap *resource_loader_bitmap=NULL;
+
#ifdef TOOLS_ENABLED
@@ -249,8 +249,6 @@ void register_scene_types() {
resource_loader_wav = memnew( ResourceFormatLoaderWAV );
ResourceLoader::add_resource_format_loader( resource_loader_wav );
- resource_loader_bitmap = memnew( ResourceFormatLoaderBitMap );
- ResourceLoader::add_resource_format_loader( resource_loader_bitmap );
#ifdef TOOLS_ENABLED
@@ -610,6 +608,7 @@ void register_scene_types() {
OS::get_singleton()->yield(); //may take time to init
+ ObjectTypeDB::register_virtual_type<SceneState>();
ObjectTypeDB::register_type<PackedScene>();
ObjectTypeDB::register_type<SceneTree>();
@@ -631,7 +630,6 @@ void unregister_scene_types() {
memdelete( resource_loader_image );
memdelete( resource_loader_wav );
- memdelete( resource_loader_bitmap );
#ifdef TOOLS_ENABLED
diff --git a/scene/register_scene_types.h b/scene/register_scene_types.h
index 7d36dbc101..15e1eb2980 100644
--- a/scene/register_scene_types.h
+++ b/scene/register_scene_types.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index afd4dc5304..e8bd6c14ad 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index 256826a4bb..405b8b6a05 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/audio_stream.cpp b/scene/resources/audio_stream.cpp
index 569ed8620d..1dd702abd2 100644
--- a/scene/resources/audio_stream.cpp
+++ b/scene/resources/audio_stream.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/audio_stream.h b/scene/resources/audio_stream.h
index b16e62b8c7..a4a2ad7599 100644
--- a/scene/resources/audio_stream.h
+++ b/scene/resources/audio_stream.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/audio_stream_resampled.cpp b/scene/resources/audio_stream_resampled.cpp
index edbca60bd3..3e10048f57 100644
--- a/scene/resources/audio_stream_resampled.cpp
+++ b/scene/resources/audio_stream_resampled.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/audio_stream_resampled.h b/scene/resources/audio_stream_resampled.h
index 570c311878..64f9d17d88 100644
--- a/scene/resources/audio_stream_resampled.h
+++ b/scene/resources/audio_stream_resampled.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/bit_mask.cpp b/scene/resources/bit_mask.cpp
index 9a6452797a..f5bfce3ef8 100644
--- a/scene/resources/bit_mask.cpp
+++ b/scene/resources/bit_mask.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -204,57 +204,3 @@ BitMap::BitMap() {
//////////////////////////////////////
-
-RES ResourceFormatLoaderBitMap::load(const String &p_path, const String& p_original_path, Error *r_error) {
-
- if (r_error)
- *r_error=ERR_FILE_CANT_OPEN;
-
- BitMap* ptr = memnew(BitMap);
- Ref<BitMap> bitmap( ptr );
-
-
- Image image;
-
- Error err = ImageLoader::load_image(p_path,&image);
-
- ERR_EXPLAIN("Failed loading image for BitMap: "+p_path);
- ERR_FAIL_COND_V(err, RES());
-
- bitmap->create_from_image_alpha(image);
- if (r_error)
- *r_error=OK;
-
- return bitmap;
-
-}
-
-bool ResourceFormatLoaderBitMap::handles_type(const String& p_type) const {
-
- return (p_type=="BitMap");
-}
-
-void ResourceFormatLoaderBitMap::get_recognized_extensions(List<String> *p_extensions) const {
-
- ImageLoader::get_recognized_extensions(p_extensions);
-}
-
-String ResourceFormatLoaderBitMap::get_resource_type(const String &p_path) const {
-
- List<String> extensions;
- ImageLoader::get_recognized_extensions(&extensions);
- String ext=p_path.extension().to_lower();
- for(List<String>::Element *E=extensions.front();E;E=E->next()) {
- if (E->get()==ext)
- return "BitMap";
- }
- return "";
-}
-
-
-ResourceFormatLoaderBitMap::ResourceFormatLoaderBitMap() {
-
-
-}
-
-
diff --git a/scene/resources/bit_mask.h b/scene/resources/bit_mask.h
index a6b29bb919..b245ea1542 100644
--- a/scene/resources/bit_mask.h
+++ b/scene/resources/bit_mask.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -62,16 +62,5 @@ public:
BitMap();
};
-class ResourceFormatLoaderBitMap : public ResourceFormatLoader {
-
-public:
-
- virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
- virtual bool handles_type(const String& p_type) const;
- virtual String get_resource_type(const String &p_path) const;
-
- ResourceFormatLoaderBitMap();
-};
#endif // BIT_MASK_H
diff --git a/scene/resources/bounds.cpp b/scene/resources/bounds.cpp
index 7382d60535..65ce5e49e8 100644
--- a/scene/resources/bounds.cpp
+++ b/scene/resources/bounds.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/bounds.h b/scene/resources/bounds.h
index 68aca6f6a0..a1610e2b57 100644
--- a/scene/resources/bounds.h
+++ b/scene/resources/bounds.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/box_shape.cpp b/scene/resources/box_shape.cpp
index ba29a1b601..9a6fedeb0b 100644
--- a/scene/resources/box_shape.cpp
+++ b/scene/resources/box_shape.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/box_shape.h b/scene/resources/box_shape.h
index 9667515657..88fca65eea 100644
--- a/scene/resources/box_shape.h
+++ b/scene/resources/box_shape.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/canvas.cpp b/scene/resources/canvas.cpp
index 51953d9683..0c87d0473d 100644
--- a/scene/resources/canvas.cpp
+++ b/scene/resources/canvas.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/canvas.h b/scene/resources/canvas.h
index 71dc080e64..5120301a67 100644
--- a/scene/resources/canvas.h
+++ b/scene/resources/canvas.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/capsule_shape.cpp b/scene/resources/capsule_shape.cpp
index 67ceed6be0..4c53645d2d 100644
--- a/scene/resources/capsule_shape.cpp
+++ b/scene/resources/capsule_shape.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/capsule_shape.h b/scene/resources/capsule_shape.h
index e516d0e3c7..4263c3a554 100644
--- a/scene/resources/capsule_shape.h
+++ b/scene/resources/capsule_shape.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp
index 923a509ad5..1887ec11d7 100644
--- a/scene/resources/capsule_shape_2d.cpp
+++ b/scene/resources/capsule_shape_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/capsule_shape_2d.h b/scene/resources/capsule_shape_2d.h
index dc679966f9..18b5c12a52 100644
--- a/scene/resources/capsule_shape_2d.h
+++ b/scene/resources/capsule_shape_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp
index c77395612c..7171af9670 100644
--- a/scene/resources/circle_shape_2d.cpp
+++ b/scene/resources/circle_shape_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/circle_shape_2d.h b/scene/resources/circle_shape_2d.h
index a5902b189c..c36e00d106 100644
--- a/scene/resources/circle_shape_2d.h
+++ b/scene/resources/circle_shape_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/color_ramp.cpp b/scene/resources/color_ramp.cpp
index 97d3fafd58..bf1f298e7a 100644
--- a/scene/resources/color_ramp.cpp
+++ b/scene/resources/color_ramp.cpp
@@ -26,6 +26,23 @@ ColorRamp::~ColorRamp() {
void ColorRamp::_bind_methods() {
+
+
+
+
+ ObjectTypeDB::bind_method(_MD("add_point","offset","color"),&ColorRamp::add_point);
+ ObjectTypeDB::bind_method(_MD("remove_point","offset","color"),&ColorRamp::remove_point);
+
+ ObjectTypeDB::bind_method(_MD("set_offset","point","offset"),&ColorRamp::set_offset);
+ ObjectTypeDB::bind_method(_MD("get_offset","point"),&ColorRamp::get_offset);
+
+ ObjectTypeDB::bind_method(_MD("set_color","point","color"),&ColorRamp::set_color);
+ ObjectTypeDB::bind_method(_MD("get_color","point"),&ColorRamp::get_color);
+
+ ObjectTypeDB::bind_method(_MD("interpolate","offset"),&ColorRamp::get_color_at_offset);
+
+ ObjectTypeDB::bind_method(_MD("get_point_count"),&ColorRamp::get_points_count);
+
ObjectTypeDB::bind_method(_MD(COLOR_RAMP_SET_OFFSETS,"offsets"),&ColorRamp::set_offsets);
ObjectTypeDB::bind_method(_MD(COLOR_RAMP_GET_OFFSETS),&ColorRamp::get_offsets);
@@ -79,6 +96,23 @@ Vector<ColorRamp::Point>& ColorRamp::get_points() {
return points;
}
+void ColorRamp::add_point(float p_offset, const Color& p_color) {
+
+ Point p;
+ p.offset=p_offset;
+ p.color=p_color;
+ is_sorted=false;
+ points.push_back(p);
+
+}
+
+void ColorRamp::remove_point(int p_index) {
+
+ ERR_FAIL_INDEX(p_index,points.size());
+ ERR_FAIL_COND(points.size()<=2);
+ points.remove(p_index);
+}
+
void ColorRamp::set_points(Vector<ColorRamp::Point>& p_points) {
points = p_points;
is_sorted = false;
diff --git a/scene/resources/color_ramp.h b/scene/resources/color_ramp.h
index 8f6ba2c3e5..aab5698c2b 100644
--- a/scene/resources/color_ramp.h
+++ b/scene/resources/color_ramp.h
@@ -32,6 +32,9 @@ public:
ColorRamp();
virtual ~ColorRamp();
+ void add_point(float p_offset, const Color& p_color);
+ void remove_point(int p_index);
+
void set_points(Vector<Point>& points);
Vector<Point>& get_points();
diff --git a/scene/resources/concave_polygon_shape.cpp b/scene/resources/concave_polygon_shape.cpp
index 7aeac04a22..34bea038f4 100644
--- a/scene/resources/concave_polygon_shape.cpp
+++ b/scene/resources/concave_polygon_shape.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/concave_polygon_shape.h b/scene/resources/concave_polygon_shape.h
index fae98ee046..a4845e9220 100644
--- a/scene/resources/concave_polygon_shape.h
+++ b/scene/resources/concave_polygon_shape.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/concave_polygon_shape_2d.cpp b/scene/resources/concave_polygon_shape_2d.cpp
index 01b7531f14..2c66155cb8 100644
--- a/scene/resources/concave_polygon_shape_2d.cpp
+++ b/scene/resources/concave_polygon_shape_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/concave_polygon_shape_2d.h b/scene/resources/concave_polygon_shape_2d.h
index 29666c88c1..89b8914741 100644
--- a/scene/resources/concave_polygon_shape_2d.h
+++ b/scene/resources/concave_polygon_shape_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/convex_polygon_shape.cpp b/scene/resources/convex_polygon_shape.cpp
index 6a405c9c94..7fcc9e97c0 100644
--- a/scene/resources/convex_polygon_shape.cpp
+++ b/scene/resources/convex_polygon_shape.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/convex_polygon_shape.h b/scene/resources/convex_polygon_shape.h
index 48454deb2b..a4e504ee24 100644
--- a/scene/resources/convex_polygon_shape.h
+++ b/scene/resources/convex_polygon_shape.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp
index a1137ba614..5c0dadefc2 100644
--- a/scene/resources/convex_polygon_shape_2d.cpp
+++ b/scene/resources/convex_polygon_shape_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,6 +30,8 @@
#include "servers/physics_2d_server.h"
#include "servers/visual_server.h"
+#include "geometry.h"
+
void ConvexPolygonShape2D::_update_shape() {
Physics2DServer::get_singleton()->shape_set_data(get_rid(),points);
@@ -40,7 +42,9 @@ void ConvexPolygonShape2D::_update_shape() {
void ConvexPolygonShape2D::set_point_cloud(const Vector<Vector2>& p_points) {
-
+ Vector<Point2> hull=Geometry::convex_hull_2d(p_points);
+ ERR_FAIL_COND(hull.size()<3);
+ set_points(hull);
}
void ConvexPolygonShape2D::set_points(const Vector<Vector2>& p_points) {
diff --git a/scene/resources/convex_polygon_shape_2d.h b/scene/resources/convex_polygon_shape_2d.h
index 1af7787f67..e1792a1075 100644
--- a/scene/resources/convex_polygon_shape_2d.h
+++ b/scene/resources/convex_polygon_shape_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index c1a389942f..7dec4029fc 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/curve.h b/scene/resources/curve.h
index 4818632dc3..262f22b7d1 100644
--- a/scene/resources/curve.h
+++ b/scene/resources/curve.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/default_theme/button_focus.png b/scene/resources/default_theme/button_focus.png
new file mode 100644
index 0000000000..52af26483e
--- /dev/null
+++ b/scene/resources/default_theme/button_focus.png
Binary files differ
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 25407a5b84..f713b9e979 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
@@ -80,6 +80,13 @@ static Ref<Texture> make_icon(T p_src) {
return texture;
}
+static Ref<Shader> make_shader(const char*vertex_code,const char*fragment_code,const char*lighting_code) {
+ Ref<Shader> shader = (memnew( Shader(Shader::MODE_CANVAS_ITEM) ));
+ shader->set_code(vertex_code, fragment_code, lighting_code);
+
+ return shader;
+}
+
static Ref<Font> make_font(int p_height,int p_ascent, int p_valign, int p_charcount, const int *p_chars,const Ref<Texture> &p_texture) {
@@ -543,7 +550,11 @@ void make_default_theme() {
t->set_constant("close_v_ofs","WindowDialog", 20 );
t->set_constant("titlebar_height","WindowDialog", 18 );
t->set_constant("title_height","WindowDialog", 20 );
-
+
+
+ // File Dialog
+
+ t->set_icon("reload","FileDialog",make_icon( icon_reload_png ));
// Popup
@@ -709,6 +720,11 @@ void make_default_theme() {
t->set_stylebox("button_pressed","Tabs", make_stylebox( button_pressed_png,4,4,4,4) );
t->set_stylebox("button","Tabs", make_stylebox( button_normal_png,4,4,4,4) );
+ t->set_icon("increment","Tabs",make_icon( scroll_button_right_png));
+ t->set_icon("increment_hilite","Tabs",make_icon( scroll_button_right_hl_png));
+ t->set_icon("decrement","Tabs",make_icon( scroll_button_left_png));
+ t->set_icon("decrement_hilite","Tabs",make_icon( scroll_button_left_hl_png));
+ t->set_icon("close","Tabs",make_icon( tab_close_png));
t->set_font("font","Tabs", default_font );
@@ -758,7 +774,11 @@ void make_default_theme() {
t->set_constant("label_width","ColorPicker", 20);
t->set_constant("hseparator","ColorPicker", 4);
-
+ t->set_icon("screen_picker","ColorPicker", make_icon( icon_color_pick_png ) );
+ t->set_icon("add_preset","ColorPicker", make_icon( icon_add_png ) );
+
+ t->set_shader("uv_editor", "ColorPicker", make_shader("", uv_editor_shader_code, ""));
+ t->set_shader("w_editor", "ColorPicker", make_shader("", w_editor_shader_code, ""));
// TooltipPanel
@@ -793,6 +813,8 @@ void make_default_theme() {
t->set_color("selection_color","RichTextLabel", Color(0.1,0.1,1,0.8) );
t->set_constant("line_separation","RichTextLabel", 1 );
+ t->set_constant("table_hseparation","RichTextLabel", 3 );
+ t->set_constant("table_vseparation","RichTextLabel", 3 );
diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h
index ddd8af46f0..44569ba192 100644
--- a/scene/resources/default_theme/default_theme.h
+++ b/scene/resources/default_theme/default_theme.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/scene/resources/default_theme/frame_focus.png b/scene/resources/default_theme/frame_focus.png
new file mode 100644
index 0000000000..0df195d83e
--- /dev/null
+++ b/scene/resources/default_theme/frame_focus.png
Binary files differ
diff --git a/scene/resources/default_theme/icon_add.png b/scene/resources/default_theme/icon_add.png
new file mode 100644
index 0000000000..26283ca67c
--- /dev/null
+++ b/scene/resources/default_theme/icon_add.png
Binary files differ
diff --git a/scene/resources/default_theme/icon_color_pick.png b/scene/resources/default_theme/icon_color_pick.png
new file mode 100644
index 0000000000..2896763834
--- /dev/null
+++ b/scene/resources/default_theme/icon_color_pick.png
Binary files differ
diff --git a/scene/resources/default_theme/icon_reload.png b/scene/resources/default_theme/icon_reload.png
new file mode 100644
index 0000000000..f7c6530d77
--- /dev/null
+++ b/scene/resources/default_theme/icon_reload.png
Binary files differ
diff --git a/scene/resources/default_theme/make_png_header.py b/scene/resources/default_theme/make_header.py
index 0f0ce1808f..2d3f989e01 100644
--- a/scene/resources/default_theme/make_png_header.py
+++ b/scene/resources/default_theme/make_header.py
@@ -3,9 +3,6 @@ import os;
import glob;
import string;
-pixmaps = glob.glob("*.png");
-
-pixmaps.sort();
#Generate include files
@@ -15,27 +12,61 @@ f.write("// THIS FILE HAS BEEN AUTOGENERATED, DONT EDIT!!\n");
f.write("\n\n");
+#Generate png image block
+
+pixmaps = glob.glob("*.png");
+
+pixmaps.sort();
+
f.write("\n\n\n");
-
-
for x in pixmaps:
-
+
var_str=x[:-4]+"_png";
-
+
f.write("static const unsigned char "+ var_str +"[]={\n");
-
+
pngf=open(x,"rb");
-
+
b=pngf.read(1);
while(len(b)==1):
f.write(hex(ord(b)))
b=pngf.read(1);
if (len(b)==1):
f.write(",")
-
+
f.write("\n};\n\n\n");
pngf.close();
-
-f.close();
+#Generate shaders block
+
+shaders = glob.glob("*.gsl")
+
+shaders.sort();
+
+f.write("\n\n\n");
+
+for x in shaders:
+
+ var_str=x[:-4]+"_shader_code";
+
+ f.write("static const char *"+ var_str +"=\n");
+
+ sf=open(x,"rb");
+
+
+ b=sf.readline();
+ while(b!=""):
+ if (b.endswith("\r\n")):
+ b=b[:-2]
+ if (b.endswith("\n")):
+ b=b[:-1]
+ f.write(" \""+b)
+ b=sf.readline();
+ if (b!=""):
+ f.write("\"\n")
+
+ f.write("\";\n\n\n");
+ sf.close();
+
+f.close();
diff --git a/scene/resources/default_theme/tab_close.png b/scene/resources/default_theme/tab_close.png
new file mode 100644
index 0000000000..10e56d5bb8
--- /dev/null
+++ b/scene/resources/default_theme/tab_close.png
Binary files differ
diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h
index c338126d3a..4c440ab99a 100644
--- a/scene/resources/default_theme/theme_data.h
+++ b/scene/resources/default_theme/theme_data.h
@@ -179,11 +179,21 @@ static const unsigned char hsplitter_png[]={
};
+static const unsigned char icon_add_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,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x12,0x0,0x0,0xb,0x12,0x1,0xd2,0xdd,0x7e,0xfc,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xec,0x49,0x44,0x41,0x54,0x38,0x8d,0xdd,0x92,0x41,0x4a,0xc4,0x30,0x18,0x85,0xbf,0x67,0x93,0xc,0xd9,0x28,0xb9,0x41,0xcf,0x21,0x7a,0x28,0xdd,0xcd,0x5,0x14,0x57,0x73,0x28,0xe7,0x20,0xbd,0x41,0x70,0x5c,0x14,0x93,0xe,0xbf,0xb,0xdb,0x61,0x5a,0x5a,0x70,0xab,0xf,0x2,0x21,0xfc,0xf9,0xf2,0xde,0x23,0xf0,0xe7,0xa5,0xb5,0xc3,0x9c,0xf3,0xae,0x94,0xf2,0xda,0xf7,0xfd,0x13,0x40,0x8c,0xf1,0x10,0x42,0xd8,0xa7,0x94,0xbe,0x96,0xb3,0x6e,0x3,0x6c,0x92,0x4e,0x40,0x1,0x90,0xf4,0x1,0xd8,0xda,0xe0,0xc,0x90,0x73,0xde,0x1,0x66,0x66,0xc1,0xcc,0x9a,0xb,0xcd,0xcc,0x99,0x59,0xc8,0x39,0x3,0xe8,0xda,0xc9,0xc,0x50,0x4a,0x79,0x91,0xf4,0x69,0x66,0xcd,0x30,0xc,0xf,0x40,0x3,0x30,0xee,0x91,0x74,0x36,0xb3,0x5b,0xe0,0x79,0xb5,0x83,0xae,0xeb,0x6c,0xb2,0x3d,0x5e,0x9e,0x5c,0x9c,0xc7,0x5,0x10,0xda,0xb6,0xbd,0xdc,0xbb,0xd9,0xe8,0xe0,0xd7,0x9a,0x45,0x88,0x31,0x1e,0x24,0x9d,0xa6,0x8,0xb5,0xd6,0x47,0x0,0xef,0xfd,0xbb,0x73,0xee,0x78,0x15,0x61,0x1d,0x10,0x42,0xd8,0x33,0x96,0x8,0x50,0x6b,0xbd,0x7,0x70,0xce,0x1d,0xbd,0xf7,0x6f,0x92,0xa,0x8b,0xd8,0x33,0xc0,0xd4,0x6e,0xce,0x19,0x49,0x53,0x66,0x24,0xd,0x92,0x4a,0x4a,0xa9,0xb0,0xd0,0xd6,0x3f,0xd0,0x68,0x35,0xf0,0x63,0xe9,0x6e,0xf9,0xf2,0x3f,0xd2,0x37,0xb9,0xed,0x67,0x29,0x9e,0xb,0x7f,0x1a,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+};
+
+
static const unsigned char icon_close_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,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xd9,0xb,0x17,0x6,0x11,0xd,0x6a,0x1e,0x9a,0x6f,0x0,0x0,0x0,0x5e,0x49,0x44,0x41,0x54,0x38,0xcb,0xd5,0x53,0xcb,0xe,0xc0,0x30,0x8,0x12,0xb2,0xff,0xff,0x65,0x77,0x5a,0xb3,0x36,0xf8,0x48,0xcc,0xe,0xf3,0xd4,0x3,0xa2,0x40,0x85,0x9b,0xdb,0xa4,0x68,0xc3,0x1a,0x13,0x5c,0xcf,0x3,0x86,0xa5,0xc5,0xcd,0xa1,0xc0,0xa,0x43,0xd5,0xf4,0x6,0x56,0x3,0x36,0x9,0x11,0x49,0xb6,0x1d,0x54,0xa,0x6a,0x83,0x48,0x1a,0xbb,0xc0,0xc8,0x97,0x6f,0x62,0xac,0x4c,0x4c,0x9,0x4e,0xc3,0xaa,0x74,0xd8,0x89,0x2a,0x23,0x61,0xf7,0x23,0x85,0x11,0xff,0xff,0x98,0x6e,0x7,0x20,0x33,0x1a,0x5b,0xf5,0xcc,0xfe,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
};
+static const unsigned char icon_color_pick_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,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x11,0x0,0x0,0xb,0x11,0x1,0x7f,0x64,0x5f,0x91,0x0,0x0,0x0,0x18,0x74,0x45,0x58,0x74,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x0,0x70,0x61,0x69,0x6e,0x74,0x2e,0x6e,0x65,0x74,0x20,0x34,0x2e,0x30,0x2e,0x36,0xfc,0x8c,0x63,0xdf,0x0,0x0,0x1,0xf7,0x49,0x44,0x41,0x54,0x38,0x4f,0x8d,0x90,0xbd,0x6b,0x53,0x51,0x18,0xc6,0xaf,0x26,0xed,0x62,0x70,0x71,0xd0,0xc1,0x2f,0x70,0xa9,0xda,0x4d,0xc7,0x8e,0xd6,0x42,0xc5,0x52,0xa5,0x42,0xa1,0xa4,0xb6,0x20,0x75,0x50,0xf4,0x52,0x41,0x1d,0x6a,0x87,0x96,0xfe,0x1,0x42,0xa1,0x20,0x52,0x71,0x56,0x50,0xf3,0xd5,0x94,0x24,0xed,0x50,0x5d,0xc4,0x41,0xa9,0x70,0xd3,0xc4,0xe7,0x9c,0xa0,0xc5,0xf,0x1c,0x2,0x6,0x29,0x4d,0xe2,0x7d,0x7d,0x4e,0x72,0xc,0xe9,0x7,0xb5,0xf,0xfc,0x48,0xee,0xcd,0xf3,0x7b,0xcf,0x7b,0xe2,0xfc,0x2f,0xc5,0x62,0x31,0x98,0xc8,0xfd,0x8,0x5c,0x8c,0xa1,0xa5,0x3f,0x81,0xe0,0x8d,0x14,0x4e,0xdc,0xcd,0x60,0x6a,0x64,0x1e,0x3,0x3d,0x31,0x84,0x6c,0x6d,0x6b,0x6,0xe6,0x10,0x1c,0x4a,0xe2,0xc0,0xf3,0x8f,0xab,0x7b,0x87,0x53,0x2a,0x40,0xf9,0x24,0xe5,0xa7,0xf7,0x17,0xf0,0xe7,0x5e,0x6,0x55,0x3e,0x7f,0xee,0x8c,0xe0,0xa0,0xad,0x3b,0x8e,0x88,0x34,0x30,0x19,0x4c,0x22,0x70,0x2b,0x85,0xa3,0x7d,0x71,0x1c,0xb9,0x1c,0x47,0x68,0x34,0x8d,0x35,0xca,0xe2,0xa6,0x21,0xe1,0x39,0xf8,0x5d,0x11,0xac,0x9f,0x8b,0xe0,0x71,0xad,0x6c,0xd2,0x2c,0x9b,0xf4,0xc6,0x70,0xfc,0xda,0x3c,0xd6,0x2e,0xc5,0xf0,0x75,0x38,0x89,0x99,0xb1,0x5,0xf8,0x77,0xd2,0xf0,0xaf,0xc4,0x51,0x3d,0x1f,0x41,0x99,0xb2,0x22,0xa7,0x6d,0x7d,0xeb,0x0,0x9e,0x70,0xa6,0x27,0x8a,0x32,0xd7,0x14,0x6e,0x20,0xdc,0xc0,0xe7,0xea,0x3e,0x4f,0x2f,0x71,0xc0,0x7,0xca,0x61,0xd2,0x62,0xeb,0xf5,0x1,0xcd,0x59,0xfe,0xa4,0xdd,0x47,0x6f,0x21,0xdd,0x51,0xf8,0x1c,0xe2,0xf3,0x2a,0xc2,0x3f,0xce,0x6c,0xf0,0x8e,0xc3,0x7,0x29,0xef,0xb3,0xd5,0x7a,0x9a,0x7,0x14,0xa,0x85,0x3e,0x52,0xc9,0x2b,0x5d,0x19,0x5d,0xc4,0x2c,0xcb,0x25,0xb3,0x9,0x87,0xc9,0x85,0x28,0xbe,0xf3,0xfb,0x31,0xbe,0xdb,0x63,0xeb,0xf5,0xfc,0xbb,0x2,0xc5,0xe,0x52,0x22,0x42,0x6e,0xba,0x8b,0xd8,0x3f,0xf5,0x46,0xe5,0x79,0xaa,0x50,0x32,0x54,0x49,0xe7,0xb6,0x3,0x28,0xb4,0x91,0xa2,0x95,0x27,0x49,0x90,0x3c,0xcb,0x42,0xcb,0xf8,0x92,0xfa,0x6d,0x65,0x9f,0xbc,0x22,0xad,0x56,0xad,0x87,0xc5,0x10,0xf1,0x88,0x91,0x9f,0x90,0x9a,0x6c,0x9f,0x7f,0x26,0x96,0xf5,0x59,0x4a,0x2e,0x79,0x49,0x4e,0x91,0x8d,0x1b,0xb0,0xf4,0x42,0xe7,0xb5,0x60,0x36,0xb7,0x8a,0xeb,0x5e,0xb8,0x49,0x36,0xd7,0xe9,0x30,0x1b,0x1a,0x89,0xb4,0x6e,0x27,0xf7,0xea,0xf7,0x4a,0x30,0xb1,0x52,0x46,0xd8,0x2b,0xe3,0x41,0xf6,0xcb,0x66,0x79,0x33,0x1b,0xc2,0x92,0xa7,0x1e,0xe6,0x4,0x57,0xbd,0x75,0xb8,0xd9,0x5f,0x5a,0xeb,0x1d,0x65,0x43,0x23,0x2c,0xb5,0xab,0xc,0x4,0x23,0x9e,0xe0,0xb6,0x57,0xd1,0x2b,0x35,0xf9,0xdb,0x4e,0xb2,0xa1,0x11,0x16,0xf,0x61,0x3a,0x57,0x55,0xaf,0x61,0x44,0x43,0x8a,0x1c,0xb6,0x3f,0xef,0x2e,0x14,0xda,0xc9,0x98,0xf9,0xb4,0xaf,0x76,0x19,0xc7,0xf9,0xb,0x8e,0xb3,0xf3,0x95,0xda,0x15,0xd3,0x79,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+};
+
+
static const unsigned char icon_folder_png[]={
0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0xf,0x14,0x33,0x39,0x1,0xd2,0x43,0x4c,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x36,0x49,0x44,0x41,0x54,0x38,0x8d,0xc5,0x92,0xcd,0x4a,0xc3,0x40,0x14,0x85,0xbf,0x7b,0x67,0x12,0x48,0x3,0x12,0x62,0x45,0xfa,0x30,0x7d,0x5,0x5d,0xfa,0x8,0xbe,0x88,0x3e,0x45,0x5f,0xc1,0x9d,0x4b,0x77,0x3e,0x81,0x2e,0xa4,0x15,0xa5,0x10,0xb2,0xc8,0xa2,0x9b,0x41,0x2c,0x62,0x4c,0x66,0x5c,0x34,0x8a,0x3f,0x95,0x26,0x2b,0xf,0xc,0xcc,0x9d,0x3b,0xe7,0xce,0x39,0x87,0x81,0xff,0x86,0x14,0x45,0x11,0xb6,0x35,0xe2,0x38,0xbe,0x9c,0x4c,0x26,0x47,0xce,0xb9,0x78,0x4b,0x3b,0x64,0x59,0xf6,0x6,0x20,0x65,0x59,0x56,0xde,0xfb,0x43,0x40,0x80,0x0,0x34,0xdd,0xa5,0x28,0x49,0x92,0x73,0x11,0x79,0xf9,0x49,0x16,0x91,0xd5,0x78,0x3c,0x9e,0x1,0x58,0x63,0x4c,0xe9,0xbd,0x3f,0x0,0xc,0x20,0xa3,0xd1,0xe8,0x2c,0x84,0x10,0x1,0x88,0xc8,0x6b,0x37,0xf8,0x9b,0xea,0x10,0xc2,0xa7,0x2a,0xa9,0xaa,0xea,0xa2,0xae,0xeb,0x63,0x40,0xd3,0x34,0x3d,0x5d,0xaf,0xd7,0xb3,0xde,0xfe,0x45,0x9e,0xd4,0x18,0x53,0x0,0x1e,0xd0,0x10,0x42,0xda,0x97,0xc,0x78,0x55,0xad,0x54,0x44,0x96,0x80,0xfd,0xf0,0x37,0x64,0x80,0x31,0x66,0xa1,0xaa,0xfa,0x8,0x68,0x77,0xb8,0x7,0xd4,0x83,0x6,0x88,0xc8,0x3,0x80,0x31,0x66,0xde,0x34,0xcd,0x94,0x4d,0x98,0x7d,0x10,0xab,0xea,0xad,0xe6,0x79,0xbe,0x4,0x88,0xa2,0xe8,0xba,0xae,0xeb,0xe9,0x17,0x35,0x3b,0xa1,0xaa,0x37,0xf6,0x4b,0x71,0x7,0x24,0x7d,0xc9,0x0,0x79,0x9e,0xcf,0x2d,0x80,0x88,0x3c,0xf,0x79,0x99,0x4d,0xd8,0x1e,0xba,0xf4,0x55,0x75,0xd5,0xed,0xdb,0x6e,0xed,0x42,0x63,0xad,0xbd,0x7,0xb0,0xce,0x39,0x6d,0xdb,0xf6,0x44,0x55,0x17,0x49,0x92,0xec,0xff,0xf1,0xfb,0x7e,0x29,0x50,0xd5,0x2b,0xe7,0x9c,0x8,0x80,0x73,0xce,0x74,0x92,0xa2,0x1,0x36,0xda,0x2c,0xcb,0xda,0x77,0xe3,0x5,0x64,0xf1,0xba,0x53,0xe9,0x44,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
};
@@ -194,6 +204,11 @@ static const unsigned char icon_play_png[]={
};
+static const unsigned char icon_reload_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,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x12,0x0,0x0,0xb,0x12,0x1,0xd2,0xdd,0x7e,0xfc,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x94,0x49,0x44,0x41,0x54,0x38,0x8d,0x85,0xd3,0xbd,0x6a,0x55,0x41,0x14,0xc5,0xf1,0xdf,0xb9,0x1f,0x91,0x20,0x5a,0x89,0xd8,0x8,0x4b,0xd0,0x42,0x1f,0xc0,0x42,0x4,0x4b,0xb,0x1b,0x9b,0xbc,0x80,0x58,0x45,0xc5,0x56,0x51,0x50,0x6b,0x21,0x9d,0xa5,0x6f,0x20,0x88,0x20,0xa8,0xad,0xa8,0xa0,0x2f,0x60,0x21,0xe8,0x4e,0x63,0xa9,0x85,0x22,0x31,0x37,0x37,0xb1,0xb8,0x73,0xc2,0xf1,0x23,0x38,0xd5,0x9c,0x61,0xaf,0x3d,0x7b,0xfe,0x6b,0x9d,0xce,0x1e,0xab,0xaa,0xc6,0x18,0xa1,0xc3,0xe,0xb6,0x92,0xec,0xfc,0x59,0x37,0xda,0x43,0x8,0xc7,0x70,0x9,0x37,0xb0,0xd2,0xd7,0x56,0x55,0x57,0x55,0xbb,0xf5,0xdd,0x1f,0xe2,0xae,0x9,0x9f,0xe2,0x24,0xb6,0x6,0x97,0x8c,0xf0,0x32,0xc9,0xb9,0xaa,0x9a,0x62,0x96,0x64,0xd1,0xa0,0x75,0x1c,0xe3,0x2,0x9e,0x34,0xc1,0x2b,0x3c,0xc6,0x3a,0x8e,0xe3,0x76,0xab,0x59,0xc6,0x41,0xfc,0xc0,0xbc,0x6f,0x30,0xc6,0x61,0x7c,0x6e,0xe2,0x53,0x49,0xde,0x57,0xd5,0x12,0xb6,0xd1,0x25,0x99,0x55,0xd5,0x3,0xac,0x36,0x1e,0xd3,0x5d,0x6,0x49,0xe6,0x78,0xd4,0xc4,0xe7,0xf1,0xa9,0x9d,0x6f,0x26,0xd9,0xc2,0xac,0x7d,0x5f,0xc1,0x73,0xcc,0xab,0xea,0x7a,0x55,0x4d,0x7b,0x30,0x37,0x71,0x6,0xdf,0x70,0x34,0xc9,0xc6,0x90,0x4d,0x92,0x21,0xa3,0x15,0xec,0xc3,0x6a,0x92,0x59,0x57,0x55,0x13,0x4c,0xdb,0x9b,0x36,0x92,0x2c,0x57,0xd5,0xb8,0x4d,0xf5,0xcf,0x55,0x55,0x33,0x4c,0x92,0x74,0xa3,0x46,0x7a,0x8e,0x13,0x38,0xd8,0x1a,0xfe,0x53,0x3c,0xb0,0xef,0x4b,0xbf,0x19,0xb5,0xf1,0x36,0xf1,0x31,0xc9,0xcc,0x22,0x34,0xff,0x5b,0x87,0xf1,0x95,0xbf,0x73,0xb0,0x86,0x5b,0xf8,0x89,0xed,0xfe,0xed,0x83,0xdb,0x97,0x70,0x19,0x6b,0x78,0x88,0xab,0xbd,0x8d,0x13,0x9c,0xc6,0x6b,0xac,0x27,0x49,0xb3,0x70,0x96,0x64,0xa7,0xc1,0x9b,0xe0,0x90,0x66,0x75,0x92,0xae,0xaa,0xba,0xde,0xc6,0xad,0x24,0x6f,0xf0,0xc,0x47,0xaa,0xea,0x3b,0x2e,0xe,0xb2,0xbf,0xdf,0x22,0xd2,0x7d,0x4e,0xce,0xb7,0x34,0xee,0xec,0x26,0x71,0x60,0xd5,0x5d,0xdc,0xb1,0x0,0xd9,0xff,0x17,0x2c,0xb2,0x30,0xc5,0x59,0xbc,0xee,0xeb,0xfb,0x9,0x86,0x84,0xef,0xe1,0x0,0xee,0xe3,0x2d,0x3e,0xe0,0x5,0xae,0x25,0xe9,0xf0,0x6e,0xc8,0xe6,0x37,0x88,0x3,0x58,0x1d,0xc6,0x2d,0x85,0xfd,0xf9,0x92,0x85,0x5b,0x86,0xd,0x7e,0x1,0x82,0x4c,0xaa,0x69,0x77,0x3c,0x4b,0x15,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+};
+
+
static const unsigned char icon_stop_png[]={
0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0xf,0x14,0x33,0x24,0x62,0xd4,0x2f,0x95,0x0,0x0,0x0,0x39,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0xa0,0x6,0xf8,0xf0,0xe1,0x3,0x33,0xb9,0x7a,0x18,0x61,0x2,0xf,0x1f,0x3e,0xfc,0x4f,0x8a,0x1,0xf2,0xf2,0xf2,0x8c,0xc,0xc,0xc,0xc,0x4c,0xa4,0xda,0x8c,0xe,0x46,0xd,0x18,0x35,0x60,0x70,0x18,0xc0,0xc0,0xc0,0x40,0x59,0x66,0xa2,0x18,0x0,0x0,0x2a,0xc7,0xf,0x64,0xd5,0xe,0x11,0x85,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
};
@@ -394,6 +409,11 @@ static const unsigned char tab_behind_png[]={
};
+static const unsigned char tab_close_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,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x12,0x0,0x0,0xb,0x12,0x1,0xd2,0xdd,0x7e,0xfc,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x1b,0x49,0x44,0x41,0x54,0x38,0x8d,0xcd,0x52,0xbb,0x4e,0xc4,0x40,0xc,0x9c,0x73,0xd2,0x50,0x38,0xd1,0x8a,0x82,0x36,0x3d,0x8,0xc4,0x43,0x88,0x13,0x12,0x20,0xf8,0x67,0x8a,0xfb,0x1,0xe,0x89,0x13,0x3d,0x47,0xb1,0x7f,0xb0,0x85,0x53,0x41,0xce,0xa6,0xd9,0x45,0xbe,0x24,0x1f,0x70,0x96,0x56,0x96,0xed,0x9d,0x91,0x3d,0x36,0x70,0x50,0x96,0x52,0xaa,0xbd,0x1f,0xd5,0xaa,0xb9,0x1a,0x79,0xb0,0x99,0x9d,0xc4,0x18,0x4d,0x55,0x2f,0xfd,0xc7,0x94,0x12,0xa9,0xea,0x53,0x8c,0xd1,0xcc,0xac,0xf1,0xb5,0x85,0x67,0x8b,0x31,0x1a,0x0,0x5,0x40,0xcc,0x7c,0x4b,0x44,0x9f,0x0,0x54,0x55,0x5f,0x44,0x64,0x5,0x60,0x7,0xa0,0xea,0xba,0x6e,0x31,0x21,0x48,0x29,0xd5,0xaa,0x7a,0x25,0x22,0xef,0x25,0xc7,0xcc,0x4b,0x33,0xb,0x7d,0xdf,0xbf,0xba,0xdc,0x29,0x11,0x7d,0x85,0x10,0x86,0x49,0x7,0x99,0xe4,0x5a,0x44,0xd6,0x73,0x1a,0x65,0xf0,0x77,0x8,0xe1,0x67,0xa2,0x1,0x0,0x84,0x10,0x6,0x22,0xda,0x30,0xf3,0x7d,0x4e,0x59,0x7e,0x60,0xe6,0xb,0x22,0xda,0x7a,0xf0,0x84,0x20,0x9b,0x9a,0x59,0xeb,0xe2,0xd2,0x65,0x53,0xc8,0x30,0x53,0x2c,0x23,0x54,0xaa,0xfa,0x9c,0x5,0x9b,0x1b,0xe1,0x8e,0x88,0x36,0x65,0xfe,0xbd,0xe,0x32,0xf8,0xd1,0x83,0x99,0xf9,0x9c,0x99,0x1f,0x4a,0x2c,0x22,0xeb,0xf1,0x8a,0xe7,0xd6,0xb8,0x3,0x50,0x65,0xc1,0xb6,0x0,0x4c,0x55,0x6f,0x44,0xe4,0xd,0xc0,0x0,0xa0,0xf6,0x6b,0xdc,0x3b,0xa4,0xa6,0x69,0x8e,0x33,0xf8,0x2c,0xab,0xfd,0x9b,0x85,0xfd,0x60,0xe6,0x25,0x80,0xaa,0x6d,0xdb,0xa3,0xb9,0x4b,0xfd,0x27,0xf1,0x7e,0xac,0x8f,0xf7,0x87,0x63,0x7f,0xc3,0xca,0xa9,0x49,0x35,0x25,0x97,0x14,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+};
+
+
static const unsigned char tab_container_bg_png[]={
0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0xa,0x45,0x69,0x43,0x43,0x50,0x49,0x43,0x43,0x20,0x70,0x72,0x6f,0x66,0x69,0x6c,0x65,0x0,0x0,0x78,0xda,0x9d,0x53,0x67,0x54,0x53,0xe9,0x16,0x3d,0xf7,0xde,0xf4,0x42,0x4b,0x88,0x80,0x94,0x4b,0x6f,0x52,0x15,0x8,0x20,0x52,0x42,0x8b,0x80,0x14,0x91,0x26,0x2a,0x21,0x9,0x10,0x4a,0x88,0x21,0xa1,0xd9,0x15,0x51,0xc1,0x11,0x45,0x45,0x4,0x1b,0xc8,0xa0,0x88,0x3,0x8e,0x8e,0x80,0x8c,0x15,0x51,0x2c,0xc,0x8a,0xa,0xd8,0x7,0xe4,0x21,0xa2,0x8e,0x83,0xa3,0x88,0x8a,0xca,0xfb,0xe1,0x7b,0xa3,0x6b,0xd6,0xbc,0xf7,0xe6,0xcd,0xfe,0xb5,0xd7,0x3e,0xe7,0xac,0xf3,0x9d,0xb3,0xcf,0x7,0xc0,0x8,0xc,0x96,0x48,0x33,0x51,0x35,0x80,0xc,0xa9,0x42,0x1e,0x11,0xe0,0x83,0xc7,0xc4,0xc6,0xe1,0xe4,0x2e,0x40,0x81,0xa,0x24,0x70,0x0,0x10,0x8,0xb3,0x64,0x21,0x73,0xfd,0x23,0x1,0x0,0xf8,0x7e,0x3c,0x3c,0x2b,0x22,0xc0,0x7,0xbe,0x0,0x1,0x78,0xd3,0xb,0x8,0x0,0xc0,0x4d,0x9b,0xc0,0x30,0x1c,0x87,0xff,0xf,0xea,0x42,0x99,0x5c,0x1,0x80,0x84,0x1,0xc0,0x74,0x91,0x38,0x4b,0x8,0x80,0x14,0x0,0x40,0x7a,0x8e,0x42,0xa6,0x0,0x40,0x46,0x1,0x80,0x9d,0x98,0x26,0x53,0x0,0xa0,0x4,0x0,0x60,0xcb,0x63,0x62,0xe3,0x0,0x50,0x2d,0x0,0x60,0x27,0x7f,0xe6,0xd3,0x0,0x80,0x9d,0xf8,0x99,0x7b,0x1,0x0,0x5b,0x94,0x21,0x15,0x1,0xa0,0x91,0x0,0x20,0x13,0x65,0x88,0x44,0x0,0x68,0x3b,0x0,0xac,0xcf,0x56,0x8a,0x45,0x0,0x58,0x30,0x0,0x14,0x66,0x4b,0xc4,0x39,0x0,0xd8,0x2d,0x0,0x30,0x49,0x57,0x66,0x48,0x0,0xb0,0xb7,0x0,0xc0,0xce,0x10,0xb,0xb2,0x0,0x8,0xc,0x0,0x30,0x51,0x88,0x85,0x29,0x0,0x4,0x7b,0x0,0x60,0xc8,0x23,0x23,0x78,0x0,0x84,0x99,0x0,0x14,0x46,0xf2,0x57,0x3c,0xf1,0x2b,0xae,0x10,0xe7,0x2a,0x0,0x0,0x78,0x99,0xb2,0x3c,0xb9,0x24,0x39,0x45,0x81,0x5b,0x8,0x2d,0x71,0x7,0x57,0x57,0x2e,0x1e,0x28,0xce,0x49,0x17,0x2b,0x14,0x36,0x61,0x2,0x61,0x9a,0x40,0x2e,0xc2,0x79,0x99,0x19,0x32,0x81,0x34,0xf,0xe0,0xf3,0xcc,0x0,0x0,0xa0,0x91,0x15,0x11,0xe0,0x83,0xf3,0xfd,0x78,0xce,0xe,0xae,0xce,0xce,0x36,0x8e,0xb6,0xe,0x5f,0x2d,0xea,0xbf,0x6,0xff,0x22,0x62,0x62,0xe3,0xfe,0xe5,0xcf,0xab,0x70,0x40,0x0,0x0,0xe1,0x74,0x7e,0xd1,0xfe,0x2c,0x2f,0xb3,0x1a,0x80,0x3b,0x6,0x80,0x6d,0xfe,0xa2,0x25,0xee,0x4,0x68,0x5e,0xb,0xa0,0x75,0xf7,0x8b,0x66,0xb2,0xf,0x40,0xb5,0x0,0xa0,0xe9,0xda,0x57,0xf3,0x70,0xf8,0x7e,0x3c,0x3c,0x45,0xa1,0x90,0xb9,0xd9,0xd9,0xe5,0xe4,0xe4,0xd8,0x4a,0xc4,0x42,0x5b,0x61,0xca,0x57,0x7d,0xfe,0x67,0xc2,0x5f,0xc0,0x57,0xfd,0x6c,0xf9,0x7e,0x3c,0xfc,0xf7,0xf5,0xe0,0xbe,0xe2,0x24,0x81,0x32,0x5d,0x81,0x47,0x4,0xf8,0xe0,0xc2,0xcc,0xf4,0x4c,0xa5,0x1c,0xcf,0x92,0x9,0x84,0x62,0xdc,0xe6,0x8f,0x47,0xfc,0xb7,0xb,0xff,0xfc,0x1d,0xd3,0x22,0xc4,0x49,0x62,0xb9,0x58,0x2a,0x14,0xe3,0x51,0x12,0x71,0x8e,0x44,0x9a,0x8c,0xf3,0x32,0xa5,0x22,0x89,0x42,0x92,0x29,0xc5,0x25,0xd2,0xff,0x64,0xe2,0xdf,0x2c,0xfb,0x3,0x3e,0xdf,0x35,0x0,0xb0,0x6a,0x3e,0x1,0x7b,0x91,0x2d,0xa8,0x5d,0x63,0x3,0xf6,0x4b,0x27,0x10,0x58,0x74,0xc0,0xe2,0xf7,0x0,0x0,0xf2,0xbb,0x6f,0xc1,0xd4,0x28,0x8,0x3,0x80,0x68,0x83,0xe1,0xcf,0x77,0xff,0xef,0x3f,0xfd,0x47,0xa0,0x25,0x0,0x80,0x66,0x49,0x92,0x71,0x0,0x0,0x5e,0x44,0x24,0x2e,0x54,0xca,0xb3,0x3f,0xc7,0x8,0x0,0x0,0x44,0xa0,0x81,0x2a,0xb0,0x41,0x1b,0xf4,0xc1,0x18,0x2c,0xc0,0x6,0x1c,0xc1,0x5,0xdc,0xc1,0xb,0xfc,0x60,0x36,0x84,0x42,0x24,0xc4,0xc2,0x42,0x10,0x42,0xa,0x64,0x80,0x1c,0x72,0x60,0x29,0xac,0x82,0x42,0x28,0x86,0xcd,0xb0,0x1d,0x2a,0x60,0x2f,0xd4,0x40,0x1d,0x34,0xc0,0x51,0x68,0x86,0x93,0x70,0xe,0x2e,0xc2,0x55,0xb8,0xe,0x3d,0x70,0xf,0xfa,0x61,0x8,0x9e,0xc1,0x28,0xbc,0x81,0x9,0x4,0x41,0xc8,0x8,0x13,0x61,0x21,0xda,0x88,0x1,0x62,0x8a,0x58,0x23,0x8e,0x8,0x17,0x99,0x85,0xf8,0x21,0xc1,0x48,0x4,0x12,0x8b,0x24,0x20,0xc9,0x88,0x14,0x51,0x22,0x4b,0x91,0x35,0x48,0x31,0x52,0x8a,0x54,0x20,0x55,0x48,0x1d,0xf2,0x3d,0x72,0x2,0x39,0x87,0x5c,0x46,0xba,0x91,0x3b,0xc8,0x0,0x32,0x82,0xfc,0x86,0xbc,0x47,0x31,0x94,0x81,0xb2,0x51,0x3d,0xd4,0xc,0xb5,0x43,0xb9,0xa8,0x37,0x1a,0x84,0x46,0xa2,0xb,0xd0,0x64,0x74,0x31,0x9a,0x8f,0x16,0xa0,0x9b,0xd0,0x72,0xb4,0x1a,0x3d,0x8c,0x36,0xa1,0xe7,0xd0,0xab,0x68,0xf,0xda,0x8f,0x3e,0x43,0xc7,0x30,0xc0,0xe8,0x18,0x7,0x33,0xc4,0x6c,0x30,0x2e,0xc6,0xc3,0x42,0xb1,0x38,0x2c,0x9,0x93,0x63,0xcb,0xb1,0x22,0xac,0xc,0xab,0xc6,0x1a,0xb0,0x56,0xac,0x3,0xbb,0x89,0xf5,0x63,0xcf,0xb1,0x77,0x4,0x12,0x81,0x45,0xc0,0x9,0x36,0x4,0x77,0x42,0x20,0x61,0x1e,0x41,0x48,0x58,0x4c,0x58,0x4e,0xd8,0x48,0xa8,0x20,0x1c,0x24,0x34,0x11,0xda,0x9,0x37,0x9,0x3,0x84,0x51,0xc2,0x27,0x22,0x93,0xa8,0x4b,0xb4,0x26,0xba,0x11,0xf9,0xc4,0x18,0x62,0x32,0x31,0x87,0x58,0x48,0x2c,0x23,0xd6,0x12,0x8f,0x13,0x2f,0x10,0x7b,0x88,0x43,0xc4,0x37,0x24,0x12,0x89,0x43,0x32,0x27,0xb9,0x90,0x2,0x49,0xb1,0xa4,0x54,0xd2,0x12,0xd2,0x46,0xd2,0x6e,0x52,0x23,0xe9,0x2c,0xa9,0x9b,0x34,0x48,0x1a,0x23,0x93,0xc9,0xda,0x64,0x6b,0xb2,0x7,0x39,0x94,0x2c,0x20,0x2b,0xc8,0x85,0xe4,0x9d,0xe4,0xc3,0xe4,0x33,0xe4,0x1b,0xe4,0x21,0xf2,0x5b,0xa,0x9d,0x62,0x40,0x71,0xa4,0xf8,0x53,0xe2,0x28,0x52,0xca,0x6a,0x4a,0x19,0xe5,0x10,0xe5,0x34,0xe5,0x6,0x65,0x98,0x32,0x41,0x55,0xa3,0x9a,0x52,0xdd,0xa8,0xa1,0x54,0x11,0x35,0x8f,0x5a,0x42,0xad,0xa1,0xb6,0x52,0xaf,0x51,0x87,0xa8,0x13,0x34,0x75,0x9a,0x39,0xcd,0x83,0x16,0x49,0x4b,0xa5,0xad,0xa2,0x95,0xd3,0x1a,0x68,0x17,0x68,0xf7,0x69,0xaf,0xe8,0x74,0xba,0x11,0xdd,0x95,0x1e,0x4e,0x97,0xd0,0x57,0xd2,0xcb,0xe9,0x47,0xe8,0x97,0xe8,0x3,0xf4,0x77,0xc,0xd,0x86,0x15,0x83,0xc7,0x88,0x67,0x28,0x19,0x9b,0x18,0x7,0x18,0x67,0x19,0x77,0x18,0xaf,0x98,0x4c,0xa6,0x19,0xd3,0x8b,0x19,0xc7,0x54,0x30,0x37,0x31,0xeb,0x98,0xe7,0x99,0xf,0x99,0x6f,0x55,0x58,0x2a,0xb6,0x2a,0x7c,0x15,0x91,0xca,0xa,0x95,0x4a,0x95,0x26,0x95,0x1b,0x2a,0x2f,0x54,0xa9,0xaa,0xa6,0xaa,0xde,0xaa,0xb,0x55,0xf3,0x55,0xcb,0x54,0x8f,0xa9,0x5e,0x53,0x7d,0xae,0x46,0x55,0x33,0x53,0xe3,0xa9,0x9,0xd4,0x96,0xab,0x55,0xaa,0x9d,0x50,0xeb,0x53,0x1b,0x53,0x67,0xa9,0x3b,0xa8,0x87,0xaa,0x67,0xa8,0x6f,0x54,0x3f,0xa4,0x7e,0x59,0xfd,0x89,0x6,0x59,0xc3,0x4c,0xc3,0x4f,0x43,0xa4,0x51,0xa0,0xb1,0x5f,0xe3,0xbc,0xc6,0x20,0xb,0x63,0x19,0xb3,0x78,0x2c,0x21,0x6b,0xd,0xab,0x86,0x75,0x81,0x35,0xc4,0x26,0xb1,0xcd,0xd9,0x7c,0x76,0x2a,0xbb,0x98,0xfd,0x1d,0xbb,0x8b,0x3d,0xaa,0xa9,0xa1,0x39,0x43,0x33,0x4a,0x33,0x57,0xb3,0x52,0xf3,0x94,0x66,0x3f,0x7,0xe3,0x98,0x71,0xf8,0x9c,0x74,0x4e,0x9,0xe7,0x28,0xa7,0x97,0xf3,0x7e,0x8a,0xde,0x14,0xef,0x29,0xe2,0x29,0x1b,0xa6,0x34,0x4c,0xb9,0x31,0x65,0x5c,0x6b,0xaa,0x96,0x97,0x96,0x58,0xab,0x48,0xab,0x51,0xab,0x47,0xeb,0xbd,0x36,0xae,0xed,0xa7,0x9d,0xa6,0xbd,0x45,0xbb,0x59,0xfb,0x81,0xe,0x41,0xc7,0x4a,0x27,0x5c,0x27,0x47,0x67,0x8f,0xce,0x5,0x9d,0xe7,0x53,0xd9,0x53,0xdd,0xa7,0xa,0xa7,0x16,0x4d,0x3d,0x3a,0xf5,0xae,0x2e,0xaa,0x6b,0xa5,0x1b,0xa1,0xbb,0x44,0x77,0xbf,0x6e,0xa7,0xee,0x98,0x9e,0xbe,0x5e,0x80,0x9e,0x4c,0x6f,0xa7,0xde,0x79,0xbd,0xe7,0xfa,0x1c,0x7d,0x2f,0xfd,0x54,0xfd,0x6d,0xfa,0xa7,0xf5,0x47,0xc,0x58,0x6,0xb3,0xc,0x24,0x6,0xdb,0xc,0xce,0x18,0x3c,0xc5,0x35,0x71,0x6f,0x3c,0x1d,0x2f,0xc7,0xdb,0xf1,0x51,0x43,0x5d,0xc3,0x40,0x43,0xa5,0x61,0x95,0x61,0x97,0xe1,0x84,0x91,0xb9,0xd1,0x3c,0xa3,0xd5,0x46,0x8d,0x46,0xf,0x8c,0x69,0xc6,0x5c,0xe3,0x24,0xe3,0x6d,0xc6,0x6d,0xc6,0xa3,0x26,0x6,0x26,0x21,0x26,0x4b,0x4d,0xea,0x4d,0xee,0x9a,0x52,0x4d,0xb9,0xa6,0x29,0xa6,0x3b,0x4c,0x3b,0x4c,0xc7,0xcd,0xcc,0xcd,0xa2,0xcd,0xd6,0x99,0x35,0x9b,0x3d,0x31,0xd7,0x32,0xe7,0x9b,0xe7,0x9b,0xd7,0x9b,0xdf,0xb7,0x60,0x5a,0x78,0x5a,0x2c,0xb6,0xa8,0xb6,0xb8,0x65,0x49,0xb2,0xe4,0x5a,0xa6,0x59,0xee,0xb6,0xbc,0x6e,0x85,0x5a,0x39,0x59,0xa5,0x58,0x55,0x5a,0x5d,0xb3,0x46,0xad,0x9d,0xad,0x25,0xd6,0xbb,0xad,0xbb,0xa7,0x11,0xa7,0xb9,0x4e,0x93,0x4e,0xab,0x9e,0xd6,0x67,0xc3,0xb0,0xf1,0xb6,0xc9,0xb6,0xa9,0xb7,0x19,0xb0,0xe5,0xd8,0x6,0xdb,0xae,0xb6,0x6d,0xb6,0x7d,0x61,0x67,0x62,0x17,0x67,0xb7,0xc5,0xae,0xc3,0xee,0x93,0xbd,0x93,0x7d,0xba,0x7d,0x8d,0xfd,0x3d,0x7,0xd,0x87,0xd9,0xe,0xab,0x1d,0x5a,0x1d,0x7e,0x73,0xb4,0x72,0x14,0x3a,0x56,0x3a,0xde,0x9a,0xce,0x9c,0xee,0x3f,0x7d,0xc5,0xf4,0x96,0xe9,0x2f,0x67,0x58,0xcf,0x10,0xcf,0xd8,0x33,0xe3,0xb6,0x13,0xcb,0x29,0xc4,0x69,0x9d,0x53,0x9b,0xd3,0x47,0x67,0x17,0x67,0xb9,0x73,0x83,0xf3,0x88,0x8b,0x89,0x4b,0x82,0xcb,0x2e,0x97,0x3e,0x2e,0x9b,0x1b,0xc6,0xdd,0xc8,0xbd,0xe4,0x4a,0x74,0xf5,0x71,0x5d,0xe1,0x7a,0xd2,0xf5,0x9d,0x9b,0xb3,0x9b,0xc2,0xed,0xa8,0xdb,0xaf,0xee,0x36,0xee,0x69,0xee,0x87,0xdc,0x9f,0xcc,0x34,0x9f,0x29,0x9e,0x59,0x33,0x73,0xd0,0xc3,0xc8,0x43,0xe0,0x51,0xe5,0xd1,0x3f,0xb,0x9f,0x95,0x30,0x6b,0xdf,0xac,0x7e,0x4f,0x43,0x4f,0x81,0x67,0xb5,0xe7,0x23,0x2f,0x63,0x2f,0x91,0x57,0xad,0xd7,0xb0,0xb7,0xa5,0x77,0xaa,0xf7,0x61,0xef,0x17,0x3e,0xf6,0x3e,0x72,0x9f,0xe3,0x3e,0xe3,0x3c,0x37,0xde,0x32,0xde,0x59,0x5f,0xcc,0x37,0xc0,0xb7,0xc8,0xb7,0xcb,0x4f,0xc3,0x6f,0x9e,0x5f,0x85,0xdf,0x43,0x7f,0x23,0xff,0x64,0xff,0x7a,0xff,0xd1,0x0,0xa7,0x80,0x25,0x1,0x67,0x3,0x89,0x81,0x41,0x81,0x5b,0x2,0xfb,0xf8,0x7a,0x7c,0x21,0xbf,0x8e,0x3f,0x3a,0xdb,0x65,0xf6,0xb2,0xd9,0xed,0x41,0x8c,0xa0,0xb9,0x41,0x15,0x41,0x8f,0x82,0xad,0x82,0xe5,0xc1,0xad,0x21,0x68,0xc8,0xec,0x90,0xad,0x21,0xf7,0xe7,0x98,0xce,0x91,0xce,0x69,0xe,0x85,0x50,0x7e,0xe8,0xd6,0xd0,0x7,0x61,0xe6,0x61,0x8b,0xc3,0x7e,0xc,0x27,0x85,0x87,0x85,0x57,0x86,0x3f,0x8e,0x70,0x88,0x58,0x1a,0xd1,0x31,0x97,0x35,0x77,0xd1,0xdc,0x43,0x73,0xdf,0x44,0xfa,0x44,0x96,0x44,0xde,0x9b,0x67,0x31,0x4f,0x39,0xaf,0x2d,0x4a,0x35,0x2a,0x3e,0xaa,0x2e,0x6a,0x3c,0xda,0x37,0xba,0x34,0xba,0x3f,0xc6,0x2e,0x66,0x59,0xcc,0xd5,0x58,0x9d,0x58,0x49,0x6c,0x4b,0x1c,0x39,0x2e,0x2a,0xae,0x36,0x6e,0x6c,0xbe,0xdf,0xfc,0xed,0xf3,0x87,0xe2,0x9d,0xe2,0xb,0xe3,0x7b,0x17,0x98,0x2f,0xc8,0x5d,0x70,0x79,0xa1,0xce,0xc2,0xf4,0x85,0xa7,0x16,0xa9,0x2e,0x12,0x2c,0x3a,0x96,0x40,0x4c,0x88,0x4e,0x38,0x94,0xf0,0x41,0x10,0x2a,0xa8,0x16,0x8c,0x25,0xf2,0x13,0x77,0x25,0x8e,0xa,0x79,0xc2,0x1d,0xc2,0x67,0x22,0x2f,0xd1,0x36,0xd1,0x88,0xd8,0x43,0x5c,0x2a,0x1e,0x4e,0xf2,0x48,0x2a,0x4d,0x7a,0x92,0xec,0x91,0xbc,0x35,0x79,0x24,0xc5,0x33,0xa5,0x2c,0xe5,0xb9,0x84,0x27,0xa9,0x90,0xbc,0x4c,0xd,0x4c,0xdd,0x9b,0x3a,0x9e,0x16,0x9a,0x76,0x20,0x6d,0x32,0x3d,0x3a,0xbd,0x31,0x83,0x92,0x91,0x90,0x71,0x42,0xaa,0x21,0x4d,0x93,0xb6,0x67,0xea,0x67,0xe6,0x66,0x76,0xcb,0xac,0x65,0x85,0xb2,0xfe,0xc5,0x6e,0x8b,0xb7,0x2f,0x1e,0x95,0x7,0xc9,0x6b,0xb3,0x90,0xac,0x5,0x59,0x2d,0xa,0xb6,0x42,0xa6,0xe8,0x54,0x5a,0x28,0xd7,0x2a,0x7,0xb2,0x67,0x65,0x57,0x66,0xbf,0xcd,0x89,0xca,0x39,0x96,0xab,0x9e,0x2b,0xcd,0xed,0xcc,0xb3,0xca,0xdb,0x90,0x37,0x9c,0xef,0x9f,0xff,0xed,0x12,0xc2,0x12,0xe1,0x92,0xb6,0xa5,0x86,0x4b,0x57,0x2d,0x1d,0x58,0xe6,0xbd,0xac,0x6a,0x39,0xb2,0x3c,0x71,0x79,0xdb,0xa,0xe3,0x15,0x5,0x2b,0x86,0x56,0x6,0xac,0x3c,0xb8,0x8a,0xb6,0x2a,0x6d,0xd5,0x4f,0xab,0xed,0x57,0x97,0xae,0x7e,0xbd,0x26,0x7a,0x4d,0x6b,0x81,0x5e,0xc1,0xca,0x82,0xc1,0xb5,0x1,0x6b,0xeb,0xb,0x55,0xa,0xe5,0x85,0x7d,0xeb,0xdc,0xd7,0xed,0x5d,0x4f,0x58,0x2f,0x59,0xdf,0xb5,0x61,0xfa,0x86,0x9d,0x1b,0x3e,0x15,0x89,0x8a,0xae,0x14,0xdb,0x17,0x97,0x15,0x7f,0xd8,0x28,0xdc,0x78,0xe5,0x1b,0x87,0x6f,0xca,0xbf,0x99,0xdc,0x94,0xb4,0xa9,0xab,0xc4,0xb9,0x64,0xcf,0x66,0xd2,0x66,0xe9,0xe6,0xde,0x2d,0x9e,0x5b,0xe,0x96,0xaa,0x97,0xe6,0x97,0xe,0x6e,0xd,0xd9,0xda,0xb4,0xd,0xdf,0x56,0xb4,0xed,0xf5,0xf6,0x45,0xdb,0x2f,0x97,0xcd,0x28,0xdb,0xbb,0x83,0xb6,0x43,0xb9,0xa3,0xbf,0x3c,0xb8,0xbc,0x65,0xa7,0xc9,0xce,0xcd,0x3b,0x3f,0x54,0xa4,0x54,0xf4,0x54,0xfa,0x54,0x36,0xee,0xd2,0xdd,0xb5,0x61,0xd7,0xf8,0x6e,0xd1,0xee,0x1b,0x7b,0xbc,0xf6,0x34,0xec,0xd5,0xdb,0x5b,0xbc,0xf7,0xfd,0x3e,0xc9,0xbe,0xdb,0x55,0x1,0x55,0x4d,0xd5,0x66,0xd5,0x65,0xfb,0x49,0xfb,0xb3,0xf7,0x3f,0xae,0x89,0xaa,0xe9,0xf8,0x96,0xfb,0x6d,0x5d,0xad,0x4e,0x6d,0x71,0xed,0xc7,0x3,0xd2,0x3,0xfd,0x7,0x23,0xe,0xb6,0xd7,0xb9,0xd4,0xd5,0x1d,0xd2,0x3d,0x54,0x52,0x8f,0xd6,0x2b,0xeb,0x47,0xe,0xc7,0x1f,0xbe,0xfe,0x9d,0xef,0x77,0x2d,0xd,0x36,0xd,0x55,0x8d,0x9c,0xc6,0xe2,0x23,0x70,0x44,0x79,0xe4,0xe9,0xf7,0x9,0xdf,0xf7,0x1e,0xd,0x3a,0xda,0x76,0x8c,0x7b,0xac,0xe1,0x7,0xd3,0x1f,0x76,0x1d,0x67,0x1d,0x2f,0x6a,0x42,0x9a,0xf2,0x9a,0x46,0x9b,0x53,0x9a,0xfb,0x5b,0x62,0x5b,0xba,0x4f,0xcc,0x3e,0xd1,0xd6,0xea,0xde,0x7a,0xfc,0x47,0xdb,0x1f,0xf,0x9c,0x34,0x3c,0x59,0x79,0x4a,0xf3,0x54,0xc9,0x69,0xda,0xe9,0x82,0xd3,0x93,0x67,0xf2,0xcf,0x8c,0x9d,0x95,0x9d,0x7d,0x7e,0x2e,0xf9,0xdc,0x60,0xdb,0xa2,0xb6,0x7b,0xe7,0x63,0xce,0xdf,0x6a,0xf,0x6f,0xef,0xba,0x10,0x74,0xe1,0xd2,0x45,0xff,0x8b,0xe7,0x3b,0xbc,0x3b,0xce,0x5c,0xf2,0xb8,0x74,0xf2,0xb2,0xdb,0xe5,0x13,0x57,0xb8,0x57,0x9a,0xaf,0x3a,0x5f,0x6d,0xea,0x74,0xea,0x3c,0xfe,0x93,0xd3,0x4f,0xc7,0xbb,0x9c,0xbb,0x9a,0xae,0xb9,0x5c,0x6b,0xb9,0xee,0x7a,0xbd,0xb5,0x7b,0x66,0xf7,0xe9,0x1b,0x9e,0x37,0xce,0xdd,0xf4,0xbd,0x79,0xf1,0x16,0xff,0xd6,0xd5,0x9e,0x39,0x3d,0xdd,0xbd,0xf3,0x7a,0x6f,0xf7,0xc5,0xf7,0xf5,0xdf,0x16,0xdd,0x7e,0x72,0x27,0xfd,0xce,0xcb,0xbb,0xd9,0x77,0x27,0xee,0xad,0xbc,0x4f,0xbc,0x5f,0xf4,0x40,0xed,0x41,0xd9,0x43,0xdd,0x87,0xd5,0x3f,0x5b,0xfe,0xdc,0xd8,0xef,0xdc,0x7f,0x6a,0xc0,0x77,0xa0,0xf3,0xd1,0xdc,0x47,0xf7,0x6,0x85,0x83,0xcf,0xfe,0x91,0xf5,0x8f,0xf,0x43,0x5,0x8f,0x99,0x8f,0xcb,0x86,0xd,0x86,0xeb,0x9e,0x38,0x3e,0x39,0x39,0xe2,0x3f,0x72,0xfd,0xe9,0xfc,0xa7,0x43,0xcf,0x64,0xcf,0x26,0x9e,0x17,0xfe,0xa2,0xfe,0xcb,0xae,0x17,0x16,0x2f,0x7e,0xf8,0xd5,0xeb,0xd7,0xce,0xd1,0x98,0xd1,0xa1,0x97,0xf2,0x97,0x93,0xbf,0x6d,0x7c,0xa5,0xfd,0xea,0xc0,0xeb,0x19,0xaf,0xdb,0xc6,0xc2,0xc6,0x1e,0xbe,0xc9,0x78,0x33,0x31,0x5e,0xf4,0x56,0xfb,0xed,0xc1,0x77,0xdc,0x77,0x1d,0xef,0xa3,0xdf,0xf,0x4f,0xe4,0x7c,0x20,0x7f,0x28,0xff,0x68,0xf9,0xb1,0xf5,0x53,0xd0,0xa7,0xfb,0x93,0x19,0x93,0x93,0xff,0x4,0x3,0x98,0xf3,0xfc,0xef,0x35,0x94,0x82,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,0xa,0x15,0x0,0x5,0x21,0x33,0xd5,0x5f,0x4d,0x0,0x0,0x1,0x3a,0x49,0x44,0x41,0x54,0x38,0xcb,0xa5,0x93,0x41,0x4a,0x3,0x51,0xc,0x86,0xbf,0x37,0xef,0xd1,0x11,0x5d,0x74,0x40,0xc1,0x5a,0xea,0x45,0xc4,0xa5,0x27,0xf0,0x34,0x73,0x84,0xe2,0x61,0x3c,0x81,0xee,0xc4,0x8b,0x8,0x76,0xd3,0xea,0x14,0x5a,0xe8,0x74,0xde,0x4b,0x5c,0x4c,0x46,0x2a,0xd4,0x3a,0xc5,0x40,0x20,0x8b,0xe4,0x4f,0xfe,0xf0,0xff,0xe,0x8,0xc0,0x0,0xc8,0x81,0x13,0xab,0x3d,0x90,0xf1,0x33,0x4,0x48,0xc0,0x16,0xd8,0x0,0x35,0xb0,0xed,0x86,0xcf,0x80,0x2,0x18,0x5a,0x9d,0x3,0xce,0x12,0x40,0x2d,0x6b,0x60,0xd,0x2c,0x81,0xa,0xdb,0x9e,0x3,0xc5,0xed,0xcd,0xdd,0xfd,0xf8,0xea,0xba,0x8c,0x29,0x16,0xaa,0xec,0xd,0xe7,0x20,0xf8,0x50,0xbd,0xcf,0xde,0xa6,0x2f,0xaf,0x4f,0x8f,0x40,0xc,0x76,0xf6,0x70,0x3c,0x9a,0x94,0xd5,0xe7,0xa2,0x88,0x31,0xa2,0xec,0x47,0x70,0x38,0x42,0x8,0xc5,0x78,0x34,0x29,0x81,0x67,0x60,0xf5,0x4d,0xa1,0x89,0x4d,0xd1,0xc4,0xe6,0xd7,0xe1,0x96,0x87,0xd2,0xc4,0x86,0x26,0x36,0x85,0x51,0x1d,0x4,0x7b,0x58,0x2e,0x22,0x88,0xa,0x7f,0x85,0xa2,0x88,0x8,0x46,0xdd,0x7,0xfb,0xb6,0x53,0x51,0x54,0x94,0x3e,0x61,0x7d,0xe,0xc8,0x42,0x47,0x2f,0x69,0xea,0x75,0x1,0x40,0xd2,0xd4,0x1,0x10,0x76,0x51,0x55,0x8f,0xba,0x80,0x5d,0x0,0x55,0x3d,0x2,0xa0,0xed,0xd3,0xe,0x40,0x5a,0xd0,0x84,0xf6,0xa4,0x20,0x2d,0x5,0x5,0x24,0x98,0x3c,0x6b,0x84,0xde,0x4f,0xa4,0xdd,0x53,0x3,0x29,0x33,0x6d,0xaf,0x71,0x59,0x95,0x79,0x8f,0xa8,0x1e,0xcc,0xcc,0x7b,0x70,0x59,0x65,0x92,0xde,0x6,0x33,0xc6,0x72,0xbe,0x98,0x4d,0x2f,0xce,0x2f,0xcb,0x24,0xa9,0xe0,0x80,0x96,0x7d,0x16,0x3e,0xe6,0x8b,0xd9,0x83,0xf9,0x61,0xe3,0x80,0xd3,0x7f,0x98,0x69,0x1d,0x8c,0x2,0x40,0x4,0x56,0xc7,0xda,0xf9,0xb,0x57,0x2d,0xbb,0xf5,0x2d,0xe4,0x89,0x1b,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
};
@@ -509,3 +529,42 @@ static const unsigned char vsplitter_png[]={
};
+
+
+
+static const char *uv_editor_shader_code=
+ "vec3 nd1sl2=vec3(UV,0);"
+ "uniform float H=0;"
+ "float nd4sl0=H;"
+ "float nd7sl0=nd1sl2.x;"
+ "float nd7sl1=nd1sl2.y;"
+ "float nd7sl2=nd1sl2.z;"
+ "float nd2sl1def=-1;"
+ "float nd2sl0=nd7sl1*nd2sl1def;"
+ "float nd6sl1def=1;"
+ "float nd6sl0=nd2sl0+nd6sl1def;"
+ "vec3 nd3sl0=vec3(nd4sl0,nd7sl0,nd6sl0);"
+ "vec3 nd5sl0;"
+ "{"
+ " vec3 c = nd3sl0;"
+ " vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);"
+ " vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);"
+ " nd5sl0=c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);"
+ "}"
+ "COLOR.rgb=nd5sl0;";
+
+
+static const char *w_editor_shader_code=
+ "vec3 nd1sl2=vec3(UV,0);"
+ "float nd2sl1=1-nd1sl2.y;"
+ "vec3 nd3sl0=vec3(nd2sl1,1,1);"
+ "vec3 nd6sl0;"
+ "{"
+ " vec3 c = nd3sl0;"
+ " vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);"
+ " vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);"
+ " nd6sl0=c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);"
+ "}"
+ "COLOR.rgb=nd6sl0;";
+
+
diff --git a/scene/resources/default_theme/uv_editor.gsl b/scene/resources/default_theme/uv_editor.gsl
new file mode 100644
index 0000000000..8c24e76dd5
--- /dev/null
+++ b/scene/resources/default_theme/uv_editor.gsl
@@ -0,0 +1,19 @@
+vec3 nd1sl2=vec3(UV,0);
+uniform float H=0;
+float nd4sl0=H;
+float nd7sl0=nd1sl2.x;
+float nd7sl1=nd1sl2.y;
+float nd7sl2=nd1sl2.z;
+float nd2sl1def=-1;
+float nd2sl0=nd7sl1*nd2sl1def;
+float nd6sl1def=1;
+float nd6sl0=nd2sl0+nd6sl1def;
+vec3 nd3sl0=vec3(nd4sl0,nd7sl0,nd6sl0);
+vec3 nd5sl0;
+{
+ vec3 c = nd3sl0;
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+ nd5sl0=c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+}
+COLOR.rgb=nd5sl0; \ No newline at end of file
diff --git a/scene/resources/default_theme/w_editor.gsl b/scene/resources/default_theme/w_editor.gsl
new file mode 100644
index 0000000000..6d2dd9a0bb
--- /dev/null
+++ b/scene/resources/default_theme/w_editor.gsl
@@ -0,0 +1,11 @@
+vec3 nd1sl2=vec3(UV,0);
+float nd2sl1=1-nd1sl2.y;
+vec3 nd3sl0=vec3(nd2sl1,1,1);
+vec3 nd6sl0;
+{
+ vec3 c = nd3sl0;
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+ nd6sl0=c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+}
+COLOR.rgb=nd6sl0; \ No newline at end of file
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index ffa02e819c..4551aff0ef 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/environment.h b/scene/resources/environment.h
index bee45b78cd..4620bf567a 100644
--- a/scene/resources/environment.h
+++ b/scene/resources/environment.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/event_stream.cpp b/scene/resources/event_stream.cpp
index e8cd08c064..8667bcc5db 100644
--- a/scene/resources/event_stream.cpp
+++ b/scene/resources/event_stream.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/event_stream.h b/scene/resources/event_stream.h
index f9a5e3785a..6ee9b76717 100644
--- a/scene/resources/event_stream.h
+++ b/scene/resources/event_stream.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 2d93113b40..0aae6fd978 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -462,31 +462,16 @@ void Font::draw_halign(RID p_canvas_item, const Point2& p_pos, HAlign p_align,fl
void Font::draw(RID p_canvas_item, const Point2& p_pos, const String& p_text, const Color& p_modulate,int p_clip_w) const {
- Point2 pos=p_pos;
- float ofs=0;
- VisualServer *vs = VisualServer::get_singleton();
+ Vector2 ofs;
for (int i=0;i<p_text.length();i++) {
- const Character * c = char_map.getptr(p_text[i]);
+ int width = get_char_size(p_text[i]).width;
- if (!c)
- continue;
-
-// if (p_clip_w>=0 && (ofs+c->rect.size.width)>(p_clip_w))
-// break; //width exceeded
-
- if (p_clip_w>=0 && (ofs+c->rect.size.width)>p_clip_w)
+ if (p_clip_w>=0 && (ofs.x+width)>p_clip_w)
break; //clip
- Point2 cpos=pos;
- cpos.x+=ofs+c->h_align;
- cpos.y-=ascent;
- cpos.y+=c->v_align;
- ERR_CONTINUE( c->texture_idx<-1 || c->texture_idx>=textures.size());
- if (c->texture_idx!=-1)
- textures[c->texture_idx]->draw_rect_region( p_canvas_item, Rect2( cpos, c->rect.size ), c->rect, p_modulate );
-
- ofs+=get_char_size(p_text[i],p_text[i+1]).width;
+
+ ofs.x+=draw_char(p_canvas_item,p_pos+ofs,p_text[i],p_text[i+1],p_modulate);
}
}
@@ -494,8 +479,11 @@ float Font::draw_char(RID p_canvas_item, const Point2& p_pos, const CharType& p_
const Character * c = char_map.getptr(p_char);
- if (!c)
+ if (!c) {
+ if (fallback.is_valid())
+ return fallback->draw_char(p_canvas_item,p_pos,p_char,p_next,p_modulate);
return 0;
+ }
Point2 cpos=p_pos;
cpos.x+=c->h_align;
@@ -508,6 +496,16 @@ float Font::draw_char(RID p_canvas_item, const Point2& p_pos, const CharType& p_
return get_char_size(p_char,p_next).width;
}
+void Font::set_fallback(const Ref<Font> &p_fallback) {
+
+ fallback=p_fallback;
+}
+
+Ref<Font> Font::get_fallback() const{
+
+ return fallback;
+}
+
void Font::_bind_methods() {
ObjectTypeDB::bind_method(_MD("create_from_fnt","path"),&Font::create_from_fnt);
@@ -519,7 +517,7 @@ void Font::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_descent"),&Font::get_descent);
ObjectTypeDB::bind_method(_MD("add_kerning_pair","char_a","char_b","kerning"),&Font::add_kerning_pair);
- ObjectTypeDB::bind_method(_MD("get_kerning_pair"),&Font::get_kerning_pair);
+ ObjectTypeDB::bind_method(_MD("get_kerning_pair","char_a","char_b"),&Font::get_kerning_pair);
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));
@@ -548,6 +546,8 @@ void Font::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_set_textures"),&Font::_set_textures);
ObjectTypeDB::bind_method(_MD("_get_textures"),&Font::_get_textures);
+ ObjectTypeDB::bind_method(_MD("set_fallback","fallback"),&Font::set_fallback);
+ ObjectTypeDB::bind_method(_MD("get_fallback"),&Font::get_fallback);
ADD_PROPERTY( PropertyInfo( Variant::ARRAY, "textures", PROPERTY_HINT_NONE,"", PROPERTY_USAGE_NOEDITOR ), _SCS("_set_textures"), _SCS("_get_textures") );
ADD_PROPERTY( PropertyInfo( Variant::INT_ARRAY, "chars", PROPERTY_HINT_NONE,"", PROPERTY_USAGE_NOEDITOR ), _SCS("_set_chars"), _SCS("_get_chars") );
@@ -556,6 +556,7 @@ 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") );
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "fallback", PROPERTY_HINT_RESOURCE_TYPE,"Font" ), _SCS("set_fallback"), _SCS("get_fallback") );
}
diff --git a/scene/resources/font.h b/scene/resources/font.h
index 6728b59f8e..61f0352992 100644
--- a/scene/resources/font.h
+++ b/scene/resources/font.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -84,6 +84,7 @@ private:
void _set_textures(const Vector<Variant> & p_textures);
Vector<Variant> _get_textures() const;
+ Ref<Font> fallback;
protected:
static void _bind_methods();
@@ -113,9 +114,13 @@ public:
int get_kerning_pair(CharType p_A,CharType p_B) const;
Vector<KerningPairKey> get_kerning_pair_keys() const;
- _FORCE_INLINE_ Size2 get_char_size(CharType p_char,CharType p_next=0) const;
+ inline Size2 get_char_size(CharType p_char,CharType p_next=0) const;
Size2 get_string_size(const String& p_string) const;
+
+ void set_fallback(const Ref<Font> &p_fallback);
+ Ref<Font> get_fallback() const;
+
void clear();
void set_distance_field_hint(bool p_distance_field);
@@ -134,8 +139,11 @@ Size2 Font::get_char_size(CharType p_char,CharType p_next) const {
const Character * c = char_map.getptr(p_char);
- if (!c)
+ if (!c) {
+ if (fallback.is_valid())
+ return fallback->get_char_size(p_char,p_next);
return Size2();
+ }
Size2 ret(c->advance,c->rect.size.y);
diff --git a/scene/resources/gibberish_stream.cpp b/scene/resources/gibberish_stream.cpp
index 7af81bd992..9d67069a6c 100644
--- a/scene/resources/gibberish_stream.cpp
+++ b/scene/resources/gibberish_stream.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/gibberish_stream.h b/scene/resources/gibberish_stream.h
index 77393db9f4..e06dc5eff2 100644
--- a/scene/resources/gibberish_stream.h
+++ b/scene/resources/gibberish_stream.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/height_map_shape.cpp b/scene/resources/height_map_shape.cpp
index 2c7c5384fa..e7b53c92c2 100644
--- a/scene/resources/height_map_shape.cpp
+++ b/scene/resources/height_map_shape.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/height_map_shape.h b/scene/resources/height_map_shape.h
index 46d49dab08..5494075107 100644
--- a/scene/resources/height_map_shape.h
+++ b/scene/resources/height_map_shape.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 55bb4e9073..e56314c1f8 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -535,6 +535,8 @@ void ShaderMaterial::_shader_changed() {
void ShaderMaterial::set_shader(const Ref<Shader>& p_shader) {
+ ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode()!=Shader::MODE_MATERIAL);
+
if (shader.is_valid())
shader->disconnect(SceneStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->_shader_changed);
shader=p_shader;
@@ -570,8 +572,8 @@ void ShaderMaterial::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_shader","shader:Shader"), &ShaderMaterial::set_shader );
ObjectTypeDB::bind_method(_MD("get_shader:Shader"), &ShaderMaterial::get_shader );
- ObjectTypeDB::bind_method(_MD("set_shader_param","param","value:var"), &ShaderMaterial::set_shader_param);
- ObjectTypeDB::bind_method(_MD("get_shader_param:var","param"), &ShaderMaterial::get_shader_param);
+ ObjectTypeDB::bind_method(_MD("set_shader_param","param","value:Variant"), &ShaderMaterial::set_shader_param);
+ ObjectTypeDB::bind_method(_MD("get_shader_param:Variant","param"), &ShaderMaterial::get_shader_param);
ObjectTypeDB::bind_method(_MD("_shader_changed"), &ShaderMaterial::_shader_changed );
}
diff --git a/scene/resources/material.h b/scene/resources/material.h
index 7b7bc50567..96b33ce129 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 8cb0904415..9537fa269f 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -971,7 +971,7 @@ void Mesh::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_morph_target_mode","mode"),&Mesh::set_morph_target_mode);
ObjectTypeDB::bind_method(_MD("get_morph_target_mode"),&Mesh::get_morph_target_mode);
- ObjectTypeDB::bind_method(_MD("add_surface","primitive","arrays","morph_arrays"),&Mesh::add_surface,DEFVAL(Array()));
+ ObjectTypeDB::bind_method(_MD("add_surface","primitive","arrays","morph_arrays","alphasort"),&Mesh::add_surface,DEFVAL(Array()),DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_surface_count"),&Mesh::get_surface_count);
ObjectTypeDB::bind_method(_MD("surface_remove","surf_idx"),&Mesh::surface_remove);
ObjectTypeDB::bind_method(_MD("surface_get_array_len","surf_idx"),&Mesh::surface_get_array_len);
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 50463ce80e..e0d9bdf7a8 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/mesh_data_tool.cpp b/scene/resources/mesh_data_tool.cpp
index 42aaed39e1..fb0fc2a247 100644
--- a/scene/resources/mesh_data_tool.cpp
+++ b/scene/resources/mesh_data_tool.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/mesh_data_tool.h b/scene/resources/mesh_data_tool.h
index e7e7924e98..4a26fc2628 100644
--- a/scene/resources/mesh_data_tool.h
+++ b/scene/resources/mesh_data_tool.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp
index 5ebab9be76..8643e96303 100644
--- a/scene/resources/mesh_library.cpp
+++ b/scene/resources/mesh_library.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h
index a6a7b71669..9a468d5555 100644
--- a/scene/resources/mesh_library.h
+++ b/scene/resources/mesh_library.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp
index 0755d101b2..c5ade63124 100644
--- a/scene/resources/multimesh.cpp
+++ b/scene/resources/multimesh.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -224,13 +224,13 @@ void MultiMesh::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_mesh","mesh:Mesh"),&MultiMesh::set_mesh);
ObjectTypeDB::bind_method(_MD("get_mesh:Mesh"),&MultiMesh::get_mesh);
- ObjectTypeDB::bind_method(_MD("set_instance_count"),&MultiMesh::set_instance_count);
+ ObjectTypeDB::bind_method(_MD("set_instance_count","count"),&MultiMesh::set_instance_count);
ObjectTypeDB::bind_method(_MD("get_instance_count"),&MultiMesh::get_instance_count);
- ObjectTypeDB::bind_method(_MD("set_instance_transform"),&MultiMesh::set_instance_transform);
- ObjectTypeDB::bind_method(_MD("get_instance_transform"),&MultiMesh::get_instance_transform);
- ObjectTypeDB::bind_method(_MD("set_instance_color"),&MultiMesh::set_instance_color);
- ObjectTypeDB::bind_method(_MD("get_instance_color"),&MultiMesh::get_instance_color);
- ObjectTypeDB::bind_method(_MD("set_aabb"),&MultiMesh::set_aabb);
+ ObjectTypeDB::bind_method(_MD("set_instance_transform","instance","transform"),&MultiMesh::set_instance_transform);
+ ObjectTypeDB::bind_method(_MD("get_instance_transform","instance"),&MultiMesh::get_instance_transform);
+ ObjectTypeDB::bind_method(_MD("set_instance_color","instance","color"),&MultiMesh::set_instance_color);
+ ObjectTypeDB::bind_method(_MD("get_instance_color","instance"),&MultiMesh::get_instance_color);
+ ObjectTypeDB::bind_method(_MD("set_aabb","visibility_aabb"),&MultiMesh::set_aabb);
ObjectTypeDB::bind_method(_MD("get_aabb"),&MultiMesh::get_aabb);
ObjectTypeDB::bind_method(_MD("generate_aabb"),&MultiMesh::generate_aabb);
diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h
index c2736e3070..0cf9e92def 100644
--- a/scene/resources/multimesh.h
+++ b/scene/resources/multimesh.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 863f2be699..43196a43d4 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,7 +33,7 @@
#include "scene/gui/control.h"
#include "scene/2d/node_2d.h"
#include "scene/main/instance_placeholder.h"
-
+#include "core/core_string_names.h"
#define PACK_VERSION 2
bool SceneState::can_instance() const {
@@ -99,6 +99,7 @@ Node *SceneState::instance(bool p_gen_edit_state) const {
Node *node=NULL;
+
if (i==0 && base_scene_idx>=0) {
//scene inheritance on root node
//print_line("scene inherit");
@@ -193,7 +194,26 @@ Node *SceneState::instance(bool p_gen_edit_state) const {
ERR_FAIL_INDEX_V( nprops[j].name, sname_count, NULL );
ERR_FAIL_INDEX_V( nprops[j].value, prop_count, NULL );
- node->set(snames[ nprops[j].name ],props[ nprops[j].value ],&valid);
+ if (snames[ nprops[j].name ]==CoreStringNames::get_singleton()->_script) {
+ //work around to avoid old script variables from disappearing, should be the proper fix to:
+ //https://github.com/godotengine/godot/issues/2958
+
+ //store old state
+ List<Pair<StringName,Variant> > old_state;
+ if (node->get_script_instance()) {
+ node->get_script_instance()->get_property_state(old_state);
+ }
+
+ node->set(snames[ nprops[j].name ],props[ nprops[j].value ],&valid);
+
+ //restore old state for new script, if exists
+ for (List<Pair<StringName,Variant> >::Element *E=old_state.front();E;E=E->next()) {
+ node->set(E->get().first,E->get().second);
+ }
+ } else {
+
+ node->set(snames[ nprops[j].name ],props[ nprops[j].value ],&valid);
+ }
}
}
@@ -460,6 +480,7 @@ Error SceneState::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<S
List<PropertyInfo> plist;
p_node->get_property_list(&plist);
+ bool saved_script=false;
for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
@@ -508,8 +529,23 @@ Error SceneState::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<S
break;
}
}
+#if 0
+// this workaround ended up causing problems:
+https://github.com/godotengine/godot/issues/3127
+ if (saved_script && exists && p_node->get_script_instance()) {
+ //if this is an overriden value by another script, save it anyway
+ //as the script change will erase it
+ //https://github.com/godotengine/godot/issues/2958
+
+ bool valid=false;
+ p_node->get_script_instance()->get_property_type(name,&valid);
+ if (valid) {
+ exists=false;
+ isdefault=false;
+ }
+ }
-
+#endif
if (exists && bool(Variant::evaluate(Variant::OP_EQUAL,value,original))) {
//exists and did not change
continue;
@@ -530,6 +566,9 @@ Error SceneState::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<S
}
}
+ if (name=="script/script")
+ saved_script=true;
+
NodeData::Property prop;
prop.name=_nm_get_string( name,name_map);
prop.value=_vm_get_variant( value, variant_map);
@@ -1519,11 +1558,44 @@ void SceneState::add_editable_instance(const NodePath& p_path){
editable_instances.push_back(p_path);
}
+DVector<String> SceneState::_get_node_groups(int p_idx) const {
+ Vector<StringName> groups = get_node_groups(p_idx);
+ DVector<String> ret;
+
+ for(int i=0;i<groups.size();i++)
+ ret.push_back(groups[i]);
+
+ return ret;
+}
+
+void SceneState::_bind_methods() {
+
+ //unbuild API
+
+ ObjectTypeDB::bind_method(_MD("get_node_count"),&SceneState::get_node_count);
+ ObjectTypeDB::bind_method(_MD("get_node_type","idx"),&SceneState::get_node_type);
+ ObjectTypeDB::bind_method(_MD("get_node_name","idx"),&SceneState::get_node_name);
+ ObjectTypeDB::bind_method(_MD("get_node_path","idx","for_parent"),&SceneState::get_node_path,DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("get_node_owner_path","idx"),&SceneState::get_node_owner_path);
+ ObjectTypeDB::bind_method(_MD("get_node_instance:PackedScene","idx"),&SceneState::get_node_instance);
+ ObjectTypeDB::bind_method(_MD("get_node_groups","idx"),&SceneState::_get_node_groups);
+ ObjectTypeDB::bind_method(_MD("get_node_property_count","idx"),&SceneState::get_node_property_count);
+ ObjectTypeDB::bind_method(_MD("get_node_property_name","idx","prop_idx"),&SceneState::get_node_property_name);
+ ObjectTypeDB::bind_method(_MD("get_node_property_value","idx","prop_idx"),&SceneState::get_node_property_value);
+ ObjectTypeDB::bind_method(_MD("get_connection_count"),&SceneState::get_connection_count);
+ ObjectTypeDB::bind_method(_MD("get_connection_source","idx"),&SceneState::get_connection_source);
+ ObjectTypeDB::bind_method(_MD("get_connection_signal","idx"),&SceneState::get_connection_signal);
+ ObjectTypeDB::bind_method(_MD("get_connection_target","idx"),&SceneState::get_connection_target);
+ ObjectTypeDB::bind_method(_MD("get_connection_method","idx"),&SceneState::get_connection_method);
+ ObjectTypeDB::bind_method(_MD("get_connection_flags","idx"),&SceneState::get_connection_flags);
+ ObjectTypeDB::bind_method(_MD("get_connection_binds","idx"),&SceneState::get_connection_binds);
+}
SceneState::SceneState() {
base_scene_idx=-1;
+ last_modified_time=0;
}
@@ -1583,6 +1655,25 @@ Node *PackedScene::instance(bool p_gen_edit_state) const {
return s;
}
+void PackedScene::replace_state(Ref<SceneState> p_by) {
+
+ state=p_by;
+ state->set_path(get_path());
+#ifdef TOOLS_ENABLED
+ state->set_last_modified_time(get_last_modified_time());
+#endif
+
+}
+
+void PackedScene::recreate_state() {
+
+ state = Ref<SceneState>( memnew( SceneState ));
+ state->set_path(get_path());
+#ifdef TOOLS_ENABLED
+ state->set_last_modified_time(get_last_modified_time());
+#endif
+}
+
Ref<SceneState> PackedScene::get_state() {
return state;
@@ -1594,6 +1685,7 @@ void PackedScene::set_path(const String& p_path,bool p_take_over) {
Resource::set_path(p_path,p_take_over);
}
+
void PackedScene::_bind_methods() {
ObjectTypeDB::bind_method(_MD("pack","path:Node"),&PackedScene::pack);
@@ -1601,6 +1693,7 @@ void PackedScene::_bind_methods() {
ObjectTypeDB::bind_method(_MD("can_instance"),&PackedScene::can_instance);
ObjectTypeDB::bind_method(_MD("_set_bundled_scene"),&PackedScene::_set_bundled_scene);
ObjectTypeDB::bind_method(_MD("_get_bundled_scene"),&PackedScene::_get_bundled_scene);
+ ObjectTypeDB::bind_method(_MD("get_state:SceneState"),&PackedScene::get_state);
ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_bundled"),_SCS("_set_bundled_scene"),_SCS("_get_bundled_scene"));
diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h
index f3ec0afb6d..7fda4392d8 100644
--- a/scene/resources/packed_scene.h
+++ b/scene/resources/packed_scene.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,6 +36,8 @@
class SceneState : public Reference {
OBJ_TYPE( SceneState, Reference );
+
+
Vector<StringName> names;
Vector<Variant> variants;
Vector<NodePath> node_paths;
@@ -50,7 +52,6 @@ class SceneState : public Reference {
FLAG_INSTANCE_IS_PLACEHOLDER=(1<<30),
FLAG_MASK=(1<<24)-1,
NO_PARENT_SAVED=0x7FFFFFFF,
- TYPE_INSTANCED=0x7FFFFFFF,
};
@@ -99,11 +100,24 @@ class SceneState : public Reference {
String path;
+ uint64_t last_modified_time;
+
_FORCE_INLINE_ Ref<SceneState> _get_base_scene_state() const;
static bool disable_placeholders;
+
+ DVector<String> _get_node_groups(int p_idx) const;
+
+protected:
+
+ static void _bind_methods();
+
public:
+ enum {
+ TYPE_INSTANCED=0x7FFFFFFF
+ };
+
static void set_disable_placeholders(bool p_disable);
int find_node_by_path(const NodePath& p_node) const;
@@ -162,6 +176,9 @@ public:
void add_connection(int p_from,int p_to, int p_signal, int p_method, int p_flags,const Vector<int>& p_binds);
void add_editable_instance(const NodePath& p_path);
+ virtual void set_last_modified_time(uint64_t p_time) { last_modified_time=p_time; }
+ uint64_t get_last_modified_time() const { return last_modified_time; }
+
SceneState();
};
@@ -189,8 +206,14 @@ public:
bool can_instance() const;
Node *instance(bool p_gen_edit_state=false) const;
+ void recreate_state();
+ void replace_state(Ref<SceneState> p_by);
+
virtual void set_path(const String& p_path,bool p_take_over=false);
+#ifdef TOOLS_ENABLED
+ virtual void set_last_modified_time(uint64_t p_time) { state->set_last_modified_time(p_time); }
+#endif
Ref<SceneState> get_state();
PackedScene();
diff --git a/scene/resources/plane_shape.cpp b/scene/resources/plane_shape.cpp
index 760a36a91e..f551414f61 100644
--- a/scene/resources/plane_shape.cpp
+++ b/scene/resources/plane_shape.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/plane_shape.h b/scene/resources/plane_shape.h
index dd285171c4..543c433965 100644
--- a/scene/resources/plane_shape.h
+++ b/scene/resources/plane_shape.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/ray_shape.cpp b/scene/resources/ray_shape.cpp
index ee55cc6e37..73ce4de976 100644
--- a/scene/resources/ray_shape.cpp
+++ b/scene/resources/ray_shape.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/ray_shape.h b/scene/resources/ray_shape.h
index edb29b83b5..0218045247 100644
--- a/scene/resources/ray_shape.h
+++ b/scene/resources/ray_shape.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/rectangle_shape_2d.cpp b/scene/resources/rectangle_shape_2d.cpp
index 7903d88736..bc0f86f0a7 100644
--- a/scene/resources/rectangle_shape_2d.cpp
+++ b/scene/resources/rectangle_shape_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/rectangle_shape_2d.h b/scene/resources/rectangle_shape_2d.h
index 96de02fb70..1ffbe1e356 100644
--- a/scene/resources/rectangle_shape_2d.h
+++ b/scene/resources/rectangle_shape_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/rich_text.cpp b/scene/resources/rich_text.cpp
index 7e58a19ac3..8acf5ff39b 100644
--- a/scene/resources/rich_text.cpp
+++ b/scene/resources/rich_text.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/rich_text.h b/scene/resources/rich_text.h
index 9dfffbfeb3..c74a391b10 100644
--- a/scene/resources/rich_text.h
+++ b/scene/resources/rich_text.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/room.cpp b/scene/resources/room.cpp
index 3673b18394..0f9eb85244 100644
--- a/scene/resources/room.cpp
+++ b/scene/resources/room.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/room.h b/scene/resources/room.h
index f621d8f1bf..c5aaea311e 100644
--- a/scene/resources/room.h
+++ b/scene/resources/room.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/sample.cpp b/scene/resources/sample.cpp
index 0a785e7bf6..4b25a2c490 100644
--- a/scene/resources/sample.cpp
+++ b/scene/resources/sample.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -210,11 +210,11 @@ void Sample::_bind_methods(){
ADD_PROPERTY( PropertyInfo( Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), _SCS("_set_data"), _SCS("_get_data") );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "stereo"), _SCS(""), _SCS("is_stereo") );
- ADD_PROPERTY( PropertyInfo( Variant::INT, "length"), _SCS(""), _SCS("get_length") );
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "length",PROPERTY_HINT_RANGE,"0,999999999"), _SCS(""), _SCS("get_length") );
ADD_PROPERTY( PropertyInfo( Variant::INT, "mix_rate", PROPERTY_HINT_RANGE,"1,192000,1" ), _SCS("set_mix_rate"), _SCS("get_mix_rate") );
ADD_PROPERTY( PropertyInfo( Variant::INT, "loop_format", PROPERTY_HINT_ENUM,"None,Forward,PingPong" ), _SCS("set_loop_format"), _SCS("get_loop_format") );
- ADD_PROPERTY( PropertyInfo( Variant::INT, "loop_begin", PROPERTY_HINT_RANGE,"0,"+itos(99999999)+",1"), _SCS("set_loop_begin"), _SCS("get_loop_begin") );
- ADD_PROPERTY( PropertyInfo( Variant::INT, "loop_end", PROPERTY_HINT_RANGE,"0,"+itos(99999999)+",1"), _SCS("set_loop_end"), _SCS("get_loop_end") );
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "loop_begin", PROPERTY_HINT_RANGE,"0,"+itos(999999999)+",1"), _SCS("set_loop_begin"), _SCS("get_loop_begin") );
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "loop_end", PROPERTY_HINT_RANGE,"0,"+itos(999999999)+",1"), _SCS("set_loop_end"), _SCS("get_loop_end") );
BIND_CONSTANT( FORMAT_PCM8 );
BIND_CONSTANT( FORMAT_PCM16 );
diff --git a/scene/resources/sample.h b/scene/resources/sample.h
index 4877e0b841..0a88167233 100644
--- a/scene/resources/sample.h
+++ b/scene/resources/sample.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/sample_library.cpp b/scene/resources/sample_library.cpp
index ffcaa1e675..5b70ee0e11 100644
--- a/scene/resources/sample_library.cpp
+++ b/scene/resources/sample_library.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/sample_library.h b/scene/resources/sample_library.h
index 88519e7035..8377967106 100644
--- a/scene/resources/sample_library.h
+++ b/scene/resources/sample_library.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp
index 5f41dc2ce8..2f18e70d7f 100644
--- a/scene/resources/scene_format_text.cpp
+++ b/scene/resources/scene_format_text.cpp
@@ -12,12 +12,6 @@
#define _printerr() ERR_PRINT(String(res_path+":"+itos(lines)+" - Parse Error: "+error_text).utf8().get_data());
-Error ResourceInteractiveLoaderText::parse_property(Variant& r_v, String &r_name) {
-
- return OK;
-}
-
-
///
@@ -308,6 +302,10 @@ Error ResourceInteractiveLoaderText::poll() {
if (error) {
if (error!=ERR_FILE_EOF) {
_printerr();
+ } else {
+ if (!ResourceCache::has(res_path)) {
+ resource->set_path(res_path);
+ }
}
return error;
}
@@ -358,7 +356,7 @@ Error ResourceInteractiveLoaderText::poll() {
int type=-1;
int name=-1;
int instance=-1;
- int base_scene=-1;
+// int base_scene=-1;
if (next_tag.fields.has("name")) {
name=packed_scene->get_state()->add_name(next_tag.fields["name"]);
@@ -368,18 +366,15 @@ Error ResourceInteractiveLoaderText::poll() {
parent=packed_scene->get_state()->add_node_path(next_tag.fields["parent"]);
}
- if (next_tag.fields.has("owner")) {
- owner=packed_scene->get_state()->add_node_path(next_tag.fields["owner"]);
- } else {
- if (parent!=-1)
- owner=0; //if no owner, owner is root
- }
if (next_tag.fields.has("type")) {
type=packed_scene->get_state()->add_name(next_tag.fields["type"]);
+ } else {
+ type=SceneState::TYPE_INSTANCED; //no type? assume this was instanced
}
+
if (next_tag.fields.has("instance")) {
instance=packed_scene->get_state()->add_value(next_tag.fields["instance"]);
@@ -390,6 +385,13 @@ Error ResourceInteractiveLoaderText::poll() {
}
}
+ if (next_tag.fields.has("owner")) {
+ owner=packed_scene->get_state()->add_node_path(next_tag.fields["owner"]);
+ } else {
+ if (parent!=-1 && !(type==SceneState::TYPE_INSTANCED && instance==-1))
+ owner=0; //if no owner, owner is root
+ }
+
int node_id = packed_scene->get_state()->add_node(parent,owner,type,name,instance);
@@ -405,6 +407,9 @@ Error ResourceInteractiveLoaderText::poll() {
_printerr();
} else {
resource=packed_scene;
+ if (!ResourceCache::has(res_path)) {
+ packed_scene->set_path(res_path);
+ }
}
return error;
}
@@ -479,8 +484,8 @@ Error ResourceInteractiveLoaderText::poll() {
}
Vector<int> bind_ints;
- for(int i=9;i<binds.size();i++) {
- bind_ints.push_back( packed_scene->get_state()->add_value( bind_ints[i] ) );
+ for(int i=0;i<binds.size();i++) {
+ bind_ints.push_back( packed_scene->get_state()->add_value( binds[i] ) );
}
packed_scene->get_state()->add_connection(
@@ -614,57 +619,63 @@ void ResourceInteractiveLoaderText::get_dependencies(FileAccess *f,List<String>
Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map) {
-
-
-#if 0
- open(p_f);
+ open(p_f,true);
ERR_FAIL_COND_V(error!=OK,error);
//FileAccess
- bool old_format=false;
-
FileAccess *fw = NULL;
String base_path=local_path.get_base_dir();
+
+ uint64_t tag_end = f->get_pos();
+
+
while(true) {
- bool exit;
- List<String> order;
- Tag *tag = parse_tag(&exit,true,&order);
- bool done=false;
- if (!tag) {
+ Error err = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp);
+
+ if (err!=OK) {
if (fw) {
memdelete(fw);
}
error=ERR_FILE_CORRUPT;
- ERR_FAIL_COND_V(!exit,error);
- error=ERR_FILE_EOF;
-
- return error;
+ ERR_FAIL_V(error);
}
- if (tag->name=="ext_resource") {
+ if (next_tag.name!="ext_resource") {
- if (!tag->args.has("index") || !tag->args.has("path") || !tag->args.has("type")) {
- old_format=true;
- break;
- }
+ //nothing was done
+ if (!fw)
+ return OK;
+
+ break;
+
+
+ } else {
if (!fw) {
fw=FileAccess::open(p_path+".depren",FileAccess::WRITE);
- fw->store_line("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); //no escape
- fw->store_line("<resource_file type=\""+resource_type+"\" subresource_count=\""+itos(resources_total)+"\" version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\" version_name=\""+VERSION_FULL_NAME+"\">");
+ if (is_scene) {
+ fw->store_line("[gd_scene load_steps="+itos(resources_total)+" format="+itos(FORMAT_VERSION)+"]\n");
+ } else {
+ fw->store_line("[gd_resource type=\""+res_type+"\" load_steps="+itos(resources_total)+" format="+itos(FORMAT_VERSION)+"]\n");
+ }
+ }
+ if (!next_tag.fields.has("path") || !next_tag.fields.has("id") || !next_tag.fields.has("type")) {
+ memdelete(fw);
+ error=ERR_FILE_CORRUPT;
+ ERR_FAIL_V(error);
}
- String path = tag->args["path"];
- String index = tag->args["index"];
- String type = tag->args["type"];
+ String path = next_tag.fields["path"];
+ int index = next_tag.fields["id"];
+ String type = next_tag.fields["type"];
bool relative=false;
@@ -673,7 +684,6 @@ Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const
relative=true;
}
-
if (p_map.has(path)) {
String np=p_map[path];
path=np;
@@ -684,74 +694,15 @@ Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const
path=base_path.path_to_file(path);
}
- tag->args["path"]=path;
- tag->args["index"]=index;
- tag->args["type"]=type;
-
- } else {
-
- done=true;
- }
+ fw->store_line("[ext_resource path=\""+path+"\" type=\""+type+"\" id="+itos(index)+"]");
- String tagt="\t<";
- if (exit)
- tagt+="/";
- tagt+=tag->name;
+ tag_end = f->get_pos();
- for(List<String>::Element *E=order.front();E;E=E->next()) {
- tagt+=" "+E->get()+"=\""+tag->args[E->get()]+"\"";
}
- tagt+=">";
- fw->store_line(tagt);
- if (done)
- break;
- close_tag("ext_resource");
- fw->store_line("\t</ext_resource>");
}
-
- if (old_format) {
- if (fw)
- memdelete(fw);
-
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- da->remove(p_path+".depren");
- memdelete(da);
- //fuck it, use the old approach;
-
- WARN_PRINT(("This file is old, so it can't refactor dependencies, opening and resaving: "+p_path).utf8().get_data());
-
- Error err;
- FileAccess *f2 = FileAccess::open(p_path,FileAccess::READ,&err);
- if (err!=OK) {
- ERR_FAIL_COND_V(err!=OK,ERR_FILE_CANT_OPEN);
- }
-
- Ref<ResourceInteractiveLoaderText> ria = memnew( ResourceInteractiveLoaderText );
- ria->local_path=Globals::get_singleton()->localize_path(p_path);
- ria->res_path=ria->local_path;
- ria->remaps=p_map;
- // ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
- ria->open(f2);
-
- err = ria->poll();
-
- while(err==OK) {
- err=ria->poll();
- }
-
- ERR_FAIL_COND_V(err!=ERR_FILE_EOF,ERR_FILE_CORRUPT);
- RES res = ria->get_resource();
- ERR_FAIL_COND_V(!res.is_valid(),ERR_FILE_CORRUPT);
-
- return ResourceFormatSaverText::singleton->save(p_path,res);
- }
-
- if (!fw) {
-
- return OK; //nothing to rename, do nothing
- }
+ f->seek(tag_end);
uint8_t c=f->get_8();
while(!f->eof_reached()) {
@@ -771,13 +722,13 @@ Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const
da->remove(p_path);
da->rename(p_path+".depren",p_path);
memdelete(da);
-#endif
+
return OK;
}
-void ResourceInteractiveLoaderText::open(FileAccess *p_f) {
+void ResourceInteractiveLoaderText::open(FileAccess *p_f,bool p_skip_first_tag) {
error=OK;
@@ -840,13 +791,15 @@ void ResourceInteractiveLoaderText::open(FileAccess *p_f) {
resources_total=0;
}
+ if (!p_skip_first_tag) {
- err = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp);
+ err = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp);
- if (err) {
- error_text="Unexpected end of file";
- _printerr();
- error=ERR_FILE_CORRUPT;
+ if (err) {
+ error_text="Unexpected end of file";
+ _printerr();
+ error=ERR_FILE_CORRUPT;
+ }
}
rp.ext_func=_parse_ext_resources;
@@ -932,6 +885,10 @@ Ref<ResourceInteractiveLoader> ResourceFormatLoaderText::load_interactive(const
void ResourceFormatLoaderText::get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const {
+ if (p_type=="") {
+ get_recognized_extensions(p_extensions);
+ return;
+ }
if (p_type=="PackedScene")
p_extensions->push_back("tscn");
@@ -1022,431 +979,37 @@ Error ResourceFormatLoaderText::rename_dependencies(const String &p_path,const M
/*****************************************************************************************************/
-void ResourceFormatSaverTextInstance::write_property(const String& p_name,const Variant& p_property,bool *r_ok) {
-
- if (r_ok)
- *r_ok=false;
-
- if (p_name!=String()) {
- f->store_string(p_name+" = ");
- }
-
- switch( p_property.get_type() ) {
-
- case Variant::NIL: {
- f->store_string("null");
- } break;
- case Variant::BOOL: {
-
- f->store_string(p_property.operator bool() ? "true":"false" );
- } break;
- case Variant::INT: {
-
- f->store_string( itos(p_property.operator int()) );
- } break;
- case Variant::REAL: {
-
- f->store_string( rtoss(p_property.operator real_t()) );
- } break;
- case Variant::STRING: {
-
- String str=p_property;
-
- str="\""+str.c_escape()+"\"";
- f->store_string( str );
- } break;
- case Variant::VECTOR2: {
-
- Vector2 v = p_property;
- f->store_string("Vector2( "+rtoss(v.x) +", "+rtoss(v.y)+" )" );
- } break;
- case Variant::RECT2: {
-
- Rect2 aabb = p_property;
- f->store_string("Rect2( "+rtoss(aabb.pos.x) +", "+rtoss(aabb.pos.y) +", "+rtoss(aabb.size.x) +", "+rtoss(aabb.size.y)+" )" );
-
- } break;
- case Variant::VECTOR3: {
-
- Vector3 v = p_property;
- f->store_string("Vector3( "+rtoss(v.x) +", "+rtoss(v.y)+", "+rtoss(v.z)+" )");
- } break;
- case Variant::PLANE: {
-
- Plane p = p_property;
- f->store_string("Plane( "+rtoss(p.normal.x) +", "+rtoss(p.normal.y)+", "+rtoss(p.normal.z)+", "+rtoss(p.d)+" )" );
-
- } break;
- case Variant::_AABB: {
-
- AABB aabb = p_property;
- f->store_string("AABB( "+rtoss(aabb.pos.x) +", "+rtoss(aabb.pos.y) +", "+rtoss(aabb.pos.z) +", "+rtoss(aabb.size.x) +", "+rtoss(aabb.size.y) +", "+rtoss(aabb.size.z)+" )" );
-
- } break;
- case Variant::QUAT: {
-
- Quat quat = p_property;
- f->store_string("Quat( "+rtoss(quat.x)+", "+rtoss(quat.y)+", "+rtoss(quat.z)+", "+rtoss(quat.w)+" )");
-
- } break;
- case Variant::MATRIX32: {
-
- String s="Matrix32( ";
- Matrix32 m3 = p_property;
- for (int i=0;i<3;i++) {
- for (int j=0;j<2;j++) {
-
- if (i!=0 || j!=0)
- s+=", ";
- s+=rtoss( m3.elements[i][j] );
- }
- }
-
- f->store_string(s+" )");
-
- } break;
- case Variant::MATRIX3: {
-
- String s="Matrix3( ";
- Matrix3 m3 = p_property;
- for (int i=0;i<3;i++) {
- for (int j=0;j<3;j++) {
-
- if (i!=0 || j!=0)
- s+=", ";
- s+=rtoss( m3.elements[i][j] );
- }
- }
-
- f->store_string(s+" )");
-
- } break;
- case Variant::TRANSFORM: {
-
- String s="Transform( ";
- Transform t = p_property;
- Matrix3 &m3 = t.basis;
- for (int i=0;i<3;i++) {
- for (int j=0;j<3;j++) {
-
- if (i!=0 || j!=0)
- s+=", ";
- s+=rtoss( m3.elements[i][j] );
- }
- }
-
- s=s+", "+rtoss(t.origin.x) +", "+rtoss(t.origin.y)+", "+rtoss(t.origin.z);
-
- f->store_string(s+" )");
- } break;
-
- // misc types
- case Variant::COLOR: {
-
- Color c = p_property;
- f->store_string("Color( "+rtoss(c.r) +", "+rtoss(c.g)+", "+rtoss(c.b)+", "+rtoss(c.a)+" )");
-
- } break;
- case Variant::IMAGE: {
-
-
- Image img=p_property;
-
- if (img.empty()) {
- f->store_string("Image()");
- break;
- }
-
- String imgstr="Image( ";
- imgstr+=itos(img.get_width());
- imgstr+=", "+itos(img.get_height());
- imgstr+=", "+itos(img.get_mipmaps());
- imgstr+=", ";
-
- switch(img.get_format()) {
-
- case Image::FORMAT_GRAYSCALE: imgstr+="GRAYSCALE"; break;
- case Image::FORMAT_INTENSITY: imgstr+="INTENSITY"; break;
- case Image::FORMAT_GRAYSCALE_ALPHA: imgstr+="GRAYSCALE_ALPHA"; break;
- case Image::FORMAT_RGB: imgstr+="RGB"; break;
- case Image::FORMAT_RGBA: imgstr+="RGBA"; break;
- case Image::FORMAT_INDEXED : imgstr+="INDEXED"; break;
- case Image::FORMAT_INDEXED_ALPHA: imgstr+="INDEXED_ALPHA"; break;
- case Image::FORMAT_BC1: imgstr+="BC1"; break;
- case Image::FORMAT_BC2: imgstr+="BC2"; break;
- case Image::FORMAT_BC3: imgstr+="BC3"; break;
- case Image::FORMAT_BC4: imgstr+="BC4"; break;
- case Image::FORMAT_BC5: imgstr+="BC5"; break;
- case Image::FORMAT_PVRTC2: imgstr+="PVRTC2"; break;
- case Image::FORMAT_PVRTC2_ALPHA: imgstr+="PVRTC2_ALPHA"; break;
- case Image::FORMAT_PVRTC4: imgstr+="PVRTC4"; break;
- case Image::FORMAT_PVRTC4_ALPHA: imgstr+="PVRTC4_ALPHA"; break;
- case Image::FORMAT_ETC: imgstr+="ETC"; break;
- case Image::FORMAT_ATC: imgstr+="ATC"; break;
- case Image::FORMAT_ATC_ALPHA_EXPLICIT: imgstr+="ATC_ALPHA_EXPLICIT"; break;
- case Image::FORMAT_ATC_ALPHA_INTERPOLATED: imgstr+="ATC_ALPHA_INTERPOLATED"; break;
- case Image::FORMAT_CUSTOM: imgstr+="CUSTOM"; break;
- default: {}
- }
-
-
- String s;
-
- DVector<uint8_t> data = img.get_data();
- int len = data.size();
- DVector<uint8_t>::Read r = data.read();
- const uint8_t *ptr=r.ptr();;
- for (int i=0;i<len;i++) {
-
- if (i>0)
- s+=", ";
- s+=itos(ptr[i]);
- }
-
- imgstr+=", ";
- f->store_string(imgstr);
- f->store_string(s);
- f->store_string(" )");
- } break;
- case Variant::NODE_PATH: {
-
- String str=p_property;
-
- str="NodePath(\""+str.c_escape()+"\")";
- f->store_string(str);
-
- } break;
-
- case Variant::OBJECT: {
-
- RES res = p_property;
- if (res.is_null()) {
- f->store_string("null");
- if (r_ok)
- *r_ok=true;
-
- break; // don't save it
- }
-
- if (external_resources.has(res)) {
-
- f->store_string("ExtResource( "+itos(external_resources[res]+1)+" )");
- } else {
-
- if (internal_resources.has(res)) {
- f->store_string("SubResource( "+itos(internal_resources[res])+" )");
- } else if (res->get_path().length() && res->get_path().find("::")==-1) {
-
- //external resource
- String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path();
- f->store_string("Resource( \""+path+"\" )");
- } else {
- f->store_string("null");
- ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
- ERR_BREAK(true);
- //internal resource
- }
- }
-
- } break;
- case Variant::INPUT_EVENT: {
-
- f->store_string("InputEvent()"); //will be added later
- } break;
- case Variant::DICTIONARY: {
-
- Dictionary dict = p_property;
-
- List<Variant> keys;
- dict.get_key_list(&keys);
- keys.sort();
-
- f->store_string("{ ");
- for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
-
- //if (!_check_type(dict[E->get()]))
- // continue;
- bool ok;
- write_property("",E->get(),&ok);
- ERR_CONTINUE(!ok);
-
- f->store_string(":");
- write_property("",dict[E->get()],&ok);
- if (!ok)
- write_property("",Variant()); //at least make the file consistent..
- if (E->next())
- f->store_string(", ");
- }
-
-
- f->store_string(" }");
-
-
- } break;
- case Variant::ARRAY: {
-
- f->store_string("[ ");
- Array array = p_property;
- int len=array.size();
- for (int i=0;i<len;i++) {
-
- if (i>0)
- f->store_string(", ");
- write_property("",array[i]);
-
-
- }
- f->store_string(" ]");
-
- } break;
-
- case Variant::RAW_ARRAY: {
-
- f->store_string("ByteArray( ");
- String s;
- DVector<uint8_t> data = p_property;
- int len = data.size();
- DVector<uint8_t>::Read r = data.read();
- const uint8_t *ptr=r.ptr();;
- for (int i=0;i<len;i++) {
+String ResourceFormatSaverTextInstance::_write_resources(void *ud,const RES& p_resource) {
- if (i>0)
- f->store_string(", ");
+ ResourceFormatSaverTextInstance *rsi=(ResourceFormatSaverTextInstance*)ud;
+ return rsi->_write_resource(p_resource);
- f->store_string(itos(ptr[i]));
-
- }
-
- f->store_string(" )");
-
- } break;
- case Variant::INT_ARRAY: {
-
- f->store_string("IntArray( ");
- DVector<int> data = p_property;
- int len = data.size();
- DVector<int>::Read r = data.read();
- const int *ptr=r.ptr();;
-
- for (int i=0;i<len;i++) {
-
- if (i>0)
- f->store_string(", ");
-
- f->store_string(itos(ptr[i]));
- }
-
-
- f->store_string(" )");
-
- } break;
- case Variant::REAL_ARRAY: {
-
- f->store_string("FloatArray( ");
- DVector<real_t> data = p_property;
- int len = data.size();
- DVector<real_t>::Read r = data.read();
- const real_t *ptr=r.ptr();;
-
- for (int i=0;i<len;i++) {
-
- if (i>0)
- f->store_string(", ");
- f->store_string(rtoss(ptr[i]));
- }
-
- f->store_string(" )");
-
- } break;
- case Variant::STRING_ARRAY: {
-
- f->store_string("StringArray( ");
- DVector<String> data = p_property;
- int len = data.size();
- DVector<String>::Read r = data.read();
- const String *ptr=r.ptr();;
- String s;
- //write_string("\n");
-
-
-
- for (int i=0;i<len;i++) {
-
- if (i>0)
- f->store_string(", ");
- String str=ptr[i];
- f->store_string(""+str.c_escape()+"\"");
- }
-
- f->store_string(" )");
-
- } break;
- case Variant::VECTOR2_ARRAY: {
-
- f->store_string("Vector2Array( ");
- DVector<Vector2> data = p_property;
- int len = data.size();
- DVector<Vector2>::Read r = data.read();
- const Vector2 *ptr=r.ptr();;
-
- for (int i=0;i<len;i++) {
-
- if (i>0)
- f->store_string(", ");
- f->store_string(rtoss(ptr[i].x)+", "+rtoss(ptr[i].y) );
- }
-
- f->store_string(" )");
-
- } break;
- case Variant::VECTOR3_ARRAY: {
-
- f->store_string("Vector3Array( ");
- DVector<Vector3> data = p_property;
- int len = data.size();
- DVector<Vector3>::Read r = data.read();
- const Vector3 *ptr=r.ptr();;
-
- for (int i=0;i<len;i++) {
-
- if (i>0)
- f->store_string(", ");
- f->store_string(rtoss(ptr[i].x)+", "+rtoss(ptr[i].y)+", "+rtoss(ptr[i].z) );
- }
-
- f->store_string(" )");
-
- } break;
- case Variant::COLOR_ARRAY: {
-
- f->store_string("ColorArray( ");
-
- DVector<Color> data = p_property;
- int len = data.size();
- DVector<Color>::Read r = data.read();
- const Color *ptr=r.ptr();;
-
- for (int i=0;i<len;i++) {
+}
- if (i>0)
- f->store_string(", ");
+String ResourceFormatSaverTextInstance::_write_resource(const RES& res) {
- f->store_string(rtoss(ptr[i].r)+", "+rtoss(ptr[i].g)+", "+rtoss(ptr[i].b)+", "+rtoss(ptr[i].a) );
+ if (external_resources.has(res)) {
- }
- f->store_string(" )");
+ return "ExtResource( "+itos(external_resources[res]+1)+" )";
+ } else {
- } break;
- default: {}
+ if (internal_resources.has(res)) {
+ return "SubResource( "+itos(internal_resources[res])+" )";
+ } else if (res->get_path().length() && res->get_path().find("::")==-1) {
+ //external resource
+ String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path();
+ return "Resource( \""+path+"\" )";
+ } else {
+ ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
+ ERR_FAIL_V("null");
+ //internal resource
+ }
}
- if (r_ok)
- *r_ok=true;
-
+ return "null";
}
-
void ResourceFormatSaverTextInstance::_find_resources(const Variant& p_variant,bool p_main) {
@@ -1580,11 +1143,18 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re
}
+ Vector<RES> sorted_er;
+ sorted_er.resize(external_resources.size());
+
for(Map<RES,int>::Element *E=external_resources.front();E;E=E->next()) {
- String p = E->key()->get_path();
+ sorted_er[E->get()]=E->key();
+ }
+
+ for(int i=0;i<sorted_er.size();i++) {
+ String p = sorted_er[i]->get_path();
- f->store_string("[ext_resource path=\""+p+"\" type=\""+E->key()->get_save_type()+"\" id="+itos(E->get()+1)+"]\n"); //bundled
+ f->store_string("[ext_resource path=\""+p+"\" type=\""+sorted_er[i]->get_save_type()+"\" id="+itos(i+1)+"]\n"); //bundled
}
if (external_resources.size())
@@ -1663,8 +1233,9 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re
if (PE->get().type==Variant::OBJECT && value.is_zero())
continue;
- write_property(name,value);
- f->store_string("\n");
+ String vars;
+ VariantWriter::write_to_string(value,vars,_write_resources,this);
+ f->store_string(name+" = "+vars+"\n");
}
@@ -1715,17 +1286,22 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re
f->store_string(header);
if (instance.is_valid()) {
+
+ String vars;
f->store_string(" instance=");
- write_property("",instance);
+ VariantWriter::write_to_string(instance,vars,_write_resources,this);
+ f->store_string(vars);
+
}
f->store_line("]\n");
for(int j=0;j<state->get_node_property_count(i);j++) {
- write_property(state->get_node_property_name(i,j),state->get_node_property_value(i,j));
- f->store_line(String());
+ String vars;
+ VariantWriter::write_to_string(state->get_node_property_value(i,j),vars,_write_resources,this);
+ f->store_string(String(state->get_node_property_name(i,j))+" = "+vars+"\n");
}
if (state->get_node_property_count(i)) {
@@ -1750,8 +1326,10 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re
Array binds=state->get_connection_binds(i);
f->store_string(connstr);
if (binds.size()) {
- f->store_string(" binds=");
- write_property("",binds);
+ String vars;
+ VariantWriter::write_to_string(binds,vars,_write_resources,this);
+ f->store_string(" binds= "+vars);
+
}
f->store_line("]\n");
diff --git a/scene/resources/scene_format_text.h b/scene/resources/scene_format_text.h
index 4f18af2b62..02436a6e2d 100644
--- a/scene/resources/scene_format_text.h
+++ b/scene/resources/scene_format_text.h
@@ -60,7 +60,6 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader {
friend class ResourceFormatLoaderText;
List<RES> resource_cache;
- Error parse_property(Variant& r_v, String &r_name);
Error error;
RES resource;
@@ -73,7 +72,7 @@ public:
virtual int get_stage() const;
virtual int get_stage_count() const;
- void open(FileAccess *p_f);
+ void open(FileAccess *p_f, bool p_skip_first_tag=false);
String recognize(FileAccess *p_f);
void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types);
Error rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map);
@@ -117,7 +116,10 @@ class ResourceFormatSaverTextInstance {
Map<RES,int> internal_resources;
void _find_resources(const Variant& p_variant,bool p_main=false);
- void write_property(const String& p_name,const Variant& p_property,bool *r_ok=NULL);
+
+ static String _write_resources(void *ud,const RES& p_resource);
+ String _write_resource(const RES& res);
+
public:
diff --git a/scene/resources/scene_preloader.cpp b/scene/resources/scene_preloader.cpp
index 09001c1a94..c031f3c721 100644
--- a/scene/resources/scene_preloader.cpp
+++ b/scene/resources/scene_preloader.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/scene_preloader.h b/scene/resources/scene_preloader.h
index d60d08afd4..2317c9e0bd 100644
--- a/scene/resources/scene_preloader.h
+++ b/scene/resources/scene_preloader.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/segment_shape_2d.cpp b/scene/resources/segment_shape_2d.cpp
index 88f7adcd9b..b8b14fd6fc 100644
--- a/scene/resources/segment_shape_2d.cpp
+++ b/scene/resources/segment_shape_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/segment_shape_2d.h b/scene/resources/segment_shape_2d.h
index 37c68b6c92..6f7b2f2d38 100644
--- a/scene/resources/segment_shape_2d.h
+++ b/scene/resources/segment_shape_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index a9376faf62..ee9f23dd2a 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -448,31 +448,19 @@ RES ResourceFormatLoaderShader::load(const String &p_path, const String& p_origi
void ResourceFormatLoaderShader::get_recognized_extensions(List<String> *p_extensions) const {
- p_extensions->push_back("shader");
+ ObjectTypeDB::get_extensions_for_type("Shader", p_extensions);
}
+
bool ResourceFormatLoaderShader::handles_type(const String& p_type) const {
- return p_type=="Shader";
+ return ObjectTypeDB::is_type(p_type, "Shader");
}
String ResourceFormatLoaderShader::get_resource_type(const String &p_path) const {
- if (p_path.extension().to_lower()=="shader")
+ if (p_path.extension().to_lower()=="shd")
return "Shader";
return "";
}
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/scene/resources/shader.h b/scene/resources/shader.h
index 61a369c408..6ee8d4e793 100644
--- a/scene/resources/shader.h
+++ b/scene/resources/shader.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp
index 7b67eaeda8..eabc84c41e 100644
--- a/scene/resources/shader_graph.cpp
+++ b/scene/resources/shader_graph.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -179,25 +179,25 @@ void ShaderGraph::_bind_methods() {
ObjectTypeDB::bind_method(_MD("default_get_value","shader_type","id","param_id"), &ShaderGraph::default_get_value);
ObjectTypeDB::bind_method(_MD("scalar_const_node_set_value","shader_type","id","value"),&ShaderGraph::scalar_const_node_set_value);
- ObjectTypeDB::bind_method(_MD("scalar_const_node_get_value","shader_type","id"),&ShaderGraph::scalar_const_node_set_value);
+ ObjectTypeDB::bind_method(_MD("scalar_const_node_get_value","shader_type","id"),&ShaderGraph::scalar_const_node_get_value);
ObjectTypeDB::bind_method(_MD("vec_const_node_set_value","shader_type","id","value"),&ShaderGraph::vec_const_node_set_value);
- ObjectTypeDB::bind_method(_MD("vec_const_node_get_value","shader_type","id"),&ShaderGraph::vec_const_node_set_value);
+ ObjectTypeDB::bind_method(_MD("vec_const_node_get_value","shader_type","id"),&ShaderGraph::vec_const_node_get_value);
ObjectTypeDB::bind_method(_MD("rgb_const_node_set_value","shader_type","id","value"),&ShaderGraph::rgb_const_node_set_value);
- ObjectTypeDB::bind_method(_MD("rgb_const_node_get_value","shader_type","id"),&ShaderGraph::rgb_const_node_set_value);
+ ObjectTypeDB::bind_method(_MD("rgb_const_node_get_value","shader_type","id"),&ShaderGraph::rgb_const_node_get_value);
ObjectTypeDB::bind_method(_MD("xform_const_node_set_value","shader_type","id","value"),&ShaderGraph::xform_const_node_set_value);
- ObjectTypeDB::bind_method(_MD("xform_const_node_get_value","shader_type","id"),&ShaderGraph::xform_const_node_set_value);
+ ObjectTypeDB::bind_method(_MD("xform_const_node_get_value","shader_type","id"),&ShaderGraph::xform_const_node_get_value);
// void get_node_list(ShaderType p_which,List<int> *p_node_list) const;
ObjectTypeDB::bind_method(_MD("texture_node_set_filter_size","shader_type","id","filter_size"),&ShaderGraph::texture_node_set_filter_size);
- ObjectTypeDB::bind_method(_MD("texture_node_get_filter_size","shader_type","id"),&ShaderGraph::texture_node_set_filter_size);
+ ObjectTypeDB::bind_method(_MD("texture_node_get_filter_size","shader_type","id"),&ShaderGraph::texture_node_get_filter_size);
ObjectTypeDB::bind_method(_MD("texture_node_set_filter_strength","shader_type","id","filter_strength"),&ShaderGraph::texture_node_set_filter_strength);
- ObjectTypeDB::bind_method(_MD("texture_node_get_filter_strength","shader_type","id"),&ShaderGraph::texture_node_set_filter_strength);
+ ObjectTypeDB::bind_method(_MD("texture_node_get_filter_strength","shader_type","id"),&ShaderGraph::texture_node_get_filter_strength);
ObjectTypeDB::bind_method(_MD("scalar_op_node_set_op","shader_type","id","op"),&ShaderGraph::scalar_op_node_set_op);
ObjectTypeDB::bind_method(_MD("scalar_op_node_get_op","shader_type","id"),&ShaderGraph::scalar_op_node_get_op);
@@ -260,7 +260,7 @@ void ShaderGraph::_bind_methods() {
ObjectTypeDB::bind_method(_MD("clear","shader_type"),&ShaderGraph::clear);
ObjectTypeDB::bind_method(_MD("node_set_state","shader_type","id","state"),&ShaderGraph::node_set_state);
- ObjectTypeDB::bind_method(_MD("node_get_state:var","shader_type","id"),&ShaderGraph::node_get_state);
+ ObjectTypeDB::bind_method(_MD("node_get_state:Variant","shader_type","id"),&ShaderGraph::node_get_state);
ObjectTypeDB::bind_method(_MD("_set_data"),&ShaderGraph::_set_data);
ObjectTypeDB::bind_method(_MD("_get_data"),&ShaderGraph::_get_data);
@@ -1533,7 +1533,7 @@ const ShaderGraph::NodeSlotInfo ShaderGraph::node_slot_info[]= {
{NODE_CURVE_MAP,{SLOT_TYPE_SCALAR,SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // vec3 interpolation (with optional curve)
{NODE_SCALAR_INPUT,{SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // scalar uniform (assignable in material)
{NODE_VEC_INPUT,{SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // vec3 uniform (assignable in material)
- {NODE_RGB_INPUT,{SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // color uniform (assignable in material)
+ {NODE_RGB_INPUT,{SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // color uniform (assignable in material)
{NODE_XFORM_INPUT,{SLOT_MAX},{SLOT_TYPE_XFORM,SLOT_MAX}}, // mat4 uniform (assignable in material)
{NODE_TEXTURE_INPUT,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // texture input (assignable in material)
{NODE_CUBEMAP_INPUT,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // cubemap input (assignable in material)
@@ -2576,8 +2576,9 @@ void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<Str
String name = p_node->param1;
Color dv= p_node->param2;
- code +="uniform color "+name+"=vec4("+rtos(dv.r)+","+rtos(dv.g)+","+rtos(dv.g)+","+rtos(dv.a)+");\n";
+ code +="uniform color "+name+"=vec4("+rtos(dv.r)+","+rtos(dv.g)+","+rtos(dv.b)+","+rtos(dv.a)+");\n";
code += OUTNAME(p_node->id,0)+"="+name+".rgb;\n";
+ code += OUTNAME(p_node->id,1)+"="+name+".a;\n";
}break;
case NODE_XFORM_INPUT: {
diff --git a/scene/resources/shader_graph.h b/scene/resources/shader_graph.h
index f867ae0388..1e6fc3507c 100644
--- a/scene/resources/shader_graph.h
+++ b/scene/resources/shader_graph.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/shape.cpp b/scene/resources/shape.cpp
index 143ef82d51..a71e414f61 100644
--- a/scene/resources/shape.cpp
+++ b/scene/resources/shape.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/shape.h b/scene/resources/shape.h
index 1992ce51c3..bfd423a300 100644
--- a/scene/resources/shape.h
+++ b/scene/resources/shape.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp
index 31b28ee892..6a9773bf14 100644
--- a/scene/resources/shape_2d.cpp
+++ b/scene/resources/shape_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -108,8 +108,8 @@ void Shape2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_custom_solver_bias"),&Shape2D::get_custom_solver_bias);
ObjectTypeDB::bind_method(_MD("collide","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide);
ObjectTypeDB::bind_method(_MD("collide_with_motion","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_with_motion);
- ObjectTypeDB::bind_method(_MD("collide_and_get_contacts:var","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide_and_get_contacts);
- ObjectTypeDB::bind_method(_MD("collide_with_motion_and_get_contacts:var","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_with_motion_and_get_contacts);
+ ObjectTypeDB::bind_method(_MD("collide_and_get_contacts:Variant","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide_and_get_contacts);
+ ObjectTypeDB::bind_method(_MD("collide_with_motion_and_get_contacts:Variant","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_with_motion_and_get_contacts);
ADD_PROPERTY( PropertyInfo(Variant::REAL,"custom_solver_bias",PROPERTY_HINT_RANGE,"0,1,0.001"),_SCS("set_custom_solver_bias"),_SCS("get_custom_solver_bias"));
}
diff --git a/scene/resources/shape_2d.h b/scene/resources/shape_2d.h
index 1737301d9d..4059af62c6 100644
--- a/scene/resources/shape_2d.h
+++ b/scene/resources/shape_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/shape_line_2d.cpp b/scene/resources/shape_line_2d.cpp
index 97e9985754..4133d2218f 100644
--- a/scene/resources/shape_line_2d.cpp
+++ b/scene/resources/shape_line_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/shape_line_2d.h b/scene/resources/shape_line_2d.h
index f32ad7fb7c..f6f75e7a95 100644
--- a/scene/resources/shape_line_2d.h
+++ b/scene/resources/shape_line_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/space_2d.cpp b/scene/resources/space_2d.cpp
index 6dbf7c4a73..d328ee3de4 100644
--- a/scene/resources/space_2d.cpp
+++ b/scene/resources/space_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/space_2d.h b/scene/resources/space_2d.h
index eb3e13ee62..270f8de3ea 100644
--- a/scene/resources/space_2d.h
+++ b/scene/resources/space_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/sphere_shape.cpp b/scene/resources/sphere_shape.cpp
index a7e28eb727..4764937371 100644
--- a/scene/resources/sphere_shape.cpp
+++ b/scene/resources/sphere_shape.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/sphere_shape.h b/scene/resources/sphere_shape.h
index 2543d94439..50682f38bb 100644
--- a/scene/resources/sphere_shape.h
+++ b/scene/resources/sphere_shape.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index 527fae5946..71a775ee24 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -83,7 +83,7 @@ void StyleBox::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_center_size"),&StyleBox::get_center_size);
ObjectTypeDB::bind_method(_MD("get_offset"),&StyleBox::get_offset);
- ObjectTypeDB::bind_method(_MD("draw"),&StyleBox::draw);
+ ObjectTypeDB::bind_method(_MD("draw","canvas_item","rect"),&StyleBox::draw);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/left", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_LEFT );
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/right", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_RIGHT );
@@ -182,10 +182,10 @@ void StyleBoxTexture::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_texture:Texture"),&StyleBoxTexture::get_texture);
ObjectTypeDB::bind_method(_MD("set_margin_size","margin","size"),&StyleBoxTexture::set_margin_size);
- ObjectTypeDB::bind_method(_MD("get_margin_size"),&StyleBoxTexture::get_margin_size);
+ ObjectTypeDB::bind_method(_MD("get_margin_size","margin"),&StyleBoxTexture::get_margin_size);
ObjectTypeDB::bind_method(_MD("set_expand_margin_size","margin","size"),&StyleBoxTexture::set_expand_margin_size);
- ObjectTypeDB::bind_method(_MD("get_expand_margin_size"),&StyleBoxTexture::get_expand_margin_size);
+ ObjectTypeDB::bind_method(_MD("get_expand_margin_size","margin"),&StyleBoxTexture::get_expand_margin_size);
ObjectTypeDB::bind_method(_MD("set_draw_center","enable"),&StyleBoxTexture::set_draw_center);
ObjectTypeDB::bind_method(_MD("get_draw_center"),&StyleBoxTexture::get_draw_center);
@@ -392,7 +392,7 @@ void StyleBoxImageMask::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_expand","expand"),&StyleBoxImageMask::set_expand);
ObjectTypeDB::bind_method(_MD("get_expand"),&StyleBoxImageMask::get_expand);
ObjectTypeDB::bind_method(_MD("set_expand_margin_size","margin","size"),&StyleBoxImageMask::set_expand_margin_size);
- ObjectTypeDB::bind_method(_MD("get_expand_margin_size"),&StyleBoxImageMask::get_expand_margin_size);
+ ObjectTypeDB::bind_method(_MD("get_expand_margin_size","margin"),&StyleBoxImageMask::get_expand_margin_size);
ADD_PROPERTY( PropertyInfo(Variant::IMAGE, "image"), _SCS("set_image"), _SCS("get_image"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "expand"), _SCS("set_expand"), _SCS("get_expand"));
diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h
index 337bb54026..d0466ed5f1 100644
--- a/scene/resources/style_box.h
+++ b/scene/resources/style_box.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index 418df97f51..bf5070fd7d 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h
index ed91b4df61..1d329f23c0 100644
--- a/scene/resources/surface_tool.h
+++ b/scene/resources/surface_tool.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 994473f11e..28754480f1 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -70,9 +70,9 @@ void Texture::_bind_methods() {
ObjectTypeDB::bind_method(_MD("has_alpha"),&Texture::has_alpha);
ObjectTypeDB::bind_method(_MD("set_flags","flags"),&Texture::set_flags);
ObjectTypeDB::bind_method(_MD("get_flags"),&Texture::get_flags);
- ObjectTypeDB::bind_method(_MD("draw","canvas_item","pos","modulate"),&Texture::draw,DEFVAL(Color(1,1,1)),DEFVAL(false));
- ObjectTypeDB::bind_method(_MD("draw_rect","canvas_item","rect","tile","modulate"),&Texture::draw_rect,DEFVAL(Color(1,1,1)),DEFVAL(false));
- ObjectTypeDB::bind_method(_MD("draw_rect_region","canvas_item","rect","src_rect","modulate"),&Texture::draw_rect_region,DEFVAL(Color(1,1,1)),DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("draw","canvas_item","pos","modulate","transpose"),&Texture::draw,DEFVAL(Color(1,1,1)),DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("draw_rect","canvas_item","rect","tile","modulate","transpose"),&Texture::draw_rect,DEFVAL(Color(1,1,1)),DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("draw_rect_region","canvas_item","rect","src_rect","modulate","transpose"),&Texture::draw_rect_region,DEFVAL(Color(1,1,1)),DEFVAL(false));
BIND_CONSTANT( FLAG_MIPMAPS );
BIND_CONSTANT( FLAG_REPEAT );
@@ -329,6 +329,16 @@ void ImageTexture::normal_to_xy() {
create_from_image(img,flags);
}
+void ImageTexture::shrink_x2_and_keep_size() {
+
+ Size2 sizeov=get_size();
+ Image img = get_data();
+ img.resize(img.get_width()/2,img.get_height()/2,Image::INTERPOLATE_BILINEAR);
+ create_from_image(img,flags);
+ set_size_override(sizeov);
+
+}
+
bool ImageTexture::has_alpha() const {
return ( format==Image::FORMAT_GRAYSCALE_ALPHA || format==Image::FORMAT_INDEXED_ALPHA || format==Image::FORMAT_RGBA );
@@ -424,10 +434,13 @@ void ImageTexture::_bind_methods() {
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("shrink_x2_and_keep_size"),&ImageTexture::shrink_x2_and_keep_size);
+
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::set_method_flags(get_type_static(),_SCS("shrink_x2_and_keep_size"),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 1a4f211af1..2627b9480a 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -148,6 +148,7 @@ public:
void fix_alpha_edges();
void premultiply_alpha();
void normal_to_xy();
+ void shrink_x2_and_keep_size();
void set_size_override(const Size2& p_size);
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index 651e234b49..685b2e07e1 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -266,7 +266,52 @@ void Theme::get_icon_list(StringName p_type, List<StringName> *p_list) const {
p_list->push_back(*key);
}
+
+}
+
+void Theme::set_shader(const StringName &p_name,const StringName &p_type,const Ref<Shader>& p_shader) {
+ bool new_value=!shader_map.has(p_type) || !shader_map[p_type].has(p_name);
+
+ shader_map[p_type][p_name]=p_shader;
+ if (new_value) {
+ _change_notify();
+ emit_changed();;
+ }
+}
+
+Ref<Shader> Theme::get_shader(const StringName &p_name, const StringName &p_type) const {
+ if (shader_map.has(p_type) && shader_map[p_type].has(p_name) && shader_map[p_type][p_name].is_valid()) {
+ return shader_map[p_type][p_name];
+ } else {
+ return NULL;
+ }
+}
+
+bool Theme::has_shader(const StringName &p_name, const StringName &p_type) const {
+ return (shader_map.has(p_type) && shader_map[p_type].has(p_name) && shader_map[p_type][p_name].is_valid());
+}
+
+void Theme::clear_shader(const StringName &p_name, const StringName &p_type) {
+ ERR_FAIL_COND(!shader_map.has(p_type));
+ ERR_FAIL_COND(!shader_map[p_type].has(p_name));
+
+ shader_map[p_type].erase(p_name);
+ _change_notify();
+ emit_changed();;
+}
+
+void Theme::get_shader_list(const StringName &p_type, List<StringName> *p_list) const {
+ if (!shader_map.has(p_type))
+ return;
+
+ const StringName *key=NULL;
+
+ while((key=shader_map[p_type].next(key))) {
+
+ p_list->push_back(*key);
+ }
+
}
@@ -552,36 +597,36 @@ void Theme::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_icon:Texture","name","type"),&Theme::get_icon);
ObjectTypeDB::bind_method(_MD("has_icon","name","type"),&Theme::has_icon);
ObjectTypeDB::bind_method(_MD("clear_icon","name","type"),&Theme::clear_icon);
- ObjectTypeDB::bind_method(_MD("get_icon_list"),&Theme::_get_icon_list);
+ ObjectTypeDB::bind_method(_MD("get_icon_list","type"),&Theme::_get_icon_list);
ObjectTypeDB::bind_method(_MD("set_stylebox","name","type","texture:StyleBox"),&Theme::set_stylebox);
ObjectTypeDB::bind_method(_MD("get_stylebox:StyleBox","name","type"),&Theme::get_stylebox);
ObjectTypeDB::bind_method(_MD("has_stylebox","name","type"),&Theme::has_stylebox);
ObjectTypeDB::bind_method(_MD("clear_stylebox","name","type"),&Theme::clear_stylebox);
- ObjectTypeDB::bind_method(_MD("get_stylebox_list"),&Theme::_get_stylebox_list);
+ ObjectTypeDB::bind_method(_MD("get_stylebox_list","type"),&Theme::_get_stylebox_list);
ObjectTypeDB::bind_method(_MD("set_font","name","type","font:Font"),&Theme::set_font);
ObjectTypeDB::bind_method(_MD("get_font:Font","name","type"),&Theme::get_font);
ObjectTypeDB::bind_method(_MD("has_font","name","type"),&Theme::has_font);
ObjectTypeDB::bind_method(_MD("clear_font","name","type"),&Theme::clear_font);
- ObjectTypeDB::bind_method(_MD("get_font_list"),&Theme::_get_font_list);
+ ObjectTypeDB::bind_method(_MD("get_font_list","type"),&Theme::_get_font_list);
ObjectTypeDB::bind_method(_MD("set_color","name","type","color"),&Theme::set_color);
ObjectTypeDB::bind_method(_MD("get_color","name","type"),&Theme::get_color);
ObjectTypeDB::bind_method(_MD("has_color","name","type"),&Theme::has_color);
ObjectTypeDB::bind_method(_MD("clear_color","name","type"),&Theme::clear_color);
- ObjectTypeDB::bind_method(_MD("get_color_list"),&Theme::_get_color_list);
+ ObjectTypeDB::bind_method(_MD("get_color_list","type"),&Theme::_get_color_list);
ObjectTypeDB::bind_method(_MD("set_constant","name","type","constant"),&Theme::set_constant);
ObjectTypeDB::bind_method(_MD("get_constant","name","type"),&Theme::get_constant);
ObjectTypeDB::bind_method(_MD("has_constant","name","type"),&Theme::has_constant);
ObjectTypeDB::bind_method(_MD("clear_constant","name","type"),&Theme::clear_constant);
- ObjectTypeDB::bind_method(_MD("get_constant_list"),&Theme::_get_constant_list);
+ ObjectTypeDB::bind_method(_MD("get_constant_list","type"),&Theme::_get_constant_list);
ObjectTypeDB::bind_method(_MD("set_default_font","font"),&Theme::set_default_theme_font);
ObjectTypeDB::bind_method(_MD("get_default_font"),&Theme::get_default_theme_font);
- ObjectTypeDB::bind_method(_MD("get_type_list"),&Theme::_get_type_list);
+ ObjectTypeDB::bind_method(_MD("get_type_list","type"),&Theme::_get_type_list);
ObjectTypeDB::bind_method("copy_default_theme",&Theme::copy_default_theme);
diff --git a/scene/resources/theme.h b/scene/resources/theme.h
index cfa0762595..180f55381d 100644
--- a/scene/resources/theme.h
+++ b/scene/resources/theme.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,6 +33,7 @@
#include "scene/resources/font.h"
#include "scene/resources/style_box.h"
#include "scene/resources/texture.h"
+#include "scene/resources/shader.h"
#include "io/resource_loader.h"
/**
@@ -48,6 +49,7 @@ class Theme : public Resource {
HashMap<StringName,HashMap<StringName,Ref<Texture>,StringNameHasher >, StringNameHasher > icon_map;
HashMap<StringName,HashMap<StringName,Ref<StyleBox>,StringNameHasher >,StringNameHasher > style_map;
HashMap<StringName,HashMap<StringName,Ref<Font>,StringNameHasher >,StringNameHasher > font_map;
+ HashMap<StringName,HashMap<StringName,Ref<Shader>,StringNameHasher >, StringNameHasher > shader_map;
HashMap<StringName,HashMap<StringName,Color,StringNameHasher >,StringNameHasher > color_map;
HashMap<StringName,HashMap<StringName,int,StringNameHasher>,StringNameHasher > constant_map;
protected:
@@ -86,7 +88,13 @@ public:
bool has_icon(const StringName& p_name,const StringName& p_type) const;
void clear_icon(const StringName& p_name,const StringName& p_type);
void get_icon_list(StringName p_type, List<StringName> *p_list) const;
-
+
+ void set_shader(const StringName& p_name,const StringName& p_type,const Ref<Shader>& p_shader);
+ Ref<Shader> get_shader(const StringName& p_name,const StringName& p_type) const;
+ bool has_shader(const StringName& p_name,const StringName& p_type) const;
+ void clear_shader(const StringName& p_name,const StringName& p_type);
+ void get_shader_list(const StringName& p_name, List<StringName> *p_list) const;
+
void set_stylebox(const StringName& p_name,const StringName& p_type,const Ref<StyleBox>& p_style);
Ref<StyleBox> get_stylebox(const StringName& p_name,const StringName& p_type) const;
bool has_stylebox(const StringName& p_name,const StringName& p_type) const;
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 28e179b34c..6f71287750 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 96048bf06b..fb0e832c1e 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/video_stream.cpp b/scene/resources/video_stream.cpp
index c957fd4c67..8e16f2e024 100644
--- a/scene/resources/video_stream.cpp
+++ b/scene/resources/video_stream.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/video_stream.h b/scene/resources/video_stream.h
index a23ef0c64f..b05a7cf773 100644
--- a/scene/resources/video_stream.h
+++ b/scene/resources/video_stream.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/volume.cpp b/scene/resources/volume.cpp
index a668a39c4f..8eb96cb4ad 100644
--- a/scene/resources/volume.cpp
+++ b/scene/resources/volume.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/volume.h b/scene/resources/volume.h
index f929792b74..be3cbddbbd 100644
--- a/scene/resources/volume.h
+++ b/scene/resources/volume.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/world.cpp b/scene/resources/world.cpp
index fb3469102c..0a88abf252 100644
--- a/scene/resources/world.cpp
+++ b/scene/resources/world.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/world.h b/scene/resources/world.h
index 165122124d..5a74f27235 100644
--- a/scene/resources/world.h
+++ b/scene/resources/world.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp
index 3b1f1d2346..8cacc0fce7 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h
index a3a79dee09..a939d935c4 100644
--- a/scene/resources/world_2d.h
+++ b/scene/resources/world_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index 9509878dc9..57bde00de4 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 48f17ed38b..b2c0e9abf0 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp
index dd5243e467..d0695451b9 100644
--- a/servers/audio/audio_driver_dummy.cpp
+++ b/servers/audio/audio_driver_dummy.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h
index 04926b89eb..9421574f93 100644
--- a/servers/audio/audio_driver_dummy.h
+++ b/servers/audio/audio_driver_dummy.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/audio_filter_sw.cpp b/servers/audio/audio_filter_sw.cpp
index 032d93b617..3fb8e8f734 100644
--- a/servers/audio/audio_filter_sw.cpp
+++ b/servers/audio/audio_filter_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/audio_filter_sw.h b/servers/audio/audio_filter_sw.h
index e8540adea6..d4d225ce29 100644
--- a/servers/audio/audio_filter_sw.h
+++ b/servers/audio/audio_filter_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/audio_mixer_sw.cpp b/servers/audio/audio_mixer_sw.cpp
index 033cd333d5..d1f36cb7b6 100644
--- a/servers/audio/audio_mixer_sw.cpp
+++ b/servers/audio/audio_mixer_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/audio_mixer_sw.h b/servers/audio/audio_mixer_sw.h
index d8d9b7bacd..f5bd4cc5ba 100644
--- a/servers/audio/audio_mixer_sw.h
+++ b/servers/audio/audio_mixer_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/audio_server_sw.cpp b/servers/audio/audio_server_sw.cpp
index 417a582da6..d634c348dc 100644
--- a/servers/audio/audio_server_sw.cpp
+++ b/servers/audio/audio_server_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -360,7 +360,7 @@ void AudioServerSW::sample_set_description(RID p_sample, const String& p_descrip
AUDIO_LOCK
sample_manager->sample_set_description(p_sample,p_description);
}
-String AudioServerSW::sample_get_description(RID p_sample, const String& p_description) const {
+String AudioServerSW::sample_get_description(RID p_sample) const {
AUDIO_LOCK
return sample_manager->sample_get_description(p_sample);
@@ -659,7 +659,7 @@ bool AudioServerSW::voice_is_active(RID p_voice) const {
RID AudioServerSW::audio_stream_create(AudioStream *p_stream) {
- AUDIO_LOCK
+ AUDIO_LOCK
Stream *s = memnew(Stream);
s->audio_stream=p_stream;
s->event_stream=NULL;
@@ -693,11 +693,11 @@ void AudioServerSW::stream_set_active(RID p_stream, bool p_active) {
Stream *s = stream_owner.get(p_stream);
ERR_FAIL_COND(!s);
+ _THREAD_SAFE_METHOD_
if (s->active==p_active)
return;
AUDIO_LOCK;
- _THREAD_SAFE_METHOD_
s->active=p_active;
if (p_active)
s->E=active_audio_streams.push_back(s);
@@ -705,6 +705,8 @@ void AudioServerSW::stream_set_active(RID p_stream, bool p_active) {
active_audio_streams.erase(s->E);
s->E=NULL;
}
+
+
}
bool AudioServerSW::stream_is_active(RID p_stream) const {
@@ -763,7 +765,6 @@ void AudioServerSW::free(RID p_id) {
void AudioServerSW::_thread_func(void *self) {
-
AudioServerSW *as=(AudioServerSW *)self;
while (!as->exit_update_thread) {
@@ -806,6 +807,7 @@ void AudioServerSW::init() {
#ifndef NO_THREADS
exit_update_thread=false;
thread = Thread::create(_thread_func,this);
+ thread->set_name("AudioServerSW");
#endif
}
diff --git a/servers/audio/audio_server_sw.h b/servers/audio/audio_server_sw.h
index c566e129c1..bc6191729c 100644
--- a/servers/audio/audio_server_sw.h
+++ b/servers/audio/audio_server_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -118,7 +118,7 @@ public:
virtual RID sample_create(SampleFormat p_format, bool p_stereo, int p_length);
virtual void sample_set_description(RID p_sample, const String& p_description);
- virtual String sample_get_description(RID p_sample, const String& p_description) const;
+ virtual String sample_get_description(RID p_sample) const;
virtual SampleFormat sample_get_format(RID p_sample) const;
virtual bool sample_is_stereo(RID p_sample) const;
diff --git a/servers/audio/reverb_buffers_sw.cpp b/servers/audio/reverb_buffers_sw.cpp
index b840b9390b..04bc056313 100644
--- a/servers/audio/reverb_buffers_sw.cpp
+++ b/servers/audio/reverb_buffers_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/reverb_buffers_sw.h b/servers/audio/reverb_buffers_sw.h
index 817122b65d..f5885e6ee8 100644
--- a/servers/audio/reverb_buffers_sw.h
+++ b/servers/audio/reverb_buffers_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/reverb_sw.cpp b/servers/audio/reverb_sw.cpp
index cc4b4bd778..5721403ba3 100644
--- a/servers/audio/reverb_sw.cpp
+++ b/servers/audio/reverb_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/reverb_sw.h b/servers/audio/reverb_sw.h
index 937824f907..b028a245c8 100644
--- a/servers/audio/reverb_sw.h
+++ b/servers/audio/reverb_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/sample_manager_sw.cpp b/servers/audio/sample_manager_sw.cpp
index 375aa88cd2..60f4d16659 100644
--- a/servers/audio/sample_manager_sw.cpp
+++ b/servers/audio/sample_manager_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/sample_manager_sw.h b/servers/audio/sample_manager_sw.h
index 94254f99d5..bd7a11a3d2 100644
--- a/servers/audio/sample_manager_sw.h
+++ b/servers/audio/sample_manager_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/voice_rb_sw.cpp b/servers/audio/voice_rb_sw.cpp
index a385e15283..8d12e5085d 100644
--- a/servers/audio/voice_rb_sw.cpp
+++ b/servers/audio/voice_rb_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/voice_rb_sw.h b/servers/audio/voice_rb_sw.h
index cbebcdb86f..f785646577 100644
--- a/servers/audio/voice_rb_sw.h
+++ b/servers/audio/voice_rb_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 6c5a2de97b..1f0a2e403a 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -48,26 +48,51 @@ AudioServer *AudioServer::get_singleton() {
void AudioServer::sample_set_signed_data(RID p_sample, const DVector<float>& p_buffer) {
+ SampleFormat format = sample_get_format(p_sample);
+
+ ERR_EXPLAIN("IMA ADPCM is not supported.");
+ ERR_FAIL_COND(format==SAMPLE_FORMAT_IMA_ADPCM);
+
int len = p_buffer.size();
ERR_FAIL_COND( len == 0 );
DVector<uint8_t> data;
- data.resize(len*2);
- DVector<uint8_t>::Write w=data.write();
-
- int16_t *samples = (int16_t*)w.ptr();
-
+ DVector<uint8_t>::Write w;
DVector<float>::Read r = p_buffer.read();
- for(int i=0;i<len;i++) {
-
- float sample = r[i];
- sample = Math::floor( sample * (1<<16) );
- if (sample<-32768)
- sample=-32768;
- else if (sample>32767)
- sample=32767;
- samples[i]=sample;
+ switch(format) {
+ case SAMPLE_FORMAT_PCM8: {
+ data.resize(len);
+ w=data.write();
+
+ int8_t *samples8 = (int8_t*)w.ptr();
+
+ for(int i=0;i<len;i++) {
+
+ float sample = Math::floor( r[i] * (1<<8) );
+ if (sample<-128)
+ sample=-128;
+ else if (sample>127)
+ sample=127;
+ samples8[i]=sample;
+ }
+ } break;
+ case SAMPLE_FORMAT_PCM16: {
+ data.resize(len*2);
+ w=data.write();
+
+ int16_t *samples16 = (int16_t*)w.ptr();
+
+ for(int i=0;i<len;i++) {
+
+ float sample = Math::floor( r[i] * (1<<16) );
+ if (sample<-32768)
+ sample=-32768;
+ else if (sample>32767)
+ sample=32767;
+ samples16[i]=sample;
+ }
+ } break;
}
w = DVector<uint8_t>::Write();
@@ -88,7 +113,7 @@ void AudioServer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("sample_get_length","sample"), &AudioServer::sample_get_length );
ObjectTypeDB::bind_method(_MD("sample_set_signed_data","sample","data"), &AudioServer::sample_set_signed_data );
- ObjectTypeDB::bind_method(_MD("sample_set_data","sample"), &AudioServer::sample_set_data );
+ ObjectTypeDB::bind_method(_MD("sample_set_data","sample","data"), &AudioServer::sample_set_data );
ObjectTypeDB::bind_method(_MD("sample_get_data","sample"), &AudioServer::sample_get_data );
ObjectTypeDB::bind_method(_MD("sample_set_mix_rate","sample","mix_rate"), &AudioServer::sample_set_mix_rate );
diff --git a/servers/audio_server.h b/servers/audio_server.h
index cd3e920f31..c56820dcbb 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -160,7 +160,7 @@ public:
virtual RID sample_create(SampleFormat p_format, bool p_stereo, int p_length)=0;
virtual void sample_set_description(RID p_sample, const String& p_description)=0;
- virtual String sample_get_description(RID p_sample, const String& p_description) const=0;
+ virtual String sample_get_description(RID p_sample) const=0;
virtual SampleFormat sample_get_format(RID p_sample) const=0;
virtual bool sample_is_stereo(RID p_sample) const=0;
diff --git a/servers/physics/area_pair_sw.cpp b/servers/physics/area_pair_sw.cpp
index 3eb96fb681..c6bf6114a0 100644
--- a/servers/physics/area_pair_sw.cpp
+++ b/servers/physics/area_pair_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/area_pair_sw.h b/servers/physics/area_pair_sw.h
index 4f8087280a..09a2934467 100644
--- a/servers/physics/area_pair_sw.h
+++ b/servers/physics/area_pair_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/area_sw.cpp b/servers/physics/area_sw.cpp
index e78f0699cb..dbc82da316 100644
--- a/servers/physics/area_sw.cpp
+++ b/servers/physics/area_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h
index 40ccdaf370..622eeb5e23 100644
--- a/servers/physics/area_sw.h
+++ b/servers/physics/area_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp
index 7eab9eb86d..a971cdaad8 100644
--- a/servers/physics/body_pair_sw.cpp
+++ b/servers/physics/body_pair_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/body_pair_sw.h b/servers/physics/body_pair_sw.h
index 8ec7a9ccef..da637ade05 100644
--- a/servers/physics/body_pair_sw.h
+++ b/servers/physics/body_pair_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp
index 8edbaf0b89..b0ed99cb48 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -380,9 +380,11 @@ void BodySW::set_space(SpaceSW *p_space){
}
+ first_integration=true;
+
}
-void BodySW::_compute_area_gravity(const AreaSW *p_area) {
+void BodySW::_compute_area_gravity_and_dampenings(const AreaSW *p_area) {
if (p_area->is_gravity_point()) {
if(p_area->get_gravity_distance_scale() > 0) {
@@ -394,6 +396,9 @@ void BodySW::_compute_area_gravity(const AreaSW *p_area) {
} else {
gravity += p_area->get_gravity_vector() * p_area->get_gravity();
}
+
+ area_linear_damp += p_area->get_linear_damp();
+ area_angular_damp += p_area->get_angular_damp();
}
void BodySW::integrate_forces(real_t p_step) {
@@ -403,41 +408,56 @@ void BodySW::integrate_forces(real_t p_step) {
return;
AreaSW *def_area = get_space()->get_default_area();
- AreaSW *damp_area = def_area;
+ // AreaSW *damp_area = def_area;
ERR_FAIL_COND(!def_area);
int ac = areas.size();
- bool replace = false;
- gravity=Vector3(0,0,0);
+ bool stopped = false;
+ gravity = Vector3(0,0,0);
+ area_linear_damp = 0;
+ area_angular_damp = 0;
if (ac) {
areas.sort();
const AreaCMP *aa = &areas[0];
- damp_area = aa[ac-1].area;
- for(int i=ac-1;i>=0;i--) {
- _compute_area_gravity(aa[i].area);
- if (aa[i].area->get_space_override_mode() == PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE) {
- replace = true;
- break;
+ // damp_area = aa[ac-1].area;
+ for(int i=ac-1;i>=0 && !stopped;i--) {
+ PhysicsServer::AreaSpaceOverrideMode mode=aa[i].area->get_space_override_mode();
+ switch (mode) {
+ case PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE:
+ case PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+ _compute_area_gravity_and_dampenings(aa[i].area);
+ stopped = mode==PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+ } break;
+ case PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE:
+ case PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+ gravity = Vector3(0,0,0);
+ area_angular_damp = 0;
+ area_linear_damp = 0;
+ _compute_area_gravity_and_dampenings(aa[i].area);
+ stopped = mode==PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE;
+ } break;
+ default: {}
}
}
}
- if( !replace ) {
- _compute_area_gravity(def_area);
+ if( !stopped ) {
+ _compute_area_gravity_and_dampenings(def_area);
}
gravity*=gravity_scale;
+ // If less than 0, override dampenings with that of the Body
if (angular_damp>=0)
area_angular_damp=angular_damp;
- else
- area_angular_damp=damp_area->get_angular_damp();
+ //else
+ // area_angular_damp=damp_area->get_angular_damp();
if (linear_damp>=0)
area_linear_damp=linear_damp;
- else
- area_linear_damp=damp_area->get_linear_damp();
+ //else
+ // area_linear_damp=damp_area->get_linear_damp();
Vector3 motion;
@@ -461,7 +481,7 @@ void BodySW::integrate_forces(real_t p_step) {
do_motion=true;
} else {
- if (!omit_force_integration) {
+ if (!omit_force_integration && !first_integration) {
//overriden by direct state query
Vector3 force=gravity*mass;
@@ -494,6 +514,7 @@ void BodySW::integrate_forces(real_t p_step) {
applied_force=Vector3();
applied_torque=Vector3();
+ first_integration=false;
//motion=linear_velocity*p_step;
@@ -731,6 +752,7 @@ BodySW::BodySW() : CollisionObjectSW(TYPE_BODY), active_list(this), inertia_upda
island_next=NULL;
island_list_next=NULL;
first_time_kinematic=false;
+ first_integration=false;
_set_static(false);
contact_count=0;
diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h
index 1a45a02744..870e8357f1 100644
--- a/servers/physics/body_sw.h
+++ b/servers/physics/body_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -79,6 +79,8 @@ class BodySW : public CollisionObjectSW {
bool omit_force_integration;
bool active;
+ bool first_integration;
+
bool continuous_cd;
bool can_sleep;
bool first_time_kinematic;
@@ -131,7 +133,7 @@ class BodySW : public CollisionObjectSW {
BodySW *island_next;
BodySW *island_list_next;
- _FORCE_INLINE_ void _compute_area_gravity(const AreaSW *p_area);
+ _FORCE_INLINE_ void _compute_area_gravity_and_dampenings(const AreaSW *p_area);
_FORCE_INLINE_ void _update_inertia_tensor();
diff --git a/servers/physics/broad_phase_basic.cpp b/servers/physics/broad_phase_basic.cpp
index c49caed795..0bed56d398 100644
--- a/servers/physics/broad_phase_basic.cpp
+++ b/servers/physics/broad_phase_basic.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/broad_phase_basic.h b/servers/physics/broad_phase_basic.h
index 9848c4b16e..6bf024044e 100644
--- a/servers/physics/broad_phase_basic.h
+++ b/servers/physics/broad_phase_basic.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/broad_phase_octree.cpp b/servers/physics/broad_phase_octree.cpp
index 874ae29755..bfe41f8423 100644
--- a/servers/physics/broad_phase_octree.cpp
+++ b/servers/physics/broad_phase_octree.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/broad_phase_octree.h b/servers/physics/broad_phase_octree.h
index 200878f6df..b87996a58c 100644
--- a/servers/physics/broad_phase_octree.h
+++ b/servers/physics/broad_phase_octree.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/broad_phase_sw.cpp b/servers/physics/broad_phase_sw.cpp
index 910be4e623..a382df6a46 100644
--- a/servers/physics/broad_phase_sw.cpp
+++ b/servers/physics/broad_phase_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/broad_phase_sw.h b/servers/physics/broad_phase_sw.h
index 2bf9f202e2..409c249865 100644
--- a/servers/physics/broad_phase_sw.h
+++ b/servers/physics/broad_phase_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/collision_object_sw.cpp b/servers/physics/collision_object_sw.cpp
index 19b3f28a2f..55c8c1b955 100644
--- a/servers/physics/collision_object_sw.cpp
+++ b/servers/physics/collision_object_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h
index c018ab6224..592c84e667 100644
--- a/servers/physics/collision_object_sw.h
+++ b/servers/physics/collision_object_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/collision_solver_sat.cpp b/servers/physics/collision_solver_sat.cpp
index 72e61f1456..8789663f63 100644
--- a/servers/physics/collision_solver_sat.cpp
+++ b/servers/physics/collision_solver_sat.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/collision_solver_sat.h b/servers/physics/collision_solver_sat.h
index 686b587243..57f5bdbbc0 100644
--- a/servers/physics/collision_solver_sat.h
+++ b/servers/physics/collision_solver_sat.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp
index b5a5c64660..716e724637 100644
--- a/servers/physics/collision_solver_sw.cpp
+++ b/servers/physics/collision_solver_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/collision_solver_sw.h b/servers/physics/collision_solver_sw.h
index 5ed5260b7d..abc50cae2c 100644
--- a/servers/physics/collision_solver_sw.h
+++ b/servers/physics/collision_solver_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/constraint_sw.cpp b/servers/physics/constraint_sw.cpp
index fb45485233..ce0e1e6963 100644
--- a/servers/physics/constraint_sw.cpp
+++ b/servers/physics/constraint_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/constraint_sw.h b/servers/physics/constraint_sw.h
index 1ec237f9c5..d61701ac07 100644
--- a/servers/physics/constraint_sw.h
+++ b/servers/physics/constraint_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/gjk_epa.cpp b/servers/physics/gjk_epa.cpp
index 9b5b3d4f67..229c6d3fb4 100644
--- a/servers/physics/gjk_epa.cpp
+++ b/servers/physics/gjk_epa.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/servers/physics/gjk_epa.h b/servers/physics/gjk_epa.h
index 08b0a65b15..23f51d66c4 100644
--- a/servers/physics/gjk_epa.h
+++ b/servers/physics/gjk_epa.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/servers/physics/joints_sw.cpp b/servers/physics/joints_sw.cpp
index aa9d3265d2..7f7df31534 100644
--- a/servers/physics/joints_sw.cpp
+++ b/servers/physics/joints_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/joints_sw.h b/servers/physics/joints_sw.h
index d7ba6ef925..c42baae961 100644
--- a/servers/physics/joints_sw.h
+++ b/servers/physics/joints_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index a9a8042c19..5eb14d80dc 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -517,7 +517,7 @@ void PhysicsServerSW::body_set_mode(RID p_body, BodyMode p_mode) {
body->set_mode(p_mode);
};
-PhysicsServer::BodyMode PhysicsServerSW::body_get_mode(RID p_body, BodyMode p_mode) const {
+PhysicsServer::BodyMode PhysicsServerSW::body_get_mode(RID p_body) const {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,BODY_MODE_STATIC);
diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h
index abbb057616..2aadac2216 100644
--- a/servers/physics/physics_server_sw.h
+++ b/servers/physics/physics_server_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -146,7 +146,7 @@ public:
virtual RID body_get_space(RID p_body) const;
virtual void body_set_mode(RID p_body, BodyMode p_mode);
- virtual BodyMode body_get_mode(RID p_body, BodyMode p_mode) const;
+ virtual BodyMode body_get_mode(RID p_body) const;
virtual void body_add_shape(RID p_body, RID p_shape, const Transform& p_transform=Transform());
virtual void body_set_shape(RID p_body, int p_shape_idx,RID p_shape);
diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp
index fabfa88ee5..5923f89120 100644
--- a/servers/physics/shape_sw.cpp
+++ b/servers/physics/shape_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1354,6 +1354,10 @@ void ConcavePolygonShapeSW::_fill_bvh(_VolumeSW_BVH* p_bvh_tree,BVH* p_bvh_array
void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) {
int src_face_count=p_faces.size();
+ if (src_face_count==0) {
+ configure(AABB());
+ return;
+ }
ERR_FAIL_COND(src_face_count%3);
src_face_count/=3;
diff --git a/servers/physics/shape_sw.h b/servers/physics/shape_sw.h
index 4826eaea4f..39779bcda3 100644
--- a/servers/physics/shape_sw.h
+++ b/servers/physics/shape_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp
index ba1c737530..08f280a976 100644
--- a/servers/physics/space_sw.cpp
+++ b/servers/physics/space_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -47,7 +47,7 @@ _FORCE_INLINE_ static bool _match_object_type_query(CollisionObjectSW *p_object,
}
-bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vector3& p_to,RayResult &r_result,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
+bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vector3& p_to, RayResult &r_result, const Set<RID>& p_exclude, uint32_t p_layer_mask, uint32_t p_object_type_mask, bool p_pick_ray) {
ERR_FAIL_COND_V(space->locked,false);
@@ -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<CollisionObjectSW*>(space->intersection_query_results[i])->is_ray_pickable()))
+ if (p_pick_ray && !(static_cast<CollisionObjectSW*>(space->intersection_query_results[i])->is_ray_pickable()))
continue;
if (p_exclude.has( space->intersection_query_results[i]->get_self()))
@@ -175,13 +175,15 @@ int PhysicsDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transfo
if (!CollisionSolverSW::solve_static(shape,p_xform,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), NULL,NULL,NULL,p_margin,0))
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);
- else
- r_results[cc].collider=NULL;
- r_results[cc].rid=col_obj->get_self();
- r_results[cc].shape=shape_idx;
+ if (r_results) {
+ 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);
+ else
+ r_results[cc].collider=NULL;
+ r_results[cc].rid=col_obj->get_self();
+ r_results[cc].shape=shape_idx;
+ }
cc++;
diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h
index ac788ba93f..6300c206d8 100644
--- a/servers/physics/space_sw.h
+++ b/servers/physics/space_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -46,7 +46,7 @@ public:
SpaceSW *space;
- virtual bool intersect_ray(const Vector3& p_from, const Vector3& 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 bool intersect_ray(const Vector3& p_from, const Vector3& 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,bool p_pick_ray=false);
virtual int intersect_shape(const RID& p_shape, const Transform& p_xform,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 Transform& p_xform,const Vector3& 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,ShapeRestInfo *r_info=NULL);
virtual bool collide_shape(RID p_shape, const Transform& p_shape_xform,float p_margin,Vector3 *r_results,int p_result_max,int &r_result_count, 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/step_sw.cpp b/servers/physics/step_sw.cpp
index 2424b36833..f10dadf81a 100644
--- a/servers/physics/step_sw.cpp
+++ b/servers/physics/step_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/step_sw.h b/servers/physics/step_sw.h
index f089c041fc..f6362f3777 100644
--- a/servers/physics/step_sw.h
+++ b/servers/physics/step_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp
index a5a132020a..759a37e84f 100644
--- a/servers/physics_2d/area_2d_sw.cpp
+++ b/servers/physics_2d/area_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h
index 6d99764c68..71192db1df 100644
--- a/servers/physics_2d/area_2d_sw.h
+++ b/servers/physics_2d/area_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp
index 3b1705bd56..0682d8abdd 100644
--- a/servers/physics_2d/area_pair_2d_sw.cpp
+++ b/servers/physics_2d/area_pair_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/area_pair_2d_sw.h b/servers/physics_2d/area_pair_2d_sw.h
index 59113c9162..a03bdb572a 100644
--- a/servers/physics_2d/area_pair_2d_sw.h
+++ b/servers/physics_2d/area_pair_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index 3afbbe5455..f1f94f3485 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,6 +29,7 @@
#include "body_2d_sw.h"
#include "space_2d_sw.h"
#include "area_2d_sw.h"
+#include "physics_2d_server_sw.h"
void Body2DSW::_update_inertia() {
@@ -378,9 +379,10 @@ void Body2DSW::set_space(Space2DSW *p_space){
}
+ first_integration=false;
}
-void Body2DSW::_compute_area_gravity(const Area2DSW *p_area) {
+void Body2DSW::_compute_area_gravity_and_dampenings(const Area2DSW *p_area) {
if (p_area->is_gravity_point()) {
if(p_area->get_gravity_distance_scale() > 0) {
@@ -393,6 +395,8 @@ void Body2DSW::_compute_area_gravity(const Area2DSW *p_area) {
gravity += p_area->get_gravity_vector() * p_area->get_gravity();
}
+ area_linear_damp += p_area->get_linear_damp();
+ area_angular_damp += p_area->get_angular_damp();
}
void Body2DSW::integrate_forces(real_t p_step) {
@@ -401,38 +405,53 @@ void Body2DSW::integrate_forces(real_t p_step) {
return;
Area2DSW *def_area = get_space()->get_default_area();
- Area2DSW *damp_area = def_area;
+ // Area2DSW *damp_area = def_area;
ERR_FAIL_COND(!def_area);
int ac = areas.size();
- bool replace = false;
- gravity=Vector2(0,0);
+ bool stopped = false;
+ gravity = Vector2(0,0);
+ area_angular_damp = 0;
+ area_linear_damp = 0;
if (ac) {
areas.sort();
const AreaCMP *aa = &areas[0];
- damp_area = aa[ac-1].area;
- for(int i=ac-1;i>=0;i--) {
- _compute_area_gravity(aa[i].area);
- if (aa[i].area->get_space_override_mode() == Physics2DServer::AREA_SPACE_OVERRIDE_REPLACE) {
- replace = true;
- break;
+ // damp_area = aa[ac-1].area;
+ for(int i=ac-1;i>=0 && !stopped;i--) {
+ Physics2DServer::AreaSpaceOverrideMode mode=aa[i].area->get_space_override_mode();
+ switch (mode) {
+ case Physics2DServer::AREA_SPACE_OVERRIDE_COMBINE:
+ case Physics2DServer::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+ _compute_area_gravity_and_dampenings(aa[i].area);
+ stopped = mode==Physics2DServer::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+ } break;
+ case Physics2DServer::AREA_SPACE_OVERRIDE_REPLACE:
+ case Physics2DServer::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+ gravity = Vector2(0,0);
+ area_angular_damp = 0;
+ area_linear_damp = 0;
+ _compute_area_gravity_and_dampenings(aa[i].area);
+ stopped = mode==Physics2DServer::AREA_SPACE_OVERRIDE_REPLACE;
+ } break;
+ default: {}
}
}
}
- if( !replace ) {
- _compute_area_gravity(def_area);
+ if( !stopped ) {
+ _compute_area_gravity_and_dampenings(def_area);
}
gravity*=gravity_scale;
+ // If less than 0, override dampenings with that of the Body2D
if (angular_damp>=0)
- area_angular_damp=angular_damp;
- else
- area_angular_damp=damp_area->get_angular_damp();
+ area_angular_damp = angular_damp;
+ //else
+ // area_angular_damp=damp_area->get_angular_damp();
if (linear_damp>=0)
- area_linear_damp=linear_damp;
- else
- area_linear_damp=damp_area->get_linear_damp();
+ area_linear_damp = linear_damp;
+ //else
+ // area_linear_damp=damp_area->get_linear_damp();
Vector2 motion;
bool do_motion=false;
@@ -454,7 +473,7 @@ void Body2DSW::integrate_forces(real_t p_step) {
//}
} else {
- if (!omit_force_integration) {
+ if (!omit_force_integration && !first_integration) {
//overriden by direct state query
Vector2 force=gravity*mass;
@@ -489,6 +508,7 @@ void Body2DSW::integrate_forces(real_t p_step) {
//motion=linear_velocity*p_step;
+ first_integration=false;
biased_angular_velocity=0;
biased_linear_velocity=Vector2();
@@ -496,7 +516,7 @@ void Body2DSW::integrate_forces(real_t p_step) {
_update_shapes_with_motion(motion);
}
- damp_area=NULL; // clear the area, so it is set in the next frame
+ // damp_area=NULL; // clear the area, so it is set in the next frame
def_area=NULL; // clear the area, so it is set in the next frame
contact_count=0;
@@ -664,6 +684,7 @@ Body2DSW::Body2DSW() : CollisionObject2DSW(TYPE_BODY), active_list(this), inerti
gravity_scale=1.0;
using_one_way_cache=false;
one_way_collision_max_depth=0.1;
+ first_integration=false;
still_time=0;
continuous_cd_mode=Physics2DServer::CCD_MODE_DISABLED;
@@ -684,3 +705,24 @@ Physics2DDirectSpaceState* Physics2DDirectBodyStateSW::get_space_state() {
return body->get_space()->get_direct_state();
}
+
+
+Variant Physics2DDirectBodyStateSW::get_contact_collider_shape_metadata(int p_contact_idx) const {
+
+ ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Variant());
+
+ if (!Physics2DServerSW::singletonsw->body_owner.owns(body->contacts[p_contact_idx].collider)) {
+
+ return Variant();
+ }
+ Body2DSW *other = Physics2DServerSW::singletonsw->body_owner.get(body->contacts[p_contact_idx].collider);
+
+ int sidx = body->contacts[p_contact_idx].collider_shape;
+ if (sidx<0 || sidx>=other->get_shape_count()) {
+
+ return Variant();
+ }
+
+
+ return other->get_shape_metadata(sidx);
+}
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index 9720b265dc..b7f3ab01db 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -81,6 +81,7 @@ class Body2DSW : public CollisionObject2DSW {
bool active;
bool can_sleep;
bool first_time_kinematic;
+ bool first_integration;
bool using_one_way_cache;
void _update_inertia();
virtual void _shapes_changed();
@@ -133,7 +134,7 @@ class Body2DSW : public CollisionObject2DSW {
Body2DSW *island_next;
Body2DSW *island_list_next;
- _FORCE_INLINE_ void _compute_area_gravity(const Area2DSW *p_area);
+ _FORCE_INLINE_ void _compute_area_gravity_and_dampenings(const Area2DSW *p_area);
friend class Physics2DDirectBodyStateSW; // i give up, too many functions to expose
@@ -385,7 +386,7 @@ public:
virtual Vector2 get_contact_collider_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2()); return body->contacts[p_contact_idx].collider_pos; }
virtual ObjectID get_contact_collider_id(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_instance_id; }
virtual int get_contact_collider_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_shape; }
- virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Variant()); return body->get_shape_metadata(body->contacts[p_contact_idx].collider_shape); }
+ virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const;
virtual Vector2 get_contact_collider_velocity_at_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2()); return body->contacts[p_contact_idx].collider_velocity_at_pos; }
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp
index eb3abbb267..db7869c6a6 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/body_pair_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -364,6 +364,9 @@ bool BodyPair2DSW::setup(float p_step) {
real_t inv_dt = 1.0/p_step;
+
+ bool do_process=false;
+
for (int i = 0; i < contact_count; i++) {
Contact& c = contacts[i];
@@ -459,10 +462,11 @@ bool BodyPair2DSW::setup(float p_step) {
c.bounce = c.bounce * dv.dot(c.normal);
}
+ do_process=true;
}
- return true;
+ return do_process;
}
void BodyPair2DSW::solve(float p_step) {
diff --git a/servers/physics_2d/body_pair_2d_sw.h b/servers/physics_2d/body_pair_2d_sw.h
index a7fa287be4..a16320585e 100644
--- a/servers/physics_2d/body_pair_2d_sw.h
+++ b/servers/physics_2d/body_pair_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/broad_phase_2d_basic.cpp b/servers/physics_2d/broad_phase_2d_basic.cpp
index e61b4735b9..3a95bb2411 100644
--- a/servers/physics_2d/broad_phase_2d_basic.cpp
+++ b/servers/physics_2d/broad_phase_2d_basic.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/broad_phase_2d_basic.h b/servers/physics_2d/broad_phase_2d_basic.h
index cdee77ffd7..80aa423819 100644
--- a/servers/physics_2d/broad_phase_2d_basic.h
+++ b/servers/physics_2d/broad_phase_2d_basic.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.cpp b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
index 4651d485c2..6a52d5fe5b 100644
--- a/servers/physics_2d/broad_phase_2d_hash_grid.cpp
+++ b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.h b/servers/physics_2d/broad_phase_2d_hash_grid.h
index a2eecf7bbf..bda5ea21cf 100644
--- a/servers/physics_2d/broad_phase_2d_hash_grid.h
+++ b/servers/physics_2d/broad_phase_2d_hash_grid.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/broad_phase_2d_sw.cpp b/servers/physics_2d/broad_phase_2d_sw.cpp
index fd8e7254b6..0dead94ca1 100644
--- a/servers/physics_2d/broad_phase_2d_sw.cpp
+++ b/servers/physics_2d/broad_phase_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/broad_phase_2d_sw.h b/servers/physics_2d/broad_phase_2d_sw.h
index 283d6941e1..056ef664fd 100644
--- a/servers/physics_2d/broad_phase_2d_sw.h
+++ b/servers/physics_2d/broad_phase_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp
index 7c8e223c57..7f9d3312b9 100644
--- a/servers/physics_2d/collision_object_2d_sw.cpp
+++ b/servers/physics_2d/collision_object_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h
index f3432060b9..1f213d8444 100644
--- a/servers/physics_2d/collision_object_2d_sw.h
+++ b/servers/physics_2d/collision_object_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/collision_solver_2d_sat.cpp
index 2525c6e942..f22b676304 100644
--- a/servers/physics_2d/collision_solver_2d_sat.cpp
+++ b/servers/physics_2d/collision_solver_2d_sat.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/collision_solver_2d_sat.h b/servers/physics_2d/collision_solver_2d_sat.h
index 554f756738..91aeb53030 100644
--- a/servers/physics_2d/collision_solver_2d_sat.h
+++ b/servers/physics_2d/collision_solver_2d_sat.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp
index 134ad04222..d9bf235c86 100644
--- a/servers/physics_2d/collision_solver_2d_sw.cpp
+++ b/servers/physics_2d/collision_solver_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/collision_solver_2d_sw.h b/servers/physics_2d/collision_solver_2d_sw.h
index 0cdd54f8b6..7e3542805c 100644
--- a/servers/physics_2d/collision_solver_2d_sw.h
+++ b/servers/physics_2d/collision_solver_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/constraint_2d_sw.cpp b/servers/physics_2d/constraint_2d_sw.cpp
index 24d56ce9fe..2f681e8590 100644
--- a/servers/physics_2d/constraint_2d_sw.cpp
+++ b/servers/physics_2d/constraint_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/constraint_2d_sw.h b/servers/physics_2d/constraint_2d_sw.h
index a9145c382f..f776dbfe2c 100644
--- a/servers/physics_2d/constraint_2d_sw.h
+++ b/servers/physics_2d/constraint_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp
index 7c12000084..958780c2e6 100644
--- a/servers/physics_2d/joints_2d_sw.cpp
+++ b/servers/physics_2d/joints_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/joints_2d_sw.h b/servers/physics_2d/joints_2d_sw.h
index e43f8eee33..86a1397c53 100644
--- a/servers/physics_2d/joints_2d_sw.h
+++ b/servers/physics_2d/joints_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index 6a1c790da8..c571331498 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1322,8 +1322,11 @@ int Physics2DServerSW::get_process_info(ProcessInfo p_info) {
}
+Physics2DServerSW *Physics2DServerSW::singletonsw=NULL;
+
Physics2DServerSW::Physics2DServerSW() {
+ singletonsw=this;
BroadPhase2DSW::create_func=BroadPhase2DHashGrid::_create;
// BroadPhase2DSW::create_func=BroadPhase2DBasic::_create;
diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h
index b2c58b788e..28acf4e2d1 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,6 +42,7 @@ class Physics2DServerSW : public Physics2DServer {
OBJ_TYPE( Physics2DServerSW, Physics2DServer );
friend class Physics2DDirectSpaceStateSW;
+friend class Physics2DDirectBodyStateSW;
bool active;
int iterations;
bool doing_sync;
@@ -65,7 +66,7 @@ friend class Physics2DDirectSpaceStateSW;
mutable RID_Owner<Body2DSW> body_owner;
mutable RID_Owner<Joint2DSW> joint_owner;
-
+ static Physics2DServerSW *singletonsw;
// void _clear_query(Query2DSW *p_query);
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp
index d3591ec744..3054ba8d59 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/shape_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h
index 6d5473aa17..4164896696 100644
--- a/servers/physics_2d/shape_2d_sw.h
+++ b/servers/physics_2d/shape_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 9f2f03baec..9ba6bdd5ba 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -192,7 +192,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matri
if (p_result_max<=0)
return 0;
- Shape2DSW *shape = static_cast<Physics2DServerSW*>(Physics2DServer::get_singleton())->shape_owner.get(p_shape);
+ Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape,0);
Rect2 aabb = p_xform.xform(shape->get_aabb());
@@ -239,7 +239,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32
- Shape2DSW *shape = static_cast<Physics2DServerSW*>(Physics2DServer::get_singleton())->shape_owner.get(p_shape);
+ Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape,false);
Rect2 aabb = p_xform.xform(shape->get_aabb());
@@ -367,7 +367,7 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Matrix32& p_s
if (p_result_max<=0)
return 0;
- Shape2DSW *shape = static_cast<Physics2DServerSW*>(Physics2DServer::get_singleton())->shape_owner.get(p_shape);
+ Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape,0);
Rect2 aabb = p_shape_xform.xform(shape->get_aabb());
@@ -474,7 +474,7 @@ static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,v
bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
- Shape2DSW *shape = static_cast<Physics2DServerSW*>(Physics2DServer::get_singleton())->shape_owner.get(p_shape);
+ Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape,0);
Rect2 aabb = p_shape_xform.xform(shape->get_aabb());
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index 97ad3d7f80..2bdbb8a881 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/step_2d_sw.cpp b/servers/physics_2d/step_2d_sw.cpp
index bc87789937..94e1d26329 100644
--- a/servers/physics_2d/step_2d_sw.cpp
+++ b/servers/physics_2d/step_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -56,14 +56,29 @@ void Step2DSW::_populate_island(Body2DSW* p_body,Body2DSW** p_island,Constraint2
}
}
-void Step2DSW::_setup_island(Constraint2DSW *p_island,float p_delta) {
+bool Step2DSW::_setup_island(Constraint2DSW *p_island,float p_delta) {
Constraint2DSW *ci=p_island;
+ Constraint2DSW *prev_ci=NULL;
+ bool removed_root=false;
while(ci) {
bool process = ci->setup(p_delta);
- //todo remove from island if process fails
+
+ if (!process) {
+ //remove from island if process fails
+ if (prev_ci) {
+ prev_ci->set_island_next(ci->get_island_next());
+ } else {
+ removed_root=true;
+ prev_ci=ci;
+ }
+ } else {
+ prev_ci=ci;
+ }
ci=ci->get_island_next();
}
+
+ return removed_root;
}
void Step2DSW::_solve_island(Constraint2DSW *p_island,int p_iterations,float p_delta){
@@ -195,9 +210,40 @@ void Step2DSW::step(Space2DSW* p_space,float p_delta,int p_iterations) {
{
Constraint2DSW *ci=constraint_island_list;
+ Constraint2DSW *prev_ci=NULL;
while(ci) {
- _setup_island(ci,p_delta);
+ if (_setup_island(ci,p_delta)==true) {
+
+ //removed the root from the island graph because it is not to be processed
+
+ Constraint2DSW *next = ci->get_island_next();
+
+ if (next) {
+ //root from list being deleted no longer exists, replace by next
+ next->set_island_list_next(ci->get_island_list_next());
+ if (prev_ci) {
+ prev_ci->set_island_list_next(next);
+ } else {
+ constraint_island_list=next;
+
+ }
+ prev_ci=next;
+ } else {
+
+ //list is empty, just skip
+ if (prev_ci) {
+ prev_ci->set_island_list_next(ci->get_island_list_next());
+
+ } else {
+ constraint_island_list=ci->get_island_list_next();
+ }
+
+ }
+ } else {
+ prev_ci=ci;
+ }
+
ci=ci->get_island_list_next();
}
}
diff --git a/servers/physics_2d/step_2d_sw.h b/servers/physics_2d/step_2d_sw.h
index d5e919836c..0c374d7e12 100644
--- a/servers/physics_2d/step_2d_sw.h
+++ b/servers/physics_2d/step_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,7 +36,7 @@ class Step2DSW {
uint64_t _step;
void _populate_island(Body2DSW* p_body,Body2DSW** p_island,Constraint2DSW **p_constraint_island);
- void _setup_island(Constraint2DSW *p_island,float p_delta);
+ bool _setup_island(Constraint2DSW *p_island,float p_delta);
void _solve_island(Constraint2DSW *p_island,int p_iterations,float p_delta);
void _check_suspend(Body2DSW *p_island,float p_delta);
public:
diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp
index b9d15d6e35..2d267a5749 100644
--- a/servers/physics_2d_server.cpp
+++ b/servers/physics_2d_server.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -102,7 +102,7 @@ void Physics2DDirectBodyState::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_contact_collider_id","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_id);
ObjectTypeDB::bind_method(_MD("get_contact_collider_object","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_object);
ObjectTypeDB::bind_method(_MD("get_contact_collider_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape);
- ObjectTypeDB::bind_method(_MD("get_contact_collider_shape_metadata:var","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape_metadata);
+ ObjectTypeDB::bind_method(_MD("get_contact_collider_shape_metadata:Variant","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape_metadata);
ObjectTypeDB::bind_method(_MD("get_contact_collider_velocity_at_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_velocity_at_pos);
ObjectTypeDB::bind_method(_MD("get_step"),&Physics2DDirectBodyState::get_step);
ObjectTypeDB::bind_method(_MD("integrate_forces"),&Physics2DDirectBodyState::integrate_forces);
@@ -548,7 +548,7 @@ void Physics2DServer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("area_attach_object_instance_ID","area","id"),&Physics2DServer::area_attach_object_instance_ID);
ObjectTypeDB::bind_method(_MD("area_get_object_instance_ID","area"),&Physics2DServer::area_get_object_instance_ID);
- ObjectTypeDB::bind_method(_MD("area_set_monitor_callback","receiver","method"),&Physics2DServer::area_set_monitor_callback);
+ ObjectTypeDB::bind_method(_MD("area_set_monitor_callback","area","receiver","method"),&Physics2DServer::area_set_monitor_callback);
ObjectTypeDB::bind_method(_MD("body_create","mode","init_sleeping"),&Physics2DServer::body_create,DEFVAL(BODY_MODE_RIGID),DEFVAL(false));
@@ -606,17 +606,17 @@ void Physics2DServer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("body_set_max_contacts_reported","body","amount"),&Physics2DServer::body_set_max_contacts_reported);
ObjectTypeDB::bind_method(_MD("body_get_max_contacts_reported","body"),&Physics2DServer::body_get_max_contacts_reported);
- ObjectTypeDB::bind_method(_MD("body_set_one_way_collision_direction","normal"),&Physics2DServer::body_set_one_way_collision_direction);
- ObjectTypeDB::bind_method(_MD("body_get_one_way_collision_direction"),&Physics2DServer::body_get_one_way_collision_direction);
+ ObjectTypeDB::bind_method(_MD("body_set_one_way_collision_direction","body","normal"),&Physics2DServer::body_set_one_way_collision_direction);
+ ObjectTypeDB::bind_method(_MD("body_get_one_way_collision_direction","body"),&Physics2DServer::body_get_one_way_collision_direction);
- ObjectTypeDB::bind_method(_MD("body_set_one_way_collision_max_depth","normal"),&Physics2DServer::body_set_one_way_collision_max_depth);
- ObjectTypeDB::bind_method(_MD("body_get_one_way_collision_max_depth"),&Physics2DServer::body_get_one_way_collision_max_depth);
+ ObjectTypeDB::bind_method(_MD("body_set_one_way_collision_max_depth","body","depth"),&Physics2DServer::body_set_one_way_collision_max_depth);
+ ObjectTypeDB::bind_method(_MD("body_get_one_way_collision_max_depth","body"),&Physics2DServer::body_get_one_way_collision_max_depth);
ObjectTypeDB::bind_method(_MD("body_set_omit_force_integration","body","enable"),&Physics2DServer::body_set_omit_force_integration);
ObjectTypeDB::bind_method(_MD("body_is_omitting_force_integration","body"),&Physics2DServer::body_is_omitting_force_integration);
- ObjectTypeDB::bind_method(_MD("body_set_force_integration_callback","body","receiver","method"),&Physics2DServer::body_set_force_integration_callback);
+ ObjectTypeDB::bind_method(_MD("body_set_force_integration_callback","body","receiver","method","userdata"),&Physics2DServer::body_set_force_integration_callback,DEFVAL(Variant()));
ObjectTypeDB::bind_method(_MD("body_test_motion","body","motion","margin","result:Physics2DTestMotionResult"),&Physics2DServer::_body_test_motion,DEFVAL(0.08),DEFVAL(Variant()));
@@ -638,7 +638,7 @@ void Physics2DServer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_active","active"),&Physics2DServer::set_active);
- ObjectTypeDB::bind_method(_MD("get_process_info"),&Physics2DServer::get_process_info);
+ ObjectTypeDB::bind_method(_MD("get_process_info","process_info"),&Physics2DServer::get_process_info);
// ObjectTypeDB::bind_method(_MD("init"),&Physics2DServer::init);
// ObjectTypeDB::bind_method(_MD("step"),&Physics2DServer::step);
@@ -663,9 +663,11 @@ void Physics2DServer::_bind_methods() {
BIND_CONSTANT( AREA_PARAM_ANGULAR_DAMP);
BIND_CONSTANT( AREA_PARAM_PRIORITY );
- BIND_CONSTANT( AREA_SPACE_OVERRIDE_COMBINE );
BIND_CONSTANT( AREA_SPACE_OVERRIDE_DISABLED );
+ BIND_CONSTANT( AREA_SPACE_OVERRIDE_COMBINE );
+ BIND_CONSTANT( AREA_SPACE_OVERRIDE_COMBINE_REPLACE );
BIND_CONSTANT( AREA_SPACE_OVERRIDE_REPLACE );
+ BIND_CONSTANT( AREA_SPACE_OVERRIDE_REPLACE_COMBINE );
BIND_CONSTANT( BODY_MODE_STATIC );
BIND_CONSTANT( BODY_MODE_KINEMATIC );
diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h
index 6845c7dfe1..08f69f98b1 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -325,7 +325,9 @@ public:
enum AreaSpaceOverrideMode {
AREA_SPACE_OVERRIDE_DISABLED,
AREA_SPACE_OVERRIDE_COMBINE,
+ AREA_SPACE_OVERRIDE_COMBINE_REPLACE, // Combines, then discards all subsequent calculations
AREA_SPACE_OVERRIDE_REPLACE,
+ AREA_SPACE_OVERRIDE_REPLACE_COMBINE // Discards all previous calculations, then keeps combining
};
virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode)=0;
diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp
index 53409acdfb..89fcffe7ed 100644
--- a/servers/physics_server.cpp
+++ b/servers/physics_server.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -467,7 +467,7 @@ void PhysicsServer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("area_attach_object_instance_ID","area","id"),&PhysicsServer::area_attach_object_instance_ID);
ObjectTypeDB::bind_method(_MD("area_get_object_instance_ID","area"),&PhysicsServer::area_get_object_instance_ID);
- ObjectTypeDB::bind_method(_MD("area_set_monitor_callback","receiver","method"),&PhysicsServer::area_set_monitor_callback);
+ ObjectTypeDB::bind_method(_MD("area_set_monitor_callback","area","receiver","method"),&PhysicsServer::area_set_monitor_callback);
ObjectTypeDB::bind_method(_MD("area_set_ray_pickable","area","enable"),&PhysicsServer::area_set_ray_pickable);
ObjectTypeDB::bind_method(_MD("area_is_ray_pickable","area"),&PhysicsServer::area_is_ray_pickable);
@@ -671,7 +671,7 @@ void PhysicsServer::_bind_methods() {
//ObjectTypeDB::bind_method(_MD("flush_queries"),&PhysicsServer::flush_queries);
- ObjectTypeDB::bind_method(_MD("get_process_info"),&PhysicsServer::get_process_info);
+ ObjectTypeDB::bind_method(_MD("get_process_info","process_info"),&PhysicsServer::get_process_info);
BIND_CONSTANT( SHAPE_PLANE );
BIND_CONSTANT( SHAPE_RAY );
@@ -693,9 +693,11 @@ void PhysicsServer::_bind_methods() {
BIND_CONSTANT( AREA_PARAM_ANGULAR_DAMP );
BIND_CONSTANT( AREA_PARAM_PRIORITY );
- BIND_CONSTANT( AREA_SPACE_OVERRIDE_COMBINE );
BIND_CONSTANT( AREA_SPACE_OVERRIDE_DISABLED );
+ BIND_CONSTANT( AREA_SPACE_OVERRIDE_COMBINE );
+ BIND_CONSTANT( AREA_SPACE_OVERRIDE_COMBINE_REPLACE );
BIND_CONSTANT( AREA_SPACE_OVERRIDE_REPLACE );
+ BIND_CONSTANT( AREA_SPACE_OVERRIDE_REPLACE_COMBINE );
BIND_CONSTANT( BODY_MODE_STATIC );
BIND_CONSTANT( BODY_MODE_KINEMATIC );
diff --git a/servers/physics_server.h b/servers/physics_server.h
index 75584966bb..8e302bf363 100644
--- a/servers/physics_server.h
+++ b/servers/physics_server.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -170,7 +170,7 @@ public:
int shape;
};
- virtual bool intersect_ray(const Vector3& p_from, const Vector3& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0;
+ virtual bool intersect_ray(const Vector3& p_from, const Vector3& 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,bool p_pick_ray=false)=0;
struct ShapeResult {
@@ -318,7 +318,9 @@ public:
enum AreaSpaceOverrideMode {
AREA_SPACE_OVERRIDE_DISABLED,
AREA_SPACE_OVERRIDE_COMBINE,
+ AREA_SPACE_OVERRIDE_COMBINE_REPLACE,
AREA_SPACE_OVERRIDE_REPLACE,
+ AREA_SPACE_OVERRIDE_REPLACE_COMBINE
};
virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode)=0;
@@ -370,7 +372,7 @@ public:
virtual RID body_get_space(RID p_body) const=0;
virtual void body_set_mode(RID p_body, BodyMode p_mode)=0;
- virtual BodyMode body_get_mode(RID p_body, BodyMode p_mode) const=0;
+ virtual BodyMode body_get_mode(RID p_body) const=0;
virtual void body_add_shape(RID p_body, RID p_shape, const Transform& p_transform=Transform())=0;
virtual void body_set_shape(RID p_body, int p_shape_idx,RID p_shape)=0;
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 2af2a79d07..4752210b5f 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/register_server_types.h b/servers/register_server_types.h
index d3d6c6b566..a62af905b3 100644
--- a/servers/register_server_types.h
+++ b/servers/register_server_types.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/spatial_sound/spatial_sound_server_sw.cpp b/servers/spatial_sound/spatial_sound_server_sw.cpp
index d00deb3912..1ce56a5cdd 100644
--- a/servers/spatial_sound/spatial_sound_server_sw.cpp
+++ b/servers/spatial_sound/spatial_sound_server_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/servers/spatial_sound/spatial_sound_server_sw.h b/servers/spatial_sound/spatial_sound_server_sw.h
index 82b1b5fa8e..8a4dabdc3e 100644
--- a/servers/spatial_sound/spatial_sound_server_sw.h
+++ b/servers/spatial_sound/spatial_sound_server_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp
index 439149b1a2..d27b322c21 100644
--- a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp
+++ b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h
index ed305d25de..619b11f376 100644
--- a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h
+++ b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/spatial_sound_2d_server.cpp b/servers/spatial_sound_2d_server.cpp
index 574c3d761f..cfe40a0937 100644
--- a/servers/spatial_sound_2d_server.cpp
+++ b/servers/spatial_sound_2d_server.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/spatial_sound_2d_server.h b/servers/spatial_sound_2d_server.h
index 9917b36be1..2d388feb49 100644
--- a/servers/spatial_sound_2d_server.h
+++ b/servers/spatial_sound_2d_server.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/spatial_sound_server.cpp b/servers/spatial_sound_server.cpp
index f5f5925483..5f93c55a91 100644
--- a/servers/spatial_sound_server.cpp
+++ b/servers/spatial_sound_server.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/spatial_sound_server.h b/servers/spatial_sound_server.h
index 1cc323b370..5037ee6e2f 100644
--- a/servers/spatial_sound_server.h
+++ b/servers/spatial_sound_server.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/particle_system_sw.cpp b/servers/visual/particle_system_sw.cpp
index aa9b737459..00c06b9e3c 100644
--- a/servers/visual/particle_system_sw.cpp
+++ b/servers/visual/particle_system_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/particle_system_sw.h b/servers/visual/particle_system_sw.h
index b7ff5e9bb5..9a176ba0d4 100644
--- a/servers/visual/particle_system_sw.h
+++ b/servers/visual/particle_system_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp
index 5984e6e35c..26eca478fd 100644
--- a/servers/visual/rasterizer.cpp
+++ b/servers/visual/rasterizer.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index aca301e0a8..b84e83cb0c 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -610,6 +610,7 @@ public:
CanvasLight *shadows_next_ptr;
CanvasLight *filter_next_ptr;
CanvasLight *next_ptr;
+ CanvasLight *mask_next_ptr;
CanvasLight() {
enabled=true;
@@ -627,6 +628,7 @@ public:
mode=VS::CANVAS_LIGHT_MODE_ADD;
texture_cache=NULL;
next_ptr=NULL;
+ mask_next_ptr=NULL;
filter_next_ptr=NULL;
shadow_buffer_size=2048;
shadow_esm_mult=80;
@@ -792,6 +794,7 @@ public:
CanvasItem* material_owner;
ViewportRender *vp_render;
bool distance_field;
+ bool light_masked;
Rect2 global_rect_cache;
@@ -918,8 +921,8 @@ 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; 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; }
+ 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; light_masked=false; }
+ 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; light_masked=false; }
virtual ~CanvasItem() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); }
};
@@ -1029,6 +1032,8 @@ public:
virtual int get_render_info(VS::RenderInfo p_info)=0;
+ virtual void set_force_16_bits_fbo(bool p_force) {}
+
Rasterizer();
virtual ~Rasterizer() {}
};
diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp
index c05438aef3..3b12b503dd 100644
--- a/servers/visual/rasterizer_dummy.cpp
+++ b/servers/visual/rasterizer_dummy.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h
index 2c503249fe..efa843839a 100644
--- a/servers/visual/rasterizer_dummy.h
+++ b/servers/visual/rasterizer_dummy.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/shader_compiler.cpp b/servers/visual/shader_compiler.cpp
index d7b171f5a7..ee5dae5ae2 100644
--- a/servers/visual/shader_compiler.cpp
+++ b/servers/visual/shader_compiler.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/shader_compiler.h b/servers/visual/shader_compiler.h
index 69d9eedf9c..29561b2145 100644
--- a/servers/visual/shader_compiler.h
+++ b/servers/visual/shader_compiler.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/shader_graph.cpp b/servers/visual/shader_graph.cpp
index 1346ec9253..07bbf9f7b4 100644
--- a/servers/visual/shader_graph.cpp
+++ b/servers/visual/shader_graph.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/shader_graph.h b/servers/visual/shader_graph.h
index 807dbb3719..07e4bb3540 100644
--- a/servers/visual/shader_graph.h
+++ b/servers/visual/shader_graph.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 68a60e26f5..d0e8bfccd6 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -2341,19 +2341,27 @@ Error ShaderLanguage::parse_flow_if(Parser& parser,Node *p_parent,Node **r_state
parser.advance();
+ if (parser.get_token_type()!=TK_CURLY_BRACKET_OPEN) {
+ parser.set_error("Expected statement block after 'if()'");
+ return ERR_PARSE_ERROR;
+ }
+
Node *substatement=NULL;
err = parse_statement(parser,cf,&substatement);
if (err)
return err;
-
cf->statements.push_back(substatement);
-
-
if (parser.get_token_type()==TK_CF_ELSE) {
parser.advance();
+
+ if (parser.get_token_type()!=TK_CURLY_BRACKET_OPEN) {
+ parser.set_error("Expected statement block after 'else'");
+ return ERR_PARSE_ERROR;
+ }
+
substatement=NULL;
err = parse_statement(parser,cf,&substatement);
if (err)
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index 9fd070ee2e..31e9fcda5b 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index a94d4f64c7..3675194325 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -6777,6 +6777,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_material_owner) {
CanvasItem *ci = p_canvas_item;
@@ -6878,6 +6879,7 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
ci->final_opacity=opacity * ci->self_opacity;
ci->global_rect_cache=global_rect;
ci->global_rect_cache.pos-=p_clip_rect.pos;
+ ci->light_masked=false;
int zidx = p_z-CANVAS_ITEM_Z_MIN;
@@ -6905,7 +6907,34 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
}
-void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_transform,Rasterizer::CanvasLight *p_lights) {
+void VisualServerRaster::_light_mask_canvas_items(int p_z,Rasterizer::CanvasItem *p_canvas_item,Rasterizer::CanvasLight *p_masked_lights) {
+
+ if (!p_masked_lights)
+ return;
+
+ Rasterizer::CanvasItem *ci=p_canvas_item;
+
+ while(ci) {
+
+ Rasterizer::CanvasLight *light=p_masked_lights;
+ while(light) {
+
+ if (ci->light_mask&light->item_mask && p_z>=light->z_min && p_z<=light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache,light->rect_cache)) {
+ ci->light_masked=true;
+ }
+
+ light=light->mask_next_ptr;
+ }
+
+ ci=ci->next;
+ }
+
+
+
+
+}
+
+void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_transform,Rasterizer::CanvasLight *p_lights,Rasterizer::CanvasLight *p_masked_lights) {
rasterizer->canvas_begin();
@@ -6938,6 +6967,11 @@ void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_trans
for(int i=0;i<z_range;i++) {
if (!z_list[i])
continue;
+
+ if (p_masked_lights) {
+ _light_mask_canvas_items(CANVAS_ITEM_Z_MIN+i,z_list[i],p_masked_lights);
+ }
+
rasterizer->canvas_render_items(z_list[i],CANVAS_ITEM_Z_MIN+i,p_canvas->modulate,p_lights);
}
} else {
@@ -7072,6 +7106,7 @@ 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;
+ Rasterizer::CanvasLight *lights_with_mask=NULL;
Rect2 shadow_rect;
int light_count=0;
@@ -7119,9 +7154,14 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
cl->radius_cache=cl->rect_cache.size.length();
}
+ if (cl->mode==CANVAS_LIGHT_MODE_MASK) {
+ cl->mask_next_ptr=lights_with_mask;
+ lights_with_mask=cl;
+ }
light_count++;
}
+
}
}
@@ -7142,6 +7182,8 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
for(Set<Rasterizer::CanvasLightOccluderInstance*>::Element *F=E->get().canvas->occluders.front();F;F=F->next()) {
+ if (!F->get()->enabled)
+ continue;
F->get()->xform_cache = xf * F->get()->xform;
if (shadow_rect.intersects_transformed(F->get()->xform_cache,F->get()->aabb_cache)) {
@@ -7190,7 +7232,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
ptr=ptr->filter_next_ptr;
}
- _render_canvas( E->get()->canvas,xform,canvas_lights );
+ _render_canvas( E->get()->canvas,xform,canvas_lights,lights_with_mask );
i++;
if (scenario_draw_canvas_bg && E->key().layer>=scenario_canvas_max_layer) {
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index b6a5ca6308..459dc60e81 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -633,7 +633,9 @@ class VisualServerRaster : public VisualServer {
static void _render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect);
void _render_canvas_item_tree(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, Rasterizer::CanvasLight *p_lights);
void _render_canvas_item(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, float p_opacity, int p_z, Rasterizer::CanvasItem **z_list, Rasterizer::CanvasItem **z_last_list, CanvasItem *p_canvas_clip, CanvasItem *p_material_owner);
- void _render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, Rasterizer::CanvasLight *p_lights);
+ void _render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, Rasterizer::CanvasLight *p_lights, Rasterizer::CanvasLight *p_masked_lights);
+ void _light_mask_canvas_items(int p_z,Rasterizer::CanvasItem *p_canvas_item,Rasterizer::CanvasLight *p_masked_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);
diff --git a/servers/visual/visual_server_wrap_mt.cpp b/servers/visual/visual_server_wrap_mt.cpp
index 19dff3d36c..478a31806c 100644
--- a/servers/visual/visual_server_wrap_mt.cpp
+++ b/servers/visual/visual_server_wrap_mt.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index 57d691ae68..fb502d8a6e 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 25e6a68469..fd2913cc7e 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -526,6 +526,7 @@ void VisualServer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("canvas_item_get_opacity"),&VisualServer::canvas_item_get_opacity);
ObjectTypeDB::bind_method(_MD("canvas_item_set_self_opacity"),&VisualServer::canvas_item_set_self_opacity);
ObjectTypeDB::bind_method(_MD("canvas_item_get_self_opacity"),&VisualServer::canvas_item_get_self_opacity);
+ ObjectTypeDB::bind_method(_MD("canvas_item_set_z"),&VisualServer::canvas_item_set_z);
ObjectTypeDB::bind_method(_MD("canvas_item_add_line"),&VisualServer::canvas_item_add_line, DEFVAL(1.0));
ObjectTypeDB::bind_method(_MD("canvas_item_add_rect"),&VisualServer::canvas_item_add_rect);
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 96c3e15cde..4841720f41 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1041,6 +1041,7 @@ public:
CANVAS_LIGHT_MODE_ADD,
CANVAS_LIGHT_MODE_SUB,
CANVAS_LIGHT_MODE_MIX,
+ CANVAS_LIGHT_MODE_MASK,
};
virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode)=0;
diff --git a/tools/Godot.app/Contents/Info.plist b/tools/Godot.app/Contents/Info.plist
index 8a89993fb9..cb2db17807 100755
--- a/tools/Godot.app/Contents/Info.plist
+++ b/tools/Godot.app/Contents/Info.plist
@@ -9,7 +9,7 @@
<key>CFBundleName</key>
<string>Godot</string>
<key>CFBundleGetInfoString</key>
- <string>(c) 2007-2014 Juan Linietsky, Ariel Manzur</string>
+ <string>(c) 2007-2016 Juan Linietsky, Ariel Manzur</string>
<key>CFBundleIconFile</key>
<string>Godot.icns</string>
<key>CFBundleIdentifier</key>
@@ -25,7 +25,7 @@
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>NSHumanReadableCopyright</key>
- <string>© 2007-2014 Juan Linietsky, Ariel Manzur</string>
+ <string>© 2007-2016 Juan Linietsky, Ariel Manzur</string>
<key>LSMinimumSystemVersion</key>
<string>10.6.0</string>
<key>LSMinimumSystemVersionByArchitecture</key>
diff --git a/tools/addheader/addheader.py b/tools/addheader/addheader.py
index 038cec96d0..0252eb396d 100644
--- a/tools/addheader/addheader.py
+++ b/tools/addheader/addheader.py
@@ -6,7 +6,7 @@ header="""\
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/addheader/header.txt b/tools/addheader/header.txt
index 359949cc3b..e4efb2dcfc 100644
--- a/tools/addheader/header.txt
+++ b/tools/addheader/header.txt
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
+/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
diff --git a/tools/collada/collada.cpp b/tools/collada/collada.cpp
index deec5f60c7..07da72718e 100644
--- a/tools/collada/collada.cpp
+++ b/tools/collada/collada.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1683,8 +1683,12 @@ Collada::Node* Collada::_parse_visual_scene_node(XMLParser& parser) {
if ( parser.has_attribute("sid") ) { //bones may not have sid
joint->sid=parser.get_attribute_value("sid");
// state.bone_map[joint->sid]=joint;
- } else if (state.idref_joints.has(name))
+ } else if (state.idref_joints.has(name)) {
joint->sid=name; //kind of a cheat but..
+ } else if (parser.has_attribute("name")) {
+ joint->sid=parser.get_attribute_value_safe("name");
+ }
+
if (joint->sid!="") {
state.sid_to_node_map[joint->sid]=id;
diff --git a/tools/collada/collada.h b/tools/collada/collada.h
index 81f51a1f3d..8983b8faf0 100644
--- a/tools/collada/collada.h
+++ b/tools/collada/collada.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/doc/doc_data.cpp b/tools/doc/doc_data.cpp
index c1d3e5e314..11e4797747 100644
--- a/tools/doc/doc_data.cpp
+++ b/tools/doc/doc_data.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -187,14 +187,13 @@ void DocData::generate(bool p_basic_types) {
arginfo=E->get().return_val;
- if (arginfo.type==Variant::NIL)
- continue;
#ifdef DEBUG_METHODS_ENABLED
if (m && m->get_return_type()!=StringName())
method.return_type=m->get_return_type();
- else
+ else if (arginfo.type!=Variant::NIL) // {
#endif
method.return_type=(arginfo.hint==PROPERTY_HINT_RESOURCE_TYPE)?arginfo.hint_string:Variant::get_type_name(arginfo.type);
+// }
} else {
@@ -585,7 +584,10 @@ void DocData::generate(bool p_basic_types) {
md.name=mi.name;
if (mi.return_val.name!="")
md.return_type=mi.return_val.name;
- else
+ else if (mi.name.find(":")!=-1) {
+ md.return_type=mi.name.get_slice(":",1);
+ md.name=mi.name.get_slice(":",0);
+ } else
md.return_type=Variant::get_type_name(mi.return_val.type);
for(int i=0;i<mi.arguments.size();i++) {
@@ -595,8 +597,9 @@ void DocData::generate(bool p_basic_types) {
ArgumentDoc ad;
ad.name=pi.name;
+
if (pi.type==Variant::NIL)
- ad.type="var";
+ ad.type="Variant";
else
ad.type=Variant::get_type_name( pi.type );
diff --git a/tools/doc/doc_data.h b/tools/doc/doc_data.h
index b62eb21b4a..877f30defb 100644
--- a/tools/doc/doc_data.h
+++ b/tools/doc/doc_data.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/docdump/class_list.xml b/tools/docdump/class_list.xml
deleted file mode 100644
index 3d07f84177..0000000000
--- a/tools/docdump/class_list.xml
+++ /dev/null
@@ -1,13625 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<doc version="0.99.1384-pre-beta" name="Engine Types">
-<class name="Animation" inherits="Resource" category="Resources">
- <brief_description>
- Contains data used to animate everything in the engine.
- </brief_description>
- <description>
- An Animation resource contains data used to animate everything in the engine. Animations are divided into tracks, and each track must be linked to a node. The state of that node can be changed through time, by adding timed keys (signals) to the track. [html br/] Animations are just data containers, and must be added to odes such as an [AnimationPlayer] or [AnimationTreePlayer] to be played back.
- </description>
- <methods>
- <method name="add_track" >
- <argument index="0" name="type" type="int">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- Add a track to the Animation. The track type must be specified as any of the values in te TYPE_* enumeration.
- </description>
- </method>
- <method name="remove_track" >
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Remove a track by specifying the track index.
- </description>
- </method>
- <method name="get_track_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the amount of tracks in the animation.
- </description>
- </method>
- <method name="track_get_type" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Get the type of a track.
- </description>
- </method>
- <method name="track_get_path" qualifiers="const" >
- <return type="NodePath">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Get the path of a track. for more information on the path format, see [method track_set_path]
- </description>
- </method>
- <method name="track_set_path" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="path" type="NodePath">
- </argument>
- <description>
- Set the path of a track. Paths must be valid scene-tree paths to a node, and must be specified starting from the parent node of the node that will reproduce the animation. Tracks that control properties or bones must append their name after the path, separated by &quot;:&quot;. Example: &quot;character/skeleton:ankle&quot; or &quot;character/mesh:transform/local:&quot;
- </description>
- </method>
- <method name="track_move_up" >
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_move_down" >
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transform_track_insert_key" >
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="time" type="real">
- </argument>
- <argument index="2" name="loc" type="Vector3">
- </argument>
- <argument index="3" name="rot" type="Quat">
- </argument>
- <argument index="4" name="scale" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_insert_key" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="key" type="real">
- </argument>
- <argument index="2" name="arg2" type="var">
- </argument>
- <argument index="3" name="arg3" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_remove_key" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="key_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_get_key_count" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Return the amount of keys in a given track.
- </description>
- </method>
- <method name="track_get_key_value" qualifiers="const" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_get_key_time" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- Return the time at which the key is located.
- </description>
- </method>
- <method name="track_find_key" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="time" type="real">
- </argument>
- <argument index="2" name="exact" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_set_interpolation_type" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="interpolation" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="track_get_interpolation_type" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transform_track_interpolate" qualifiers="const" >
- <return type="Array">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="time_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="value_track_interpolate" qualifiers="const" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="time_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="blend_track_interpolate" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="time_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="property_track_get_key_indices" qualifiers="const" >
- <return type="IntArray">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="time_sec" type="real">
- </argument>
- <argument index="2" name="delta" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="property_track_get_key_value" qualifiers="const" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="key_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="property_track_get_name" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="key_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="method_track_get_key_indices" qualifiers="const" >
- <return type="IntArray">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="time_sec" type="real">
- </argument>
- <argument index="2" name="delta" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="method_track_get_name" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="key_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="method_track_get_params" qualifiers="const" >
- <return type="Array">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="key_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_length" >
- <argument index="0" name="time_sec" type="real">
- </argument>
- <description>
- Set the total length of the animation (in seconds). Note that length is not delimited by the last key, as this one may be before or after the end to ensure correct interpolation and looping.
- </description>
- </method>
- <method name="get_length" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the total length of the animation (in seconds).
- </description>
- </method>
- <method name="set_loop" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- Set a flag indicating that the animation must loop. This is uses for correct interpolation of animation cycles, and for hinting the player that it must restart the animation once it&apos;s over.
- </description>
- </method>
- <method name="has_loop" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return wether the animation has the loop flag set.
- </description>
- </method>
- </methods>
- <constants>
- <constant name="INTERPOLATION_CUBIC" value="2">
- </constant>
- <constant name="TYPE_TRANSFORM" value="0">
- Transform tracks are used to change node local transforms or skeleton pose bones. Transitions are Interpolated.
- </constant>
- <constant name="TYPE_BLEND" value="4">
- </constant>
- <constant name="TYPE_PROPERTY" value="2">
- TODO will be changed and bleh
- </constant>
- <constant name="TYPE_VALUE" value="1">
- Value tracks set values in node properties, but only those which can be Interpolated.
- </constant>
- <constant name="INTERPOLATION_NEAREST" value="0">
- </constant>
- <constant name="INTERPOLATION_LINEAR" value="1">
- </constant>
- <constant name="TYPE_METHOD" value="3">
- </constant>
- </constants>
-</class>
-<class name="AnimationPlayer" inherits="Misc" category="Nodes/Animation Nodes">
- <brief_description>
- Container and player of [Animaton] resources.
- </brief_description>
- <description>
- An animation player is used for general purpose playback of [Animation] resources. It contains a dictionary of animations (referenced by name) and custom blend times between their transitions. Additionally, animations can be played and blended in diferent channels.
- </description>
- <methods>
- <method name="add_animation" >
- <return type="int">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="animation" type="Object">
- </argument>
- <description>
- Add an animation resource to the player, which will be later referenced by the &quot;name&quot; argument.
- </description>
- </method>
- <method name="remove_animation" >
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- Remove an animation from the player (by supplying the same name used to add it).
- </description>
- </method>
- <method name="rename_animation" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="newname" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_animation" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- Request wether an [Animation] name exist within the player.
- </description>
- </method>
- <method name="get_animation" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- Get an [Animation] resource by requesting a name.
- </description>
- </method>
- <method name="get_animation_list" qualifiers="const" >
- <return type="StringArray">
- </return>
- <description>
- Get the list of names of the animations stored in the player.
- </description>
- </method>
- <method name="set_blend_time" >
- <argument index="0" name="anim_from" type="String">
- </argument>
- <argument index="1" name="anim_to" type="String">
- </argument>
- <argument index="2" name="sec" type="real">
- </argument>
- <description>
- Specify a blend time (in seconds) between two animations, referemced by their names.
- </description>
- </method>
- <method name="get_blend_time" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="anim_from" type="String">
- </argument>
- <argument index="1" name="anim_to" type="String">
- </argument>
- <description>
- Get the blend time between two animations, referemced by their names.
- </description>
- </method>
- <method name="play" >
- <argument index="0" name="name" type="String" default="&quot;&quot;">
- </argument>
- <argument index="1" name="channel" type="int" default="0">
- </argument>
- <description>
- Start playback of an animation (referenced by &quot;name&quot;). Optionally a channel can be specified.
- </description>
- </method>
- <method name="stop" >
- <argument index="0" name="channel" type="int" default="0">
- </argument>
- <description>
- Start playback of an animation channel. (or channel 0 if none is provided).
- </description>
- </method>
- <method name="stop_all" >
- <description>
- Stop playback on all animation channels.
- </description>
- </method>
- <method name="is_playing" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="channel" type="int" default="0">
- </argument>
- <description>
- Return wether an animation chanel is playing (or channel 0 if none is provided).
- </description>
- </method>
- <method name="get_current_animation" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="channel" type="int" default="0">
- </argument>
- <description>
- Return the name of the animation being played in a channel (or channel 0 if none is provided).
- </description>
- </method>
- <method name="set_pause" >
- <argument index="0" name="paused" type="bool">
- </argument>
- <description>
- Pause the playback in all animation channels.
- </description>
- </method>
- <method name="is_paused" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return [html i]true[html /i] if all playback is paused.
- </description>
- </method>
- <method name="set_speed" >
- <argument index="0" name="speed" type="real">
- </argument>
- <argument index="1" name="channel" type="int" default="0">
- </argument>
- <description>
- Set a speed scaling ratio in a given animation channel (or channel 0 if none is provided). Default ratio is [html i]1[html /i] (no scaling).
- </description>
- </method>
- <method name="get_speed" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="channel" type="int" default="0">
- </argument>
- <description>
- Get the speed scaling ratio in a given animation channel (or channel 0 if none is provided). Default ratio is [html i]1[html /i] (no scaling).
- </description>
- </method>
- <method name="seek" >
- <argument index="0" name="pos_sec" type="real">
- </argument>
- <argument index="1" name="channel" type="int" default="0">
- </argument>
- <description>
- Seek the animation in an animation channel (or channel 0 if none is provided) to a specific position (in seconds).
- </description>
- </method>
- <method name="get_pos" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="channel" type="int" default="0">
- </argument>
- <description>
- Return the playback position (in seconds) in an animation channel (or channel 0 if none is provided)
- </description>
- </method>
- <method name="find_animation" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="animation" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_caches" >
- <description>
- The animation player creates caches for faster access to the nodes it will animate. However, if a specific node is removed, it may not notice it, so clear_caches will force the player to search for the nodes again.
- </description>
- </method>
- </methods>
- <constants>
- <constant name="MAX_CHANNELS" value="8">
- Maximum amount of animation channels.
- </constant>
- </constants>
-</class>
-<class name="AnimationTreePlayer" inherits="Node" category="Nodes/Animation Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_node" >
- <argument index="0" name="type" type="int">
- </argument>
- <argument index="1" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_node_id" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="node_set_name" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="node_get_name" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="node_get_input_count" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="animation_node_set_animation" >
- <argument index="0" name="arg0" type="int">
- </argument>
- <argument index="1" name="arg1" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="animation_node_get_animation" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_set_fadein_time" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="time_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_get_fadein_time" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_set_fadeout_time" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="time_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_get_fadeout_time" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_set_autorestart" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_set_autorestart_delay" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="delay_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_set_autorestart_random_delay" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="rand_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_has_autorestart" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_get_autorestart_delay" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_get_autorestart_random_delay" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_start" >
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_stop" >
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="oneshot_node_is_active" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mix_node_set_amount" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="ratio" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="mix_node_get_amount" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="blend2_node_set_amount" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="blend" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="blend2_node_get_amount" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="blend3_node_set_amount" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="blend" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="blend3_node_get_amount" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="blend4_node_set_amount" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="blend" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="blend4_node_get_amount" qualifiers="const" >
- <return type="Vector2">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="timescale_node_set_scale" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="scale" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="timescale_node_get_scale" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="timeseek_node_seek" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="pos_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_set_input_count" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="count" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_get_input_count" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_delete_input" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="input_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_set_input_auto_advance" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="input_idx" type="int">
- </argument>
- <argument index="2" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_has_input_auto_advance" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="input_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_set_xfade_time" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="time_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_get_xfade_time" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_set_current" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="input_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="transition_node_get_current" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="node_set_pos" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="screen_pos" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="node_get_pos" qualifiers="const" >
- <return type="Vector2">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_node" >
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="connect" >
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="dst_id" type="int">
- </argument>
- <argument index="2" name="dst_input_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_connected" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="dst_id" type="int">
- </argument>
- <argument index="2" name="dst_input_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="disconnect" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="dst_input_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_active" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_active" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_base_path" >
- <argument index="0" name="path" type="NodePath">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_base_path" qualifiers="const" >
- <return type="NodePath">
- </return>
- <description>
- </description>
- </method>
- <method name="reset" >
- <description>
- </description>
- </method>
- <method name="recompute_caches" >
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="AudioServer" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="sample_create" >
- <return type="RID">
- </return>
- <argument index="0" name="format" type="int">
- </argument>
- <argument index="1" name="stereo" type="bool">
- </argument>
- <argument index="2" name="length" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_set_description" >
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="description" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_description" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_format" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_is_stereo" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_length" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_set_signed_data" >
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="data" type="RealArray">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_set_data" >
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RawArray">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_data" qualifiers="const" >
- <return type="RawArray">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_set_mix_rate" >
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="mix_rate" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_mix_rate" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_set_loop_format" >
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="loop_format" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_loop_format" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_set_loop_begin" >
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="pos" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_loop_begin" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_set_loop_end" >
- <argument index="0" name="sample" type="RID">
- </argument>
- <argument index="1" name="pos" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="sample_get_loop_end" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="voice_play" >
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="sample" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_volume" >
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="volume" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_pan" >
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="pan" type="real">
- </argument>
- <argument index="2" name="depth" type="real" default="0">
- </argument>
- <argument index="3" name="height" type="real" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_filter" >
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="type" type="int">
- </argument>
- <argument index="2" name="cutoff" type="real">
- </argument>
- <argument index="3" name="resonance" type="real">
- </argument>
- <argument index="4" name="gain" type="real" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_chorus" >
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="chorus" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_reverb" >
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="room" type="int">
- </argument>
- <argument index="2" name="reverb" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_mix_rate" >
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="rate" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_positional" >
- <argument index="0" name="voice" type="RID">
- </argument>
- <argument index="1" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_volume" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_pan" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_pan_height" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_pan_depth" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_filter_type" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_filter_cutoff" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_filter_resonance" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_chorus" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_reverb_type" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_reverb" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_get_mix_rate" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_is_positional" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_stop" >
- <argument index="0" name="voice" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="free" >
- <argument index="0" name="rid" type="RID">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="SAMPLE_LOOP_PING_PONG" value="2">
- </constant>
- <constant name="SAMPLE_FORMAT_IMA_ADPCM" value="2">
- </constant>
- <constant name="FILTER_HIPASS" value="3">
- </constant>
- <constant name="FILTER_NONE" value="0">
- </constant>
- <constant name="REVERB_HALL" value="3">
- </constant>
- <constant name="REVERB_MEDIUM" value="1">
- </constant>
- <constant name="REVERB_SMALL" value="0">
- </constant>
- <constant name="FILTER_LOWPASS" value="1">
- </constant>
- <constant name="SAMPLE_LOOP_FORWARD" value="1">
- </constant>
- <constant name="REVERB_LARGE" value="2">
- </constant>
- <constant name="SAMPLE_FORMAT_PCM16" value="1">
- </constant>
- <constant name="FILTER_BANDLIMIT" value="6">
- </constant>
- <constant name="FILTER_NOTCH" value="4">
- </constant>
- <constant name="FILTER_BANDPASS" value="2">
- </constant>
- <constant name="SAMPLE_FORMAT_PCM8" value="0">
- </constant>
- <constant name="SAMPLE_LOOP_NONE" value="0">
- </constant>
- </constants>
-</class>
-<class name="AudioServerSW" inherits="AudioServer" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="AudioStream" inherits="Resource" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="play" >
- <description>
- </description>
- </method>
- <method name="stop" >
- <description>
- </description>
- </method>
- <method name="is_playing" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_loop" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_loop" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_stream_name" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_loop_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="seek_pos" >
- <argument index="0" name="pos" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_pos" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_update_mode" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="update" >
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="UPDATE_IDLE" value="1">
- </constant>
- <constant name="UPDATE_THREAD" value="2">
- </constant>
- <constant name="UPDATE_NONE" value="0">
- </constant>
- </constants>
-</class>
-<class name="AudioStreamOGG" inherits="AudioStream" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="BCSFX" inherits="ScenarioFX" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="BGColorFX" inherits="ScenarioFX" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="BGImageFX" inherits="ScenarioFX" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="BaseButton" inherits="Control" category="Nodes/GUI Nodes">
- <brief_description>
- Provides a base class for different kinds of buttons.
- </brief_description>
- <description>
- BaseButton is the abstract base class for buttons, so it shouldn&apos;t be used directly (It doesnt display anything). Other types of buttons inherit from it.
- </description>
- <methods>
- <method name="set_pressed" >
- <argument index="0" name="pressed" type="bool">
- </argument>
- <description>
- Set the button to pressed state (only if toggle_mode is active).
- </description>
- </method>
- <method name="is_pressed" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return when the button is pressed (only if toggle_mode is active).
- </description>
- </method>
- <method name="set_toggle_mode" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- Set the button toggle_mode property. Toggle mode makes the button flip state between pressed and unpressed each time its area is clicked.
- </description>
- </method>
- <method name="is_toggle_mode" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return the toggle_mode property (see [method set_toggle_mode]).
- </description>
- </method>
- <method name="set_disabled" >
- <argument index="0" name="disabled" type="bool">
- </argument>
- <description>
- Set the button into disabled state. When a button is disabled, it can&apos;t be clicked or toggled.
- </description>
- </method>
- <method name="is_disabled" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return wether the button is in disabled state (see [method set_disabled]).
- </description>
- </method>
- <method name="set_click_on_press" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- Set the button click_on_press mode. This mode generates click signals when a mousebutton or key is just pressed (by default signals are generated when the button/keys are released and both press and release occur in the visual area of the Button).
- </description>
- </method>
- <method name="get_click_on_press" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return the state of the click_on_press property (see [method set_click_on_press]).
- </description>
- </method>
- </methods>
- <signals>
- <signal name="toggled">
- <argument index="0" name="pressed" type="bool">
- </argument>
- <description>
- This signal is emitted when the button was just toggled between pressed and normal states (only if toggle_mode is active). The new state is contained in the [html i]pressed[html /i] argument.
- </description>
- </signal>
- <signal name="pressed">
- <description>
- This signal is emitted every time the button is pressed or toggled.
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="BodyShape" inherits="Spatial" category="Nodes/3D/3D Physics Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="BoxShape" inherits="Shape" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_extents" >
- <argument index="0" name="extents" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_extents" qualifiers="const" >
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Button" inherits="BaseButton" category="Nodes/GUI Nodes">
- <brief_description>
- Standard themed Button.
- </brief_description>
- <description>
- Button is just the standard themed button: [html image src=&quot;images/button_example.png&quot;/] It can contain a text and an icon, and will display them according to the current theme.
- </description>
- <methods>
- <method name="set_text" >
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- Set the button text, which will be displayed inside the button area.
- </description>
- </method>
- <method name="get_text" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- Return the button text.
- </description>
- </method>
- <method name="set_icon" >
- <argument index="0" name="texture" type="Object">
- </argument>
- <description>
- Set the button icon, which will be displayed to the left of the text.
- </description>
- </method>
- <method name="get_icon" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- Return the button icon.
- </description>
- </method>
- <method name="set_flat" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- Set the [html i]flat[html /i] property of a Button. Flat buttons don&apos;t display decoration unless hoevered or pressed.
- </description>
- </method>
- <method name="set_clip_text" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- Set the [html i]clip_text[html /i] property of a Button. When this property is enabled, text that is too large to fit the button is clipped, when disabled (default) the Button will always be wide enough to hold the text.
- </description>
- </method>
- <method name="get_clip_text" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return the state of the [html i]clip_text[html /i] property (see [method set_clip_text])
- </description>
- </method>
- <method name="is_flat" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return the state of the [html i]flat[html /i] property (see [method set_flat])
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Camera" inherits="Spatial" category="Nodes/3D">
- <brief_description>
- Camera node, displays from a point of view.
- </brief_description>
- <description>
- Camera is a special node that displays what is visible from its current location. Cameras register themselves in the nearest [Viewport] node (when ascending the tree). Only one camera can be active per viewport. If no viewport is available ascending the tree, the Camera will register in the global viewport. In other words, a Camera just provides [html i]3D[html /i] display capabilities to a [Viewport], and, without one, a [Scene] registered in that [Viewport] (or higher viewports) can&apos;t be displayed.
- </description>
- <methods>
- <method name="project_ray_normal" qualifiers="const" >
- <return type="Vector3">
- </return>
- <argument index="0" name="screen_point" type="Vector2">
- </argument>
- <description>
- Return a normal vector in worldspace, that is the result of projecting a point on the [Viewport] rectangle by the camera proyection. This is useful for casting rays in the form of (origin,normal) for object intersection or picking.
- </description>
- </method>
- <method name="project_ray_origin" qualifiers="const" >
- <return type="Vector3">
- </return>
- <argument index="0" name="screen_point" type="Vector2">
- </argument>
- <description>
- Return a 3D position in worldspace, that is the result of projecting a point on the [Viewport] rectangle by the camera proyection. This is useful for casting rays in the form of (origin,normal) for object intersection or picking.
- </description>
- </method>
- <method name="unproject_position" qualifiers="const" >
- <return type="Vector2">
- </return>
- <argument index="0" name="world_point" type="Vector3">
- </argument>
- <description>
- Return how a 3D point in worldpsace maps to a 2D coordinate in the [Viewport] rectangle.
- </description>
- </method>
- <method name="set_perspective" >
- <argument index="0" name="fov" type="real">
- </argument>
- <argument index="1" name="z_near" type="real">
- </argument>
- <argument index="2" name="z_far" type="real">
- </argument>
- <description>
- Set the camera projection to perspective mode, by specifying a [html i]FOV[html /i] angle in degrees (FOV means Field of View), and the [html i]near[html /i] and [html i]far[html /i] clip planes in worldspace units.
- </description>
- </method>
- <method name="set_orthogonal" >
- <argument index="0" name="size" type="real">
- </argument>
- <argument index="1" name="z_near" type="real">
- </argument>
- <argument index="2" name="z_far" type="real">
- </argument>
- <description>
- Set the camera projection to orthogonal mode, by specifying a rectangle and the [html i]near[html /i] and [html i]far[html /i] clip planes in worldspace units. (As a hint, 2D games often use this projection, with values specified in pixels)
- </description>
- </method>
- <method name="make_current" >
- <description>
- Make this camera the current Camera for the [Viewport] (see class description). If the Camera Node is outside the scene tree, it will attempt to become current once it&apos;s added.
- </description>
- </method>
- <method name="clear_current" >
- <description>
- </description>
- </method>
- <method name="is_current" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return wether the Camera is the current one in the [Viewport], or plans to become current (if outside the scene tree).
- </description>
- </method>
- <method name="get_camera_transform" qualifiers="const" >
- <return type="Transform">
- </return>
- <description>
- Get the camera transform. Subclassed cameras (such as CharacterCamera) may provide different transforms than the [Node] transform.
- </description>
- </method>
- <method name="get_fov" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="PROJECTION_PERSPECTIVE" value="0">
- Perspective Projection (object&apos;s size on the screen becomes smaller when far away).
- </constant>
- <constant name="PROJECTION_ORTHOGONAL" value="1">
- Orthogonal Projection (objects remain the same size on the screen no matter how far away they are).
- </constant>
- </constants>
-</class>
-<class name="CanvasItem" inherits="Node" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="edit_set_state" >
- <argument index="0" name="state" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="edit_get" qualifiers="const" >
- <description>
- </description>
- </method>
- <method name="edit_set_rect" >
- <argument index="0" name="rect" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- <method name="edit_rotate" >
- <argument index="0" name="degrees" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_rect" qualifiers="const" >
- <return type="Rect2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_canvas_item" qualifiers="const" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="is_visible" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="is_hidden" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="show" >
- <description>
- </description>
- </method>
- <method name="hide" >
- <description>
- </description>
- </method>
- <method name="update" >
- <description>
- </description>
- </method>
- <method name="set_as_toplevel" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_set_as_toplevel" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_blend_mode" >
- <argument index="0" name="blend_mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_blend_mode" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_opacity" >
- <argument index="0" name="opacity" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_opacity" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_self_opacity" >
- <argument index="0" name="self_opacity" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_self_opacity" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="item_rect_changed">
- <description>
- </description>
- </signal>
- <signal name="draw">
- <description>
- </description>
- </signal>
- <signal name="visibility_changed">
- <description>
- </description>
- </signal>
- <signal name="hide">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="NOTIFICATION_EXIT_CANVAS" value="33">
- </constant>
- <constant name="NOTIFICATION_DRAW" value="30">
- </constant>
- <constant name="BLEND_MODE_MUL" value="3">
- </constant>
- <constant name="BLEND_MODE_MIX" value="0">
- </constant>
- <constant name="NOTIFICATION_ENTER_CANVAS" value="32">
- </constant>
- <constant name="NOTIFICATION_VISIBILITY_CHANGED" value="31">
- </constant>
- <constant name="BLEND_MODE_ADD" value="1">
- </constant>
- <constant name="BLEND_MODE_SUB" value="2">
- </constant>
- </constants>
-</class>
-<class name="CapsuleShape" inherits="Shape" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_radius" >
- <argument index="0" name="radius" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_radius" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_height" >
- <argument index="0" name="height" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_height" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="CheckButton" inherits="BaseButton" category="Nodes/GUI Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_text" >
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_text" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ColorPicker" inherits="Control" category="Nodes/GUI Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_color" >
- <argument index="0" name="arg0" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color" qualifiers="const" >
- <return type="Color">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="color_changed">
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="ConcavePolygonShape" inherits="Shape" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_faces" >
- <argument index="0" name="faces" type="Vector3Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_faces" qualifiers="const" >
- <return type="Vector3Array">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ConfirmationDialog" inherits="Popup" category="Nodes/GUI Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_ok" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_cancel" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_text" >
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_hide_on_ok" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_hide_on_ok" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="register_text_enter" >
- <argument index="0" name="line_edit" type="Object">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="confirmed">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="Control" inherits="CanvasItem" category="Core">
- <brief_description>
- Control is the base class Node for all the GUI components.
- </brief_description>
- <description>
- Control is the base class Node for all the GUI components. Every GUI component inherits from it, directly or indirectly. Control Nodes contain positions relative to their parent control nodes. In this way, sections of the scene tree made of contiguous Control Nodes, become user interfaces.[html br/]&#10;&#9;Controls contain a [html i]canvas item[html /i] RID from the visual server, and can draw to it when receiving a NOTIFICATION_DRAW.[html br/]&#10;&#9;TODO: Explain margins and anchors[html br/]&#10;&#9;TODO: explain focus[html br/]
- </description>
- <methods>
- <method name="accept_event" >
- <description>
- </description>
- </method>
- <method name="get_minimum_size" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- Return the minimum size this Control can shrink to. A control will never be displayed or resized smaller than its minimum size.
- </description>
- </method>
- <method name="is_window" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return wether this control is a [html i]window[html /i]. Controls are considered windows when their parent [Node] is not a Control.
- </description>
- </method>
- <method name="get_window" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- Return the [html i]window[html /i] for this control, ascending the scene tree (see [method is_window]).
- </description>
- </method>
- <method name="set_anchor" >
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="anchor_mode" type="int">
- </argument>
- <description>
- Change the anchor (ANCHOR_BEGIN, ANCHOR_END, ANCHOR_RATIO) type for a margin (MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM). Changing the anchor mode converts the current margin offset from the previos anchor mode to the new one, so margin offsets ([method set_margin]) must be done after setting anchors, or at the same time ([method set_anchor_and_margin]).
- </description>
- </method>
- <method name="get_anchor" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="margin" type="int">
- </argument>
- <description>
- Return the anchor type (ANCHOR_BEGIN, ANCHOR_END, ANCHOR_RATIO) for a given margin (MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM).
- </description>
- </method>
- <method name="set_margin" >
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="offset" type="real">
- </argument>
- <description>
- Set a margin offset. Margin can be one of (MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM). Offset value being set depends on the anchor mode.
- </description>
- </method>
- <method name="set_anchor_and_margin" >
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="anchor_mode" type="int">
- </argument>
- <argument index="2" name="offset" type="real">
- </argument>
- <description>
- Change the anchor (ANCHOR_BEGIN, ANCHOR_END, ANCHOR_RATIO) type for a margin (MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM), and also set its offset. This is a helper (see [method set_anchor] and [method set_margin]).
- </description>
- </method>
- <method name="set_begin" >
- <argument index="0" name="pos" type="Vector2">
- </argument>
- <description>
- Sets MARGIN_LEFT and MARGIN_TOP at the same time. This is a helper (see [method set_margin]).
- </description>
- </method>
- <method name="set_end" >
- <argument index="0" name="pos" type="Vector2">
- </argument>
- <description>
- Sets MARGIN_RIGHT and MARGIN_BOTTOM at the same time. This is a helper (see [method set_margin]).
- </description>
- </method>
- <method name="set_pos" >
- <argument index="0" name="pos" type="Vector2">
- </argument>
- <description>
- Move the Control to a new position, relative to the top-left corner of the parent Control, changing all margins if needed and without changing current anchor mode. This is a helper (see [method set_margin]).
- </description>
- </method>
- <method name="set_size" >
- <argument index="0" name="size" type="Vector2">
- </argument>
- <description>
- Changes MARGIN_RIGHT and MARGIN_BOTTOM to fit a given size. This is a helper (see [method set_margin]).
- </description>
- </method>
- <method name="set_global_pos" >
- <argument index="0" name="pos" type="Vector2">
- </argument>
- <description>
- Move the Control to a new position, relative to the top-left corner of the [html i]window[html /i] Control, and without changing current anchor mode. (see [method set_margin]).
- </description>
- </method>
- <method name="get_margin" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="margin" type="int">
- </argument>
- <description>
- Return a margin offset. Margin can be one of (MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM). Offset value being returned depends on the anchor mode.
- </description>
- </method>
- <method name="get_begin" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_end" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- Returns MARGIN_LEFT and MARGIN_TOP at the same time. This is a helper (see [method set_margin]).
- </description>
- </method>
- <method name="get_pos" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- Returns the Control position, relative to the top-left corner of the parent Control and independly of the anchor mode.
- </description>
- </method>
- <method name="get_size" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- Returns the size of the Control, computed from all margins, however the size returned will [html b]never be smaller than the minimum size reported by [method get_minimum_size][html /b]. This means that even if end position of the Control rectangle is smaller than the begin position, the Control will still display and interact correctly. (see description, [method get_minimum_size], [method set_margin], [method set_anchor]).
- </description>
- </method>
- <method name="get_global_pos" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- Returns the Control position, relative to the top-left corner of the parent Control and independent of the anchor mode.
- </description>
- </method>
- <method name="get_rect" qualifiers="const" >
- <return type="Rect2">
- </return>
- <description>
- Return position and size of the Control, relative to the top-left corner of the parent Control. This is a helper (see [method get_pos],[method get_size]).
- </description>
- </method>
- <method name="get_global_rect" qualifiers="const" >
- <return type="Rect2">
- </return>
- <description>
- Return position and size of the Control, relative to the top-left corner of the [html i]window[html /i] Control. This is a helper (see [method get_global_pos],[method get_size]).
- </description>
- </method>
- <method name="set_area_as_parent_rect" >
- <description>
- Change all margins and anchors, so this Control always takes up the same area as the parent Control. This is a helper (see [method set_anchor],[method set_margin]).
- </description>
- </method>
- <method name="show_modal" >
- <argument index="0" name="exclusive" type="bool" default="false">
- </argument>
- <description>
- Display a Control as modal. Control must be a subwindow (see [method set_as_subwindow]). Modal controls capture the input signals until closed or the area outside them is accessed. When a modal control loses focus, or the ESC key is pressed, they automatically hide. Modal controls are used extensively for popup dialogs and menus.
- </description>
- </method>
- <method name="set_focus_mode" >
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- Set the focus access mode for the control (FOCUS_NONE, FOCUS_CLICK, FOCUS_ALL). Only one Control can be focused at the same time, and it will receive keyboard signals.
- </description>
- </method>
- <method name="has_focus" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return wether the Control is the current focused control (see [method set_focus_mode]).
- </description>
- </method>
- <method name="grab_focus" >
- <description>
- Steal the focus from another control and become the focused control (see [method set_focus_mode]).
- </description>
- </method>
- <method name="set_theme" >
- <argument index="0" name="theme" type="Object">
- </argument>
- <description>
- Override whole the [Theme] for this Control and all its children controls.
- </description>
- </method>
- <method name="get_theme" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- Return a [Theme] override, if one exists (see [method set_theme]).
- </description>
- </method>
- <method name="add_icon_override" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="texture" type="Object">
- </argument>
- <description>
- Override a single icon ([Texture]) in the theme of this Control. If texture is empty, override is cleared.
- </description>
- </method>
- <method name="add_style_override" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="stylebox" type="Object">
- </argument>
- <description>
- Override a single stylebox ([Stylebox]) in the theme of this Control. If stylebox is empty, override is cleared.
- </description>
- </method>
- <method name="add_font_override" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="font" type="Object">
- </argument>
- <description>
- Override a single font (font) in the theme of this Control. If font is empty, override is cleared.
- </description>
- </method>
- <method name="add_color_override" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_constant_override" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="constant" type="int">
- </argument>
- <description>
- Override a single constant (integer) in the theme of this Control. If constant equals Theme.INVALID_CONSTANT, override is cleared.
- </description>
- </method>
- <method name="get_parent_control" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- Return the parent Control. Unlike get_parent() in [Node], only returns a valid object if the parent is a Control.
- </description>
- </method>
- <method name="set_tooltip" >
- <argument index="0" name="tooltip" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_tooltip" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="atpos" type="Vector2" default="Vector2(0,0)">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_cursor_shape" >
- <argument index="0" name="shape" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_default_cursor_shape" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_cursor_shape" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="pos" type="Vector2" default="Vector2(0,0)">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_focus_neighbour" >
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="neighbour" type="NodePath">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_focus_neighbour" qualifiers="const" >
- <return type="NodePath">
- </return>
- <argument index="0" name="margin" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="focus_enter">
- <description>
- </description>
- </signal>
- <signal name="mouse_enter">
- <description>
- </description>
- </signal>
- <signal name="resized">
- <description>
- </description>
- </signal>
- <signal name="focus_exit">
- <description>
- </description>
- </signal>
- <signal name="input_event">
- <description>
- </description>
- </signal>
- <signal name="mouse_exit">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="CURSOR_FDIAGSIZE" value="12">
- </constant>
- <constant name="CURSOR_CAN_DROP" value="7">
- </constant>
- <constant name="CURSOR_DRAG" value="6">
- </constant>
- <constant name="CURSOR_IBEAM" value="1">
- </constant>
- <constant name="NOTIFICATION_FOCUS_ENTER" value="37">
- Control gained focus.
- </constant>
- <constant name="CURSOR_MOVE" value="13">
- </constant>
- <constant name="NOTIFICATION_MOUSE_ENTER" value="35">
- Mouse pointer entered the area of the Control.
- </constant>
- <constant name="NOTIFICATION_RESIZED" value="34">
- Control changed size (get_size() reports the new size).
- </constant>
- <constant name="FOCUS_CLICK" value="1">
- Control can acquire focus only if clicked.
- </constant>
- <constant name="CURSOR_HELP" value="16">
- </constant>
- <constant name="CURSOR_VSIZE" value="9">
- </constant>
- <constant name="CURSOR_VSPLIT" value="14">
- </constant>
- <constant name="CURSOR_BDIAGSIZE" value="11">
- </constant>
- <constant name="CURSOR_CROSS" value="3">
- </constant>
- <constant name="CURSOR_POINTING_HAND" value="2">
- </constant>
- <constant name="NOTIFICATION_FOCUS_EXIT" value="38">
- Control lost focus.
- </constant>
- <constant name="FOCUS_NONE" value="0">
- Control can&apos;t acquire focus.
- </constant>
- <constant name="ANCHOR_BEGIN" value="0">
- X is relative to MARGIN_LEFT, Y is relative to MARGIN_TOP,
- </constant>
- <constant name="CURSOR_HSIZE" value="10">
- </constant>
- <constant name="CURSOR_BUSY" value="5">
- </constant>
- <constant name="CURSOR_ARROW" value="0">
- </constant>
- <constant name="NOTIFICATION_MODAL_CLOSE" value="40">
- </constant>
- <constant name="NOTIFICATION_MOUSE_EXIT" value="36">
- Mouse pointer exited the area of the Control.
- </constant>
- <constant name="FOCUS_ALL" value="2">
- Control can acquire focus if clicked, or by pressing TAB/Directionals in the keyboard from another Control.
- </constant>
- <constant name="CURSOR_HSPLIT" value="15">
- </constant>
- <constant name="ANCHOR_RATIO" value="2">
- X and Y are a ratio (0 to 1) relative to the parent size 0 is left/top, 1 is right/bottom.
- </constant>
- <constant name="ANCHOR_END" value="1">
- X is relative to -MARGIN_RIGHT, Y is relative to -MARGIN_BOTTOM,
- </constant>
- <constant name="CURSOR_FORBIDDEN" value="8">
- </constant>
- <constant name="CURSOR_WAIT" value="4">
- </constant>
- <constant name="NOTIFICATION_THEME_CHANGED" value="39">
- </constant>
- </constants>
-</class>
-<class name="ConvexPolygonShape" inherits="Shape" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_planes" >
- <argument index="0" name="planes" type="Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_planes" qualifiers="const" >
- <return type="Array">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="GridMap" inherits="Spatial" category="Nodes/3D">
- <brief_description>
- GridMap is like a tile map, but in 3D.
- </brief_description>
- <description>
- GridMap is a 3D Tile map, using [html i]3D Cells[html /i] instead of tiles. On each cell, a mesh and a collision volume can be placed from a [MeshLibrary]. GridMap is used for designing worlds quickly. Despite that GridMaps can contain up to hundreds millions of cells, they are very optimized, and only use resources for the cells that contain items.
- </description>
- <methods>
- <method name="set_theme" >
- <argument index="0" name="theme" type="Object">
- </argument>
- <description>
- Set a MeshLibrary. Cell indices refer to items in the theme.
- </description>
- </method>
- <method name="get_theme" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- Get the current MeshLibrary (if exists).
- </description>
- </method>
- <method name="set_cell_size" >
- <argument index="0" name="size" type="real">
- </argument>
- <description>
- Set the size of a cell, in worldpsace units. All cells in a GridMap are the same size.
- </description>
- </method>
- <method name="get_cell_size" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the current cell size.
- </description>
- </method>
- <method name="set_octant_size" >
- <argument index="0" name="size" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_octant_size" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_width" >
- <argument index="0" name="width" type="int">
- </argument>
- <description>
- Set the width of the GridMap. Width is the amount of cells i the direction of the X coordinate.
- </description>
- </method>
- <method name="get_width" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Get the width of the GridMap. Width is the amount of cells i the direction of the X coordinate.
- </description>
- </method>
- <method name="set_height" >
- <argument index="0" name="height" type="int">
- </argument>
- <description>
- Set the height of the GridMap. Height is the amount of cells i the direction of the Y coordinate.
- </description>
- </method>
- <method name="get_height" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Get the height of the GridMap. Height is the amount of cells i the direction of the Y coordinate.
- </description>
- </method>
- <method name="set_depth" >
- <argument index="0" name="depth" type="int">
- </argument>
- <description>
- Set the depth of the GridMap. Depth is the amount of cells i the direction of the Z coordinate.
- </description>
- </method>
- <method name="get_depth" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Get the depth of the GridMap. Depth is the amount of cells i the direction of the Z coordinate.
- </description>
- </method>
- <method name="set_cell_item" >
- <argument index="0" name="x" type="int">
- </argument>
- <argument index="1" name="y" type="int">
- </argument>
- <argument index="2" name="z" type="int">
- </argument>
- <argument index="3" name="item" type="int">
- </argument>
- <argument index="4" name="orientation" type="int" default="0">
- </argument>
- <description>
- Set a cell item (x,y,z pos). Cell items are indices to items in the [MeshLibrary].
- </description>
- </method>
- <method name="get_cell_item" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="x" type="int">
- </argument>
- <argument index="1" name="y" type="int">
- </argument>
- <argument index="2" name="z" type="int">
- </argument>
- <description>
- Get a cell item (x,y,z pos). Cell items are indices to items in the [MeshLibrary].
- </description>
- </method>
- <method name="get_cell_item_orientation" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="x" type="int">
- </argument>
- <argument index="1" name="y" type="int">
- </argument>
- <argument index="2" name="z" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="resource_changed" >
- <argument index="0" name="arg0" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_center_x" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_center_x" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_center_y" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_center_y" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_center_z" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_center_z" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_clip" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <argument index="1" name="clipabove" type="bool" default="true">
- </argument>
- <argument index="2" name="floor" type="int" default="0">
- </argument>
- <argument index="3" name="axis" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="crate_area" >
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="area" type="AABB">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_bounds" qualifiers="const" >
- <return type="AABB">
- </return>
- <argument index="0" name="area" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_exterior_portal" >
- <argument index="0" name="area" type="int">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_name" >
- <argument index="0" name="area" type="int">
- </argument>
- <argument index="1" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_name" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="area" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_is_exterior_portal" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="area" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_portal_disable_distance" >
- <argument index="0" name="area" type="int">
- </argument>
- <argument index="1" name="distance" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_portal_disable_distance" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="area" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_portal_disable_color" >
- <argument index="0" name="area" type="int">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_portal_disable_color" qualifiers="const" >
- <return type="Color">
- </return>
- <argument index="0" name="area" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="erase_area" >
- <argument index="0" name="area" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_unused_area_id" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="INVALID_CELL_ITEM" value="-1">
- Value indicating that a cell item is not used or invalid.
- </constant>
- </constants>
-</class>
-<class name="MeshLibrary" inherits="Resource" category="Resources">
- <brief_description>
- Theme for a [GridMap].
- </brief_description>
- <description>
- MeshLibrary is [Resource] containing the data used in a [GridMap]. It&apos;s filled with items, each containing a mesh and a collision shape.
- </description>
- <methods>
- <method name="create_item" >
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- Create a new item, and assign it a given id.
- </description>
- </method>
- <method name="set_item_name" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="name" type="String">
- </argument>
- <description>
- Set the name of an item, referenced by id.
- </description>
- </method>
- <method name="set_item_mesh" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="mesh" type="Object">
- </argument>
- <description>
- Set the [Mesh] of an item, referenced by id.
- </description>
- </method>
- <method name="set_item_shape" >
- <argument index="0" name="id" type="int">
- </argument>
- <argument index="1" name="shape" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_name" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- Get the name of an item, referenced by id.
- </description>
- </method>
- <method name="get_item_mesh" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- Get the [Mesh] of an item, referenced by id.
- </description>
- </method>
- <method name="get_item_shape" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_item" >
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- Remove an item, referenced by id.
- </description>
- </method>
- <method name="clear" >
- <description>
- Clear all items contained in this resource.
- </description>
- </method>
- <method name="get_item_list" qualifiers="const" >
- <return type="IntArray">
- </return>
- <description>
- Get the list of item IDs contained in this theme.
- </description>
- </method>
- <method name="get_last_unused_item_id" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Get the last unused item id. This is useful for creating new item IDs.
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="CylinderShape" inherits="Shape" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_radius" >
- <argument index="0" name="radius" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_radius" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_height" >
- <argument index="0" name="height" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_height" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="DOFBlurFX" inherits="ScenarioFX" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="DirectionalLight" inherits="Light" category="Nodes/3D/3D Visual Nodes/3D Light Nodes">
- <brief_description>
- Directional Light, such as the Sun or the Moon.
- </brief_description>
- <description>
- A DirectionalLight is a type of [Light] node that emits light constantly in one direction (the negative z axis of the node). It is used lights with strong intensity that are located far away from the scene to model sunlight or moonlight. The worldpace location of the DirectionalLight transform (origin) is ignored, only the basis is used do determine light direction.
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="DynamicBody" inherits="PhysicsBody" category="Nodes/3D">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_mass" >
- <argument index="0" name="mass" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_friction" >
- <argument index="0" name="friction" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_bounce" >
- <argument index="0" name="bounce" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_mass" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_friction" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_bounce" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_linear_velocity" >
- <argument index="0" name="linear_velocity" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_linear_velocity" qualifiers="const" >
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_angular_velocity" >
- <argument index="0" name="angular_velocity" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_angular_velocity" qualifiers="const" >
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_sleeping" >
- <argument index="0" name="sleeping" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_sleeping" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_applied_force" >
- <argument index="0" name="applied_force" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_applied_force" qualifiers="const" >
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_applied_torque" >
- <argument index="0" name="applied_torque" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_applied_torque" qualifiers="const" >
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="apply_local_impulse" >
- <argument index="0" name="pos" type="Vector3">
- </argument>
- <argument index="1" name="impulse" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_axis_velocity" >
- <argument index="0" name="axis_velocity" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_direct_state_control" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_direct_state_control_enabled" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_omit_force_integration" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_omitting_force_integration" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="DynamicCharacterBody" inherits="DynamicBody" category="Nodes/3D">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="DynamicCustomBody" inherits="DynamicBody" category="Nodes/3D">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_mode" >
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="DynamicRigidBody" inherits="DynamicBody" category="Nodes/3D">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="FileDialog" inherits="Popup" category="Nodes/GUI Nodes">
- <brief_description>
- Dialog for selecting files or directories in the filesystem.
- </brief_description>
- <description>
- FileDialog is a preset dialog used to choose files and directories in the filesystem. It supports filter masks.
- </description>
- <methods>
- <method name="clear_filters" >
- <description>
- Clear all the added filters in the dialog.
- </description>
- </method>
- <method name="add_filter" >
- <argument index="0" name="filter" type="String">
- </argument>
- <description>
- Add a custom filter. Filter format is: &quot;mask ; description.
- </description>
- </method>
- <method name="get_current_dir" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- Get the current working directory of the file dialog.
- </description>
- </method>
- <method name="get_current_file" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- Get the current selected file of the file dialog (empty if none).
- </description>
- </method>
- <method name="get_current_path" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- Get the current selected path (directory and file) of the file dialog (empty if none).
- </description>
- </method>
- <method name="set_current_dir" >
- <argument index="0" name="dir" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_current_file" >
- <argument index="0" name="file" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_current_path" >
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_mode" >
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- Set the file dialog mode from the MODE_* enum.
- </description>
- </method>
- <method name="get_mode" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Get the file dialog mode from the MODE_* enum.
- </description>
- </method>
- </methods>
- <signals>
- <signal name="dir_selected">
- <argument index="0" name="dir" type="String">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="file_selected">
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- Event emitted when the user selects a file (double clicks it or presses the OK button).
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="MODE_OPEN_DIR" value="1">
- </constant>
- <constant name="MODE_OPEN_FILE" value="0">
- Editor will not allow to select nonexistent files.
- </constant>
- <constant name="MODE_SAVE_FILE" value="2">
- Editor will warn when a file exists.
- </constant>
- </constants>
-</class>
-<class name="FixedMaterial" inherits="Material" category="Resources">
- <brief_description>
- Simple Material with a fixed parameter set.
- </brief_description>
- <description>
- FixedMaterial is a simple type of material [Resource], which contains a fixed amount of paramters. It is the only type of material supported in fixed-pipeline devices and APIs. It is also an often a better alternative to [ShaderMaterial] for most simple use cases.
- </description>
- <methods>
- <method name="set_shader" >
- <argument index="0" name="shader" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shader" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_parameter" >
- <argument index="0" name="param" type="int">
- </argument>
- <argument index="1" name="value" type="var">
- </argument>
- <description>
- Set a parameter, parameters are defined in the PARAM_* enum. The type of each parameter may change, so it&apos;s best to check the enum.
- </description>
- </method>
- <method name="get_parameter" qualifiers="const" >
- <argument index="0" name="param" type="int">
- </argument>
- <description>
- Return a parameter, parameters are defined in the PARAM_* enum. The type of each parameter may change, so it&apos;s best to check the enum.
- </description>
- </method>
- <method name="set_texture" >
- <argument index="0" name="param" type="int">
- </argument>
- <argument index="1" name="texture" type="Object">
- </argument>
- <description>
- Set a texture. Textures change parameters per texel and are mapped to the model depending on the texcoord mode (see [method set_texcoord_mode]).
- </description>
- </method>
- <method name="get_texture" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="param" type="int">
- </argument>
- <description>
- Return a texture. Textures change parameters per texel and are mapped to the model depending on the texcoord mode (see [method set_texcoord_mode]).
- </description>
- </method>
- <method name="set_texgen_mode" >
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- Set the texture coordinate generation mode. Materials have a unique, texgen mode which can generate texture coordinates on the fly. Texgen mode must be one of the values from the TEXGEN_* enum. TEXGEN can be selected as a texture coordinate mode (see [method set_texcoord_mode]).
- </description>
- </method>
- <method name="get_texgen_mode" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the texture coordinate generation mode. Materials have a unique, texgen mode which can generate texture coordinates on the fly. Texgen mode must be one of the values from the TEXGEN_* enum. TEXGEN can be selected as a texture coordinate mode (see [method set_texcoord_mode]).
- </description>
- </method>
- <method name="set_texcoord_mode" >
- <argument index="0" name="param" type="int">
- </argument>
- <argument index="1" name="mode" type="int">
- </argument>
- <description>
- Set the texture coordinate mode. Each texture param (from the PARAM_* enum) has one. It defines how the textures are mapped to the object.
- </description>
- </method>
- <method name="get_texcoord_mode" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="param" type="int">
- </argument>
- <description>
- Return the texture coordinate mode. Each texture param (from the PARAM_* enum) has one. It defines how the textures are mapped to the object.
- </description>
- </method>
- <method name="set_uv_transform" >
- <argument index="0" name="transform" type="Transform">
- </argument>
- <description>
- Sets a special transform used to post-transform UV coordinates of the uv_xfrom tecoord mode: TEXCOORD_UV_TRANSFORM
- </description>
- </method>
- <method name="get_uv_transform" qualifiers="const" >
- <return type="Transform">
- </return>
- <description>
- Returns the special transform used to post-transform UV coordinates of the uv_xfrom tecoord mode: TEXCOORD_UV_TRANSFORM
- </description>
- </method>
- </methods>
- <constants>
- <constant name="PARAM_SPECULAR_EXP" value="4">
- Specular Exponent (size of the specular dot)
- </constant>
- <constant name="PARAM_DETAIL" value="1">
- Detail Layer for diffuse lighting.
- </constant>
- <constant name="TEXCOORD_UV2" value="2">
- Read texture coordinates from the UV2 array.
- </constant>
- <constant name="TEXGEN_SCREENZ" value="3">
- Use the screen coordinates as UV, scaled by depth and the screenz coefficient.
- </constant>
- <constant name="TEXCOORD_UV_TRANSFORM" value="1">
- Read texture coordinates from the UV array and transform them by uv_xform.
- </constant>
- <constant name="TEXGEN_LOCAL_XY" value="0">
- Use object local X and Y coordinates as UV.
- </constant>
- <constant name="PARAM_SHADE_PARAM" value="8">
- </constant>
- <constant name="PARAM_MAX" value="9">
- Maximum amount of parameters
- </constant>
- <constant name="PARAM_DIFFUSE" value="0">
- Diffuse Lighting (light scattered from surface).
- </constant>
- <constant name="PARAM_EMISSION" value="3">
- Emission Lighting (light emitted from the surface)
- </constant>
- <constant name="PARAM_SPECULAR" value="2">
- Specular Lighting (light reflected from the surface).
- </constant>
- <constant name="PARAM_DETAIL_MIX" value="6">
- Mix coefficient for the detail layer.
- </constant>
- <constant name="TEXGEN_SPHERE" value="1">
- Use view normal reflected by object normal as UV.
- </constant>
- <constant name="PARAM_NORMAL" value="7">
- Normal Map (irregularity map).
- </constant>
- <constant name="PARAM_GLOW" value="5">
- Glow (Visible emitted scattered light).
- </constant>
- <constant name="TEXCOORD_UV" value="0">
- Read texture coordinates from the UV array.
- </constant>
- <constant name="TEXCOORD_TEXGEN" value="3">
- Use texture coordinates from the texgen.
- </constant>
- <constant name="TEXGEN_SCREEN" value="2">
- Use the screen coordinates as UV.
- </constant>
- </constants>
-</class>
-<class name="FogFX" inherits="ScenarioFX" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="FollowCamera" inherits="Camera" category="Nodes/3D">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_orbit" >
- <argument index="0" name="orbit" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_orbit" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_orbit_x" >
- <argument index="0" name="x" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_orbit_y" >
- <argument index="0" name="y" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_min_orbit_x" >
- <argument index="0" name="x" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_min_orbit_x" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_max_orbit_x" >
- <argument index="0" name="x" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_max_orbit_x" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_height" >
- <argument index="0" name="height" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_height" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_inclination" >
- <argument index="0" name="inclination" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_inclination" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="rotate_orbit" >
- <argument index="0" name="arg0" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_distance" >
- <argument index="0" name="distance" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_distance" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_max_distance" >
- <argument index="0" name="max_distance" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_max_distance" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_min_distance" >
- <argument index="0" name="min_distance" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_min_distance" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_clip" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_clip" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_autoturn" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_autoturn" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_autoturn_tolerance" >
- <argument index="0" name="degrees" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_autoturn_tolerance" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_autoturn_speed" >
- <argument index="0" name="speed" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_autoturn_speed" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_smoothing" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_smoothing" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_rotation_smoothing" >
- <argument index="0" name="amount" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_rotation_smoothing" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_translation_smoothing" >
- <argument index="0" name="amount" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_translation_smoothing" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_use_lookat_target" >
- <argument index="0" name="use" type="bool">
- </argument>
- <argument index="1" name="lookat" type="Vector3" default="Vector3(0, 0, 0)">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Font" inherits="Resource" category="Resources">
- <brief_description>
- Internationalized font and text drawing support.
- </brief_description>
- <description>
- Font contains an unicode compatible character set, as well as the ability to draw it with variable width, ascent, descent and kerning. For creating fonts from TTF files (or other font formats), see the editor support for fonts. TODO check wikipedia for graph of ascent/baseline/descent/height/etc.
- </description>
- <methods>
- <method name="set_height" >
- <argument index="0" name="px" type="real">
- </argument>
- <description>
- Set the total font height (ascent plus descent) in pixels.
- </description>
- </method>
- <method name="get_height" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the total font height (ascent plus descent) in pixels.
- </description>
- </method>
- <method name="set_ascent" >
- <argument index="0" name="px" type="real">
- </argument>
- <description>
- Set the font ascent (number of pixels above the baseline).
- </description>
- </method>
- <method name="get_ascent" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the font ascent (number of pixels above the baseline).
- </description>
- </method>
- <method name="get_descent" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the font descent (number of pixels below the baseline).
- </description>
- </method>
- <method name="add_kerning_pair" >
- <argument index="0" name="char_a" type="int">
- </argument>
- <argument index="1" name="char_b" type="int">
- </argument>
- <argument index="2" name="kerning" type="int">
- </argument>
- <description>
- Add a kerning pair to the [Font] as a difference. Kerning pairs are special cases where a typeface advance is determined by the next character.
- </description>
- </method>
- <method name="get_kerning_pair" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- Return a kerning pair as a difference. Kerning pairs are special cases where a typeface advance is determined by the next character.
- </description>
- </method>
- <method name="add_texture" >
- <argument index="0" name="texture" type="Object">
- </argument>
- <description>
- Add a texture to the [Font].
- </description>
- </method>
- <method name="add_char" >
- <argument index="0" name="character" type="int">
- </argument>
- <argument index="1" name="texture" type="int">
- </argument>
- <argument index="2" name="rect" type="Rect2">
- </argument>
- <argument index="3" name="align" type="Vector2" default="Vector2(0,0)">
- </argument>
- <argument index="4" name="advance" type="real" default="-1">
- </argument>
- <description>
- Add a character to the font, where &quot;character&quot; is the unicode value, &quot;texture&quot; is the texture index, &quot;rect&quot; is the region in the texture (in pixels!), &quot;align&quot; is the (optional) alignment for the character and &quot;advance&quot; is the (optional) advance.
- </description>
- </method>
- <method name="get_char_size" qualifiers="const" >
- <return type="Vector2">
- </return>
- <argument index="0" name="char" type="int">
- </argument>
- <argument index="1" name="next" type="int" default="0">
- </argument>
- <description>
- Return the size of a character, optionally taking kerning into account if the next character is provided.
- </description>
- </method>
- <method name="get_string_size" qualifiers="const" >
- <return type="Vector2">
- </return>
- <argument index="0" name="string" type="String">
- </argument>
- <description>
- Return the size of a string, taking kerning and advance into account.
- </description>
- </method>
- <method name="clear" >
- <description>
- Clear all the font data.
- </description>
- </method>
- <method name="draw" qualifiers="const" >
- <argument index="0" name="canvas_item" type="RID">
- </argument>
- <argument index="1" name="pos" type="Vector2">
- </argument>
- <argument index="2" name="string" type="String">
- </argument>
- <argument index="3" name="modulate" type="Color" default="Color(1,1,1,1)">
- </argument>
- <argument index="4" name="clip_w" type="int" default="-1">
- </argument>
- <description>
- Draw &quot;string&quot; into a canvas item using the font at a given &quot;pos&quot; position, with &quot;modulate&quot; color, and optionally clipping the width. &quot;pos&quot; specifies te baseline, not the top. To draw from the top, [html i]ascent[html /i] must be added to the Y axis.
- </description>
- </method>
- <method name="draw_char" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="canvas_item" type="RID">
- </argument>
- <argument index="1" name="pos" type="Vector2">
- </argument>
- <argument index="2" name="char" type="int">
- </argument>
- <argument index="3" name="next" type="int" default="-1">
- </argument>
- <argument index="4" name="modulate" type="Color" default="Color(1,1,1,1)">
- </argument>
- <description>
- Draw character &quot;char&quot; into a canvas item using the font at a given &quot;pos&quot; position, with &quot;modulate&quot; color, and optionally kerning if &quot;next&quot; is apassed. clipping the width. &quot;pos&quot; specifies te baseline, not the top. To draw from the top, [html i]ascent[html /i] must be added to the Y axis. The width used by the character is returned, making this function useful for drawing strings character by character.
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="GammaFX" inherits="ScenarioFX" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="_Geometry" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="build_box_planes" >
- <return type="Array">
- </return>
- <argument index="0" name="extents" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="build_cylinder_planes" >
- <return type="Array">
- </return>
- <argument index="0" name="radius" type="real">
- </argument>
- <argument index="1" name="height" type="real">
- </argument>
- <argument index="2" name="sides" type="int">
- </argument>
- <argument index="3" name="axis" type="int" default="2">
- </argument>
- <description>
- </description>
- </method>
- <method name="build_capsule_planes" >
- <return type="Array">
- </return>
- <argument index="0" name="radius" type="real">
- </argument>
- <argument index="1" name="height" type="real">
- </argument>
- <argument index="2" name="sides" type="int">
- </argument>
- <argument index="3" name="lats" type="int">
- </argument>
- <argument index="4" name="axis" type="int" default="2">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Globals" inherits="Object" category="Core">
- <brief_description>
- Contains global variables accessible from everywhere.
- </brief_description>
- <description>
- Contains global variables accessible from everywhere. Use the normal [Object] API, such as &quot;Globals.get(variable)&quot;, &quot;Globals.set(variable,value)&quot; or &quot;Globals.has(variable)&quot; to access them. Variables stored in engine.cfg are also loaded into globals, making this object very useful for reading custom game configuration options.
- </description>
- <methods>
- <method name="has" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_order" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="pos" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_order" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_persisting" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_persisting" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear" >
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="localize_path" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="globalize_path" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="GlowFX" inherits="ScenarioFX" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="HDRFX" inherits="ScenarioFX" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="HScrollBar" inherits="ScrollBar" category="Nodes/GUI Nodes">
- <brief_description>
- Horizontal version of [ScrollBar], which goes from top (min) to bottom (max).
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="HSeparator" inherits="Separator" category="Nodes/GUI Nodes">
- <brief_description>
- Horizontal version of [Separator].
- </brief_description>
- <description>
- Horizontal version of [Separator]. It is used to separate objects vertiacally, though (but it looks horizontal!).
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="HSlider" inherits="Slider" category="Nodes/GUI Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="IP" inherits="Object" category="Networking">
- <brief_description>
- IP Protocol support functions.
- </brief_description>
- <description>
- IP contains some support functions for the IPv4 protocol. TCP/IP support is in different classes (see [TCP_Client], [TCP_Server]). IP provides hostname resolution support, both blocking and threaded.
- </description>
- <methods>
- <method name="resolve_hostname" >
- <return type="String">
- </return>
- <argument index="0" name="host" type="String">
- </argument>
- <description>
- Resolve a given hostname, blocking. Resolved hostname is returned as an IP.
- </description>
- </method>
- <method name="resolve_hostname_queue_item" >
- <return type="int">
- </return>
- <argument index="0" name="host" type="String">
- </argument>
- <description>
- Create a queue item for resolving a given hostname. The queue ID is returned, or RESOLVER_INVALID_ID on error.
- </description>
- </method>
- <method name="get_resolve_item_status" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- Return the status of hostname queued for resolving, given it&apos;s queue ID. Returned status can be any of the RESOLVER_STATUS_* enumeration.
- </description>
- </method>
- <method name="get_resolve_item_address" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- Return a resolved item address, or an empty string if an error happened or resolution didn&apos;t happen yet (see [method get_resolve_item_status]).
- </description>
- </method>
- <method name="erase_resolve_item" >
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- Erase a queue ID, removing it from the queue if needed. This should be used after a queue is completed to free it and enable more queries to happen.
- </description>
- </method>
- </methods>
- <constants>
- <constant name="RESOLVER_INVALID_ID" value="-1">
- </constant>
- <constant name="RESOLVER_MAX_QUERIES" value="32">
- </constant>
- <constant name="RESOLVER_STATUS_NONE" value="0">
- </constant>
- <constant name="RESOLVER_STATUS_ERROR" value="3">
- </constant>
- <constant name="RESOLVER_STATUS_WAITING" value="1">
- </constant>
- <constant name="RESOLVER_STATUS_DONE" value="2">
- </constant>
- </constants>
-</class>
-<class name="IP_Unix" inherits="IP" category="Networking">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="InputMap" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Label" inherits="Range" category="Nodes/GUI Nodes">
- <brief_description>
- Control that displays formatted text.
- </brief_description>
- <description>
- Label is a control that displays formatted text, optionally autowrapping it to the [Control] area. It inherits from range to be able to scroll wrapped text vertically.
- </description>
- <methods>
- <method name="set_align" >
- <argument index="0" name="align" type="int">
- </argument>
- <description>
- Set the alignmend mode to any of the ALIGN_* enumeration values.
- </description>
- </method>
- <method name="get_align" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the alignmend mode (any of the ALIGN_* enumeration values).
- </description>
- </method>
- <method name="set_text" >
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- Set the label text. Text can contain newlines.
- </description>
- </method>
- <method name="get_text" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- Return the label text. Text can contain newlines.
- </description>
- </method>
- <method name="set_autowrap" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- Set [html i]autowrap[html /i] mode. When enabled, autowrap will fit text to the control width, breaking sentences when they exceed the available horizontal space. When disabled, the label minimum width becomes the width of the longest row, and the minimum height large enough to fit all rows.
- </description>
- </method>
- <method name="has_autowrap" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return the state of the [html i]autowrap[html /i] mode (see [method set_autowrap]).
- </description>
- </method>
- </methods>
- <constants>
- <constant name="ALIGN_CENTER" value="1">
- Align rows centered.
- </constant>
- <constant name="ALIGN_LEFT" value="0">
- Align rows to the left (default).
- </constant>
- <constant name="ALIGN_RIGHT" value="2">
- Align rows to the right (default).
- </constant>
- <constant name="ALIGN_FILL" value="3">
- Expand row whitespaces to fit the width.
- </constant>
- </constants>
-</class>
-<class name="Light" inherits="VisualInstance" category="Nodes/3D/3D Visual Nodes/3D Light Nodes">
- <brief_description>
- Provides a base class for different kinds of light nodes.
- </brief_description>
- <description>
- Light is the abstract base class for light nodes, so it shouldn&apos;t be used directly (It can&apos;t be instanced). Other types of light nodes inherit from it. Light contains the common variables and parameters used for lighting.
- </description>
- <methods>
- <method name="set_parameter" >
- <argument index="0" name="variable" type="int">
- </argument>
- <argument index="1" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_parameter" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_color" >
- <argument index="0" name="color" type="int">
- </argument>
- <argument index="1" name="value" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color" qualifiers="const" >
- <return type="Color">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_project_shadows" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_project_shadows" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_projector" >
- <argument index="0" name="projector" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_projector" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_operator" >
- <argument index="0" name="operator" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_operator" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="COLOR_DIFFUSE" value="1">
- </constant>
- <constant name="PARAM_SPOT_ANGLE" value="1">
- </constant>
- <constant name="PARAM_ATTENUATION" value="4">
- </constant>
- <constant name="COLOR_SPECULAR" value="2">
- </constant>
- <constant name="COLOR_AMBIENT" value="0">
- </constant>
- <constant name="PARAM_SHADOW_DARKENING" value="5">
- </constant>
- <constant name="PARAM_RADIUS" value="2">
- </constant>
- <constant name="PARAM_SPOT_ATTENUATION" value="4">
- </constant>
- <constant name="PARAM_ENERGY" value="3">
- </constant>
- </constants>
-</class>
-<class name="LineEdit" inherits="Control" category="Nodes/GUI Nodes">
- <brief_description>
- Control that provides single line string editing.
- </brief_description>
- <description>
- LineEdit provides a single line string editor, used for text fields.
- </description>
- <methods>
- <method name="clear" >
- <description>
- Clear the [LineEdit] text.
- </description>
- </method>
- <method name="select_all" >
- <description>
- Select the whole string.
- </description>
- </method>
- <method name="set_text" >
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- Set the text in the [LineEdit], clearing the existing one and the selection.
- </description>
- </method>
- <method name="get_text" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- Return the text in the [LineEdit].
- </description>
- </method>
- <method name="set_cursor_pos" >
- <argument index="0" name="pos" type="int">
- </argument>
- <description>
- Set the cursor position inside the [LineEdit], causing it to scroll if needed.
- </description>
- </method>
- <method name="get_cursor_pos" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the cursor position inside the [LineEdit].
- </description>
- </method>
- <method name="set_max_length" >
- <argument index="0" name="chars" type="int">
- </argument>
- <description>
- Set the maximum amount of characters the [LineEdit] can edit, and cropping existing text in case it exceeds that limit. Setting 0 removes the limit.
- </description>
- </method>
- <method name="get_max_length" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the maximum amount of characters the [LineEdit] can edit. If 0 is returned, no limit exists.
- </description>
- </method>
- <method name="append_at_cursor" >
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- Append text at cursor, scrolling the [LineEdit] when needed.
- </description>
- </method>
- <method name="set_editable" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- Set the [html i]editable[html /i] status of the [LineEdit]. When disabled, existing text can&apos;t be modified and new text can&apos;t be added.
- </description>
- </method>
- <method name="is_editable" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return the [html i]editable[html /i] status of the [LineEdit] (see [method set_editable]).
- </description>
- </method>
- <method name="set_secret" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- Set the [html i]secret[html /i] status of the [LineEdit]. When enabled, every character is displayed as &quot;*&quot;.
- </description>
- </method>
- <method name="is_secret" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return the [html i]secret[html /i] status of the [LineEdit] (see [method set_secret]).
- </description>
- </method>
- <method name="select" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="text_entered">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- This signal is emitted when the user presses KEY_ENTER on the [LineEdit]. This signal is often used as an alternate confirmation mechanism in dialogs.
- </description>
- </signal>
- <signal name="text_changed">
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- When the text changes, this signal is emitted.
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="MainLoop" inherits="Object" category="Main Loop">
- <brief_description>
- Main loop is the abstract main loop base class.
- </brief_description>
- <description>
- Main loop is the abstract main loop base class. All other main loop classes are derived from it. Upon application start, a [MainLoop] has to be provided to OS, else the application will exit. This happens automatically (and a [SceneMainLoop] is created), unless a main [Script] is supplied, which may or not create and return a [MainLoop].
- </description>
- <methods>
- </methods>
- <constants>
- <constant name="NOTIFICATION_WM_QUIT_REQUEST" value="7">
- </constant>
- <constant name="NOTIFICATION_WM_FOCUS_IN" value="5">
- </constant>
- <constant name="NOTIFICATION_WM_FOCUS_OUT" value="6">
- </constant>
- </constants>
-</class>
-<class name="Material" inherits="Resource" category="Resources">
- <brief_description>
- Abstract base [Resource] for coloring and shading geometry.
- </brief_description>
- <description>
- Material is a base [Resource] used for coloring and shading geometry. All materials inherit from it and almost all [VisualInstance] derived nodes carry a Material. A few flags and parameters are shared between all material types and are configured here.
- </description>
- <methods>
- <method name="set_flag" >
- <argument index="0" name="flag" type="int">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- Set a [Material] flag, which toggles on or off a behavior when rendering. See enumeration FLAG_* for a list.
- </description>
- </method>
- <method name="get_flag" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="flag" type="int">
- </argument>
- <description>
- Return a [Material] flag, which toggles on or off a behavior when rendering. See enumeration FLAG_* for a list.
- </description>
- </method>
- <method name="set_hint" >
- <argument index="0" name="hint" type="int">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_hint" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="hint" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_blend_mode" >
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- Set blend mode for the material, which can be one of BLEND_MODE_MIX (default), BLEND_MODE_ADD, BLEND_MODE_SUB. Keep in mind that only BLEND_MODE_MIX ensures that the material [html i]may[html /i] be opaque, any other blend mode will render with alpha blending enabled in raster-based [VisualServer] implementations.
- </description>
- </method>
- <method name="get_blend_mode" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return blend mode for the material, which can be one of BLEND_MODE_MIX (default), BLEND_MODE_ADD, BLEND_MODE_SUB. Keep in mind that only BLEND_MODE_MIX ensures that the material [html i]may[html /i] be opaque, any other blend mode will render with alpha blending enabled in raster-based [VisualServer] implementations.
- </description>
- </method>
- <method name="set_shade_model" >
- <argument index="0" name="model" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shade_model" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_line_width" >
- <argument index="0" name="width" type="real">
- </argument>
- <description>
- Set the line width for geometry drawn with FLAG_WIREFRAME enabled, or LINE primitives. Note that not all hardware or VisualServer backends support this (like DirectX).
- </description>
- </method>
- <method name="get_line_width" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the line width for geometry drawn with FLAG_WIREFRAME enabled, or LINE primitives. Note that not all hardware or VisualServer backends support this (like DirectX).
- </description>
- </method>
- <method name="set_shader_param" >
- <argument index="0" name="param" type="String">
- </argument>
- <argument index="1" name="arg1" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shader_param" qualifiers="const" >
- <argument index="0" name="arg0" type="String">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="SHADE_MODEL_FRESNEL" value="2">
- </constant>
- <constant name="SHADE_MODEL_LAMBERT" value="0">
- </constant>
- <constant name="HINT_DECAL" value="0">
- </constant>
- <constant name="FLAG_WIREFRAME" value="5">
- Triangle geometry is drawn as lines if this flag is enabled.
- </constant>
- <constant name="SHADE_MODEL_TOON" value="3">
- </constant>
- <constant name="SHADE_MODEL_LAMBERT_WRAP" value="1">
- </constant>
- <constant name="HINT_NO_SHADOW" value="2">
- </constant>
- <constant name="FLAG_DOUBLE_SIDED" value="1">
- Both front facing and back facing triangles are rendered when this flag is enabled.
- </constant>
- <constant name="FLAG_BILLBOARD_TOGGLE" value="6">
- Geometry world transform is computed as billboard if this flag is enabled, often used for impostors.
- </constant>
- <constant name="FLAG_UNSHADED" value="3">
- Shading (lighting) is disabled when this flag is enabled.
- </constant>
- <constant name="BLEND_MODE_MIX" value="0">
- Use the regular alpha blending equation (source and dest colors are faded) (default).
- </constant>
- <constant name="SHADE_MODEL_CUSTOM_0" value="4">
- </constant>
- <constant name="SHADE_MODEL_CUSTOM_1" value="5">
- </constant>
- <constant name="FLAG_MAX" value="7">
- Maximum amount of flags
- </constant>
- <constant name="FLAG_VISIBLE" value="0">
- Geometry is visible when this flag is enabled (default).
- </constant>
- <constant name="SHADE_MODEL_CUSTOM_2" value="6">
- </constant>
- <constant name="HINT_MAX" value="4">
- </constant>
- <constant name="HINT_NO_DEPTH_DRAW" value="3">
- </constant>
- <constant name="BLEND_MODE_ADD" value="1">
- Use additive blending equation, often used for particle effects such as fire or light decals.
- </constant>
- <constant name="SHADE_MODEL_CUSTOM_3" value="7">
- </constant>
- <constant name="HINT_OPAQUE_PRE_PASS" value="1">
- </constant>
- <constant name="FLAG_ONTOP" value="4">
- </constant>
- <constant name="BLEND_MODE_SUB" value="2">
- Use substractive blending equation, often used for some smoke effects or types of glass.
- </constant>
- <constant name="FLAG_INVERT_FACES" value="2">
- Front facing and back facing order is swapped when this flag is enabled.
- </constant>
- </constants>
-</class>
-<class name="MenuButton" inherits="Button" category="Nodes/GUI Nodes">
- <brief_description>
- Special button that brings up a [PopupMenu] when clicked.
- </brief_description>
- <description>
- Special button that brings up a [PopupMenu] when clicked. That&apos;s pretty much all it does, as it&apos;s just a helper class when bulding GUIs.
- </description>
- <methods>
- <method name="get_popup" >
- <return type="Object">
- </return>
- <description>
- Return the [PopupMenu] contained in this button.
- </description>
- </method>
- </methods>
- <signals>
- <signal name="about_to_show">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="Mesh" inherits="Resource" category="Resources">
- <brief_description>
- A [Resource] that contains vertex-array based geometry.
- </brief_description>
- <description>
- Mesh is a type of [Resource] that contains vertex-array based geometry, divided in [html i]surfaces[html /i]. Each surface contains a completely separate array and a material used to draw it. Design wise, a mesh with multiple surfaces is prefered to a single surface, because objects created in 3D editing software commonly contain multiple materials.
- </description>
- <methods>
- <method name="add_morph_target" >
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_morph_target_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_morph_target" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="index" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_morph_targets" >
- <description>
- </description>
- </method>
- <method name="add_surface" >
- <argument index="0" name="primitive" type="int">
- </argument>
- <argument index="1" name="format" type="int">
- </argument>
- <argument index="2" name="array_len" type="int">
- </argument>
- <argument index="3" name="index_array_len" type="int">
- </argument>
- <description>
- Create a new surface ([method get_surface_count] will become surf_idx for this.[html br/]&#10;&#9;&#9;&#9;Surfaces are created to be rendered using a &quot;primitive&quot;, which may be PRIMITIVE_POINTS, PRIMITIVE_LINES, PRIMITIVE_LINE_STRIP, PRIMITIVE_LINE_LOOP, PRIMITIVE_TRIANGLES, PRIMITIVE_TRIANGLE_STRIP, PRIMITIVE_TRIANGLE_FAN. (As a note, when using indices, it is recommended to only use just points, lines or triangles).[html br/]&#10;&#9;&#9;&#9;The format of a surface determines which arrays it will allocate and hold, so &quot;format&quot; is a combination of ARRAY_FORMAT_* mask constants ORed together. ARRAY_FORMAT_VERTEX must be always present. &quot;array_len&quot; determines the amount of vertices in the array (not primitives!). if ARRAY_FORMAT_INDEX is in the format mask, then it means that an index array will be allocated and &quot;index_array_len&quot; must be passed.
- </description>
- </method>
- <method name="get_surface_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the amount of surfaces that the [Mesh] holds.
- </description>
- </method>
- <method name="surface_remove" >
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <description>
- Remove a surface at position surf_idx, shifting greater surfaces one surf_idx slot down.
- </description>
- </method>
- <method name="surface_set_array" >
- <return type="int">
- </return>
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <argument index="1" name="array" type="int">
- </argument>
- <argument index="2" name="data" type="var">
- </argument>
- <description>
- Set a surface array, array must be defined in the format (see [method add_surface]), and which array being set in &quot;data&quot; must be indicated passing a value from the ARRAY_* enum (NOT THE ARRAY_FORMAT_ enum!!). A Mesh can&apos;t be displayed (error will be reported) if an array that is present in the format was not set.
- </description>
- </method>
- <method name="surface_get_array" qualifiers="const" >
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <argument index="1" name="array" type="int">
- </argument>
- <description>
- Return a surface array, array must be defined in the format (see [method add_surface]), and which array being returned must be indicated passing a value from the ARRAY_* enum (NOT THE ARRAY_FORMAT_ enum!!) (see [method add_surface]).
- </description>
- </method>
- <method name="surface_get_array_len" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <description>
- Return the length in vertices of the vertex array in the requested surface (see [method add_surface]).
- </description>
- </method>
- <method name="surface_get_array_index_len" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <description>
- Return the length in indices of the index array in the requested surface (see [method add_surface]).
- </description>
- </method>
- <method name="surface_get_format" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <description>
- Return the format mask of the requested surface (see [method add_surface]).
- </description>
- </method>
- <method name="surface_get_primitive_type" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <description>
- Return the primitive type of the requested surface (see [method add_surface]).
- </description>
- </method>
- <method name="surface_set_material" >
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <argument index="1" name="arg1" type="Object">
- </argument>
- <description>
- Set a [Material] for a given surface. Surface will be rendered using this material.
- </description>
- </method>
- <method name="surface_get_material" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <description>
- Return a [Material] in a given surface. Surface is rendered using this material.
- </description>
- </method>
- </methods>
- <constants>
- <constant name="PRIMITIVE_LINES" value="1">
- Render array as lines (every two vertices a line is created).
- </constant>
- <constant name="ARRAY_FORMAT_TEX_UV2" value="32">
- </constant>
- <constant name="ARRAY_TEX_UV2" value="5">
- </constant>
- <constant name="ARRAY_WEIGHTS_SIZE" value="4">
- Amount of weights/bone indices per vertex (always 4).
- </constant>
- <constant name="ARRAY_FORMAT_VERTEX" value="1">
- Array format will include vertices (mandatory).
- </constant>
- <constant name="ARRAY_VERTEX" value="0">
- Vertex array (array of [Vector3]() vertices).
- </constant>
- <constant name="PRIMITIVE_POINTS" value="0">
- Render array as points (one vertex equals one point).
- </constant>
- <constant name="ARRAY_FORMAT_BONES" value="64">
- Array format will include bone indices.
- </constant>
- <constant name="ARRAY_FORMAT_COLOR" value="8">
- Array format will include a color array.
- </constant>
- <constant name="ARRAY_BONES" value="6">
- Array of bone indices, as a float array. Each element in groups of 4 floats.
- </constant>
- <constant name="ARRAY_COLOR" value="3">
- Vertex array (array of [Color]() colors).
- </constant>
- <constant name="ARRAY_FORMAT_INDEX" value="256">
- Index array will be used.
- </constant>
- <constant name="ARRAY_INDEX" value="8">
- Array of integers, used as indices referencing vertices. No index can be beyond the vertex array size.
- </constant>
- <constant name="PRIMITIVE_TRIANGLE_STRIP" value="5">
- Render array as triangle strips.
- </constant>
- <constant name="ARRAY_FORMAT_TANGENT" value="4">
- Array format will include tangents
- </constant>
- <constant name="ARRAY_FORMAT_NORMAL" value="2">
- Array format will include normals
- </constant>
- <constant name="ARRAY_TANGENT" value="2">
- Tangent array, array of groups of 4 floats. first 3 floats determine the tangent, and the last the binormal direction as -1 or 1.
- </constant>
- <constant name="ARRAY_NORMAL" value="1">
- Normal array (array of [Vector3]() normals).
- </constant>
- <constant name="PRIMITIVE_TRIANGLES" value="4">
- Render array as triangles (every three vertices a triangle is created).
- </constant>
- <constant name="PRIMITIVE_LINE_LOOP" value="3">
- Render array as line loop (like line strip, but closed).
- </constant>
- <constant name="PRIMITIVE_LINE_STRIP" value="2">
- Render array as line strip.
- </constant>
- <constant name="ARRAY_FORMAT_WEIGHTS" value="128">
- Array format will include bone weights.
- </constant>
- <constant name="ARRAY_FORMAT_TEX_UV" value="16">
- Array format will include UVs.
- </constant>
- <constant name="ARRAY_WEIGHTS" value="7">
- Array of bone weights, as a float array. Each element in groups of 4 floats.
- </constant>
- <constant name="ARRAY_TEX_UV" value="4">
- UV array (array of [Vector3]() UVs or float array of groups of 2 floats (u,v)).
- </constant>
- <constant name="PRIMITIVE_TRIANGLE_FAN" value="6">
- Render array as triangle fans.
- </constant>
- <constant name="NO_INDEX_ARRAY" value="-1">
- Default value used for index_array_len when no indices are present.
- </constant>
- </constants>
-</class>
-<class name="MeshInstance" inherits="VisualInstance" category="Nodes/3D/3D Visual Nodes">
- <brief_description>
- Node that instances meshes into a [Scenario].
- </brief_description>
- <description>
- MeshInstance is a [Node] that takes a [Mesh] resource and adds it to the current [Scenario] by creating an instance of it. This is the class most often used to get 3D geometry rendered and can be used to instance a sigle [Mesh] in many places. This allows to reuse geometry and save on resources. When a [Mesh] has to be instanced more than thousands of times at close proximity, consider using a [MultiMesh] in a [MultiMeshInstance] instead.
- </description>
- <methods>
- <method name="set_mesh" >
- <argument index="0" name="mesh" type="Object">
- </argument>
- <description>
- Set the [Mesh] resource for the instance.
- </description>
- </method>
- <method name="get_mesh" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- Return the current [Mesh] resource for the instance.
- </description>
- </method>
- <method name="get_aabb" qualifiers="const" >
- <return type="AABB">
- </return>
- <description>
- Return the AABB of the mesh, in local coordinates.
- </description>
- </method>
- <method name="create_trimesh_collision" >
- <description>
- This helper creates a [StaticBody] child [Node] using the mesh geometry as collision. It&apos;s mainly used for testing.
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Misc" inherits="Node" category="Core">
- <brief_description>
- Soon to be removed, bye bye.
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="MultiMesh" inherits="Resource" category="Resources">
- <brief_description>
- Provides high perfomance mesh instancing.
- </brief_description>
- <description>
- MultiMesh provides low level mesh instancing. If the amount of [Mesh] instances needed goes from hundreds to thousands (and most need to be visible at close proximity) creating such a large amount of [MeshInstance] nodes may affect performance by using too much CPU or video memory. [html br/]For this case a MultiMesh becomes very useful, as it can draw thousands of instances with little API overhead.[html br/] As a drawback, if the instances are too far away of each other, performance may be reduced as every sigle instance will always rendered (they are spatially indexed as one, for the whole object).[html br/] Since instances may have any behavior, the AABB used for visibility must be provided by the user, or generated with [method generate_aabb].
- </description>
- <methods>
- <method name="set_mesh" >
- <argument index="0" name="arg0" type="Object">
- </argument>
- <description>
- Set the [Mesh] resource to be drawn in multiple instances.
- </description>
- </method>
- <method name="get_mesh" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- Return the [Mesh] resource drawn as multiple instances.
- </description>
- </method>
- <method name="set_instance_count" >
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- Set the amount of instnces that is going to be drawn. Changing this number will erase all the existing instance transform and color data.
- </description>
- </method>
- <method name="get_instance_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the amount of instnces that is going to be drawn.
- </description>
- </method>
- <method name="set_instance_transform" >
- <argument index="0" name="arg0" type="int">
- </argument>
- <argument index="1" name="arg1" type="Transform">
- </argument>
- <description>
- Set the transform for a specific instance.
- </description>
- </method>
- <method name="get_instance_transform" qualifiers="const" >
- <return type="Transform">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- Return the transform of a specific instance.
- </description>
- </method>
- <method name="set_instance_color" >
- <argument index="0" name="arg0" type="int">
- </argument>
- <argument index="1" name="arg1" type="Color">
- </argument>
- <description>
- Set the color of a specific instance.
- </description>
- </method>
- <method name="get_instance_color" qualifiers="const" >
- <return type="Color">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- Get the color of a specific instance.
- </description>
- </method>
- <method name="set_aabb" >
- <argument index="0" name="arg0" type="AABB">
- </argument>
- <description>
- Set the visibility AABB. If not provided, MultiMesh will not be visible.
- </description>
- </method>
- <method name="get_aabb" qualifiers="const" >
- <return type="AABB">
- </return>
- <description>
- Return the visibility AABB.
- </description>
- </method>
- <method name="generate_aabb" >
- <description>
- Generate a new visibility AABB, using mesh AABB and instance transforms. Since instance information is stored in the [VisualServer], this function is VERY SLOW and must NOT be used often.
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="MultiMeshInstance" inherits="VisualInstance" category="Nodes/3D/3D Visual Nodes">
- <brief_description>
- Node that instances a [MultiMesh].
- </brief_description>
- <description>
- MultiMeshInstance is a [Node] that takes a [MultiMesh] resource and adds it to the current [Scenario] by creating an instance of it (yes, this is an instance of instances).
- </description>
- <methods>
- <method name="set_multimesh" >
- <argument index="0" name="multimesh" type="Object">
- </argument>
- <description>
- Set the [MultiMesh] to be instance.
- </description>
- </method>
- <method name="get_multimesh" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- Return the [MultiMesh] that is used for instancing.
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Node" inherits="Object" category="Nodes">
- <brief_description>
- Base class for all the &quot;Scene&quot; elements.
- </brief_description>
- <description>
- Nodes can be set as children of other nodes, resulting in a tree arrangement. Any tree of nodes is called a &quot;Scene&quot;.[html br/] Scenes can be saved to disk, and then instanced into other scenes. This allows for very high flexibility in the architecture and data model of the projects. Scenes become &quot;active&quot; and part of the &quot;Scene Tree&quot; once they are added as children of a [RootNode].[html br/][html br/]&#10;&#9;As an illustrative example, a Scene (tree of nodes):&#10;&#9;[html div align=&quot;center&quot;][html img src=&quot;images/scene.png&quot;/][html /div]&#10;&#9;This scene will was edited separatedly, then is added as part of a game (by instancing it), becoming part of a &quot;Scene Tree&quot;:&#10;&#9;[html div align=&quot;center&quot;][html img src=&quot;images/scene_tree.png&quot;/][html /div]&#10;&#9;In short, nodes are an effective all-in-one way to create and organize assets, gameplay and game data.&#10;&#9;When a Node is freed (deleted), it will delete all its children&#10;&#9;nodes.&#10;&#9;TODO: explain better process/signal/group call ordering
- </description>
- <methods>
- <method name="set_name" >
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- Set the name of the [Node]. Name must be unique within parent, and setting an already existing name will cause for the node to be automatically renamed.
- </description>
- </method>
- <method name="get_name" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- Return the name of the [Node]. Name is be unique within parent.
- </description>
- </method>
- <method name="add_child" >
- <argument index="0" name="node" type="Node">
- </argument>
- <description>
- Add a child [Node]. Nodes can have as many children as they want, but every child must have a unique name. Children nodes are automatically deleted when the parent node is deleted, so deleting a whole scene is performed by deleting its topmost node.
- </description>
- </method>
- <method name="remove_child" >
- <argument index="0" name="node" type="Node">
- </argument>
- <description>
- Remove a child [Node]. Node is NOT deleted and will have to be deleted manually.
- </description>
- </method>
- <method name="get_child_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the amount of children nodes.
- </description>
- </method>
- <method name="get_child" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Return a children node by it&apos;s index (see [method get_child_count]). This method is often used for iterating all children of a node.
- </description>
- </method>
- <method name="has_node" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="path" type="NodePath">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_node" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="path" type="NodePath">
- </argument>
- <description>
- Fetch a node. &quot;path&quot; must be valid (or else error will occur) and can be either the name of a child node, a relative path (from the current node to another node), or an absolute path to a node.[html br/] Examples ofa paths are: get_node(&quot;Sword&quot;) , get_node(&quot;../Swamp/Alligator&quot;) , get_node(&quot;/MyGame&quot;). [html br/]Note: fetching absolute paths only works when the node is inside the scene tree (see [method is_inside_tree]).
- </description>
- </method>
- <method name="get_parent" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- Return the parent [Node] of the current [Node], or an empty Object if the node lacks a parent.
- </description>
- </method>
- <method name="is_inside_scene" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="is_a_parent_of" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="node" type="Node">
- </argument>
- <description>
- Return [html i]true[html /i] if the &quot;node&quot; argument is a direct or indirect child of the current node, otherwise return [html i]false[html /i].
- </description>
- </method>
- <method name="is_greater_than" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="node" type="Node">
- </argument>
- <description>
- Return [html i]true[html /i] if &quot;node&quot; occurs later in the scene hierarchy than the current node, otherwise return [html i]false[html /i].
- </description>
- </method>
- <method name="get_path" qualifiers="const" >
- <return type="NodePath">
- </return>
- <description>
- Return the absolute path of the current node. This only works if the curent node is inside the scene tree (see [method is_inside_tree]).
- </description>
- </method>
- <method name="get_path_to" qualifiers="const" >
- <return type="NodePath">
- </return>
- <argument index="0" name="node" type="Node">
- </argument>
- <description>
- Return the relative path from the current node to the specified node in &quot;node&quot; argument. Both nodes must be in the same scene, or else the function will fail.
- </description>
- </method>
- <method name="add_to_group" >
- <argument index="0" name="group" type="String">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- Add a node to a group. Groups are helpers to name and organize group of nodes, like for example: &quot;Enemies&quot; &quot;Collectables&quot;, etc. A [Node] can be in any number of groups. Nodes can be assigned a group at any time, but will not be added to it until they are inside the scene tree (see [method is_inside_tree]).
- </description>
- </method>
- <method name="remove_from_group" >
- <argument index="0" name="group" type="String">
- </argument>
- <description>
- Remove a node from a group.
- </description>
- </method>
- <method name="move_child" >
- <argument index="0" name="child_node" type="Node">
- </argument>
- <argument index="1" name="to_pos" type="int">
- </argument>
- <description>
- Move a child node to a different position (order) amongst the other children. Since calls, signals, etc are performed by tree order, changing the order of chilren nodes may be useful.
- </description>
- </method>
- <method name="raise" >
- <description>
- Move this node to the top of the array of nodes of the parent node. This is often useful on GUIs ([Control]), because their order of drawing fully depends on their order in the tree.
- </description>
- </method>
- <method name="set_owner" >
- <argument index="0" name="arg0" type="Object">
- </argument>
- <description>
- Set the node owner. A node can have any other node as owner (as long as a valid parent, grandparent, etc ascending in the tree). When saving a node (using SceneSaver) all the nodes it owns will be saved with it. This allows to create complex SceneTrees, with instancing and subinstancing.
- </description>
- </method>
- <method name="get_owner" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- Get the node owner (see [method set_node_owner]).
- </description>
- </method>
- <method name="remove_and_skip" >
- <description>
- Remove a node and set all its children as childrens of the parent node (if exists). All even subscriptions that pass by the removed node will be unsubscribed.
- </description>
- </method>
- <method name="get_index" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Get the node index in the parent (assuming it has a parent).
- </description>
- </method>
- <method name="print_tree" >
- <description>
- Print the screne to stdout. Used mainly for debugging purposes.
- </description>
- </method>
- <method name="set_filename" >
- <argument index="0" name="filename" type="String">
- </argument>
- <description>
- A node can contain a filename. This filename should not be changed by the user, unless writing editors and tools. When a scene is instanced from a file, it topmost node contains the filename from where it was loaded.
- </description>
- </method>
- <method name="get_filename" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- Return a filename that may be containedA node can contained by the node. When a scene is instanced from a file, it topmost node contains the filename from where it was loaded (see [method set_filename]).
- </description>
- </method>
- <method name="propagate_notification" >
- <argument index="0" name="what" type="int">
- </argument>
- <description>
- Notify the current node and all its chldren recursively by calling notification() in all of them.
- </description>
- </method>
- <method name="set_process" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- Enables or disables node processing. When a node is being processed, it will receive a NOTIFICATION_PROCESS on every frame. It is common to check how much time was elapsed since the previous frame by calling [method get_process_time]. If the application is set to run at 60 fps, NOTIFICATION_PROCESS will be received 60 times per second (even if the visuals are running at faster or lower fps). Because of this, nodes that wish to do processing are recommended to use [method set_idle_process] instead, unless strong syncronization is requiered (for example, to modify the behavior of physics objects).
- </description>
- </method>
- <method name="get_process_time" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the amount of time elapsed (in seconds) between two succesive NOTIFICATION_PROCESS notifications.
- </description>
- </method>
- <method name="is_processing" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return wether processing is enabled in the current node.
- </description>
- </method>
- <method name="set_idle_process" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- Enables or disables node idle processing. When a node is being idle-processed, it will receive a NOTIFICATION_IDLE_PROCESS when idle. It is common to check how much time was elapsed since the previous idle time by calling [method get_idle_process_time]. Idle processing is commonly syncronized to [VisualServer] being done rendering a frame, so this type of processing is syncronized to the visible frames per second. To syncronize with the desired frames per second, see [method set_process] instead.
- </description>
- </method>
- <method name="get_idle_process_time" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the amount of time elapsed (in seconds) between two succesive NOTIFICATION_IDLE_PROCESS notifications.
- </description>
- </method>
- <method name="is_idle_processing" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return wether idle processing is enabled in the current node.
- </description>
- </method>
- <method name="set_process_input" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_processing_input" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_process_unhandled_input" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_processing_unhandled_input" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_process_mode" >
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_process_mode" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_world" >
- <argument index="0" name="world" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_world" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_current_world" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_scene" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="duplicate" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="arg0" type="Object">
- </argument>
- <argument index="1" name="arg1" type="bool" default="NULL">
- </argument>
- <description>
- Return a duplicate of the scene, with all nodes and parameters copied. Subscriptions will not be duplicated.
- </description>
- </method>
- <method name="replace_by" >
- <argument index="0" name="node" type="Node">
- </argument>
- <argument index="1" name="keep_data" type="bool" default="false">
- </argument>
- <description>
- Replace a node in a scene by a given one. Subscriptions that pass through this node will be lost.
- </description>
- </method>
- </methods>
- <signals>
- <signal name="enter_scene">
- <description>
- </description>
- </signal>
- <signal name="renamed">
- <description>
- </description>
- </signal>
- <signal name="exit_scene">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="NOTIFICATION_ENTER_WORLD" value="20">
- </constant>
- <constant name="PROCESS_PAUSE" value="1">
- </constant>
- <constant name="NOTIFICATION_UNPARENTED" value="19">
- Notification received when a node is unparented (parent removed it from the list of children).
- </constant>
- <constant name="NOTIFICATION_CHILDREN_CONFIGURED" value="14">
- </constant>
- <constant name="NOTIFICATION_PROCESS" value="16">
- Notification received every frame when the process flag is set (see [method set_process]).
- </constant>
- <constant name="NOTIFICATION_EXIT_SCENE" value="11">
- </constant>
- <constant name="PROCESS_ALWAYS" value="2">
- </constant>
- <constant name="PROCESS_NORMAL" value="0">
- </constant>
- <constant name="NOTIFICATION_EXIT_WORLD" value="21">
- </constant>
- <constant name="NOTIFICATION_MOVED_IN_PARENT" value="12">
- </constant>
- <constant name="NOTIFICATION_PARENTED" value="18">
- Notification received when a node is set as a child of another node. Note that this doesn&apos;t mean that a node entered the Scene Tree.
- </constant>
- <constant name="NOTIFICATION_ENTER_SCENE" value="10">
- </constant>
- <constant name="NOTIFICATION_IDLE_PROCESS" value="17">
- Notification received every time the application enters idle when the idle process flag is set (see [method set_process]).
- </constant>
- </constants>
-</class>
-<class name="Node2D" inherits="CanvasItem" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_pos" >
- <argument index="0" name="pos" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_rot" >
- <argument index="0" name="rot" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_scale" >
- <argument index="0" name="scale" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_pos" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_rot" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_scale" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="NOTIFICATION_DRAW" value="30">
- </constant>
- </constants>
-</class>
-<class name="_OS" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_mouse_show" >
- <argument index="0" name="show" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_mouse_grab" >
- <argument index="0" name="grab" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_mouse_grab_enabled" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_mouse_pos" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_clipboard" >
- <argument index="0" name="clipboard" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_clipboard" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_video_mode" >
- <argument index="0" name="size" type="Vector2">
- </argument>
- <argument index="1" name="fullscreen" type="bool">
- </argument>
- <argument index="2" name="resizable" type="bool">
- </argument>
- <argument index="3" name="screen" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_video_mode_size" qualifiers="const" >
- <return type="Vector2">
- </return>
- <argument index="0" name="screen" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_video_mode_fullscreen" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="screen" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_video_mode_resizable" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="screen" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_fullscreen_mode_list" qualifiers="const" >
- <return type="Array">
- </return>
- <argument index="0" name="screen" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_iterations_per_second" >
- <argument index="0" name="iterations_per_second" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_iterations_per_second" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_low_processor_usage_mode" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_in_low_processor_usage_mode" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_executable_path" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="execute" >
- <return type="int">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <argument index="1" name="arguments" type="StringArray">
- </argument>
- <argument index="2" name="blocking" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="kill" >
- <return type="int">
- </return>
- <argument index="0" name="pid" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_environment" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="environment" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_environment" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="environment" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_name" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_cmdline_args" >
- <return type="StringArray">
- </return>
- <description>
- </description>
- </method>
- <method name="get_main_loop" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_date" qualifiers="const" >
- <return type="Dictionary">
- </return>
- <description>
- </description>
- </method>
- <method name="get_time" qualifiers="const" >
- <return type="Dictionary">
- </return>
- <description>
- </description>
- </method>
- <method name="delay_usec" qualifiers="const" >
- <argument index="0" name="usec" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_ticks_msec" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="can_draw" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_frames_drawn" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="is_stdout_verbose" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="MONTH_NOVEMBER" value="10">
- </constant>
- <constant name="MONTH_OCTOBER" value="9">
- </constant>
- <constant name="MONTH_DECEMBER" value="11">
- </constant>
- <constant name="MONTH_SEPTEMBER" value="8">
- </constant>
- <constant name="MONTH_MAY" value="4">
- </constant>
- <constant name="DAY_FRIDAY" value="5">
- </constant>
- <constant name="DAY_TUESDAY" value="2">
- </constant>
- <constant name="MONTH_APRIL" value="3">
- </constant>
- <constant name="MONTH_FEBRUARY" value="1">
- </constant>
- <constant name="DAY_MONDAY" value="1">
- </constant>
- <constant name="MONTH_AUGUST" value="7">
- </constant>
- <constant name="MONTH_JUNE" value="5">
- </constant>
- <constant name="MONTH_JANUARY" value="0">
- </constant>
- <constant name="MONTH_MARCH" value="2">
- </constant>
- <constant name="MONTH_JULY" value="6">
- </constant>
- <constant name="DAY_THURSDAY" value="4">
- </constant>
- <constant name="DAY_WEDNESDAY" value="3">
- </constant>
- <constant name="DAY_SUNDAY" value="0">
- </constant>
- <constant name="DAY_SATURDAY" value="6">
- </constant>
- </constants>
-</class>
-<class name="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_type" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="is_type" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set" >
- <argument index="0" name="property" type="String">
- </argument>
- <argument index="1" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="get" qualifiers="const" >
- <argument index="0" name="property" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_property_list" qualifiers="const" >
- <return type="Array">
- </return>
- <description>
- </description>
- </method>
- <method name="notification" >
- <argument index="0" name="what" type="int">
- </argument>
- <argument index="1" name="arg1" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_instance_ID" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_script" >
- <argument index="0" name="script" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_script" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_meta" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_meta" qualifiers="const" >
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_meta" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_meta_list" qualifiers="const" >
- <return type="StringArray">
- </return>
- <description>
- </description>
- </method>
- <method name="call" >
- <argument index="0" name="method" type="String">
- </argument>
- <argument index="1" name="arg1" type="var" default="NULL">
- </argument>
- <argument index="2" name="arg2" type="var" default="NULL">
- </argument>
- <argument index="3" name="arg3" type="var" default="NULL">
- </argument>
- <argument index="4" name="arg4" type="var" default="NULL">
- </argument>
- <description>
- </description>
- </method>
- <method name="call_deferred" >
- <argument index="0" name="method" type="String">
- </argument>
- <argument index="1" name="arg1" type="var" default="NULL">
- </argument>
- <argument index="2" name="arg2" type="var" default="NULL">
- </argument>
- <argument index="3" name="arg3" type="var" default="NULL">
- </argument>
- <argument index="4" name="arg4" type="var" default="NULL">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_user_signal" >
- <argument index="0" name="signal" type="String">
- </argument>
- <argument index="1" name="arguments" type="Array" default="Array()">
- </argument>
- <description>
- </description>
- </method>
- <method name="emit_signal" >
- <argument index="0" name="signal" type="String">
- </argument>
- <argument index="1" name="arguments" type="Array" default="Array()">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_signal_list" qualifiers="const" >
- <return type="Array">
- </return>
- <description>
- </description>
- </method>
- <method name="connect" >
- <argument index="0" name="signal" type="String">
- </argument>
- <argument index="1" name="target" type="Object">
- </argument>
- <argument index="2" name="method" type="String">
- </argument>
- <argument index="3" name="binds" type="Array" default="Array()">
- </argument>
- <argument index="4" name="flags" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="disconnect" >
- <argument index="0" name="signal" type="String">
- </argument>
- <argument index="1" name="target" type="Object">
- </argument>
- <argument index="2" name="method" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_block_signals" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_blocking_signals" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="NOTIFICATION_POSTINITIALIZE" value="0">
- </constant>
- <constant name="NOTIFICATION_PREDELETE" value="1">
- </constant>
- </constants>
-</class>
-<class name="OmniLight" inherits="Light" category="Nodes/3D/3D Visual Nodes/3D Light Nodes">
- <brief_description>
- OmniDirectional Light, such as a lightbulb or a candle.
- </brief_description>
- <description>
- An OmniDirectional light is a type of [Light] node that emits lights in all directions. The light is attenuated through the distance and this attenuation can be configured by changing the energy, radius and attenuation parameters of [Light]. TODO: Image of an omnilight.
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="OptionButton" inherits="Button" category="Nodes/GUI Nodes">
- <brief_description>
- Button control that provides selectable options when pressed.
- </brief_description>
- <description>
- OptionButton is a type button that provides a selectable list of items when pressed. The item selected becomes the &quot;current&quot; item and is displayed as the button text.
- </description>
- <methods>
- <method name="add_item" >
- <argument index="0" name="label" type="String">
- </argument>
- <argument index="1" name="id" type="int" default="-1">
- </argument>
- <description>
- Add an item, with text &quot;label&quot; and (optionally) id. If no &quot;id&quot; is passed, &quot;id&quot; becomes the item index. New items are appended at the end.
- </description>
- </method>
- <method name="add_icon_item" >
- <argument index="0" name="texture" type="Object">
- </argument>
- <argument index="1" name="label" type="String">
- </argument>
- <argument index="2" name="id" type="int">
- </argument>
- <description>
- Add an item, with a &quot;texture&quot; icon, text &quot;label&quot; and (optionally) id. If no &quot;id&quot; is passed, &quot;id&quot; becomes the item index. New items are appended at the end.
- </description>
- </method>
- <method name="set_item_text" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="text" type="String">
- </argument>
- <description>
- Set the text of an item at index &quot;idx&quot;.
- </description>
- </method>
- <method name="set_item_icon" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="texture" type="Object">
- </argument>
- <description>
- Set the icon of an item at index &quot;idx&quot;.
- </description>
- </method>
- <method name="set_item_disabled" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="disabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_ID" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="id" type="int">
- </argument>
- <description>
- Set the ID of an item at index &quot;idx&quot;.
- </description>
- </method>
- <method name="set_item_metadata" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="metadata" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_text" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Return the text of the item at index &quot;idx&quot;.
- </description>
- </method>
- <method name="get_item_icon" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Return the icon of the item at index &quot;idx&quot;.
- </description>
- </method>
- <method name="get_item_ID" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Return the ID of the item at index &quot;idx&quot;.
- </description>
- </method>
- <method name="get_item_metadata" qualifiers="const" >
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_item_disabled" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the amount of items in the OptionButton.
- </description>
- </method>
- <method name="add_separator" >
- <description>
- Add a separator to the list of items. Separators help to group items. Separator also takes up an index and is appended at the end.
- </description>
- </method>
- <method name="clear" >
- <description>
- Clear all the items in the [OptionButton].
- </description>
- </method>
- <method name="select" >
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- Select an item by index and make it the current item.
- </description>
- </method>
- <method name="get_selected" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the current item index
- </description>
- </method>
- <method name="get_selected_ID" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selected_metadata" qualifiers="const" >
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="item_selected">
- <argument index="0" name="ID" type="int">
- </argument>
- <description>
- This signal is emitted when the current item was changed by the user. ID of the item selected is passed as argument (if no IDs were added, ID will be just the item index).
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="PacketPeer" inherits="Object" category="Core">
- <brief_description>
- Abstraction and base class for packet-based protocols.
- </brief_description>
- <description>
- PacketPeer is an abstration and base class for packet-based protocols (such as UDP). It provides an API for sending and receiving packets both as raw data or variables. This makes it easy to transfer data over a protocol, without having to encode data as low level bytes or having to worry about network ordering.
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PacketPeerStream" inherits="PacketPeer" category="Core">
- <brief_description>
- Wrapper to use a PacketPeer over a StreamPeer.
- </brief_description>
- <description>
- PacketStreamPeer provides a wrapper for working using packets over a stream. This allows for using packet based code with StreamPeers. PacketPeerStream implements a custom protocol over the StreamPeer, so the user should not read or write to the wrapped StreamPeer directly.
- </description>
- <methods>
- <method name="set_stream_peer" >
- <argument index="0" name="peer" type="Object">
- </argument>
- <description>
- Set the StreamPeer object to be wrapped
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Panel" inherits="Control" category="Nodes/GUI Nodes">
- <brief_description>
- Provides an opaque background for [Control] children.
- </brief_description>
- <description>
- Panel is a [Control] that displays an opaque background. It&apos;s commoly used as a parent and container for other types of [Control] nodes.&#10;&#9;[html div align=&quot;center&quot;][html img src=&quot;images/panel_example.png&quot;/][html /div]
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Particles" inherits="VisualInstance" category="Nodes/3D/3D Visual Nodes">
- <brief_description>
- Particle system 3D Node
- </brief_description>
- <description>
- Particles is a particle system 3D [Node] that is used to simulate several types of particle effects, such as explosions, rain, snow, fireflies, or other magical-like shinny sparkles. Particles are drawn using impostors, and given their dynamic behavior, the user must provide a visibility AABB (although helpers to create one automatically exist).
- </description>
- <methods>
- <method name="set_amount" >
- <argument index="0" name="amount" type="int">
- </argument>
- <description>
- Set total amount of particles in the system.
- </description>
- </method>
- <method name="get_amount" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the total amount of particles in the system.
- </description>
- </method>
- <method name="set_emitting" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- Set the &quot;emitting&quot; property state. When emitting, the particle system generates new particles at constant rate.
- </description>
- </method>
- <method name="is_emitting" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return the &quot;emitting&quot; property state (see [method set_emitting]).
- </description>
- </method>
- <method name="set_visibility_aabb" >
- <argument index="0" name="aabb" type="AABB">
- </argument>
- <description>
- Set the visibility AABB for the particle system, since the default one will not work properly most of the time.
- </description>
- </method>
- <method name="get_visibility_aabb" qualifiers="const" >
- <return type="AABB">
- </return>
- <description>
- Return the current visibility AABB.
- </description>
- </method>
- <method name="set_emission_half_extents" >
- <argument index="0" name="half_extents" type="Vector3">
- </argument>
- <description>
- Set the half extents for the emission box.
- </description>
- </method>
- <method name="get_emission_half_extents" qualifiers="const" >
- <return type="Vector3">
- </return>
- <description>
- Return the half extents for the emission box.
- </description>
- </method>
- <method name="set_emission_points" >
- <argument index="0" name="points" type="Vector3Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_emission_points" qualifiers="const" >
- <return type="Vector3Array">
- </return>
- <description>
- </description>
- </method>
- <method name="set_gravity_normal" >
- <argument index="0" name="normal" type="Vector3">
- </argument>
- <description>
- Set the normal vector towards where gravity is pulling (by default, negative Y).
- </description>
- </method>
- <method name="get_gravity_normal" qualifiers="const" >
- <return type="Vector3">
- </return>
- <description>
- Return the normal vector towards where gravity is pulling (by default, negative Y).
- </description>
- </method>
- <method name="set_variable" >
- <argument index="0" name="variable" type="int">
- </argument>
- <argument index="1" name="value" type="real">
- </argument>
- <description>
- Set a specific variable for the particle system (see VAR_* enum).
- </description>
- </method>
- <method name="get_variable" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="variable" type="int">
- </argument>
- <description>
- Return a specific variable for the particle system (see VAR_* enum).
- </description>
- </method>
- <method name="set_randomness" >
- <argument index="0" name="variable" type="int">
- </argument>
- <argument index="1" name="randomness" type="real">
- </argument>
- <description>
- Set the randomness for a specific variable of the particle system. Randomness produces small changes from the default each time a particle is emitted.
- </description>
- </method>
- <method name="get_randomness" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- Return the randomness for a specific variable of the particle system. Randomness produces small changes from the default each time a particle is emitted.
- </description>
- </method>
- <method name="set_color_phase_pos" >
- <argument index="0" name="phase" type="int">
- </argument>
- <argument index="1" name="pos" type="real">
- </argument>
- <description>
- Set the position of a color phase (0 to 1)
- </description>
- </method>
- <method name="get_color_phase_pos" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="phase" type="int">
- </argument>
- <description>
- Return the position of a color phase (0 to 1)
- </description>
- </method>
- <method name="set_color_phase_color" >
- <argument index="0" name="phase" type="int">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <description>
- Set the color of a color phase.
- </description>
- </method>
- <method name="get_color_phase_color" qualifiers="const" >
- <return type="Color">
- </return>
- <argument index="0" name="phase" type="int">
- </argument>
- <description>
- Return the color of a color phase.
- </description>
- </method>
- <method name="set_material" >
- <argument index="0" name="material" type="Object">
- </argument>
- <description>
- Set the material used to draw particles
- </description>
- </method>
- <method name="get_material" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- Return the material used to draw particles
- </description>
- </method>
- <method name="set_emit_timeout" >
- <argument index="0" name="arg0" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_emit_timeout" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_height_from_velocity" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_height_from_velocity" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_color_phases" >
- <argument index="0" name="count" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color_phases" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="VAR_FINAL_SIZE" value="9">
- </constant>
- <constant name="VAR_INITIAL_SIZE" value="8">
- </constant>
- <constant name="VAR_LINEAR_ACCELERATION" value="5">
- </constant>
- <constant name="VAR_MAX" value="13">
- </constant>
- <constant name="VAR_DRAG" value="6">
- </constant>
- <constant name="VAR_GRAVITY" value="2">
- </constant>
- <constant name="VAR_SPREAD" value="1">
- </constant>
- <constant name="VAR_LIFETIME" value="0">
- </constant>
- <constant name="VAR_HEIGHT_SPEED_SCALE" value="12">
- </constant>
- <constant name="VAR_INITIAL_ANGLE" value="10">
- </constant>
- <constant name="VAR_TANGENTIAL_ACCELERATION" value="7">
- </constant>
- <constant name="VAR_ANGULAR_VELOCITY" value="4">
- </constant>
- <constant name="VAR_HEIGHT" value="11">
- </constant>
- <constant name="VAR_LINEAR_VELOCITY" value="3">
- </constant>
- </constants>
-</class>
-<class name="Particles2D" inherits="Node2D" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_emitting" >
- <argument index="0" name="active" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_emitting" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_amount" >
- <argument index="0" name="amount" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_amount" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_lifetime" >
- <argument index="0" name="lifetime" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_lifetime" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_param" >
- <argument index="0" name="param" type="int">
- </argument>
- <argument index="1" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_param" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_randomness" >
- <argument index="0" name="param" type="int">
- </argument>
- <argument index="1" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_randomness" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_texture" >
- <argument index="0" name="texture" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_texture" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_emissor_offset" >
- <argument index="0" name="offset" type="Vector2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_emissor_offset" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="set_initial_color" >
- <argument index="0" name="initial_color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_initial_color" qualifiers="const" >
- <return type="Color">
- </return>
- <description>
- </description>
- </method>
- <method name="set_final_color" >
- <argument index="0" name="final_color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_final_color" qualifiers="const" >
- <return type="Color">
- </return>
- <description>
- </description>
- </method>
- <method name="set_use_parent_space" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_using_parent_space" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="PARAM_FINAL_SIZE" value="9">
- </constant>
- <constant name="PARAM_INITIAL_SIZE" value="8">
- </constant>
- <constant name="PARAM_RADIAL_ACCEL" value="6">
- </constant>
- <constant name="PARAM_GRAVITY_STRENGTH" value="5">
- </constant>
- <constant name="PARAM_MAX" value="11">
- </constant>
- <constant name="PARAM_HUE_VARIATION" value="10">
- </constant>
- <constant name="PARAM_TANGENTIAL_ACCEL" value="7">
- </constant>
- <constant name="PARAM_GRAVITY_DIRECTION" value="4">
- </constant>
- <constant name="PARAM_SPREAD" value="1">
- </constant>
- <constant name="PARAM_SPIN_VELOCITY" value="3">
- </constant>
- <constant name="PARAM_LINEAR_VELOCITY" value="2">
- </constant>
- <constant name="PARAM_DIRECTION" value="0">
- </constant>
- </constants>
-</class>
-<class name="PhysicsBody" inherits="Spatial" category="Nodes/3D">
- <brief_description>
- Base class for differnt types of Physics bodies.
- </brief_description>
- <description>
- PhysicsBody is an abstract base class for implementing a physics body. All PhysicsBody types inherit from it.
- </description>
- <methods>
- <method name="add_shape" >
- <argument index="0" name="shape" type="Object">
- </argument>
- <argument index="1" name="transform" type="Transform" default="Transform()">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shape_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_shape" >
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <argument index="1" name="shape" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_shape_transform" >
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <argument index="1" name="transform" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shape" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shape_transform" qualifiers="const" >
- <return type="Transform">
- </return>
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_shape" >
- <argument index="0" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_shapes" >
- <description>
- </description>
- </method>
- <method name="get_body" qualifiers="const" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="set_max_contacts_reported" >
- <argument index="0" name="contacts" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_max_contacts_reported" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_contacts_reported_depth_treshold" >
- <argument index="0" name="depth" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contacts_reported_depth_treshold" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PhysicsDirectBodyState" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_total_gravity" qualifiers="const" >
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="get_total_density" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_inverse_mass" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_inverse_inertia_tensor" qualifiers="const" >
- <return type="Matrix3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_linear_velocity" >
- <argument index="0" name="velocity" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_linear_velocity" qualifiers="const" >
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_angular_velocity" >
- <argument index="0" name="velocity" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_angular_velocity" qualifiers="const" >
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="set_transform" >
- <argument index="0" name="transform" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_transform" qualifiers="const" >
- <return type="Transform">
- </return>
- <description>
- </description>
- </method>
- <method name="set_sleep_state" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_sleeping" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_contact_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_contact_local_pos" qualifiers="const" >
- <return type="Vector3">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_local_normal" qualifiers="const" >
- <return type="Vector3">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_local_shape" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider_pos" qualifiers="const" >
- <return type="Vector3">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider_id" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider_shape" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_contact_collider_velocity_at_pos" qualifiers="const" >
- <return type="Vector3">
- </return>
- <argument index="0" name="contact_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PhysicsDirectBodyStateSW" inherits="PhysicsDirectBodyState" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PhysicsServer" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="shape_create" >
- <return type="RID">
- </return>
- <argument index="0" name="shape_type" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="shape_set_data" >
- <argument index="0" name="shape" type="RID">
- </argument>
- <argument index="1" name="data" type="var">
- </argument>
- <argument index="2" name="margin" type="real" default="-1">
- </argument>
- <description>
- </description>
- </method>
- <method name="shape_get_type" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="shape" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="shape_get_data" qualifiers="const" >
- <argument index="0" name="shape" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="space_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="area_create" >
- <return type="RID">
- </return>
- <argument index="0" name="space" type="int">
- </argument>
- <argument index="1" name="arg1" type="bool" default="RID()">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_param" >
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <argument index="2" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_shape" >
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="shape" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_bounds" >
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="bounds" type="Dictionary">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_set_transform" >
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="transform" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_param" qualifiers="const" >
- <argument index="0" name="area" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_shape" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_bounds" qualifiers="const" >
- <return type="Dictionary">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="area_get_transform" qualifiers="const" >
- <return type="Transform">
- </return>
- <argument index="0" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_create" >
- <return type="RID">
- </return>
- <argument index="0" name="space" type="int">
- </argument>
- <argument index="1" name="arg1" type="bool" default="RID()">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_mode" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_mode" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_add_shape" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape" type="RID">
- </argument>
- <argument index="2" name="transform" type="Transform" default="Transform()">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_shape" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <argument index="2" name="shape" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_shape_transform" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <argument index="2" name="transform" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_shape_count" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_shape" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_shape_transform" qualifiers="const" >
- <return type="Transform">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="shape_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_attach_object_instance_ID" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="ID" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_object_instance_ID" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_user_flags" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="user_flags" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_user_flags" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_param" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <argument index="2" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_param" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_static_simulate_motion" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="motion" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_state" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="state" type="int">
- </argument>
- <argument index="2" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_state" qualifiers="const" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="state" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_applied_force" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="applied_force" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_applied_force" qualifiers="const" >
- <return type="Vector3">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_applied_torque" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="applied_torque" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_get_applied_torque" qualifiers="const" >
- <return type="Vector3">
- </return>
- <argument index="0" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_set_axis_velocity" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="axis_velocity" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_apply_impulse" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="pos" type="Vector3">
- </argument>
- <argument index="2" name="impulse" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_add_collision_exception" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="against_body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="body_remove_collision_exception" >
- <argument index="0" name="body" type="RID">
- </argument>
- <argument index="1" name="against_body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_create" >
- <return type="RID">
- </return>
- <argument index="0" name="receiver" type="Object">
- </argument>
- <argument index="1" name="callback" type="String">
- </argument>
- <argument index="2" name="userdata" type="var">
- </argument>
- <argument index="3" name="persist" type="bool" default="true">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_body_state" >
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_body_direct_state" >
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="body" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_area" >
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="area" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_intersection" >
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="space" type="RID">
- </argument>
- <argument index="2" name="exclude" type="Array" default="Array()">
- </argument>
- <argument index="3" name="usermask" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_intersection_ray" >
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="origin" type="Vector3">
- </argument>
- <argument index="2" name="dir" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_intersection_segment" >
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="from" type="Vector3">
- </argument>
- <argument index="2" name="to" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_intersection_shape" >
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="shape" type="RID">
- </argument>
- <argument index="2" name="arg2" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_intersection_bounds" >
- <argument index="0" name="query" type="RID">
- </argument>
- <argument index="1" name="bounds" type="Dictionary">
- </argument>
- <argument index="2" name="arg2" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_clear" >
- <argument index="0" name="query" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_get_type" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="query" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="query_get_target" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="query" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="free" >
- <argument index="0" name="rid" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_active" >
- <argument index="0" name="active" type="bool">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="QUERY_BODY_STATE" value="1">
- </constant>
- <constant name="BODY_PARAM_FRICTION" value="1">
- </constant>
- <constant name="AREA_PARAM_OVERRIDE_PARAMS" value="0">
- </constant>
- <constant name="SHAPE_CUSTOM" value="9">
- </constant>
- <constant name="QUERY_INTERSECTION" value="4">
- </constant>
- <constant name="BODY_STATE_SLEEPING" value="3">
- </constant>
- <constant name="QUERY_AREA_MONITOR" value="3">
- </constant>
- <constant name="QUERY_BODY_DIRECT_STATE" value="2">
- </constant>
- <constant name="QUERY_NONE" value="0">
- </constant>
- <constant name="CONE_TWIST_VAR_RELAXATION" value="4">
- </constant>
- <constant name="CONE_TWIST_VAR_BIAS" value="3">
- </constant>
- <constant name="CONE_TWIST_VAR_SWING_SPAN_LIMIT_1" value="0">
- </constant>
- <constant name="HINGE_VAR_MOTOR_ENABLED" value="5">
- </constant>
- <constant name="HINGE_VAR_LIMIT_SOFTNESS" value="3">
- </constant>
- <constant name="HINGE_VAR_ANGULAR_ONLY" value="0">
- </constant>
- <constant name="BODY_STATE_ANGULAR_VELOCITY" value="2">
- </constant>
- <constant name="SHAPE_CAPSULE" value="5">
- </constant>
- <constant name="CONE_TWIST_VAR_SWING_SPAN_LIMIT_2" value="1">
- </constant>
- <constant name="BODY_STATE_LINEAR_VELOCITY" value="1">
- </constant>
- <constant name="BODY_MODE_CHARACTER" value="2">
- </constant>
- <constant name="AREA_PARAM_GRAVITY" value="1">
- </constant>
- <constant name="SHAPE_CONCAVE_POLYGON" value="7">
- </constant>
- <constant name="TYPE_BODY" value="0">
- </constant>
- <constant name="HINGE_VAR_MOTOR_TARGET_VELOCITY" value="6">
- </constant>
- <constant name="HINGE_VAR_HIGHER_LIMIT" value="2">
- </constant>
- <constant name="SHAPE_HEIGHTMAP" value="8">
- </constant>
- <constant name="SHAPE_SPHERE" value="2">
- </constant>
- <constant name="CONE_TWIST_VAR_TWIST_SPAN_LIMIT" value="2">
- </constant>
- <constant name="BODY_MODE_RIGID" value="1">
- </constant>
- <constant name="AREA_PARAM_DENSITY" value="5">
- </constant>
- <constant name="AREA_PARAM_GRAVITY_VECTOR" value="2">
- </constant>
- <constant name="SHAPE_PLANE" value="0">
- </constant>
- <constant name="HINGE_VAR_MOTOR_IMPULSE" value="7">
- </constant>
- <constant name="HINGE_VAR_RELAXATION" value="4">
- </constant>
- <constant name="HINGE_VAR_LOWER_LIMIT" value="1">
- </constant>
- <constant name="BODY_STATE_TRANSFORM" value="0">
- </constant>
- <constant name="BODY_PARAM_MASS" value="2">
- </constant>
- <constant name="BODY_PARAM_BOUNCE" value="0">
- </constant>
- <constant name="BODY_MODE_STATIC" value="0">
- </constant>
- <constant name="SHAPE_BOX" value="3">
- </constant>
- <constant name="TYPE_AREA" value="1">
- </constant>
- <constant name="AREA_PARAM_PRIORITY" value="6">
- </constant>
- <constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="4">
- </constant>
- <constant name="AREA_PARAM_GRAVITY_IS_POINT" value="3">
- </constant>
- <constant name="SHAPE_CONVEX_POLYGON" value="6">
- </constant>
- <constant name="SHAPE_CYLINDER" value="4">
- </constant>
- </constants>
-</class>
-<class name="PhysicsServerSW" inherits="PhysicsServer" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PlaneShape" inherits="Shape" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_plane" >
- <argument index="0" name="plane" type="Plane">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_plane" qualifiers="const" >
- <return type="Plane">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Popup" inherits="Control" category="Core">
- <brief_description>
- Base container control for popups and dialogs.
- </brief_description>
- <description>
- PopUp is a base [Control] used to show dialogs and popups. It&apos;s a subwindow and modal by default (see [Control]) and has helpers for custom popup behavior.
- </description>
- <methods>
- <method name="popup_centered" >
- <argument index="0" name="size" type="Vector2" default="Vector2(0,0)">
- </argument>
- <description>
- Popup (show the control in modal form) in the center of the screen, at the curent size, or at a size determined by &quot;size&quot;.
- </description>
- </method>
- <method name="popup_centered_ratio" >
- <argument index="0" name="ratio" type="real" default="0.75">
- </argument>
- <description>
- Popup (show the control in modal form) in the center of the screen, scalled at a ratio of size of the screen.
- </description>
- </method>
- <method name="popup" >
- <description>
- Popup (show the control in modal form).
- </description>
- </method>
- <method name="set_exclusive" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_exclusive" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="about_to_show">
- <description>
- This signal is emitted when a popup is about to be shown. (often used in [PopupMenu] for clearing the list of options and creating a new one according to the current context).
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="PopupDialog" inherits="Popup" category="Nodes/GUI Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="PopupMenu" inherits="Popup" category="Nodes/GUI Nodes">
- <brief_description>
- PopupMenu displays a list of options.
- </brief_description>
- <description>
- PopupMenu is the typical Control that displays a list of options. They are popular in toolbars or context menus.
- </description>
- <methods>
- <method name="add_icon_item" >
- <argument index="0" name="texture" type="Object">
- </argument>
- <argument index="1" name="label" type="String">
- </argument>
- <argument index="2" name="id" type="int" default="-1">
- </argument>
- <argument index="3" name="accel" type="int" default="0">
- </argument>
- <description>
- Add a new item with text &quot;label&quot; and icon &quot;texture. An id can optonally be provided, as well as an accelerator. If no id is provided, one will be created from the index.
- </description>
- </method>
- <method name="add_item" >
- <argument index="0" name="label" type="String">
- </argument>
- <argument index="1" name="id" type="int" default="-1">
- </argument>
- <argument index="2" name="accel" type="int" default="0">
- </argument>
- <description>
- Add a new item with text &quot;label&quot;. An id can optonally be provided, as well as an accelerator. If no id is provided, one will be created from the index.
- </description>
- </method>
- <method name="add_icon_check_item" >
- <argument index="0" name="texture" type="Object">
- </argument>
- <argument index="1" name="label" type="String">
- </argument>
- <argument index="2" name="id" type="int" default="-1">
- </argument>
- <argument index="3" name="accel" type="int" default="0">
- </argument>
- <description>
- Add a new checkable item with text &quot;label&quot; and icon &quot;texture. An id can optonally be provided, as well as an accelerator. If no id is provided, one will be created from the index. Note that checkable items just display a checkmark, but don&apos;t have any built-in checking behavior and must be checked/unchecked manually.
- </description>
- </method>
- <method name="add_check_item" >
- <argument index="0" name="label" type="String">
- </argument>
- <argument index="1" name="id" type="int" default="-1">
- </argument>
- <argument index="2" name="accel" type="int" default="0">
- </argument>
- <description>
- Add a new checkable item with text &quot;label&quot;. An id can optonally be provided, as well as an accelerator. If no id is provided, one will be created from the index. Note that checkable items just display a checkmark, but don&apos;t have any built-in checking behavior and must be checked/unchecked manually.
- </description>
- </method>
- <method name="set_item_text" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="text" type="String">
- </argument>
- <description>
- Set the text of the item at index &quot;idx&quot;.
- </description>
- </method>
- <method name="set_item_icon" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="icon" type="Object">
- </argument>
- <description>
- Set the icon of the item at index &quot;idx&quot;.
- </description>
- </method>
- <method name="set_item_accelerator" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="accel" type="int">
- </argument>
- <description>
- Set the accelerator of the item at index &quot;idx&quot;. Accelerators are special combinations of keys that activate the item, no matter which control is fucused.
- </description>
- </method>
- <method name="set_item_metadata" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="metadata" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_checked" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- Set the checkstate status of the item at index &quot;idx&quot;.
- </description>
- </method>
- <method name="set_item_disabled" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_item_ID" >
- <argument index="0" name="idx" type="int">
- </argument>
- <argument index="1" name="id" type="int">
- </argument>
- <description>
- Set the id of the item at index &quot;idx&quot;.
- </description>
- </method>
- <method name="get_item_text" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Return the text of the item at index &quot;idx&quot;.
- </description>
- </method>
- <method name="get_item_icon" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Return the icon of the item at index &quot;idx&quot;.
- </description>
- </method>
- <method name="get_item_metadata" qualifiers="const" >
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_accelerator" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Return the accelerator of the item at index &quot;idx&quot;. Accelerators are special combinations of keys that activate the item, no matter which control is fucused.
- </description>
- </method>
- <method name="is_item_checked" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Return the checkstate status of the item at index &quot;idx&quot;.
- </description>
- </method>
- <method name="is_item_disabled" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_item_ID" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="idx" type="int">
- </argument>
- <description>
- Return the id of the item at index &quot;idx&quot;.
- </description>
- </method>
- <method name="get_item_index" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="id" type="int">
- </argument>
- <description>
- Find and return the index of the item containing a given id.
- </description>
- </method>
- <method name="get_item_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the amount of items.
- </description>
- </method>
- <method name="add_separator" >
- <description>
- Add a separator between items. Separators also occupy an index.
- </description>
- </method>
- <method name="clear" >
- <description>
- Clear the popup menu.
- </description>
- </method>
- </methods>
- <signals>
- <signal name="item_pressed">
- <argument index="0" name="ID" type="int">
- </argument>
- <description>
- This even is emitted when an item is pressed or its accelerator is activated. The id of the item is returned if it exists, else the index.
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="PopupPanel" inherits="Popup" category="Nodes/GUI Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Portal" inherits="VisualInstance" category="Nodes/3D/3D Visual Nodes">
- <brief_description>
- Portals provide virtual openings to rooms.
- </brief_description>
- <description>
- Portals provide virtual openings to [RoomInstance] nodes, so cameras can look at them from the outside. Note that portals are a visibility optimization technique, and are in no way related to the game of the same name (as in, they are not used for teleportation). For more information on how rooms and portals work, see [RoomInstance]. Portals are represented as 2D convex polygon shapes (in the X,Y local plane), and are placed on the surface of the areas occupied by a [RoomInstance], to indicate that the room can be accessed or looked-at through them. If two rooms are next to each other, and two similar portals in each of them share the same world position (and are parallel and opposed to each other), they will automatically &quot;connect&quot; and form &quot;doors&quot; (for example, the portals that connect a kitchen to a living room are placed in the door they share). Portals must always have a [RoomInstance] node as a parent, grandparent or far parent, or else they will not be active.
- </description>
- <methods>
- <method name="set_shape" >
- <argument index="0" name="points" type="Array">
- </argument>
- <description>
- Set the portal shape. The shape is an array of [Point2] points, representing a convex polygon in the X,Y plane.
- </description>
- </method>
- <method name="get_shape" qualifiers="const" >
- <return type="Array">
- </return>
- <description>
- Return the portal shape. The shape is an array of [Point2] points, representing a convex polygon in the X,Y plane.
- </description>
- </method>
- <method name="set_enabled" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- Enable the portal (it is enabled by defaul though), disabling it will cause the parent [RoomInstance] to not be visible any longer when looking through the portal.
- </description>
- </method>
- <method name="is_enabled" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return wether the portal is active. When disabled it causes the parent [RoomInstance] to not be visible any longer when looking through the portal.
- </description>
- </method>
- <method name="set_disable_distance" >
- <argument index="0" name="distance" type="real">
- </argument>
- <description>
- Set the distance threshold for disabling the portal. Every time that the portal goes beyond &quot;distance&quot;, it disables itself, becoming the opaque color (see [method set_disabled_color]).
- </description>
- </method>
- <method name="get_disable_distance" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the distance threshold for disabling the portal. Every time that the portal goes beyond &quot;distance&quot;, it disables itself, becoming the opaque color (see [method set_disabled_color]).
- </description>
- </method>
- <method name="set_disabled_color" >
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- When the portal goes beyond the disable distance (see [method set_disable_distance]), it becomes opaque and displayed with color &quot;color&quot;.
- </description>
- </method>
- <method name="get_disabled_color" qualifiers="const" >
- <return type="Color">
- </return>
- <description>
- Return the color for when the portal goes beyond the disable distance (see [method set_disable_distance]) and becomes disabled.
- </description>
- </method>
- <method name="set_connect_range" >
- <argument index="0" name="range" type="real">
- </argument>
- <description>
- Set the range for auto-connecting two portals from different rooms sharing the same space.
- </description>
- </method>
- <method name="get_connect_range" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the range for auto-connecting two portals from different rooms sharing the same space.
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Range" inherits="Control" category="Core">
- <brief_description>
- Abstract base class for range-based controls.
- </brief_description>
- <description>
- Range is a base class for [Control] nodes that change a floating point [html i]value[html /i] between a need a [html i]minimum[html /i], [html i]maximum[html /i], using [html i]step[html /i] and [html i]page[html /i], for example a [ScrollBar].
- </description>
- <methods>
- <method name="get_val" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the current value.
- </description>
- </method>
- <method name="get_min" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the minimum value.
- </description>
- </method>
- <method name="get_max" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the maximum value.
- </description>
- </method>
- <method name="get_step" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the stepping, if step is 0, stepping is disabled.
- </description>
- </method>
- <method name="get_page" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return the page size, if page is 0, paging is disabled.
- </description>
- </method>
- <method name="get_unit_value" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- Return value mapped to 0 to 1 (unit) range.
- </description>
- </method>
- <method name="set_val" >
- <argument index="0" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_min" >
- <argument index="0" name="minimum" type="real">
- </argument>
- <description>
- Set minimum value, clamped range value to it if it&apos;s less.
- </description>
- </method>
- <method name="set_max" >
- <argument index="0" name="maximum" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_step" >
- <argument index="0" name="step" type="real">
- </argument>
- <description>
- Set step value. If step is 0, stepping will be disabled.
- </description>
- </method>
- <method name="set_page" >
- <argument index="0" name="pagesize" type="real">
- </argument>
- <description>
- Set page size. Page is mainly used for scrollbars or anything that controls text scrolling.
- </description>
- </method>
- <method name="set_unit_value" >
- <argument index="0" name="value" type="real">
- </argument>
- <description>
- Set value mapped to 0 to 1 (unit) range, it will then be converted to the actual value within min and max.
- </description>
- </method>
- <method name="share" >
- <argument index="0" name="with" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="unshare" >
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="value_changed">
- <argument index="0" name="value" type="real">
- </argument>
- <description>
- This signal is emitted when value changes.
- </description>
- </signal>
- <signal name="changed">
- <description>
- This signal is emitted when min, max, range or step change.
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="RayShape" inherits="Shape" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_length" >
- <argument index="0" name="length" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_length" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Reference" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Resource" inherits="Reference" category="Resources">
- <brief_description>
- Base class for all resources.
- </brief_description>
- <description>
- Resource is the base class for all resource types. Resources are primarily data containers. They are reference counted and freed when no longer in use. They are also loaded only once from disk, and further attempts to load the resource will return the same reference (all this in contrast to a [Node], which is not reference counted and can be instanced from disk as many times as desred). Resources can be saved externally on disk or bundled into another object, such as a [Node] or another resource.
- </description>
- <methods>
- <method name="set_path" >
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- Set the path of the resource. This is useful mainly for editors when saving/loading, and shouldn&apos;t be changed by anything else.
- </description>
- </method>
- <method name="get_path" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- Return the path of the resource. This is useful mainly for editors when saving/loading, and shouldn&apos;t be changed by anything else.
- </description>
- </method>
- <method name="set_name" >
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- Set the name of the resources, any name is ok (it doesn&apos;t have to be unique). Name is for descriptive purposes only.
- </description>
- </method>
- <method name="get_name" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- Return the name of the resources, any name is ok (it doesn&apos;t have to be unique). Name is for descriptive purposes only.
- </description>
- </method>
- <method name="get_rid" qualifiers="const" >
- <return type="RID">
- </return>
- <description>
- Return the RID of the resource (or an empty RID). Many resources (such as [Texture], [Mesh], etc) are high level abstractions of resources stored in a server, so this function will return the original RID.
- </description>
- </method>
- </methods>
- <signals>
- <signal name="changed">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="_ResourceLoader" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="load" >
- <return type="Object">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <argument index="1" name="type_hint" type="String" default="&quot;&quot;">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_recognized_extensions_for_type" >
- <return type="StringArray">
- </return>
- <argument index="0" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="_ResourceSaver" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="save" >
- <return type="int">
- </return>
- <argument index="0" name="path" type="String">
- </argument>
- <argument index="1" name="resource" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_recognized_extensions" >
- <return type="StringArray">
- </return>
- <argument index="0" name="type" type="Object">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="RichTextLabel" inherits="Control" category="Nodes/GUI Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_text" >
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_image" >
- <argument index="0" name="image" type="Texture">
- </argument>
- <description>
- </description>
- </method>
- <method name="newline" >
- <description>
- </description>
- </method>
- <method name="push_font" >
- <argument index="0" name="font" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="push_color" >
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="push_align" >
- <argument index="0" name="align" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="push_indent" >
- <argument index="0" name="level" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="push_list" >
- <argument index="0" name="type" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="push_meta" >
- <argument index="0" name="data" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="push_underline" >
- <description>
- </description>
- </method>
- <method name="pop" >
- <description>
- </description>
- </method>
- <method name="clear" >
- <description>
- </description>
- </method>
- <method name="set_meta_underline" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_meta_underlined" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_scroll_active" >
- <argument index="0" name="active" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_scroll_active" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_scroll_follow" >
- <argument index="0" name="follow" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_scroll_following" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_tab_size" >
- <argument index="0" name="spaces" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_tab_size" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="meta_clicked">
- <argument index="0" name="meta" type="Nil">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="ITEM_TEXT" value="1">
- </constant>
- <constant name="ITEM_MAIN" value="0">
- </constant>
- <constant name="ALIGN_CENTER" value="1">
- </constant>
- <constant name="ITEM_UNDERLINE" value="6">
- </constant>
- <constant name="ITEM_META" value="10">
- </constant>
- <constant name="ITEM_COLOR" value="5">
- </constant>
- <constant name="ITEM_FONT" value="4">
- </constant>
- <constant name="LIST_DOTS" value="2">
- </constant>
- <constant name="ALIGN_LEFT" value="0">
- </constant>
- <constant name="LIST_LETTERS" value="1">
- </constant>
- <constant name="LIST_NUMBERS" value="0">
- </constant>
- <constant name="ITEM_INDENT" value="8">
- </constant>
- <constant name="ITEM_NEWLINE" value="3">
- </constant>
- <constant name="ALIGN_RIGHT" value="2">
- </constant>
- <constant name="ITEM_ALIGN" value="7">
- </constant>
- <constant name="ITEM_IMAGE" value="2">
- </constant>
- <constant name="ALIGN_FILL" value="3">
- </constant>
- <constant name="ITEM_LIST" value="9">
- </constant>
- </constants>
-</class>
-<class name="Room" inherits="Resource" category="Resources">
- <brief_description>
- Room data resource.
- </brief_description>
- <description>
- Room contains the data to define the bounds of a scene (using a BSP Tree). It is instanced by a [RoomInstance] node to create rooms. See that class documentation for more information about rooms.
- </description>
- <methods>
- <method name="set_bounds" >
- <argument index="0" name="bsp_tree" type="Dictionary">
- </argument>
- <description>
- Set the bounds of the room as a BSP tree. a BSP Tree is defined a Dictionary: (TODO - see source code on how to create a BSP tree from a dictionary).
- </description>
- </method>
- <method name="get_bounds" qualifiers="const" >
- <return type="Dictionary">
- </return>
- <description>
- Return the bounds of the room as a BSP tree. a BSP Tree is defined a Dictionary: (TODO - see source code on how to create a BSP tree from a dictionary).
- </description>
- </method>
- <method name="set_geometry_hint" >
- <argument index="0" name="triangles" type="Vector3Array">
- </argument>
- <description>
- Set the &quot;geometry&quot; hint of the room. This means, how the room actually looks (an array of [Vector3]s, forming triangles).
- </description>
- </method>
- <method name="get_geometry_hint" qualifiers="const" >
- <return type="Vector3Array">
- </return>
- <description>
- Return the &quot;geometry&quot; hint of the room. This means, how the room actually looks (an array of [Vector3]s, forming triangles).
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="RoomInstance" inherits="VisualInstance" category="Nodes/3D/3D Visual Nodes">
- <brief_description>
- Node that instances a Room.
- </brief_description>
- <description>
- RoomInstance is a [Node] that instances a [Room] resource and places it on the world. Rooms are used for defining the areas taken up by [html i]interiors[html /i]. An [html i]interior[html /i] is any closed space that has an entrance/exit (or not) to the outside world, for example the inside of a house, a room in a house, a cave.[html br/]So why is this used? Rooms and Portals ([Portal]) are a common visualization optimization technique, it is used to make interiors invisible (not rendered) when the camera is at the exterior (such as an open field), and also the exterior invisible when inside an interior (such as a house). It is also used to make interior rooms invisible from other interior rooms.&#10;[html div align=&quot;center&quot;][html img src=&quot;images/portals_example.png&quot;/][html /div]
- </description>
- <methods>
- <method name="set_room" >
- <argument index="0" name="room" type="Object">
- </argument>
- <description>
- Set the [Room] resource, containing the room bounds.
- </description>
- </method>
- <method name="get_room" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- Return the [Room] resource, containing the room bounds.
- </description>
- </method>
- <method name="compute_room_from_subtree" >
- <description>
- This helper function computes a [Room] from the shapes of all the children [VisualInstance] nodes, and sets it to the node.
- </description>
- </method>
- <method name="set_simulate_acoustics" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_simulating_acoustics" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SSAOFX" inherits="ScenarioFX" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Sample" inherits="Resource" category="Resources">
- <brief_description>
- Audio Sample (sound) class.
- </brief_description>
- <description>
- Sample provides an audio sample class, containing audio data, together with some information for playback, such as format, mix rate and loop. It is used by sound playback routines.
- </description>
- <methods>
- <method name="create" >
- <argument index="0" name="format" type="int">
- </argument>
- <argument index="1" name="stereo" type="bool">
- </argument>
- <argument index="2" name="length" type="int">
- </argument>
- <description>
- Create new data for the sample, with format &quot;format&quot; (see FORMAT_* enum), stereo hint, and length in frames (not samples or bytes!) &quot;frame&quot;. Calling create overrides previous existing data if it exists. Stereo samples are interleaved pairs of left and right (in that order) points
- </description>
- </method>
- <method name="get_format" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the sample format (see FORMAT_* enum).
- </description>
- </method>
- <method name="is_stereo" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return true if the sample was created stereo.
- </description>
- </method>
- <method name="get_length" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the sample length in frames.
- </description>
- </method>
- <method name="set_data" >
- <argument index="0" name="data" type="RawArray">
- </argument>
- <description>
- Set sample data. Data must be little endian, no matter the host platform, and exactly as long to fit all frames. Example, if data is Stereo, 16 bits, 256 frames, it will be 1024 bytes long.
- </description>
- </method>
- <method name="get_data" qualifiers="const" >
- <return type="RawArray">
- </return>
- <description>
- Return sample data. Data will be endian, no matter with the host platform, and exactly as long to fit all frames. Example, if data is Stereo, 16 bits, 256 frames, it will be 1024 bytes long.
- </description>
- </method>
- <method name="set_mix_rate" >
- <argument index="0" name="hz" type="int">
- </argument>
- <description>
- Set the mix rate for the sample (expected playback frequency).
- </description>
- </method>
- <method name="get_mix_rate" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the mix rate for the sample (expected playback frequency).
- </description>
- </method>
- <method name="set_loop_format" >
- <argument index="0" name="format" type="int">
- </argument>
- <description>
- Set the loop format, see LOOP_* enum
- </description>
- </method>
- <method name="get_loop_format" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the loop format, see LOOP_* enum.
- </description>
- </method>
- <method name="set_loop_begin" >
- <argument index="0" name="pos" type="int">
- </argument>
- <description>
- Set the loop begin position, it must be a valid frame and less than the loop end position.
- </description>
- </method>
- <method name="get_loop_begin" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the loop begin position.
- </description>
- </method>
- <method name="set_loop_end" >
- <argument index="0" name="pos" type="int">
- </argument>
- <description>
- Set the loop end position, it must be a valid frame and greater than the loop begin position.
- </description>
- </method>
- <method name="get_loop_end" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the loop begin position.
- </description>
- </method>
- </methods>
- <constants>
- <constant name="FORMAT_IMA_ADPCM" value="2">
- Ima-ADPCM Audio.
- </constant>
- <constant name="LOOP_FORWARD" value="1">
- Forward looping (when playback reaches loop end, goes back to loop begin)
- </constant>
- <constant name="FORMAT_PCM16" value="1">
- 16-Bits signed little endian PCM audio.
- </constant>
- <constant name="FORMAT_PCM8" value="0">
- 8-Bits signed little endian PCM audio.
- </constant>
- <constant name="LOOP_NONE" value="0">
- No loop enabled.
- </constant>
- <constant name="LOOP_PING_PONG" value="2">
- Ping-Pong looping (when playback reaches loop end, plays backward untilloop begin). Not available in all platforms.
- </constant>
- </constants>
-</class>
-<class name="SampleLibrary" inherits="Resource" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="add_sample" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="sample" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_sample" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_sample" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="remove_sample" >
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SamplePlayer" inherits="Node" category="Nodes/Audio Nodes">
- <brief_description>
- Sample Player node.
- </brief_description>
- <description>
- SamplePlayer is a [Node] meant for simple sample playback. A library of samples is loaded and played back &quot;as is&quot;, without positioning or anything.
- </description>
- <methods>
- <method name="set_sample_library" >
- <argument index="0" name="library" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_sample_library" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_voice_count" >
- <argument index="0" name="max_voices" type="int">
- </argument>
- <description>
- Set the amount of simultaneous voices that will be used for playback.
- </description>
- </method>
- <method name="get_voice_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the amount of simultaneous voices that will be used for playback.
- </description>
- </method>
- <method name="play" >
- <return type="int">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="unique" type="bool" default="false">
- </argument>
- <description>
- Play back sample, given it&apos;s identifier &quot;name&quot;. if &quot;unique&quot; is true, all othere previous samples will be stopped. The voice allocated for playback will be returned.
- </description>
- </method>
- <method name="stop" >
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- Stop a voice &quot;voice&quot;. (see [method play]).
- </description>
- </method>
- <method name="stop_all" >
- <description>
- </description>
- </method>
- <method name="set_mix_rate" >
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="hz" type="int">
- </argument>
- <description>
- Change the mix rate of a voice &quot;voice&quot; to given &quot;hz&quot;.
- </description>
- </method>
- <method name="set_pitch_scale" >
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="ratio" type="real">
- </argument>
- <description>
- Scale the pitch (mix rate) of a voice by a ratio value &quot;ratio&quot;. A ratio of 1.0 means the voice is unscaled.
- </description>
- </method>
- <method name="set_volume" >
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="nrg" type="real">
- </argument>
- <description>
- Set the volume of a voice, 0db is maximum volume (every about -6db, volume is reduced in half). &quot;db&quot; does in fact go from zero to negative.
- </description>
- </method>
- <method name="set_volume_db" >
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="nrg" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_pan" >
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="pan" type="real">
- </argument>
- <argument index="2" name="depth" type="real" default="0">
- </argument>
- <argument index="3" name="height" type="real" default="0">
- </argument>
- <description>
- Set the panning of a voice. Panning goes from -1 (left) to +1 (right). Optionally, if the hardware supports 3D sound, also set depth and height (also in range -1 to +1).
- </description>
- </method>
- <method name="set_filter" >
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="type" type="int">
- </argument>
- <argument index="2" name="cutoff_hz" type="real">
- </argument>
- <argument index="3" name="resonance" type="real">
- </argument>
- <argument index="4" name="gain" type="real" default="0">
- </argument>
- <description>
- Set and enable a filter of a voice, with type &quot;type&quot; (see FILTER_* enum), cutoff (0 to 22khz) frequency and resonance (0+).
- </description>
- </method>
- <method name="set_chorus" >
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="send" type="real">
- </argument>
- <description>
- Set the chorus send level of a voice (0 to 1). For setting chorus parameters, see [AudioServer].
- </description>
- </method>
- <method name="set_reverb" >
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="room_type" type="int">
- </argument>
- <argument index="2" name="send" type="real">
- </argument>
- <description>
- Set the reverb send level and type of a voice (0 to 1). (see REVERB_* enum for type).
- </description>
- </method>
- <method name="get_mix_rate" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- Return the current mix rate for a given voice.
- </description>
- </method>
- <method name="get_pitch_scale" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- Return the current pitch scale for a given voice.
- </description>
- </method>
- <method name="get_volume" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- Return the current volume (in db) for a given voice. 0db is maximum volume (every about -6db, volume is reduced in half). &quot;db&quot; does in fact go from zero to negative.
- </description>
- </method>
- <method name="get_volume_db" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_pan" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- Return the current panning for a given voice. Panning goes from -1 (left) to +1 (right).
- </description>
- </method>
- <method name="get_pan_depth" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- Return the current pan depth for a given voice (not used unless the hardware supports 3D sound)
- </description>
- </method>
- <method name="get_pan_height" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- Return the current pan height for a given voice (not used unless the hardware supports 3D sound)
- </description>
- </method>
- <method name="get_filter_type" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- Return the current filter type in use (see FILTER_* enum) for a given voice.
- </description>
- </method>
- <method name="get_filter_cutoff" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- Return the current filter cutoff for a given voice. Cutoff goes from 0 to 22khz.
- </description>
- </method>
- <method name="get_filter_resonance" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- Return the current filter resonance for a given voice. Resonance goes from 0 up.
- </description>
- </method>
- <method name="get_filter_gain" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_chorus" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- Return the current chorus send level for a given voice. (0 to 1).
- </description>
- </method>
- <method name="get_reverb_room" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- Return the current reverb room type for a given voice (see REVERB_* enum).
- </description>
- </method>
- <method name="get_reverb" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- Return the current reverb send level for a given voice. (0 to 1).
- </description>
- </method>
- <method name="set_default_pitch_scale" >
- <argument index="0" name="ratio" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_volume" >
- <argument index="0" name="nrg" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_volume_db" >
- <argument index="0" name="db" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_pan" >
- <argument index="0" name="pan" type="real">
- </argument>
- <argument index="1" name="depth" type="real" default="0">
- </argument>
- <argument index="2" name="height" type="real" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_filter" >
- <argument index="0" name="type" type="int">
- </argument>
- <argument index="1" name="cutoff_hz" type="real">
- </argument>
- <argument index="2" name="resonance" type="real">
- </argument>
- <argument index="3" name="gain" type="real" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_chorus" >
- <argument index="0" name="send" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_default_reverb" >
- <argument index="0" name="room_type" type="int">
- </argument>
- <argument index="1" name="send" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_default_pitch_scale" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_volume" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_volume_db" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_pan" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_pan_depth" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_pan_height" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_filter_type" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_filter_cutoff" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_filter_resonance" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_filter_gain" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_chorus" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_reverb_room" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_default_reverb" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="FILTER_HIPASS" value="3">
- HighPass filter is used for voice.
- </constant>
- <constant name="FILTER_NONE" value="0">
- Filter is disabled for voice.
- </constant>
- <constant name="REVERB_HALL" value="3">
- Huge reverb room (cathedral, warehouse).
- </constant>
- <constant name="REVERB_MEDIUM" value="1">
- Medium reverb room (street)
- </constant>
- <constant name="REVERB_SMALL" value="0">
- Small reverb room (house room).
- </constant>
- <constant name="FILTER_HIGH_SHELF" value="8">
- </constant>
- <constant name="FILTER_PEAK" value="5">
- </constant>
- <constant name="FILTER_LOWPASS" value="1">
- Lowpass filter is used for voice.
- </constant>
- <constant name="REVERB_LARGE" value="2">
- Large reverb room (Theather)
- </constant>
- <constant name="FILTER_LOW_SHELF" value="7">
- </constant>
- <constant name="FILTER_BANDLIMIT" value="6">
- Band-Limit filter is used for voice, in this case resonance is the highpass cutoff.
- </constant>
- <constant name="FILTER_NOTCH" value="4">
- Notch filter is used for voice.
- </constant>
- <constant name="FILTER_BANDPASS" value="2">
- Bandpass filter is used for voice.
- </constant>
- </constants>
-</class>
-<class name="ScenarioFX" inherits="Node" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- Deprecated, will go away.
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SceneMainLoop" inherits="MainLoop" category="Main Loop">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_editor_hint" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_editor_hint" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_pause" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_paused" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="quit" >
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="screen_resized">
- <description>
- </description>
- </signal>
- <signal name="node_removed">
- <argument index="0" name="node" type="Object">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="tree_changed">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="Script" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="ScrollBar" inherits="Range" category="Core">
- <brief_description>
- Base class for scroll bars.
- </brief_description>
- <description>
- Scrollbars are a [Range] based [Control], that display a draggable area (the size of the page). Horizontal ([HScrollBar]) and Vertical ([VScrollBar]) versions are available.
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Separator" inherits="Control" category="Nodes/GUI Nodes">
- <brief_description>
- Base class for separators.
- </brief_description>
- <description>
- Separator is a [Control] used for sepataring other controls. It&apos;s purely a visual decoration. Horizontal ([HSeparator]) and Vertical ([VSeparator]) versions are available.
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Shader" inherits="Resource" category="Resources">
- <brief_description>
- To be changed, ignore.
- </brief_description>
- <description>
- To be changed, ignore.
- </description>
- <methods>
- <method name="set_mode" >
- <argument index="0" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_mode" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_vertex_code" >
- <argument index="0" name="code" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_vertex_code" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_fragment_code" >
- <argument index="0" name="code" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_fragment_code" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_use_world_transform" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_using_world_transform" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_param" >
- <argument index="0" name="param" type="String">
- </argument>
- <argument index="1" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_param" qualifiers="const" >
- <argument index="0" name="param" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_param_list" qualifiers="const" >
- <return type="StringArray">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="MODE_MATERIAL" value="0">
- </constant>
- <constant name="MODE_POST_PROCESS" value="1">
- </constant>
- </constants>
-</class>
-<class name="ShaderMaterial" inherits="Material" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_shader" >
- <argument index="0" name="shader" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_shader" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Shape" inherits="Resource" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Skeleton" inherits="Spatial" category="Nodes/3D">
- <brief_description>
- Skeleton for characters and animated objects.
- </brief_description>
- <description>
- Skeleton provides a hierachial interface for managing bones, including pose, rest and animation (see [Animation]). Skeleton will support rag doll dynamics in the future.
- </description>
- <methods>
- <method name="add_bone" >
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- Add a bone, with name &quot;name&quot;. [method get_bone_count] will become the bone index.
- </description>
- </method>
- <method name="find_bone" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- Return the bone index that matches &quot;name&quot; as its name.
- </description>
- </method>
- <method name="get_bone_name" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- Return the name of the bone at index &quot;index&quot;
- </description>
- </method>
- <method name="get_bone_parent" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- Return the bone index which is the parent of the bone at &quot;bone_idx&quot;. If -1, then bone has no parent. Note that the parent bone returned will always be less than &quot;bone_idx&quot;.
- </description>
- </method>
- <method name="set_bone_parent" >
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <argument index="1" name="parent_idx" type="int">
- </argument>
- <description>
- Set the bone index &quot;parent_idx&quot; as the parent of the bone at &quot;bone_idx&quot;. If -1, then bone has no parent. Note: &quot;parent_idx&quot; must be less than &quot;bone_idx&quot;.
- </description>
- </method>
- <method name="get_bone_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- Return the amount of bones in the skeleton.
- </description>
- </method>
- <method name="get_bone_rest" qualifiers="const" >
- <return type="Transform">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- Return the rest transform for a bone &quot;bone_idx&quot;.
- </description>
- </method>
- <method name="set_bone_rest" >
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <argument index="1" name="rest" type="Transform">
- </argument>
- <description>
- Set the rest transform for bone &quot;bone_idx&quot;
- </description>
- </method>
- <method name="bind_child_node_to_bone" >
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <argument index="1" name="node" type="Object">
- </argument>
- <description>
- Deprecated soon
- </description>
- </method>
- <method name="unbind_child_node_from_bone" >
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <argument index="1" name="node" type="Object">
- </argument>
- <description>
- Deprecated soon
- </description>
- </method>
- <method name="get_bound_child_nodes_to_bone" qualifiers="const" >
- <return type="Array">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- Deprecated Soon
- </description>
- </method>
- <method name="clear_bones" >
- <description>
- Clear all the bones in this skeleton.
- </description>
- </method>
- <method name="get_bone_pose" qualifiers="const" >
- <return type="Transform">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- Return the pose transform for bone &quot;bone_idx&quot;.
- </description>
- </method>
- <method name="set_bone_pose" >
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <argument index="1" name="pose" type="Transform">
- </argument>
- <description>
- Return the pose transform for bone &quot;bone_idx&quot;.
- </description>
- </method>
- <method name="get_bone_custom_pose" qualifiers="const" >
- <return type="Transform">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_bone_custom_pose" >
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <argument index="1" name="custom_pose" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_bone_transform" qualifiers="const" >
- <return type="Transform">
- </return>
- <argument index="0" name="bone_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="NOTIFICATION_UPDATE_SKELETON" value="50">
- </constant>
- </constants>
-</class>
-<class name="SkyBoxFX" inherits="ScenarioFX" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Slider" inherits="Range" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SoundRoomParams" inherits="Node" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_param" >
- <argument index="0" name="param" type="int">
- </argument>
- <argument index="1" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_param" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="param" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_reverb_mode" >
- <argument index="0" name="reverb_mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_reverb_mode" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_force_params_to_all_sources" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_forcing_params_to_all_sources" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Spatial" inherits="Node" category="Nodes/3D">
- <brief_description>
- Base class for all 3D nodes.
- </brief_description>
- <description>
- Spatial is the base for every type of 3D [Node]. It contains a 3D [Transform] which can be set or get as local or global. If a Spatial [Node] has Spatial children, their transforms will be relative to the parent.
- </description>
- <methods>
- <method name="set_transform" >
- <argument index="0" name="local" type="Transform">
- </argument>
- <description>
- Set the transform locally, relative to the parent spatial node.
- </description>
- </method>
- <method name="get_transform" qualifiers="const" >
- <return type="Transform">
- </return>
- <description>
- Return the local transform, relative to the bone parent.
- </description>
- </method>
- <method name="set_global_transform" >
- <argument index="0" name="global" type="Transform">
- </argument>
- <description>
- Set the transform globally, relative to worldspace.
- </description>
- </method>
- <method name="get_global_transform" qualifiers="const" >
- <return type="Transform">
- </return>
- <description>
- Return the gloal transform, relative to worldspace.
- </description>
- </method>
- <method name="get_parent_spatial" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- Return the parent [Spatial], or an empty [Object] if no parent exists or parent is not of type [Spatial.
- </description>
- </method>
- <method name="update_gizmo" >
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="NOTIFICATION_SCENARIO_CHANGED" value="41">
- Spatial nodes receive this notification when the viewport next to it in ascending hierarchy changed the [Scenario].
- </constant>
- <constant name="NOTIFICATION_TRANSFORM_CHANGED" value="40">
- Spatial nodes receive this notifacation with their global transform changes. This means that either the current or a parent node changed it&apos;s transform.
- </constant>
- </constants>
-</class>
-<class name="SpatialPlayer" inherits="Spatial" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SpatialSamplePlayer" inherits="SpatialPlayer" category="Nodes/3D">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_sample_library" >
- <argument index="0" name="library" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_sample_library" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_polyphony" >
- <argument index="0" name="voices" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_polyphony" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="play" >
- <return type="int">
- </return>
- <argument index="0" name="sample" type="String">
- </argument>
- <argument index="1" name="voice" type="int" default="-2">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_pitch_scale" >
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="ratio" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="voice_set_volume_scale_db" >
- <argument index="0" name="voice" type="int">
- </argument>
- <argument index="1" name="db" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_voice_active" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="stop_voice" >
- <argument index="0" name="voice" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="stop_all" >
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="NEXT_VOICE" value="-2">
- </constant>
- <constant name="INVALID_VOICE" value="-1">
- </constant>
- </constants>
-</class>
-<class name="SpatialSoundServer" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SpatialSoundServerSW" inherits="SpatialSoundServer" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SpatialStreamPlayer" inherits="SpatialPlayer" category="Nodes/3D">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_stream" >
- <argument index="0" name="stream" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_stream" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="play" >
- <description>
- </description>
- </method>
- <method name="stop" >
- <description>
- </description>
- </method>
- <method name="is_playing" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_loop" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_loop" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_stream_name" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_loop_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_pos" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="seek_pos" >
- <argument index="0" name="time" type="real">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SphereShape" inherits="Shape" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_radius" >
- <argument index="0" name="radius" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_radius" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SpinBox" inherits="Range" category="Nodes/GUI Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_suffix" >
- <argument index="0" name="suffix" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_suffix" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_prefix" >
- <argument index="0" name="prefix" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_prefix" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="set_editable" >
- <argument index="0" name="editable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_editable" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SpotLight" inherits="Light" category="Nodes/3D/3D Visual Nodes/3D Light Nodes">
- <brief_description>
- Spotlight Light, such as a reflector spotlight or a latern.
- </brief_description>
- <description>
- A SpotLight light is a type of [Light] node that emits lights in a specific direction, in the shape of a cone. The light is attenuated through the distance and this attenuation can be configured by changing the energy, radius and attenuation parameters of [Light]. TODO: Image of a spotlight.
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Sprite" inherits="Node2D" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_texture" >
- <argument index="0" name="texture" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_texture" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_centered" >
- <argument index="0" name="centered" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_centered" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_flip_h" >
- <argument index="0" name="flip_h" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_flipped_h" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_flip_v" >
- <argument index="0" name="flip_v" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_flipped_v" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_frame" >
- <argument index="0" name="frame" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_frame" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_vframes" >
- <argument index="0" name="vframes" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_vframes" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_hframes" >
- <argument index="0" name="hframes" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_hframes" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_modulate" >
- <argument index="0" name="modulate" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_modulate" qualifiers="const" >
- <return type="Color">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SquirrelScript" inherits="Script" category="Resources">
- <brief_description>
- Squirrel script language support.
- </brief_description>
- <description>
- [html a href=&quot;http://squirrel-lang.org/&quot;]Squirrel Language[html /a] support for the engine. Allows to load a [Script] from a .sq or .nut source or compiled file, or bundled it into scenes.
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StaticBody" inherits="PhysicsBody" category="Nodes/3D">
- <brief_description>
- PhysicsBody for static collision objects.
- </brief_description>
- <description>
- StaticBody implements a static collision [Node], by utilizing a rigid body in the [PhysicsServer]. Static bodies are used for static collision. For more information on physics body nodes, see [PhysicsBody].
- </description>
- <methods>
- <method name="set_simulated_motion" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_simulating_motion" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="simulate_motion" >
- <argument index="0" name="new_transform" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="create_shapes_from_child_meshes" >
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StreamPeer" inherits="Object" category="Networking">
- <brief_description>
- Abstraction and base class for stream-based protocols.
- </brief_description>
- <description>
- StreamPeer is an abstration and base class for stream-based protocols (such as TCP or Unix Sockets). It provides an API for sending and receiving data through streams as raw data or strings.
- </description>
- <methods>
- <method name="put_data" >
- <return type="int">
- </return>
- <argument index="0" name="data" type="RawArray">
- </argument>
- <description>
- Send a chunk of data through the connection, blocking if necesary until the data is done sending. This function returns an [Error] code.
- </description>
- </method>
- <method name="put_partial_data" >
- <return type="Array">
- </return>
- <argument index="0" name="data" type="RawArray">
- </argument>
- <description>
- Send a chunk of data through the connection, if all the data could not be sent at once, only part of it will. This function returns two values, an [Error] code and an integer, describing how much data was actually sent.
- </description>
- </method>
- <method name="get_data" >
- <return type="Array">
- </return>
- <argument index="0" name="bytes" type="int">
- </argument>
- <description>
- Return a chunk data with the received bytes. The amount of bytes to be received can be requested in the &quot;bytes&quot; argument. If not enough bytes are available, the function will block until the desired amount is received. This function returns two values, an [Error] code and a data array.
- </description>
- </method>
- <method name="get_partial_data" >
- <return type="Array">
- </return>
- <argument index="0" name="bytes" type="int">
- </argument>
- <description>
- Return a chunk data with the received bytes. The amount of bytes to be received can be requested in the &quot;bytes&quot; argument. If not enough bytes are available, the function will return how many were actually received. This function returns two values, an [Error] code, and a data array.
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StreamPeerTCP" inherits="StreamPeer" category="Networking/Networking">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="connect" >
- <return type="int">
- </return>
- <argument index="0" name="host" type="String">
- </argument>
- <argument index="1" name="ip" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_connected" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_connected_host" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_connected_port" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="disconnect" >
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StreamPlayer" inherits="Node" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_stream" >
- <argument index="0" name="stream" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_stream" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="play" >
- <description>
- </description>
- </method>
- <method name="stop" >
- <description>
- </description>
- </method>
- <method name="is_playing" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_loop" >
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_loop" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_volume" >
- <argument index="0" name="volume" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_volume" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_volume_db" >
- <argument index="0" name="db" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_volume_db" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="get_stream_name" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_loop_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_pos" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="seek_pos" >
- <argument index="0" name="time" type="real">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StyleBox" inherits="Resource" category="Core">
- <brief_description>
- Base class for dawing stylized boxes for the UI.
- </brief_description>
- <description>
- StyleBox is [Resource] that provides an abstract base class for dawing stylized boxes for the UI. StyleBoxes are used for dawing the styles of buttons, line edit backgrounds, tree backgrounds, etc. and also for testing a transparency mask for pointer signals. If mask test fails on a StyleBox assigned as mask to a control, clicks and motion signals will go through it to the one below.
- </description>
- <methods>
- <method name="test_mask" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="point" type="Vector2">
- </argument>
- <argument index="1" name="rect" type="Rect2">
- </argument>
- <description>
- Test a position in a rectangle, return wether it pases the mask test.
- </description>
- </method>
- <method name="set_default_margin" >
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="offset" type="real">
- </argument>
- <description>
- Set the default offset &quot;offset&quot; of the margin &quot;margin&quot; (see MARGIN_* enum) for a StyleBox, Controls that draw styleboxes with context inside need to know the margin, so the border of the stylebox is not occluded.
- </description>
- </method>
- <method name="get_default_margin" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="margin" type="int">
- </argument>
- <description>
- Return the default offset of the margin &quot;margin&quot; (see MARGIN_* enum) of a StyleBox, Controls that draw styleboxes with context inside need to know the margin, so the border of the stylebox is not occluded.
- </description>
- </method>
- <method name="get_margin" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="margin" type="int">
- </argument>
- <description>
- Return the offset of margin &quot;margin&quot; (see MARGIN_* enum).
- </description>
- </method>
- <method name="get_minimum_size" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- Return the minimum size that this stylebox can be shrunk to.
- </description>
- </method>
- <method name="get_offset" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- Return the &quot;offset&quot; of a stylebox, this is a helper function, like writing Point2( style.get_margin(MARGIN_LEFT), style.get_margin(MARGIN_TOP) )
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StyleBoxEmpty" inherits="StyleBox" category="Resources">
- <brief_description>
- Empty stylebox (does not display anything).
- </brief_description>
- <description>
- Empty stylebox (really does not display anything).
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StyleBoxFlat" inherits="StyleBox" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_bg_color" >
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_bg_color" qualifiers="const" >
- <return type="Color">
- </return>
- <description>
- </description>
- </method>
- <method name="set_light_color" >
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_light_color" qualifiers="const" >
- <return type="Color">
- </return>
- <description>
- </description>
- </method>
- <method name="set_dark_color" >
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_dark_color" qualifiers="const" >
- <return type="Color">
- </return>
- <description>
- </description>
- </method>
- <method name="set_border_size" >
- <argument index="0" name="size" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_border_size" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_border_blend" >
- <argument index="0" name="blend" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_border_blend" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_draw_center" >
- <argument index="0" name="size" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_draw_center" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StyleBoxImageMask" inherits="StyleBox" category="Resources">
- <brief_description>
- Image mask based StyleBox, for mask test.
- </brief_description>
- <description>
- This StyleBox is similar to [StyleBoxTexture], but only meant to be used for mask testing. It takes an image and applies stretch rules to determine if the poit clicked is masked or not.
- </description>
- <methods>
- <method name="set_image" >
- <argument index="0" name="image" type="Image">
- </argument>
- <description>
- Set the image used for mask testing. Pixels (converted to grey) that have a value, less than 0.5 will fail the test.
- </description>
- </method>
- <method name="get_image" qualifiers="const" >
- <return type="Image">
- </return>
- <description>
- Return the image used for mask testing. (see [method set_imag]).
- </description>
- </method>
- <method name="set_expand" >
- <argument index="0" name="expand" type="bool">
- </argument>
- <description>
- Set the expand property (default). When expanding, the image will use the same rules as [StyleBoxTexture] for expand. If not expanding, the image will always be tested at its original size.
- </description>
- </method>
- <method name="get_expand" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- Return wether the expand property is set(default). When expanding, the image will use the same rules as [StyleBoxTexture] for expand. If not expanding, the image will always be tested at its original size.
- </description>
- </method>
- <method name="set_expand_margin_size" >
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="size" type="real">
- </argument>
- <description>
- Set an expand margin size (from enum MARGIN_*). Parts of the image below the size of the margin (and in the direction of the margin) will not expand.
- </description>
- </method>
- <method name="get_expand_margin_size" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- Return the expand margin size (from enum MARGIN_*). Parts of the image below the size of the margin (and in the direction of the margin) will not expand.
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="StyleBoxTexture" inherits="StyleBox" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_texture" >
- <argument index="0" name="texture" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_texture" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_margin_size" >
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="size" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_margin_size" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_expand_margin_size" >
- <argument index="0" name="margin" type="int">
- </argument>
- <argument index="1" name="size" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_expand_margin_size" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_draw_center" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_draw_center" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_center_size" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="draw" qualifiers="const" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="SurfaceTool" inherits="Reference" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="begin" >
- <argument index="0" name="primitive" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_vertex" >
- <argument index="0" name="vertex" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_color" >
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_normal" >
- <argument index="0" name="normal" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_tangent" >
- <argument index="0" name="tangent" type="Plane">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_uv" >
- <argument index="0" name="uv" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_uv2" >
- <argument index="0" name="uv2" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_bones" >
- <argument index="0" name="bones" type="IntArray">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_weights" >
- <argument index="0" name="weights" type="RealArray">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_material" >
- <argument index="0" name="material" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="index" >
- <description>
- </description>
- </method>
- <method name="deindex" >
- <description>
- </description>
- </method>
- <method name="generate_flat_normals" >
- <description>
- </description>
- </method>
- <method name="generate_smooth_normals" >
- <description>
- </description>
- </method>
- <method name="generate_tangents" >
- <description>
- </description>
- </method>
- <method name="commit" >
- <return type="Object">
- </return>
- <argument index="0" name="existing" type="Object" default="Object()">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear" >
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="TCP_Server" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="listen" >
- <return type="int">
- </return>
- <argument index="0" name="port" type="int">
- </argument>
- <argument index="1" name="accepted_hosts" type="StringArray" default="StringArray()">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_connection_available" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="take_connection" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="stop" >
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="TabContainer" inherits="Control" category="Nodes/GUI Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="get_tab_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_current_tab" >
- <argument index="0" name="tab_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_current_tab" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_tab_align" >
- <argument index="0" name="align" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_tab_align" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_tabs_visible" >
- <argument index="0" name="visible" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="are_tabs_visible" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_tab_title" >
- <argument index="0" name="tab_idx" type="int">
- </argument>
- <argument index="1" name="title" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_tab_title" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="tab_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_tab_icon" >
- <argument index="0" name="tab_idx" type="int">
- </argument>
- <argument index="1" name="icon" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_tab_icon" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="tab_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="tab_changed">
- <argument index="0" name="tab" type="int">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="TestCube" inherits="VisualInstance" category="Nodes/3D/3D Visual Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="TextEdit" inherits="Control" category="Nodes/GUI Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_text" >
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="insert_text_at_cursor" >
- <argument index="0" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_line_count" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_text" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="get_line" >
- <return type="String">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="cursor_set_column" >
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="cursor_set_line" >
- <argument index="0" name="line" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="cursor_get_column" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="cursor_get_line" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_readonly" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_wrap" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_max_chars" >
- <argument index="0" name="amount" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="cut" >
- <description>
- </description>
- </method>
- <method name="copy" >
- <description>
- </description>
- </method>
- <method name="paste" >
- <description>
- </description>
- </method>
- <method name="select_all" >
- <description>
- </description>
- </method>
- <method name="select" >
- <argument index="0" name="from_line" type="int">
- </argument>
- <argument index="1" name="from_column" type="int">
- </argument>
- <argument index="2" name="to_line" type="int">
- </argument>
- <argument index="3" name="to_column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_selection_active" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selection_from_line" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selection_from_column" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selection_to_line" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selection_to_column" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selection_text" qualifiers="const" >
- <return type="String">
- </return>
- <description>
- </description>
- </method>
- <method name="search" qualifiers="const" >
- <return type="IntArray">
- </return>
- <argument index="0" name="flags" type="String">
- </argument>
- <argument index="1" name="from_line" type="int">
- </argument>
- <argument index="2" name="from_column" type="int">
- </argument>
- <argument index="3" name="to_line" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="undo" >
- <description>
- </description>
- </method>
- <method name="redo" >
- <description>
- </description>
- </method>
- <method name="clear_undo_history" >
- <description>
- </description>
- </method>
- <method name="set_syntax_coloring" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_syntax_coloring_enabled" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="add_keyword_color" >
- <argument index="0" name="keyword" type="String">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_color_region" >
- <argument index="0" name="begin_key" type="String">
- </argument>
- <argument index="1" name="end_key" type="String">
- </argument>
- <argument index="2" name="color" type="Color">
- </argument>
- <argument index="3" name="line_only" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_symbol_color" >
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_custom_bg_color" >
- <argument index="0" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_colors" >
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="text_changed">
- <description>
- </description>
- </signal>
- <signal name="cursor_changed">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="SEARCH_MATCH_CASE" value="1">
- </constant>
- <constant name="SEARCH_BACKWARDS" value="4">
- </constant>
- <constant name="SEARCH_WHOLE_WORDS" value="2">
- </constant>
- </constants>
-</class>
-<class name="Texture" inherits="Resource" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="create" >
- <argument index="0" name="width" type="int">
- </argument>
- <argument index="1" name="height" type="int">
- </argument>
- <argument index="2" name="format" type="int">
- </argument>
- <argument index="3" name="flags" type="int" default="7">
- </argument>
- <description>
- </description>
- </method>
- <method name="create_from_image" >
- <argument index="0" name="image" type="Image">
- </argument>
- <argument index="1" name="flags" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_flags" >
- <argument index="0" name="flags" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_flags" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_format" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="load" >
- <argument index="0" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="blit_rect" >
- <argument index="0" name="x" type="int">
- </argument>
- <argument index="1" name="y" type="int">
- </argument>
- <argument index="2" name="image" type="Image">
- </argument>
- <argument index="3" name="cube_side" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_rect" qualifiers="const" >
- <return type="Image">
- </return>
- <argument index="0" name="x" type="int">
- </argument>
- <argument index="1" name="y" type="int">
- </argument>
- <argument index="2" name="width" type="int">
- </argument>
- <argument index="3" name="height" type="int">
- </argument>
- <argument index="4" name="cube_side" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_width" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_height" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_size" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_rid" qualifiers="const" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="has_alpha" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="draw" qualifiers="const" >
- <argument index="0" name="canvas_item" type="RID">
- </argument>
- <argument index="1" name="pos" type="Vector2">
- </argument>
- <argument index="2" name="modulate" type="Color" default="Color(1,1,1,1)">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="CUBEMAP_BACK" value="5">
- </constant>
- <constant name="CUBEMAP_FRONT" value="4">
- </constant>
- <constant name="FLAG_CUBEMAP" value="8">
- </constant>
- <constant name="CUBEMAP_TOP" value="3">
- </constant>
- <constant name="CUBEMAP_LEFT" value="0">
- </constant>
- <constant name="FLAG_FILTER" value="4">
- </constant>
- <constant name="FLAG_MIPMAPS" value="1">
- </constant>
- <constant name="CUBEMAP_BOTTOM" value="2">
- </constant>
- <constant name="FLAGS_DEFAULT" value="7">
- </constant>
- <constant name="CUBEMAP_RIGHT" value="1">
- </constant>
- <constant name="FLAG_REPEAT" value="2">
- </constant>
- </constants>
-</class>
-<class name="TextureButton" inherits="BaseButton" category="Nodes/GUI Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_normal_texture" >
- <argument index="0" name="texture" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_pressed_texture" >
- <argument index="0" name="texture" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_hover_texture" >
- <argument index="0" name="texture" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_disabled_texture" >
- <argument index="0" name="texture" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_focused_texture" >
- <argument index="0" name="texture" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_click_mask" >
- <argument index="0" name="texture" type="Image">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_normal_texture" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_pressed_texture" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_hover_texture" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_disabled_texture" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_focused_texture" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_click_mask" qualifiers="const" >
- <return type="Image">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="TextureFrame" inherits="Control" category="Nodes/GUI Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_texture" >
- <argument index="0" name="texture" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_texture" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_expand" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_expand" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Theme" inherits="Resource" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_icon" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <argument index="2" name="texture" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_icon" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_icon" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_icon" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_icon_list" qualifiers="const" >
- <return type="StringArray">
- </return>
- <argument index="0" name="arg0" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_stylebox" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <argument index="2" name="texture" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_stylebox" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_stylebox" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_stylebox" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_stylebox_list" qualifiers="const" >
- <return type="StringArray">
- </return>
- <argument index="0" name="arg0" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_font" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <argument index="2" name="font" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_font" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_font" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_font" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_font_list" qualifiers="const" >
- <return type="StringArray">
- </return>
- <argument index="0" name="arg0" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_color" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <argument index="2" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color" qualifiers="const" >
- <return type="Color">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_color" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_color" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_color_list" qualifiers="const" >
- <return type="StringArray">
- </return>
- <argument index="0" name="arg0" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_constant" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <argument index="2" name="constant" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_constant" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_constant" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_constant" >
- <argument index="0" name="name" type="String">
- </argument>
- <argument index="1" name="type" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_constant_list" qualifiers="const" >
- <return type="StringArray">
- </return>
- <argument index="0" name="arg0" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_type_list" qualifiers="const" >
- <return type="StringArray">
- </return>
- <argument index="0" name="arg0" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="copy_default_theme" >
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Timer" inherits="Node" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_wait_time" >
- <argument index="0" name="time_sec" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_wait_time" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- <method name="set_one_shot" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_one_shot" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_autostart" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="has_autostart" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="start" >
- <description>
- </description>
- </method>
- <method name="stop" >
- <description>
- </description>
- </method>
- <method name="get_time_left" qualifiers="const" >
- <return type="real">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="timeout">
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- </constants>
-</class>
-<class name="Tree" inherits="Control" category="Nodes/GUI Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="clear" >
- <description>
- </description>
- </method>
- <method name="create_item" >
- <return type="Object">
- </return>
- <argument index="0" name="arg0" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_root" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="set_column_min_width" >
- <argument index="0" name="arg0" type="int">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_column_expand" >
- <argument index="0" name="arg0" type="int">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_column_width" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_hide_root" >
- <argument index="0" name="arg0" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_next_selected" >
- <return type="Object">
- </return>
- <argument index="0" name="arg0" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_selected" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_selected_column" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_pressed_button" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="set_select_mode" >
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_columns" >
- <argument index="0" name="amount" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_columns" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_edited" qualifiers="const" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_edited_column" qualifiers="const" >
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_custom_popup_rect" qualifiers="const" >
- <return type="Rect2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_item_rect" qualifiers="const" >
- <return type="Rect2">
- </return>
- <argument index="0" name="item" type="Object">
- </argument>
- <argument index="1" name="column" type="int" default="-1">
- </argument>
- <description>
- </description>
- </method>
- <method name="ensure_cursor_is_visible" >
- <description>
- </description>
- </method>
- <method name="set_column_titles_visible" >
- <argument index="0" name="visible" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="are_column_titles_visible" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_column_title" >
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="title" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_column_title" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_scroll" qualifiers="const" >
- <return type="Vector2">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <signals>
- <signal name="multi_selected">
- <description>
- </description>
- </signal>
- <signal name="custom_popup_edited">
- <argument index="0" name="arrow_clicked" type="bool">
- </argument>
- <description>
- </description>
- </signal>
- <signal name="item_edited">
- <description>
- </description>
- </signal>
- <signal name="item_selected">
- <description>
- </description>
- </signal>
- <signal name="item_doubleclicked">
- <description>
- </description>
- </signal>
- <signal name="cell_selected">
- <description>
- </description>
- </signal>
- <signal name="button_pressed">
- <argument index="0" name="item" type="Object">
- </argument>
- <argument index="1" name="column" type="int">
- </argument>
- <argument index="2" name="id" type="int">
- </argument>
- <description>
- </description>
- </signal>
- </signals>
- <constants>
- <constant name="SELECT_ROW" value="1">
- </constant>
- <constant name="SELECT_SINGLE" value="0">
- </constant>
- <constant name="SELECT_MULTI" value="2">
- </constant>
- </constants>
-</class>
-<class name="TreeItem" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_cell_mode" >
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_cell_mode" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_checked" >
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="checked" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_checked" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_text" >
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="text" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_text" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_icon" >
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="texture" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_icon" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_range" >
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="value" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_range" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_range_config" >
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="min" type="real">
- </argument>
- <argument index="2" name="max" type="real">
- </argument>
- <argument index="3" name="step" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_range_config" >
- <return type="Dictionary">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_metadata" >
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="meta" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_metadata" qualifiers="const" >
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_collapsed" >
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_collapsed" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="get_next" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_prev" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_parent" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_children" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_next_visible" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="get_prev_visible" >
- <return type="Object">
- </return>
- <description>
- </description>
- </method>
- <method name="remove_child" >
- <argument index="0" name="child" type="Object">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_selectable" >
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="selectable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_selected" >
- <return type="bool">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="select" >
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="deselect" >
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_editable" >
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="enabled" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_editable" >
- <return type="bool">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_custom_color" >
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_custom_color" >
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_custom_bg_color" >
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="color" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="clear_custom_bg_color" >
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="add_button" >
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="button" type="Object">
- </argument>
- <argument index="2" name="arg2" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_button_count" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_button" qualifiers="const" >
- <return type="Object">
- </return>
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="button_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="erase_button" >
- <argument index="0" name="column" type="int">
- </argument>
- <argument index="1" name="button_idx" type="int">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="CELL_MODE_ICON" value="3">
- </constant>
- <constant name="CELL_MODE_CUSTOM" value="4">
- </constant>
- <constant name="CELL_MODE_RANGE" value="2">
- </constant>
- <constant name="CELL_MODE_CHECK" value="1">
- </constant>
- <constant name="CELL_MODE_STRING" value="0">
- </constant>
- </constants>
-</class>
-<class name="VScrollBar" inherits="ScrollBar" category="Nodes/GUI Nodes">
- <brief_description>
- Vertical version of [ScrollBar], which goes from left (min) to right (max).
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="VSeparator" inherits="Separator" category="Nodes/GUI Nodes">
- <brief_description>
- Vertical version of [Separator].
- </brief_description>
- <description>
- Vertical version of [Separator]. It is used to separate objects horizontally, though (but it looks vertical!).
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="VSlider" inherits="Slider" category="Nodes/GUI Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="Viewport" inherits="Node" category="Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="set_rect" >
- <argument index="0" name="rect" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_rect" qualifiers="const" >
- <return type="Rect2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_visible_rect" qualifiers="const" >
- <return type="Rect2">
- </return>
- <description>
- </description>
- </method>
- <method name="get_viewport" qualifiers="const" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="VisualInstance" inherits="Spatial" category="Nodes/3D/3D Visual Nodes">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="override_material_param" >
- <argument index="0" name="param" type="String">
- </argument>
- <argument index="1" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_visible" >
- <argument index="0" name="visible" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_visible" qualifiers="const" >
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_base" >
- <argument index="0" name="base" type="RID">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
-<class name="VisualServer" inherits="Object" category="Core">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- <method name="texture_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="texture_create_from_image" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="Image">
- </argument>
- <argument index="1" name="arg1" type="int" default="7">
- </argument>
- <description>
- </description>
- </method>
- <method name="texture_allocate" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="int">
- </argument>
- <argument index="3" name="arg3" type="int">
- </argument>
- <argument index="4" name="arg4" type="int" default="7">
- </argument>
- <description>
- </description>
- </method>
- <method name="texture_blit_rect" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="int">
- </argument>
- <argument index="3" name="arg3" type="Image">
- </argument>
- <argument index="4" name="arg4" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="texture_set_flags" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="texture_get_flags" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="texture_get_width" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="texture_get_height" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_create" >
- <return type="RID">
- </return>
- <argument index="0" name="mode" type="int" default="0">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_set_mode" >
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="mode" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_get_mode" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="shader" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_set_vertex_code" >
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="code" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_get_vertex_code" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="shader" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_set_fragment_code" >
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="code" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_get_fragment_code" qualifiers="const" >
- <return type="String">
- </return>
- <argument index="0" name="shader" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_set_param" >
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="param" type="String">
- </argument>
- <argument index="2" name="value" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_get_param" qualifiers="const" >
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="param" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_get_param_list" qualifiers="const" >
- <return type="StringArray">
- </return>
- <argument index="0" name="shader" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_set_use_world_transform" >
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="shader_is_using_world_transform" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="shader" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="material_set_shader" >
- <argument index="0" name="shader" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_get_shader" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_set_param" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <argument index="2" name="arg2" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_get_param" qualifiers="const" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_set_flag" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_get_flag" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_set_blend_mode" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_get_blend_mode" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_set_line_width" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="material_get_line_width" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_set_parameter" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_get_parameter" qualifiers="const" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_set_texture" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_get_texture" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_set_texgen_mode" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_get_texgen_mode" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_set_texcoord_mode" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_get_texcoord_mode" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_set_uv_transform" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="fixed_material_get_uv_transform" qualifiers="const" >
- <return type="Transform">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="mesh_surface_set_array" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="int">
- </argument>
- <argument index="3" name="arg3" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_get_array" qualifiers="const" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_set_material" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="RID">
- </argument>
- <argument index="3" name="arg3" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_get_material" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_get_array_len" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_get_array_index_len" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_get_format" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_surface_get_primitive_type" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_erase_surface" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_get_surface_count" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="multimesh_set_mesh" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_set_aabb" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="AABB">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_instance_set_transform" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_instance_set_color" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_get_mesh" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_get_aabb" qualifiers="const" >
- <return type="AABB">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="AABB">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_instance_get_transform" qualifiers="const" >
- <return type="Transform">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="multimesh_instance_get_color" qualifiers="const" >
- <return type="Color">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="poly_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="poly_set_material" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <argument index="2" name="arg2" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="poly_add_primitive" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Vector3Array">
- </argument>
- <argument index="2" name="arg2" type="Vector3Array">
- </argument>
- <argument index="3" name="arg3" type="ColorArray">
- </argument>
- <argument index="4" name="arg4" type="Vector3Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="poly_clear" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="particles_set_amount" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_amount" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_emitting" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_is_emitting" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_visibility_aabb" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="AABB">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_visibility_aabb" qualifiers="const" >
- <return type="AABB">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_variable" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_variable" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_randomness" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_randomness" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_color_phases" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_color_phases" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_color_phase_pos" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_color_phase_pos" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_color_phase_color" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_color_phase_color" qualifiers="const" >
- <return type="Color">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_attractors" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_attractors" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_attractor_pos" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="Vector3">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_attractor_pos" qualifiers="const" >
- <return type="Vector3">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_attractor_strength" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_get_attractor_strength" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_material" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <argument index="2" name="arg2" type="bool" default="false">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_set_height_from_velocity" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="particles_has_height_from_velocity" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_create" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_get_type" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_set_color" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_get_color" qualifiers="const" >
- <return type="Color">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_set_shadow" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_has_shadow" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_set_volumetric" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_is_volumetric" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_set_projector" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_get_projector" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_set_var" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="light_get_var" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="skeleton_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="skeleton_resize" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="skeleton_get_bone_count" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="skeleton_bone_set_transform" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="skeleton_bone_get_transform" >
- <return type="Transform">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="room_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="room_set_bounds" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Dictionary">
- </argument>
- <description>
- </description>
- </method>
- <method name="room_get_bounds" qualifiers="const" >
- <return type="Dictionary">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="portal_set_shape" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_get_shape" qualifiers="const" >
- <return type="Array">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_set_enabled" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_is_enabled" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_set_disable_distance" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_get_disable_distance" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_set_disabled_color" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="portal_get_disabled_color" qualifiers="const" >
- <return type="Color">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="camera_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="camera_set_perspective" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <argument index="3" name="arg3" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="camera_set_orthogonal" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <argument index="3" name="arg3" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="camera_set_transform" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="viewport_set_rect" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_get_rect" qualifiers="const" >
- <return type="Rect2">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_attach_camera" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID" default="RID()">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_get_attached_camera" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_get_scenario" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_attach_canvas" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_remove_canvas" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_move_canvas_to_top" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="viewport_move_canvas_to_bottom" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="scenario_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="scenario_set_debug" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="scenario_fx_get_effects" qualifiers="const" >
- <return type="StringArray">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="scenario_fx_set_active" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <argument index="2" name="arg2" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="scenario_fx_is_active" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="scenario_fx_get_effect_params" qualifiers="const" >
- <return type="Array">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="scenario_fx_get_effect_param" qualifiers="const" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <argument index="2" name="arg2" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="scenario_fx_set_effect_param" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="String">
- </argument>
- <argument index="2" name="arg2" type="String">
- </argument>
- <argument index="3" name="arg3" type="var">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="instance_get_base" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_get_base_aabb" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_set_transform" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Transform">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_get_transform" qualifiers="const" >
- <return type="Transform">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_attach_object_instance_ID" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_get_object_instance_ID" qualifiers="const" >
- <return type="int">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_attach_skeleton" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_get_skeleton" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_set_room" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_get_room" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_set_exterior" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_is_exterior" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instances_cull_aabb" qualifiers="const" >
- <return type="Array">
- </return>
- <argument index="0" name="arg0" type="AABB">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instances_cull_ray" qualifiers="const" >
- <return type="Array">
- </return>
- <argument index="0" name="arg0" type="Vector3">
- </argument>
- <argument index="1" name="arg1" type="Vector3">
- </argument>
- <argument index="2" name="arg2" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instances_cull_convex" qualifiers="const" >
- <return type="Array">
- </return>
- <argument index="0" name="arg0" type="Vector3">
- </argument>
- <argument index="1" name="arg1" type="Vector3">
- </argument>
- <argument index="2" name="arg2" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_geometry_set_visible" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_geometry_is_visible" qualifiers="const" >
- <return type="bool">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_geometry_override_material_param" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="instance_geometry_get_material_param" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="canvas_item_create" >
- <return type="RID">
- </return>
- <description>
- </description>
- </method>
- <method name="canvas_item_set_parent" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_get_parent" qualifiers="const" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_set_custom_rect" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <argument index="2" name="arg2" type="Rect2">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_set_clip" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="bool">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_set_opacity" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_get_opacity" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_set_self_opacity" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_get_self_opacity" qualifiers="const" >
- <return type="real">
- </return>
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_add_line" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Vector2">
- </argument>
- <argument index="2" name="arg2" type="Vector2">
- </argument>
- <argument index="3" name="arg3" type="Color">
- </argument>
- <argument index="4" name="arg4" type="real" default="1">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_add_rect" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Rect2">
- </argument>
- <argument index="2" name="arg2" type="Color">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_add_texture_rect" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Rect2">
- </argument>
- <argument index="2" name="arg2" type="RID">
- </argument>
- <argument index="3" name="arg3" type="bool">
- </argument>
- <argument index="4" name="arg4" type="Color" default="Color(1,1,1,1)">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_add_texture_rect_region" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Rect2">
- </argument>
- <argument index="2" name="arg2" type="RID">
- </argument>
- <argument index="3" name="arg3" type="Rect2">
- </argument>
- <argument index="4" name="arg4" type="Color" default="Color(1,1,1,1)">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_add_style_box" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Rect2">
- </argument>
- <argument index="2" name="arg2" type="RID">
- </argument>
- <argument index="3" name="arg3" type="RealArray">
- </argument>
- <argument index="4" name="arg4" type="Color" default="Color(1,1,1,1)">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_add_primitive" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Array">
- </argument>
- <argument index="2" name="arg2" type="ColorArray">
- </argument>
- <argument index="3" name="arg3" type="Array" default="Array()">
- </argument>
- <argument index="4" name="arg4" type="RID" default="RID()">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_clear" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="canvas_item_raise" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- <method name="cursor_set_rotation" >
- <argument index="0" name="arg0" type="real">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="cursor_set_texture" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Vector2">
- </argument>
- <argument index="2" name="arg2" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="cursor_set_visible" >
- <argument index="0" name="arg0" type="bool">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="cursor_set_pos" >
- <argument index="0" name="arg0" type="Vector2">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="make_sphere_mesh" >
- <return type="RID">
- </return>
- <argument index="0" name="arg0" type="int">
- </argument>
- <argument index="1" name="arg1" type="int">
- </argument>
- <argument index="2" name="arg2" type="real">
- </argument>
- <description>
- </description>
- </method>
- <method name="mesh_add_surface_from_planes" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <argument index="1" name="arg1" type="Array">
- </argument>
- <description>
- </description>
- </method>
- <method name="free" >
- <argument index="0" name="arg0" type="RID">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- <constant name="INSTANCE_GEOMETRY_MASK" value="30">
- </constant>
- <constant name="INSTANCE_PARTICLES" value="4">
- </constant>
- <constant name="SCENARIO_DEBUG_WIREFRAME" value="1">
- </constant>
- <constant name="LIGHT_VAR_ATTENUATION" value="4">
- </constant>
- <constant name="LIGHT_VAR_SPOT_ANGLE" value="1">
- </constant>
- <constant name="LIGHT_COLOR_DIFFUSE" value="1">
- </constant>
- <constant name="PARTICLE_ANGULAR_VELOCITY" value="4">
- </constant>
- <constant name="INSTANCE_LIGHT" value="5">
- </constant>
- <constant name="INSTANCE_MULTIMESH" value="2">
- </constant>
- <constant name="PARTICLE_HEIGHT" value="11">
- </constant>
- <constant name="PARTICLE_LINEAR_VELOCITY" value="3">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_SPECULAR" value="2">
- </constant>
- <constant name="ARRAY_VERTEX" value="0">
- </constant>
- <constant name="LIGHT_SPOT" value="2">
- </constant>
- <constant name="CUBEMAP_BACK" value="5">
- </constant>
- <constant name="MATERIAL_FLAG_MAX" value="7">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_DETAIL_MIX" value="6">
- </constant>
- <constant name="ARRAY_COLOR" value="3">
- </constant>
- <constant name="ARRAY_FORMAT_BONES" value="64">
- </constant>
- <constant name="PRIMITIVE_MAX" value="7">
- </constant>
- <constant name="FIXED_MATERIAL_TEXGEN_SPHERE" value="1">
- </constant>
- <constant name="ARRAY_FORMAT_INDEX" value="256">
- </constant>
- <constant name="PRIMITIVE_TRIANGLE_STRIP" value="5">
- </constant>
- <constant name="MAX_PARTICLE_ATTRACTORS" value="4">
- </constant>
- <constant name="TEXTURE_FLAG_FILTER" value="4">
- </constant>
- <constant name="CUBEMAP_TOP" value="3">
- </constant>
- <constant name="MATERIAL_BLEND_MODE_ADD" value="1">
- </constant>
- <constant name="FIXED_MATERIAL_TEXCOORD_TEXGEN" value="3">
- </constant>
- <constant name="FIXED_MATERIAL_TEXCOORD_UV" value="0">
- </constant>
- <constant name="ARRAY_TANGENT" value="2">
- </constant>
- <constant name="ARRAY_FORMAT_NORMAL" value="2">
- </constant>
- <constant name="INFO_VIDEO_MEM_USED" value="3">
- </constant>
- <constant name="LIGHT_VAR_SPOT_ATTENUATION" value="0">
- </constant>
- <constant name="TEXTURE_FLAG_MIPMAPS" value="1">
- </constant>
- <constant name="MATERIAL_FLAG_INVERT_FACES" value="2">
- </constant>
- <constant name="MATERIAL_BLEND_MODE_SUB" value="2">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_DETAIL" value="1">
- </constant>
- <constant name="INSTANCE_ROOM" value="6">
- </constant>
- <constant name="INSTANCE_MESH" value="1">
- </constant>
- <constant name="SCENARIO_DEBUG_DISABLED" value="0">
- </constant>
- <constant name="PARTICLE_VAR_MAX" value="13">
- </constant>
- <constant name="PRIMITIVE_TRIANGLES" value="4">
- </constant>
- <constant name="PRIMITIVE_LINE_STRIP" value="2">
- </constant>
- <constant name="TEXTURE_FLAGS_DEFAULT" value="7">
- </constant>
- <constant name="CUBEMAP_BOTTOM" value="2">
- </constant>
- <constant name="FIXED_MATERIAL_TEXGEN_SCREENZ" value="3">
- </constant>
- <constant name="FIXED_MATERIAL_TEXCOORD_UV2" value="2">
- </constant>
- <constant name="ARRAY_FORMAT_TEX_UV" value="16">
- </constant>
- <constant name="ARRAY_FORMAT_WEIGHTS" value="128">
- </constant>
- <constant name="INFO_MATERIAL_CHANGES_IN_FRAME" value="1">
- </constant>
- <constant name="PARTICLE_SPREAD" value="1">
- </constant>
- <constant name="PARTICLE_LIFETIME" value="0">
- </constant>
- <constant name="PRIMITIVE_TRIANGLE_FAN" value="6">
- </constant>
- <constant name="NO_INDEX_ARRAY" value="-1">
- </constant>
- <constant name="MATERIAL_FLAG_BILLBOARD" value="6">
- </constant>
- <constant name="FIXED_MATERIAL_TEXGEN_LOCAL_XY" value="0">
- </constant>
- <constant name="SCENARIO_DEBUG_OVERDRAW" value="2">
- </constant>
- <constant name="PARTICLE_HEIGHT_SPEED_SCALE" value="12">
- </constant>
- <constant name="PARTICLE_INITIAL_ANGLE" value="10">
- </constant>
- <constant name="PARTICLE_TANGENTIAL_ACCELERATION" value="7">
- </constant>
- <constant name="PRIMITIVE_LINES" value="1">
- </constant>
- <constant name="CUSTOM_ARRAY_SIZE" value="8">
- </constant>
- <constant name="ARRAY_WEIGHTS_SIZE" value="4">
- </constant>
- <constant name="MATERIAL_FLAG_UNSHADED" value="3">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_DIFFUSE" value="0">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_MAX" value="9">
- </constant>
- <constant name="LIGHT_COLOR_SPECULAR" value="2">
- </constant>
- <constant name="MATERIAL_BLEND_MODE_MIX" value="0">
- </constant>
- <constant name="MATERIAL_BLEND_MODE_MUL" value="3">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_EMISSION" value="3">
- </constant>
- <constant name="ARRAY_MAX" value="9">
- </constant>
- <constant name="ARRAY_FORMAT_VERTEX" value="1">
- </constant>
- <constant name="INFO_OBJECTS_IN_FRAME" value="0">
- </constant>
- <constant name="LIGHT_VAR_MAX" value="6">
- </constant>
- <constant name="LIGHT_COLOR_AMBIENT" value="0">
- </constant>
- <constant name="LIGHT_DIRECTIONAL" value="0">
- </constant>
- <constant name="PRIMITIVE_POINTS" value="0">
- </constant>
- <constant name="CUBEMAP_FRONT" value="4">
- </constant>
- <constant name="SHADER_MATERIAL" value="0">
- </constant>
- <constant name="MATERIAL_FLAG_VISIBLE" value="0">
- </constant>
- <constant name="ARRAY_BONES" value="6">
- </constant>
- <constant name="ARRAY_FORMAT_COLOR" value="8">
- </constant>
- <constant name="INSTANCE_PORTAL" value="7">
- </constant>
- <constant name="MAX_CURSORS" value="8">
- </constant>
- <constant name="TEXTURE_FLAG_CUBEMAP" value="8">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_GLOW" value="5">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_NORMAL" value="7">
- </constant>
- <constant name="ARRAY_INDEX" value="8">
- </constant>
- <constant name="INFO_VERTEX_MEM_USED" value="5">
- </constant>
- <constant name="INFO_USAGE_VIDEO_MEM_TOTAL" value="2">
- </constant>
- <constant name="LIGHT_VAR_RADIUS" value="2">
- </constant>
- <constant name="PARTICLE_FINAL_SIZE" value="9">
- </constant>
- <constant name="PARTICLE_INITIAL_SIZE" value="8">
- </constant>
- <constant name="PARTICLE_LINEAR_ACCELERATION" value="5">
- </constant>
- <constant name="CUBEMAP_LEFT" value="0">
- </constant>
- <constant name="MATERIAL_FLAG_ONTOP" value="4">
- </constant>
- <constant name="FIXED_MATERIAL_TEXGEN_SCREEN" value="2">
- </constant>
- <constant name="ARRAY_NORMAL" value="1">
- </constant>
- <constant name="ARRAY_FORMAT_TANGENT" value="4">
- </constant>
- <constant name="INSTANCE_POLY" value="3">
- </constant>
- <constant name="FIXED_MATERIAL_PARAM_SPECULAR_EXP" value="4">
- </constant>
- <constant name="LIGHT_VAR_ENERGY" value="3">
- </constant>
- <constant name="PARTICLE_RADIAL_ACCELERATION" value="6">
- </constant>
- <constant name="PARTICLE_GRAVITY" value="2">
- </constant>
- <constant name="PRIMITIVE_LINE_LOOP" value="3">
- </constant>
- <constant name="MATERIAL_FLAG_WIREFRAME" value="5">
- </constant>
- <constant name="ARRAY_TEX_UV" value="4">
- </constant>
- <constant name="ARRAY_WEIGHTS" value="7">
- </constant>
- <constant name="INFO_TEXTURE_MEM_USED" value="4">
- </constant>
- <constant name="LIGHT_OMNI" value="1">
- </constant>
- <constant name="MAX_PARTICLE_COLOR_PHASES" value="4">
- </constant>
- <constant name="TEXTURE_FLAG_REPEAT" value="2">
- </constant>
- <constant name="CUBEMAP_RIGHT" value="1">
- </constant>
- <constant name="SHADER_POST_PROCESS" value="1">
- </constant>
- <constant name="MATERIAL_FLAG_DOUBLE_SIDED" value="1">
- </constant>
- <constant name="FIXED_MATERIAL_TEXCOORD_UV_TRANSFORM" value="1">
- </constant>
- </constants>
-</class>
-<class name="World" inherits="Resource" category="Resources">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
-</doc>
diff --git a/tools/docdump/doc_dump.cpp b/tools/docdump/doc_dump.cpp
index 5f108ee9c8..f8e035e3fa 100644
--- a/tools/docdump/doc_dump.cpp
+++ b/tools/docdump/doc_dump.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/docdump/doc_dump.h b/tools/docdump/doc_dump.h
index cb18289e31..372f5e0969 100644
--- a/tools/docdump/doc_dump.h
+++ b/tools/docdump/doc_dump.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/docdump/main.css b/tools/docdump/main.css
deleted file mode 100644
index a76e6bbed8..0000000000
--- a/tools/docdump/main.css
+++ /dev/null
@@ -1,146 +0,0 @@
-BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV, SPAN {
- font-family: Arial, Geneva, Helvetica, sans-serif;
-}
-
-a {
-
- text-decoration: none;
-
-}
-
-a:hover {
-
- text-decoration: underline;
-}
-
-td.top_table {
-
- padding: 5px;
-}
-
-div.method_doc {
-
- padding-bottom: 30px;
-}
-
-div.method_description {
- margin-left: 30px;
-}
-
-list.inh_class_list {
- margin-left: 30px;
-
-}
-
-div.inh_class_list {
- margin-left: 30px;
-
-}
-
-div.method_doc div.method {
-
- font-size: 12pt;
- font-weight: bold;
-}
-
-span.funcdecl {
-
- color: #202060;
-}
-
-span.funcdef {
-
- color: #202060;
-}
-
-
-span.qualifier {
-
- font-weight: bold;
-}
-
-
-span.symbol {
-
- /*font-weight: bold;*/
- color: #471870;
-}
-
-
-span.datatype {
-
- color: #6a1533;
-}
-
-tr.category_title {
-
- background-color: #333333;
-}
-a.category_title {
- font-weight: bold;
- color: #FFFFFF;
-}
-
-div.method_list {
-
- margin-left: 30px;
-}
-
-div.constant_list {
-
- margin-left: 30px;
-}
-
-div.member_list {
-
- margin-left: 30px;
-}
-
-div.description {
-
- margin-left: 30px;
-}
-
-div.class_description {
-
- margin-left: 30px;
-}
-
-div.method_list li div {
-
- display: inline;
-}
-
-div.member_list li div.member {
-
- display: inline;
-}
-
-div.constant_list li div.constant {
-
- display: inline;
-}
-
-span.member_description {
-
- font-style: italic;
- color: grey;
-}
-
-span.constant_description {
-
- font-style: italic;
- color: grey;
-}
-
-span.identifier {
-
- font-weight: bold;
-}
-
-
-table.class_table td {
-
- vertical-align: top;
-}
-
diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp
index ace6fda696..cdce910665 100644
--- a/tools/editor/animation_editor.cpp
+++ b/tools/editor/animation_editor.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,6 +34,7 @@
#include "pair.h"
#include "scene/gui/separator.h"
#include "editor_node.h"
+#include "tools/editor/plugins/animation_player_editor_plugin.h"
/* Missing to fix:
*Set
@@ -903,6 +904,23 @@ void AnimationKeyEditor::_menu_track(int p_type) {
optimize_dialog->popup_centered(Size2(250,180));
} break;
+ case TRACK_MENU_CLEAN_UP: {
+
+ cleanup_dialog->popup_centered_minsize(Size2(300,0));
+ } break;
+ case TRACK_MENU_CLEAN_UP_CONFIRM: {
+
+ if (cleanup_all->is_pressed()) {
+ List<StringName> names;
+ AnimationPlayerEditor::singleton->get_player()->get_animation_list(&names);
+ for (List<StringName>::Element *E=names.front();E;E=E->next()) {
+ _cleanup_animation(AnimationPlayerEditor::singleton->get_player()->get_animation(E->get()));
+ }
+ } else {
+ _cleanup_animation(animation);
+
+ }
+ } break;
case CURVE_SET_LINEAR: {
curve_edit->force_transition(1.0);
@@ -933,6 +951,57 @@ void AnimationKeyEditor::_menu_track(int p_type) {
}
+void AnimationKeyEditor::_cleanup_animation(Ref<Animation> p_animation) {
+
+
+ for(int i=0;i<p_animation->get_track_count();i++) {
+
+ bool prop_exists=false;
+ Variant::Type valid_type=Variant::NIL;
+ Object *obj=NULL;
+
+ RES res;
+ Node *node = root->get_node_and_resource(p_animation->track_get_path(i),res);
+
+ if (res.is_valid()) {
+ obj=res.ptr();
+ } else if (node) {
+ obj=node;
+ }
+
+ if (obj && p_animation->track_get_type(i)==Animation::TYPE_VALUE) {
+ valid_type=obj->get_static_property_type(p_animation->track_get_path(i).get_property(),&prop_exists);
+ }
+
+ if (!obj && cleanup_tracks->is_pressed()) {
+
+ p_animation->remove_track(i);
+ i--;
+ continue;
+ }
+
+ if (!prop_exists || p_animation->track_get_type(i)!=Animation::TYPE_VALUE || cleanup_keys->is_pressed()==false)
+ continue;
+
+ for(int j=0;j<p_animation->track_get_key_count(i);j++) {
+
+ Variant v = p_animation->track_get_key_value(i,j);
+
+ if (!Variant::can_convert(v.get_type(),valid_type)) {
+ p_animation->track_remove_key(i,j);
+ j--;
+ }
+ }
+
+ if (p_animation->track_get_key_count(i)==0 && cleanup_tracks->is_pressed()) {
+ p_animation->remove_track(i);
+ i--;
+ }
+ }
+
+ undo_redo->clear_history();
+ _update_paths();
+}
void AnimationKeyEditor::_animation_optimize() {
@@ -1016,6 +1085,7 @@ void AnimationKeyEditor::_track_editor_draw() {
move_up_button->set_disabled(true);
move_down_button->set_disabled(true);
remove_button->set_disabled(true);
+
return;
}
@@ -1042,6 +1112,7 @@ void AnimationKeyEditor::_track_editor_draw() {
timecolor = Color::html("ff4a414f");
Color hover_color = Color(1,1,1,0.05);
Color select_color = Color(1,1,1,0.1);
+ Color invalid_path_color = Color(1,0.6,0.4,0.5);
Color track_select_color =Color::html("ffbd8e8e");
Ref<Texture> remove_icon = get_icon("Remove","EditorIcons");
@@ -1068,6 +1139,9 @@ void AnimationKeyEditor::_track_editor_draw() {
get_icon("KeyCall","EditorIcons")
};
+ Ref<Texture> invalid_icon = get_icon("KeyInvalid","EditorIcons");
+ Ref<Texture> invalid_icon_hover = get_icon("KeyInvalidHover","EditorIcons");
+
Ref<Texture> hsize_icon = get_icon("Hsize","EditorIcons");
Ref<Texture> type_hover=get_icon("KeyHover","EditorIcons");
@@ -1254,6 +1328,23 @@ void AnimationKeyEditor::_track_editor_draw() {
break;
int y = h+i*h+sep;
+ bool prop_exists=false;
+ Variant::Type valid_type=Variant::NIL;
+ Object *obj=NULL;
+
+ RES res;
+ Node *node = root->get_node_and_resource(animation->track_get_path(idx),res);
+
+ if (res.is_valid()) {
+ obj=res.ptr();
+ } else if (node) {
+ obj=node;
+ }
+
+ if (obj && animation->track_get_type(idx)==Animation::TYPE_VALUE) {
+ valid_type=obj->get_static_property_type(animation->track_get_path(idx).get_property(),&prop_exists);
+ }
+
if (/*mouse_over.over!=MouseOver::OVER_NONE &&*/ idx==mouse_over.track) {
Color sepc=hover_color;
@@ -1274,6 +1365,8 @@ void AnimationKeyEditor::_track_editor_draw() {
ncol=track_select_color;
te->draw_string(font,Point2(ofs+Point2(type_icon[0]->get_width()+sep,y+font->get_ascent()+(sep/2))).floor(),np,ncol,name_limit-(type_icon[0]->get_width()+sep)-5);
+ if (!obj)
+ te->draw_line(ofs+Point2(0,y+h/2),ofs+Point2(name_limit,y+h/2),invalid_path_color);
te->draw_line(ofs+Point2(0,y+h),ofs+Point2(size.width,y+h),sepcolor);
@@ -1339,6 +1432,8 @@ void AnimationKeyEditor::_track_editor_draw() {
int kc=animation->track_get_key_count(idx);
bool first=true;
+
+
for(int i=0;i<kc;i++) {
@@ -1386,7 +1481,21 @@ void AnimationKeyEditor::_track_editor_draw() {
}
- te->draw_texture(tex,ofs+Point2(x,y+key_vofs).floor());
+ if (prop_exists && !Variant::can_convert(value.get_type(),valid_type)) {
+ te->draw_texture(invalid_icon,ofs+Point2(x,y+key_vofs).floor());
+ }
+
+ if (prop_exists && !Variant::can_convert(value.get_type(),valid_type)) {
+ if (tex==type_hover)
+ te->draw_texture(invalid_icon_hover,ofs+Point2(x,y+key_vofs).floor());
+ else
+ te->draw_texture(invalid_icon,ofs+Point2(x,y+key_vofs).floor());
+ } else {
+
+ te->draw_texture(tex,ofs+Point2(x,y+key_vofs).floor());
+ }
+
+
first=false;
}
@@ -1594,7 +1703,7 @@ bool AnimationKeyEditor::_edit_if_single_selection() {
if (selection.size()==0) {
curve_edit->set_mode(AnimationCurveEdit::MODE_DISABLED);
- print_line("disable");
+ //print_line("disable");
} else {
curve_edit->set_mode(AnimationCurveEdit::MODE_MULTIPLE);
@@ -1605,13 +1714,13 @@ bool AnimationKeyEditor::_edit_if_single_selection() {
curve_edit->set_multiple(animation->track_get_key_transition(E->key().track,E->key().key));
}
- print_line("multiple");
+ //print_line("multiple");
}
return false;
}
curve_edit->set_mode(AnimationCurveEdit::MODE_SINGLE);
- print_line("regular");
+ //print_line("regular");
int idx = selection.front()->key().track;
int key = selection.front()->key().key;
@@ -2555,6 +2664,8 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) {
String text;
text="time: "+rtos(animation->track_get_key_time(idx,mouse_over.over_key))+"\n";
+
+
switch(animation->track_get_type(idx)) {
case Animation::TYPE_TRANSFORM: {
@@ -2569,8 +2680,33 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) {
} break;
case Animation::TYPE_VALUE: {
- Variant v = animation->track_get_key_value(idx,mouse_over.over_key);
- text+="value: "+String(v)+"\n";
+ Variant v = animation->track_get_key_value(idx,mouse_over.over_key);;
+ //text+="value: "+String(v)+"\n";
+
+ bool prop_exists=false;
+ Variant::Type valid_type=Variant::NIL;
+ Object *obj=NULL;
+
+ RES res;
+ Node *node = root->get_node_and_resource(animation->track_get_path(idx),res);
+
+ if (res.is_valid()) {
+ obj=res.ptr();
+ } else if (node) {
+ obj=node;
+ }
+
+ if (obj) {
+ valid_type=obj->get_static_property_type(animation->track_get_path(idx).get_property(),&prop_exists);
+ }
+
+ text+="type: "+Variant::get_type_name(v.get_type())+"\n";
+ if (prop_exists && !Variant::can_convert(v.get_type(),valid_type)) {
+ text+="value: "+String(v)+" (Invalid, expected type: "+Variant::get_type_name(valid_type)+")\n";
+ } else {
+ text+="value: "+String(v)+"\n";
+ }
+
} break;
case Animation::TYPE_METHOD: {
@@ -2593,6 +2729,9 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) {
} break;
}
text+="easing: "+rtos(animation->track_get_key_transition(idx,mouse_over.over_key));
+
+
+
track_editor->set_tooltip(text);
return;
@@ -2668,9 +2807,15 @@ void AnimationKeyEditor::_notification(int p_what) {
switch(p_what) {
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+
+ EditorNode::get_singleton()->update_keying();
+ } break;
case NOTIFICATION_ENTER_TREE: {
+ key_editor->edit(key_edit);
+
zoomicon->set_texture( get_icon("Zoom","EditorIcons") );
menu_add_track->set_icon(get_icon("AddTrack","EditorIcons"));
@@ -2703,6 +2848,7 @@ void AnimationKeyEditor::_notification(int p_what) {
//menu_track->get_popup()->add_submenu_item("Set Transitions..","Transitions");
//menu_track->get_popup()->add_separator();
menu_track->get_popup()->add_item("Optimize Animation",TRACK_MENU_OPTIMIZE);
+ menu_track->get_popup()->add_item("Clean-Up Animation",TRACK_MENU_CLEAN_UP);
curve_linear->set_icon(get_icon("CurveLinear","EditorIcons"));
curve_in->set_icon(get_icon("CurveIn","EditorIcons"));
@@ -2849,6 +2995,8 @@ void AnimationKeyEditor::set_animation(const Ref<Animation>& p_anim) {
_update_menu();
selected_track=-1;
_edit_if_single_selection();
+
+ EditorNode::get_singleton()->update_keying();
}
void AnimationKeyEditor::set_root(Node *p_root) {
@@ -2878,13 +3026,13 @@ void AnimationKeyEditor::set_keying(bool p_enabled) {
keying=p_enabled;
_update_menu();
- emit_signal("keying_changed",p_enabled);
+ emit_signal("keying_changed");
}
bool AnimationKeyEditor::has_keying() const {
- return keying;
+ return is_visible() && animation.is_valid();
}
void AnimationKeyEditor::_query_insert(const InsertData& p_id) {
@@ -3213,6 +3361,7 @@ Ref<Animation> AnimationKeyEditor::get_current_animation() const {
void AnimationKeyEditor::_animation_len_changed(float p_len) {
+
if (updating)
return;
@@ -3340,8 +3489,10 @@ void AnimationKeyEditor::_insert_delay() {
void AnimationKeyEditor::_step_changed(float p_len) {
updating=true;
- if (!animation.is_null())
+ if (!animation.is_null()) {
animation->set_step(p_len);
+ emit_signal("animation_step_changed",animation->get_step());
+ }
updating=false;
}
@@ -3552,21 +3703,33 @@ void AnimationKeyEditor::_bind_methods() {
ADD_SIGNAL( MethodInfo("keying_changed" ) );
ADD_SIGNAL( MethodInfo("timeline_changed", PropertyInfo(Variant::REAL,"pos") ) );
ADD_SIGNAL( MethodInfo("animation_len_changed", PropertyInfo(Variant::REAL,"len") ) );
+ ADD_SIGNAL( MethodInfo("animation_step_changed", PropertyInfo(Variant::REAL,"step") ) );
ADD_SIGNAL( MethodInfo("key_edited", PropertyInfo(Variant::INT,"track"), PropertyInfo(Variant::INT,"key") ) );
}
-AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_history,EditorSelection *p_selection) {
+AnimationKeyEditor::AnimationKeyEditor() {
alc="animation_len_changed";
- editor_selection=p_selection;
+ editor_selection=EditorNode::get_singleton()->get_editor_selection();
selected_track=-1;
updating=false;
te_drawing=false;
- undo_redo=p_undo_redo;
- history=p_history;
+ undo_redo=EditorNode::get_singleton()->get_undo_redo();
+ history=EditorNode::get_singleton()->get_editor_history();
+
+ ec = memnew (Control);
+ ec->set_custom_minimum_size(Size2(0,150));
+ add_child(ec);
+ ec->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ h_scroll = memnew( HScrollBar );
+ h_scroll->connect("value_changed",this,"_scroll_changed");
+ add_child(h_scroll);
+ h_scroll->set_val(0);
+
HBoxContainer *hb = memnew( HBoxContainer );
add_child(hb);
@@ -3724,10 +3887,6 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h
// menu->get_popup()->connect("item_pressed",this,"_menu_callback");
- ec = memnew (Control);
- ec->set_custom_minimum_size(Size2(0,150));
- add_child(ec);
- ec->set_v_size_flags(SIZE_EXPAND_FILL);
hb = memnew( HBoxContainer);
hb->set_area_as_parent_rect();
@@ -3767,7 +3926,7 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h
key_edit = memnew( AnimationKeyEdit );
key_edit->undo_redo=undo_redo;
//key_edit->ke_dialog=key_edit_dialog;
- key_editor->edit(key_edit);
+
type_menu = memnew( PopupMenu );
add_child(type_menu);
for(int i=0;i<Variant::VARIANT_MAX;i++)
@@ -3804,12 +3963,6 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h
curve_edit->set_v_size_flags(SIZE_EXPAND_FILL);
key_editor_tab->add_child(curve_vb);
- h_scroll = memnew( HScrollBar );
- h_scroll->connect("value_changed",this,"_scroll_changed");
- add_child(h_scroll);
- h_scroll->set_val(0);
-
-
track_name = memnew( LineEdit );
track_name->set_as_toplevel(true);
track_name->hide();
@@ -3862,6 +4015,33 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h
add_child(call_select);
call_select->set_title("Call Functions in Which Node?");
+ cleanup_dialog = memnew( ConfirmationDialog );
+ add_child(cleanup_dialog);
+ VBoxContainer *cleanup_vb = memnew( VBoxContainer );
+ cleanup_dialog->add_child(cleanup_vb);
+ cleanup_dialog->set_child_rect(cleanup_vb);
+ cleanup_keys = memnew( CheckButton );
+ cleanup_keys->set_text("Remove invalid keys");
+ cleanup_keys->set_pressed(true);
+ cleanup_vb->add_child(cleanup_keys);
+
+ cleanup_tracks = memnew( CheckButton );
+ cleanup_tracks->set_text("Remove unresolved and empty tracks");
+ cleanup_tracks->set_pressed(true);
+ cleanup_vb->add_child(cleanup_tracks);
+
+ cleanup_all = memnew( CheckButton );
+ cleanup_all->set_text("Clean-Up all animations");
+ cleanup_vb->add_child(cleanup_all);
+
+ cleanup_dialog->set_title("Clean up Animation(s) (NO UNDO!)");
+ cleanup_dialog->get_ok()->set_text("Clean-Up");
+
+ cleanup_dialog->connect("confirmed",this,"_menu_track",varray(TRACK_MENU_CLEAN_UP_CONFIRM));
+
+ add_constant_override("separation",get_constant("separation","VBoxContainer"));
+
+
}
AnimationKeyEditor::~AnimationKeyEditor() {
diff --git a/tools/editor/animation_editor.h b/tools/editor/animation_editor.h
index 629377d78e..c8a539179e 100644
--- a/tools/editor/animation_editor.h
+++ b/tools/editor/animation_editor.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -89,6 +89,8 @@ class AnimationKeyEditor : public VBoxContainer {
TRACK_MENU_NEXT_STEP,
TRACK_MENU_PREV_STEP,
TRACK_MENU_OPTIMIZE,
+ TRACK_MENU_CLEAN_UP,
+ TRACK_MENU_CLEAN_UP_CONFIRM,
CURVE_SET_LINEAR,
CURVE_SET_IN,
CURVE_SET_OUT,
@@ -190,6 +192,11 @@ class AnimationKeyEditor : public VBoxContainer {
SpinBox *optimize_angular_error;
SpinBox *optimize_max_angle;
+ ConfirmationDialog *cleanup_dialog;
+ CheckButton *cleanup_keys;
+ CheckButton *cleanup_tracks;
+ CheckButton *cleanup_all;
+
SpinBox *step;
MenuButton *menu_add_track;
@@ -255,7 +262,7 @@ class AnimationKeyEditor : public VBoxContainer {
EditorSelection *editor_selection;
- AnimationKeyEditor();
+
float _get_zoom_scale() const;
@@ -284,6 +291,7 @@ class AnimationKeyEditor : public VBoxContainer {
void _animation_changed();
void _animation_optimize();
+ void _cleanup_animation(Ref<Animation> p_animation);
void _scroll_changed(double);
@@ -326,7 +334,7 @@ public:
void insert_value_key(const String& p_property, const Variant& p_value, bool p_advance);
void insert_transform_key(Spatial *p_node,const String& p_sub,const Transform& p_xform);
- AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_history, EditorSelection *p_selection);
+ AnimationKeyEditor();
~AnimationKeyEditor();
};
diff --git a/tools/editor/array_property_edit.cpp b/tools/editor/array_property_edit.cpp
index 9cd443270b..66c2782da5 100644
--- a/tools/editor/array_property_edit.cpp
+++ b/tools/editor/array_property_edit.cpp
@@ -72,6 +72,15 @@ bool ArrayPropertyEdit::_set(const StringName& p_name, const Variant& p_value){
ur->add_undo_method(this,"_set_value",i,arr.get(i));
}
+ } else if (newsize>size && size) {
+
+ Variant init;
+ Variant::CallError ce;
+ init = Variant::construct(arr.get(size-1).get_type(),NULL,0,ce);
+ for(int i=size;i<newsize;i++) {
+ ur->add_do_method(this,"_set_value",i,init);
+ }
+
}
ur->add_do_method(this,"_notif_change");
ur->add_undo_method(this,"_notif_change");
@@ -83,6 +92,7 @@ bool ArrayPropertyEdit::_set(const StringName& p_name, const Variant& p_value){
_change_notify();
return true;
}
+
} else if (pn.begins_with("indices")) {
if (pn.find("_")!=-1) {
@@ -209,6 +219,15 @@ void ArrayPropertyEdit::edit(Object* p_obj,const StringName& p_prop,Variant::Typ
}
+Node *ArrayPropertyEdit::get_node() {
+
+ Object *o = ObjectDB::get_instance(obj);
+ if (!o)
+ return NULL;
+
+ return o->cast_to<Node>();
+}
+
void ArrayPropertyEdit::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_set_size"),&ArrayPropertyEdit::_set_size);
diff --git a/tools/editor/array_property_edit.h b/tools/editor/array_property_edit.h
index acfb8e68ed..948b2a71a3 100644
--- a/tools/editor/array_property_edit.h
+++ b/tools/editor/array_property_edit.h
@@ -30,6 +30,8 @@ public:
void edit(Object* p_obj, const StringName& p_prop, Variant::Type p_deftype);
+ Node *get_node();
+
ArrayPropertyEdit();
};
diff --git a/tools/editor/call_dialog.cpp b/tools/editor/call_dialog.cpp
index 0e3abcf4ef..edcd7371f2 100644
--- a/tools/editor/call_dialog.cpp
+++ b/tools/editor/call_dialog.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/call_dialog.h b/tools/editor/call_dialog.h
index fe69847796..2d04e7b6cd 100644
--- a/tools/editor/call_dialog.h
+++ b/tools/editor/call_dialog.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/code_editor.cpp b/tools/editor/code_editor.cpp
index 0728b3b7c1..fe863bfebc 100644
--- a/tools/editor/code_editor.cpp
+++ b/tools/editor/code_editor.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -612,6 +612,7 @@ CodeTextEditor::CodeTextEditor() {
if (!font_overrode)
text_editor->add_font_override("font",get_font("source","Fonts"));
+
text_editor->set_show_line_numbers(true);
text_editor->set_brace_matching(true);
text_editor->set_auto_indent(true);
diff --git a/tools/editor/code_editor.h b/tools/editor/code_editor.h
index 0c32aeb68f..5ed7ce9052 100644
--- a/tools/editor/code_editor.h
+++ b/tools/editor/code_editor.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/connections_dialog.cpp b/tools/editor/connections_dialog.cpp
index d4937d7114..1e530b21c2 100644
--- a/tools/editor/connections_dialog.cpp
+++ b/tools/editor/connections_dialog.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -96,7 +96,11 @@ void ConnectDialog::_notification(int p_what) {
RID ci = get_canvas_item();
get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size()));
- }
+ }
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ bind_editor->edit(cdbinds);
+ }
}
void ConnectDialog::_tree_node_selected() {
@@ -456,7 +460,6 @@ ConnectDialog::ConnectDialog() {
set_as_toplevel(true);
cdbinds = memnew( ConnectDialogBinds );
- bind_editor->edit(cdbinds);
error = memnew( ConfirmationDialog );
add_child(error);
diff --git a/tools/editor/connections_dialog.h b/tools/editor/connections_dialog.h
index 4a1c3f189c..d5e228e799 100644
--- a/tools/editor/connections_dialog.h
+++ b/tools/editor/connections_dialog.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/console.cpp b/tools/editor/console.cpp
deleted file mode 100644
index 0c98f05706..0000000000
--- a/tools/editor/console.cpp
+++ /dev/null
@@ -1,386 +0,0 @@
-/*************************************************************************/
-/* console.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "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 "console.h"
-#include "os/os.h"
-#include "os/keyboard.h"
-
-#include "editor_icons.h"
-#include "scene/gui/label.h"
-#include "globals.h"
-
-
-void Console::_stats_update_timer_callback() {
-
- if (!status->is_visible())
- return;
-
- VisualServer *vs = VisualServer::get_singleton();
-
- stats.render_objects_in_frame->set_text(1,String::num(vs->get_render_info( VisualServer::INFO_OBJECTS_IN_FRAME ) ) );
- stats.material_changes_in_frame->set_text(1,String::num(vs->get_render_info( VisualServer::INFO_MATERIAL_CHANGES_IN_FRAME ) ) );
-
- int64_t total_vmem = vs->get_render_info( VisualServer::INFO_USAGE_VIDEO_MEM_TOTAL );
- if (total_vmem<0)
- stats.usage_video_mem_total->set_text(1, "Unknown");
- else
- stats.usage_video_mem_total->set_text(1,String::humanize_size( total_vmem ) );
-
- stats.usage_video_mem_used->set_text(1,String::humanize_size( vs->get_render_info( VisualServer::INFO_VIDEO_MEM_USED ) ) );
- stats.usage_texture_mem_used->set_text(1,String::humanize_size( vs->get_render_info( VisualServer::INFO_TEXTURE_MEM_USED ) ) );
- stats.usage_vertex_mem_used->set_text(1,String::humanize_size( vs->get_render_info( VisualServer::INFO_VERTEX_MEM_USED ) ) );
-
-
- stats.usage_static_memory_total->set_text(1,String::humanize_size( Memory::get_static_mem_available() ) );
- stats.usage_static_memory->set_text(1,String::humanize_size( Memory::get_static_mem_usage() ) );
- stats.usage_dynamic_memory_total->set_text(1,String::humanize_size( Memory::get_dynamic_mem_available() ) );
- stats.usage_dynamic_memory->set_text(1,String::humanize_size( Memory::get_dynamic_mem_usage() ) );
- stats.usage_objects_instanced->set_text(1,String::num( ObjectDB::get_object_count()) );
-
-
-}
-
-void Console::_print_handle(void *p_this,const String& p_string) {
-
-
- return;
- Console *self = (Console*)p_this;
-
- OutputQueue oq;
- oq.text=p_string;
- oq.type=OutputStrings::LINE_NORMAL;
-
-
- if (self->output_queue_mutex)
- self->output_queue_mutex->lock();
-
- self->output_queue.push_back(oq);
-
- if (self->output_queue_mutex)
- self->output_queue_mutex->unlock();
-
-}
-void Console::_error_handle(void *p_this,const char*p_function,const char* p_file,int p_line,const char *p_error, const char *p_explanation,ErrorHandlerType p_type) {
-
-
- Console *self = (Console*)p_this;
-
- OutputQueue oq;
- oq.text="ERROR: "+String(p_file)+":"+itos(p_line)+", in function: "+String(p_function);
- oq.text+="\n "+String(p_error)+".";
- if (p_explanation && p_explanation[0])
- oq.text+="\n Reason: "+String(p_explanation);
- oq.text+="\n";
- oq.type=OutputStrings::LINE_ERROR;
-
-
- if (self->output_queue_mutex)
- self->output_queue_mutex->lock();
-
- self->output_queue.push_back(oq);
-
- if (self->output_queue_mutex)
- self->output_queue_mutex->unlock();
-
-
-}
-
-void Console::_window_input_event(InputEvent p_event) {
-
- Control::_window_input_event(p_event);
-
- if (p_event.type==InputEvent::KEY && p_event.key.pressed) {
-
- if (p_event.key.scancode==KEY_QUOTELEFT && p_event.key.mod.control) {
-
- if (is_visible())
- hide();
- else {
- globals_property_editor->edit( NULL );
- globals_property_editor->edit( Globals::get_singleton() );
- show();
- };
- }
-
- if (p_event.key.scancode==KEY_ESCAPE && !window_has_modal_stack() && is_visible()) {
- hide();
- get_tree()->call_group(0,"windows","_cancel_input_ID",p_event.ID);
- }
-
-
- }
-}
-
-void Console::_window_resize_event() {
-
-// Control::_window_resize_event();
- _resized();
-}
-
-
-void Console::_resized() {
-
- set_pos( Point2( 0, OS::get_singleton()->get_video_mode().height-height) );
- set_size( Size2( OS::get_singleton()->get_video_mode().width, height) );
-}
-
-void Console::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_ENTER_TREE: {
-
- _resized();
- show();
- globals_property_editor->edit( Globals::get_singleton() );
-
- } break;
-
- case NOTIFICATION_PROCESS: {
- //pop messies
-
- if (output_queue_mutex)
- output_queue_mutex->lock();
-
- while(output_queue.size()) {
-
- OutputQueue q = output_queue.front()->get();
- if (q.type==OutputStrings::LINE_ERROR || q.type==OutputStrings::LINE_WARNING)
- errors->add_line(q.text,q.meta,q.type);
- output->add_line(q.text,q.meta,q.type);
- output_queue.pop_front();
- }
-
- if (output_queue_mutex)
- output_queue_mutex->unlock();
-
- } break;
- case NOTIFICATION_DRAW: {
-
- RID ci = get_canvas_item();
- get_stylebox("panel","Panel")->draw(ci,Rect2(Point2(),get_size()));
-
- } break;
- }
-}
-
-
-void Console::_close_pressed() {
-
- hide();
-}
-
-void Console::_inspector_node_selected() {
-
-
- Node *node = inspect_tree_editor->get_selected();
-
- if (!node)
- inspect_property_editor->edit(NULL);
- else {
-
- inspect_history.add_object(node->get_instance_ID());
-
- inspect_property_editor->edit(node);
- }
-
-}
-
-void Console::_bind_methods() {
-
- ObjectTypeDB::bind_method("_stats_update_timer_callback",&Console::_stats_update_timer_callback);
- ObjectTypeDB::bind_method("_close_pressed",&Console::_close_pressed);
- ObjectTypeDB::bind_method("_inspector_node_selected",&Console::_inspector_node_selected);
-}
-
-
-Console::Console() {
-
- Ref<Theme> theme( memnew( Theme ) );
- set_theme( theme );
- editor_register_icons(theme);
-
- height=300;
- tabs = memnew( TabContainer );
- tabs->set_tab_align(TabContainer::ALIGN_LEFT);
- add_child(tabs);
- tabs->set_area_as_parent_rect();
-
- output = memnew( OutputStrings );
- output->set_name("Output");
- tabs->add_child(output);
- errors = memnew( OutputStrings );
- errors->set_name("Errors");
- tabs->add_child(errors);
- status = memnew( Control );
- status->set_name("Stats");
- tabs->add_child(status);
- inspect = memnew( Control );
- inspect->set_name("Inspect");
- tabs->add_child(inspect);
- globals = memnew( Control );
- globals->set_name("Globals");
- tabs->add_child(globals);
-
- // stats
-
- stats_tree = memnew( Tree );
- stats_tree->set_hide_root(true);
- stats_tree->set_columns(2);
- status->add_child(stats_tree);
- stats_tree->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
- stats_tree->set_anchor( MARGIN_RIGHT, ANCHOR_RATIO );
- stats_tree->set_margin( MARGIN_RIGHT, 0.5 );
- stats_tree->set_begin( Point2( 20,25 ) );
- stats_tree->set_end( Point2( 0.5,5 ) );
-
- Label *stats_label = memnew( Label );
- stats_label->set_text("Engine Statistics:");
- stats_label->set_pos( Point2( 5,5 ) );
- status->add_child(stats_label);
-
- TreeItem *stats_tree_root = stats_tree->create_item(NULL);
-
- {
- //system items
- TreeItem *system_item = stats_tree->create_item(stats_tree_root);
- system_item->set_text(0,"System");
-
- stats.usage_static_memory_total = stats_tree->create_item(system_item);
- stats.usage_static_memory_total->set_text(0,"Total Static Mem");;
- stats.usage_static_memory = stats_tree->create_item(system_item);
- stats.usage_static_memory->set_text(0,"Static Mem Usage");;
- stats.usage_dynamic_memory_total = stats_tree->create_item(system_item);
- stats.usage_dynamic_memory_total->set_text(0,"Total Dynamic Mem");;
- stats.usage_dynamic_memory = stats_tree->create_item(system_item);
- stats.usage_dynamic_memory->set_text(0,"Dynamic Mem Usage");
- stats.usage_objects_instanced = stats_tree->create_item(system_item);
- stats.usage_objects_instanced->set_text(0,"Instanced Objects");
-
- //render items
- TreeItem *render_item = stats_tree->create_item(stats_tree_root);
- render_item->set_text(0,"Render");
- stats.render_objects_in_frame = stats_tree->create_item(render_item);
- stats.render_objects_in_frame->set_text(0,"Visible Objects");
- stats.material_changes_in_frame = stats_tree->create_item(render_item);
- stats.material_changes_in_frame->set_text(0,"Material Changes");
- stats.usage_video_mem_total = stats_tree->create_item(render_item);
- stats.usage_video_mem_total->set_text(0,"Total Video Mem");
- stats.usage_texture_mem_used = stats_tree->create_item(render_item);
- stats.usage_texture_mem_used->set_text(0,"Texture Mem Usage");
- stats.usage_vertex_mem_used = stats_tree->create_item(render_item);
- stats.usage_vertex_mem_used->set_text(0,"Vertex Mem Usage");
- stats.usage_video_mem_used = stats_tree->create_item(render_item);
- stats.usage_video_mem_used->set_text(0,"Combined Mem Usage");
- }
-
- {
-
- inspect_tree_editor = memnew( SceneTreeEditor );
- inspect_tree_editor->set_anchor( MARGIN_RIGHT, ANCHOR_RATIO );
- inspect_tree_editor->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
- inspect_tree_editor->set_begin( Point2( 20, 5 ) );
- inspect_tree_editor->set_end( Point2( 0.49, 5 ) );
- inspect->add_child(inspect_tree_editor);
-
- inspect_property_editor = memnew( PropertyEditor );
- inspect_property_editor->set_anchor( MARGIN_LEFT, ANCHOR_RATIO );
- inspect_property_editor->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- inspect_property_editor->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
- inspect_property_editor->set_begin( Point2( 0.51, 5 ) );
- inspect_property_editor->set_end( Point2( 5, 5 ) );
- inspect->add_child(inspect_property_editor);
- }
-
-
- { //globals
-
- globals_property_editor = memnew( PropertyEditor );
- globals_property_editor->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- globals_property_editor->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
- globals_property_editor->set_begin( Point2( 15, 5 ) );
- globals_property_editor->set_end( Point2( 5, 5 ) );
- globals_property_editor->get_top_label()->set_text("Globals Editor:");
- globals->add_child(globals_property_editor);
-
- }
-
-
-#ifndef NO_THREADS
- output_queue_mutex = Mutex::create();
-#else
- output_queue_mutex = NULL;
-#endif
-
-
- hide();
- set_process(true);
-
- close = memnew( Button );
- add_child(close);
- close->set_anchor( MARGIN_LEFT, ANCHOR_END);
- close->set_anchor( MARGIN_RIGHT, ANCHOR_END);
- close->set_begin( Point2( 25, 3 ) );
- close->set_end( Point2( 5, 3 ) );
- close->set_flat(true);
- close->connect("pressed", this,"_close_pressed");
-
-
- close->set_icon( get_icon("close","Icons") );
-// force_top_viewport(true);
-
-
- err_handler.userdata=this;
- err_handler.errfunc=_error_handle;
- add_error_handler(&err_handler);
-
- print_handler.userdata=this;
- print_handler.printfunc=_print_handle;
- add_print_handler(&print_handler);
-
- Timer *timer = memnew( Timer );
- add_child(timer);
- timer->set_wait_time(1);
- timer->start();
- timer->connect("timeout", this,"_stats_update_timer_callback");
- inspect_tree_editor->connect("node_selected", this,"_inspector_node_selected");
-
-
-
-}
-
-
-Console::~Console() {
-
- if (output_queue_mutex)
- memdelete(output_queue_mutex);
-
- remove_error_handler(&err_handler);
- remove_print_handler(&print_handler);
-
-}
diff --git a/tools/editor/create_dialog.cpp b/tools/editor/create_dialog.cpp
index a9119349c8..0f39d72308 100644
--- a/tools/editor/create_dialog.cpp
+++ b/tools/editor/create_dialog.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/create_dialog.h b/tools/editor/create_dialog.h
index f200e1caf5..6f959fd467 100644
--- a/tools/editor/create_dialog.h
+++ b/tools/editor/create_dialog.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/default_saver.cpp b/tools/editor/default_saver.cpp
index c865adb1eb..611232e04b 100644
--- a/tools/editor/default_saver.cpp
+++ b/tools/editor/default_saver.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/default_saver.h b/tools/editor/default_saver.h
index 4e11ff5592..2b1a1edb23 100644
--- a/tools/editor/default_saver.h
+++ b/tools/editor/default_saver.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/doc_code_font.h b/tools/editor/doc_code_font.h
index 91f67c4a41..879c873ea1 100644
--- a/tools/editor/doc_code_font.h
+++ b/tools/editor/doc_code_font.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/doc_font.h b/tools/editor/doc_font.h
index f2e5e7950b..a3c3b58b21 100644
--- a/tools/editor/doc_font.h
+++ b/tools/editor/doc_font.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/doc_title_font.h b/tools/editor/doc_title_font.h
index fb6b4eaf5b..75a3f049f0 100644
--- a/tools/editor/doc_title_font.h
+++ b/tools/editor/doc_title_font.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_data.cpp b/tools/editor/editor_data.cpp
index 673ee30adb..c872b1c3ca 100644
--- a/tools/editor/editor_data.cpp
+++ b/tools/editor/editor_data.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,6 +31,9 @@
#include "editor_settings.h"
#include "os/dir_access.h"
#include "io/resource_loader.h"
+#include "scene/resources/packed_scene.h"
+#include "os/file_access.h"
+#include "editor_node.h"
void EditorHistory::_cleanup_history() {
@@ -338,6 +341,14 @@ void EditorData::set_editor_states(const Dictionary& p_states) {
}
+void EditorData::notify_edited_scene_changed() {
+
+ for(int i=0;i<editor_plugins.size();i++) {
+
+ editor_plugins[i]->edited_scene_changed();
+ }
+}
+
void EditorData::clear_editor_states() {
for(int i=0;i<editor_plugins.size();i++) {
@@ -485,6 +496,93 @@ void EditorData::remove_scene(int p_idx){
edited_scene.remove(p_idx);
}
+
+bool EditorData::_find_updated_instances(Node* p_root,Node *p_node,Set<String> &checked_paths) {
+
+// if (p_root!=p_node && p_node->get_owner()!=p_root && !p_root->is_editable_instance(p_node->get_owner()))
+// return false;
+
+ Ref<SceneState> ss;
+
+ if (p_node==p_root) {
+ ss=p_node->get_scene_inherited_state();
+ } else if (p_node->get_filename()!=String()){
+ ss=p_node->get_scene_instance_state();
+ }
+
+ if (ss.is_valid()) {
+ String path = ss->get_path();
+
+ if (!checked_paths.has(path)) {
+
+ uint64_t modified_time = FileAccess::get_modified_time(path);
+ if (modified_time!=ss->get_last_modified_time()) {
+ return true; //external scene changed
+ }
+
+ checked_paths.insert(path);
+ }
+
+ }
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+ bool found = _find_updated_instances(p_root,p_node->get_child(i),checked_paths);
+ if (found)
+ return true;
+ }
+
+ return false;
+}
+
+
+bool EditorData::check_and_update_scene(int p_idx) {
+
+ ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),false);
+ if (!edited_scene[p_idx].root)
+ return false;
+
+ Set<String> checked_scenes;
+
+
+ bool must_reload = _find_updated_instances(edited_scene[p_idx].root,edited_scene[p_idx].root,checked_scenes);
+
+ if (must_reload) {
+ Ref<PackedScene> pscene;
+ pscene.instance();
+
+ EditorProgress ep("update_scene","Updating Scene",2);
+ ep.step("Storing local changes..",0);
+ //pack first, so it stores diffs to previous version of saved scene
+ Error err = pscene->pack(edited_scene[p_idx].root);
+ ERR_FAIL_COND_V(err!=OK,false);
+ ep.step("Updating scene..",1);
+ Node *new_scene = pscene->instance(true);
+ ERR_FAIL_COND_V(!new_scene,false);
+
+ //transfer selection
+ List<Node*> new_selection;
+ for (List<Node*>::Element *E=edited_scene[p_idx].selection.front();E;E=E->next()) {
+ NodePath p = edited_scene[p_idx].root->get_path_to(E->get());
+ Node *new_node = new_scene->get_node(p);
+ if (new_node)
+ new_selection.push_back(new_node);
+ }
+
+ new_scene->set_filename( edited_scene[p_idx].root->get_filename() );
+
+ memdelete(edited_scene[p_idx].root);
+ edited_scene[p_idx].root=new_scene;
+ edited_scene[p_idx].selection=new_selection;
+
+ return true;
+
+ }
+
+ return false;
+
+}
+
int EditorData::get_edited_scene() const {
return current_edited_scene;
@@ -537,6 +635,16 @@ String EditorData::get_scene_type(int p_idx) const {
return edited_scene[p_idx].root->get_type();
}
+void EditorData::move_edited_scene_to_index(int p_idx) {
+
+ ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());
+ ERR_FAIL_INDEX(p_idx,edited_scene.size());
+
+ EditedScene es=edited_scene[current_edited_scene];
+ edited_scene.remove(current_edited_scene);
+ edited_scene.insert(p_idx,es);
+ current_edited_scene=p_idx;
+}
Ref<Script> EditorData::get_scene_root_script(int p_idx) const {
diff --git a/tools/editor/editor_data.h b/tools/editor/editor_data.h
index c5ee83ae63..fcc8ccef06 100644
--- a/tools/editor/editor_data.h
+++ b/tools/editor/editor_data.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -144,6 +144,8 @@ private:
Vector<EditedScene> edited_scene;
int current_edited_scene;
+ bool _find_updated_instances(Node* p_root,Node *p_node,Set<String> &checked_paths);
+
public:
EditorPlugin* get_editor(Object *p_object);
@@ -193,6 +195,8 @@ public:
void clear_edited_scenes();
void set_edited_scene_live_edit_root(const NodePath& p_root);
NodePath get_edited_scene_live_edit_root();
+ bool check_and_update_scene(int p_idx);
+ void move_edited_scene_to_index(int p_idx);
void set_plugin_window_layout(Ref<ConfigFile> p_layout);
@@ -200,6 +204,7 @@ public:
void save_edited_scene_state(EditorSelection *p_selection,EditorHistory *p_history,const Dictionary& p_custom);
Dictionary restore_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history);
+ void notify_edited_scene_changed();
EditorData();
diff --git a/tools/editor/editor_dir_dialog.cpp b/tools/editor/editor_dir_dialog.cpp
index a8421acff8..8512154485 100644
--- a/tools/editor/editor_dir_dialog.cpp
+++ b/tools/editor/editor_dir_dialog.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -205,31 +205,36 @@ void EditorDirDialog::_bind_methods() {
EditorDirDialog::EditorDirDialog() {
+ updating=false;
+
set_title("Choose a Directory");
+ set_hide_on_ok(false);
+
tree = memnew( Tree );
add_child(tree);
set_child_rect(tree);
- updating=false;
- get_ok()->set_text("Choose");
- set_hide_on_ok(false);
-
-
+ tree->connect("item_activated",this,"_ok");
makedir = add_button("Create Folder",OS::get_singleton()->get_swap_ok_cancel()?true:false,"makedir");
makedir->connect("pressed",this,"_make_dir");
makedialog = memnew( ConfirmationDialog );
makedialog->set_title("Create Folder");
+ add_child(makedialog);
+
VBoxContainer *makevb= memnew( VBoxContainer );
makedialog->add_child(makevb);
makedialog->set_child_rect(makevb);
+
makedirname = memnew( LineEdit );
makevb->add_margin_child("Name:",makedirname);
- add_child(makedialog);
makedialog->register_text_enter(makedirname);
makedialog->connect("confirmed",this,"_make_dir_confirm");
+
mkdirerr = memnew( AcceptDialog );
mkdirerr->set_text("Could not create folder.");
add_child(mkdirerr);
+ get_ok()->set_text("Choose");
+
}
diff --git a/tools/editor/editor_dir_dialog.h b/tools/editor/editor_dir_dialog.h
index 8ac83b86e8..1c2593219c 100644
--- a/tools/editor/editor_dir_dialog.h
+++ b/tools/editor/editor_dir_dialog.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_file_dialog.cpp b/tools/editor/editor_file_dialog.cpp
index c62347d129..a9b23767f1 100644
--- a/tools/editor/editor_file_dialog.cpp
+++ b/tools/editor/editor_file_dialog.cpp
@@ -6,6 +6,8 @@
#include "editor_resource_preview.h"
#include "editor_settings.h"
#include "scene/gui/margin_container.h"
+#include "os/file_access.h"
+
EditorFileDialog::GetIconFunc EditorFileDialog::get_icon_func=NULL;
EditorFileDialog::GetIconFunc EditorFileDialog::get_large_icon_func=NULL;
@@ -27,14 +29,14 @@ void EditorFileDialog::_notification(int p_what) {
dir_prev->set_icon(get_icon("ArrowLeft","EditorIcons"));
dir_next->set_icon(get_icon("ArrowRight","EditorIcons"));
dir_up->set_icon(get_icon("ArrowUp","EditorIcons"));
+ refresh->set_icon(get_icon("Reload","EditorIcons"));
favorite->set_icon(get_icon("Favorites","EditorIcons"));
fav_up->set_icon(get_icon("MoveUp","EditorIcons"));
fav_down->set_icon(get_icon("MoveDown","EditorIcons"));
fav_rm->set_icon(get_icon("RemoveSmall","EditorIcons"));
- }
- if (p_what==NOTIFICATION_PROCESS) {
+ } else if (p_what==NOTIFICATION_PROCESS) {
if (preview_waiting) {
preview_wheel_timeout-=get_process_delta_time();
@@ -47,12 +49,57 @@ void EditorFileDialog::_notification(int p_what) {
preview_wheel_timeout=0.1;
}
}
- }
-
- if (p_what==NOTIFICATION_DRAW) {
+ } else if (p_what==NOTIFICATION_DRAW) {
//RID ci = get_canvas_item();
//get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size()));
+ } else if (p_what==NOTIFICATION_POPUP_HIDE) {
+
+ set_process_unhandled_input(false);
+
+ } else if (p_what==EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
+
+ bool show_hidden=EditorSettings::get_singleton()->get("file_dialog/show_hidden_files");
+ if (show_hidden_files!=show_hidden)
+ set_show_hidden_files(show_hidden);
+ set_display_mode((DisplayMode)EditorSettings::get_singleton()->get("file_dialog/display_mode").operator int());
+ }
+}
+
+void EditorFileDialog::_unhandled_input(const InputEvent& p_event) {
+
+ if (p_event.type==InputEvent::KEY && is_window_modal_on_top()) {
+
+ const InputEventKey &k=p_event.key;
+
+ if (k.pressed) {
+
+ bool handled=true;
+
+ switch (k.scancode) {
+
+ case KEY_H: {
+
+ if (k.mod.command) {
+
+ bool show=!show_hidden_files;
+ set_show_hidden_files(show);
+ EditorSettings::get_singleton()->set("file_dialog/show_hidden_files",show);
+ } else {
+ handled=false;
+ }
+
+ } break;
+ case KEY_F5: {
+
+ invalidate();
+ } break;
+ default: { handled=false; }
+ }
+
+ if (handled)
+ accept_event();
+ }
}
}
@@ -147,6 +194,8 @@ void EditorFileDialog::_post_popup() {
_update_favorites();
}
+ set_process_unhandled_input(true);
+
}
void EditorFileDialog::_thumbnail_result(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata) {
@@ -189,6 +238,9 @@ void EditorFileDialog::_thumbnail_done(const String& p_path,const Ref<Texture>&
void EditorFileDialog::_request_single_thumbnail(const String& p_path) {
+ if (!FileAccess::exists(p_path))
+ return;
+
EditorResourcePreview::get_singleton()->queue_resource_preview(p_path,this,"_thumbnail_done",p_path);
//print_line("want file "+p_path);
set_process(true);
@@ -430,6 +482,8 @@ void EditorFileDialog::update_file_list() {
}
+ String cdir = dir_access->get_current_dir();
+ bool skip_pp = access==ACCESS_RESOURCES && cdir=="res://";
dir_access->list_dir_begin();
@@ -450,7 +504,7 @@ void EditorFileDialog::update_file_list() {
if (show_hidden || !ishidden) {
if (!isdir)
files.push_back(item);
- else
+ else if (item!=".." || !skip_pp)
dirs.push_back(item);
}
}
@@ -1012,7 +1066,9 @@ void EditorFileDialog::_go_forward(){
}
-bool EditorFileDialog::default_show_hidden_files=true;
+bool EditorFileDialog::default_show_hidden_files=false;
+
+EditorFileDialog::DisplayMode EditorFileDialog::default_display_mode=DISPLAY_THUMBNAILS;
void EditorFileDialog::set_display_mode(DisplayMode p_mode) {
@@ -1038,6 +1094,8 @@ EditorFileDialog::DisplayMode EditorFileDialog::get_display_mode() const{
void EditorFileDialog::_bind_methods() {
+ ObjectTypeDB::bind_method(_MD("_unhandled_input"),&EditorFileDialog::_unhandled_input);
+
ObjectTypeDB::bind_method(_MD("_item_selected"),&EditorFileDialog::_item_selected);
ObjectTypeDB::bind_method(_MD("_item_db_selected"),&EditorFileDialog::_item_dc_selected);
ObjectTypeDB::bind_method(_MD("_dir_entered"),&EditorFileDialog::_dir_entered);
@@ -1060,7 +1118,7 @@ void EditorFileDialog::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_vbox:VBoxContainer"),&EditorFileDialog::get_vbox);
ObjectTypeDB::bind_method(_MD("set_access","access"),&EditorFileDialog::set_access);
ObjectTypeDB::bind_method(_MD("get_access"),&EditorFileDialog::get_access);
- ObjectTypeDB::bind_method(_MD("set_show_hidden_files"),&EditorFileDialog::set_show_hidden_files);
+ ObjectTypeDB::bind_method(_MD("set_show_hidden_files","show"),&EditorFileDialog::set_show_hidden_files);
ObjectTypeDB::bind_method(_MD("is_showing_hidden_files"),&EditorFileDialog::is_showing_hidden_files);
ObjectTypeDB::bind_method(_MD("_select_drive"),&EditorFileDialog::_select_drive);
ObjectTypeDB::bind_method(_MD("_make_dir"),&EditorFileDialog::_make_dir);
@@ -1113,6 +1171,10 @@ void EditorFileDialog::set_default_show_hidden_files(bool p_show) {
default_show_hidden_files=p_show;
}
+void EditorFileDialog::set_default_display_mode(DisplayMode p_mode) {
+ default_display_mode=p_mode;
+}
+
void EditorFileDialog::_save_to_recent() {
String dir = get_current_dir();
@@ -1141,8 +1203,8 @@ void EditorFileDialog::_save_to_recent() {
EditorFileDialog::EditorFileDialog() {
- show_hidden_files=true;
- display_mode=DISPLAY_THUMBNAILS;
+ show_hidden_files=default_show_hidden_files;
+ display_mode=default_display_mode;
local_history_pos=0;
VBoxContainer *vbc = memnew( VBoxContainer );
@@ -1170,6 +1232,10 @@ EditorFileDialog::EditorFileDialog() {
pathhb->add_child(dir);
dir->set_h_size_flags(SIZE_EXPAND_FILL);
+ refresh = memnew( ToolButton );
+ refresh->connect("pressed",this,"_update_file_list");
+ pathhb->add_child(refresh);
+
favorite = memnew( ToolButton );
favorite->set_toggle_mode(true);
favorite->connect("toggled",this,"_favorite_toggled");
@@ -1178,11 +1244,13 @@ EditorFileDialog::EditorFileDialog() {
mode_thumbnails = memnew( ToolButton );
mode_thumbnails->connect("pressed",this,"set_display_mode",varray(DISPLAY_THUMBNAILS));
mode_thumbnails->set_toggle_mode(true);
- mode_thumbnails->set_pressed(true);
+ mode_thumbnails->set_pressed(display_mode==DISPLAY_THUMBNAILS);
pathhb->add_child(mode_thumbnails);
+
mode_list = memnew( ToolButton );
mode_list->connect("pressed",this,"set_display_mode",varray(DISPLAY_LIST));
mode_list->set_toggle_mode(true);
+ mode_list->set_pressed(display_mode==DISPLAY_LIST);
pathhb->add_child(mode_list);
drives = memnew( OptionButton );
diff --git a/tools/editor/editor_file_dialog.h b/tools/editor/editor_file_dialog.h
index 6cfd970516..3590964a51 100644
--- a/tools/editor/editor_file_dialog.h
+++ b/tools/editor/editor_file_dialog.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -108,6 +108,7 @@ private:
ToolButton *mode_list;
+ ToolButton *refresh;
ToolButton *favorite;
ToolButton *fav_up;
@@ -127,6 +128,7 @@ private:
int preview_wheel_index;
float preview_wheel_timeout;
static bool default_show_hidden_files;
+ static DisplayMode default_display_mode;
bool show_hidden_files;
DisplayMode display_mode;
@@ -174,6 +176,8 @@ private:
void _thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata);
void _request_single_thumbnail(const String& p_path);
+ void _unhandled_input(const InputEvent& p_event);
+
protected:
void _notification(int p_what);
@@ -210,6 +214,7 @@ public:
bool is_showing_hidden_files() const;
static void set_default_show_hidden_files(bool p_show);
+ static void set_default_display_mode(DisplayMode p_mode);
void invalidate();
diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp
index 33e4a15c85..c7c1a48e34 100644
--- a/tools/editor/editor_file_system.cpp
+++ b/tools/editor/editor_file_system.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,6 +37,31 @@
EditorFileSystem *EditorFileSystem::singleton=NULL;
+void EditorFileSystemDirectory::sort_files() {
+
+ files.sort_custom<FileInfoSort>();
+}
+
+int EditorFileSystemDirectory::find_file_index(const String& p_file) const {
+
+ for(int i=0;i<files.size();i++) {
+ if (files[i]->file==p_file)
+ return i;
+ }
+ return -1;
+
+}
+int EditorFileSystemDirectory::find_dir_index(const String& p_dir) const{
+
+
+ for(int i=0;i<subdirs.size();i++) {
+ if (subdirs[i]->name==p_dir)
+ return i;
+ }
+
+ return -1;
+}
+
int EditorFileSystemDirectory::get_subdir_count() const {
@@ -59,7 +84,7 @@ String EditorFileSystemDirectory::get_file(int p_idx) const{
ERR_FAIL_INDEX_V(p_idx,files.size(),"");
- return files[p_idx].file;
+ return files[p_idx]->file;
}
String EditorFileSystemDirectory::get_path() const {
@@ -91,22 +116,22 @@ String EditorFileSystemDirectory::get_file_path(int p_idx) const {
bool EditorFileSystemDirectory::get_file_meta(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,files.size(),"");
- return files[p_idx].meta.enabled;
+ return files[p_idx]->meta.enabled;
}
Vector<String> EditorFileSystemDirectory::get_file_deps(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,files.size(),Vector<String>());
- return files[p_idx].meta.deps;
+ return files[p_idx]->meta.deps;
}
Vector<String> EditorFileSystemDirectory::get_missing_sources(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,files.size(),Vector<String>());
Vector<String> missing;
- for(int i=0;i<files[p_idx].meta.sources.size();i++) {
- if (files[p_idx].meta.sources[i].missing)
- missing.push_back(files[p_idx].meta.sources[i].path);
+ for(int i=0;i<files[p_idx]->meta.sources.size();i++) {
+ if (files[p_idx]->meta.sources[i].missing)
+ missing.push_back(files[p_idx]->meta.sources[i].path);
}
return missing;
@@ -116,8 +141,8 @@ Vector<String> EditorFileSystemDirectory::get_missing_sources(int p_idx) const {
bool EditorFileSystemDirectory::is_missing_sources(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,files.size(),false);
- for(int i=0;i<files[p_idx].meta.sources.size();i++) {
- if (files[p_idx].meta.sources[i].missing)
+ for(int i=0;i<files[p_idx]->meta.sources.size();i++) {
+ if (files[p_idx]->meta.sources[i].missing)
return true;
}
@@ -127,7 +152,7 @@ bool EditorFileSystemDirectory::is_missing_sources(int p_idx) const {
StringName EditorFileSystemDirectory::get_file_type(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,files.size(),"");
- return files[p_idx].type;
+ return files[p_idx]->type;
}
String EditorFileSystemDirectory::get_name() {
@@ -157,11 +182,17 @@ void EditorFileSystemDirectory::_bind_methods() {
EditorFileSystemDirectory::EditorFileSystemDirectory() {
+ modified_time=0;
parent=NULL;
}
EditorFileSystemDirectory::~EditorFileSystemDirectory() {
+ for(int i=0;i<files.size();i++) {
+
+ memdelete(files[i]);
+ }
+
for(int i=0;i<subdirs.size();i++) {
memdelete(subdirs[i]);
@@ -173,19 +204,6 @@ EditorFileSystemDirectory::~EditorFileSystemDirectory() {
-
-
-EditorFileSystem::DirItem::~DirItem() {
-
- for(int i=0;i<dirs.size();i++) {
- memdelete(dirs[i]);
- }
-
- for(int i=0;i<files.size();i++) {
- memdelete(files[i]);
- }
-}
-
EditorFileSystemDirectory::ImportMeta EditorFileSystem::_get_meta(const String& p_path) {
Ref<ResourceImportMetadata> imd = ResourceLoader::load_import_metadata(p_path);
@@ -214,160 +232,16 @@ EditorFileSystemDirectory::ImportMeta EditorFileSystem::_get_meta(const String&
return m;
}
-EditorFileSystem::DirItem* EditorFileSystem::_scan_dir(DirAccess *da,Set<String> &extensions,String p_name,float p_from,float p_range,const String& p_path,HashMap<String,FileCache> &file_cache,HashMap<String,DirCache> &dir_cache,EditorProgressBG& p_prog) {
- if (abort_scan)
- return NULL;
-
- if (p_path!=String()) {
- if (FileAccess::exists(("res://"+p_path).plus_file("engine.cfg"))) {
- return NULL;
- }
- }
-
- List<String> dirs;
- List<String> files;
- Set<String> pngs;
-
- String path=p_path;
- if (path.ends_with("/"))
- path=path.substr(0,path.length()-1);
- String global_path = Globals::get_singleton()->get_resource_path().plus_file(path);
-
- path="res://"+path;
- uint64_t mtime = FileAccess::get_modified_time(global_path);
-
- DirCache *dc = dir_cache.getptr(path);
-
-
- if (false && dc && dc->modification_time==mtime) {
- //use the cached files, since directory did not change
- for (Set<String>::Element *E=dc->subdirs.front();E;E=E->next()) {
- dirs.push_back(E->get());
- }
- for (Set<String>::Element *E=dc->files.front();E;E=E->next()) {
- files.push_back(E->get());
- }
-
- } else {
- //use the filesystem, some files may have changed
- Error err = da->change_dir(global_path);
- if (err!=OK) {
- print_line("Can't change to: "+path);
- ERR_FAIL_COND_V(err!=OK,NULL);
- }
+void EditorFileSystem::_scan_filesystem() {
-
- da->list_dir_begin();
- while (true) {
-
- bool isdir;
- String f = da->get_next(&isdir);
- if (f=="")
- break;
- if (isdir) {
- dirs.push_back(f);
- } else {
- String ext = f.extension().to_lower();
- if (extensions.has(ext))
- files.push_back(f);
-
- }
-
- }
-
- da->list_dir_end();
- files.sort();
- dirs.sort();
-
- }
-
-
-
- //print_line(da->get_current_dir()+": dirs: "+itos(dirs.size())+" files:"+itos(files.size()) );
-
- //find subdirs
- Vector<DirItem*> subdirs;
-
- //String current = da->get_current_dir();
- float idx=0;
- for (List<String>::Element *E=dirs.front();E;E=E->next(),idx+=1.0) {
-
- String d = E->get();
- if (d.begins_with(".")) //ignore hidden and . / ..
- continue;
-
- //ERR_CONTINUE( da->change_dir(d)!= OK );
- DirItem *sdi = _scan_dir(da,extensions,d,p_from+(idx/dirs.size())*p_range,p_range/dirs.size(),p_path+d+"/",file_cache,dir_cache,p_prog);
- if (sdi) {
- subdirs.push_back(sdi);
- }
- //da->change_dir(current);
- }
-
-
- if (subdirs.empty() && files.empty()) {
- total=p_from+p_range;
- p_prog.step(total*100);
- return NULL; //give up, nothing to do here
- }
-
- DirItem *di = memnew( DirItem );
- di->path=path;
- di->name=p_name;
- di->dirs=subdirs;
- di->modified_time=mtime;
-
- //add files
- for (List<String>::Element *E=files.front();E;E=E->next()) {
-
- SceneItem * si = memnew( SceneItem );
- si->file=E->get();
- si->path="res://"+p_path+si->file;
- FileCache *fc = file_cache.getptr(si->path);
- uint64_t mt = FileAccess::get_modified_time(si->path);
-
- if (fc && fc->modification_time == mt) {
-
- si->meta=fc->meta;
- si->type=fc->type;
- si->modified_time=fc->modification_time;
- } else {
- si->meta=_get_meta(si->path);
- si->type=ResourceLoader::get_resource_type(si->path);
- si->modified_time=mt;
-
- }
-
- if (si->meta.enabled) {
- md_count++;
- if (_check_meta_sources(si->meta)) {
- sources_changed.push_back(si->path);
- }
- }
- di->files.push_back(si);
- }
-
- total=p_from+p_range;
- p_prog.step(total*100);
-
- return di;
-}
-
-
-void EditorFileSystem::_scan_scenes() {
-
- ERR_FAIL_COND(!scanning || scandir);
+ ERR_FAIL_COND(!scanning || new_filesystem);
//read .fscache
- HashMap<String,FileCache> file_cache;
- HashMap<String,DirCache> dir_cache;
- DirCache *dc=NULL;
String cpath;
sources_changed.clear();
-
-
+ file_cache.clear();
String project=Globals::get_singleton()->get_resource_path();
@@ -387,26 +261,7 @@ void EditorFileSystem::_scan_scenes() {
ERR_CONTINUE( split.size() != 3);
String name = split[1];
- dir_cache[name]=DirCache();
- dc=&dir_cache[name];
- dc->modification_time=split[2].to_int64();
-
- if (name!="res://") {
-
- cpath=name+"/";
-
- int sp=name.find_last("/");
- if (sp==5)
- sp=6;
- String pd = name.substr(0,sp);
- DirCache *dcp = dir_cache.getptr(pd);
- ERR_CONTINUE(!dcp);
- dcp->subdirs.insert(name.get_file());
- } else {
-
- cpath=name;
- }
-
+ cpath=name;
} else {
Vector<String> split = l.split("::");
@@ -414,12 +269,8 @@ void EditorFileSystem::_scan_scenes() {
String name = split[0];
String file;
- if (!name.begins_with("res://")) {
- file=name;
- name=cpath+name;
- } else {
- file=name.get_file();
- }
+ file=name;
+ name=cpath.plus_file(name);
FileCache fc;
fc.type=split[1];
@@ -453,8 +304,6 @@ void EditorFileSystem::_scan_scenes() {
file_cache[name]=fc;
- ERR_CONTINUE(!dc);
- dc->files.insert(file);
}
}
@@ -465,39 +314,31 @@ void EditorFileSystem::_scan_scenes() {
+ EditorProgressBG scan_progress("efs","ScanFS",1000);
+ ScanProgress sp;
+ sp.low=0;
+ sp.hi=1;
+ sp.progress=&scan_progress;
- total=0;
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- //da->change_dir( Globals::get_singleton()->get_resource_path() );
+ new_filesystem = memnew( EditorFileSystemDirectory );
+ new_filesystem->parent=NULL;
+ DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ d->change_dir("res://");
+ _scan_new_dir(new_filesystem,d,sp);
- List<String> extensionsl;
- ResourceLoader::get_recognized_extensions_for_type("",&extensionsl);
- Set<String> extensions;
- for(List<String>::Element *E = extensionsl.front();E;E=E->next()) {
+ file_cache.clear(); //clear caches, no longer needed
- extensions.insert(E->get());
- }
-
- EditorProgressBG scan_progress("efs","ScanFS",100);
-
- md_count=0;
- scandir=_scan_dir(da,extensions,"",0,1,"",file_cache,dir_cache,scan_progress);
- memdelete(da);
- if (abort_scan && scandir) {
- memdelete(scandir);
- scandir=NULL;
-
- }
+ memdelete(d);
//save back the findings
// String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("file_cache");
f=FileAccess::open(fscache,FileAccess::WRITE);
- _save_type_cache_fs(scandir,f);
+ _save_filesystem_cache(new_filesystem,f);
f->close();
memdelete(f);
@@ -510,7 +351,95 @@ void EditorFileSystem::_scan_scenes() {
void EditorFileSystem::_thread_func(void *_userdata) {
EditorFileSystem *sd = (EditorFileSystem*)_userdata;
- sd->_scan_scenes();
+ sd->_scan_filesystem();
+
+}
+
+bool EditorFileSystem::_update_scan_actions() {
+
+ sources_changed.clear();
+
+ bool fs_changed=false;
+
+ for (List<ItemAction>::Element *E=scan_actions.front();E;E=E->next()) {
+
+ ItemAction&ia = E->get();
+
+ switch(ia.action) {
+ case ItemAction::ACTION_NONE: {
+
+ } break;
+ case ItemAction::ACTION_DIR_ADD: {
+
+ //print_line("*ACTION ADD DIR: "+ia.new_dir->get_name());
+ int idx=0;
+ for(int i=0;i<ia.dir->subdirs.size();i++) {
+
+ if (ia.new_dir->name<ia.dir->subdirs[i]->name)
+ break;
+ idx++;
+ }
+ if (idx==ia.dir->subdirs.size()) {
+ ia.dir->subdirs.push_back(ia.new_dir);
+ } else {
+ ia.dir->subdirs.insert(idx,ia.new_dir);
+ }
+
+ fs_changed=true;
+ } break;
+ case ItemAction::ACTION_DIR_REMOVE: {
+
+ ERR_CONTINUE(!ia.dir->parent);
+ //print_line("*ACTION REMOVE DIR: "+ia.dir->get_name());
+ ia.dir->parent->subdirs.erase(ia.dir);
+ memdelete( ia.dir );
+ fs_changed=true;
+ } break;
+ case ItemAction::ACTION_FILE_ADD: {
+
+ int idx=0;
+ for(int i=0;i<ia.dir->files.size();i++) {
+
+ if (ia.new_file->file<ia.dir->files[i]->file)
+ break;
+ idx++;
+ }
+ if (idx==ia.dir->files.size()) {
+ ia.dir->files.push_back(ia.new_file);
+ } else {
+ ia.dir->files.insert(idx,ia.new_file);
+ }
+
+ fs_changed=true;
+ //print_line("*ACTION ADD FILE: "+ia.new_file->file);
+
+ } break;
+ case ItemAction::ACTION_FILE_REMOVE: {
+
+ int idx = ia.dir->find_file_index(ia.file);
+ ERR_CONTINUE(idx==-1);
+ memdelete( ia.dir->files[idx] );
+ ia.dir->files.remove(idx);
+
+ fs_changed=true;
+ //print_line("*ACTION REMOVE FILE: "+ia.file);
+
+ } break;
+ case ItemAction::ACTION_FILE_SOURCES_CHANGED: {
+
+ int idx = ia.dir->find_file_index(ia.file);
+ ERR_CONTINUE(idx==-1);
+ String full_path = ia.dir->get_file_path(idx);
+ sources_changed.push_back(full_path);
+
+ } break;
+
+ }
+ }
+
+ scan_actions.clear();
+
+ return fs_changed;
}
@@ -526,19 +455,15 @@ void EditorFileSystem::scan() {
abort_scan=false;
if (!use_threads) {
scanning=true;
- _scan_scenes();
- if (rootdir)
- memdelete(rootdir);
- rootdir=scandir;
+ scan_total=0;
+ _scan_filesystem();
if (filesystem)
memdelete(filesystem);
// file_type_cache.clear();
- filesystem=_update_tree(rootdir);
-
- if (rootdir)
- memdelete(rootdir);
- rootdir=NULL;
- scanning=false;
+ filesystem=new_filesystem;
+ new_filesystem=NULL;
+ _update_scan_actions();
+ scanning=false;
emit_signal("filesystem_changed");
emit_signal("sources_changed",sources_changed.size()>0);
@@ -548,6 +473,7 @@ void EditorFileSystem::scan() {
set_process(true);
Thread::Settings s;
scanning=true;
+ scan_total=0;
s.priority=Thread::PRIORITY_LOW;
thread = Thread::create(_thread_func,this,s);
//tree->hide();
@@ -559,14 +485,10 @@ void EditorFileSystem::scan() {
}
-bool EditorFileSystem::_check_meta_sources(EditorFileSystemDirectory::ImportMeta & p_meta,EditorProgressBG *ep) {
+bool EditorFileSystem::_check_meta_sources(EditorFileSystemDirectory::ImportMeta & p_meta) {
if (p_meta.enabled) {
- if (ep) {
- ep->step(ss_amount++);
- }
-
for(int j=0;j<p_meta.sources.size();j++) {
@@ -584,9 +506,9 @@ bool EditorFileSystem::_check_meta_sources(EditorFileSystemDirectory::ImportMeta
if (mt!=p_meta.sources[j].modified_time) {
//scan
String md5 = FileAccess::get_md5(src);
- print_line("checking: "+src);
- print_line("md5: "+md5);
- print_line("vs: "+p_meta.sources[j].md5);
+ //print_line("checking: "+src);
+ //print_line("md5: "+md5);
+ //print_line("vs: "+p_meta.sources[j].md5);
if (md5!=p_meta.sources[j].md5) {
//really changed
return true;
@@ -599,18 +521,300 @@ bool EditorFileSystem::_check_meta_sources(EditorFileSystemDirectory::ImportMeta
return false;
}
-void EditorFileSystem::_scan_sources(EditorFileSystemDirectory *p_dir,EditorProgressBG *ep) {
+void EditorFileSystem::ScanProgress::update(int p_current,int p_total) const {
+
+ float ratio = low + ((hi-low)/p_total)*p_current;
+ progress->step(ratio*1000);
+ EditorFileSystem::singleton->scan_total=ratio;
+}
+
+EditorFileSystem::ScanProgress EditorFileSystem::ScanProgress::get_sub(int p_current,int p_total) const{
+
+ ScanProgress sp=*this;
+ float slice = (sp.hi-sp.low)/p_total;
+ sp.low+=slice*p_current;
+ sp.hi=slice;
+ return sp;
+
+
+}
+
+
+void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess *da,const ScanProgress& p_progress) {
+
+ List<String> dirs;
+ List<String> files;
+
+ String cd = da->get_current_dir();
+
+ p_dir->modified_time = FileAccess::get_modified_time(cd);
+
+
+ da->list_dir_begin();
+ while (true) {
+
+ bool isdir;
+ String f = da->get_next(&isdir);
+ if (f=="")
+ break;
+
+ if (isdir) {
+
+ if (f.begins_with(".")) //ignore hidden and . / ..
+ continue;
+
+ if (FileAccess::exists(cd.plus_file(f).plus_file("engine.cfg"))) // skip if another project inside this
+ continue;
+
+ dirs.push_back(f);
+
+ } else {
+
+ files.push_back(f);
+ }
+
+ }
+
+ da->list_dir_end();
+
+ dirs.sort();
+ files.sort();
+
+ int total = dirs.size()+files.size();
+ int idx=0;
+
+ for (List<String>::Element *E=dirs.front();E;E=E->next(),idx++) {
+
+ if (da->change_dir(E->get())==OK) {
+
+ EditorFileSystemDirectory *efd = memnew( EditorFileSystemDirectory );
+
+ efd->parent=p_dir;
+ efd->name=E->get();
+
+ _scan_new_dir(efd,da,p_progress.get_sub(idx,total));
+
+ int idx=0;
+ for(int i=0;i<p_dir->subdirs.size();i++) {
+
+ if (efd->name<p_dir->subdirs[i]->name)
+ break;
+ idx++;
+ }
+ if (idx==p_dir->subdirs.size()) {
+ p_dir->subdirs.push_back(efd);
+ } else {
+ p_dir->subdirs.insert(idx,efd);
+ }
+
+ da->change_dir("..");
+ } else {
+ ERR_PRINTS("Can't go into subdir: "+E->get());
+ }
+
+ p_progress.update(idx,total);
+
+ }
+
+ for (List<String>::Element*E=files.front();E;E=E->next(),idx++) {
+
+ String ext = E->get().extension().to_lower();
+ if (!valid_extensions.has(ext))
+ continue; //invalid
+
+ EditorFileSystemDirectory::FileInfo *fi = memnew( EditorFileSystemDirectory::FileInfo );
+ fi->file=E->get();
+
+ String path = cd.plus_file(fi->file);
+
+ FileCache *fc = file_cache.getptr(path);
+ uint64_t mt = FileAccess::get_modified_time(path);
+
+ if (fc && fc->modification_time == mt) {
+
+ fi->meta=fc->meta;
+ fi->type=fc->type;
+ fi->modified_time=fc->modification_time;
+ } else {
+ fi->meta=_get_meta(path);
+ fi->type=ResourceLoader::get_resource_type(path);
+ fi->modified_time=mt;
+
+ }
+
+ if (fi->meta.enabled) {
+ if (_check_meta_sources(fi->meta)) {
+ ItemAction ia;
+ ia.action=ItemAction::ACTION_FILE_SOURCES_CHANGED;
+ ia.dir=p_dir;
+ ia.file=E->get();
+ scan_actions.push_back(ia);
+ }
+ }
+
+ p_dir->files.push_back(fi);
+ p_progress.update(idx,total);
+ }
+
+}
+
+
+void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const ScanProgress& p_progress) {
+
+ uint64_t current_mtime = FileAccess::get_modified_time(p_dir->get_path());
+
+ bool updated_dir=false;
+
+ //print_line("dir: "+p_dir->get_path()+" MODTIME: "+itos(p_dir->modified_time)+" CTIME: "+itos(current_mtime));
+
+ if (current_mtime!=p_dir->modified_time) {
+
+ updated_dir=true;
+ p_dir->modified_time=current_mtime;
+ //ooooops, dir changed, see what's going on
+
+ //first mark everything as veryfied
+
+ for(int i=0;i<p_dir->files.size();i++) {
+
+ p_dir->files[i]->verified=false;
+ }
+
+ for(int i=0;i<p_dir->subdirs.size();i++) {
+
+ p_dir->get_subdir(i)->verified=false;
+ }
+
+ //then scan files and directories and check what's different
+
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ String cd = p_dir->get_path();
+ da->change_dir(cd);
+ da->list_dir_begin();
+ while (true) {
+
+ bool isdir;
+ String f = da->get_next(&isdir);
+ if (f=="")
+ break;
+
+ if (isdir) {
+
+ if (f.begins_with(".")) //ignore hidden and . / ..
+ continue;
+
+ int idx = p_dir->find_dir_index(f);
+ if (idx==-1) {
+
+ if (FileAccess::exists(cd.plus_file(f).plus_file("engine.cfg"))) // skip if another project inside this
+ continue;
+
+ EditorFileSystemDirectory *efd = memnew( EditorFileSystemDirectory );
+
+ efd->parent=p_dir;
+ efd->name=f;
+ DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ d->change_dir(cd.plus_file(f));
+ _scan_new_dir(efd,d,p_progress.get_sub(1,1));
+ memdelete(d);
+
+
+ ItemAction ia;
+ ia.action=ItemAction::ACTION_DIR_ADD;
+ ia.dir=p_dir;
+ ia.file=f;
+ ia.new_dir=efd;
+ scan_actions.push_back(ia);
+ } else {
+ p_dir->subdirs[idx]->verified=true;
+ }
+
+
+ } else {
+ String ext = f.extension().to_lower();
+ if (!valid_extensions.has(ext))
+ continue; //invalid
+
+ int idx = p_dir->find_file_index(f);
+
+ if (idx==-1) {
+ //never seen this file, add actition to add it
+ EditorFileSystemDirectory::FileInfo *fi = memnew( EditorFileSystemDirectory::FileInfo );
+ fi->file=f;
+
+ String path = cd.plus_file(fi->file);
+ fi->modified_time=FileAccess::get_modified_time(path);
+ fi->meta=_get_meta(path);
+ fi->type=ResourceLoader::get_resource_type(path);
+
+ {
+ ItemAction ia;
+ ia.action=ItemAction::ACTION_FILE_ADD;
+ ia.dir=p_dir;
+ ia.file=f;
+ ia.new_file=fi;
+ scan_actions.push_back(ia);
+ }
+
+ //take the chance and scan sources
+ if (_check_meta_sources(fi->meta)) {
+
+ ItemAction ia;
+ ia.action=ItemAction::ACTION_FILE_SOURCES_CHANGED;
+ ia.dir=p_dir;
+ ia.file=f;
+ scan_actions.push_back(ia);
+ }
+
+ } else {
+ p_dir->files[idx]->verified=true;
+ }
+
+
+ }
+
+ }
+ da->list_dir_end();
+ memdelete(da);
+
+
+
+
+ }
for(int i=0;i<p_dir->files.size();i++) {
- if (_check_meta_sources(p_dir->files[i].meta,ep)) {
- sources_changed.push_back(p_dir->get_file_path(i));
+ if (updated_dir && !p_dir->files[i]->verified) {
+ //this file was removed, add action to remove it
+ ItemAction ia;
+ ia.action=ItemAction::ACTION_FILE_REMOVE;
+ ia.dir=p_dir;
+ ia.file=p_dir->files[i]->file;
+ scan_actions.push_back(ia);
+ continue;
+
+ }
+ if (_check_meta_sources(p_dir->files[i]->meta)) {
+ ItemAction ia;
+ ia.action=ItemAction::ACTION_FILE_SOURCES_CHANGED;
+ ia.dir=p_dir;
+ ia.file=p_dir->files[i]->file;
+ scan_actions.push_back(ia);
}
}
for(int i=0;i<p_dir->subdirs.size();i++) {
- _scan_sources(p_dir->get_subdir(i),ep);
+ if (updated_dir && !p_dir->subdirs[i]->verified) {
+ //this directory was removed, add action to remove it
+ ItemAction ia;
+ ia.action=ItemAction::ACTION_DIR_REMOVE;
+ ia.dir=p_dir->subdirs[i];
+ scan_actions.push_back(ia);
+ continue;
+
+ }
+ _scan_fs_changes(p_dir->get_subdir(i),p_progress);
}
}
@@ -619,9 +823,12 @@ void EditorFileSystem::_thread_func_sources(void *_userdata) {
EditorFileSystem *efs = (EditorFileSystem*)_userdata;
if (efs->filesystem) {
- EditorProgressBG pr("sources","ScanSources",efs->md_count);
- efs->ss_amount=0;
- efs->_scan_sources(efs->filesystem,&pr);
+ EditorProgressBG pr("sources","ScanSources",1000);
+ ScanProgress sp;
+ sp.progress=&pr;
+ sp.hi=1;
+ sp.low=0;
+ efs->_scan_fs_changes(efs->filesystem,sp);
}
efs->scanning_sources_done=true;
}
@@ -643,8 +850,17 @@ void EditorFileSystem::scan_sources() {
abort_scan=false;
if (!use_threads) {
- if (filesystem)
- _scan_sources(filesystem,NULL);
+ if (filesystem) {
+ EditorProgressBG pr("sources","ScanSources",1000);
+ ScanProgress sp;
+ sp.progress=&pr;
+ sp.hi=1;
+ sp.low=0;
+ scan_total=0;
+ _scan_fs_changes(filesystem,sp);
+ if (_update_scan_actions())
+ emit_signal("filesystem_changed");
+ }
scanning_sources=false;
scanning_sources_done=true;
emit_signal("sources_changed",sources_changed.size()>0);
@@ -652,8 +868,8 @@ void EditorFileSystem::scan_sources() {
ERR_FAIL_COND(thread_sources);
set_process(true);
+ scan_total=0;
Thread::Settings s;
- ss_amount=0;
s.priority=Thread::PRIORITY_LOW;
thread_sources = Thread::create(_thread_func_sources,this,s);
//tree->hide();
@@ -665,53 +881,14 @@ void EditorFileSystem::scan_sources() {
}
-EditorFileSystemDirectory* EditorFileSystem::_update_tree(DirItem *p_item) {
-
- EditorFileSystemDirectory *efd = memnew( EditorFileSystemDirectory );
-
- if (!p_item)
- return efd; //empty likely
- efd->name=p_item->name;
-
- for(int i=0;i<p_item->files.size();i++) {
-
- String s = p_item->files[i]->type;
- //if (p_item->files[i]->meta)
- // s="*"+s;
-
-// file_type_cache[p_item->files[i]->path]=s;
- if (p_item->files[i]->type=="")
- continue; //ignore because it's invalid
- EditorFileSystemDirectory::FileInfo fi;
- fi.file=p_item->files[i]->file;
- fi.type=p_item->files[i]->type;
- fi.meta=p_item->files[i]->meta;
- fi.modified_time=p_item->files[i]->modified_time;
-
- efd->files.push_back(fi);
-
- }
-
- for(int i=0;i<p_item->dirs.size();i++) {
-
- EditorFileSystemDirectory *efsd =_update_tree(p_item->dirs[i]);
- efsd->parent=efd;
- efd->subdirs.push_back( efsd );
-
- }
-
-
- return efd;
-}
-
void EditorFileSystem::_notification(int p_what) {
switch(p_what) {
case NOTIFICATION_ENTER_TREE: {
- _load_type_cache();
- scan();
+
+ scan();
} break;
case NOTIFICATION_EXIT_TREE: {
if (use_threads && thread) {
@@ -727,13 +904,13 @@ void EditorFileSystem::_notification(int p_what) {
set_process(false);
}
- if (rootdir)
- memdelete(rootdir);
- rootdir=NULL;
if (filesystem)
memdelete(filesystem);
+ if (new_filesystem)
+ memdelete(new_filesystem);
filesystem=NULL;
+ new_filesystem=NULL;
} break;
case NOTIFICATION_PROCESS: {
@@ -751,6 +928,8 @@ void EditorFileSystem::_notification(int p_what) {
Thread::wait_to_finish(thread_sources);
memdelete(thread_sources);
thread_sources=NULL;
+ if (_update_scan_actions())
+ emit_signal("filesystem_changed");
//print_line("sources changed: "+itos(sources_changed.size()));
emit_signal("sources_changed",sources_changed.size()>0);
}
@@ -758,21 +937,14 @@ void EditorFileSystem::_notification(int p_what) {
set_process(false);
- if (rootdir)
- memdelete(rootdir);
if (filesystem)
memdelete(filesystem);
- rootdir=scandir;
- scandir=NULL;
-// file_type_cache.clear();
- filesystem=_update_tree(rootdir);
-
- if (rootdir)
- memdelete(rootdir);
- rootdir=NULL;
+ filesystem=new_filesystem;
+ new_filesystem=NULL;
Thread::wait_to_finish(thread);
memdelete(thread);
thread=NULL;
+ _update_scan_actions();
emit_signal("filesystem_changed");
emit_signal("sources_changed",sources_changed.size()>0);
//print_line("initial sources changed: "+itos(sources_changed.size()));
@@ -794,7 +966,7 @@ bool EditorFileSystem::is_scanning() const {
}
float EditorFileSystem::get_scanning_progress() const {
- return total;
+ return scan_total;
}
EditorFileSystemDirectory *EditorFileSystem::get_filesystem() {
@@ -802,12 +974,12 @@ EditorFileSystemDirectory *EditorFileSystem::get_filesystem() {
return filesystem;
}
-void EditorFileSystem::_save_type_cache_fs(DirItem *p_dir,FileAccess *p_file) {
+void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory*p_dir,FileAccess *p_file) {
if (!p_dir)
return; //none
- p_file->store_line("::"+p_dir->path+"::"+String::num(p_dir->modified_time));
+ p_file->store_line("::"+p_dir->get_path()+"::"+String::num(p_dir->modified_time));
for(int i=0;i<p_dir->files.size();i++) {
@@ -832,126 +1004,96 @@ void EditorFileSystem::_save_type_cache_fs(DirItem *p_dir,FileAccess *p_file) {
p_file->store_line(s);
}
- for(int i=0;i<p_dir->dirs.size();i++) {
+ for(int i=0;i<p_dir->subdirs.size();i++) {
- _save_type_cache_fs(p_dir->dirs[i],p_file);
+ _save_filesystem_cache(p_dir->subdirs[i],p_file);
}
}
-void EditorFileSystem::_load_type_cache(){
-
- GLOBAL_LOCK_FUNCTION
-
-
-#if 0
- //this is not good, removed for now as it interferes with metadata stored in files
-
- String project=Globals::get_singleton()->get_resource_path();
- FileAccess *f =FileAccess::open(project+"/types.cache",FileAccess::READ);
-
- if (!f) {
-
- WARN_PRINT("Can't open types.cache.");
- return;
- }
-
- file_type_cache.clear();
- while(!f->eof_reached()) {
-
- String path=f->get_line();
- if (f->eof_reached())
- break;
- String type=f->get_line();
- file_type_cache[path]=type;
- }
-
- memdelete(f);
-#endif
-}
bool EditorFileSystem::_find_file(const String& p_file,EditorFileSystemDirectory ** r_d, int &r_file_pos) const {
//todo make faster
- if (!filesystem || scanning)
- return false;
+ if (!filesystem || scanning)
+ return false;
- String f = Globals::get_singleton()->localize_path(p_file);
+ String f = Globals::get_singleton()->localize_path(p_file);
- if (!f.begins_with("res://"))
- return false;
- f=f.substr(6,f.length());
- f=f.replace("\\","/");
+ if (!f.begins_with("res://"))
+ return false;
+ f=f.substr(6,f.length());
+ f=f.replace("\\","/");
- Vector<String> path = f.split("/");
+ Vector<String> path = f.split("/");
- if (path.size()==0)
- return false;
- String file=path[path.size()-1];
- path.resize(path.size()-1);
+ if (path.size()==0)
+ return false;
+ String file=path[path.size()-1];
+ path.resize(path.size()-1);
- EditorFileSystemDirectory *fs=filesystem;
+ EditorFileSystemDirectory *fs=filesystem;
- for(int i=0;i<path.size();i++) {
+ for(int i=0;i<path.size();i++) {
- int idx=-1;
- for(int j=0;j<fs->get_subdir_count();j++) {
+ int idx=-1;
+ for(int j=0;j<fs->get_subdir_count();j++) {
- if (fs->get_subdir(j)->get_name()==path[i]) {
- idx=j;
- break;
- }
- }
+ if (fs->get_subdir(j)->get_name()==path[i]) {
+ idx=j;
+ break;
+ }
+ }
- if (idx==-1) {
- //does not exist, create i guess?
- EditorFileSystemDirectory *efsd = memnew( EditorFileSystemDirectory );
- efsd->name=path[i];
- int idx2=0;
- for(int j=0;j<fs->get_subdir_count();j++) {
+ if (idx==-1) {
+ //does not exist, create i guess?
+ EditorFileSystemDirectory *efsd = memnew( EditorFileSystemDirectory );
+ efsd->name=path[i];
+ int idx2=0;
+ for(int j=0;j<fs->get_subdir_count();j++) {
- if (efsd->name<fs->get_subdir(j)->get_name())
- break;
- idx2++;
- }
+ if (efsd->name<fs->get_subdir(j)->get_name())
+ break;
+ idx2++;
+ }
- if (idx2==fs->get_subdir_count())
- fs->subdirs.push_back(efsd);
- else
- fs->subdirs.insert(idx2,efsd);
- fs=efsd;
- } else {
+ if (idx2==fs->get_subdir_count())
+ fs->subdirs.push_back(efsd);
+ else
+ fs->subdirs.insert(idx2,efsd);
+ fs=efsd;
+ } else {
- fs=fs->get_subdir(idx);
+ fs=fs->get_subdir(idx);
+ }
}
- }
- int cpos=-1;
- for(int i=0;i<fs->files.size();i++) {
+ int cpos=-1;
+ for(int i=0;i<fs->files.size();i++) {
- if (fs->files[i].file==file) {
- cpos=i;
- break;
+ if (fs->files[i]->file==file) {
+ cpos=i;
+ break;
+ }
}
- }
r_file_pos=cpos;
*r_d=fs;
- if (cpos!=-1) {
+ if (cpos!=-1) {
- return true;
- } else {
+ return true;
+ } else {
- return false;
- }
+ return false;
+ }
}
@@ -967,7 +1109,7 @@ String EditorFileSystem::get_file_type(const String& p_file) const {
}
- return fs->files[cpos].type;
+ return fs->files[cpos]->type;
}
@@ -1024,16 +1166,16 @@ EditorFileSystemDirectory *EditorFileSystem::get_path(const String& p_path) {
void EditorFileSystem::_resource_saved(const String& p_path){
- print_line("resource saved: "+p_path);
+ //print_line("resource saved: "+p_path);
EditorFileSystem::get_singleton()->update_file(p_path);
}
String EditorFileSystem::_find_first_from_source(EditorFileSystemDirectory* p_dir,const String &p_src) const {
for(int i=0;i<p_dir->files.size();i++) {
- for(int j=0;j<p_dir->files[i].meta.sources.size();j++) {
+ for(int j=0;j<p_dir->files[i]->meta.sources.size();j++) {
- if (p_dir->files[i].meta.sources[j].path==p_src)
+ if (p_dir->files[i]->meta.sources[j].path==p_src)
return p_dir->get_file_path(i);
}
}
@@ -1070,6 +1212,7 @@ void EditorFileSystem::update_file(const String& p_file) {
if (!FileAccess::exists(p_file)) {
//was removed
+ memdelete( fs->files[cpos] );
fs->files.remove(cpos);
call_deferred("emit_signal","filesystem_changed"); //update later
return;
@@ -1083,13 +1226,13 @@ void EditorFileSystem::update_file(const String& p_file) {
int idx=0;
for(int i=0;i<fs->files.size();i++) {
- if (p_file<fs->files[i].file)
+ if (p_file<fs->files[i]->file)
break;
idx++;
}
- EditorFileSystemDirectory::FileInfo fi;
- fi.file=p_file.get_file();
+ EditorFileSystemDirectory::FileInfo *fi = memnew( EditorFileSystemDirectory::FileInfo );
+ fi->file=p_file.get_file();
if (idx==fs->files.size()) {
fs->files.push_back(fi);
@@ -1102,10 +1245,10 @@ void EditorFileSystem::update_file(const String& p_file) {
}
- print_line("UPDATING: "+p_file);
- fs->files[cpos].type=type;
- fs->files[cpos].modified_time=FileAccess::get_modified_time(p_file);
- fs->files[cpos].meta=_get_meta(p_file);
+ //print_line("UPDATING: "+p_file);
+ fs->files[cpos]->type=type;
+ fs->files[cpos]->modified_time=FileAccess::get_modified_time(p_file);
+ fs->files[cpos]->meta=_get_meta(p_file);
call_deferred("emit_signal","filesystem_changed"); //update later
@@ -1128,15 +1271,22 @@ EditorFileSystem::EditorFileSystem() {
thread = NULL;
scanning=false;
- scandir=NULL;
- rootdir=NULL;
use_threads=true;
thread_sources=NULL;
+ new_filesystem=NULL;
scanning_sources=false;
ResourceSaver::set_save_callback(_resource_saved);
+ List<String> extensionsl;
+ ResourceLoader::get_recognized_extensions_for_type("",&extensionsl);
+ for(List<String>::Element *E = extensionsl.front();E;E=E->next()) {
+
+ valid_extensions.insert(E->get());
+ }
+
+ scan_total=0;
}
EditorFileSystem::~EditorFileSystem() {
diff --git a/tools/editor/editor_file_system.h b/tools/editor/editor_file_system.h
index f79dd209ef..d11fa0cfb1 100644
--- a/tools/editor/editor_file_system.h
+++ b/tools/editor/editor_file_system.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,6 +42,8 @@ class EditorFileSystemDirectory : public Object {
OBJ_TYPE( EditorFileSystemDirectory,Object );
String name;
+ uint64_t modified_time;
+ bool verified; //used for checking changes
EditorFileSystemDirectory *parent;
Vector<EditorFileSystemDirectory*> subdirs;
@@ -68,11 +70,20 @@ class EditorFileSystemDirectory : public Object {
String file;
StringName type;
uint64_t modified_time;
-
ImportMeta meta;
+ bool verified; //used for checking changes
+
+ };
+
+ struct FileInfoSort {
+ bool operator()(const FileInfo *p_a,const FileInfo *p_b) const {
+ return p_a->file<p_b->file;
+ }
};
- Vector<FileInfo> files;
+ void sort_files();
+
+ Vector<FileInfo*> files;
static void _bind_methods();
@@ -96,6 +107,9 @@ public:
EditorFileSystemDirectory *get_parent();
+ int find_file_index(const String& p_file) const;
+ int find_dir_index(const String& p_dir) const;
+
EditorFileSystemDirectory();
~EditorFileSystemDirectory();
@@ -107,45 +121,47 @@ class EditorFileSystem : public Node {
_THREAD_SAFE_CLASS_
- struct SceneItem {
+
+ struct ItemAction {
+
+ enum Action {
+ ACTION_NONE,
+ ACTION_DIR_ADD,
+ ACTION_DIR_REMOVE,
+ ACTION_FILE_ADD,
+ ACTION_FILE_REMOVE,
+ ACTION_FILE_SOURCES_CHANGED
+ };
+
+ Action action;
+ EditorFileSystemDirectory *dir;
String file;
- String path;
- String type;
- uint64_t modified_time;
- EditorFileSystemDirectory::ImportMeta meta;
- };
+ EditorFileSystemDirectory *new_dir;
+ EditorFileSystemDirectory::FileInfo *new_file;
- struct DirItem {
+ ItemAction() { action=ACTION_NONE; dir=NULL; new_dir=NULL; new_file=NULL; }
- uint64_t modified_time;
- String path;
- String name;
- Vector<DirItem*> dirs;
- Vector<SceneItem*> files;
- ~DirItem();
};
- float total;
bool use_threads;
Thread *thread;
static void _thread_func(void *_userdata);
- DirItem *scandir;
- DirItem *rootdir;
+ EditorFileSystemDirectory *new_filesystem;
bool abort_scan;
bool scanning;
+ float scan_total;
- EditorFileSystemDirectory* _update_tree(DirItem *p_item);
- void _scan_scenes();
- void _load_type_cache();
+ void _scan_filesystem();
EditorFileSystemDirectory *filesystem;
static EditorFileSystem *singleton;
+ /* Used for reading the filesystem cache file */
struct FileCache {
String type;
@@ -154,34 +170,43 @@ class EditorFileSystem : public Node {
Vector<String> deps;
};
- struct DirCache {
+ HashMap<String,FileCache> file_cache;
- uint64_t modification_time;
- Set<String> files;
- Set<String> subdirs;
- };
+ struct ScanProgress {
+ float low;
+ float hi;
+ mutable EditorProgressBG *progress;
+ void update(int p_current,int p_total) const;
+ ScanProgress get_sub(int p_current,int p_total) const;
+ };
static EditorFileSystemDirectory::ImportMeta _get_meta(const String& p_path);
- bool _check_meta_sources(EditorFileSystemDirectory::ImportMeta & p_meta,EditorProgressBG *ep=NULL);
+ bool _check_meta_sources(EditorFileSystemDirectory::ImportMeta & p_meta);
- DirItem* _scan_dir(DirAccess *da,Set<String> &extensions,String p_name,float p_from,float p_range,const String& p_path,HashMap<String,FileCache> &file_cache,HashMap<String,DirCache> &dir_cache,EditorProgressBG& p_prog);
- void _save_type_cache_fs(DirItem *p_dir,FileAccess *p_file);
+ void _save_filesystem_cache(EditorFileSystemDirectory *p_dir,FileAccess *p_file);
bool _find_file(const String& p_file,EditorFileSystemDirectory ** r_d, int &r_file_pos) const;
- void _scan_sources(EditorFileSystemDirectory *p_dir,EditorProgressBG *ep);
+ void _scan_fs_changes(EditorFileSystemDirectory *p_dir, const ScanProgress &p_progress);
int md_count;
+ Set<String> valid_extensions;
+
+ void _scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess *da,const ScanProgress& p_progress);
Thread *thread_sources;
bool scanning_sources;
bool scanning_sources_done;
- int ss_amount;
+
static void _thread_func_sources(void *_userdata);
+
List<String> sources_changed;
+ List<ItemAction> scan_actions;
+
+ bool _update_scan_actions();
static void _resource_saved(const String& p_path);
String _find_first_from_source(EditorFileSystemDirectory* p_dir,const String &p_src) const;
diff --git a/tools/editor/editor_fonts.cpp b/tools/editor/editor_fonts.cpp
index f145f1ddef..b12b041f16 100644
--- a/tools/editor/editor_fonts.cpp
+++ b/tools/editor/editor_fonts.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_fonts.h b/tools/editor/editor_fonts.h
index cc990a560c..3b2422c3e3 100644
--- a/tools/editor/editor_fonts.h
+++ b/tools/editor/editor_fonts.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_help.cpp b/tools/editor/editor_help.cpp
index a5a3890129..2ece518f8d 100644
--- a/tools/editor/editor_help.cpp
+++ b/tools/editor/editor_help.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -690,16 +690,28 @@ Error EditorHelp::_goto_desc(const String& p_class,int p_vscr) {
class_desc->pop();
//class_desc->add_newline();
- class_desc->add_newline();
+// class_desc->add_newline();
class_desc->push_indent(1);
+ class_desc->push_table(2);
+ class_desc->set_table_column_expand(1,1);
for(int i=0;i<cd.methods.size();i++) {
+ class_desc->push_cell();
+
+
method_line[cd.methods[i].name]=class_desc->get_line_count()-2; //gets overriden if description
+ class_desc->push_align(RichTextLabel::ALIGN_RIGHT);
class_desc->push_font(doc_code_font);
_add_type(cd.methods[i].return_type);
- class_desc->add_text(" ");
+ //class_desc->add_text(" ");
+ class_desc->pop(); //align
+ class_desc->pop(); //font
+ class_desc->pop(); //cell
+ class_desc->push_cell();
+ class_desc->push_font(doc_code_font);
+
if (cd.methods[i].description!="") {
method_descr=true;
class_desc->push_meta("@"+cd.methods[i].name);
@@ -742,12 +754,14 @@ Error EditorHelp::_goto_desc(const String& p_class,int p_vscr) {
}
class_desc->pop();//monofont
- class_desc->add_newline();
+// class_desc->add_newline();
+ class_desc->pop(); //cell
}
-
+ class_desc->pop(); //table
class_desc->pop();
class_desc->add_newline();
+ class_desc->add_newline();
}
diff --git a/tools/editor/editor_help.h b/tools/editor/editor_help.h
index 04ac4d35ff..059a7ae11d 100644
--- a/tools/editor/editor_help.h
+++ b/tools/editor/editor_help.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_icons.h b/tools/editor/editor_icons.h
index 910febc895..191b908682 100644
--- a/tools/editor/editor_icons.h
+++ b/tools/editor/editor_icons.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp
index f52c6e67a2..77331256f3 100644
--- a/tools/editor/editor_import_export.cpp
+++ b/tools/editor/editor_import_export.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -41,6 +41,8 @@
#include "io/md5.h"
#include "io_plugins/editor_texture_import_plugin.h"
#include "tools/editor/plugins/script_editor_plugin.h"
+#include "io/zip_io.h"
+
String EditorImportPlugin::validate_source_path(const String& p_path) {
@@ -399,6 +401,40 @@ Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const
}
+String EditorExportPlatform::find_export_template(String template_file_name, String *err) const {
+ String user_file = EditorSettings::get_singleton()->get_settings_path()
+ +"/templates/"+template_file_name;
+ String system_file=OS::get_singleton()->get_installed_templates_path();
+ bool has_system_path=(system_file!="");
+ system_file+=template_file_name;
+
+ // Prefer user file
+ if (FileAccess::exists(user_file)) {
+ return user_file;
+ }
+
+ // Now check system file
+ if (has_system_path) {
+ if (FileAccess::exists(system_file)) {
+ return system_file;
+ }
+ }
+
+ // Not found
+ if (err) {
+ *err+="No export template found at \""+user_file+"\"";
+ if (has_system_path)
+ *err+="\n or \""+system_file+"\".";
+ else
+ *err+=".";
+ }
+ return "";
+}
+
+bool EditorExportPlatform::exists_export_template(String template_file_name, String *err) const {
+ return find_export_template(template_file_name,err)!="";
+}
+
///////////////////////////////////////
@@ -419,6 +455,9 @@ bool EditorExportPlatformPC::_set(const StringName& p_name, const Variant& p_val
} else if (n=="resources/pack_mode") {
export_mode=ExportMode(int(p_value));
+ } else if (n=="resources/bundle_dependencies_(for_optical_disc)") {
+
+ bundle=p_value;
} else if (n=="binary/64_bits") {
use64=p_value;
@@ -442,6 +481,9 @@ bool EditorExportPlatformPC::_get(const StringName& p_name,Variant &r_ret) const
} else if (n=="resources/pack_mode") {
r_ret=export_mode;
+ } else if (n=="resources/bundle_dependencies_(for_optical_disc)") {
+
+ r_ret=bundle;
} else if (n=="binary/64_bits") {
r_ret=use64;
@@ -456,7 +498,8 @@ void EditorExportPlatformPC::_get_property_list( List<PropertyInfo> *p_list) con
p_list->push_back( PropertyInfo( Variant::STRING, "custom_binary/debug", PROPERTY_HINT_GLOBAL_FILE,binary_extension));
p_list->push_back( PropertyInfo( Variant::STRING, "custom_binary/release", PROPERTY_HINT_GLOBAL_FILE,binary_extension));
- p_list->push_back( PropertyInfo( Variant::INT, "resources/pack_mode", PROPERTY_HINT_ENUM,"Single Exec.,Exec+Pack (.pck),Copy,Bundles (Optical)"));
+ p_list->push_back( PropertyInfo( Variant::INT, "resources/pack_mode", PROPERTY_HINT_ENUM,"Pack into executable,Pack into binary file (.pck),Pack into archive file (.zip)"));
+ p_list->push_back( PropertyInfo( Variant::BOOL, "resources/bundle_dependencies_(for_optical_disc)"));
p_list->push_back( PropertyInfo( Variant::BOOL, "binary/64_bits"));
}
@@ -957,6 +1000,9 @@ void EditorExportPlatform::gen_export_flags(Vector<String> &r_flags, int p_flags
String host = EditorSettings::get_singleton()->get("network/debug_host");
+ if (p_flags&EXPORT_REMOTE_DEBUG_LOCALHOST)
+ host="localhost";
+
if (p_flags&EXPORT_DUMB_CLIENT) {
int port = EditorSettings::get_singleton()->get("file_server/port");
String passwd = EditorSettings::get_singleton()->get("file_server/password");
@@ -971,6 +1017,7 @@ void EditorExportPlatform::gen_export_flags(Vector<String> &r_flags, int p_flags
if (p_flags&EXPORT_REMOTE_DEBUG) {
r_flags.push_back("-rdebug");
+
r_flags.push_back(host+":"+String::num(GLOBAL_DEF("debug/debug_port", 6007)));
List<String> breakpoints;
@@ -1028,7 +1075,7 @@ Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path
MD5Final(&ctx);
pd->f->store_buffer(ctx.digest,16);
}
- pd->ep->step("Storing File: "+p_path,2+p_file*100/p_total);
+ pd->ep->step("Storing File: "+p_path,2+p_file*100/p_total,false);
pd->count++;
pd->ftmp->store_buffer(p_data.ptr(),p_data.size());
if (pd->alignment > 1) {
@@ -1043,6 +1090,58 @@ Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path
}
+Error EditorExportPlatform::save_zip_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total) {
+
+
+ String path=p_path.replace_first("res://","");
+
+ ZipData *zd = (ZipData*)p_userdata;
+
+ zipFile zip=(zipFile)zd->zip;
+
+ zipOpenNewFileInZip(zip,
+ path.utf8().get_data(),
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ Z_DEFLATED,
+ Z_DEFAULT_COMPRESSION);
+
+ zipWriteInFileInZip(zip,p_data.ptr(),p_data.size());
+ zipCloseFileInZip(zip);
+
+ zd->ep->step("Storing File: "+p_path,2+p_file*100/p_total,false);
+ zd->count++;
+ return OK;
+
+}
+
+Error EditorExportPlatform::save_zip(const String& p_path, bool p_make_bundles) {
+
+ EditorProgress ep("savezip","Packing",102);
+
+ //FileAccess *tmp = FileAccess::open(tmppath,FileAccess::WRITE);
+
+ FileAccess *src_f;
+ zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ zipFile zip=zipOpen2(p_path.utf8().get_data(),APPEND_STATUS_CREATE,NULL,&io);
+
+ ZipData zd;
+ zd.count=0;
+ zd.ep=&ep;
+ zd.zip=zip;
+
+
+ Error err = export_project_files(save_zip_file,&zd,p_make_bundles);
+
+ zipClose(zip,NULL);
+
+ return err;
+}
+
Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles, int p_alignment) {
EditorProgress ep("savepack","Packing",102);
@@ -1131,19 +1230,32 @@ Error EditorExportPlatformPC::export_project(const String& p_path, bool p_debug,
ep.step("Setting Up..",0);
- String exe_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
- if (use64) {
- if (p_debug)
- exe_path=custom_debug_binary!=""?custom_debug_binary:exe_path+debug_binary64;
- else
- exe_path=custom_release_binary!=""?custom_release_binary:exe_path+release_binary64;
- } else {
+ String exe_path="";
- if (p_debug)
- exe_path=custom_debug_binary!=""?custom_debug_binary:exe_path+debug_binary32;
- else
- exe_path=custom_release_binary!=""?custom_release_binary:exe_path+release_binary32;
+ if (p_debug)
+ exe_path=custom_debug_binary;
+ else
+ exe_path=custom_release_binary;
+ if (exe_path=="") {
+ String fname;
+ if (use64) {
+ if (p_debug)
+ fname=debug_binary64;
+ else
+ fname=release_binary64;
+ } else {
+ if (p_debug)
+ fname=debug_binary32;
+ else
+ fname=release_binary32;
+ }
+ String err="";
+ exe_path=find_export_template(fname,&err);
+ if (exe_path=="") {
+ EditorNode::add_io_error(err);
+ return ERR_FILE_CANT_READ;
+ }
}
FileAccess *src_exe=FileAccess::open(exe_path,FileAccess::READ);
@@ -1173,26 +1285,32 @@ Error EditorExportPlatformPC::export_project(const String& p_path, bool p_debug,
}
}
+ String dstfile = p_path.replace_first("res://","").replace("\\","/");
if (export_mode!=EXPORT_EXE) {
- String dstfile=p_path.replace_first("res://","").replace("\\","/");
+ String dstfile_extension=export_mode==EXPORT_ZIP?".zip":".pck";
if (dstfile.find("/")!=-1)
- dstfile=dstfile.get_base_dir()+"/data.pck";
+ dstfile=dstfile.get_base_dir()+"/data"+dstfile_extension;
else
- dstfile="data.pck";
+ dstfile="data"+dstfile_extension;
+ if (export_mode==EXPORT_PACK) {
- memdelete(dst);
- dst=FileAccess::open(dstfile,FileAccess::WRITE);
- if (!dst) {
+ memdelete(dst);
- EditorNode::add_io_error("Can't write data pack to:\n "+p_path);
- return ERR_FILE_CANT_WRITE;
+ dst=FileAccess::open(dstfile,FileAccess::WRITE);
+ if (!dst) {
+
+ EditorNode::add_io_error("Can't write data pack to:\n "+p_path);
+ return ERR_FILE_CANT_WRITE;
+ }
}
}
+
+
memdelete(src_exe);
- Error err = save_pack(dst,export_mode==EXPORT_BUNDLES);
+ Error err = export_mode==EXPORT_ZIP?save_zip(dstfile,bundle):save_pack(dst,bundle);
memdelete(dst);
return err;
}
@@ -1207,14 +1325,12 @@ bool EditorExportPlatformPC::can_export(String *r_error) const {
String err;
bool valid=true;
- String exe_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
-
- if (use64 && (!FileAccess::exists(exe_path+debug_binary64) || !FileAccess::exists(exe_path+release_binary64))) {
+ if (use64 && (!exists_export_template(debug_binary64)) || !exists_export_template(release_binary64)) {
valid=false;
err="No 64 bits export templates found.\nDownload and install export templates.\n";
}
- if (!use64 && (!FileAccess::exists(exe_path+debug_binary32) || !FileAccess::exists(exe_path+release_binary32))) {
+ if (!use64 && (!exists_export_template(debug_binary32) || !exists_export_template(release_binary32))) {
valid=false;
err="No 32 bits export templates found.\nDownload and install export templates.\n";
}
@@ -1562,6 +1678,17 @@ void EditorImportExport::image_export_get_images_in_group(const StringName& p_gr
}
}
+void EditorImportExport::set_convert_text_scenes(bool p_convert) {
+
+ convert_text_scenes=p_convert;
+}
+
+bool EditorImportExport::get_convert_text_scenes() const{
+
+ return convert_text_scenes;
+}
+
+
void EditorImportExport::load_config() {
Ref<ConfigFile> cf = memnew( ConfigFile );
@@ -1604,6 +1731,12 @@ void EditorImportExport::load_config() {
}
}
+ if (cf->has_section("convert_scenes")) {
+
+ convert_text_scenes = cf->get_value("convert_scenes","convert_text_scenes");
+ }
+
+
if (cf->has_section("export_filter_files")) {
@@ -1720,6 +1853,15 @@ void EditorImportExport::load_config() {
if (cf->has_section("convert_samples")) {
+ if (cf->has_section_key("convert_samples","action")) {
+ String action = cf->get_value("convert_samples","action");
+ if (action=="none") {
+ sample_action=SAMPLE_ACTION_NONE;
+ } else if (action=="compress_ram") {
+ sample_action=SAMPLE_ACTION_COMPRESS_RAM;
+ }
+ }
+
if (cf->has_section_key("convert_samples","max_hz"))
sample_action_max_hz=cf->get_value("convert_samples","max_hz");
@@ -1837,6 +1979,8 @@ void EditorImportExport::save_config() {
case SCRIPT_ACTION_ENCRYPT: cf->set_value("script","action","encrypt"); break;
}
+ cf->set_value("convert_scenes","convert_text_scenes",convert_text_scenes);
+
cf->set_value("script","encrypt_key",script_key);
switch(sample_action) {
@@ -1935,6 +2079,8 @@ EditorImportExport::EditorImportExport() {
sample_action_max_hz=44100;
sample_action_trim=false;
+ convert_text_scenes=true;
+
}
diff --git a/tools/editor/editor_import_export.h b/tools/editor/editor_import_export.h
index 1a3171e66b..272464d9b0 100644
--- a/tools/editor/editor_import_export.h
+++ b/tools/editor/editor_import_export.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,6 +33,7 @@
#include "scene/main/node.h"
#include "scene/resources/texture.h"
+
class EditorExportPlatform;
class FileAccess;
class EditorProgress;
@@ -86,6 +87,8 @@ protected:
Vector<uint8_t> get_exported_file_default(String& p_fname) const;
virtual Vector<uint8_t> get_exported_file(String& p_fname) const;
virtual Vector<StringName> get_dependencies(bool p_bundles) const;
+ virtual String find_export_template(String template_file_name, String *err=NULL) const;
+ virtual bool exists_export_template(String template_file_name, String *err=NULL) const;
struct TempData {
@@ -105,8 +108,17 @@ protected:
};
+ struct ZipData {
+
+ void* zip;
+ EditorProgress *ep;
+ int count;
+
+ };
+
void gen_export_flags(Vector<String> &r_flags, int p_flags);
static Error save_pack_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total);
+ static Error save_zip_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total);
public:
@@ -124,14 +136,17 @@ public:
enum ExportFlags {
EXPORT_DUMB_CLIENT=1,
EXPORT_REMOTE_DEBUG=2,
- EXPORT_VIEW_COLLISONS=4,
- EXPORT_VIEW_NAVIGATION=8
+ EXPORT_REMOTE_DEBUG_LOCALHOST=4,
+ EXPORT_VIEW_COLLISONS=8,
+ EXPORT_VIEW_NAVIGATION=16,
};
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, int p_alignment = 1);
+ Error save_zip(const String& p_path, bool p_make_bundles=false);
+
virtual String get_name() const =0;
virtual ImageCompression get_image_compression() const=0;
virtual Ref<Texture> get_logo() const =0;
@@ -161,8 +176,7 @@ public:
enum ExportMode {
EXPORT_EXE,
EXPORT_PACK,
- EXPORT_COPY,
- EXPORT_BUNDLES
+ EXPORT_ZIP
};
@@ -184,6 +198,7 @@ private:
Ref<Texture> logo;
ExportMode export_mode;
+ bool bundle;
protected:
bool _set(const StringName& p_name, const Variant& p_value);
@@ -284,6 +299,8 @@ protected:
int sample_action_max_hz;
bool sample_action_trim;
+ bool convert_text_scenes;
+
static EditorImportExport* singleton;
static void _bind_methods();
@@ -362,6 +379,9 @@ public:
void sample_set_trim(bool p_trim);
bool sample_get_trim() const;
+ void set_convert_text_scenes(bool p_convert);
+ bool get_convert_text_scenes() const;
+
void load_config();
void save_config();
diff --git a/tools/editor/editor_log.cpp b/tools/editor/editor_log.cpp
index 264117eecd..bcdafbb06a 100644
--- a/tools/editor/editor_log.cpp
+++ b/tools/editor/editor_log.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -79,8 +79,6 @@ void EditorLog::_notification(int p_what) {
if (p_what==NOTIFICATION_ENTER_TREE) {
log->add_color_override("default_color",get_color("font_color","Tree"));
- tb->set_normal_texture( get_icon("Collapse","EditorIcons"));
- tb->set_hover_texture( get_icon("CollapseHl","EditorIcons"));
//button->set_icon(get_icon("Console","EditorIcons"));
}
@@ -98,11 +96,6 @@ void EditorLog::_notification(int p_what) {
}
-void EditorLog::_close_request() {
-
- _flip_request();
-
-}
void EditorLog::_clear_request() {
@@ -122,17 +115,17 @@ void EditorLog::add_message(const String& p_msg,bool p_error) {
if (p_error) {
Ref<Texture> icon = get_icon("Error","EditorIcons");
log->add_image( icon );
- button->set_icon(icon);
+ //button->set_icon(icon);
log->push_color(get_color("fg_error","Editor"));
} else {
- button->set_icon(Ref<Texture>());
+ //button->set_icon(Ref<Texture>());
}
log->add_newline();
log->add_text(p_msg);
- button->set_text(p_msg);
+// button->set_text(p_msg);
if (p_error)
log->pop();
@@ -156,21 +149,7 @@ void EditorLog::_dragged(const Point2& p_ofs) {
*/
-Button *EditorLog::get_button() {
- return button;
-}
-
-void EditorLog::_flip_request() {
-
- if (is_visible()) {
- hide();
- button->show();
- } else {
- show();
- button->hide();
- }
-}
void EditorLog::_undo_redo_cbk(void *p_self,const String& p_name) {
@@ -181,21 +160,16 @@ void EditorLog::_undo_redo_cbk(void *p_self,const String& p_name) {
void EditorLog::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("_close_request"),&EditorLog::_close_request );
- ObjectTypeDB::bind_method(_MD("_flip_request"),&EditorLog::_flip_request );
ObjectTypeDB::bind_method(_MD("_clear_request"),&EditorLog::_clear_request );
//ObjectTypeDB::bind_method(_MD("_dragged"),&EditorLog::_dragged );
- ADD_SIGNAL( MethodInfo("close_request"));
- ADD_SIGNAL( MethodInfo("show_request"));
ADD_SIGNAL( MethodInfo("clear_request"));
}
EditorLog::EditorLog() {
- VBoxContainer *vb = memnew( VBoxContainer);
- add_child(vb);
- vb->set_v_size_flags(SIZE_EXPAND_FILL);
+ VBoxContainer *vb = this;
+ add_constant_override("separation",get_constant("separation","VBoxContainer"));
HBoxContainer *hb = memnew( HBoxContainer );
vb->add_child(hb);
@@ -204,14 +178,6 @@ EditorLog::EditorLog() {
title->set_h_size_flags(SIZE_EXPAND_FILL);
hb->add_child(title);
-
- button = memnew( Button );
- button->set_text_align(Button::ALIGN_LEFT);
- button->connect("pressed",this,"_flip_request");
- button->set_focus_mode(FOCUS_NONE);
- button->set_clip_text(true);
- button->set_tooltip("Open/Close output panel.");
-
//pd = memnew( PaneDrag );
//hb->add_child(pd);
//pd->connect("dragged",this,"_dragged");
@@ -222,14 +188,9 @@ EditorLog::EditorLog() {
clearbutton->set_text("Clear");
clearbutton->connect("pressed", this,"_clear_request");
- tb = memnew( TextureButton );
- hb->add_child(tb);
- tb->connect("pressed",this,"_close_request");
-
-
ec = memnew( Control);
vb->add_child(ec);
- ec->set_custom_minimum_size(Size2(0,100));
+ ec->set_custom_minimum_size(Size2(0,180));
ec->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -243,9 +204,8 @@ EditorLog::EditorLog() {
log->set_selection_enabled(true);
log->set_focus_mode(FOCUS_CLICK);
pc->add_child(log);
- add_message(VERSION_FULL_NAME" (c) 2008-2015 Juan Linietsky, Ariel Manzur.");
+ add_message(VERSION_FULL_NAME" (c) 2008-2016 Juan Linietsky, Ariel Manzur.");
//log->add_text("Initialization Complete.\n"); //because it looks cool.
- add_style_override("panel",get_stylebox("panelf","Panel"));
eh.errfunc=_error_handler;
eh.userdata=this;
@@ -255,7 +215,6 @@ EditorLog::EditorLog() {
EditorNode::get_undo_redo()->set_commit_notify_callback(_undo_redo_cbk,this);
- hide();
}
diff --git a/tools/editor/editor_log.h b/tools/editor/editor_log.h
index 93044f9a2d..699be710d8 100644
--- a/tools/editor/editor_log.h
+++ b/tools/editor/editor_log.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -40,15 +40,13 @@
#include "scene/gui/tool_button.h"
#include "pane_drag.h"
#include "os/thread.h"
-class EditorLog : public PanelContainer {
+class EditorLog : public VBoxContainer {
- OBJ_TYPE( EditorLog, PanelContainer );
+ OBJ_TYPE( EditorLog, VBoxContainer );
- Button *button;
Button *clearbutton;
Label *title;
RichTextLabel *log;
- TextureButton *tb;
HBoxContainer *title_hb;
// PaneDrag *pd;
Control *ec;
@@ -60,8 +58,6 @@ class EditorLog : public PanelContainer {
Thread::ID current;
// void _dragged(const Point2& p_ofs);
- void _close_request();
- void _flip_request();
void _clear_request();
static void _undo_redo_cbk(void *p_self,const String& p_name);
protected:
@@ -73,7 +69,7 @@ public:
void add_message(const String& p_msg, bool p_error=false);
void deinit();
- Button *get_button();
+
void clear();
EditorLog();
~EditorLog();
diff --git a/tools/editor/editor_name_dialog.cpp b/tools/editor/editor_name_dialog.cpp
new file mode 100644
index 0000000000..c221b908e0
--- /dev/null
+++ b/tools/editor/editor_name_dialog.cpp
@@ -0,0 +1,89 @@
+/*************************************************************************/
+/* editor_name_dialog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "editor_name_dialog.h"
+#include "object_type_db.h"
+#include "os/keyboard.h"
+
+void EditorNameDialog::_line_input_event(const InputEvent& p_event) {
+
+ if (p_event.type == InputEvent::KEY) {
+
+ if (!p_event.key.pressed)
+ return;
+
+ switch (p_event.key.scancode) {
+ case KEY_ENTER:
+ case KEY_RETURN: {
+
+ if (get_hide_on_ok())
+ hide();
+ ok_pressed();
+ accept_event();
+ } break;
+ case KEY_ESCAPE: {
+
+ hide();
+ accept_event();
+ } break;
+ }
+ }
+}
+
+void EditorNameDialog::_post_popup() {
+
+ ConfirmationDialog::_post_popup();
+ name->clear();
+ name->grab_focus();
+}
+
+void EditorNameDialog::ok_pressed() {
+
+ if (name->get_text()!="") {
+ emit_signal("name_confirmed", name->get_text());
+ }
+}
+
+void EditorNameDialog::_bind_methods() {
+
+ ObjectTypeDB::bind_method("_line_input_event",&EditorNameDialog::_line_input_event);
+
+ ADD_SIGNAL(MethodInfo("name_confirmed",PropertyInfo( Variant::STRING,"name")));
+}
+
+EditorNameDialog::EditorNameDialog()
+{
+ name = memnew( LineEdit );
+ add_child(name);
+ move_child(name, get_label()->get_index()+1);
+ name->set_margin(MARGIN_TOP,5);
+ name->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,5);
+ name->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,5);
+ name->connect("input_event", this, "_line_input_event");
+}
diff --git a/tools/editor/console.h b/tools/editor/editor_name_dialog.h
index aff425fcde..9e66908899 100644
--- a/tools/editor/console.h
+++ b/tools/editor/editor_name_dialog.h
@@ -1,11 +1,11 @@
/*************************************************************************/
-/* console.h */
+/* editor_name_dialog.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,91 +26,32 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CONSOLE_H
-#define CONSOLE_H
-#include "scene/gui/popup.h"
-#include "scene/gui/button.h"
-#include "scene/gui/tab_container.h"
-#include "scene/gui/tree.h"
-#include "scene/main/timer.h"
-#include "output_strings.h"
-#include "property_editor.h"
-#include "scene_tree_editor.h"
-#include "editor_data.h"
+#ifndef EDITOR_NAME_DIALOG_H
+#define EDITOR_NAME_DIALOG_H
-class Console : public Popup {
+#include "scene/gui/dialogs.h"
+#include "scene/gui/line_edit.h"
- OBJ_TYPE( Console, Popup );
+class EditorNameDialog : public ConfirmationDialog {
- TabContainer *tabs;
- OutputStrings *output;
- OutputStrings *errors;
- Control *status;
- Control *inspect;
- Control *globals;
- Button *close;
- int height;
+ OBJ_TYPE( EditorNameDialog, ConfirmationDialog );
- EditorHistory inspect_history;
- SceneTreeEditor *inspect_tree_editor;
- PropertyEditor *inspect_property_editor;
- PropertyEditor *globals_property_editor;
+ LineEdit *name;
- Tree *stats_tree;
-
- struct StatsItems {
-
- TreeItem *render_objects_in_frame;
- TreeItem *material_changes_in_frame;
-
- TreeItem *usage_video_mem_total;
- TreeItem *usage_video_mem_used;
- TreeItem *usage_texture_mem_used;
- TreeItem *usage_vertex_mem_used;
-
- TreeItem *usage_static_memory_total;
- TreeItem *usage_static_memory;
- TreeItem *usage_dynamic_memory_total;
- TreeItem *usage_dynamic_memory;
- TreeItem *usage_objects_instanced;
-
- } stats;
-
- struct OutputQueue {
-
- OutputStrings::LineType type;
- Variant meta;
- String text;
- };
-
- Mutex *output_queue_mutex;
- List<OutputQueue> output_queue;
-
-
- ErrorHandlerList err_handler;
- PrintHandlerList print_handler;
-
- void _inspector_node_selected();
-
- static void _error_handle(void *p_this,const char*p_function,const char* p_file,int p_line,const char *p_error, const char *p_explanation,ErrorHandlerType p_type);
- static void _print_handle(void *p_this,const String& p_string);
+ void _line_input_event(const InputEvent& p_event);
protected:
- virtual void _window_input_event(InputEvent p_event);
- virtual void _window_resize_event();
+ static void _bind_methods();
+ virtual void ok_pressed();
+ virtual void _post_popup();
- void _stats_update_timer_callback();
- void _resized();
- void _close_pressed();
+public:
- void _notification(int p_what);
+ LineEdit* get_line_edit() { return name; }
- static void _bind_methods();
-public:
- Console();
- ~Console();
+ EditorNameDialog();
};
-#endif // CONSOLE_H
+#endif // EDITOR_NAME_DIALOG_H
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index 7b96db56f2..9fe76a738a 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -55,6 +55,7 @@
#include "bind/core_bind.h"
#include "io/zip_io.h"
#include "io/config_file.h"
+#include "animation_editor.h"
// plugins
#include "plugins/sprite_frames_editor_plugin.h"
@@ -102,6 +103,7 @@
#include "tools/editor/io_plugins/editor_sample_import_plugin.h"
#include "tools/editor/io_plugins/editor_translation_import_plugin.h"
#include "tools/editor/io_plugins/editor_mesh_import_plugin.h"
+#include "tools/editor/io_plugins/editor_export_scene.h"
#include "plugins/editor_preview_plugins.h"
@@ -142,6 +144,7 @@ void EditorNode::_update_scene_tabs() {
}
scene_tabs->set_current_tab(editor_data.get_edited_scene());
+ scene_tabs->ensure_tab_visible(editor_data.get_edited_scene());
}
@@ -161,7 +164,7 @@ void EditorNode::_update_title() {
void EditorNode::_unhandled_input(const InputEvent& p_event) {
- if (p_event.type==InputEvent::KEY && p_event.key.pressed && !p_event.key.echo) {
+ if (p_event.type==InputEvent::KEY && p_event.key.pressed && !p_event.key.echo && !gui_base->get_viewport()->gui_has_modal_stack()) {
switch(p_event.key.scancode) {
@@ -414,7 +417,7 @@ void EditorNode::_rebuild_import_menu()
{
PopupMenu* p = import_menu->get_popup();
p->clear();
- p->add_item("Sub-Scene", FILE_IMPORT_SUBSCENE);
+ p->add_item("Node from scene", FILE_IMPORT_SUBSCENE);
p->add_separator();
for (int i = 0; i < editor_import_export->get_import_plugin_count(); i++) {
p->add_item(editor_import_export->get_import_plugin(i)->get_visible_name(), IMPORT_PLUGIN_BASE + i);
@@ -510,13 +513,21 @@ void EditorNode::save_resource_as(const Ref<Resource>& p_resource) {
file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
bool relpaths = (p_resource->has_meta("__editor_relpaths__") && p_resource->get_meta("__editor_relpaths__").operator bool());
+ current_option=RESOURCE_SAVE_AS;
List<String> extensions;
Ref<PackedScene> sd = memnew( PackedScene );
ResourceSaver::get_recognized_extensions(p_resource,&extensions);
file->clear_filters();
+
+ List<String> preferred;
for(int i=0;i<extensions.size();i++) {
+ if (p_resource->is_type("Script") && (extensions[i]=="tres" || extensions[i]=="res" || extensions[i]=="xml")) {
+ //this serves no purpose and confused people
+ continue;
+ }
file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
+ preferred.push_back(extensions[i]);
}
//file->set_current_path(current_path);
@@ -528,11 +539,11 @@ void EditorNode::save_resource_as(const Ref<Resource>& p_resource) {
file->set_current_path(p_resource->get_path().replacen("."+ext,"."+extensions.front()->get()));
}
}
- } else {
+ } else if (preferred.size()) {
String existing;
if (extensions.size()) {
- existing="new_"+p_resource->get_type().to_lower()+"."+extensions.front()->get().to_lower();
+ existing="new_"+p_resource->get_type().to_lower()+"."+preferred.front()->get().to_lower();
}
file->set_current_path(existing);
@@ -542,7 +553,6 @@ void EditorNode::save_resource_as(const Ref<Resource>& p_resource) {
}
-
void EditorNode::_menu_option(int p_option) {
_menu_option_confirm(p_option,false);
@@ -584,59 +594,66 @@ void EditorNode::_dialog_display_file_error(String p_file,Error p_error) {
}
-void EditorNode::_get_scene_metadata() {
+void EditorNode::_get_scene_metadata(const String& p_file) {
Node *scene = editor_data.get_edited_scene_root();
if (!scene)
return;
+ String path = EditorSettings::get_singleton()->get_project_settings_path().plus_file(p_file.get_file()+"-editstate-"+p_file.md5_text()+".cfg");
- if (scene->has_meta("__editor_plugin_states__")) {
+ Ref<ConfigFile> cf;
+ cf.instance();
- Dictionary md = scene->get_meta("__editor_plugin_states__");
- editor_data.set_editor_states(md);
+ Error err = cf->load(path);
+ if (err!=OK)
+ return; //must not exist
- }
+ List<String> esl;
+ cf->get_section_keys("editor_states",&esl);
- if (scene->has_meta("__editor_run_settings__")) {
+ Dictionary md;
+ for (List<String>::Element *E=esl.front();E;E=E->next()) {
- Dictionary md = scene->get_meta("__editor_run_settings__");
- if (md.has("run_mode"))
- run_settings_dialog->set_run_mode(md["run_mode"]);
- if (md.has("custom_args"))
- run_settings_dialog->set_custom_arguments(md["custom_args"]);
+ Variant st=cf->get_value("editor_states",E->get());
+ if (st.get_type()) {
+ md[E->get()]=st;
+ }
}
+
+ editor_data.set_editor_states(md);
+
}
-void EditorNode::_set_scene_metadata() {
+void EditorNode::_set_scene_metadata(const String& p_file) {
Node *scene = editor_data.get_edited_scene_root();
if (!scene)
return;
- { /* Editor States */
- Dictionary md = editor_data.get_editor_states();
-
- if (!md.empty()) {
- scene->set_meta("__editor_plugin_states__",md);
- }
- }
+ scene->set_meta("__editor_run_settings__",Variant()); //clear it (no point in keeping it)
+ scene->set_meta("__editor_plugin_states__",Variant());
- { /* Run Settings */
+ String path = EditorSettings::get_singleton()->get_project_settings_path().plus_file(p_file.get_file()+"-editstate-"+p_file.md5_text()+".cfg");
+ Ref<ConfigFile> cf;
+ cf.instance();
- Dictionary md;
- md["run_mode"]=run_settings_dialog->get_run_mode();
- md["custom_args"]=run_settings_dialog->get_custom_arguments();
- scene->set_meta("__editor_run_settings__",md);
- }
+ Dictionary md = editor_data.get_editor_states();
+ List<Variant> keys;
+ md.get_key_list(&keys);
+ for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
+ cf->set_value("editor_states",E->get(),md[E->get()]);
+ }
+ Error err = cf->save(path);
+ ERR_FAIL_COND(err!=OK);
}
@@ -954,8 +971,24 @@ void EditorNode::_save_scene(String p_file) {
}
- _set_scene_metadata();
- Ref<PackedScene> sdata = memnew( PackedScene );
+ _set_scene_metadata(p_file);
+
+
+ Ref<PackedScene> sdata;
+
+ if (ResourceCache::has(p_file)) {
+ // something may be referencing this resource and we are good with that.
+ // we must update it, but also let the previous scene state go, as
+ // old version still work for referencing changes in instanced or inherited scenes
+
+ sdata = Ref<PackedScene>( ResourceCache::get(p_file)->cast_to<PackedScene>() );
+ if (sdata.is_valid())
+ sdata->recreate_state();
+ else
+ sdata.instance();
+ } else {
+ sdata.instance();
+ }
Error err = sdata->pack(scene);
@@ -1162,75 +1195,6 @@ void EditorNode::_dialog_action(String p_file) {
save_translatable_strings(p_file);
} break;
- case FILE_SAVE_SUBSCENE: {
-
- List<Node*> selection = editor_selection->get_selected_node_list();
-
- if (selection.size()!=1) {
-
- current_option=-1;
- //confirmation->get_cancel()->hide();
- accept->get_ok()->set_text("I see..");
- accept->set_text("This operation requieres a single selected node.");
- accept->popup_centered_minsize();
- break;
- }
-
- Node *base = selection.front()->get();
-
- Map<Node*,Node*> reown;
- reown[editor_data.get_edited_scene_root()]=base;
- Node *copy = base->duplicate_and_reown(reown);
- if (copy) {
-
- Ref<PackedScene> sdata = memnew( PackedScene );
- Error err = sdata->pack(copy);
- memdelete(copy);
-
- if (err!=OK) {
-
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text("I see..");
- accept->set_text("Couldn't save subscene. Likely dependencies (instances) couldn't be satisfied.");
- accept->popup_centered_minsize();
- return;
- }
-
- int flg=0;
- if (EditorSettings::get_singleton()->get("on_save/compress_binary_resources"))
- flg|=ResourceSaver::FLAG_COMPRESS;
- if (EditorSettings::get_singleton()->get("on_save/save_paths_as_relative"))
- flg|=ResourceSaver::FLAG_RELATIVE_PATHS;
-
-
- err = ResourceSaver::save(p_file,sdata,flg);
- if (err!=OK) {
-
- current_option=-1;
- //confirmation->get_cancel()->hide();
- accept->get_ok()->set_text("I see..");
- accept->set_text("Error saving scene.");
- accept->popup_centered_minsize();
- break;
- }
- //EditorFileSystem::get_singleton()->update_file(p_file,sdata->get_type());
-
- } else {
-
- current_option=-1;
- //confirmation->get_cancel()->hide();
- accept->get_ok()->set_text("I see..");
- accept->set_text("Error duplicating scene to save it.");
- accept->popup_centered_minsize();
- break;
-
- }
-
-
- } break;
-
case FILE_SAVE_SCENE:
case FILE_SAVE_AS_SCENE: {
@@ -1290,10 +1254,18 @@ void EditorNode::_dialog_action(String p_file) {
case FILE_EXPORT_TILESET: {
Ref<TileSet> ml;
- if (file_export_lib_merge->is_pressed() && FileAccess::exists(p_file)) {
+ if (FileAccess::exists(p_file)) {
ml=ResourceLoader::load(p_file,"TileSet");
- if (ml.is_null()) {
+ if (!file_export_lib_merge->is_pressed()) {
+ ml->clear();
+ }
+
+ }
+
+ if (ml.is_null()) {
+
+ if (file_export_lib_merge->is_pressed()) {
current_option=-1;
//accept->get_cancel()->hide();
accept->get_ok()->set_text("I see..");
@@ -1302,9 +1274,6 @@ void EditorNode::_dialog_action(String p_file) {
return;
}
- }
-
- if (ml.is_null()) {
ml = Ref<TileSet>( memnew( TileSet ));
}
@@ -1409,6 +1378,65 @@ void EditorNode::_dialog_action(String p_file) {
save_resource_in_path(current_res,p_file);
} break;
+ case SETTINGS_LAYOUT_SAVE: {
+
+ if (p_file.empty())
+ return;
+
+ Ref<ConfigFile> config;
+ config.instance();
+ Error err = config->load(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts.cfg"));
+
+ if (err==ERR_CANT_OPEN) {
+ config.instance(); // new config
+ } else if (err!=OK) {
+ show_warning("Error trying to save layout!");
+ return;
+ }
+
+ _save_docks_to_config(config, p_file);
+
+ config->save(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts.cfg"));
+
+ layout_dialog->hide();
+ _update_layouts_menu();
+
+ if (p_file=="Default") {
+ show_warning("Default editor layout overridden.");
+ }
+
+ } break;
+ case SETTINGS_LAYOUT_DELETE: {
+
+ if (p_file.empty())
+ return;
+
+ Ref<ConfigFile> config;
+ config.instance();
+ Error err = config->load(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts.cfg"));
+
+ if (err!=OK || !config->has_section(p_file)) {
+ show_warning("Layout name not found!");
+ return;
+ }
+
+ // erase
+ List<String> keys;
+ config->get_section_keys(p_file, &keys);
+ for (List<String>::Element *E=keys.front();E;E=E->next()) {
+ config->set_value(p_file, E->get(), Variant());
+ }
+
+ config->save(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts.cfg"));
+
+ layout_dialog->hide();
+ _update_layouts_menu();
+
+ if (p_file=="Default") {
+ show_warning("Restored Default layout to base settings.");
+ }
+
+ } break;
default: { //save scene?
if (file->get_mode()==FileDialog::MODE_SAVE_FILE) {
@@ -1562,6 +1590,10 @@ void EditorNode::_edit_current() {
scene_tree_dock->set_selected(NULL);
property_editor->edit( NULL );
object_menu->set_disabled(true);
+
+ if (editor_plugin_over)
+ editor_plugin_over->make_visible(false);
+
return;
}
@@ -1710,7 +1742,7 @@ void EditorNode::_edit_current() {
//p->add_item("All Methods",OBJECT_CALL_METHOD);
- _update_keying();
+ update_keying();
}
void EditorNode::_resource_created() {
@@ -1749,7 +1781,7 @@ void EditorNode::_run(bool p_current,const String& p_custom) {
}
play_button->set_pressed(false);
- play_button->set_icon(gui_base->get_icon("Play","EditorIcons"));
+ play_button->set_icon(gui_base->get_icon("MainPlay","EditorIcons"));
//pause_button->set_pressed(false);
play_scene_button->set_pressed(false);
play_scene_button->set_icon(gui_base->get_icon("PlayScene","EditorIcons"));
@@ -1976,21 +2008,21 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
} break;
case FILE_QUICK_OPEN_SCENE: {
- quick_open->popup("PackedScene");
+ quick_open->popup("PackedScene", true);
quick_open->set_title("Quick Open Scene..");
} break;
case FILE_QUICK_OPEN_SCRIPT: {
- quick_open->popup("Script");
+ quick_open->popup("Script", true);
quick_open->set_title("Quick Open Script..");
} break;
case FILE_QUICK_OPEN_FILE: {
- quick_open->popup("Resource",false,true);
+ quick_open->popup("Resource", false, true);
quick_open->set_title("Quick Search File..");
} break;
@@ -2008,7 +2040,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
} break;
case FILE_CLOSE: {
- if (!p_confirmed) {
+ if (!p_confirmed && unsaved_cache) {
confirmation->get_ok()->set_text("Yes");
//confirmation->get_cancel()->show();
confirmation->set_text("Close scene? (Unsaved changes will be lost)");
@@ -2037,7 +2069,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
return;
};
// fallthrough to save_as
- } break;
+ };
case FILE_SAVE_AS_SCENE: {
Node *scene = editor_data.get_edited_scene_root();
@@ -2141,70 +2173,6 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
file->set_title("Save Translatable Strings");
file->popup_centered_ratio();
-
- } break;
-
- case FILE_SAVE_SUBSCENE: {
-
- Node *scene = editor_data.get_edited_scene_root();
-
- if (!scene) {
-
- current_option=-1;
- //confirmation->get_cancel()->hide();
- accept->get_ok()->set_text("I see..");
- accept->set_text("This operation can't be done without a scene.");
- accept->popup_centered_minsize();
- break;
- }
-
-
- List<Node*> selection = editor_selection->get_selected_node_list();
-
- if (selection.size()!=1) {
-
- current_option=-1;
- //confirmation->get_cancel()->hide();
- accept->get_ok()->set_text("I see..");
- accept->set_text("This operation requieres a single selected node.");
- accept->popup_centered_minsize();
- break;
- }
-
- Node *tocopy = selection.front()->get();
-
- if (tocopy!=editor_data.get_edited_scene_root() && tocopy->get_filename()!="") {
-
-
- current_option=-1;
- //confirmation->get_cancel()->hide();
- accept->get_ok()->set_text("I see..");
- accept->set_text("This operation can't be done on instanced scenes.");
- accept->popup_centered_minsize();
- break;
- }
-
- file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
-
- List<String> extensions;
- Ref<PackedScene> sd = memnew( PackedScene );
- ResourceSaver::get_recognized_extensions(sd,&extensions);
- file->clear_filters();
- for(int i=0;i<extensions.size();i++) {
-
- file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
- }
-
-
- String existing;
- if (extensions.size()) {
- existing="new_scene."+extensions.front()->get().to_lower();
- }
- file->set_current_path(existing);
-
-
- file->popup_centered_ratio();
- file->set_title("Save Sub-Scene As..");
} break;
case FILE_SAVE_OPTIMIZED: {
Node *scene = editor_data.get_edited_scene_root();
@@ -2399,7 +2367,14 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
if (!scene)
break;
-
+
+ String filename = scene->get_filename();
+
+ if (filename==String()) {
+ show_warning("Can't reload a scene that was never saved..");
+ break;
+ }
+
if (unsaved_cache && !p_confirmed) {
confirmation->get_ok()->set_text("Revert");
confirmation->set_text("This action cannot be undone. Revert anyway?");
@@ -2407,7 +2382,13 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
break;
}
- Error err = load_scene(scene->get_filename());
+
+ int cur_idx = editor_data.get_edited_scene();
+ _remove_edited_scene();
+ Error err = load_scene(filename);
+ editor_data.move_edited_scene_to_index(cur_idx);
+ get_undo_redo()->clear_history();
+ scene_tabs->set_current_tab(cur_idx);
} break;
@@ -2621,7 +2602,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
editor_run.stop();
play_button->set_pressed(false);
- play_button->set_icon(gui_base->get_icon("Play","EditorIcons"));
+ play_button->set_icon(gui_base->get_icon("MainPlay","EditorIcons"));
play_scene_button->set_pressed(false);
play_scene_button->set_icon(gui_base->get_icon("PlayScene","EditorIcons"));
//pause_button->set_pressed(false);
@@ -2746,11 +2727,6 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
//optimized_presets->popup_centered_ratio();
} break;
- case SETTINGS_SHOW_ANIMATION: {
-
- animation_panel_make_visible( ! animation_panel->is_visible() );
-
- } break;
case SETTINGS_LOAD_EXPORT_TEMPLATES: {
@@ -3000,7 +2976,7 @@ void EditorNode::set_edited_scene(Node *p_scene) {
if (get_editor_data().get_edited_scene_root()) {
if (get_editor_data().get_edited_scene_root()->get_parent()==scene_root)
scene_root->remove_child(get_editor_data().get_edited_scene_root());
- animation_editor->set_root(NULL);
+
}
get_editor_data().set_edited_scene_root(p_scene);
@@ -3013,7 +2989,7 @@ void EditorNode::set_edited_scene(Node *p_scene) {
if (p_scene) {
if (p_scene->get_parent()!=scene_root)
scene_root->add_child(p_scene);
- animation_editor->set_root(p_scene);
+
}
}
@@ -3069,7 +3045,7 @@ Error EditorNode::save_translatable_strings(const String& p_to_file) {
OS::Time time = OS::get_singleton()->get_time();
f->store_line("# Translation Strings Dump.");
f->store_line("# Created By.");
- f->store_line("# \t" VERSION_FULL_NAME " (c) 2008-2015 Juan Linietsky, Ariel Manzur.");
+ f->store_line("# \t" VERSION_FULL_NAME " (c) 2008-2016 Juan Linietsky, Ariel Manzur.");
f->store_line("# From Scene: ");
f->store_line("# \t"+get_edited_scene()->get_filename());
f->store_line("");
@@ -3332,6 +3308,8 @@ void EditorNode::_set_main_scene_state(Dictionary p_state) {
//changing_scene=true; //avoid script change from opening editor
ScriptEditor::get_singleton()->get_debugger()->update_live_edit_root();
ScriptEditor::get_singleton()->set_scene_root_script( editor_data.get_scene_root_script(editor_data.get_edited_scene()) );
+ editor_data.notify_edited_scene_changed();
+
//changing_scene=false;
}
@@ -3345,15 +3323,25 @@ void EditorNode::set_current_version(uint64_t p_version) {
bool EditorNode::is_changing_scene() const {
return changing_scene;
}
+
+void EditorNode::_clear_undo_history() {
+
+ get_undo_redo()->clear_history();
+}
+
void EditorNode::set_current_scene(int p_idx) {
+ if (editor_data.check_and_update_scene(p_idx)) {
+ call_deferred("_clear_undo_history");
+ }
+
changing_scene=true;
editor_data.save_edited_scene_state(editor_selection,&editor_history,_get_main_scene_state());
if (get_editor_data().get_edited_scene_root()) {
if (get_editor_data().get_edited_scene_root()->get_parent()==scene_root)
scene_root->remove_child(get_editor_data().get_edited_scene_root());
- animation_editor->set_root(NULL);
+
}
//print_line("set current 2 ");
@@ -3375,7 +3363,7 @@ void EditorNode::set_current_scene(int p_idx) {
if (new_scene) {
if (new_scene->get_parent()!=scene_root)
scene_root->add_child(new_scene);
- animation_editor->set_root(new_scene);
+
}
//print_line("set current 4 ");
@@ -3423,11 +3411,13 @@ Error EditorNode::load_scene(const String& p_scene, bool p_ignore_broken_deps,bo
}
- for(int i=0;i<editor_data.get_edited_scene_count();i++) {
+ if(!p_set_inherited) {
+ for(int i=0;i<editor_data.get_edited_scene_count();i++) {
- if (editor_data.get_scene_path(i)==p_scene) {
- _scene_tab_changed(i);
- return OK;
+ if (editor_data.get_scene_path(i)==p_scene) {
+ _scene_tab_changed(i);
+ return OK;
+ }
}
}
@@ -3509,7 +3499,18 @@ Error EditorNode::load_scene(const String& p_scene, bool p_ignore_broken_deps,bo
add_io_error(txt);
}
- sdata->set_path(lpath,true); //take over path
+ if (ResourceCache::has(lpath)) {
+ //used from somewhere else? no problem! update state and replace sdata
+ Ref<PackedScene> ps = Ref<PackedScene>( ResourceCache::get(lpath)->cast_to<PackedScene>() );
+ if (ps.is_valid()) {
+ ps->replace_state( sdata->get_state() );
+ ps->set_last_modified_time( sdata->get_last_modified_time() );
+ sdata=ps;
+ }
+
+ } else {
+ sdata->set_path(lpath,true); //take over path
+ }
Node*new_scene=sdata->instance(true);
@@ -3557,7 +3558,7 @@ Error EditorNode::load_scene(const String& p_scene, bool p_ignore_broken_deps,bo
new_scene->set_scene_instance_state(Ref<SceneState>());
set_edited_scene(new_scene);
- _get_scene_metadata();
+ _get_scene_metadata(p_scene);
/*
editor_data.set_edited_scene_root(new_scene);
@@ -3628,7 +3629,7 @@ void EditorNode::_instance_request(const String& p_path){
void EditorNode::_property_keyed(const String& p_keyed,const Variant& p_value,bool p_advance) {
- animation_editor->insert_value_key(p_keyed,p_value,p_advance);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_value_key(p_keyed,p_value,p_advance);
}
void EditorNode::_transform_keyed(Object *sp,const String& p_sub,const Transform& p_key) {
@@ -3636,16 +3637,16 @@ void EditorNode::_transform_keyed(Object *sp,const String& p_sub,const Transform
Spatial *s=sp->cast_to<Spatial>();
if (!s)
return;
- animation_editor->insert_transform_key(s,p_sub,p_key);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_transform_key(s,p_sub,p_key);
}
-void EditorNode::_update_keying() {
+void EditorNode::update_keying() {
//print_line("KR: "+itos(p_enabled));
bool valid=false;
- if (animation_editor->has_keying()) {
+ if (AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) {
if (editor_history.get_path_size()>=1) {
@@ -3679,6 +3680,7 @@ void EditorNode::_show_messages() {
}
+#if 0
void EditorNode::animation_panel_make_visible(bool p_visible) {
if (!p_visible) {
@@ -3691,6 +3693,7 @@ void EditorNode::animation_panel_make_visible(bool p_visible) {
settings_menu->get_popup()->set_item_checked(idx,p_visible);
}
+
void EditorNode::animation_editor_make_visible(bool p_visible) {
if (p_visible) {
@@ -3712,10 +3715,9 @@ void EditorNode::animation_editor_make_visible(bool p_visible) {
}
animation_editor->set_keying(p_visible);
- _update_keying();
}
-
+#endif
void EditorNode::_add_to_recent_scenes(const String& p_scene) {
String base="_"+Globals::get_singleton()->get_resource_path().replace("\\","::").replace("/","::");
@@ -3808,24 +3810,26 @@ void EditorNode::_update_recent_scenes() {
}
-void EditorNode::hide_animation_player_editors() {
-
- emit_signal("hide_animation_player_editors");
-}
-
-void EditorNode::_quick_opened(const String& p_resource) {
+void EditorNode::_quick_opened() {
if (current_option==FILE_QUICK_OPEN_FILE) {
- scenes_dock->open(p_resource);
+ String res_path = quick_open->get_selected();
+
+ scenes_dock->open(res_path);
return;
}
- if (quick_open->get_base_type()=="PackedScene") {
- open_request(p_resource);
- } else {
- load_resource(p_resource);
- }
+ Vector<String> files = quick_open->get_selected_files();
+
+ for (int i = 0; i < files.size(); i++) {
+ String res_path = files[i];
+ if (quick_open->get_base_type()=="PackedScene") {
+ open_request(res_path);
+ } else {
+ load_resource(res_path);
+ }
+ }
}
void EditorNode::_quick_run(const String& p_resource) {
@@ -3945,9 +3949,9 @@ void EditorNode::progress_add_task(const String& p_task,const String& p_label, i
singleton->progress_dialog->add_task(p_task,p_label,p_steps);
}
-void EditorNode::progress_task_step(const String& p_task, const String& p_state, int p_step) {
+void EditorNode::progress_task_step(const String& p_task, const String& p_state, int p_step,bool p_force_redraw) {
- singleton->progress_dialog->task_step(p_task,p_state,p_step);
+ singleton->progress_dialog->task_step(p_task,p_state,p_step,p_force_redraw);
}
@@ -3976,87 +3980,6 @@ void EditorNode::progress_end_task_bg(const String& p_task) {
}
-void EditorNode::_bind_methods() {
-
-
- ObjectTypeDB::bind_method("_menu_option",&EditorNode::_menu_option);
- ObjectTypeDB::bind_method("_menu_confirm_current",&EditorNode::_menu_confirm_current);
- ObjectTypeDB::bind_method("_dialog_action",&EditorNode::_dialog_action);
- ObjectTypeDB::bind_method("_resource_selected",&EditorNode::_resource_selected,DEFVAL(""));
- ObjectTypeDB::bind_method("_property_editor_forward",&EditorNode::_property_editor_forward);
- ObjectTypeDB::bind_method("_property_editor_back",&EditorNode::_property_editor_back);
- ObjectTypeDB::bind_method("_editor_select",&EditorNode::_editor_select);
- ObjectTypeDB::bind_method("_node_renamed",&EditorNode::_node_renamed);
- ObjectTypeDB::bind_method("edit_node",&EditorNode::edit_node);
- ObjectTypeDB::bind_method("_imported",&EditorNode::_imported);
- ObjectTypeDB::bind_method("_unhandled_input",&EditorNode::_unhandled_input);
-
- ObjectTypeDB::bind_method("_get_scene_metadata",&EditorNode::_get_scene_metadata);
- ObjectTypeDB::bind_method("set_edited_scene",&EditorNode::set_edited_scene);
- ObjectTypeDB::bind_method("open_request",&EditorNode::open_request);
- ObjectTypeDB::bind_method("_instance_request",&EditorNode::_instance_request);
- ObjectTypeDB::bind_method("_update_keying",&EditorNode::_update_keying);
- ObjectTypeDB::bind_method("_property_keyed",&EditorNode::_property_keyed);
- ObjectTypeDB::bind_method("_transform_keyed",&EditorNode::_transform_keyed);
- ObjectTypeDB::bind_method("_close_messages",&EditorNode::_close_messages);
- ObjectTypeDB::bind_method("_show_messages",&EditorNode::_show_messages);
- ObjectTypeDB::bind_method("_vp_resized",&EditorNode::_vp_resized);
- ObjectTypeDB::bind_method("_quick_opened",&EditorNode::_quick_opened);
- ObjectTypeDB::bind_method("_quick_run",&EditorNode::_quick_run);
-
- ObjectTypeDB::bind_method("_resource_created",&EditorNode::_resource_created);
-
- ObjectTypeDB::bind_method("_import_action",&EditorNode::_import_action);
- //ObjectTypeDB::bind_method("_import",&EditorNode::_import);
-// ObjectTypeDB::bind_method("_import_conflicts_solved",&EditorNode::_import_conflicts_solved);
- ObjectTypeDB::bind_method("_open_recent_scene",&EditorNode::_open_recent_scene);
-// ObjectTypeDB::bind_method("_open_recent_scene_confirm",&EditorNode::_open_recent_scene_confirm);
-
- ObjectTypeDB::bind_method("_save_optimized",&EditorNode::_save_optimized);
- ObjectTypeDB::bind_method(_MD("animation_panel_make_visible","enable"),&EditorNode::animation_panel_make_visible);
-
- ObjectTypeDB::bind_method("stop_child_process",&EditorNode::stop_child_process);
-
- ObjectTypeDB::bind_method("_sources_changed",&EditorNode::_sources_changed);
- ObjectTypeDB::bind_method("_fs_changed",&EditorNode::_fs_changed);
- ObjectTypeDB::bind_method("_dock_select_draw",&EditorNode::_dock_select_draw);
- ObjectTypeDB::bind_method("_dock_select_input",&EditorNode::_dock_select_input);
- ObjectTypeDB::bind_method("_dock_pre_popup",&EditorNode::_dock_pre_popup);
- ObjectTypeDB::bind_method("_dock_split_dragged",&EditorNode::_dock_split_dragged);
- ObjectTypeDB::bind_method("_save_docks",&EditorNode::_save_docks);
- ObjectTypeDB::bind_method("_dock_popup_exit",&EditorNode::_dock_popup_exit);
- ObjectTypeDB::bind_method("_dock_move_left",&EditorNode::_dock_move_left);
- ObjectTypeDB::bind_method("_dock_move_right",&EditorNode::_dock_move_right);
-
- ObjectTypeDB::bind_method("set_current_scene",&EditorNode::set_current_scene);
- ObjectTypeDB::bind_method("set_current_version",&EditorNode::set_current_version);
- ObjectTypeDB::bind_method("_scene_tab_changed",&EditorNode::_scene_tab_changed);
- ObjectTypeDB::bind_method("_scene_tab_closed",&EditorNode::_scene_tab_closed);
- ObjectTypeDB::bind_method("_scene_tab_script_edited",&EditorNode::_scene_tab_script_edited);
- ObjectTypeDB::bind_method("_set_main_scene_state",&EditorNode::_set_main_scene_state);
- ObjectTypeDB::bind_method("_update_scene_tabs",&EditorNode::_update_scene_tabs);
-
- ObjectTypeDB::bind_method("_prepare_history",&EditorNode::_prepare_history);
- ObjectTypeDB::bind_method("_select_history",&EditorNode::_select_history);
-
- ObjectTypeDB::bind_method("_toggle_search_bar",&EditorNode::_toggle_search_bar);
- ObjectTypeDB::bind_method("_clear_search_box",&EditorNode::_clear_search_box);
-
- ObjectTypeDB::bind_method(_MD("add_editor_import_plugin", "plugin"), &EditorNode::add_editor_import_plugin);
- ObjectTypeDB::bind_method(_MD("remove_editor_import_plugin", "plugin"), &EditorNode::remove_editor_import_plugin);
- ObjectTypeDB::bind_method(_MD("get_gui_base"), &EditorNode::get_gui_base);
-
- ADD_SIGNAL( MethodInfo("play_pressed") );
- ADD_SIGNAL( MethodInfo("pause_pressed") );
- ADD_SIGNAL( MethodInfo("stop_pressed") );
- ADD_SIGNAL( MethodInfo("hide_animation_player_editors") );
- ADD_SIGNAL( MethodInfo("request_help") );
- ADD_SIGNAL( MethodInfo("script_add_function_request",PropertyInfo(Variant::OBJECT,"obj"),PropertyInfo(Variant::STRING,"function"),PropertyInfo(Variant::STRING_ARRAY,"args")) );
- ADD_SIGNAL( MethodInfo("resource_saved",PropertyInfo(Variant::OBJECT,"obj")) );
-
-
-
-}
Ref<Texture> EditorNode::_file_dialog_get_icon(const String& p_path) {
@@ -4322,6 +4245,15 @@ void EditorNode::_save_docks() {
Ref<ConfigFile> config;
config.instance();
+ _save_docks_to_config(config, "docks");
+ editor_data.get_plugin_window_layout(config);
+
+ config->save(EditorSettings::get_singleton()->get_project_settings_path().plus_file("editor_layout.cfg"));
+
+}
+
+void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String& p_section) {
+
for(int i=0;i<DOCK_SLOT_MAX;i++) {
String names;
for(int j=0;j<dock_slot[i]->get_tab_count();j++) {
@@ -4332,7 +4264,7 @@ void EditorNode::_save_docks() {
}
if (names!="") {
- config->set_value("docks","dock_"+itos(i+1),names);
+ p_layout->set_value(p_section,"dock_"+itos(i+1),names);
}
}
@@ -4346,7 +4278,7 @@ void EditorNode::_save_docks() {
for(int i=0;i<DOCK_SLOT_MAX/2;i++) {
if (splits[i]->is_visible()) {
- config->set_value("docks","dock_split_"+itos(i+1),splits[i]->get_split_offset());
+ p_layout->set_value(p_section,"dock_split_"+itos(i+1),splits[i]->get_split_offset());
}
}
@@ -4360,13 +4292,9 @@ void EditorNode::_save_docks() {
for(int i=0;i<4;i++) {
- config->set_value("docks","dock_hsplit_"+itos(i+1),h_splits[i]->get_split_offset());
+ p_layout->set_value(p_section,"dock_hsplit_"+itos(i+1),h_splits[i]->get_split_offset());
}
- editor_data.get_plugin_window_layout(config);
-
- config->save(EditorSettings::get_singleton()->get_project_settings_path().plus_file("editor_layout.cfg"));
-
}
void EditorNode::save_layout() {
@@ -4385,15 +4313,26 @@ void EditorNode::_load_docks() {
config.instance();
Error err = config->load(EditorSettings::get_singleton()->get_project_settings_path().plus_file("editor_layout.cfg"));
if (err!=OK) {
- return; //no config
+ //no config
+ if (overridden_default_layout>=0) {
+ _layout_menu_option(overridden_default_layout);
+ }
+ return;
}
+ _load_docks_from_config(config, "docks");
+ editor_data.set_plugin_window_layout(config);
+
+}
+
+void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String& p_section) {
+
for(int i=0;i<DOCK_SLOT_MAX;i++) {
- if (!config->has_section_key("docks","dock_"+itos(i+1)))
+ if (!p_layout->has_section_key(p_section,"dock_"+itos(i+1)))
continue;
- Vector<String> names = String(config->get_value("docks","dock_"+itos(i+1))).split(",");
+ Vector<String> names = String(p_layout->get_value(p_section,"dock_"+itos(i+1))).split(",");
for(int j=0;j<names.size();j++) {
@@ -4413,7 +4352,7 @@ void EditorNode::_load_docks() {
if (atidx==-1) //well, it's not anywhere
continue;
- if (atidx==j) {
+ if (atidx==i) {
node->raise();
continue;
}
@@ -4428,7 +4367,6 @@ void EditorNode::_load_docks() {
dock_slot[i]->add_child(node);
dock_slot[i]->show();
}
-
}
VSplitContainer*splits[DOCK_SLOT_MAX/2]={
@@ -4440,14 +4378,14 @@ void EditorNode::_load_docks() {
for(int i=0;i<DOCK_SLOT_MAX/2;i++) {
- if (!config->has_section_key("docks","dock_split_"+itos(i+1)))
+ if (!p_layout->has_section_key(p_section,"dock_split_"+itos(i+1)))
continue;
- int ofs = config->get_value("docks","dock_split_"+itos(i+1));
+ int ofs = p_layout->get_value(p_section,"dock_split_"+itos(i+1));
splits[i]->set_split_offset(ofs);
}
- HSplitContainer *h_splits[4]={
+ HSplitContainer*h_splits[4]={
left_l_hsplit,
left_r_hsplit,
main_hsplit,
@@ -4455,9 +4393,9 @@ void EditorNode::_load_docks() {
};
for(int i=0;i<4;i++) {
- if (!config->has_section_key("docks","dock_hsplit_"+itos(i+1)))
+ if (!p_layout->has_section_key(p_section,"dock_hsplit_"+itos(i+1)))
continue;
- int ofs = config->get_value("docks","dock_hsplit_"+itos(i+1));
+ int ofs = p_layout->get_value(p_section,"dock_hsplit_"+itos(i+1));
h_splits[i]->set_split_offset(ofs);
}
@@ -4475,8 +4413,80 @@ void EditorNode::_load_docks() {
dock_slot[i]->set_current_tab(0);
}
}
+}
- editor_data.set_plugin_window_layout(config);
+
+void EditorNode::_update_layouts_menu() {
+
+ editor_layouts->clear();
+ overridden_default_layout=-1;
+
+ editor_layouts->set_size(Vector2());
+ editor_layouts->add_item("Save Layout", SETTINGS_LAYOUT_SAVE);
+ editor_layouts->add_item("Delete Layout", SETTINGS_LAYOUT_DELETE);
+ editor_layouts->add_separator();
+ editor_layouts->add_item("Default", SETTINGS_LAYOUT_DEFAULT);
+
+ Ref<ConfigFile> config;
+ config.instance();
+ Error err = config->load(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts.cfg"));
+ if (err!=OK) {
+ return; //no config
+ }
+
+ List<String> layouts;
+ config.ptr()->get_sections(&layouts);
+
+ for (List<String>::Element *E=layouts.front();E;E=E->next()) {
+
+ String layout=E->get();
+
+ if (layout=="Default") {
+ editor_layouts->remove_item(editor_layouts->get_item_index(SETTINGS_LAYOUT_DEFAULT));
+ overridden_default_layout=editor_layouts->get_item_count();
+ }
+
+ editor_layouts->add_item(layout);
+ }
+
+}
+
+void EditorNode::_layout_menu_option(int p_id) {
+
+ switch (p_id) {
+
+ case SETTINGS_LAYOUT_SAVE: {
+
+ current_option=p_id;
+ layout_dialog->set_title("Save Layout");
+ layout_dialog->get_ok()->set_text("Save");
+ layout_dialog->popup_centered();
+ } break;
+ case SETTINGS_LAYOUT_DELETE: {
+
+ current_option=p_id;
+ layout_dialog->set_title("Delete Layout");
+ layout_dialog->get_ok()->set_text("Delete");
+ layout_dialog->popup_centered();
+ } break;
+ case SETTINGS_LAYOUT_DEFAULT: {
+
+ _load_docks_from_config(default_layout, "docks");
+ _save_docks();
+ } break;
+ default: {
+
+ Ref<ConfigFile> config;
+ config.instance();
+ Error err = config->load(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts.cfg"));
+ if (err!=OK) {
+ return; //no config
+ }
+
+ _load_docks_from_config(config, editor_layouts->get_item_text(p_id));
+ _save_docks();
+ }
+ }
}
@@ -4523,12 +4533,14 @@ void EditorNode::_scene_tab_changed(int p_tab) {
editor_data.get_undo_redo().create_action("Switch Scene Tab");
editor_data.get_undo_redo().add_do_method(this,"set_current_version",unsaved?saved_version:0);
editor_data.get_undo_redo().add_do_method(this,"set_current_scene",p_tab);
- editor_data.get_undo_redo().add_do_method(scene_tabs,"set_current_tab",p_tab);
+ //editor_data.get_undo_redo().add_do_method(scene_tabs,"set_current_tab",p_tab);
+ //editor_data.get_undo_redo().add_do_method(scene_tabs,"ensure_tab_visible",p_tab);
editor_data.get_undo_redo().add_do_method(this,"set_current_version",next_scene_version==0?editor_data.get_undo_redo().get_version()+1:next_scene_version);
editor_data.get_undo_redo().add_undo_method(this,"set_current_version",next_scene_version);
editor_data.get_undo_redo().add_undo_method(this,"set_current_scene",editor_data.get_edited_scene());
- editor_data.get_undo_redo().add_undo_method(scene_tabs,"set_current_tab",editor_data.get_edited_scene());
+ //editor_data.get_undo_redo().add_undo_method(scene_tabs,"set_current_tab",editor_data.get_edited_scene());
+ //editor_data.get_undo_redo().add_undo_method(scene_tabs,"ensure_tab_visible",p_tab,editor_data.get_edited_scene());
editor_data.get_undo_redo().add_undo_method(this,"set_current_version",saved_version);
editor_data.get_undo_redo().commit_action();
@@ -4558,6 +4570,173 @@ void EditorNode::_clear_search_box() {
property_editor->update_tree();
}
+ToolButton *EditorNode::add_bottom_panel_item(String p_text,Control *p_item) {
+
+ ToolButton *tb = memnew( ToolButton );
+ tb->connect("toggled",this,"_bottom_panel_switch",varray(bottom_panel_items.size()));
+ tb->set_text(p_text);
+ tb->set_toggle_mode(true);
+ tb->set_focus_mode(Control::FOCUS_NONE);
+ bottom_panel_vb->add_child(p_item);
+ bottom_panel_hb->raise();
+ bottom_panel_hb->add_child(tb);
+ p_item->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ p_item->hide();
+ BottomPanelItem bpi;
+ bpi.button=tb;
+ bpi.control=p_item;
+ bpi.name=p_text;
+ bottom_panel_items.push_back(bpi);
+
+ return tb;
+
+}
+
+void EditorNode::hide_bottom_panel() {
+
+ _bottom_panel_switch(false,0);
+
+}
+
+void EditorNode::make_bottom_panel_item_visible(Control *p_item) {
+
+ for(int i=0;i<bottom_panel_items.size();i++) {
+
+ if (bottom_panel_items[i].control==p_item) {
+ _bottom_panel_switch(true,i);
+ break;
+ }
+ }
+}
+
+void EditorNode::raise_bottom_panel_item(Control *p_item) {
+
+ for(int i=0;i<bottom_panel_items.size();i++) {
+
+ if (bottom_panel_items[i].control==p_item) {
+ bottom_panel_items[i].button->raise();
+ SWAP( bottom_panel_items[i], bottom_panel_items[bottom_panel_items.size()-1]);
+ break;
+ }
+ }
+
+ for(int i=0;i<bottom_panel_items.size();i++) {
+ bottom_panel_items[i].button->disconnect("toggled",this,"_bottom_panel_switch");
+ bottom_panel_items[i].button->connect("toggled",this,"_bottom_panel_switch",varray(i));
+ }
+
+}
+
+void EditorNode::_bottom_panel_switch(bool p_enable,int p_idx) {
+
+ ERR_FAIL_INDEX(p_idx,bottom_panel_items.size());
+
+
+
+ if (p_enable) {
+ for(int i=0;i<bottom_panel_items.size();i++) {
+
+ bottom_panel_items[i].button->set_pressed(i==p_idx);
+ bottom_panel_items[i].control->set_hidden(i!=p_idx);
+ }
+ center_split->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE);
+ center_split->set_collapsed(false);
+ } else {
+ for(int i=0;i<bottom_panel_items.size();i++) {
+
+ bottom_panel_items[i].button->set_pressed(false);
+ bottom_panel_items[i].control->set_hidden(true);
+ }
+ center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN);
+ center_split->set_collapsed(true);
+ }
+}
+
+void EditorNode::_bind_methods() {
+
+
+ ObjectTypeDB::bind_method("_menu_option",&EditorNode::_menu_option);
+ ObjectTypeDB::bind_method("_menu_confirm_current",&EditorNode::_menu_confirm_current);
+ ObjectTypeDB::bind_method("_dialog_action",&EditorNode::_dialog_action);
+ ObjectTypeDB::bind_method("_resource_selected",&EditorNode::_resource_selected,DEFVAL(""));
+ ObjectTypeDB::bind_method("_property_editor_forward",&EditorNode::_property_editor_forward);
+ ObjectTypeDB::bind_method("_property_editor_back",&EditorNode::_property_editor_back);
+ ObjectTypeDB::bind_method("_editor_select",&EditorNode::_editor_select);
+ ObjectTypeDB::bind_method("_node_renamed",&EditorNode::_node_renamed);
+ ObjectTypeDB::bind_method("edit_node",&EditorNode::edit_node);
+ ObjectTypeDB::bind_method("_imported",&EditorNode::_imported);
+ ObjectTypeDB::bind_method("_unhandled_input",&EditorNode::_unhandled_input);
+
+ ObjectTypeDB::bind_method("_get_scene_metadata",&EditorNode::_get_scene_metadata);
+ ObjectTypeDB::bind_method("set_edited_scene",&EditorNode::set_edited_scene);
+ ObjectTypeDB::bind_method("open_request",&EditorNode::open_request);
+ ObjectTypeDB::bind_method("_instance_request",&EditorNode::_instance_request);
+ ObjectTypeDB::bind_method("update_keying",&EditorNode::update_keying);
+ ObjectTypeDB::bind_method("_property_keyed",&EditorNode::_property_keyed);
+ ObjectTypeDB::bind_method("_transform_keyed",&EditorNode::_transform_keyed);
+ ObjectTypeDB::bind_method("_close_messages",&EditorNode::_close_messages);
+ ObjectTypeDB::bind_method("_show_messages",&EditorNode::_show_messages);
+ ObjectTypeDB::bind_method("_vp_resized",&EditorNode::_vp_resized);
+ ObjectTypeDB::bind_method("_quick_opened",&EditorNode::_quick_opened);
+ ObjectTypeDB::bind_method("_quick_run",&EditorNode::_quick_run);
+
+ ObjectTypeDB::bind_method("_resource_created",&EditorNode::_resource_created);
+
+ ObjectTypeDB::bind_method("_import_action",&EditorNode::_import_action);
+ //ObjectTypeDB::bind_method("_import",&EditorNode::_import);
+// ObjectTypeDB::bind_method("_import_conflicts_solved",&EditorNode::_import_conflicts_solved);
+ ObjectTypeDB::bind_method("_open_recent_scene",&EditorNode::_open_recent_scene);
+// ObjectTypeDB::bind_method("_open_recent_scene_confirm",&EditorNode::_open_recent_scene_confirm);
+
+ ObjectTypeDB::bind_method("_save_optimized",&EditorNode::_save_optimized);
+
+ ObjectTypeDB::bind_method("stop_child_process",&EditorNode::stop_child_process);
+
+ ObjectTypeDB::bind_method("_sources_changed",&EditorNode::_sources_changed);
+ ObjectTypeDB::bind_method("_fs_changed",&EditorNode::_fs_changed);
+ ObjectTypeDB::bind_method("_dock_select_draw",&EditorNode::_dock_select_draw);
+ ObjectTypeDB::bind_method("_dock_select_input",&EditorNode::_dock_select_input);
+ ObjectTypeDB::bind_method("_dock_pre_popup",&EditorNode::_dock_pre_popup);
+ ObjectTypeDB::bind_method("_dock_split_dragged",&EditorNode::_dock_split_dragged);
+ ObjectTypeDB::bind_method("_save_docks",&EditorNode::_save_docks);
+ ObjectTypeDB::bind_method("_dock_popup_exit",&EditorNode::_dock_popup_exit);
+ ObjectTypeDB::bind_method("_dock_move_left",&EditorNode::_dock_move_left);
+ ObjectTypeDB::bind_method("_dock_move_right",&EditorNode::_dock_move_right);
+
+ ObjectTypeDB::bind_method("_layout_menu_option",&EditorNode::_layout_menu_option);
+
+ ObjectTypeDB::bind_method("set_current_scene",&EditorNode::set_current_scene);
+ ObjectTypeDB::bind_method("set_current_version",&EditorNode::set_current_version);
+ ObjectTypeDB::bind_method("_scene_tab_changed",&EditorNode::_scene_tab_changed);
+ ObjectTypeDB::bind_method("_scene_tab_closed",&EditorNode::_scene_tab_closed);
+ ObjectTypeDB::bind_method("_scene_tab_script_edited",&EditorNode::_scene_tab_script_edited);
+ ObjectTypeDB::bind_method("_set_main_scene_state",&EditorNode::_set_main_scene_state);
+ ObjectTypeDB::bind_method("_update_scene_tabs",&EditorNode::_update_scene_tabs);
+
+ ObjectTypeDB::bind_method("_prepare_history",&EditorNode::_prepare_history);
+ ObjectTypeDB::bind_method("_select_history",&EditorNode::_select_history);
+
+ ObjectTypeDB::bind_method("_toggle_search_bar",&EditorNode::_toggle_search_bar);
+ ObjectTypeDB::bind_method("_clear_search_box",&EditorNode::_clear_search_box);
+ ObjectTypeDB::bind_method("_clear_undo_history",&EditorNode::_clear_undo_history);
+
+ ObjectTypeDB::bind_method(_MD("add_editor_import_plugin", "plugin"), &EditorNode::add_editor_import_plugin);
+ ObjectTypeDB::bind_method(_MD("remove_editor_import_plugin", "plugin"), &EditorNode::remove_editor_import_plugin);
+ ObjectTypeDB::bind_method(_MD("get_gui_base"), &EditorNode::get_gui_base);
+ ObjectTypeDB::bind_method(_MD("_bottom_panel_switch"), &EditorNode::_bottom_panel_switch);
+
+
+ ADD_SIGNAL( MethodInfo("play_pressed") );
+ ADD_SIGNAL( MethodInfo("pause_pressed") );
+ ADD_SIGNAL( MethodInfo("stop_pressed") );
+ ADD_SIGNAL( MethodInfo("request_help") );
+ ADD_SIGNAL( MethodInfo("script_add_function_request",PropertyInfo(Variant::OBJECT,"obj"),PropertyInfo(Variant::STRING,"function"),PropertyInfo(Variant::STRING_ARRAY,"args")) );
+ ADD_SIGNAL( MethodInfo("resource_saved",PropertyInfo(Variant::OBJECT,"obj")) );
+
+
+
+}
+
EditorNode::EditorNode() {
EditorHelp::generate_doc(); //before any editor classes are crated
@@ -4589,6 +4768,8 @@ EditorNode::EditorNode() {
ResourceLoader::set_abort_on_missing_resources(false);
FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files"));
+ EditorFileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files"));
+ EditorFileDialog::set_default_display_mode((EditorFileDialog::DisplayMode)EditorSettings::get_singleton()->get("file_dialog/display_mode").operator int());
ResourceLoader::set_error_notify_func(this,_load_error_notify);
ResourceLoader::set_dependency_error_notify_func(this,_dependency_error_report);
@@ -4842,7 +5023,7 @@ EditorNode::EditorNode() {
scene_tabs=memnew( Tabs );
scene_tabs->add_tab("unsaved");
scene_tabs->set_tab_align(Tabs::ALIGN_CENTER);
- scene_tabs->set_tab_close_display_policy(Tabs::SHOW_ACTIVE_ONLY);
+ scene_tabs->set_tab_close_display_policy(Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY);
scene_tabs->connect("tab_changed",this,"_scene_tab_changed");
scene_tabs->connect("right_button_pressed",this,"_scene_tab_script_edited");
scene_tabs->connect("tab_close", this, "_scene_tab_closed");
@@ -4872,8 +5053,9 @@ EditorNode::EditorNode() {
//scene_root_base->add_child(scene_root);
- scene_root->set_meta("_editor_disable_input",true);
+ //scene_root->set_meta("_editor_disable_input",true);
VisualServer::get_singleton()->viewport_set_hide_scenario(scene_root->get_viewport(),true);
+ scene_root->set_disable_input(true);
scene_root->set_as_audio_listener_2d(true);
scene_root->set_size_override(true,Size2(Globals::get_singleton()->get("display/width"),Globals::get_singleton()->get("display/height")));
@@ -4888,44 +5070,6 @@ EditorNode::EditorNode() {
scene_root_parent->add_child(viewport);
- PanelContainer *pc = memnew( PanelContainer );
- top_split->add_child(pc);
- animation_vb = memnew( VBoxContainer );
- animation_vb->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- pc->add_child(animation_vb);
- animation_panel=pc;
- animation_panel->hide();
-
-
- HBoxContainer *animation_hb = memnew( HBoxContainer);
- animation_vb->add_child(animation_hb);
-
- Label *l= memnew( Label );
- l->set_text("Animation:");
- //l->set_h_size_flags(Control::SIZE_);
- animation_hb->add_child(l);
-
- animation_panel_hb = memnew( HBoxContainer );
- animation_hb->add_child(animation_panel_hb);
- animation_panel_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
-
-
- /*pd_anim = memnew( PaneDrag );
- animation_hb->add_child(pd_anim);
- pd_anim->connect("dragged",this,"_dragged");
- pd_anim->set_default_cursor_shape(Control::CURSOR_MOVE);
- pd_anim->hide();*/
-
- anim_close = memnew( TextureButton );
- animation_hb->add_child(anim_close);
- anim_close->connect("pressed",this,"animation_panel_make_visible",make_binds(false));
- anim_close->set_normal_texture( anim_close->get_icon("Close","EditorIcons"));
- anim_close->set_hover_texture( anim_close->get_icon("CloseHover","EditorIcons"));
- anim_close->set_pressed_texture( anim_close->get_icon("Close","EditorIcons"));
-
-
-
-
PanelContainer *top_region = memnew( PanelContainer );
top_region->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
HBoxContainer *left_menu_hb = memnew( HBoxContainer );
@@ -4977,7 +5121,6 @@ EditorNode::EditorNode() {
pm_export->set_name("Export");
p->add_child(pm_export);
p->add_submenu_item("Convert To..","Export");
- pm_export->add_item("Subscene..",FILE_SAVE_SUBSCENE);
pm_export->add_item("Translatable Strings..",FILE_DUMP_STRINGS);
pm_export->add_separator();
pm_export->add_item("MeshLibrary..",FILE_EXPORT_MESH_LIBRARY);
@@ -4994,7 +5137,11 @@ EditorNode::EditorNode() {
p->add_separator();
p->add_item("Revert Scene",EDIT_REVERT);
p->add_separator();
- p->add_item("Quit to Project List",RUN_PROJECT_MANAGER,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_Q);
+#ifdef OSX_ENABLED
+ p->add_item("Quit to Project List",RUN_PROJECT_MANAGER,KEY_MASK_SHIFT+KEY_MASK_ALT+KEY_Q);
+#else
+ p->add_item("Quit to Project List",RUN_PROJECT_MANAGER,KEY_MASK_SHIFT+KEY_MASK_CTRL+KEY_Q);
+#endif
p->add_item("Quit",FILE_QUIT,KEY_MASK_CMD+KEY_Q);
recent_scenes = memnew( PopupMenu );
@@ -5231,17 +5378,25 @@ EditorNode::EditorNode() {
right_menu_hb->add_child( settings_menu );
p=settings_menu->get_popup();
-
//p->add_item("Export Settings",SETTINGS_EXPORT_PREFERENCES);
p->add_item("Editor Settings",SETTINGS_PREFERENCES);
//p->add_item("Optimization Presets",SETTINGS_OPTIMIZED_PRESETS);
p->add_separator();
- p->add_check_item("Show Animation",SETTINGS_SHOW_ANIMATION,KEY_MASK_CMD+KEY_N);
+ editor_layouts = memnew( PopupMenu );
+ editor_layouts->set_name("Layouts");
+ p->add_child(editor_layouts);
+ editor_layouts->connect("item_pressed",this,"_layout_menu_option");
+ p->add_submenu_item("Editor Layout", "Layouts");
p->add_separator();
p->add_item("Install Export Templates",SETTINGS_LOAD_EXPORT_TEMPLATES);
p->add_separator();
p->add_item("About",SETTINGS_ABOUT);
+ layout_dialog = memnew( EditorNameDialog );
+ gui_base->add_child(layout_dialog);
+ layout_dialog->set_hide_on_ok(false);
+ layout_dialog->set_size(Size2(175, 70));
+ layout_dialog->connect("name_confirmed", this,"_dialog_action");
sources_button = memnew( ToolButton );
right_menu_hb->add_child(sources_button);
@@ -5396,7 +5551,7 @@ EditorNode::EditorNode() {
prop_editor_base->add_child(search_bar);
search_bar->hide();
- l = memnew( Label("Search: ") );
+ Label *l = memnew( Label("Search: ") );
search_bar->add_child(l);
search_box = memnew( LineEdit );
@@ -5423,44 +5578,61 @@ EditorNode::EditorNode() {
scenes_dock = memnew( ScenesDock(this) );
scenes_dock->set_name("FileSystem");
+ scenes_dock->set_use_thumbnails(int(EditorSettings::get_singleton()->get("file_dialog/display_mode"))==EditorFileDialog::DISPLAY_THUMBNAILS);
dock_slot[DOCK_SLOT_LEFT_BR]->add_child(scenes_dock);
//prop_pallete->add_child(scenes_dock);
scenes_dock->connect("open",this,"open_request");
scenes_dock->connect("instance",this,"_instance_request");
+ const String docks_section = "docks";
+ overridden_default_layout=-1;
+ default_layout.instance();
+ default_layout->set_value(docks_section, "dock_3", "Scene");
+ default_layout->set_value(docks_section, "dock_4", "FileSystem");
+ default_layout->set_value(docks_section, "dock_5", "Inspector");
- log = memnew( EditorLog );
- center_split->add_child(log);
- log->connect("close_request",this,"_close_messages");
- log->connect("show_request",this,"_show_messages");
- //left_split->set_dragger_visible(false);
+ for(int i=0;i<DOCK_SLOT_MAX/2;i++)
+ default_layout->set_value(docks_section, "dock_hsplit_"+itos(i+1), 0);
+ for(int i=0;i<DOCK_SLOT_MAX/2;i++)
+ default_layout->set_value(docks_section, "dock_split_"+itos(i+1), 0);
+ _update_layouts_menu();
- old_split_ofs=0;
+ bottom_panel = memnew( PanelContainer );
+ bottom_panel->add_style_override("panel",gui_base->get_stylebox("panelf","Panel"));
+ center_split->add_child(bottom_panel);
+ center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN);
+ bottom_panel_vb = memnew( VBoxContainer );
+ bottom_panel->add_child(bottom_panel_vb);
+ //bottom_panel_vb->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- animation_editor = memnew( AnimationKeyEditor(get_undo_redo(),&editor_history,editor_selection) );
- animation_editor->set_anchor_and_margin(MARGIN_RIGHT,Control::ANCHOR_END,0);
- animation_editor->set_margin(MARGIN_BOTTOM,200);
- animation_editor->connect("keying_changed",this,"_update_keying");
+ bottom_panel_hb = memnew( HBoxContainer );
+ bottom_panel_vb->add_child(bottom_panel_hb);
- animation_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- animation_vb->add_child(animation_editor);
- center_split->connect("resized",this,"_vp_resized");
+ log = memnew( EditorLog );
+
+ add_bottom_panel_item("Output",log);
+
+ //left_split->set_dragger_visible(false);
- animation_editor->hide();
+ old_split_ofs=0;
+
+ center_split->connect("resized",this,"_vp_resized");
+
/*PanelContainer *bottom_pc = memnew( PanelContainer );
srt->add_child(bottom_pc);
bottom_hb = memnew( HBoxContainer );
bottom_pc->add_child(bottom_hb);*/
- center_vb->add_child( log->get_button() );
- log->get_button()->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+
+// center_vb->add_child( log->get_button() );
+// log->get_button()->set_h_size_flags(Control::SIZE_EXPAND_FILL);
//progress_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -5569,7 +5741,7 @@ EditorNode::EditorNode() {
about->get_ok()->set_text("Thanks!");
about->set_hide_on_ok(true);
Label *about_text = memnew( Label );
- about_text->set_text(VERSION_FULL_NAME"\n(c) 2008-2015 Juan Linietsky, Ariel Manzur.\n");
+ about_text->set_text(VERSION_FULL_NAME"\n(c) 2008-2016 Juan Linietsky, Ariel Manzur.\n");
about_text->set_pos(Point2(gui_base->get_icon("Logo","EditorIcons")->get_size().width+30,20));
gui_base->add_child(about);
about->add_child(about_text);
@@ -5660,7 +5832,7 @@ EditorNode::EditorNode() {
file_templates->connect("file_selected", this,"_dialog_action");
property_editor->connect("resource_selected", this,"_resource_selected");
property_editor->connect("property_keyed", this,"_property_keyed");
- animation_editor->connect("resource_selected", this,"_resource_selected");
+
//plugin stuff
file_server = memnew( EditorFileServer );
@@ -5684,11 +5856,17 @@ EditorNode::EditorNode() {
editor_import_export->add_export_plugin( Ref<EditorTextureExportPlugin>( memnew(EditorTextureExportPlugin)));
editor_import_export->add_export_plugin( Ref<EditorSampleExportPlugin>( memnew(EditorSampleExportPlugin)));
+ editor_import_export->add_export_plugin( Ref<EditorSceneExportPlugin>( memnew(EditorSceneExportPlugin)));
+
+ add_editor_plugin( memnew( AnimationPlayerEditorPlugin(this) ) );
add_editor_plugin( memnew( CanvasItemEditorPlugin(this) ) );
add_editor_plugin( memnew( SpatialEditorPlugin(this) ) );
add_editor_plugin( memnew( ScriptEditorPlugin(this) ) );
- add_editor_plugin( memnew( AnimationPlayerEditorPlugin(this) ) );
+
+ //more visually meaningful to have this later
+ raise_bottom_panel_item(AnimationPlayerEditor::singleton);
+
add_editor_plugin( memnew( ShaderGraphEditorPlugin(this,true) ) );
add_editor_plugin( memnew( ShaderGraphEditorPlugin(this,false) ) );
add_editor_plugin( memnew( ShaderEditorPlugin(this,true) ) );
@@ -5721,7 +5899,8 @@ EditorNode::EditorNode() {
add_editor_plugin( memnew( Polygon2DEditorPlugin(this) ) );
add_editor_plugin( memnew( LightOccluder2DEditorPlugin(this) ) );
add_editor_plugin( memnew( NavigationPolygonEditorPlugin(this) ) );
- add_editor_plugin( memnew( ColorRampEditorPlugin(this) ) );
+ add_editor_plugin( memnew( ColorRampEditorPlugin(this,true) ) );
+ add_editor_plugin( memnew( ColorRampEditorPlugin(this,false) ) );
add_editor_plugin( memnew( CollisionShape2DEditorPlugin(this) ) );
for(int i=0;i<EditorPlugins::get_plugin_count();i++)
@@ -5734,9 +5913,10 @@ EditorNode::EditorNode() {
resource_preview->add_preview_generator( Ref<EditorScriptPreviewPlugin>( memnew(EditorScriptPreviewPlugin )));
resource_preview->add_preview_generator( Ref<EditorSamplePreviewPlugin>( memnew(EditorSamplePreviewPlugin )));
resource_preview->add_preview_generator( Ref<EditorMeshPreviewPlugin>( memnew(EditorMeshPreviewPlugin )));
+ resource_preview->add_preview_generator( Ref<EditorBitmapPreviewPlugin>( memnew(EditorBitmapPreviewPlugin )));
circle_step_msec=OS::get_singleton()->get_ticks_msec();
- circle_step_frame=OS::get_singleton()->get_frames_drawn();;
+ circle_step_frame=OS::get_singleton()->get_frames_drawn();
circle_step=0;
_rebuild_import_menu();
diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h
index 5cc9d9eaa2..4dc942c023 100644
--- a/tools/editor/editor_node.h
+++ b/tools/editor/editor_node.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -56,7 +56,7 @@
#include "tools/editor/editor_run.h"
#include "tools/editor/pane_drag.h"
-#include "tools/editor/animation_editor.h"
+
#include "tools/editor/script_create_dialog.h"
#include "tools/editor/run_settings_dialog.h"
#include "tools/editor/project_settings.h"
@@ -76,6 +76,7 @@
#include "editor_reimport_dialog.h"
#include "import_settings.h"
#include "tools/editor/editor_plugin.h"
+#include "tools/editor/editor_name_dialog.h"
#include "fileserver/editor_file_server.h"
#include "editor_resource_preview.h"
@@ -99,13 +100,12 @@ typedef void (*EditorNodeInitCallback)();
class EditorNode : public Node {
OBJ_TYPE( EditorNode, Node );
-
+
enum {
-
- HISTORY_SIZE=64
+ HISTORY_SIZE=64
};
+
enum MenuOptions {
-
FILE_NEW_SCENE,
FILE_NEW_INHERITED_SCENE,
FILE_OPEN_SCENE,
@@ -118,7 +118,6 @@ class EditorNode : public Node {
FILE_EXPORT_MESH_LIBRARY,
FILE_EXPORT_TILESET,
FILE_SAVE_OPTIMIZED,
- FILE_SAVE_SUBSCENE,
FILE_DUMP_STRINGS,
FILE_OPEN_RECENT,
FILE_OPEN_OLD_SCENE,
@@ -167,7 +166,9 @@ class EditorNode : public Node {
SETTINGS_EXPORT_PREFERENCES,
SETTINGS_PREFERENCES,
SETTINGS_OPTIMIZED_PRESETS,
- SETTINGS_SHOW_ANIMATION,
+ SETTINGS_LAYOUT_SAVE,
+ SETTINGS_LAYOUT_DELETE,
+ SETTINGS_LAYOUT_DEFAULT,
SETTINGS_LOAD_EXPORT_TEMPLATES,
SETTINGS_HELP,
SETTINGS_ABOUT,
@@ -228,7 +229,6 @@ class EditorNode : public Node {
Control *vp_base;
PaneDrag *pd;
//PaneDrag *pd_anim;
- TextureButton *anim_close;
Panel *menu_panel;
@@ -248,7 +248,6 @@ class EditorNode : public Node {
ToolButton *pause_button;
ToolButton *stop_button;
ToolButton *run_settings_button;
- ToolButton *animation_menu;
ToolButton *play_scene_button;
ToolButton *play_custom_scene_button;
MenuButton *debug_button;
@@ -284,6 +283,11 @@ class EditorNode : public Node {
AcceptDialog *about;
AcceptDialog *warning;
+ int overridden_default_layout;
+ Ref<ConfigFile> default_layout;
+ PopupMenu *editor_layouts;
+ EditorNameDialog *layout_dialog;
+
//OptimizedPresetsDialog *optimized_presets;
EditorSettingsDialog *settings_config_dialog;
RunSettingsDialog *run_settings_dialog;
@@ -309,15 +313,12 @@ class EditorNode : public Node {
String defer_export_platform;
bool defer_export_debug;
Node *_last_instanced_scene;
- PanelContainer *animation_panel;
- HBoxContainer *animation_panel_hb;
- VBoxContainer *animation_vb;
EditorPath *editor_path;
ToolButton *resource_new_button;
ToolButton *resource_load_button;
MenuButton *resource_save_button;
MenuButton *editor_history_menu;
- AnimationKeyEditor *animation_editor;
+
EditorLog *log;
CenterContainer *tabs_center;
EditorQuickOpen *quick_open;
@@ -380,6 +381,21 @@ class EditorNode : public Node {
EditorFileServer *file_server;
+
+ struct BottomPanelItem {
+ String name;
+ Control *control;
+ ToolButton *button;
+ };
+
+ Vector<BottomPanelItem> bottom_panel_items;
+
+ PanelContainer *bottom_panel;
+ HBoxContainer *bottom_panel_hb;
+ VBoxContainer *bottom_panel_vb;
+
+ void _bottom_panel_switch(bool p_enable, int p_idx);
+
String external_file;
List<String> previous_scenes;
bool opening_prev;
@@ -411,8 +427,8 @@ class EditorNode : public Node {
void _node_renamed();
void _editor_select(int p_which);
- void _set_scene_metadata();
- void _get_scene_metadata();
+ void _set_scene_metadata(const String &p_file);
+ void _get_scene_metadata(const String& p_file);
void _update_title();
void _update_scene_tabs();
void _close_messages();
@@ -429,9 +445,8 @@ class EditorNode : public Node {
void _property_keyed(const String& p_keyed, const Variant& p_value, bool p_advance);
void _transform_keyed(Object *sp,const String& p_sub,const Transform& p_key);
- void _update_keying();
void _hide_top_editors();
- void _quick_opened(const String& p_resource);
+ void _quick_opened();
void _quick_run(const String& p_resource);
void _run(bool p_current=false, const String &p_custom="");
@@ -523,13 +538,19 @@ class EditorNode : public Node {
void _save_docks();
void _load_docks();
+ void _save_docks_to_config(Ref<ConfigFile> p_layout, const String& p_section);
+ void _load_docks_from_config(Ref<ConfigFile> p_layout, const String& p_section);
+
+ void _update_layouts_menu();
+ void _layout_menu_option(int p_idx);
void _toggle_search_bar(bool p_pressed);
void _clear_search_box();
+ void _clear_undo_history();
protected:
void _notification(int p_what);
- static void _bind_methods();
+ static void _bind_methods();
public:
enum EditorTable {
@@ -573,13 +594,10 @@ public:
static EditorLog *get_log() { return singleton->log; }
Control* get_viewport();
- AnimationKeyEditor *get_animation_editor() const { return animation_editor; }
- Control *get_animation_panel() { return animation_vb; }
- HBoxContainer *get_animation_panel_hb() { return animation_panel_hb; }
- void animation_editor_make_visible(bool p_visible);
- void hide_animation_player_editors();
- void animation_panel_make_visible(bool p_visible);
+ //void animation_editor_make_visible(bool p_visible);
+ //void hide_animation_player_editors();
+ //void animation_panel_make_visible(bool p_visible);
void set_edited_scene(Node *p_scene);
@@ -599,6 +617,7 @@ public:
void set_current_scene(int p_idx);
static EditorData& get_editor_data() { return singleton->editor_data; }
+ EditorHistory * get_editor_history() { return &editor_history; }
static VSplitContainer *get_top_split() { return singleton->top_split; }
@@ -632,7 +651,7 @@ public:
static void add_io_error(const String& p_error);
static void progress_add_task(const String& p_task,const String& p_label, int p_steps);
- static void progress_task_step(const String& p_task,const String& p_state, int p_step=-1);
+ static void progress_task_step(const String& p_task,const String& p_state, int p_step=-1,bool p_force_refresh=true);
static void progress_end_task(const String& p_task);
static void progress_add_task_bg(const String& p_task,const String& p_label, int p_steps);
@@ -647,6 +666,14 @@ public:
void save_layout();
+ void update_keying();
+
+
+ ToolButton* add_bottom_panel_item(String p_text,Control *p_item);
+ void make_bottom_panel_item_visible(Control *p_item);
+ void raise_bottom_panel_item(Control *p_item);
+ void hide_bottom_panel();
+
EditorNode();
~EditorNode();
void get_singleton(const char* arg1, bool arg2);
@@ -659,7 +686,7 @@ public:
struct EditorProgress {
String task;
- void step(const String& p_state, int p_step=-1) { EditorNode::progress_task_step(task,p_state,p_step); }
+ void step(const String& p_state, int p_step=-1,bool p_force_refresh=true) { EditorNode::progress_task_step(task,p_state,p_step,p_force_refresh); }
EditorProgress(const String& p_task,const String& p_label,int p_amount) { EditorNode::progress_add_task(p_task,p_label,p_amount); task=p_task; }
~EditorProgress() { EditorNode::progress_end_task(task); }
};
diff --git a/tools/editor/editor_path.cpp b/tools/editor/editor_path.cpp
index 94e2efe346..4cf98e832c 100644
--- a/tools/editor/editor_path.cpp
+++ b/tools/editor/editor_path.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_path.h b/tools/editor/editor_path.h
index 2edaeb92a3..11e1005ba3 100644
--- a/tools/editor/editor_path.h
+++ b/tools/editor/editor_path.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_plugin.cpp b/tools/editor/editor_plugin.cpp
index 7417d707bb..b7ccb452e9 100644
--- a/tools/editor/editor_plugin.cpp
+++ b/tools/editor/editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_plugin.h b/tools/editor/editor_plugin.h
index 0f3a1e2e3c..bf1e185a37 100644
--- a/tools/editor/editor_plugin.h
+++ b/tools/editor/editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -92,6 +92,7 @@ public:
virtual bool get_remove_list(List<Node*> *p_list);
virtual void set_window_layout(Ref<ConfigFile> p_layout);
virtual void get_window_layout(Ref<ConfigFile> p_layout);
+ virtual void edited_scene_changed(){}; // if changes are pending in editor, apply them
virtual void restore_global_state();
virtual void save_global_state();
diff --git a/tools/editor/editor_reimport_dialog.cpp b/tools/editor/editor_reimport_dialog.cpp
index 8842a485b3..eab5a5e32d 100644
--- a/tools/editor/editor_reimport_dialog.cpp
+++ b/tools/editor/editor_reimport_dialog.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_reimport_dialog.h b/tools/editor/editor_reimport_dialog.h
index 9726bac805..0c2d0eb52c 100644
--- a/tools/editor/editor_reimport_dialog.h
+++ b/tools/editor/editor_reimport_dialog.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_run.cpp b/tools/editor/editor_run.cpp
index b635cea84b..fb0f24c084 100644
--- a/tools/editor/editor_run.cpp
+++ b/tools/editor/editor_run.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_run.h b/tools/editor/editor_run.h
index e1b0b081c7..0b96a2c91c 100644
--- a/tools/editor/editor_run.h
+++ b/tools/editor/editor_run.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_run_native.cpp b/tools/editor/editor_run_native.cpp
index 2eedba93dc..234dd03087 100644
--- a/tools/editor/editor_run_native.cpp
+++ b/tools/editor/editor_run_native.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_run_native.h b/tools/editor/editor_run_native.h
index 77d6dc198e..04dad6b6aa 100644
--- a/tools/editor/editor_run_native.h
+++ b/tools/editor/editor_run_native.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_selection.cpp b/tools/editor/editor_selection.cpp
index d8fd8735fc..f3fbdba907 100644
--- a/tools/editor/editor_selection.cpp
+++ b/tools/editor/editor_selection.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_selection.h b/tools/editor/editor_selection.h
index f10f313a4e..d238d86567 100644
--- a/tools/editor/editor_selection.h
+++ b/tools/editor/editor_selection.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp
index 15de6e7266..4195ba97e6 100644
--- a/tools/editor/editor_settings.cpp
+++ b/tools/editor/editor_settings.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -515,6 +515,8 @@ void EditorSettings::_load_defaults() {
set("text_editor/create_signal_callbacks",true);
set("file_dialog/show_hidden_files", false);
+ set("file_dialog/display_mode", 0);
+ hints["file_dialog/display_mode"]=PropertyInfo(Variant::INT,"file_dialog/display_mode",PROPERTY_HINT_ENUM,"Thumbnails,List");
set("file_dialog/thumbnail_size", 64);
hints["file_dialog/thumbnail_size"]=PropertyInfo(Variant::INT,"file_dialog/thumbnail_size",PROPERTY_HINT_RANGE,"32,128,16");
diff --git a/tools/editor/editor_settings.h b/tools/editor/editor_settings.h
index 4ba940cd1c..d1a11360af 100644
--- a/tools/editor/editor_settings.h
+++ b/tools/editor/editor_settings.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -107,6 +107,7 @@ public:
static EditorSettings *get_singleton();
void erase(String p_var);
String get_settings_path() const;
+ String get_global_settings_path() const;
String get_project_settings_path() const;
const Map<String,Plugin>& get_plugins() const { return plugins; }
diff --git a/tools/editor/editor_sub_scene.cpp b/tools/editor/editor_sub_scene.cpp
index 2a6eba2554..e58e2c1351 100644
--- a/tools/editor/editor_sub_scene.cpp
+++ b/tools/editor/editor_sub_scene.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -196,7 +196,11 @@ void EditorSubScene::_bind_methods() {
EditorSubScene::EditorSubScene() {
+ scene=NULL;
+
set_title("Select Sub-Scene..");
+ set_hide_on_ok(false);
+
VBoxContainer *vb = memnew( VBoxContainer );
add_child(vb);
set_child_rect(vb);
@@ -211,9 +215,11 @@ EditorSubScene::EditorSubScene() {
hb->add_child(b);
b->connect("pressed",this,"_path_browse");
vb->add_margin_child("Scene Path:",hb);
+
tree = memnew( Tree );
tree->set_v_size_flags(SIZE_EXPAND_FILL);
- vb->add_margin_child("Import From Node:",tree)->set_v_size_flags(SIZE_EXPAND_FILL);
+ vb->add_margin_child("Import From Node:",tree,true);
+ tree->connect("item_activated",this,"_ok");
file_dialog = memnew( EditorFileDialog );
List<String> extensions;
@@ -228,8 +234,4 @@ EditorSubScene::EditorSubScene() {
add_child(file_dialog);
file_dialog->connect("file_selected",this,"_path_selected");
- scene=NULL;
-
- set_hide_on_ok(false);
-
}
diff --git a/tools/editor/editor_sub_scene.h b/tools/editor/editor_sub_scene.h
index dfd6c531e2..3dd86eefda 100644
--- a/tools/editor/editor_sub_scene.h
+++ b/tools/editor/editor_sub_scene.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_vu.cpp b/tools/editor/editor_vu.cpp
index ac11aceb21..7a133c9736 100644
--- a/tools/editor/editor_vu.cpp
+++ b/tools/editor/editor_vu.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/editor_vu.h b/tools/editor/editor_vu.h
index 4c51ac31c0..78fe3eda86 100644
--- a/tools/editor/editor_vu.h
+++ b/tools/editor/editor_vu.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/file_type_cache.cpp b/tools/editor/file_type_cache.cpp
index a86400a560..7044a9900c 100644
--- a/tools/editor/file_type_cache.cpp
+++ b/tools/editor/file_type_cache.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/file_type_cache.h b/tools/editor/file_type_cache.h
index efc6d22b25..18451cbe19 100644
--- a/tools/editor/file_type_cache.h
+++ b/tools/editor/file_type_cache.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/groups_editor.cpp b/tools/editor/groups_editor.cpp
index 2e82854014..6840a8b205 100644
--- a/tools/editor/groups_editor.cpp
+++ b/tools/editor/groups_editor.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,151 +27,130 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "groups_editor.h"
-#include "scene/gui/box_container.h"
+#include "scene/gui/box_container.h"
#include "scene/gui/label.h"
+void GroupsEditor::_add_group(const String& p_group) {
-#include "print_string.h"
+ if (!node)
+ return;
-void GroupsEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
- connect("confirmed", this,"_close");
- }
- if (p_what==NOTIFICATION_EXIT_TREE) {
- disconnect("confirmed", this,"_close");
- }
-}
+ String name = group_name->get_text();
+ if (name.strip_edges()=="")
+ return;
-void GroupsEditor::_close() {
-
- hide();
-
-}
-void GroupsEditor::_add() {
-
- if (!node)
+ if (node->is_in_group(name))
return;
-
- undo_redo->create_action("Add To Group");
- undo_redo->add_do_method(node,"add_to_group",group_name->get_text(),true);
- undo_redo->add_undo_method(node,"remove_from_group",group_name->get_text());
+ undo_redo->create_action("Add to Group");
+
+ undo_redo->add_do_method(node,"add_to_group",name,true);
undo_redo->add_do_method(this,"update_tree");
+ undo_redo->add_undo_method(node,"remove_from_group",name,get_text());
undo_redo->add_undo_method(this,"update_tree");
undo_redo->commit_action();
}
+void GroupsEditor::_remove_group(Object *p_item, int p_column, int p_id) {
-void GroupsEditor::_remove() {
-
- if (!tree->get_selected())
- return;
if (!node)
return;
- TreeItem *sel = tree->get_selected();
- if (!sel)
+ TreeItem *ti = p_item->cast_to<TreeItem>();
+ if (!ti)
return;
-
- node->remove_from_group( sel->get_text(0) );
- update_tree();
+
+ String name = ti->get_text(0);
+
+ undo_redo->create_action("Remove from Group");
+
+ undo_redo->add_do_method(node,"remove_from_group",name);
+ undo_redo->add_do_method(this,"update_tree");
+ undo_redo->add_undo_method(node,"add_to_group",name,true);
+ undo_redo->add_undo_method(this,"update_tree");
+
+ undo_redo->commit_action();
}
+struct _GroupInfoComparator {
+
+ bool operator()(const Node::GroupInfo& p_a, const Node::GroupInfo& p_b) const {
+ return p_a.name.operator String() < p_b.name.operator String();
+ }
+};
+
void GroupsEditor::update_tree() {
-
tree->clear();
-
+
if (!node)
return;
-
- List<GroupInfo> groups;
+
+ List<Node::GroupInfo> groups;
node->get_groups(&groups);
-
+ groups.sort_custom<_GroupInfoComparator>();
+
TreeItem *root=tree->create_item();
-
+
for(List<GroupInfo>::Element *E=groups.front();E;E=E->next()) {
-
- if (!E->get().persistent)
+
+ Node::GroupInfo gi = E->get();
+ if (!gi.persistent)
continue;
+
TreeItem *item=tree->create_item(root);
- item->set_text(0, E->get().name);
-
+ item->set_text(0, gi.name);
+ item->add_button(0, get_icon("Remove", "EditorIcons"), 0);
}
-
}
void GroupsEditor::set_current(Node* p_node) {
-
+
node=p_node;
update_tree();
-
}
void GroupsEditor::_bind_methods() {
-
- ObjectTypeDB::bind_method("_add",&GroupsEditor::_add);
- ObjectTypeDB::bind_method("_close",&GroupsEditor::_close);
- ObjectTypeDB::bind_method("_remove",&GroupsEditor::_remove);
+
+ ObjectTypeDB::bind_method("_add_group",&GroupsEditor::_add_group);
+ ObjectTypeDB::bind_method("_remove_group",&GroupsEditor::_remove_group);
ObjectTypeDB::bind_method("update_tree",&GroupsEditor::update_tree);
}
GroupsEditor::GroupsEditor() {
+ node=NULL;
+
set_title("Group Editor");
-
- Label * label = memnew( Label );
- label->set_pos( Point2( 8,11) );
- label->set_text("Groups:");
-
- add_child(label);
-
- group_name = memnew(LineEdit);
- group_name->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- group_name->set_begin( Point2( 15,28) );
- group_name->set_end( Point2( 94,48 ) );
-
- add_child(group_name);
-
- tree = memnew( Tree );
- tree->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- tree->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
- tree->set_begin( Point2( 15,52) );
- tree->set_end( Point2( 94,42 ) );
- tree->set_hide_root(true);
- add_child(tree);
-
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+ set_child_rect(vbc);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ vbc->add_margin_child("Group", hbc);
+
+ group_name = memnew( LineEdit );
+ group_name->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(group_name);
+ group_name->connect("text_entered",this,"_add_group");
+
add = memnew( Button );
- add->set_anchor( MARGIN_LEFT, ANCHOR_END );
- add->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- add->set_begin( Point2( 90, 28 ) );
- add->set_end( Point2( 15, 48 ) );
add->set_text("Add");
-
- add_child(add);
-
- remove = memnew( Button );
- remove->set_anchor( MARGIN_LEFT, ANCHOR_END );
- remove->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- remove->set_begin( Point2( 90, 52 ) );
- remove->set_end( Point2( 15, 72 ) );
- remove->set_text("Remove");
-
- add_child(remove);
+ hbc->add_child(add);
+ add->connect("pressed", this,"_add_group", varray(String()));
- get_ok()->set_text("Close");
-
- add->connect("pressed", this,"_add");
- remove->connect("pressed", this,"_remove");
+ tree = memnew( Tree );
+ tree->set_hide_root(true);
+ tree->set_v_size_flags(SIZE_EXPAND_FILL);
+ vbc->add_margin_child("Node Group(s)", tree, true);
+ tree->connect("button_pressed",this,"_remove_group");
-
- node=NULL;
+ get_ok()->set_text("Close");
}
-
GroupsEditor::~GroupsEditor()
{
}
diff --git a/tools/editor/groups_editor.h b/tools/editor/groups_editor.h
index 09883a150f..b5bccb2766 100644
--- a/tools/editor/groups_editor.h
+++ b/tools/editor/groups_editor.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,42 +29,42 @@
#ifndef GROUPS_EDITOR_H
#define GROUPS_EDITOR_H
-
#include "scene/gui/dialogs.h"
#include "scene/gui/button.h"
#include "scene/gui/tree.h"
#include "scene/gui/line_edit.h"
#include "undo_redo.h"
+
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
-class GroupsEditor : public ConfirmationDialog {
-
- OBJ_TYPE( GroupsEditor, ConfirmationDialog );
-
+
+class GroupsEditor : public AcceptDialog {
+
+ OBJ_TYPE(GroupsEditor,AcceptDialog);
+
+ Node *node;
+
LineEdit *group_name;
- Tree *tree;
Button *add;
- Button *remove;
- Node *node;
+ Tree *tree;
+
UndoRedo *undo_redo;
-
+
void update_tree();
- void _add();
- void _remove();
+ void _add_group(const String& p_group="");
+ void _remove_group(Object *p_item, int p_column, int p_id);
void _close();
-
protected:
-
- void _notification(int p_what);
- static void _bind_methods();
+
+ static void _bind_methods();
public:
-
+
void set_undo_redo(UndoRedo *p_undoredo) { undo_redo=p_undoredo; }
void set_current(Node* p_node);
-
+
GroupsEditor();
~GroupsEditor();
-
};
+
#endif
diff --git a/tools/editor/icons/icon_add_track.png b/tools/editor/icons/icon_add_track.png
index 3862597828..6a90950173 100644
--- a/tools/editor/icons/icon_add_track.png
+++ b/tools/editor/icons/icon_add_track.png
Binary files differ
diff --git a/tools/editor/icons/icon_console.png b/tools/editor/icons/icon_console.png
new file mode 100644
index 0000000000..7dc7407ef7
--- /dev/null
+++ b/tools/editor/icons/icon_console.png
Binary files differ
diff --git a/tools/editor/icons/icon_create_new_scene_from.png b/tools/editor/icons/icon_create_new_scene_from.png
new file mode 100644
index 0000000000..e747c4f59f
--- /dev/null
+++ b/tools/editor/icons/icon_create_new_scene_from.png
Binary files differ
diff --git a/tools/editor/icons/icon_edit_pivot.png b/tools/editor/icons/icon_edit_pivot.png
new file mode 100644
index 0000000000..d68f7bbf25
--- /dev/null
+++ b/tools/editor/icons/icon_edit_pivot.png
Binary files differ
diff --git a/tools/editor/icons/icon_key_invalid.png b/tools/editor/icons/icon_key_invalid.png
new file mode 100644
index 0000000000..e8e6c87180
--- /dev/null
+++ b/tools/editor/icons/icon_key_invalid.png
Binary files differ
diff --git a/tools/editor/icons/icon_key_invalid_hover.png b/tools/editor/icons/icon_key_invalid_hover.png
new file mode 100644
index 0000000000..6f0396d96a
--- /dev/null
+++ b/tools/editor/icons/icon_key_invalid_hover.png
Binary files differ
diff --git a/tools/editor/icons/icon_list_select.png b/tools/editor/icons/icon_list_select.png
new file mode 100644
index 0000000000..cbe81d4328
--- /dev/null
+++ b/tools/editor/icons/icon_list_select.png
Binary files differ
diff --git a/tools/editor/icons/icon_pin.png b/tools/editor/icons/icon_pin.png
index 037352137d..4862ee8f71 100644
--- a/tools/editor/icons/icon_pin.png
+++ b/tools/editor/icons/icon_pin.png
Binary files differ
diff --git a/tools/editor/import_settings.cpp b/tools/editor/import_settings.cpp
index 36d7828be0..2bbd1e3805 100644
--- a/tools/editor/import_settings.cpp
+++ b/tools/editor/import_settings.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/import_settings.h b/tools/editor/import_settings.h
index 31237dd8cf..5a383a1a1a 100644
--- a/tools/editor/import_settings.h
+++ b/tools/editor/import_settings.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/io_plugins/editor_atlas.cpp b/tools/editor/io_plugins/editor_atlas.cpp
index 7e9acd193d..f894e7e8b2 100644
--- a/tools/editor/io_plugins/editor_atlas.cpp
+++ b/tools/editor/io_plugins/editor_atlas.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/io_plugins/editor_atlas.h b/tools/editor/io_plugins/editor_atlas.h
index 716faff0c6..0135e76622 100644
--- a/tools/editor/io_plugins/editor_atlas.h
+++ b/tools/editor/io_plugins/editor_atlas.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/io_plugins/editor_export_scene.cpp b/tools/editor/io_plugins/editor_export_scene.cpp
new file mode 100644
index 0000000000..dff41a59ed
--- /dev/null
+++ b/tools/editor/io_plugins/editor_export_scene.cpp
@@ -0,0 +1,112 @@
+#include "editor_export_scene.h"
+#include "io/resource_loader.h"
+#include "io/resource_saver.h"
+#include "os/dir_access.h"
+#include "os/file_access.h"
+#include "tools/editor/editor_settings.h"
+#include "scene/resources/packed_scene.h"
+#include "globals.h"
+
+Vector<uint8_t> EditorSceneExportPlugin::custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform) {
+
+ if (!EditorImportExport::get_singleton()->get_convert_text_scenes()) {
+ return Vector<uint8_t>();
+ }
+
+
+ String extension = p_path.extension();
+
+ //step 1 check if scene
+
+ if (extension=="xml" || extension=="xres") {
+
+ String type = ResourceLoader::get_resource_type(p_path);
+
+ if (type!="PackedScene")
+ return Vector<uint8_t>();
+
+ } else if (extension!="tscn" && extension!="xscn") {
+ return Vector<uint8_t>();
+ }
+
+ //step 2 check if cached
+
+ uint64_t sd=0;
+ String smd5;
+ String gp = Globals::get_singleton()->globalize_path(p_path);
+ String md5=gp.md5_text();
+ String tmp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/");
+
+ bool valid=false;
+ {
+ //if existing, make sure it's valid
+ FileAccessRef f = FileAccess::open(tmp_path+"scnexp-"+md5+".txt",FileAccess::READ);
+ if (f) {
+
+ uint64_t d = f->get_line().strip_edges().to_int64();
+ sd = FileAccess::get_modified_time(p_path);
+
+ if (d==sd) {
+ valid=true;
+ } else {
+ String cmd5 = f->get_line().strip_edges();
+ smd5 = FileAccess::get_md5(p_path);
+ if (cmd5==smd5) {
+ valid=true;
+ }
+ }
+
+
+ }
+ }
+
+ if (!valid) {
+ //cache failed, convert
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+
+ String copy = p_path+".convert."+extension;
+
+ // a copy will allow loading the internal resources without conflicting with opened scenes
+ da->copy(p_path,copy);
+
+ //@todo for tscn use something more efficient
+
+ Ref<PackedScene> copyres = ResourceLoader::load(copy,"PackedScene");
+
+ da->remove(copy);
+
+ memdelete(da);
+
+ ERR_FAIL_COND_V(!copyres.is_valid(),Vector<uint8_t>());
+
+ Error err = ResourceSaver::save(tmp_path+"scnexp-"+md5+".scn",copyres);
+
+ copyres=Ref<PackedScene>();
+
+ ERR_FAIL_COND_V(err!=OK,Vector<uint8_t>());
+
+ FileAccessRef f = FileAccess::open(tmp_path+"scnexp-"+md5+".txt",FileAccess::WRITE);
+
+ if (sd==0)
+ sd = FileAccess::get_modified_time(p_path);
+ if (smd5==String())
+ smd5 = FileAccess::get_md5(p_path);
+
+ f->store_line(String::num(sd));
+ f->store_line(smd5);
+ f->store_line(gp); //source path for reference
+ }
+
+
+ Vector<uint8_t> ret = FileAccess::get_file_as_array(tmp_path+"scnexp-"+md5+".scn");
+
+ p_path+=".converted.scn";
+
+ return ret;
+
+}
+
+
+EditorSceneExportPlugin::EditorSceneExportPlugin()
+{
+}
diff --git a/tools/editor/io_plugins/editor_export_scene.h b/tools/editor/io_plugins/editor_export_scene.h
new file mode 100644
index 0000000000..134da6c234
--- /dev/null
+++ b/tools/editor/io_plugins/editor_export_scene.h
@@ -0,0 +1,16 @@
+#ifndef EDITOR_EXPORT_SCENE_H
+#define EDITOR_EXPORT_SCENE_H
+
+#include "tools/editor/editor_import_export.h"
+
+
+class EditorSceneExportPlugin : public EditorExportPlugin {
+ OBJ_TYPE( EditorSceneExportPlugin, EditorExportPlugin );
+public:
+
+ virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform);
+
+ EditorSceneExportPlugin();
+};
+
+#endif // EDITOR_EXPORT_SCENE_H
diff --git a/tools/editor/io_plugins/editor_font_import_plugin.cpp b/tools/editor/io_plugins/editor_font_import_plugin.cpp
index 10a3877529..9b4ca246e7 100644
--- a/tools/editor/io_plugins/editor_font_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_font_import_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -520,6 +520,10 @@ class EditorFontImportDialog : public ConfirmationDialog {
return;
}
+ if (dest->get_line_edit()->get_text().get_file()==".fnt") {
+ dest->get_line_edit()->set_text(dest->get_line_edit()->get_text().get_base_dir() + "/" + source->get_line_edit()->get_text().get_file().basename() + ".fnt" );
+ }
+
Ref<ResourceImportMetadata> rimd = get_rimd();
if (rimd.is_null()) {
@@ -617,6 +621,7 @@ public:
source->get_file_dialog()->set_mode(EditorFileDialog::MODE_OPEN_FILE);
source->get_file_dialog()->add_filter("*.ttf;TrueType");
source->get_file_dialog()->add_filter("*.otf;OpenType");
+ source->get_file_dialog()->add_filter("*.fnt;BMFont");
source->get_line_edit()->connect("text_entered",this,"_src_changed");
vbl->add_margin_child("Source Font:",source);
@@ -872,10 +877,31 @@ static unsigned char get_SDF_radial(
Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata>& p_from, const String &p_existing) {
+
+
Ref<ResourceImportMetadata> from = p_from;
ERR_FAIL_COND_V(from->get_source_count()!=1,Ref<Font>());
String src_path = EditorImportPlugin::expand_source_path(from->get_source_path(0));
+
+ if (src_path.extension().to_lower()=="fnt") {
+
+ if (ResourceLoader::load(src_path).is_valid()) {
+ EditorNode::get_singleton()->show_warning("Path: "+src_path+"\nIs a Godot font file, please supply a BMFont type file instead.");
+ return Ref<Font>();
+ }
+
+ Ref<Font> font;
+ font.instance();
+ Error err = font->create_from_fnt(src_path);
+ if (err) {
+ EditorNode::get_singleton()->show_warning("Path: "+src_path+"\nFailed opening as BMFont file.");
+ return Ref<Font>();
+ }
+
+ return font;
+ }
+
int size = from->get_option("font/size");
#ifdef FREETYPE_ENABLED
diff --git a/tools/editor/io_plugins/editor_font_import_plugin.h b/tools/editor/io_plugins/editor_font_import_plugin.h
index 451f01080e..814897c5f0 100644
--- a/tools/editor/io_plugins/editor_font_import_plugin.h
+++ b/tools/editor/io_plugins/editor_font_import_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/io_plugins/editor_import_collada.cpp b/tools/editor/io_plugins/editor_import_collada.cpp
index d57cff850e..7de9d978f2 100644
--- a/tools/editor/io_plugins/editor_import_collada.cpp
+++ b/tools/editor/io_plugins/editor_import_collada.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -68,6 +68,7 @@ struct ColladaImport {
Map<String,NodeMap> node_map; //map from collada node to engine node
+ Map<String,String> node_name_map; //map from collada node to engine node
Map<String, Ref<Mesh> > mesh_cache;
Map<String, Ref<Curve3D> > curve_cache;
Map<String, Ref<Material> > material_cache;
@@ -124,6 +125,7 @@ Error ColladaImport::_populate_skeleton(Skeleton *p_skeleton,Collada::Node *p_no
nm.node=p_skeleton;
nm.bone = r_bone;
node_map[p_node->id]=nm;
+ node_name_map[p_node->name]=p_node->id;
skeleton_bone_map[p_skeleton][joint->sid]=r_bone;
@@ -345,6 +347,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) {
NodeMap nm;
nm.node=node;
node_map[p_node->id]=nm;
+ node_name_map[p_node->name]=p_node->id;
Transform xf = p_node->default_transform;
xf = collada.fix_transform( xf ) * p_node->post_transform;
@@ -1906,9 +1909,20 @@ void ColladaImport::create_animations(bool p_make_tracks_in_all_bones) {
Collada::AnimationTrack &at = collada.state.animation_tracks[i];
//print_line("CHANNEL: "+at.target+" PARAM: "+at.param);
+
+ String node;
+
if (!node_map.has(at.target)) {
- print_line("Coudlnt find node: "+at.target);
- continue;
+
+ if (node_name_map.has(at.target)) {
+
+ node=node_name_map[at.target];
+ } else {
+ print_line("Coudlnt find node: "+at.target);
+ continue;
+ }
+ } else {
+ node=at.target;
}
@@ -1917,8 +1931,9 @@ void ColladaImport::create_animations(bool p_make_tracks_in_all_bones) {
valid_animated_properties.push_back(i);
} else {
- node_map[at.target].anim_tracks.push_back(i);
- valid_animated_nodes.insert(at.target);
+
+ node_map[node].anim_tracks.push_back(i);
+ valid_animated_nodes.insert(node);
}
}
@@ -1934,6 +1949,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
Ref<Animation> animation = Ref<Animation>( memnew( Animation ));
+
if (p_clip==-1) {
//print_line("default");
@@ -2007,10 +2023,12 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
while(f<anim_length) {
base_snapshots.push_back(f);
+
f+=snapshot_interval;
if (f>=anim_length) {
base_snapshots.push_back(anim_length);
+
}
}
@@ -2019,11 +2037,17 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
bool tracks_found=false;
+
+
for(Set<String>::Element* E=valid_animated_nodes.front();E;E=E->next()) {
// take snapshots
- if (!collada.state.scene_map.has(E->get()))
+
+
+ if (!collada.state.scene_map.has(E->get())) {
+
continue;
+ }
NodeMap &nm = node_map[E->get()];
String path = scene->get_path_to(nm.node);
@@ -2039,7 +2063,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
Collada::Node *cn = collada.state.scene_map[E->get()];
if (cn->ignore_anim) {
- //print_line("warning, ignoring animation on node: "+path);
+
continue;
}
@@ -2058,20 +2082,23 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
for(int i=0;i<at.keys.size();i++)
snapshots.push_back(at.keys[i].time);
- print_line("using anim snapshots");
}
for(int i=0;i<snapshots.size();i++) {
+
for(List<int>::Element *ET=nm.anim_tracks.front();ET;ET=ET->next()) {
//apply tracks
+
if (p_clip==-1) {
- if (track_filter.has(ET->get()))
+ if (track_filter.has(ET->get())) {
+
continue;
+ }
} else {
if (!track_filter.has(ET->get()))
diff --git a/tools/editor/io_plugins/editor_import_collada.h b/tools/editor/io_plugins/editor_import_collada.h
index 243cd043a0..de45dc38f4 100644
--- a/tools/editor/io_plugins/editor_import_collada.h
+++ b/tools/editor/io_plugins/editor_import_collada.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.cpp b/tools/editor/io_plugins/editor_sample_import_plugin.cpp
index 7888246956..b81c88c817 100644
--- a/tools/editor/io_plugins/editor_sample_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_sample_import_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -859,7 +859,7 @@ Vector<uint8_t> EditorSampleExportPlugin::custom_export(String& p_path,const Ref
ERR_FAIL_COND_V(err!=OK,Vector<uint8_t>());
- p_path=p_path.basename()+".smp";
+ p_path=p_path.basename()+".converted.smp";
return FileAccess::get_file_as_array(savepath);
}
diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.h b/tools/editor/io_plugins/editor_sample_import_plugin.h
index 89319affa0..b31562af76 100644
--- a/tools/editor/io_plugins/editor_sample_import_plugin.h
+++ b/tools/editor/io_plugins/editor_sample_import_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.cpp b/tools/editor/io_plugins/editor_scene_import_plugin.cpp
index ca44df269b..a3b6827cd4 100644
--- a/tools/editor/io_plugins/editor_scene_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_scene_import_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.h b/tools/editor/io_plugins/editor_scene_import_plugin.h
index 71efab9503..1f3b73fe7f 100644
--- a/tools/editor/io_plugins/editor_scene_import_plugin.h
+++ b/tools/editor/io_plugins/editor_scene_import_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp
index 8d5a4f1dcf..29273ebd06 100644
--- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1666,7 +1666,7 @@ EditorTextureImportPlugin::EditorTextureImportPlugin(EditorNode *p_editor, Mode
if (pl.is_valid()) {
Vector<uint8_t> ce = pl->custom_export(p_path,p_platform);
if (ce.size()) {
- p_path=p_path.basename()+".tex";
+ p_path=p_path.basename()+".converted.tex";
return ce;
}
}
@@ -1680,7 +1680,7 @@ EditorTextureImportPlugin::EditorTextureImportPlugin(EditorNode *p_editor, Mode
if (pl.is_valid()) {
Vector<uint8_t> ce = pl->custom_export(p_path,p_platform);
if (ce.size()) {
- p_path=p_path.basename()+".tex";
+ p_path=p_path.basename()+".converted.tex";
return ce;
}
}
diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.h b/tools/editor/io_plugins/editor_texture_import_plugin.h
index 38fd671e9d..cb63ba98c8 100644
--- a/tools/editor/io_plugins/editor_texture_import_plugin.h
+++ b/tools/editor/io_plugins/editor_texture_import_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/io_plugins/editor_translation_import_plugin.cpp b/tools/editor/io_plugins/editor_translation_import_plugin.cpp
index d152d71af4..1edfe697b6 100644
--- a/tools/editor/io_plugins/editor_translation_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_translation_import_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/io_plugins/editor_translation_import_plugin.h b/tools/editor/io_plugins/editor_translation_import_plugin.h
index f3c2884534..cadcdc03b3 100644
--- a/tools/editor/io_plugins/editor_translation_import_plugin.h
+++ b/tools/editor/io_plugins/editor_translation_import_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/optimized_save_dialog.cpp b/tools/editor/optimized_save_dialog.cpp
index 687d3675fc..4814b3b021 100644
--- a/tools/editor/optimized_save_dialog.cpp
+++ b/tools/editor/optimized_save_dialog.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/optimized_save_dialog.h b/tools/editor/optimized_save_dialog.h
index 739d0e1506..bdc36eddc1 100644
--- a/tools/editor/optimized_save_dialog.h
+++ b/tools/editor/optimized_save_dialog.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/output_strings.cpp b/tools/editor/output_strings.cpp
index 30569d11b0..a19352f4ec 100644
--- a/tools/editor/output_strings.cpp
+++ b/tools/editor/output_strings.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/output_strings.h b/tools/editor/output_strings.h
index ad893534fa..3d5deb1646 100644
--- a/tools/editor/output_strings.h
+++ b/tools/editor/output_strings.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/pane_drag.cpp b/tools/editor/pane_drag.cpp
index fb137de5ce..8e8c2941ec 100644
--- a/tools/editor/pane_drag.cpp
+++ b/tools/editor/pane_drag.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/pane_drag.h b/tools/editor/pane_drag.h
index a6cd9b6662..24f2ef7ed8 100644
--- a/tools/editor/pane_drag.h
+++ b/tools/editor/pane_drag.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/animation_data_editor_plugin.cpp b/tools/editor/plugins/animation_data_editor_plugin.cpp
index d8d65b875a..a73c75056b 100644
--- a/tools/editor/plugins/animation_data_editor_plugin.cpp
+++ b/tools/editor/plugins/animation_data_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/animation_data_editor_plugin.h b/tools/editor/plugins/animation_data_editor_plugin.h
index 0daa67d0a5..0a12638474 100644
--- a/tools/editor/plugins/animation_data_editor_plugin.h
+++ b/tools/editor/plugins/animation_data_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/animation_player_editor_plugin.cpp b/tools/editor/plugins/animation_player_editor_plugin.cpp
index 6542fc8b4a..43b4276d45 100644
--- a/tools/editor/plugins/animation_player_editor_plugin.cpp
+++ b/tools/editor/plugins/animation_player_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,20 +32,20 @@
#include "io/resource_saver.h"
#include "os/keyboard.h"
#include "tools/editor/editor_settings.h"
+#include "tools/editor/animation_editor.h"
void AnimationPlayerEditor::_node_removed(Node *p_node) {
if (player && player == p_node) {
player=NULL;
- hide();
+
set_process(false);
- if (edit_anim->is_pressed()) {
- editor->get_animation_editor()->set_animation(Ref<Animation>());
- editor->get_animation_editor()->set_root(NULL);
- editor->animation_editor_make_visible(false);
- edit_anim->set_pressed(false);
- }
+ key_editor->set_animation(Ref<Animation>());
+ key_editor->set_root(NULL);
+ _update_player();
+ //editor->animation_editor_make_visible(false);
+
}
}
@@ -72,19 +72,18 @@ void AnimationPlayerEditor::_notification(int p_what) {
Ref<Animation> anim = player->get_animation(animname);
if (!anim.is_null()) {
- seek->set_max(anim->get_length());
+ frame->set_max(anim->get_length());
}
}
}
- seek->set_val(player->get_current_animation_pos());
- if (edit_anim->is_pressed())
- editor->get_animation_editor()->set_anim_pos(player->get_current_animation_pos());
+ frame->set_val(player->get_current_animation_pos());
+ key_editor->set_anim_pos(player->get_current_animation_pos());
EditorNode::get_singleton()->get_property_editor()->refresh();
} else if (last_active) {
//need the last frame after it stopped
- seek->set_val(player->get_current_animation_pos());
+ frame->set_val(player->get_current_animation_pos());
}
last_active=player->is_playing();
@@ -94,7 +93,7 @@ void AnimationPlayerEditor::_notification(int p_what) {
if (p_what==NOTIFICATION_ENTER_TREE) {
- editor->connect("hide_animation_player_editors",this,"_hide_anim_editors");
+// editor->connect("hide_animation_player_editors",this,"_hide_anim_editors");
add_anim->set_icon( get_icon("New","EditorIcons") );
rename_anim->set_icon( get_icon("Rename","EditorIcons") );
duplicate_anim->set_icon( get_icon("Duplicate","EditorIcons") );
@@ -103,7 +102,7 @@ void AnimationPlayerEditor::_notification(int p_what) {
save_anim->set_icon(get_icon("Save", "EditorIcons"));
save_anim->get_popup()->connect("item_pressed", this, "_animation_save_menu");
remove_anim->set_icon( get_icon("Remove","EditorIcons") );
- edit_anim->set_icon( get_icon("Edit","EditorIcons") );
+
blend_anim->set_icon( get_icon("Blend","EditorIcons") );
play->set_icon( get_icon("PlayStart","EditorIcons") );
play_from->set_icon( get_icon("Play","EditorIcons") );
@@ -113,13 +112,14 @@ void AnimationPlayerEditor::_notification(int p_what) {
autoplay_icon=get_icon("AutoPlay","EditorIcons");
stop->set_icon( get_icon("Stop","EditorIcons") );
resource_edit_anim->set_icon( get_icon("EditResource","EditorIcons") );
- pin->set_normal_texture(get_icon("Pin","EditorIcons") );
- pin->set_pressed_texture( get_icon("PinPressed","EditorIcons") );
+ pin->set_icon(get_icon("Pin","EditorIcons") );
tool_anim->set_icon(get_icon("Tools","EditorIcons"));
tool_anim->get_popup()->connect("item_pressed",this,"_animation_tool_menu");
blend_editor.next->connect("text_changed",this,"_blend_editor_next_changed");
+ nodename->set_icon(get_icon("AnimationPlayer","EditorIcons"));
+
/*
anim_editor_load->set_normal_texture( get_icon("AnimGet","EditorIcons"));
anim_editor_store->set_normal_texture( get_icon("AnimSet","EditorIcons"));
@@ -295,22 +295,25 @@ void AnimationPlayerEditor::_animation_selected(int p_which) {
player->set_current_animation( current );
Ref<Animation> anim = player->get_animation(current);
- if (edit_anim->is_pressed()) {
- Ref<Animation> anim = player->get_animation(current);
- editor->get_animation_editor()->set_animation(anim);
+ {
+
+ key_editor->set_animation(anim);
Node *root = player->get_node(player->get_root());
if (root) {
- editor->get_animation_editor()->set_root(root);
+ key_editor->set_root(root);
}
}
- seek->set_max(anim->get_length());
+ frame->set_max(anim->get_length());
+ if (anim->get_step())
+ frame->set_step(anim->get_step());
+ else
+ frame->set_step(0.00001);
+
} else {
- if (edit_anim->is_pressed()) {
- editor->get_animation_editor()->set_animation(Ref<Animation>());
- editor->get_animation_editor()->set_root(NULL);
- }
+ key_editor->set_animation(Ref<Animation>());
+ key_editor->set_root(NULL);
}
@@ -631,7 +634,7 @@ Dictionary AnimationPlayerEditor::get_state() const {
if (is_visible() && player) {
d["player"]=EditorNode::get_singleton()->get_edited_scene()->get_path_to(player);
d["animation"]=player->get_current_animation();
- d["editing"]=edit_anim->is_pressed();
+
}
return d;
@@ -648,16 +651,12 @@ void AnimationPlayerEditor::set_state(const Dictionary& p_state) {
show();
set_process(true);
ensure_visibility();
- EditorNode::get_singleton()->animation_panel_make_visible(true);
+// EditorNode::get_singleton()->animation_panel_make_visible(true);
if (p_state.has("animation")) {
String anim = p_state["animation"];
_select_anim_by_name(anim);
- if (p_state.has("editing") && p_state["editing"]) {
-
- edit_anim->set_pressed(true);
- _animation_edit();
- }
+ _animation_edit();
}
}
@@ -678,36 +677,22 @@ void AnimationPlayerEditor::_animation_resource_edit() {
void AnimationPlayerEditor::_animation_edit() {
-// if (animation->get_item_count()==0)
-// return;
-
- if (edit_anim->is_pressed()) {
- editor->animation_editor_make_visible(true);
-
- //editor->get_animation_editor()->set_root(player->get_roo); - get root pending
- if (animation->get_item_count()) {
- String current = animation->get_item_text(animation->get_selected());
- Ref<Animation> anim = player->get_animation(current);
- editor->get_animation_editor()->set_animation(anim);
- Node *root = player->get_node(player->get_root());
- if (root) {
- editor->get_animation_editor()->set_root(root);
- }
+ if (animation->get_item_count()) {
+ String current = animation->get_item_text(animation->get_selected());
+ Ref<Animation> anim = player->get_animation(current);
+ key_editor->set_animation(anim);
+ Node *root = player->get_node(player->get_root());
+ if (root) {
+ key_editor->set_root(root);
+ }
- } else {
+ } else {
- editor->get_animation_editor()->set_animation(Ref<Animation>());
- editor->get_animation_editor()->set_root(NULL);
+ key_editor->set_animation(Ref<Animation>());
+ key_editor->set_root(NULL);
- }
- } else {
- editor->animation_editor_make_visible(false);
- editor->get_animation_editor()->set_animation(Ref<Animation>());
- editor->get_animation_editor()->set_root(NULL);
}
- //get_scene()->get_root_node()->call("_resource_selected",anim,"");
-
}
void AnimationPlayerEditor::_dialog_action(String p_file) {
@@ -800,16 +785,21 @@ void AnimationPlayerEditor::_update_animation() {
void AnimationPlayerEditor::_update_player() {
- if (!player)
- return;
updating=true;
List<StringName> animlist;
- player->get_animation_list(&animlist);
+ if (player)
+ player->get_animation_list(&animlist);
animation->clear();
- nodename->set_text(player->get_name());
+ if (player)
+ nodename->set_text(player->get_name());
+ else
+ nodename->set_text("<empty>");
+
+ add_anim->set_disabled(player==NULL);
+ load_anim->set_disabled(player==NULL);
stop->set_disabled(animlist.size()==0);
play->set_disabled(animlist.size()==0);
play_bw->set_disabled(animlist.size()==0);
@@ -837,6 +827,9 @@ void AnimationPlayerEditor::_update_player() {
}
+ if (!player)
+ return;
+
updating=false;
if (active_idx!=-1) {
animation->select(active_idx);
@@ -852,17 +845,14 @@ void AnimationPlayerEditor::_update_player() {
//pause->set_pressed(player->is_paused());
- if (edit_anim->is_pressed()) {
-
- if (animation->get_item_count()) {
- String current = animation->get_item_text(animation->get_selected());
- Ref<Animation> anim = player->get_animation(current);
- editor->get_animation_editor()->set_animation(anim);
- Node *root = player->get_node(player->get_root());
- if (root) {
- editor->get_animation_editor()->set_root(root);
- }
+ if (animation->get_item_count()) {
+ String current = animation->get_item_text(animation->get_selected());
+ Ref<Animation> anim = player->get_animation(current);
+ key_editor->set_animation(anim);
+ Node *root = player->get_node(player->get_root());
+ if (root) {
+ key_editor->set_root(root);
}
}
@@ -958,7 +948,7 @@ void AnimationPlayerEditor::_seek_value_changed(float p_value) {
Ref<Animation> anim;
anim=player->get_animation(current);
- float pos = anim->get_length() * (p_value / seek->get_max());
+ float pos = anim->get_length() * (p_value / frame->get_max());
if (player->is_valid()) {
float cpos = player->get_current_animation_pos();
@@ -968,8 +958,7 @@ void AnimationPlayerEditor::_seek_value_changed(float p_value) {
player->seek(pos,true);
}
- if (edit_anim->is_pressed())
- editor->get_animation_editor()->set_anim_pos(pos);
+ key_editor->set_anim_pos(pos);
updating=true;
};
@@ -999,19 +988,19 @@ void AnimationPlayerEditor::_editor_store() {
String current = animation->get_item_text(animation->get_selected());
Ref<Animation> anim = player->get_animation(current);
- if (editor->get_animation_editor()->get_current_animation()==anim)
+ if (key_editor->get_current_animation()==anim)
return; //already there
undo_redo->create_action("Store anim in editor");
- undo_redo->add_do_method(editor->get_animation_editor(),"set_animation",anim);
- undo_redo->add_undo_method(editor->get_animation_editor(),"remove_animation",anim);
+ undo_redo->add_do_method(key_editor,"set_animation",anim);
+ undo_redo->add_undo_method(key_editor,"remove_animation",anim);
undo_redo->commit_action();
}
void AnimationPlayerEditor::_editor_load(){
- Ref<Animation> anim = editor->get_animation_editor()->get_current_animation();
+ Ref<Animation> anim = key_editor->get_current_animation();
if (anim.is_null())
return;
@@ -1059,7 +1048,16 @@ void AnimationPlayerEditor::_editor_load(){
void AnimationPlayerEditor::_animation_key_editor_anim_len_changed(float p_len) {
- seek->set_max(p_len);
+ frame->set_max(p_len);
+
+}
+
+void AnimationPlayerEditor::_animation_key_editor_anim_step_changed(float p_len) {
+
+ if (p_len)
+ frame->set_step(p_len);
+ else
+ frame->set_step(0.00001);
}
@@ -1074,7 +1072,7 @@ void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos) {
if (player->is_playing() )
return;
- seek->set_val(p_pos);
+ frame->set_val(p_pos);
EditorNode::get_singleton()->get_property_editor()->refresh();
@@ -1087,13 +1085,11 @@ void AnimationPlayerEditor::_hide_anim_editors() {
player=NULL;
hide();
set_process(false);
- if (edit_anim->is_pressed()) {
- editor->get_animation_editor()->set_animation(Ref<Animation>());
- editor->get_animation_editor()->set_root(NULL);
- editor->animation_editor_make_visible(false);
- edit_anim->set_pressed(false);
- }
+ key_editor->set_animation(Ref<Animation>());
+ key_editor->set_root(NULL);
+// editor->animation_editor_make_visible(false);
+
}
@@ -1238,6 +1234,7 @@ void AnimationPlayerEditor::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_list_changed"),&AnimationPlayerEditor::_list_changed);
ObjectTypeDB::bind_method(_MD("_animation_key_editor_seek"),&AnimationPlayerEditor::_animation_key_editor_seek);
ObjectTypeDB::bind_method(_MD("_animation_key_editor_anim_len_changed"),&AnimationPlayerEditor::_animation_key_editor_anim_len_changed);
+ ObjectTypeDB::bind_method(_MD("_animation_key_editor_anim_step_changed"),&AnimationPlayerEditor::_animation_key_editor_anim_step_changed);
ObjectTypeDB::bind_method(_MD("_hide_anim_editors"),&AnimationPlayerEditor::_hide_anim_editors);
ObjectTypeDB::bind_method(_MD("_animation_duplicate"),&AnimationPlayerEditor::_animation_duplicate);
ObjectTypeDB::bind_method(_MD("_blend_editor_next_changed"),&AnimationPlayerEditor::_blend_editor_next_changed);
@@ -1250,8 +1247,15 @@ void AnimationPlayerEditor::_bind_methods() {
}
+AnimationPlayerEditor *AnimationPlayerEditor::singleton=NULL;
+
+AnimationPlayer *AnimationPlayerEditor::get_player() const {
+
+ return player;
+}
AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) {
editor=p_editor;
+ singleton=this;
updating=false;
@@ -1271,6 +1275,50 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) {
add_child(hb);
+ play_bw_from = memnew( ToolButton );
+ play_bw_from->set_tooltip("Play backwards selected animation from current pos. (A)");
+ hb->add_child(play_bw_from);
+
+ play_bw = memnew( ToolButton );
+ play_bw->set_tooltip("Play backwards selected animation from end. (Shift+A)");
+ hb->add_child(play_bw);
+
+ stop = memnew( ToolButton );
+ stop->set_toggle_mode(true);
+ hb->add_child(stop);
+ stop->set_tooltip("Stop animation playback. (S)");
+
+ play = memnew( ToolButton );
+ play->set_tooltip("Play selected animation from start. (Shift+D)");
+ hb->add_child(play);
+
+
+ play_from = memnew( ToolButton );
+ play_from->set_tooltip("Play selected animation from current pos. (D)");
+ hb->add_child(play_from);
+
+
+
+ //pause = memnew( Button );
+ //pause->set_toggle_mode(true);
+ //hb->add_child(pause);
+
+ frame = memnew( SpinBox );
+ hb->add_child(frame);
+ frame->set_custom_minimum_size(Size2(80,0));
+ frame->set_stretch_ratio(2);
+ frame->set_tooltip("Animation position (in seconds).");
+
+ hb->add_child( memnew( VSeparator));
+
+ scale = memnew( LineEdit );
+ hb->add_child(scale);
+ scale->set_h_size_flags(SIZE_EXPAND_FILL);
+ scale->set_stretch_ratio(1);
+ scale->set_tooltip("Scale animation playback globally for the node.");
+ scale->hide();
+
+
add_anim = memnew( ToolButton );
add_anim->set_tooltip("Create new animation in player.");
@@ -1330,67 +1378,13 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) {
//tool_anim->get_popup()->add_item("Edit Anim Resource",TOOL_PASTE_ANIM);
hb->add_child(tool_anim);
-
- edit_anim = memnew( ToolButton );
- edit_anim->set_toggle_mode(true);
- hb->add_child(edit_anim);
- edit_anim->set_tooltip("Open animation editor.\nProperty editor will displays all editable keys too.");
-
-
- hb = memnew (HBoxContainer);
- add_child(hb);
-
- play_bw_from = memnew( ToolButton );
- play_bw_from->set_tooltip("Play backwards selected animation from current pos. (A)");
- hb->add_child(play_bw_from);
-
- play_bw = memnew( ToolButton );
- play_bw->set_tooltip("Play backwards selected animation from end. (Shift+A)");
- hb->add_child(play_bw);
-
- stop = memnew( ToolButton );
- stop->set_toggle_mode(true);
- hb->add_child(stop);
- stop->set_tooltip("Stop animation playback. (S)");
-
- play = memnew( ToolButton );
- play->set_tooltip("Play selected animation from start. (Shift+D)");
- hb->add_child(play);
+ nodename = memnew( Button );
+ hb->add_child(nodename);
+ pin = memnew( ToolButton );
+ pin->set_toggle_mode(true);
+ hb->add_child(pin);
- play_from = memnew( ToolButton );
- play_from->set_tooltip("Play selected animation from current pos. (D)");
- hb->add_child(play_from);
-
-
-
- //pause = memnew( Button );
- //pause->set_toggle_mode(true);
- //hb->add_child(pause);
-
- seek = memnew( HSlider );
- seek->set_val(0);
- seek->set_step(0.01);
- hb->add_child(seek);
- seek->set_h_size_flags(SIZE_EXPAND_FILL);
- seek->set_stretch_ratio(8);
- seek->set_tooltip("Seek animation (when stopped).");
-
- frame = memnew( SpinBox );
- hb->add_child(frame);
- frame->set_h_size_flags(SIZE_EXPAND_FILL);
- frame->set_stretch_ratio(2);
- frame->set_tooltip("Animation position (in seconds).");
- seek->share(frame);
-
-
-
- scale = memnew( LineEdit );
- hb->add_child(scale);
- scale->set_h_size_flags(SIZE_EXPAND_FILL);
- scale->set_stretch_ratio(1);
- scale->set_tooltip("Scale animation playback globally for the node.");
- scale->hide();
resource_edit_anim= memnew( Button );
hb->add_child(resource_edit_anim);
@@ -1457,30 +1451,31 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) {
load_anim->connect("pressed", this,"_animation_load");
duplicate_anim->connect("pressed", this,"_animation_duplicate");
//frame->connect("text_entered", this,"_seek_frame_changed");
- edit_anim->connect("pressed", this,"_animation_edit");
+
blend_anim->connect("pressed", this,"_animation_blend");
remove_anim->connect("pressed", this,"_animation_remove");
animation->connect("item_selected", this,"_animation_selected",Vector<Variant>(),true);
resource_edit_anim->connect("pressed", this,"_animation_resource_edit");
file->connect("file_selected", this,"_dialog_action");
- seek->connect("value_changed", this, "_seek_value_changed",Vector<Variant>(),true);
+ frame->connect("value_changed", this, "_seek_value_changed",Vector<Variant>(),true);
scale->connect("text_entered", this, "_scale_changed",Vector<Variant>(),true);
- editor->get_animation_editor()->connect("timeline_changed",this,"_animation_key_editor_seek");
- editor->get_animation_editor()->connect("animation_len_changed",this,"_animation_key_editor_anim_len_changed");
-
- HBoxContainer *ahb = editor->get_animation_panel_hb();
- nodename = memnew( Label );
- ahb->add_child(nodename);
- nodename->set_h_size_flags(SIZE_EXPAND_FILL);
- nodename->set_opacity(0.5);
- pin = memnew( TextureButton );
- pin->set_toggle_mode(true);
- ahb->add_child(pin);
+
+
renaming=false;
last_active=false;
set_process_unhandled_key_input(true);
+
+ key_editor = memnew( AnimationKeyEditor);
+ add_child(key_editor);
+ add_constant_override("separation",get_constant("separation","VBoxContainer"));
+ key_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+ key_editor->connect("timeline_changed",this,"_animation_key_editor_seek");
+ key_editor->connect("animation_len_changed",this,"_animation_key_editor_anim_len_changed");
+ key_editor->connect("animation_step_changed",this,"_animation_key_editor_anim_step_changed");
+
+ _update_player();
}
@@ -1503,7 +1498,7 @@ void AnimationPlayerEditorPlugin::make_visible(bool p_visible) {
anim_editor->show();
anim_editor->set_process(true);
anim_editor->ensure_visibility();
- editor->animation_panel_make_visible(true);
+// editor->animation_panel_make_visible(true);
} else {
// anim_editor->hide();
@@ -1517,7 +1512,8 @@ AnimationPlayerEditorPlugin::AnimationPlayerEditorPlugin(EditorNode *p_node) {
editor=p_node;
anim_editor = memnew( AnimationPlayerEditor(editor) );
anim_editor->set_undo_redo(editor->get_undo_redo());
- editor->get_animation_panel()->add_child(anim_editor);
+
+ editor->add_bottom_panel_item("Animation",anim_editor);
/*
editor->get_viewport()->add_child(anim_editor);
anim_editor->set_area_as_parent_rect();
diff --git a/tools/editor/plugins/animation_player_editor_plugin.h b/tools/editor/plugins/animation_player_editor_plugin.h
index ac4d1ab6ba..0ad849c2f9 100644
--- a/tools/editor/plugins/animation_player_editor_plugin.h
+++ b/tools/editor/plugins/animation_player_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -41,7 +41,7 @@
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
-
+class AnimationKeyEditor;
class AnimationPlayerEditor : public VBoxContainer {
OBJ_TYPE(AnimationPlayerEditor, VBoxContainer );
@@ -78,17 +78,16 @@ class AnimationPlayerEditor : public VBoxContainer {
Button *autoplay;
Button *rename_anim;
Button *duplicate_anim;
- Button *edit_anim;
+
Button *resource_edit_anim;
Button *load_anim;
MenuButton *save_anim;
Button *blend_anim;
Button *remove_anim;
MenuButton *tool_anim;
- TextureButton *pin;
- Label *nodename;
+ ToolButton *pin;
+ Button *nodename;
SpinBox *frame;
- HSlider *seek;
LineEdit *scale;
LineEdit *name;
Label *name_title;
@@ -117,6 +116,9 @@ class AnimationPlayerEditor : public VBoxContainer {
bool updating;
bool updating_blends;
+ AnimationKeyEditor *key_editor;
+
+
void _select_anim_by_name(const String& p_anim);
void _play_pressed();
void _play_from_pressed();
@@ -158,10 +160,13 @@ class AnimationPlayerEditor : public VBoxContainer {
void _animation_key_editor_seek(float p_pos);
void _animation_key_editor_anim_len_changed(float p_new);
+ void _animation_key_editor_anim_step_changed(float p_len);
+
void _unhandled_key_input(const InputEvent& p_ev);
void _animation_tool_menu(int p_option);
void _animation_save_menu(int p_option);
+
AnimationPlayerEditor();
protected:
@@ -171,6 +176,10 @@ protected:
static void _bind_methods();
public:
+ AnimationPlayer *get_player() const;
+ static AnimationPlayerEditor *singleton;
+
+ AnimationKeyEditor* get_key_editor() { return key_editor; }
Dictionary get_state() const;
void set_state(const Dictionary& p_state);
diff --git a/tools/editor/plugins/animation_tree_editor_plugin.cpp b/tools/editor/plugins/animation_tree_editor_plugin.cpp
index 382bc44726..d85553b4db 100644
--- a/tools/editor/plugins/animation_tree_editor_plugin.cpp
+++ b/tools/editor/plugins/animation_tree_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1498,18 +1498,17 @@ bool AnimationTreeEditorPlugin::handles(Object *p_object) const {
void AnimationTreeEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
- editor->hide_animation_player_editors();
- editor->animation_panel_make_visible(true);
- anim_tree_editor->show();
+// editor->hide_animation_player_editors();
+// editor->animation_panel_make_visible(true);
+ button->show();
+ editor->make_bottom_panel_item_visible(anim_tree_editor);
anim_tree_editor->set_fixed_process(true);
- EditorNode::get_top_split()->set_collapsed(false);
-
} else {
- anim_tree_editor->hide();
+ if (anim_tree_editor->is_visible())
+ editor->hide_bottom_panel();
+ button->hide();
anim_tree_editor->set_fixed_process(false);
- editor->animation_panel_make_visible(false);
- EditorNode::get_top_split()->set_collapsed(true);
}
}
@@ -1517,12 +1516,10 @@ AnimationTreeEditorPlugin::AnimationTreeEditorPlugin(EditorNode *p_node) {
editor=p_node;
anim_tree_editor = memnew( AnimationTreeEditor );
- //editor->get_viewport()->add_child(anim_tree_editor);
- //anim_tree_editor->set_area_as_parent_rect();
- editor->get_animation_panel()->add_child(anim_tree_editor);
- anim_tree_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- anim_tree_editor->hide();
+ anim_tree_editor->set_custom_minimum_size(Size2(0,300));
+ button=editor->add_bottom_panel_item("AnimationTree",anim_tree_editor);
+ button->hide();
diff --git a/tools/editor/plugins/animation_tree_editor_plugin.h b/tools/editor/plugins/animation_tree_editor_plugin.h
index bd29530c7a..4884a22d90 100644
--- a/tools/editor/plugins/animation_tree_editor_plugin.h
+++ b/tools/editor/plugins/animation_tree_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -176,6 +176,7 @@ class AnimationTreeEditorPlugin : public EditorPlugin {
AnimationTreeEditor *anim_tree_editor;
EditorNode *editor;
+ Button *button;
public:
diff --git a/tools/editor/plugins/camera_editor_plugin.cpp b/tools/editor/plugins/camera_editor_plugin.cpp
index 08ed2c745d..7433264b16 100644
--- a/tools/editor/plugins/camera_editor_plugin.cpp
+++ b/tools/editor/plugins/camera_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/camera_editor_plugin.h b/tools/editor/plugins/camera_editor_plugin.h
index afb8f9415d..ea016ecb4d 100644
--- a/tools/editor/plugins/camera_editor_plugin.h
+++ b/tools/editor/plugins/camera_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp
index a3164fc524..a259fa0fcc 100644
--- a/tools/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,6 +37,8 @@
#include "os/input.h"
#include "tools/editor/editor_settings.h"
#include "scene/gui/grid_container.h"
+#include "tools/editor/animation_editor.h"
+#include "tools/editor/plugins/animation_player_editor_plugin.h"
class SnapDialog : public ConfirmationDialog {
@@ -152,9 +154,49 @@ public:
}
};
+void CanvasItemEditor::_edit_set_pivot(const Vector2& mouse_pos) {
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ undo_redo->create_action("Move Pivot");
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Node2D *n2d = E->get()->cast_to<Node2D>();
+
+ if (n2d && n2d->edit_has_pivot()) {
+
+ Vector2 offset = n2d->edit_get_pivot();
+ Vector2 gpos = n2d->get_global_pos();
+
+ Vector2 local_mouse_pos = n2d->get_canvas_transform().affine_inverse().xform(mouse_pos);
+
+ Vector2 motion_ofs = gpos-local_mouse_pos;
+
+ undo_redo->add_do_method(n2d,"set_global_pos",local_mouse_pos);
+ undo_redo->add_do_method(n2d,"edit_set_pivot",offset+n2d->get_global_transform().affine_inverse().basis_xform(motion_ofs));
+ undo_redo->add_undo_method(n2d,"set_global_pos",gpos);
+ undo_redo->add_undo_method(n2d,"edit_set_pivot",offset);
+ for(int i=0;i<n2d->get_child_count();i++) {
+ Node2D *n2dc = n2d->get_child(i)->cast_to<Node2D>();
+ if (!n2dc)
+ continue;
+
+ undo_redo->add_do_method(n2dc,"set_global_pos",n2dc->get_global_pos());
+ undo_redo->add_undo_method(n2dc,"set_global_pos",n2dc->get_global_pos());
+
+ }
+
+ }
+
+ }
+
+ undo_redo->commit_action();
+
+}
+
void CanvasItemEditor::_unhandled_key_input(const InputEvent& p_ev) {
- if (!is_visible())
+ if (!is_visible() || get_viewport()->gui_has_modal_stack())
return;
if (p_ev.key.mod.control)
// prevent to change tool mode when control key is pressed
@@ -179,38 +221,7 @@ void CanvasItemEditor::_unhandled_key_input(const InputEvent& p_ev) {
mouse_pos=transform.affine_inverse().xform(mouse_pos);
mouse_pos=snap_point(mouse_pos);
- undo_redo->create_action("Move Pivot");
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- Node2D *n2d = E->get()->cast_to<Node2D>();
-
- if (n2d && n2d->edit_has_pivot()) {
-
- Vector2 offset = n2d->edit_get_pivot();
- Vector2 gpos = n2d->get_global_pos();
-
- Vector2 motion_ofs = gpos-mouse_pos;
-
- undo_redo->add_do_method(n2d,"set_global_pos",mouse_pos);
- undo_redo->add_do_method(n2d,"edit_set_pivot",offset+n2d->get_global_transform().affine_inverse().basis_xform(motion_ofs));
- undo_redo->add_undo_method(n2d,"set_global_pos",gpos);
- undo_redo->add_undo_method(n2d,"edit_set_pivot",offset);
- for(int i=0;i<n2d->get_child_count();i++) {
- Node2D *n2dc = n2d->get_child(i)->cast_to<Node2D>();
- if (!n2dc)
- continue;
-
- undo_redo->add_do_method(n2dc,"set_global_pos",n2dc->get_global_pos());
- undo_redo->add_undo_method(n2dc,"set_global_pos",n2dc->get_global_pos());
-
- }
-
- }
-
- }
-
- undo_redo->commit_action();
+ _edit_set_pivot(mouse_pos);
}
}
@@ -221,7 +232,7 @@ void CanvasItemEditor::_unhandled_key_input(const InputEvent& p_ev) {
void CanvasItemEditor::_tool_select(int p_index) {
- ToolButton *tb[TOOL_MAX]={select_button,move_button,rotate_button,pan_button};
+ ToolButton *tb[TOOL_MAX]={select_button,list_select_button,move_button,rotate_button,pivot_button,pan_button};
for(int i=0;i<TOOL_MAX;i++) {
tb[i]->set_pressed(i==p_index);
@@ -396,9 +407,9 @@ void CanvasItemEditor::_node_removed(Node *p_node) {
#endif
}
-void CanvasItemEditor::_keying_changed(bool p_changed) {
+void CanvasItemEditor::_keying_changed() {
- if (p_changed)
+ if (AnimationPlayerEditor::singleton->get_key_editor()->has_keying())
animation_hb->show();
else
animation_hb->hide();
@@ -938,6 +949,75 @@ bool CanvasItemEditor::get_remove_list(List<Node*> *p_list) {
}
+void CanvasItemEditor::_list_select(const InputEventMouseButton& b) {
+
+ Point2 click=Point2(b.x,b.y);
+
+ Node* scene = editor->get_edited_scene();
+ if (!scene)
+ return;
+
+ _find_canvas_items_at_pos(click, scene,transform,Matrix32(), selection_results);
+
+ for(int i=0;i<selection_results.size();i++) {
+ CanvasItem *item=selection_results[i].item;
+ if (item!=scene && item->get_owner()!=scene && !scene->is_editable_instance(item->get_owner())) {
+ //invalid result
+ selection_results.remove(i);
+ i--;
+ }
+
+ }
+
+ if (selection_results.size() == 1) {
+
+ CanvasItem *item = selection_results[0].item;
+ selection_results.clear();
+
+ additive_selection=b.mod.shift;
+ if (!_select(item, click, additive_selection, false))
+ return;
+
+ } else if (!selection_results.empty()) {
+
+ selection_results.sort();
+
+ NodePath root_path = get_tree()->get_edited_scene_root()->get_path();
+ StringName root_name = root_path.get_name(root_path.get_name_count()-1);
+
+ for (int i = 0; i < selection_results.size(); i++) {
+
+ CanvasItem *item=selection_results[i].item;
+
+
+ Ref<Texture> icon;
+ if (item->has_meta("_editor_icon"))
+ icon=item->get_meta("_editor_icon");
+ else
+ icon=get_icon( has_icon(item->get_type(),"EditorIcons")?item->get_type():String("Object"),"EditorIcons");
+
+ String node_path="/"+root_name+"/"+root_path.rel_path_to(item->get_path());
+
+ selection_menu->add_item(item->get_name());
+ selection_menu->set_item_icon(i, icon );
+ selection_menu->set_item_metadata(i, node_path);
+ selection_menu->set_item_tooltip(i,String(item->get_name())+
+ "\nType: "+item->get_type()+"\nPath: "+node_path);
+ }
+
+ additive_selection=b.mod.shift;
+
+ selection_menu->set_global_pos(Vector2( b.global_x, b.global_y ));
+ selection_menu->popup();
+ selection_menu->call_deferred("grab_click_focus");
+ selection_menu->set_invalidate_click_until_motion();
+
+
+ return;
+ }
+
+}
+
void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
{
@@ -993,59 +1073,11 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
if (b.button_index==BUTTON_RIGHT) {
- if (b.pressed && tool==TOOL_SELECT && b.mod.alt) {
-
- Point2 click=Point2(b.x,b.y);
-
- Node* scene = editor->get_edited_scene();
- if (!scene)
- return;
-
- _find_canvas_items_at_pos(click, scene,transform,Matrix32(), selection_results);
-
- if (selection_results.size() == 1) {
-
- CanvasItem *item = selection_results[0].item;
- selection_results.clear();
-
- additive_selection=b.mod.shift;
- if (!_select(item, click, additive_selection, false))
- return;
-
- } else if (!selection_results.empty()) {
-
- selection_results.sort();
-
- NodePath root_path = get_tree()->get_edited_scene_root()->get_path();
- StringName root_name = root_path.get_name(root_path.get_name_count()-1);
- for (int i = 0; i < selection_results.size(); i++) {
+ if (b.pressed && (tool==TOOL_SELECT && b.mod.alt)) {
- CanvasItem *item=selection_results[i].item;
-
- Ref<Texture> icon;
- if (item->has_meta("_editor_icon"))
- icon=item->get_meta("_editor_icon");
- else
- icon=get_icon( has_icon(item->get_type(),"EditorIcons")?item->get_type():String("Object"),"EditorIcons");
-
- String node_path="/"+root_name+"/"+root_path.rel_path_to(item->get_path());
-
- selection_menu->add_item(item->get_name());
- selection_menu->set_item_icon(i, icon );
- selection_menu->set_item_metadata(i, node_path);
- selection_menu->set_item_tooltip(i,String(item->get_name())+
- "\nType: "+item->get_type()+"\nPath: "+node_path);
- }
-
- additive_selection=b.mod.shift;
-
- selection_menu->set_global_pos(Vector2( b.global_x, b.global_y ));
- selection_menu->popup();
- selection_menu->call_deferred("grab_click_focus");
-
- return;
- }
+ _list_select(b);
+ return;
}
if (get_item_count() > 0 && drag!=DRAG_NONE) {
@@ -1103,6 +1135,26 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
//if (!canvas_items.size())
// return;
+ if (b.button_index==BUTTON_LEFT && tool==TOOL_LIST_SELECT) {
+ if (b.pressed)
+ _list_select(b);
+ return;
+ }
+
+
+ if (b.button_index==BUTTON_LEFT && tool==TOOL_EDIT_PIVOT) {
+ if (b.pressed) {
+
+ Point2 mouse_pos(b.x,b.y);
+ mouse_pos=transform.affine_inverse().xform(mouse_pos);
+ mouse_pos=snap_point(mouse_pos);
+ _edit_set_pivot(mouse_pos);
+ }
+ return;
+ }
+
+
+
if (tool==TOOL_PAN || b.button_index!=BUTTON_LEFT || Input::get_singleton()->is_key_pressed(KEY_SPACE))
return;
@@ -1491,6 +1543,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
continue;
}
+
dfrom = drag_point_from;
dto = snap_point(dto - (drag == DRAG_ALL ? drag_from - drag_point_from : Vector2(0, 0)), drag_point_from);
@@ -1498,30 +1551,35 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) -
canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dfrom);
-
Rect2 local_rect = canvas_item->get_item_rect();
-
- if (false && drag!=DRAG_ALL && m.mod.alt) {
- float aspect = local_rect.size.get_aspect();
- if (aspect!=0) {
- if (ABS(drag_vector.x) > ABS(drag_vector.y)) {
-
- drag_vector.y = ABS(drag_vector.x)/aspect * SGN(drag_vector.y);
- } else {
-
- drag_vector.x = ABS(drag_vector.y)*aspect * SGN(drag_vector.x);
- }
- }
- }
-
-
-
Vector2 begin=local_rect.pos;
Vector2 end=local_rect.pos+local_rect.size;
Vector2 minsize = canvas_item->edit_get_minimum_size();
bool uniform = m.mod.shift;
bool symmetric=m.mod.alt;
+ if (uniform) {
+ float aspect = local_rect.size.get_aspect();
+ switch(drag) {
+ case DRAG_BOTTOM_LEFT:
+ case DRAG_TOP_RIGHT: {
+ if (aspect > 1.0) { // width > height, take x as reference
+ drag_vector.y = -drag_vector.x/aspect;
+ } else { // height > width, take y as reference
+ drag_vector.x = -drag_vector.y*aspect;
+ }
+ } break;
+ case DRAG_BOTTOM_RIGHT:
+ case DRAG_TOP_LEFT: {
+ if (aspect > 1.0) { // width > height, take x as reference
+ drag_vector.y = drag_vector.x/aspect;
+ } else { // height > width, take y as reference
+ drag_vector.x = drag_vector.y*aspect;
+ }
+ } break;
+ default: {}
+ }
+ }
switch(drag) {
case DRAG_ALL: {
@@ -1540,19 +1598,11 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
} break;
case DRAG_BOTTOM_RIGHT: {
- if (uniform) {
- drag_vector.y=drag_vector.x;
- minsize.y=minsize.x;
- }
incend(begin.x,end.x,drag_vector.x,minsize.x,symmetric);
incend(begin.y,end.y,drag_vector.y,minsize.y,symmetric);
- } break;
+ } break;
case DRAG_TOP_LEFT: {
- if (uniform) {
- drag_vector.y=drag_vector.x;
- minsize.y=minsize.x;
- }
incbeg(begin.x,end.x,drag_vector.x,minsize.x,symmetric);
incbeg(begin.y,end.y,drag_vector.y,minsize.y,symmetric);
} break;
@@ -1568,20 +1618,12 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
} break;
case DRAG_TOP_RIGHT: {
- if (uniform) {
- drag_vector.x=-drag_vector.y;
- minsize.x=minsize.y;
- }
incbeg(begin.y,end.y,drag_vector.y,minsize.y,symmetric);
incend(begin.x,end.x,drag_vector.x,minsize.x,symmetric);
} break;
case DRAG_BOTTOM_LEFT: {
- if (uniform) {
- drag_vector.x=-drag_vector.y;
- minsize.x=minsize.y;
- }
incbeg(begin.x,end.x,drag_vector.x,minsize.x,symmetric);
incend(begin.y,end.y,drag_vector.y,minsize.y,symmetric);
} break;
@@ -1831,6 +1873,8 @@ void CanvasItemEditor::_viewport_draw() {
CanvasItem *single_item=NULL;
+ bool pivot_found=false;
+
for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
@@ -1872,7 +1916,7 @@ void CanvasItemEditor::_viewport_draw() {
viewport->draw_line(endpoints[i],endpoints[(i+1)%4],c,2);
}
- if (single && (tool==TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE)) { //kind of sucks
+ if (single && (tool==TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE || tool==TOOL_EDIT_PIVOT)) { //kind of sucks
if (canvas_item->cast_to<Node2D>()) {
@@ -1880,6 +1924,7 @@ void CanvasItemEditor::_viewport_draw() {
if (canvas_item->cast_to<Node2D>()->edit_has_pivot()) {
viewport->draw_texture(pivot,xform.get_origin()+(-pivot->get_size()/2).floor());
can_move_pivot=true;
+ pivot_found=true;
}
}
@@ -1914,6 +1959,7 @@ void CanvasItemEditor::_viewport_draw() {
//E->get().last_rect = rect;
}
+ pivot_button->set_disabled(!pivot_found);
VisualServer::get_singleton()->canvas_item_add_set_transform(ci,Matrix32());
@@ -2118,9 +2164,11 @@ void CanvasItemEditor::_notification(int p_what) {
}
select_button->set_icon( get_icon("ToolSelect","EditorIcons"));
+ list_select_button->set_icon( get_icon("ListSelect","EditorIcons"));
move_button->set_icon( get_icon("ToolMove","EditorIcons"));
rotate_button->set_icon( get_icon("ToolRotate","EditorIcons"));
pan_button->set_icon( get_icon("ToolPan", "EditorIcons"));
+ pivot_button->set_icon( get_icon("EditPivot", "EditorIcons"));
select_handle=get_icon("EditorHandle","EditorIcons");
lock_button->set_icon(get_icon("Lock","EditorIcons"));
unlock_button->set_icon(get_icon("Unlock","EditorIcons"));
@@ -2649,11 +2697,11 @@ void CanvasItemEditor::_popup_callback(int p_op) {
Node2D *n2d = canvas_item->cast_to<Node2D>();
if (key_pos)
- editor->get_animation_editor()->insert_node_value_key(n2d,"transform/pos",n2d->get_pos(),existing);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d,"transform/pos",n2d->get_pos(),existing);
if (key_rot)
- editor->get_animation_editor()->insert_node_value_key(n2d,"transform/rot",Math::rad2deg(n2d->get_rot()),existing);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d,"transform/rot",Math::rad2deg(n2d->get_rot()),existing);
if (key_scale)
- editor->get_animation_editor()->insert_node_value_key(n2d,"transform/scale",n2d->get_scale(),existing);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d,"transform/scale",n2d->get_scale(),existing);
if (n2d->has_meta("_edit_bone_") && n2d->get_parent_item()) {
@@ -2681,11 +2729,11 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(List<Node2D*>::Element *F=ik_chain.front();F;F=F->next()) {
if (key_pos)
- editor->get_animation_editor()->insert_node_value_key(F->get(),"transform/pos",F->get()->get_pos(),existing);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(),"transform/pos",F->get()->get_pos(),existing);
if (key_rot)
- editor->get_animation_editor()->insert_node_value_key(F->get(),"transform/rot",Math::rad2deg(F->get()->get_rot()),existing);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(),"transform/rot",Math::rad2deg(F->get()->get_rot()),existing);
if (key_scale)
- editor->get_animation_editor()->insert_node_value_key(F->get(),"transform/scale",F->get()->get_scale(),existing);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(),"transform/scale",F->get()->get_scale(),existing);
}
@@ -2697,9 +2745,9 @@ void CanvasItemEditor::_popup_callback(int p_op) {
Control *ctrl = canvas_item->cast_to<Control>();
if (key_pos)
- editor->get_animation_editor()->insert_node_value_key(ctrl,"rect/pos",ctrl->get_pos(),existing);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl,"rect/pos",ctrl->get_pos(),existing);
if (key_scale)
- editor->get_animation_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size(),existing);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size(),existing);
}
}
@@ -2821,7 +2869,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
if (key_pos)
ctrl->set_pos(Point2());
//if (key_scale)
- // editor->get_animation_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size());
+ // AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size());
}
}
@@ -3155,7 +3203,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
hb->add_child(select_button);
select_button->connect("pressed",this,"_tool_select",make_binds(TOOL_SELECT));
select_button->set_pressed(true);
- select_button->set_tooltip("Select Mode (Q)\n"+keycode_get_string(KEY_MASK_CMD)+"Drag: Rotate\nAlt+Drag: Move\nPress 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving).");
+ select_button->set_tooltip("Select Mode (Q)\n"+keycode_get_string(KEY_MASK_CMD)+"Drag: Rotate\nAlt+Drag: Move\nPress 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving).\nAlt+RMB: Depth list selection");
+
move_button = memnew( ToolButton );
move_button->set_toggle_mode(true);
@@ -3171,6 +3220,18 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
hb->add_child(memnew(VSeparator));
+ list_select_button = memnew( ToolButton );
+ list_select_button->set_toggle_mode(true);
+ hb->add_child(list_select_button);
+ list_select_button->connect("pressed",this,"_tool_select",make_binds(TOOL_LIST_SELECT));
+ list_select_button->set_tooltip("Show a list of all objects at the position clicked\n(same as Alt+RMB in selet mode).");
+
+ pivot_button = memnew( ToolButton );
+ pivot_button->set_toggle_mode(true);
+ hb->add_child(pivot_button);
+ pivot_button->connect("pressed",this,"_tool_select",make_binds(TOOL_EDIT_PIVOT));
+ pivot_button->set_tooltip("Click to change object's rotation pivot");
+
pan_button = memnew( ToolButton );
pan_button->set_toggle_mode(true);
hb->add_child(pan_button);
@@ -3357,7 +3418,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
box_selecting=false;
//zoom=0.5;
singleton=this;
- editor->get_animation_editor()->connect("keying_changed",this,"_keying_changed");
+ AnimationPlayerEditor::singleton->get_key_editor()->connect("keying_changed",this,"_keying_changed");
set_process_unhandled_key_input(true);
can_move_pivot=false;
drag=DRAG_NONE;
diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h
index b96d36f7dc..df24734fd7 100644
--- a/tools/editor/plugins/canvas_item_editor_plugin.h
+++ b/tools/editor/plugins/canvas_item_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -67,8 +67,10 @@ class CanvasItemEditor : public VBoxContainer {
enum Tool {
TOOL_SELECT,
+ TOOL_LIST_SELECT,
TOOL_MOVE,
TOOL_ROTATE,
+ TOOL_EDIT_PIVOT,
TOOL_PAN,
TOOL_MAX
};
@@ -240,9 +242,11 @@ class CanvasItemEditor : public VBoxContainer {
List<PoseClipboard> pose_clipboard;
ToolButton *select_button;
+ ToolButton *list_select_button;
ToolButton *move_button;
ToolButton *rotate_button;
+ ToolButton *pivot_button;
ToolButton *pan_button;
ToolButton *lock_button;
@@ -264,6 +268,7 @@ class CanvasItemEditor : public VBoxContainer {
PopupMenu *selection_menu;
+
//PopupMenu *popup;
DragType drag;
Point2 drag_from;
@@ -304,11 +309,13 @@ class CanvasItemEditor : public VBoxContainer {
CanvasItem *ref_item;
+ void _edit_set_pivot(const Vector2& mouse_pos);
void _add_canvas_item(CanvasItem *p_canvas_item);
void _remove_canvas_item(CanvasItem *p_canvas_item);
void _clear_canvas_items();
void _visibility_changed(ObjectID p_canvas_item);
void _key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE p_move_mode);
+ void _list_select(const InputEventMouseButton& b);
DragType _find_drag_type(const Matrix32& p_xform, const Rect2& p_local_rect, const Point2& p_click, Vector2& r_point);
@@ -337,7 +344,7 @@ class CanvasItemEditor : public VBoxContainer {
CanvasItem *get_single_item();
int get_item_count();
- void _keying_changed(bool p_changed);
+ void _keying_changed();
void _unhandled_key_input(const InputEvent& p_ev);
diff --git a/tools/editor/plugins/collision_polygon_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_editor_plugin.cpp
index 60683f4eda..d4198f3166 100644
--- a/tools/editor/plugins/collision_polygon_editor_plugin.cpp
+++ b/tools/editor/plugins/collision_polygon_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/collision_polygon_editor_plugin.h b/tools/editor/plugins/collision_polygon_editor_plugin.h
index 20a0b3c3f6..45e287ef00 100644
--- a/tools/editor/plugins/collision_polygon_editor_plugin.h
+++ b/tools/editor/plugins/collision_polygon_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/color_ramp_editor_plugin.cpp b/tools/editor/plugins/color_ramp_editor_plugin.cpp
index df50535402..42ff1b1de9 100644
--- a/tools/editor/plugins/color_ramp_editor_plugin.cpp
+++ b/tools/editor/plugins/color_ramp_editor_plugin.cpp
@@ -3,14 +3,20 @@
*/
#include "color_ramp_editor_plugin.h"
+#include "spatial_editor_plugin.h"
+#include "canvas_item_editor_plugin.h"
-ColorRampEditorPlugin::ColorRampEditorPlugin(EditorNode *p_node) {
+ColorRampEditorPlugin::ColorRampEditorPlugin(EditorNode *p_node, bool p_2d) {
editor=p_node;
ramp_editor = memnew( ColorRampEdit );
- add_custom_control(CONTAINER_CANVAS_EDITOR_BOTTOM,ramp_editor);
- //add_custom_control(CONTAINER_SPATIAL_EDITOR_BOTTOM,ramp_editor);
+ _2d=p_2d;
+ if (p_2d)
+ add_custom_control(CONTAINER_CANVAS_EDITOR_BOTTOM,ramp_editor);
+ else
+ add_custom_control(CONTAINER_SPATIAL_EDITOR_BOTTOM,ramp_editor);
+
ramp_editor->set_custom_minimum_size(Size2(100, 48));
ramp_editor->hide();
ramp_editor->connect("ramp_changed", this, "ramp_changed");
@@ -27,7 +33,10 @@ void ColorRampEditorPlugin::edit(Object *p_object) {
bool ColorRampEditorPlugin::handles(Object *p_object) const {
- return p_object->is_type("ColorRamp");
+ if (_2d)
+ return p_object->is_type("ColorRamp") && CanvasItemEditor::get_singleton()->is_visible() == true;
+ else
+ return p_object->is_type("ColorRamp") && SpatialEditor::get_singleton()->is_visible() == true;
}
void ColorRampEditorPlugin::make_visible(bool p_visible) {
diff --git a/tools/editor/plugins/color_ramp_editor_plugin.h b/tools/editor/plugins/color_ramp_editor_plugin.h
index e39a5d65fe..f07dbabeb3 100644
--- a/tools/editor/plugins/color_ramp_editor_plugin.h
+++ b/tools/editor/plugins/color_ramp_editor_plugin.h
@@ -13,6 +13,7 @@ class ColorRampEditorPlugin : public EditorPlugin {
OBJ_TYPE( ColorRampEditorPlugin, EditorPlugin );
+ bool _2d;
Ref<ColorRamp> color_ramp_ref;
ColorRampEdit *ramp_editor;
EditorNode *editor;
@@ -29,7 +30,7 @@ public:
virtual bool handles(Object *p_node) const;
virtual void make_visible(bool p_visible);
- ColorRampEditorPlugin(EditorNode *p_node);
+ ColorRampEditorPlugin(EditorNode *p_node, bool p_2d);
~ColorRampEditorPlugin();
};
diff --git a/tools/editor/plugins/control_editor_plugin.cpp b/tools/editor/plugins/control_editor_plugin.cpp
index 7348a69665..375622a89c 100644
--- a/tools/editor/plugins/control_editor_plugin.cpp
+++ b/tools/editor/plugins/control_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/control_editor_plugin.h b/tools/editor/plugins/control_editor_plugin.h
index 074298d0df..94cffc8d8d 100644
--- a/tools/editor/plugins/control_editor_plugin.h
+++ b/tools/editor/plugins/control_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/cube_grid_theme_editor_plugin.cpp b/tools/editor/plugins/cube_grid_theme_editor_plugin.cpp
index c118485083..c861a5841a 100644
--- a/tools/editor/plugins/cube_grid_theme_editor_plugin.cpp
+++ b/tools/editor/plugins/cube_grid_theme_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/cube_grid_theme_editor_plugin.h b/tools/editor/plugins/cube_grid_theme_editor_plugin.h
index 583ddf6e14..72ee171e19 100644
--- a/tools/editor/plugins/cube_grid_theme_editor_plugin.h
+++ b/tools/editor/plugins/cube_grid_theme_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/editor_preview_plugins.cpp b/tools/editor/plugins/editor_preview_plugins.cpp
index 5f52d4c3e7..f3b5272571 100644
--- a/tools/editor/plugins/editor_preview_plugins.cpp
+++ b/tools/editor/plugins/editor_preview_plugins.cpp
@@ -6,16 +6,30 @@
#include "scene/resources/material.h"
#include "scene/resources/sample.h"
#include "scene/resources/mesh.h"
+#include "scene/resources/bit_mask.h"
bool EditorTexturePreviewPlugin::handles(const String& p_type) const {
- return ObjectTypeDB::is_type(p_type,"ImageTexture");
+ return (ObjectTypeDB::is_type(p_type,"ImageTexture") || ObjectTypeDB::is_type(p_type, "AtlasTexture"));
}
Ref<Texture> EditorTexturePreviewPlugin::generate(const RES& p_from) {
- Ref<ImageTexture> tex =p_from;
- Image img = tex->get_data();
+ Image img;
+ Ref<AtlasTexture> atex = p_from;
+ if (atex.is_valid()) {
+ Ref<ImageTexture> tex = atex->get_atlas();
+ if (!tex.is_valid()) {
+ return Ref<Texture>();
+ }
+ Image atlas = tex->get_data();
+ img = atlas.get_rect(atex->get_region());
+ }
+ else {
+ Ref<ImageTexture> tex = p_from;
+ img = tex->get_data();
+ }
+
if (img.empty())
return Ref<Texture>();
@@ -58,6 +72,81 @@ EditorTexturePreviewPlugin::EditorTexturePreviewPlugin() {
}
+////////////////////////////////////////////////////////////////////////////
+
+bool EditorBitmapPreviewPlugin::handles(const String& p_type) const {
+
+ return ObjectTypeDB::is_type(p_type,"BitMap");
+}
+
+Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES& p_from) {
+
+ Ref<BitMap> bm =p_from;
+
+ if (bm->get_size()==Size2()) {
+ return Ref<Texture>();
+ }
+
+ DVector<uint8_t> data;
+
+ data.resize(bm->get_size().width*bm->get_size().height);
+
+ {
+ DVector<uint8_t>::Write w=data.write();
+
+ for(int i=0;i<bm->get_size().width;i++) {
+ for(int j=0;j<bm->get_size().height;j++) {
+ if (bm->get_bit(Point2i(i,j))) {
+ w[j*bm->get_size().width+i]=255;
+ } else {
+ w[j*bm->get_size().width+i]=0;
+
+ }
+ }
+
+ }
+ }
+
+
+ Image img(bm->get_size().width,bm->get_size().height,0,Image::FORMAT_GRAYSCALE,data);
+
+ int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
+ if (img.is_compressed()) {
+ if (img.decompress()!=OK)
+ return Ref<Texture>();
+ } else if (img.get_format()!=Image::FORMAT_RGB && img.get_format()!=Image::FORMAT_RGBA) {
+ img.convert(Image::FORMAT_RGBA);
+ }
+
+ int width,height;
+ if (img.get_width() > thumbnail_size && img.get_width() >= img.get_height()) {
+
+ width=thumbnail_size;
+ height = img.get_height() * thumbnail_size / img.get_width();
+ } else if (img.get_height() > thumbnail_size && img.get_height() >= img.get_width()) {
+
+ height=thumbnail_size;
+ width = img.get_width() * thumbnail_size / img.get_height();
+ } else {
+
+ width=img.get_width();
+ height=img.get_height();
+ }
+
+ img.resize(width,height);
+
+ Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
+
+ ptex->create_from_image(img,0);
+ return ptex;
+
+}
+
+EditorBitmapPreviewPlugin::EditorBitmapPreviewPlugin() {
+
+
+}
+
///////////////////////////////////////////////////////////////////////////
diff --git a/tools/editor/plugins/editor_preview_plugins.h b/tools/editor/plugins/editor_preview_plugins.h
index 98071e2a0e..b3bfda8045 100644
--- a/tools/editor/plugins/editor_preview_plugins.h
+++ b/tools/editor/plugins/editor_preview_plugins.h
@@ -13,6 +13,17 @@ public:
};
+class EditorBitmapPreviewPlugin : public EditorResourcePreviewGenerator {
+public:
+
+ virtual bool handles(const String& p_type) const;
+ virtual Ref<Texture> generate(const RES& p_from);
+
+ EditorBitmapPreviewPlugin();
+};
+
+
+
class EditorPackedScenePreviewPlugin : public EditorResourcePreviewGenerator {
Ref<Texture> _gen_from_imd(Ref<ResourceImportMetadata> p_imd);
diff --git a/tools/editor/plugins/item_list_editor_plugin.cpp b/tools/editor/plugins/item_list_editor_plugin.cpp
index fa261edea3..6f0db959ba 100644
--- a/tools/editor/plugins/item_list_editor_plugin.cpp
+++ b/tools/editor/plugins/item_list_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,7 +30,6 @@
#include "io/resource_loader.h"
-
bool ItemListPlugin::_set(const StringName& p_name, const Variant& p_value) {
String name = p_name;
@@ -45,12 +44,10 @@ bool ItemListPlugin::_set(const StringName& p_name, const Variant& p_value) {
set_item_checkable(idx,p_value);
else if (what=="checked")
set_item_checked(idx,p_value);
- else if (what=="enabled")
- set_item_enabled(idx,p_value);
- else if (what=="accel")
- set_item_accel(idx,p_value);
else if (what=="id")
set_item_id(idx,p_value);
+ else if (what=="enabled")
+ set_item_enabled(idx,p_value);
else if (what=="separator")
set_item_separator(idx,p_value);
else
@@ -60,6 +57,7 @@ bool ItemListPlugin::_set(const StringName& p_name, const Variant& p_value) {
}
bool ItemListPlugin::_get(const StringName& p_name,Variant &r_ret) const {
+
String name = p_name;
int idx = name.get_slice("/",0).to_int();
String what=name.get_slice("/",1);
@@ -72,12 +70,10 @@ bool ItemListPlugin::_get(const StringName& p_name,Variant &r_ret) const {
r_ret=is_item_checkable(idx);
else if (what=="checked")
r_ret=is_item_checked(idx);
- else if (what=="enabled")
- r_ret=is_item_enabled(idx);
- else if (what=="accel")
- r_ret=get_item_accel(idx);
else if (what=="id")
r_ret=get_item_id(idx);
+ else if (what=="enabled")
+ r_ret=is_item_enabled(idx);
else if (what=="separator")
r_ret=is_item_separator(idx);
else
@@ -93,66 +89,119 @@ void ItemListPlugin::_get_property_list( List<PropertyInfo> *p_list) const {
p_list->push_back( PropertyInfo(Variant::STRING,base+"text") );
p_list->push_back( PropertyInfo(Variant::OBJECT,base+"icon",PROPERTY_HINT_RESOURCE_TYPE,"Texture") );
- if (get_flags()&FLAG_CHECKABLE) {
+ int flags = get_flags();
+
+ if (flags&FLAG_CHECKABLE) {
p_list->push_back( PropertyInfo(Variant::BOOL,base+"checkable") );
p_list->push_back( PropertyInfo(Variant::BOOL,base+"checked") );
-
}
- if (get_flags()&FLAG_ENABLE) {
+ if (flags&FLAG_ID)
+ p_list->push_back( PropertyInfo(Variant::INT,base+"id",PROPERTY_HINT_RANGE,"-1,4096") );
+
+ if (flags&FLAG_ENABLE)
p_list->push_back( PropertyInfo(Variant::BOOL,base+"enabled") );
- }
- if (get_flags()&FLAG_ACCEL) {
+ if (flags&FLAG_SEPARATOR)
+ p_list->push_back( PropertyInfo(Variant::BOOL,base+"separator") );
+ }
+}
- p_list->push_back( PropertyInfo(Variant::INT,base+"accel",PROPERTY_HINT_KEY_ACCEL) );
+///////////////////////////////////////////////////////////////
+///////////////////////// PLUGINS /////////////////////////////
+///////////////////////////////////////////////////////////////
- }
- if (get_flags()&FLAG_ID) {
+void ItemListOptionButtonPlugin::set_object(Object *p_object) {
- p_list->push_back( PropertyInfo(Variant::INT,base+"id",PROPERTY_HINT_RANGE,"-1,4096") );
+ ob = p_object->cast_to<OptionButton>();
+}
- }
- if (get_flags()&FLAG_SEPARATOR) {
+bool ItemListOptionButtonPlugin::handles(Object *p_object) const {
- p_list->push_back( PropertyInfo(Variant::BOOL,base+"separator") );
+ return p_object->is_type("OptionButton");
+}
- }
- }
+int ItemListOptionButtonPlugin::get_flags() const {
+
+ return FLAG_ICON|FLAG_ID|FLAG_ENABLE;
}
-void ItemListEditor::_node_removed(Node *p_node) {
+void ItemListOptionButtonPlugin::add_item() {
- if(p_node==item_list) {
- item_list=NULL;
- hide();
- dialog->hide();
- }
+ ob->add_item( "Item "+itos(ob->get_item_count()));
+ _change_notify();
+}
+int ItemListOptionButtonPlugin::get_item_count() const {
+ return ob->get_item_count();
}
-void ItemListEditor::_delete_pressed() {
+void ItemListOptionButtonPlugin::erase(int p_idx) {
- String p = prop_editor->get_selected_path();
+ ob->remove_item(p_idx);
+ _change_notify();
+}
- if (p.find("/")!=-1) {
+ItemListOptionButtonPlugin::ItemListOptionButtonPlugin() {
- if (selected_idx<0 || selected_idx>=item_plugins.size())
- return;
+ ob=NULL;
+}
- item_plugins[selected_idx]->erase(p.get_slice("/",0).to_int());;
- }
+///////////////////////////////////////////////////////////////
+
+void ItemListPopupMenuPlugin::set_object(Object *p_object) {
+ if (p_object->is_type("MenuButton"))
+ pp = p_object->cast_to<MenuButton>()->get_popup();
+ else
+ pp = p_object->cast_to<PopupMenu>();
}
-void ItemListEditor::_add_pressed() {
+bool ItemListPopupMenuPlugin::handles(Object *p_object) const {
- if (selected_idx<0 || selected_idx>=item_plugins.size())
- return;
+ return p_object->is_type("PopupMenu") || p_object->is_type("MenuButton");
+}
- item_plugins[selected_idx]->add_item();
+int ItemListPopupMenuPlugin::get_flags() const {
+
+ return FLAG_ICON|FLAG_CHECKABLE|FLAG_ID|FLAG_ENABLE|FLAG_SEPARATOR;
+}
+
+void ItemListPopupMenuPlugin::add_item() {
+
+ pp->add_item( "Item "+itos(pp->get_item_count()));
+ _change_notify();
+}
+
+int ItemListPopupMenuPlugin::get_item_count() const {
+
+ return pp->get_item_count();
+}
+
+void ItemListPopupMenuPlugin::erase(int p_idx) {
+
+ pp->remove_item(p_idx);
+ _change_notify();
+}
+
+ItemListPopupMenuPlugin::ItemListPopupMenuPlugin() {
+
+ pp=NULL;
+}
+
+///////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////
+
+void ItemListEditor::_node_removed(Node *p_node) {
+
+ if(p_node==item_list) {
+ item_list=NULL;
+ hide();
+ dialog->hide();
+ }
}
void ItemListEditor::_notification(int p_notification) {
@@ -160,57 +209,73 @@ void ItemListEditor::_notification(int p_notification) {
if (p_notification==NOTIFICATION_ENTER_TREE) {
add_button->set_icon(get_icon("Add","EditorIcons"));
- del_button->set_icon(get_icon("Del","EditorIcons"));
+ del_button->set_icon(get_icon("Remove","EditorIcons"));
}
}
+void ItemListEditor::_add_pressed() {
-void ItemListEditor::_menu_option(int p_option) {
+ if (selected_idx==-1)
+ return;
+ item_plugins[selected_idx]->add_item();
+}
- switch(p_option) {
+void ItemListEditor::_delete_pressed() {
- case MENU_EDIT_ITEMS: {
+ TreeItem *ti = tree->get_selected();
- dialog->popup_centered_ratio();
- } break;
- }
+ if (!ti)
+ return;
+
+ if (ti->get_parent()!=tree->get_root())
+ return;
+
+ int idx = ti->get_text(0).to_int();
+
+ if (selected_idx==-1)
+ return;
+
+ item_plugins[selected_idx]->erase(idx);
}
+void ItemListEditor::_edit_items() {
+
+ dialog->popup_centered(Vector2(300, 400));
+}
void ItemListEditor::edit(Node *p_item_list) {
item_list=p_item_list;
+ if (!item_list) {
+ selected_idx=-1;
+ property_editor->edit(NULL);
+ return;
+ }
+
for(int i=0;i<item_plugins.size();i++) {
if (item_plugins[i]->handles(p_item_list)) {
item_plugins[i]->set_object(p_item_list);
- prop_editor->edit(item_plugins[i]);
+ property_editor->edit(item_plugins[i]);
+
+ if (has_icon(item_list->get_type(), "EditorIcons"))
+ toolbar_button->set_icon(get_icon(item_list->get_type(), "EditorIcons"));
+ else
+ toolbar_button->set_icon(Ref<Texture>());
+
selected_idx=i;
return;
}
}
selected_idx=-1;
-
- prop_editor->edit(NULL);
-
-}
-
-
-void ItemListEditor::_bind_methods() {
-
- ObjectTypeDB::bind_method("_menu_option",&ItemListEditor::_menu_option);
- ObjectTypeDB::bind_method("_add_button",&ItemListEditor::_add_pressed);
- ObjectTypeDB::bind_method("_delete_button",&ItemListEditor::_delete_pressed);
-
- //ObjectTypeDB::bind_method("_populate",&ItemListEditor::_populate);
-
+ property_editor->edit(NULL);
}
bool ItemListEditor::handles(Object *p_object) const {
- return false;
+
for(int i=0;i<item_plugins.size();i++) {
if (item_plugins[i]->handles(p_object)) {
return true;
@@ -218,57 +283,65 @@ bool ItemListEditor::handles(Object *p_object) const {
}
return false;
+}
+void ItemListEditor::_bind_methods() {
+
+ ObjectTypeDB::bind_method("_edit_items",&ItemListEditor::_edit_items);
+ ObjectTypeDB::bind_method("_add_button",&ItemListEditor::_add_pressed);
+ ObjectTypeDB::bind_method("_delete_button",&ItemListEditor::_delete_pressed);
}
+
ItemListEditor::ItemListEditor() {
selected_idx=-1;
- options = memnew( MenuButton );
- add_child(options);
- options->set_area_as_parent_rect();
- options->set_text("Items");
- options->get_popup()->add_item("Edit Items",MENU_EDIT_ITEMS);
- //options->get_popup()->add_item("Clear",MENU_CLEAR);
+ add_child( memnew( VSeparator ) );
- options->get_popup()->connect("item_pressed", this,"_menu_option");
+ toolbar_button = memnew( ToolButton );
+ toolbar_button->set_text("Items");
+ add_child(toolbar_button);
+ toolbar_button->connect("pressed",this,"_edit_items");
dialog = memnew( AcceptDialog );
+ dialog->set_title("Item List Editor");
add_child( dialog );
-
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ dialog->add_child(vbc);
+ dialog->set_child_rect(vbc);
HBoxContainer *hbc = memnew( HBoxContainer );
-
- dialog->add_child(hbc);
- dialog->set_child_rect(hbc);
-
- prop_editor = memnew( PropertyEditor );
-
- hbc->add_child(prop_editor);
- prop_editor->set_h_size_flags(SIZE_EXPAND_FILL);
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- hbc->add_child(vbc);
+ hbc->set_h_size_flags(SIZE_EXPAND_FILL);
+ vbc->add_child(hbc);
add_button = memnew( Button );
- //add_button->set_text("Add");
+ add_button->set_text("Add");
+ hbc->add_child(add_button);
add_button->connect("pressed",this,"_add_button");
- vbc->add_child(add_button);
+
+ hbc->add_spacer();
del_button = memnew( Button );
- //del_button->set_text("Del");
+ del_button->set_text("Delete");
+ hbc->add_child(del_button);
del_button->connect("pressed",this,"_delete_button");
- vbc->add_child(del_button);
- dialog->set_title("Item List");
- prop_editor->hide_top_label();
+ property_editor = memnew( PropertyEditor );
+ property_editor->hide_top_label();
+ property_editor->set_subsection_selectable(true);
+ vbc->add_child(property_editor);
+ property_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+ tree = property_editor->get_scene_tree();
+}
+ItemListEditor::~ItemListEditor() {
+ for(int i=0;i<item_plugins.size();i++)
+ memdelete( item_plugins[i] );
}
-
void ItemListEditorPlugin::edit(Object *p_object) {
item_list_editor->edit(p_object->cast_to<Node>());
@@ -288,127 +361,19 @@ void ItemListEditorPlugin::make_visible(bool p_visible) {
item_list_editor->hide();
item_list_editor->edit(NULL);
}
-
-}
-
-
-ItemListEditor::~ItemListEditor() {
-
- for(int i=0;i<item_plugins.size();i++)
- memdelete( item_plugins[i] );
}
-///////////////////////// PLUGINS /////////////////////////////
-///////////////////////// PLUGINS /////////////////////////////
-///////////////////////// PLUGINS /////////////////////////////
-///////////////////////// PLUGINS /////////////////////////////
-///////////////////////// PLUGINS /////////////////////////////
-
-
-class ItemListOptionButtonPlugin : public ItemListPlugin {
-
- OBJ_TYPE(ItemListOptionButtonPlugin,ItemListPlugin);
-
- OptionButton *ob;
-public:
-
- virtual void set_object(Object *p_object) { ob = p_object->cast_to<OptionButton>(); }
-
- virtual bool handles(Object *p_object) const { return p_object->cast_to<OptionButton>()!=NULL; }
-
- virtual int get_flags() const { return FLAG_ICON|FLAG_ID|FLAG_ENABLE; }
-
- virtual void set_item_text(int p_idx,const String& p_text){ ob->set_item_text(p_idx,p_text);}
- virtual void set_item_icon(int p_idx,const Ref<Texture>& p_tex){ ob->set_item_icon(p_idx,p_tex);}
- virtual void set_item_enabled(int p_idx,int p_enabled){ ob->set_item_disabled(p_idx,!p_enabled);}
- virtual void set_item_id(int p_idx,int p_id){ ob->set_item_ID(p_idx,p_id);}
-
-
- virtual String get_item_text(int p_idx) const{ return ob->get_item_text(p_idx); };
- virtual Ref<Texture> get_item_icon(int p_idx) const{ return ob->get_item_icon(p_idx); };
- virtual bool is_item_enabled(int p_idx) const{ return !ob->is_item_disabled(p_idx); };
- virtual int get_item_id(int p_idx) const{ return ob->get_item_ID(p_idx); };
-
- virtual void add_item() { ob->add_item( "New Item "+itos(ob->get_item_count())); _change_notify();}
- virtual int get_item_count() const { return ob->get_item_count(); }
- virtual void erase(int p_idx) { ob->remove_item(p_idx); _change_notify();}
-
-
- ItemListOptionButtonPlugin() { ob=NULL; }
-};
-
-class ItemListPopupMenuPlugin : public ItemListPlugin {
-
- OBJ_TYPE(ItemListPopupMenuPlugin,ItemListPlugin);
-
- PopupMenu *pp;
-public:
-
- virtual void set_object(Object *p_object) {
- if (p_object->cast_to<MenuButton>())
- pp = p_object->cast_to<MenuButton>()->get_popup();
- else
- pp = p_object->cast_to<PopupMenu>();
- }
-
- virtual bool handles(Object *p_object) const { return p_object->cast_to<PopupMenu>()!=NULL || p_object->cast_to<MenuButton>()!=NULL; }
-
- virtual int get_flags() const { return FLAG_ICON|FLAG_ID|FLAG_ENABLE|FLAG_CHECKABLE|FLAG_SEPARATOR|FLAG_ACCEL; }
-
- virtual void set_item_text(int p_idx,const String& p_text){ pp->set_item_text(p_idx,p_text); }
- virtual void set_item_icon(int p_idx,const Ref<Texture>& p_tex){ pp->set_item_icon(p_idx,p_tex);}
- virtual void set_item_checkable(int p_idx,bool p_check){ pp->set_item_as_checkable(p_idx,p_check);}
- virtual void set_item_checked(int p_idx,bool p_checked){ pp->set_item_checked(p_idx,p_checked);}
- virtual void set_item_accel(int p_idx,int p_accel){ pp->set_item_accelerator(p_idx,p_accel);}
- virtual void set_item_enabled(int p_idx,int p_enabled){ pp->set_item_disabled(p_idx,!p_enabled);}
- virtual void set_item_id(int p_idx,int p_id){ pp->set_item_ID(p_idx,p_idx);}
- virtual void set_item_separator(int p_idx,bool p_separator){ pp->set_item_as_separator(p_idx,p_separator);}
-
-
- virtual String get_item_text(int p_idx) const{ return pp->get_item_text(p_idx); };
- virtual Ref<Texture> get_item_icon(int p_idx) const{ return pp->get_item_icon(p_idx); };
- virtual bool is_item_checkable(int p_idx) const{ return pp->is_item_checkable(p_idx); };
- virtual bool is_item_checked(int p_idx) const{ return pp->is_item_checked(p_idx); };
- virtual int get_item_accel(int p_idx) const{ return pp->get_item_accelerator(p_idx); };
- virtual bool is_item_enabled(int p_idx) const{ return !pp->is_item_disabled(p_idx); };
- virtual int get_item_id(int p_idx) const{ return pp->get_item_ID(p_idx); };
- virtual bool is_item_separator(int p_idx) const{ return pp->is_item_separator(p_idx); };
-
-
-
- virtual void add_item() { pp->add_item( "New Item "+itos(pp->get_item_count())); _change_notify();}
- virtual int get_item_count() const { return pp->get_item_count(); }
- virtual void erase(int p_idx) { pp->remove_item(p_idx); _change_notify();}
-
-
- ItemListPopupMenuPlugin() { pp=NULL; }
-};
-
-
-
-
-
-
ItemListEditorPlugin::ItemListEditorPlugin(EditorNode *p_node) {
editor=p_node;
item_list_editor = memnew( ItemListEditor );
- editor->get_viewport()->add_child(item_list_editor);
-
-// item_list_editor->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
-// item_list_editor->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
- item_list_editor->set_margin(MARGIN_LEFT,180);
- item_list_editor->set_margin(MARGIN_RIGHT,230);
- item_list_editor->set_margin(MARGIN_TOP,0);
- item_list_editor->set_margin(MARGIN_BOTTOM,10);
-
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(item_list_editor);
item_list_editor->hide();
- item_list_editor->add_plugin( memnew( ItemListOptionButtonPlugin) );
- item_list_editor->add_plugin( memnew( ItemListPopupMenuPlugin) );
+ item_list_editor->add_plugin( memnew( ItemListOptionButtonPlugin ) );
+ item_list_editor->add_plugin( memnew( ItemListPopupMenuPlugin ) );
}
-
ItemListEditorPlugin::~ItemListEditorPlugin()
{
}
diff --git a/tools/editor/plugins/item_list_editor_plugin.h b/tools/editor/plugins/item_list_editor_plugin.h
index 351dbb800d..95d316b199 100644
--- a/tools/editor/plugins/item_list_editor_plugin.h
+++ b/tools/editor/plugins/item_list_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,10 +31,11 @@
#include "tools/editor/editor_plugin.h"
#include "tools/editor/editor_node.h"
+#include "canvas_item_editor_plugin.h"
+
#include "scene/gui/option_button.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/popup_menu.h"
-#include "scene/gui/spin_box.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
@@ -51,43 +52,42 @@ protected:
bool _get(const StringName& p_name,Variant &r_ret) const;
void _get_property_list( List<PropertyInfo> *p_list) const;
-
public:
enum Flags {
FLAG_ICON=1,
FLAG_CHECKABLE=2,
- FLAG_ACCEL=4,
- FLAG_ID=8,
- FLAG_ENABLE=16,
- FLAG_SEPARATOR=32
+ FLAG_ID=4,
+ FLAG_ENABLE=8,
+ FLAG_SEPARATOR=16
};
virtual void set_object(Object *p_object)=0;
-
virtual bool handles(Object *p_object) const=0;
virtual int get_flags() const=0;
- virtual void set_item_text(int p_idx,const String& p_text){}
- virtual void set_item_icon(int p_idx,const Ref<Texture>& p_tex){}
- virtual void set_item_checkable(int p_idx,bool p_check){}
- virtual void set_item_checked(int p_idx,bool p_checked){}
- virtual void set_item_accel(int p_idx,int p_accel){}
- virtual void set_item_enabled(int p_idx,int p_enabled){}
- virtual void set_item_id(int p_idx,int p_id){}
- virtual void set_item_separator(int p_idx,bool p_separator){}
-
-
+ virtual void set_item_text(int p_idx, const String& p_text) {}
virtual String get_item_text(int p_idx) const{ return ""; };
+
+ virtual void set_item_icon(int p_idx, const Ref<Texture>& p_tex) {}
virtual Ref<Texture> get_item_icon(int p_idx) const{ return Ref<Texture>(); };
+
+ virtual void set_item_checkable(int p_idx, bool p_check) {}
virtual bool is_item_checkable(int p_idx) const{ return false; };
+
+ virtual void set_item_checked(int p_idx, bool p_checked) {}
virtual bool is_item_checked(int p_idx) const{ return false; };
- virtual int get_item_accel(int p_idx) const{ return 0; };
+
+ virtual void set_item_enabled(int p_idx, int p_enabled) {}
virtual bool is_item_enabled(int p_idx) const{ return false; };
+
+ virtual void set_item_id(int p_idx, int p_id) {}
virtual int get_item_id(int p_idx) const{ return -1; };
- virtual bool is_item_separator(int p_idx) const{ return false; };
+
+ virtual void set_item_separator(int p_idx, bool p_separator) {}
+ virtual bool is_item_separator(int p_idx) const { return false; };
virtual void add_item()=0;
virtual int get_item_count() const=0;
@@ -96,41 +96,107 @@ public:
ItemListPlugin() {}
};
-class ItemListEditor : public Control {
+///////////////////////////////////////////////////////////////
- OBJ_TYPE(ItemListEditor, Control );
+class ItemListOptionButtonPlugin : public ItemListPlugin {
- Node *item_list;
+ OBJ_TYPE(ItemListOptionButtonPlugin,ItemListPlugin);
- enum {
+ OptionButton *ob;
+public:
- MENU_EDIT_ITEMS,
- MENU_CLEAR
- };
+ virtual void set_object(Object *p_object);
+ virtual bool handles(Object *p_object) const;
+ virtual int get_flags() const;
- AcceptDialog *dialog;
+ virtual void set_item_text(int p_idx, const String& p_text) { ob->set_item_text(p_idx,p_text); }
+ virtual String get_item_text(int p_idx) const { return ob->get_item_text(p_idx); }
- PropertyEditor *prop_editor;
+ virtual void set_item_icon(int p_idx, const Ref<Texture>& p_tex) { ob->set_item_icon(p_idx, p_tex); }
+ virtual Ref<Texture> get_item_icon(int p_idx) const { return ob->get_item_icon(p_idx); }
- MenuButton * options;
- int selected_idx;
+ virtual void set_item_enabled(int p_idx, int p_enabled) { ob->set_item_disabled(p_idx, !p_enabled); }
+ virtual bool is_item_enabled(int p_idx) const { return !ob->is_item_disabled(p_idx); }
+
+ virtual void set_item_id(int p_idx, int p_id) { ob->set_item_ID(p_idx,p_id); }
+ virtual int get_item_id(int p_idx) const { return ob->get_item_ID(p_idx); }
+
+ virtual void add_item();
+ virtual int get_item_count() const;
+ virtual void erase(int p_idx);
+
+ ItemListOptionButtonPlugin();
+};
+
+class ItemListPopupMenuPlugin : public ItemListPlugin {
+
+ OBJ_TYPE(ItemListPopupMenuPlugin,ItemListPlugin);
+
+ PopupMenu *pp;
+public:
+
+ virtual void set_object(Object *p_object);
+ virtual bool handles(Object *p_object) const;
+ virtual int get_flags() const;
+ virtual void set_item_text(int p_idx, const String& p_text) { pp->set_item_text(p_idx,p_text); }
+ virtual String get_item_text(int p_idx) const { return pp->get_item_text(p_idx); }
+
+ virtual void set_item_icon(int p_idx, const Ref<Texture>& p_tex) { pp->set_item_icon(p_idx,p_tex); }
+ virtual Ref<Texture> get_item_icon(int p_idx) const { return pp->get_item_icon(p_idx); }
+
+ virtual void set_item_checkable(int p_idx, bool p_check) { pp->set_item_as_checkable(p_idx,p_check); }
+ virtual bool is_item_checkable(int p_idx) const { return pp->is_item_checkable(p_idx); }
+
+ virtual void set_item_checked(int p_idx, bool p_checked) { pp->set_item_checked(p_idx,p_checked); }
+ virtual bool is_item_checked(int p_idx) const { return pp->is_item_checked(p_idx); }
+
+ virtual void set_item_enabled(int p_idx, int p_enabled) { pp->set_item_disabled(p_idx,!p_enabled); }
+ virtual bool is_item_enabled(int p_idx) const { return !pp->is_item_disabled(p_idx); }
+
+ virtual void set_item_id(int p_idx, int p_id) { pp->set_item_ID(p_idx,p_idx); }
+ virtual int get_item_id(int p_idx) const { return pp->get_item_ID(p_idx); }
+
+ virtual void set_item_separator(int p_idx, bool p_separator) { pp->set_item_as_separator(p_idx,p_separator); }
+ virtual bool is_item_separator(int p_idx) const { return pp->is_item_separator(p_idx); }
+
+ virtual void add_item();
+ virtual int get_item_count() const;
+ virtual void erase(int p_idx);
+
+ ItemListPopupMenuPlugin();
+};
+
+///////////////////////////////////////////////////////////////
+
+class ItemListEditor : public HBoxContainer {
+
+ OBJ_TYPE(ItemListEditor,HBoxContainer);
+
+ Node *item_list;
+
+ ToolButton *toolbar_button;
+
+ AcceptDialog *dialog;
+ PropertyEditor *property_editor;
+ Tree *tree;
Button *add_button;
Button *del_button;
-
-// FileDialog *emission_file_dialog;
- void _menu_option(int);
+ int selected_idx;
Vector<ItemListPlugin*> item_plugins;
- void _node_removed(Node *p_node);
+ void _edit_items();
+
void _add_pressed();
void _delete_pressed();
+
+ void _node_removed(Node *p_node);
+
protected:
void _notification(int p_notification);
-
static void _bind_methods();
public:
@@ -143,7 +209,7 @@ public:
class ItemListEditorPlugin : public EditorPlugin {
- OBJ_TYPE( ItemListEditorPlugin, EditorPlugin );
+ OBJ_TYPE(ItemListEditorPlugin,EditorPlugin);
ItemListEditor *item_list_editor;
EditorNode *editor;
diff --git a/tools/editor/plugins/mesh_editor_plugin.cpp b/tools/editor/plugins/mesh_editor_plugin.cpp
index cea774f94b..5314529a23 100644
--- a/tools/editor/plugins/mesh_editor_plugin.cpp
+++ b/tools/editor/plugins/mesh_editor_plugin.cpp
@@ -1,13 +1,8 @@
#include "mesh_editor_plugin.h"
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/3d/mesh_instance.h"
#include "scene/3d/physics_body.h"
#include "scene/3d/body_shape.h"
-#include "scene/gui/spin_box.h"
#include "scene/gui/box_container.h"
-#include "scene/3d/mesh_instance.h"
#include "scene/3d/navigation_mesh.h"
#include "spatial_editor_plugin.h"
@@ -38,92 +33,106 @@ void MeshInstanceEditor::_menu_option(int p_option) {
}
switch(p_option) {
- case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY: {
+ case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY:
+ case MENU_OPTION_CREATE_STATIC_CONVEX_BODY: {
- Ref<Shape> shape = mesh->create_trimesh_shape();
- if (shape.is_null())
- return;
- StaticBody *body = memnew( StaticBody );
- CollisionShape *cshape = memnew( CollisionShape );
- cshape->set_shape(shape);
- body->add_child(cshape);
- Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner();
+ bool trimesh_shape = (p_option==MENU_OPTION_CREATE_STATIC_TRIMESH_BODY);
+ EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection();
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Create Static Trimesh");
- ur->add_do_method(node,"add_child",body);
- ur->add_do_method(body,"set_owner",owner);
- ur->add_do_method(cshape,"set_owner",owner);
- ur->add_do_reference(body);
- ur->add_undo_method(node,"remove_child",body);
- ur->commit_action();
- } break;
- case MENU_OPTION_CREATE_STATIC_CONVEX_BODY: {
+ List<Node*> selection = editor_selection->get_selected_node_list();
- Ref<Shape> shape = mesh->create_convex_shape();
- if (shape.is_null())
- return;
- StaticBody *body = memnew( StaticBody );
- CollisionShape *cshape = memnew( CollisionShape );
- cshape->set_shape(shape);
- body->add_child(cshape);
- Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner();
+ if (selection.empty()) {
+ Ref<Shape> shape = trimesh_shape ? mesh->create_trimesh_shape() : mesh->create_convex_shape();
+ if (shape.is_null())
+ return;
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Create Static Trimesh");
- ur->add_do_method(node,"add_child",body);
- ur->add_do_method(body,"set_owner",owner);
- ur->add_do_method(cshape,"set_owner",owner);
- ur->add_do_reference(body);
- ur->add_undo_method(node,"remove_child",body);
- ur->commit_action();
+ CollisionShape *cshape = memnew( CollisionShape );
+ cshape->set_shape(shape);
+ StaticBody *body = memnew( StaticBody );
+ body->add_child(cshape);
- } break;
- case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE: {
+ Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner();
+ if (trimesh_shape)
+ ur->create_action("Create Static Trimesh Body");
+ else
+ ur->create_action("Create Static Convex Body");
- if (node==get_tree()->get_edited_scene_root()) {
- err_dialog->set_text("This doesn't work on scene root!");
- err_dialog->popup_centered_minsize();
+ ur->add_do_method(node,"add_child",body);
+ ur->add_do_method(body,"set_owner",owner);
+ ur->add_do_method(cshape,"set_owner",owner);
+ ur->add_do_reference(body);
+ ur->add_undo_method(node,"remove_child",body);
+ ur->commit_action();
return;
}
- Ref<Shape> shape = mesh->create_trimesh_shape();
- if (shape.is_null())
- return;
- CollisionShape *cshape = memnew( CollisionShape );
- cshape->set_shape(shape);
- Node *owner = node->get_owner();
+ if (trimesh_shape)
+ ur->create_action("Create Static Trimesh Body");
+ else
+ ur->create_action("Create Static Convex Body");
+
+ for (List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ MeshInstance *instance = E->get()->cast_to<MeshInstance>();
+ if (!instance)
+ continue;
+
+ Ref<Mesh> m = instance->get_mesh();
+ if (m.is_null())
+ continue;
+
+ Ref<Shape> shape = trimesh_shape ? m->create_trimesh_shape() : m->create_convex_shape();
+ if (shape.is_null())
+ continue;
+
+ CollisionShape *cshape = memnew( CollisionShape );
+ cshape->set_shape(shape);
+ StaticBody *body = memnew( StaticBody );
+ body->add_child(cshape);
+
+ Node *owner = instance==get_tree()->get_edited_scene_root() ? instance : instance->get_owner();
+
+ ur->add_do_method(instance,"add_child",body);
+ ur->add_do_method(body,"set_owner",owner);
+ ur->add_do_method(cshape,"set_owner",owner);
+ ur->add_do_reference(body);
+ ur->add_undo_method(instance,"remove_child",body);
+ }
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Create Static Trimesh");
- ur->add_do_method(node->get_parent(),"add_child",cshape);
- ur->add_do_method(node->get_parent(),"move_child",cshape,node->get_index()+1);
- ur->add_do_method(cshape,"set_owner",owner);
- ur->add_do_reference(cshape);
- ur->add_undo_method(node->get_parent(),"remove_child",cshape);
ur->commit_action();
} break;
- case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: {
+ case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE:
+ case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: {
if (node==get_tree()->get_edited_scene_root()) {
err_dialog->set_text("This doesn't work on scene root!");
err_dialog->popup_centered_minsize();
return;
}
- Ref<Shape> shape = mesh->create_convex_shape();
+
+ bool trimesh_shape = (p_option==MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE);
+
+ Ref<Shape> shape = trimesh_shape ? mesh->create_trimesh_shape() : mesh->create_convex_shape();
if (shape.is_null())
return;
+
CollisionShape *cshape = memnew( CollisionShape );
cshape->set_shape(shape);
Node *owner = node->get_owner();
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Create Static Trimesh");
+
+ if (trimesh_shape)
+ ur->create_action("Create Trimesh Shape");
+ else
+ ur->create_action("Create Convex Shape");
+
ur->add_do_method(node->get_parent(),"add_child",cshape);
ur->add_do_method(node->get_parent(),"move_child",cshape,node->get_index()+1);
ur->add_do_method(cshape,"set_owner",owner);
@@ -132,10 +141,8 @@ void MeshInstanceEditor::_menu_option(int p_option) {
ur->commit_action();
} break;
- case MENU_OPTION_CREATE_NAVMESH: {
-
-
+ case MENU_OPTION_CREATE_NAVMESH: {
Ref<NavigationMesh> nmesh = memnew( NavigationMesh );
@@ -158,6 +165,7 @@ void MeshInstanceEditor::_menu_option(int p_option) {
ur->add_undo_method(node,"remove_child",nmi);
ur->commit_action();
} break;
+
case MENU_OPTION_CREATE_OUTLINE_MESH: {
outline_dialog->popup_centered(Vector2(200, 90));
diff --git a/tools/editor/plugins/mesh_editor_plugin.h b/tools/editor/plugins/mesh_editor_plugin.h
index e502b5dc2b..6b3e23f31f 100644
--- a/tools/editor/plugins/mesh_editor_plugin.h
+++ b/tools/editor/plugins/mesh_editor_plugin.h
@@ -23,24 +23,19 @@ class MeshInstanceEditor : public Node {
MENU_OPTION_CREATE_OUTLINE_MESH,
};
+ MeshInstance *node;
+
+ MenuButton *options;
+
ConfirmationDialog *outline_dialog;
SpinBox *outline_size;
AcceptDialog *err_dialog;
-
- Panel *panel;
- MeshInstance *node;
-
- LineEdit *surface_source;
- LineEdit *mesh_source;
-
-
void _menu_option(int p_option);
void _create_outline_mesh();
friend class MeshInstanceEditorPlugin;
- MenuButton * options;
protected:
void _node_removed(Node *p_node);
diff --git a/tools/editor/plugins/multimesh_editor_plugin.cpp b/tools/editor/plugins/multimesh_editor_plugin.cpp
index a5c823f8bd..3f63ef706b 100644
--- a/tools/editor/plugins/multimesh_editor_plugin.cpp
+++ b/tools/editor/plugins/multimesh_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/multimesh_editor_plugin.h b/tools/editor/plugins/multimesh_editor_plugin.h
index edc3dfd55f..245da1eeb7 100644
--- a/tools/editor/plugins/multimesh_editor_plugin.h
+++ b/tools/editor/plugins/multimesh_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/particles_2d_editor_plugin.cpp b/tools/editor/plugins/particles_2d_editor_plugin.cpp
index dadfa8bfdc..2488c4cdd9 100644
--- a/tools/editor/plugins/particles_2d_editor_plugin.cpp
+++ b/tools/editor/plugins/particles_2d_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/particles_2d_editor_plugin.h b/tools/editor/plugins/particles_2d_editor_plugin.h
index dba0bb4dae..f70a0e7b76 100644
--- a/tools/editor/plugins/particles_2d_editor_plugin.h
+++ b/tools/editor/plugins/particles_2d_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/particles_editor_plugin.cpp b/tools/editor/plugins/particles_editor_plugin.cpp
index 5c84d9a86a..2df6d3ea90 100644
--- a/tools/editor/plugins/particles_editor_plugin.cpp
+++ b/tools/editor/plugins/particles_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/particles_editor_plugin.h b/tools/editor/plugins/particles_editor_plugin.h
index 92756af1f6..ff80bffc29 100644
--- a/tools/editor/plugins/particles_editor_plugin.h
+++ b/tools/editor/plugins/particles_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/path_2d_editor_plugin.cpp b/tools/editor/plugins/path_2d_editor_plugin.cpp
index d037adc555..509edbe5f8 100644
--- a/tools/editor/plugins/path_2d_editor_plugin.cpp
+++ b/tools/editor/plugins/path_2d_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -534,6 +534,7 @@ void Path2DEditor::edit(Node *p_path2d) {
if (!node->is_connected("visibility_changed", this, "_node_visibility_changed"))
node->connect("visibility_changed", this, "_node_visibility_changed");
+
} else {
if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
@@ -614,6 +615,7 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) {
editor=p_editor;
undo_redo = editor->get_undo_redo();
+ mode=MODE_EDIT;
action=ACTION_NONE;
#if 0
diff --git a/tools/editor/plugins/path_2d_editor_plugin.h b/tools/editor/plugins/path_2d_editor_plugin.h
index 9f15c0669f..973c17464e 100644
--- a/tools/editor/plugins/path_2d_editor_plugin.h
+++ b/tools/editor/plugins/path_2d_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/path_editor_plugin.cpp b/tools/editor/plugins/path_editor_plugin.cpp
index f4bdf50fe9..b99e632604 100644
--- a/tools/editor/plugins/path_editor_plugin.cpp
+++ b/tools/editor/plugins/path_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/path_editor_plugin.h b/tools/editor/plugins/path_editor_plugin.h
index fcd4241e59..18bad23bd1 100644
--- a/tools/editor/plugins/path_editor_plugin.h
+++ b/tools/editor/plugins/path_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/polygon_2d_editor_plugin.cpp b/tools/editor/plugins/polygon_2d_editor_plugin.cpp
index cd82297365..3e9c58d604 100644
--- a/tools/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/tools/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -755,7 +755,6 @@ void Polygon2DEditor::edit(Node *p_collision_polygon) {
canvas_item_editor=CanvasItemEditor::get_singleton();
}
-
if (p_collision_polygon) {
node=p_collision_polygon->cast_to<Polygon2D>();
diff --git a/tools/editor/plugins/resource_preloader_editor_plugin.cpp b/tools/editor/plugins/resource_preloader_editor_plugin.cpp
index 9cd20ac53a..8490f63ff0 100644
--- a/tools/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/tools/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -356,11 +356,16 @@ bool ResourcePreloaderEditorPlugin::handles(Object *p_object) const {
void ResourcePreloaderEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
- preloader_editor->show();
+ //preloader_editor->show();
+ button->show();
+ editor->make_bottom_panel_item_visible(preloader_editor);
// preloader_editor->set_process(true);
} else {
- preloader_editor->hide();
+ if (preloader_editor->is_visible())
+ editor->hide_bottom_panel();
+ button->hide();
+ //preloader_editor->hide();
// preloader_editor->set_process(false);
}
@@ -370,11 +375,14 @@ ResourcePreloaderEditorPlugin::ResourcePreloaderEditorPlugin(EditorNode *p_node)
editor=p_node;
preloader_editor = memnew( ResourcePreloaderEditor );
- editor->get_viewport()->add_child(preloader_editor);
- preloader_editor->set_area_as_parent_rect();
+ preloader_editor->set_custom_minimum_size(Size2(0,250));
+
+ button=editor->add_bottom_panel_item("ResourcePreloader",preloader_editor);
+ button->hide();
+
// preloader_editor->set_anchor( MARGIN_TOP, Control::ANCHOR_END);
// preloader_editor->set_margin( MARGIN_TOP, 120 );
- preloader_editor->hide();
+
diff --git a/tools/editor/plugins/resource_preloader_editor_plugin.h b/tools/editor/plugins/resource_preloader_editor_plugin.h
index 88272bc603..53436797a9 100644
--- a/tools/editor/plugins/resource_preloader_editor_plugin.h
+++ b/tools/editor/plugins/resource_preloader_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -85,6 +85,7 @@ class ResourcePreloaderEditorPlugin : public EditorPlugin {
ResourcePreloaderEditor *preloader_editor;
EditorNode *editor;
+ Button *button;
public:
diff --git a/tools/editor/plugins/rich_text_editor_plugin.cpp b/tools/editor/plugins/rich_text_editor_plugin.cpp
index a0daad854f..08374d6624 100644
--- a/tools/editor/plugins/rich_text_editor_plugin.cpp
+++ b/tools/editor/plugins/rich_text_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/rich_text_editor_plugin.h b/tools/editor/plugins/rich_text_editor_plugin.h
index 478dc0d308..ae1d04be01 100644
--- a/tools/editor/plugins/rich_text_editor_plugin.h
+++ b/tools/editor/plugins/rich_text_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/sample_editor_plugin.cpp b/tools/editor/plugins/sample_editor_plugin.cpp
index d88f2adc73..ffa39bd010 100644
--- a/tools/editor/plugins/sample_editor_plugin.cpp
+++ b/tools/editor/plugins/sample_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/sample_editor_plugin.h b/tools/editor/plugins/sample_editor_plugin.h
index e615667914..22dc75b53b 100644
--- a/tools/editor/plugins/sample_editor_plugin.h
+++ b/tools/editor/plugins/sample_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/sample_library_editor_plugin.cpp b/tools/editor/plugins/sample_library_editor_plugin.cpp
index b497458a2a..a28fbb2ec8 100644
--- a/tools/editor/plugins/sample_library_editor_plugin.cpp
+++ b/tools/editor/plugins/sample_library_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -423,11 +423,16 @@ bool SampleLibraryEditorPlugin::handles(Object *p_object) const {
void SampleLibraryEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
- sample_library_editor->show();
+ //sample_library_editor->show();
+ button->show();
+ editor->make_bottom_panel_item_visible(sample_library_editor);
// sample_library_editor->set_process(true);
} else {
- sample_library_editor->hide();
+ if (sample_library_editor->is_visible())
+ editor->hide_bottom_panel();
+ button->hide();
+
// sample_library_editor->set_process(false);
}
@@ -437,11 +442,16 @@ SampleLibraryEditorPlugin::SampleLibraryEditorPlugin(EditorNode *p_node) {
editor=p_node;
sample_library_editor = memnew( SampleLibraryEditor );
- editor->get_viewport()->add_child(sample_library_editor);
- sample_library_editor->set_area_as_parent_rect();
+
+ //editor->get_viewport()->add_child(sample_library_editor);
+ sample_library_editor->set_custom_minimum_size(Size2(0,250));
+ button=p_node->add_bottom_panel_item("SampleLibrary",sample_library_editor);
+ button->hide();
+
+ //sample_library_editor->set_area_as_parent_rect();
// sample_library_editor->set_anchor( MARGIN_TOP, Control::ANCHOR_END);
// sample_library_editor->set_margin( MARGIN_TOP, 120 );
- sample_library_editor->hide();
+ //sample_library_editor->hide();
diff --git a/tools/editor/plugins/sample_library_editor_plugin.h b/tools/editor/plugins/sample_library_editor_plugin.h
index 2770ca2d9a..cbdcf5fc3f 100644
--- a/tools/editor/plugins/sample_library_editor_plugin.h
+++ b/tools/editor/plugins/sample_library_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -90,6 +90,7 @@ class SampleLibraryEditorPlugin : public EditorPlugin {
SampleLibraryEditor *sample_library_editor;
EditorNode *editor;
+ Button *button;
public:
diff --git a/tools/editor/plugins/sample_player_editor_plugin.cpp b/tools/editor/plugins/sample_player_editor_plugin.cpp
index f1c7ca8c98..3085ad87d8 100644
--- a/tools/editor/plugins/sample_player_editor_plugin.cpp
+++ b/tools/editor/plugins/sample_player_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/sample_player_editor_plugin.h b/tools/editor/plugins/sample_player_editor_plugin.h
index cdd1a99c17..013b042487 100644
--- a/tools/editor/plugins/sample_player_editor_plugin.h
+++ b/tools/editor/plugins/sample_player_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp
index e01cf72149..34d7e89760 100644
--- a/tools/editor/plugins/script_editor_plugin.cpp
+++ b/tools/editor/plugins/script_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -316,6 +316,8 @@ void ScriptTextEditor::_load_theme_settings() {
get_text_edit()->add_keyword_color("Color",basetype_color);
get_text_edit()->add_keyword_color("Image",basetype_color);
get_text_edit()->add_keyword_color("InputEvent",basetype_color);
+ get_text_edit()->add_keyword_color("Rect2",basetype_color);
+ get_text_edit()->add_keyword_color("NodePath",basetype_color);
//colorize engine types
Color type_color= EDITOR_DEF("text_editor/engine_type_color",Color(0.0,0.2,0.4));
@@ -325,7 +327,11 @@ void ScriptTextEditor::_load_theme_settings() {
for(List<StringName>::Element *E=types.front();E;E=E->next()) {
- get_text_edit()->add_keyword_color(E->get(),type_color);
+ String n = E->get();
+ if (n.begins_with("_"))
+ n = n.substr(1, n.length());
+
+ get_text_edit()->add_keyword_color(n,type_color);
}
//colorize comments
@@ -379,6 +385,8 @@ void ScriptTextEditor::reload_text() {
te->set_h_scroll(h);
te->set_v_scroll(v);
+ te->tag_saved_version();
+
_line_col_changed();
}
@@ -391,6 +399,12 @@ void ScriptTextEditor::_notification(int p_what) {
}
}
+
+bool ScriptTextEditor::is_unsaved() {
+
+ return get_text_edit()->get_version()!=get_text_edit()->get_saved_version();
+}
+
String ScriptTextEditor::get_name() {
String name;
@@ -492,6 +506,59 @@ static Node* _find_node_for_script(Node* p_base, Node*p_current, const Ref<Scrip
return NULL;
}
+static void _find_changed_scripts_for_external_editor(Node* p_base, Node*p_current, Set<Ref<Script> > &r_scripts) {
+
+ if (p_current->get_owner()!=p_base && p_base!=p_current)
+ return;
+ Ref<Script> c = p_current->get_script();
+
+ if (c.is_valid())
+ r_scripts.insert(c);
+
+ for(int i=0;i<p_current->get_child_count();i++) {
+ _find_changed_scripts_for_external_editor(p_base,p_current->get_child(i),r_scripts);
+ }
+
+}
+
+void ScriptEditor::_update_modified_scripts_for_external_editor() {
+
+ if (!bool(EditorSettings::get_singleton()->get("external_editor/use_external_editor")))
+ return;
+
+ Set<Ref<Script> > scripts;
+
+ Node *base = get_tree()->get_edited_scene_root();
+ if (base) {
+ _find_changed_scripts_for_external_editor(base,base,scripts);
+ }
+
+ for (Set<Ref<Script> >::Element *E=scripts.front();E;E=E->next()) {
+
+ Ref<Script> script = E->get();
+
+ if (script->get_path()=="" || script->get_path().find("local://")!=-1 || script->get_path().find("::")!=-1) {
+
+ continue; //internal script, who cares, though weird
+ }
+
+ uint64_t last_date = script->get_last_modified_time();
+ uint64_t date = FileAccess::get_modified_time(script->get_path());
+
+ if (last_date!=date) {
+
+ Ref<Script> rel_script = ResourceLoader::load(script->get_path(),script->get_type(),true);
+ ERR_CONTINUE(!rel_script.is_valid());
+ script->set_source_code( rel_script->get_source_code() );
+ script->set_last_modified_time( rel_script->get_last_modified_time() );
+ script->update_exports();
+ }
+
+ }
+}
+
+
+
void ScriptTextEditor::_code_complete_script(const String& p_code, List<String>* r_options) {
Node *base = get_tree()->get_edited_scene_root();
@@ -543,7 +610,6 @@ void ScriptEditor::_breaked(bool p_breaked,bool p_can_debug) {
void ScriptEditor::_show_debugger(bool p_show) {
debug_menu->get_popup()->set_item_checked( debug_menu->get_popup()->get_item_index(DEBUG_SHOW), p_show);
-
}
void ScriptEditor::_script_created(Ref<Script> p_script) {
@@ -749,6 +815,7 @@ void ScriptEditor::_reload_scripts(){
}
disk_changed->hide();
+ _update_script_names();
}
@@ -791,46 +858,53 @@ bool ScriptEditor::_test_script_times_on_disk() {
TreeItem *r = disk_changed_list->create_item();
disk_changed_list->set_hide_root(true);
- bool all_ok=true;
+ bool need_ask=false;
+ bool need_reload=false;
+ bool use_autoreload=bool(EDITOR_DEF("text_editor/auto_reload_scripts_on_external_change",false));
+
for(int i=0;i<tab_container->get_child_count();i++) {
ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>();
- if (!ste)
- continue;
+ if (ste) {
+ Ref<Script> script = ste->get_edited_script();
- Ref<Script> script = ste->get_edited_script();
+ if (script->get_path()=="" || script->get_path().find("local://")!=-1 || script->get_path().find("::")!=-1)
+ continue; //internal script, who cares
- if (script->get_path()=="" || script->get_path().find("local://")!=-1 || script->get_path().find("::")!=-1)
- continue; //internal script, who cares
+ uint64_t last_date = script->get_last_modified_time();
+ uint64_t date = FileAccess::get_modified_time(script->get_path());
- uint64_t last_date = script->get_last_modified_time();
- uint64_t date = FileAccess::get_modified_time(script->get_path());
+ //printf("last date: %lli vs date: %lli\n",last_date,date);
+ if (last_date!=date) {
- //printf("last date: %lli vs date: %lli\n",last_date,date);
- if (last_date!=date) {
+ TreeItem *ti = disk_changed_list->create_item(r);
+ ti->set_text(0,script->get_path().get_file());
- TreeItem *ti = disk_changed_list->create_item(r);
- ti->set_text(0,script->get_path().get_file());
- all_ok=false;
- //r->set_metadata(0,);
+ if (!use_autoreload || ste->is_unsaved()) {
+ need_ask=true;
+ }
+ need_reload=true;
+ //r->set_metadata(0,);
+ }
}
}
- if (!all_ok) {
- if (bool(EDITOR_DEF("text_editor/auto_reload_changed_scripts",false))) {
+ if (need_reload) {
+ if (!need_ask) {
script_editor->_reload_scripts();
+ need_reload=false;
} else {
disk_changed->call_deferred("popup_centered_ratio",0.5);
}
}
- return all_ok;
+ return need_reload;
}
void ScriptEditor::swap_lines(TextEdit *tx, int line1, int line2)
@@ -912,7 +986,22 @@ void ScriptEditor::_menu_option(int p_option) {
case WINDOW_PREV: {
_history_back();
} break;
-
+ case DEBUG_SHOW: {
+ if (debugger) {
+ bool visible = debug_menu->get_popup()->is_item_checked( debug_menu->get_popup()->get_item_index(DEBUG_SHOW) );
+ debug_menu->get_popup()->set_item_checked( debug_menu->get_popup()->get_item_index(DEBUG_SHOW), !visible);
+ if (visible)
+ debugger->hide();
+ else
+ debugger->show();
+ }
+ } break;
+ case DEBUG_SHOW_KEEP_OPEN: {
+ bool visible = debug_menu->get_popup()->is_item_checked( debug_menu->get_popup()->get_item_index(DEBUG_SHOW_KEEP_OPEN) );
+ if (debugger)
+ debugger->set_hide_on_stop(visible);
+ debug_menu->get_popup()->set_item_checked( debug_menu->get_popup()->get_item_index(DEBUG_SHOW_KEEP_OPEN), !visible);
+ } break;
}
@@ -929,8 +1018,10 @@ void ScriptEditor::_menu_option(int p_option) {
script_create_dialog->popup_centered(Size2(300, 300));
} break;
case FILE_SAVE: {
- if (!_test_script_times_on_disk())
+
+ if (_test_script_times_on_disk())
return;
+
editor->save_resource( current->get_edited_script() );
} break;
@@ -1137,12 +1228,14 @@ void ScriptEditor::_menu_option(int p_option) {
return;
int line = tx->cursor_get_line();
int next_line = line + 1;
+ int column = tx->cursor_get_column();
- if (line == tx->get_line_count() || next_line > tx->get_line_count())
- return;
+ if (line >= tx->get_line_count() - 1)
+ tx->set_line(line, tx->get_line(line) + "\n");
String line_clone = tx->get_line(line);
tx->insert_at(line_clone, next_line);
+ tx->cursor_set_column(column);
tx->update();
} break;
@@ -1264,16 +1357,6 @@ void ScriptEditor::_menu_option(int p_option) {
debugger->debug_continue();
} break;
- case DEBUG_SHOW: {
- if (debugger) {
- bool visible = debug_menu->get_popup()->is_item_checked( debug_menu->get_popup()->get_item_index(DEBUG_SHOW) );
- debug_menu->get_popup()->set_item_checked( debug_menu->get_popup()->get_item_index(DEBUG_SHOW), !visible);
- if (visible)
- debugger->hide();
- else
- debugger->show();
- }
- } break;
case HELP_CONTEXTUAL: {
String text = current->get_text_edit()->get_selection_text();
if (text == "")
@@ -1401,6 +1484,7 @@ void ScriptEditor::_notification(int p_what) {
if (p_what==MainLoop::NOTIFICATION_WM_FOCUS_IN) {
_test_script_times_on_disk();
+ _update_modified_scripts_for_external_editor();
}
if (p_what==NOTIFICATION_PROCESS) {
@@ -1409,6 +1493,11 @@ void ScriptEditor::_notification(int p_what) {
}
+void ScriptEditor::edited_scene_changed() {
+
+ _update_modified_scripts_for_external_editor();
+
+}
static const Node * _find_node_with_script(const Node* p_node, const RefPtr & p_script) {
@@ -1692,7 +1781,7 @@ void ScriptEditor::_update_script_colors() {
if (h>hist_size) {
continue;
}
- float v = Math::ease((edit_pass-pass)/float_t(hist_size),0.4);
+ float v = Math::ease((edit_pass-pass)/float(hist_size),0.4);
script_list->set_item_custom_bg_color(i,hot_color.linear_interpolate(cold_color,v));
@@ -1835,6 +1924,7 @@ void ScriptEditor::edit(const Ref<Script>& p_script) {
ScriptTextEditor *ste = memnew( ScriptTextEditor );
ste->set_edited_script(p_script);
ste->get_text_edit()->set_tooltip_request_func(this,"_get_debug_tooltip",ste);
+ ste->get_text_edit()->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/auto_brace_complete"));
tab_container->add_child(ste);
_go_to_tab(tab_container->get_tab_count()-1);
@@ -1959,6 +2049,15 @@ void ScriptEditor::_editor_settings_changed() {
autosave_timer->stop();
}
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>();
+ if (!ste)
+ continue;
+
+ ste->get_text_edit()->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/auto_brace_complete"));
+ }
+
}
void ScriptEditor::_autosave_scripts() {
@@ -2174,6 +2273,10 @@ void ScriptEditor::_history_back(){
void ScriptEditor::set_scene_root_script( Ref<Script> p_script ) {
bool open_dominant = EditorSettings::get_singleton()->get("text_editor/open_dominant_script_on_scene_change");
+
+ if (bool(EditorSettings::get_singleton()->get("external_editor/use_external_editor")))
+ return;
+
if (open_dominant && p_script.is_valid()) {
edit(p_script);
}
@@ -2220,18 +2323,15 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
menu_hb = memnew( HBoxContainer );
add_child(menu_hb);
- v_split = memnew( VSplitContainer );
- add_child(v_split);
- v_split->set_v_size_flags(SIZE_EXPAND_FILL);
script_split = memnew( HSplitContainer );
- v_split->add_child(script_split);
+ add_child(script_split);
script_split->set_v_size_flags(SIZE_EXPAND_FILL);
script_list = memnew( ItemList );
script_split->add_child(script_list);
- script_list->set_custom_minimum_size(Size2(70,0));
- script_split->set_split_offset(70);
+ script_list->set_custom_minimum_size(Size2(0,0));
+ script_split->set_split_offset(140);
tab_container = memnew( TabContainer );
tab_container->set_tabs_visible(false);
@@ -2315,7 +2415,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
debug_menu->get_popup()->add_item("Break",DEBUG_BREAK);
debug_menu->get_popup()->add_item("Continue",DEBUG_CONTINUE);
debug_menu->get_popup()->add_separator();
- debug_menu->get_popup()->add_check_item("Show Debugger",DEBUG_SHOW);
+ //debug_menu->get_popup()->add_check_item("Show Debugger",DEBUG_SHOW);
+ debug_menu->get_popup()->add_check_item("Keep Debugger Open",DEBUG_SHOW_KEEP_OPEN);
debug_menu->get_popup()->connect("item_pressed", this,"_menu_option");
debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_NEXT), true);
@@ -2443,7 +2544,11 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
quick_open->connect("goto_line",this,"_goto_script_line2");
- v_split->add_child(debugger);
+
+ Button *db = EditorNode::get_singleton()->add_bottom_panel_item("Debugger",debugger);
+ debugger->set_tool_button(db);
+
+
debugger->connect("breaked",this,"_breaked");
autosave_timer = memnew( Timer );
@@ -2557,6 +2662,11 @@ void ScriptEditorPlugin::get_breakpoints(List<String> *p_breakpoints) {
return script_editor->get_breakpoints(p_breakpoints);
}
+void ScriptEditorPlugin::edited_scene_changed() {
+
+ script_editor->edited_scene_changed();
+}
+
ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) {
editor=p_node;
@@ -2566,7 +2676,7 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) {
script_editor->hide();
- EDITOR_DEF("text_editor/auto_reload_changed_scripts",false);
+ EDITOR_DEF("text_editor/auto_reload_scripts_on_external_change",true);
EDITOR_DEF("text_editor/open_dominant_script_on_scene_change",true);
EDITOR_DEF("external_editor/use_external_editor",false);
EDITOR_DEF("external_editor/exec_path","");
diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h
index e755f570ef..c52da41a43 100644
--- a/tools/editor/plugins/script_editor_plugin.h
+++ b/tools/editor/plugins/script_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -103,7 +103,7 @@ public:
void reload_text();
String get_name() ;
Ref<Texture> get_icon() ;
-
+ bool is_unsaved();
ScriptTextEditor();
};
@@ -151,7 +151,8 @@ class ScriptEditor : public VBoxContainer {
DEBUG_BREAK,
DEBUG_CONTINUE,
DEBUG_SHOW,
- HELP_CONTEXTUAL,
+ DEBUG_SHOW_KEEP_OPEN,
+ HELP_CONTEXTUAL,
WINDOW_MOVE_LEFT,
WINDOW_MOVE_RIGHT,
WINDOW_NEXT,
@@ -211,8 +212,6 @@ class ScriptEditor : public VBoxContainer {
Tree *disk_changed_list;
ConfirmationDialog *disk_changed;
- VSplitContainer *v_split;
-
bool restoring_layout;
String _get_debug_tooltip(const String&p_text,Node *_ste);
@@ -271,6 +270,7 @@ class ScriptEditor : public VBoxContainer {
void _go_to_tab(int p_idx);
void _update_history_pos(int p_new_pos);
void _update_script_colors();
+ void _update_modified_scripts_for_external_editor();
static ScriptEditor *script_editor;
@@ -302,6 +302,8 @@ public:
void set_scene_root_script( Ref<Script> p_script );
+ virtual void edited_scene_changed();
+
ScriptEditorDebugger *get_debugger() { return debugger; }
ScriptEditor(EditorNode *p_editor);
@@ -338,6 +340,7 @@ public:
virtual void get_breakpoints(List<String> *p_breakpoints);
+ virtual void edited_scene_changed();
ScriptEditorPlugin(EditorNode *p_node);
~ScriptEditorPlugin();
diff --git a/tools/editor/plugins/shader_editor_plugin.cpp b/tools/editor/plugins/shader_editor_plugin.cpp
index a182d57742..18d8f5efc0 100644
--- a/tools/editor/plugins/shader_editor_plugin.cpp
+++ b/tools/editor/plugins/shader_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -172,11 +172,8 @@ ShaderTextEditor::ShaderTextEditor() {
void ShaderEditor::_menu_option(int p_option) {
- int selected = tab_container->get_current_tab();
- if (selected<0 || selected>=tab_container->get_child_count())
- return;
- ShaderTextEditor *current = tab_container->get_child(selected)->cast_to<ShaderTextEditor>();
+ ShaderTextEditor *current = tab_container->get_current_tab_control()->cast_to<ShaderTextEditor>();
if (!current)
return;
@@ -235,6 +232,11 @@ void ShaderEditor::_menu_option(int p_option) {
void ShaderEditor::_tab_changed(int p_which) {
+ ShaderTextEditor *shader_editor = tab_container->get_tab_control(p_which)->cast_to<ShaderTextEditor>();
+
+ if (shader_editor && is_inside_tree())
+ shader_editor->get_text_edit()->grab_focus();
+
ensure_select_current();
}
diff --git a/tools/editor/plugins/shader_editor_plugin.h b/tools/editor/plugins/shader_editor_plugin.h
index 4ead2ba94e..26d20b80b4 100644
--- a/tools/editor/plugins/shader_editor_plugin.h
+++ b/tools/editor/plugins/shader_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/shader_graph_editor_plugin.cpp b/tools/editor/plugins/shader_graph_editor_plugin.cpp
index 3a7dc26466..36a8c79b84 100644
--- a/tools/editor/plugins/shader_graph_editor_plugin.cpp
+++ b/tools/editor/plugins/shader_graph_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -2658,13 +2658,13 @@ void ShaderGraphEditor::edit(Ref<ShaderGraph> p_shader) {
void ShaderGraphEditor::_add_node(int p_type) {
ShaderGraph::ShaderType shader_type=ShaderGraph::ShaderType(tabs->get_current_tab());
-
graph_edits[shader_type]->add_node(p_type, next_location);
}
void ShaderGraphEditor::_popup_requested(const Vector2 &p_position)
{
- next_location = get_local_mouse_pos();
+ Vector2 scroll_ofs=graph_edits[tabs->get_current_tab()]->get_graph_edit()->get_scroll_ofs();
+ next_location = get_local_mouse_pos() + scroll_ofs;
popup->set_global_pos(p_position);
popup->set_size( Size2( 200, 0) );
popup->popup();
diff --git a/tools/editor/plugins/shader_graph_editor_plugin.h b/tools/editor/plugins/shader_graph_editor_plugin.h
index 39e9b29d45..0336696911 100644
--- a/tools/editor/plugins/shader_graph_editor_plugin.h
+++ b/tools/editor/plugins/shader_graph_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -149,7 +149,7 @@ class ShaderGraphView : public Node {
void _end_node_move();
void _move_node(int p_id,const Vector2& p_to);
void _duplicate_nodes_request();
- void _duplicate_nodes(const Array &p_nodes);
+ void _duplicate_nodes(const Array &p_nodes);
void _delete_nodes_request();
diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp
index 7816efe89f..236d69dfb3 100644
--- a/tools/editor/plugins/spatial_editor_plugin.cpp
+++ b/tools/editor/plugins/spatial_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -39,6 +39,9 @@
#include "scene/resources/surface_tool.h"
#include "tools/editor/spatial_editor_gizmos.h"
#include "globals.h"
+#include "tools/editor/plugins/animation_player_editor_plugin.h"
+#include "tools/editor/animation_editor.h"
+
#define DISTANCE_DEFAULT 4
@@ -736,6 +739,68 @@ void SpatialEditorViewport::_smouseenter() {
surface->grab_focus();
}
+void SpatialEditorViewport::_list_select(InputEventMouseButton b) {
+
+ _find_items_at_pos(Vector2( b.x, b.y ),clicked_includes_current,selection_results,b.mod.shift);
+
+ Node *scene=editor->get_edited_scene();
+
+ for(int i=0;i<selection_results.size();i++) {
+ Spatial *item=selection_results[i].item;
+ if (item!=scene && item->get_owner()!=scene && !scene->is_editable_instance(item->get_owner())) {
+ //invalid result
+ selection_results.remove(i);
+ i--;
+ }
+
+ }
+
+
+ clicked_wants_append=b.mod.shift;
+
+ if (selection_results.size() == 1) {
+
+ clicked=selection_results[0].item->get_instance_ID();
+ selection_results.clear();
+
+ if (clicked) {
+ _select_clicked(clicked_wants_append,true);
+ clicked=0;
+ }
+
+ } else if (!selection_results.empty()) {
+
+ NodePath root_path = get_tree()->get_edited_scene_root()->get_path();
+ StringName root_name = root_path.get_name(root_path.get_name_count()-1);
+
+ for (int i = 0; i < selection_results.size(); i++) {
+
+ Spatial *spat=selection_results[i].item;
+
+ Ref<Texture> icon;
+ if (spat->has_meta("_editor_icon"))
+ icon=spat->get_meta("_editor_icon");
+ else
+ icon=get_icon( has_icon(spat->get_type(),"EditorIcons")?spat->get_type():String("Object"),"EditorIcons");
+
+ String node_path="/"+root_name+"/"+root_path.rel_path_to(spat->get_path());
+
+ selection_menu->add_item(spat->get_name());
+ selection_menu->set_item_icon(i, icon );
+ selection_menu->set_item_metadata(i, node_path);
+ selection_menu->set_item_tooltip(i,String(spat->get_name())+
+ "\nType: "+spat->get_type()+"\nPath: "+node_path);
+ }
+
+ selection_menu->set_global_pos(Vector2( b.global_x, b.global_y ));
+ selection_menu->popup();
+ selection_menu->call_deferred("grab_click_focus");
+ selection_menu->set_invalidate_click_until_motion();
+
+
+
+ }
+}
void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
if (previewing)
@@ -868,50 +933,9 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
if (nav_scheme == NAVIGATION_MAYA)
break;
- _find_items_at_pos(Vector2( b.x, b.y ),clicked_includes_current,selection_results,b.mod.shift);
-
- clicked_wants_append=b.mod.shift;
-
- if (selection_results.size() == 1) {
-
- clicked=selection_results[0].item->get_instance_ID();
- selection_results.clear();
-
- if (clicked) {
- _select_clicked(clicked_wants_append,true);
- clicked=0;
- }
-
- } else if (!selection_results.empty()) {
-
- NodePath root_path = get_tree()->get_edited_scene_root()->get_path();
- StringName root_name = root_path.get_name(root_path.get_name_count()-1);
-
- for (int i = 0; i < selection_results.size(); i++) {
-
- Spatial *spat=selection_results[i].item;
-
- Ref<Texture> icon;
- if (spat->has_meta("_editor_icon"))
- icon=spat->get_meta("_editor_icon");
- else
- icon=get_icon( has_icon(spat->get_type(),"EditorIcons")?spat->get_type():String("Object"),"EditorIcons");
-
- String node_path="/"+root_name+"/"+root_path.rel_path_to(spat->get_path());
+ _list_select(b);
+ return;
- selection_menu->add_item(spat->get_name());
- selection_menu->set_item_icon(i, icon );
- selection_menu->set_item_metadata(i, node_path);
- selection_menu->set_item_tooltip(i,String(spat->get_name())+
- "\nType: "+spat->get_type()+"\nPath: "+node_path);
- }
-
- selection_menu->set_global_pos(Vector2( b.global_x, b.global_y ));
- selection_menu->popup();
- selection_menu->call_deferred("grab_click_focus");
-
- break;
- }
}
}
@@ -984,6 +1008,11 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
break;
}
+ if (spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_LIST_SELECT) {
+ _list_select(b);
+ break;
+ }
+
_edit.mouse_pos=Point2(b.x,b.y);
_edit.snap=false;
_edit.mode=TRANSFORM_NONE;
@@ -1591,6 +1620,8 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
case InputEvent::KEY: {
const InputEventKey &k = p_event.key;
+ if (!k.pressed)
+ break;
switch(k.scancode) {
case KEY_S: {
@@ -1651,7 +1682,8 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
} break;
case KEY_KP_5: {
- orthogonal = !orthogonal;
+
+ //orthogonal = !orthogonal;
_menu_option(orthogonal?VIEW_PERSPECTIVE:VIEW_ORTHOGONAL);
_update_name();
@@ -1662,7 +1694,7 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
if (!get_selected_count() || _edit.mode!=TRANSFORM_NONE)
break;
- if (!editor->get_animation_editor()->has_keying()) {
+ if (!AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) {
set_message("Keying is disabled (no key inserted).");
break;
}
@@ -2383,6 +2415,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
add_child(c);
c->set_area_as_parent_rect();
viewport = memnew( Viewport );
+ viewport->set_disable_input(true);
c->add_child(viewport);
surface = memnew( Control );
add_child(surface);
@@ -2600,6 +2633,13 @@ Dictionary SpatialEditor::get_state() const {
Dictionary d;
+ d["snap_enabled"]=snap_enabled;
+ d["translate_snap"]=get_translate_snap();
+ d["rotate_snap"]=get_rotate_snap();
+ d["scale_snap"]=get_scale_snap();
+
+ int local_coords_index=transform_menu->get_popup()->get_item_index(MENU_TRANSFORM_LOCAL_COORDS);
+ d["local_coords"]=transform_menu->get_popup()->is_item_checked( local_coords_index );
int vc=0;
if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT) ))
@@ -2641,37 +2681,52 @@ void SpatialEditor::set_state(const Dictionary& p_state) {
Dictionary d = p_state;
- ERR_FAIL_COND(!d.has("viewport_mode"));
- ERR_FAIL_COND(!d.has("viewports"));
- ERR_FAIL_COND(!d.has("default_light"));
- ERR_FAIL_COND(!d.has("show_grid"));
- ERR_FAIL_COND(!d.has("show_origin"));
- ERR_FAIL_COND(!d.has("fov"));
- ERR_FAIL_COND(!d.has("znear"));
- ERR_FAIL_COND(!d.has("zfar"));
+ if (d.has("snap_enabled")) {
+ snap_enabled=d["snap_enabled"];
+ int snap_enabled_idx=transform_menu->get_popup()->get_item_index(MENU_TRANSFORM_USE_SNAP);
+ transform_menu->get_popup()->set_item_checked( snap_enabled_idx, snap_enabled );
+ }
- int vc = d["viewport_mode"];
+ if (d.has("translate_snap"))
+ snap_translate->set_text(d["translate_snap"]);
- if (vc==1)
- _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
- else if (vc==2)
- _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS);
- else if (vc==3)
- _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS);
- else if (vc==4)
- _menu_item_pressed(MENU_VIEW_USE_4_VIEWPORTS);
- else if (vc==5)
- _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS_ALT);
- else if (vc==6)
- _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS_ALT);
-
- Array vp = d["viewports"];
- ERR_FAIL_COND(vp.size()>4);
+ if (d.has("rotate_snap"))
+ snap_rotate->set_text(d["rotate_snap"]);
- for(int i=0;i<4;i++) {
- viewports[i]->set_state(vp[i]);
+ if (d.has("scale_snap"))
+ snap_scale->set_text(d["scale_snap"]);
+
+ if (d.has("local_coords")) {
+ int local_coords_idx=transform_menu->get_popup()->get_item_index(MENU_TRANSFORM_LOCAL_COORDS);
+ transform_menu->get_popup()->set_item_checked( local_coords_idx, d["local_coords"] );
+ update_transform_gizmo();
}
+ if (d.has("viewport_mode")) {
+ int vc = d["viewport_mode"];
+
+ if (vc==1)
+ _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
+ else if (vc==2)
+ _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS);
+ else if (vc==3)
+ _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS);
+ else if (vc==4)
+ _menu_item_pressed(MENU_VIEW_USE_4_VIEWPORTS);
+ else if (vc==5)
+ _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS_ALT);
+ else if (vc==6)
+ _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS_ALT);
+ }
+
+ if (d.has("viewports")) {
+ Array vp = d["viewports"];
+ ERR_FAIL_COND(vp.size()>4);
+
+ for(int i=0;i<4;i++) {
+ viewports[i]->set_state(vp[i]);
+ }
+ }
if (d.has("zfar"))
settings_zfar->set_val(float(d["zfar"]));
@@ -2841,13 +2896,14 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
case MENU_TOOL_SELECT:
case MENU_TOOL_MOVE:
case MENU_TOOL_ROTATE:
- case MENU_TOOL_SCALE: {
+ case MENU_TOOL_SCALE:
+ case MENU_TOOL_LIST_SELECT: {
- for(int i=0;i<4;i++)
+ for(int i=0;i<TOOL_MAX;i++)
tool_button[i]->set_pressed(i==p_option);
tool_mode=(ToolMode)p_option;
- static const char *_mode[]={"Selection Mode.","Translation Mode.","Rotation Mode.","Scale Mode."};
+ static const char *_mode[]={"Selection Mode.","Translation Mode.","Rotation Mode.","Scale Mode.","List Selection Mode."};
// set_message(_mode[p_option],3);
update_transform_gizmo();
@@ -3474,19 +3530,13 @@ void SpatialEditor::_instance_scene() {
undo_redo->commit_action();
#endif
}
-/*
-void SpatialEditor::_update_selection() {
-
-
-}
-*/
void SpatialEditor::_unhandled_key_input(InputEvent p_event) {
- if (!is_visible())
+ if (!is_visible() || get_viewport()->gui_has_modal_stack())
return;
- {
+ {
EditorNode *en = editor;
EditorPlugin *over_plugin = en->get_editor_plugin_over();
@@ -3530,6 +3580,7 @@ void SpatialEditor::_notification(int p_what) {
tool_button[SpatialEditor::TOOL_MODE_MOVE]->set_icon( get_icon("ToolMove","EditorIcons") );
tool_button[SpatialEditor::TOOL_MODE_ROTATE]->set_icon( get_icon("ToolRotate","EditorIcons") );
tool_button[SpatialEditor::TOOL_MODE_SCALE]->set_icon( get_icon("ToolScale","EditorIcons") );
+ tool_button[SpatialEditor::TOOL_MODE_LIST_SELECT]->set_icon( get_icon("ListSelect","EditorIcons") );
instance_button->set_icon( get_icon("SpatialAdd","EditorIcons") );
instance_button->hide();
@@ -3684,7 +3735,6 @@ void SpatialEditor::_bind_methods() {
ObjectTypeDB::bind_method("_menu_item_pressed",&SpatialEditor::_menu_item_pressed);
ObjectTypeDB::bind_method("_xform_dialog_action",&SpatialEditor::_xform_dialog_action);
ObjectTypeDB::bind_method("_instance_scene",&SpatialEditor::_instance_scene);
-// ObjectTypeDB::bind_method("_update_selection",&SpatialEditor::_update_selection);
ObjectTypeDB::bind_method("_get_editor_data",&SpatialEditor::_get_editor_data);
ObjectTypeDB::bind_method("_request_gizmo",&SpatialEditor::_request_gizmo);
ObjectTypeDB::bind_method("_default_light_angle_input",&SpatialEditor::_default_light_angle_input);
@@ -3786,7 +3836,6 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
editor=p_editor;
editor_selection=editor->get_editor_selection();
editor_selection->add_editor_plugin(this);
- editor_selection->connect("selection_changed",this,"_update_selection");
snap_enabled=false;
tool_mode = TOOL_MODE_SELECT;
@@ -3807,7 +3856,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
tool_button[TOOL_MODE_SELECT]->set_pressed(true);
button_binds[0]=MENU_TOOL_SELECT;
tool_button[TOOL_MODE_SELECT]->connect("pressed", this,"_menu_item_pressed",button_binds);
- tool_button[TOOL_MODE_SELECT]->set_tooltip("Select Mode (Q)");
+ tool_button[TOOL_MODE_SELECT]->set_tooltip("Select Mode (Q)\n"+keycode_get_string(KEY_MASK_CMD)+"Drag: Rotate\nAlt+Drag: Move\nAlt+RMB: Depth list selection");
tool_button[TOOL_MODE_MOVE] = memnew( ToolButton );
@@ -3839,10 +3888,22 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
hbc_menu->add_child( instance_button );
instance_button->set_flat(true);
instance_button->connect("pressed",this,"_instance_scene");
+ instance_button->hide();
VSeparator *vs = memnew( VSeparator );
hbc_menu->add_child(vs);
+ tool_button[TOOL_MODE_LIST_SELECT] = memnew( ToolButton );
+ hbc_menu->add_child( tool_button[TOOL_MODE_LIST_SELECT] );
+ tool_button[TOOL_MODE_LIST_SELECT]->set_toggle_mode(true);
+ tool_button[TOOL_MODE_LIST_SELECT]->set_flat(true);
+ button_binds[0]=MENU_TOOL_LIST_SELECT;
+ tool_button[TOOL_MODE_LIST_SELECT]->connect("pressed", this,"_menu_item_pressed",button_binds);
+ tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip("Show a list of all objects at the position clicked\n(same as Alt+RMB in selet mode).");
+
+ vs = memnew( VSeparator );
+ hbc_menu->add_child(vs);
+
PopupMenu *p;
@@ -3962,6 +4023,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
settings_light_base->connect("input_event",this,"_default_light_angle_input");
settings_vbc->add_margin_child("Default Light Normal:",settings_light_base);
settings_light_vp = memnew( Viewport );
+ settings_light_vp->set_disable_input(true);
settings_light_vp->set_use_own_world(true);
settings_light_base->add_child(settings_light_vp);
diff --git a/tools/editor/plugins/spatial_editor_plugin.h b/tools/editor/plugins/spatial_editor_plugin.h
index ebd3f77fe7..b0e366b140 100644
--- a/tools/editor/plugins/spatial_editor_plugin.h
+++ b/tools/editor/plugins/spatial_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -137,7 +137,6 @@ private:
Vector3 _get_screen_to_space(const Vector3& p_vector3);
void _select_region();
- void _update_selection();
bool _gizmo_select(const Vector2& p_screenpos,bool p_hilite_only=false);
float get_znear() const;
@@ -239,6 +238,7 @@ private:
void _finish_gizmo_instances();
void _selection_result_pressed(int);
void _selection_menu_hide();
+ void _list_select(InputEventMouseButton b);
protected:
@@ -287,7 +287,9 @@ public:
TOOL_MODE_SELECT,
TOOL_MODE_MOVE,
TOOL_MODE_ROTATE,
- TOOL_MODE_SCALE
+ TOOL_MODE_SCALE,
+ TOOL_MODE_LIST_SELECT,
+ TOOL_MAX
};
@@ -369,6 +371,7 @@ private:
MENU_TOOL_MOVE,
MENU_TOOL_ROTATE,
MENU_TOOL_SCALE,
+ MENU_TOOL_LIST_SELECT,
MENU_TRANSFORM_USE_SNAP,
MENU_TRANSFORM_CONFIGURE_SNAP,
MENU_TRANSFORM_LOCAL_COORDS,
@@ -392,7 +395,7 @@ private:
};
- Button *tool_button[4];
+ Button *tool_button[TOOL_MAX];
Button *instance_button;
diff --git a/tools/editor/plugins/sprite_frames_editor_plugin.cpp b/tools/editor/plugins/sprite_frames_editor_plugin.cpp
index e90087efda..af73828b61 100644
--- a/tools/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/tools/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -338,7 +338,6 @@ void SpriteFramesEditor::_update_library() {
TreeItem *ti = tree->create_item(root);
ti->set_cell_mode(0,TreeItem::CELL_MODE_STRING);
- ti->set_editable(0,true);
ti->set_selectable(0,true);
if (frames->get_frame(i).is_null()) {
@@ -346,7 +345,7 @@ void SpriteFramesEditor::_update_library() {
ti->set_text(0,"Frame "+itos(i)+" (empty)");
} else {
- ti->set_text(0,"Frame "+itos(i));
+ ti->set_text(0,"Frame "+itos(i)+" ("+frames->get_frame(i)->get_name()+")");
ti->set_icon(0,frames->get_frame(i));
}
if (frames->get_frame(i).is_valid())
@@ -486,11 +485,15 @@ bool SpriteFramesEditorPlugin::handles(Object *p_object) const {
void SpriteFramesEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
- frames_editor->show();
+ button->show();
+ editor->make_bottom_panel_item_visible(frames_editor);
// frames_editor->set_process(true);
} else {
- frames_editor->hide();
+ button->hide();
+ if (frames_editor->is_visible())
+ editor->hide_bottom_panel();
+
// frames_editor->set_process(false);
}
@@ -500,11 +503,9 @@ SpriteFramesEditorPlugin::SpriteFramesEditorPlugin(EditorNode *p_node) {
editor=p_node;
frames_editor = memnew( SpriteFramesEditor );
- editor->get_viewport()->add_child(frames_editor);
- frames_editor->set_area_as_parent_rect();
-// frames_editor->set_anchor( MARGIN_TOP, Control::ANCHOR_END);
-// frames_editor->set_margin( MARGIN_TOP, 120 );
- frames_editor->hide();
+ frames_editor->set_custom_minimum_size(Size2(0,300));
+ button=editor->add_bottom_panel_item("SpriteFrames",frames_editor);
+ button->hide();
diff --git a/tools/editor/plugins/sprite_frames_editor_plugin.h b/tools/editor/plugins/sprite_frames_editor_plugin.h
index 969d7b1ce3..5d0a6cb035 100644
--- a/tools/editor/plugins/sprite_frames_editor_plugin.h
+++ b/tools/editor/plugins/sprite_frames_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -94,6 +94,7 @@ class SpriteFramesEditorPlugin : public EditorPlugin {
SpriteFramesEditor *frames_editor;
EditorNode *editor;
+ Button *button;
public:
diff --git a/tools/editor/plugins/sprite_region_editor_plugin.cpp b/tools/editor/plugins/sprite_region_editor_plugin.cpp
index 35c53cf562..8dfa8a60a6 100644
--- a/tools/editor/plugins/sprite_region_editor_plugin.cpp
+++ b/tools/editor/plugins/sprite_region_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Author: Mariano Suligoy */
/* */
@@ -367,7 +367,7 @@ void SpriteRegionEditor::edit(Node *p_sprite)
{
if (p_sprite) {
node=p_sprite->cast_to<Sprite>();
- node->connect("exit_tree",this,"_node_removed",varray(),CONNECT_ONESHOT);
+ node->connect("exit_tree",this,"_node_removed",varray(p_sprite),CONNECT_ONESHOT);
} else {
if (node)
node->disconnect("exit_tree",this,"_node_removed");
@@ -411,6 +411,7 @@ SpriteRegionEditor::SpriteRegionEditor(EditorNode* p_editor)
snap_step=Vector2(10,10);
use_snap=false;
snap_show_grid=false;
+ drag=false;
add_child( memnew( VSeparator ));
edit_node = memnew( ToolButton );
@@ -449,7 +450,7 @@ SpriteRegionEditor::SpriteRegionEditor(EditorNode* p_editor)
hb_tools->add_child( memnew( VSeparator ));
hb_tools->add_child( memnew( Label("Grid Offset:") ) );
- SpinBox *sb_off_x = memnew( SpinBox );
+ sb_off_x = memnew( SpinBox );
sb_off_x->set_min(-256);
sb_off_x->set_max(256);
sb_off_x->set_step(1);
@@ -458,7 +459,7 @@ SpriteRegionEditor::SpriteRegionEditor(EditorNode* p_editor)
sb_off_x->connect("value_changed", this, "_set_snap_off_x");
hb_tools->add_child(sb_off_x);
- SpinBox *sb_off_y = memnew( SpinBox );
+ sb_off_y = memnew( SpinBox );
sb_off_y->set_min(-256);
sb_off_y->set_max(256);
sb_off_y->set_step(1);
@@ -470,7 +471,7 @@ SpriteRegionEditor::SpriteRegionEditor(EditorNode* p_editor)
hb_tools->add_child( memnew( VSeparator ));
hb_tools->add_child( memnew( Label("Grid Step:") ) );
- SpinBox *sb_step_x = memnew( SpinBox );
+ sb_step_x = memnew( SpinBox );
sb_step_x->set_min(-256);
sb_step_x->set_max(256);
sb_step_x->set_step(1);
@@ -479,7 +480,7 @@ SpriteRegionEditor::SpriteRegionEditor(EditorNode* p_editor)
sb_step_x->connect("value_changed", this, "_set_snap_step_x");
hb_tools->add_child(sb_step_x);
- SpinBox *sb_step_y = memnew( SpinBox );
+ sb_step_y = memnew( SpinBox );
sb_step_y->set_min(-256);
sb_step_y->set_max(256);
sb_step_y->set_step(1);
@@ -488,8 +489,6 @@ SpriteRegionEditor::SpriteRegionEditor(EditorNode* p_editor)
sb_step_y->connect("value_changed", this, "_set_snap_step_y");
hb_tools->add_child(sb_step_y);
-// MARIANOGNU::TODO: Add more tools?
-
HBoxContainer *main_hb = memnew( HBoxContainer );
main_vb->add_child(main_hb);
edit_draw = memnew( Control );
@@ -554,6 +553,50 @@ void SpriteRegionEditorPlugin::make_visible(bool p_visible)
}
}
+
+Dictionary SpriteRegionEditorPlugin::get_state() const {
+
+ Dictionary state;
+ state["zoom"]=region_editor->zoom->get_val();
+ state["snap_offset"]=region_editor->snap_offset;
+ state["snap_step"]=region_editor->snap_step;
+ state["use_snap"]=region_editor->use_snap;
+ state["snap_show_grid"]=region_editor->snap_show_grid;
+ return state;
+}
+
+void SpriteRegionEditorPlugin::set_state(const Dictionary& p_state){
+
+ Dictionary state=p_state;
+ if (state.has("zoom")) {
+ region_editor->zoom->set_val(p_state["zoom"]);
+ }
+
+ if (state.has("snap_step")) {
+ Vector2 s = state["snap_step"];
+ region_editor->sb_step_x->set_val(s.x);
+ region_editor->sb_step_y->set_val(s.y);
+ region_editor->snap_step = s;
+ }
+
+ if (state.has("snap_offset")) {
+ Vector2 ofs = state["snap_offset"];
+ region_editor->sb_off_x->set_val(ofs.x);
+ region_editor->sb_off_y->set_val(ofs.y);
+ region_editor->snap_offset = ofs;
+ }
+
+ if (state.has("use_snap")) {
+ region_editor->use_snap=state["use_snap"];
+ region_editor->b_snap_enable->set_pressed(state["use_snap"]);
+ }
+
+ if (state.has("snap_show_grid")) {
+ region_editor->snap_show_grid=state["snap_show_grid"];
+ region_editor->b_snap_grid->set_pressed(state["snap_show_grid"]);
+ }
+}
+
SpriteRegionEditorPlugin::SpriteRegionEditorPlugin(EditorNode *p_node)
{
editor = p_node;
diff --git a/tools/editor/plugins/sprite_region_editor_plugin.h b/tools/editor/plugins/sprite_region_editor_plugin.h
index cf69395f40..47cb210863 100644
--- a/tools/editor/plugins/sprite_region_editor_plugin.h
+++ b/tools/editor/plugins/sprite_region_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Author: Mariano Suligoy */
/* */
@@ -41,6 +41,8 @@ class SpriteRegionEditor : public HBoxContainer {
OBJ_TYPE(SpriteRegionEditor, HBoxContainer );
+ friend class SpriteRegionEditorPlugin;
+
ToolButton *edit_node;
// Button *use_region;
ToolButton *b_snap_enable;
@@ -48,6 +50,10 @@ class SpriteRegionEditor : public HBoxContainer {
TextureFrame *icon_zoom;
HSlider *zoom;
SpinBox *zoom_value;
+ SpinBox *sb_step_y;
+ SpinBox *sb_step_x;
+ SpinBox *sb_off_y;
+ SpinBox *sb_off_x;
Control *edit_draw;
VScrollBar *vscroll;
@@ -113,11 +119,13 @@ class SpriteRegionEditorPlugin : public EditorPlugin
EditorNode *editor;
public:
- virtual String get_name() const { return "Sprite"; }
+ virtual String get_name() const { return "SpriteRegion"; }
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);
+ void set_state(const Dictionary &p_state);
+ Dictionary get_state() const;
SpriteRegionEditorPlugin(EditorNode *p_node);
};
diff --git a/tools/editor/plugins/stream_editor_plugin.cpp b/tools/editor/plugins/stream_editor_plugin.cpp
index 81db7f2846..d896784074 100644
--- a/tools/editor/plugins/stream_editor_plugin.cpp
+++ b/tools/editor/plugins/stream_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/stream_editor_plugin.h b/tools/editor/plugins/stream_editor_plugin.h
index 7378bfad0c..5730612d61 100644
--- a/tools/editor/plugins/stream_editor_plugin.h
+++ b/tools/editor/plugins/stream_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/style_box_editor_plugin.cpp b/tools/editor/plugins/style_box_editor_plugin.cpp
index 898c69e1e0..3d7cf4135d 100644
--- a/tools/editor/plugins/style_box_editor_plugin.cpp
+++ b/tools/editor/plugins/style_box_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -90,19 +90,24 @@ bool StyleBoxEditorPlugin::handles(Object *p_node) const{
void StyleBoxEditorPlugin::make_visible(bool p_visible){
- if (p_visible)
- stylebox_editor->show();
- else
- stylebox_editor->hide();
+ if (p_visible) {
+ button->show();
+
+ } else {
+ if (stylebox_editor->is_visible())
+ EditorNode::get_singleton()->hide_bottom_panel();
+ button->hide();
+ }
}
StyleBoxEditorPlugin::StyleBoxEditorPlugin(EditorNode *p_node) {
stylebox_editor = memnew( StyleBoxEditor );
+ stylebox_editor->set_custom_minimum_size(Size2(0,250));
- p_node->get_viewport()->add_child(stylebox_editor);
- stylebox_editor->set_area_as_parent_rect();
- stylebox_editor->hide();
+ //p_node->get_viewport()->add_child(stylebox_editor);
+ button = p_node->add_bottom_panel_item("StyleBox",stylebox_editor);
+ button->hide();
}
diff --git a/tools/editor/plugins/style_box_editor_plugin.h b/tools/editor/plugins/style_box_editor_plugin.h
index 00b0871572..737f830bbb 100644
--- a/tools/editor/plugins/style_box_editor_plugin.h
+++ b/tools/editor/plugins/style_box_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -65,6 +65,7 @@ class StyleBoxEditorPlugin : public EditorPlugin {
StyleBoxEditor *stylebox_editor;
EditorNode *editor;
+ Button *button;
public:
diff --git a/tools/editor/plugins/theme_editor_plugin.cpp b/tools/editor/plugins/theme_editor_plugin.cpp
index 63ba57bfc0..ef7b3b17c3 100644
--- a/tools/editor/plugins/theme_editor_plugin.cpp
+++ b/tools/editor/plugins/theme_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -831,21 +831,26 @@ bool ThemeEditorPlugin::handles(Object *p_node) const{
void ThemeEditorPlugin::make_visible(bool p_visible){
if (p_visible) {
- theme_editor->show();
theme_editor->set_process(true);
+ button->show();
} else {
- theme_editor->hide();
theme_editor->set_process(false);
+ if (theme_editor->is_visible())
+ EditorNode::get_singleton()->hide_bottom_panel();
+ button->hide();
}
}
ThemeEditorPlugin::ThemeEditorPlugin(EditorNode *p_node) {
+ editor=p_node;
theme_editor = memnew( ThemeEditor );
+ theme_editor->set_custom_minimum_size(Size2(0,500));
+
+// p_node->get_viewport()->add_child(theme_editor);
+ button=EditorNode::get_singleton()->add_bottom_panel_item("Theme",theme_editor);
+ button->hide();
- p_node->get_viewport()->add_child(theme_editor);
- theme_editor->set_area_as_parent_rect();
- theme_editor->hide();
}
diff --git a/tools/editor/plugins/theme_editor_plugin.h b/tools/editor/plugins/theme_editor_plugin.h
index 40c7ad8186..52c4aed839 100644
--- a/tools/editor/plugins/theme_editor_plugin.h
+++ b/tools/editor/plugins/theme_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -102,6 +102,7 @@ class ThemeEditorPlugin : public EditorPlugin {
ThemeEditor *theme_editor;
EditorNode *editor;
+ Button *button;
public:
diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp
index 66c7a39096..29326a2222 100644
--- a/tools/editor/plugins/tile_map_editor_plugin.cpp
+++ b/tools/editor/plugins/tile_map_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -218,7 +218,8 @@ struct _TileMapEditorCopyData {
bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
- if (!node || !node->get_tileset().is_valid())
+
+ if (!node || !node->get_tileset().is_valid() || !node->is_visible())
return false;
Matrix32 xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
@@ -675,12 +676,9 @@ void TileMapEditor::_canvas_draw() {
Ref<Texture> t = ts->tile_get_texture(st);
if (t.is_valid()) {
Vector2 from = node->map_to_world(over_tile)+node->get_cell_draw_offset();
+ Vector2 tile_ofs = ts->tile_get_texture_offset(st);
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()) {
@@ -690,23 +688,47 @@ void TileMapEditor::_canvas_draw() {
rect=Rect2(from,r.get_size());
}
+ bool transp = transpose->is_pressed();
+ bool flip_h = mirror_x->is_pressed();
+ bool flip_v = mirror_y->is_pressed();
+
+ if (rect.size.y > rect.size.x) {
+ if ((flip_h && (flip_v || transp)) || (flip_v && !transp))
+ tile_ofs.y += rect.size.y - rect.size.x;
+ } else if (rect.size.y < rect.size.x) {
+ if ((flip_v && (flip_h || transp)) || (flip_h && !transp))
+ tile_ofs.x += rect.size.x - rect.size.y;
+ }
+
+ if (transp) {
+ SWAP(tile_ofs.x, tile_ofs.y);
+ }
+
+ if (flip_h) {
+ sc.x*=-1.0;
+ tile_ofs.x*=-1.0;
+ }
+ if (flip_v) {
+ sc.y*=-1.0;
+ tile_ofs.y*=-1.0;
+ }
if (node->get_tile_origin()==TileMap::TILE_ORIGIN_TOP_LEFT) {
- rect.pos+=ts->tile_get_texture_offset(st);
+ rect.pos+=tile_ofs;
} 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);
+ Vector2 center = (s/2) - tile_ofs;
- if (mirror_x->is_pressed())
+ if (flip_h)
rect.pos.x-=s.x-center.x;
else
rect.pos.x-=center.x;
- if (mirror_y->is_pressed())
+ if (flip_v)
rect.pos.y-=s.y-center.y;
else
rect.pos.y-=center.y;
@@ -717,10 +739,10 @@ void TileMapEditor::_canvas_draw() {
if (r==Rect2()) {
- canvas_item_editor->draw_texture_rect(t,rect,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),transp);
} else {
- canvas_item_editor->draw_texture_rect_region(t,rect,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),transp);
}
}
}
diff --git a/tools/editor/plugins/tile_map_editor_plugin.h b/tools/editor/plugins/tile_map_editor_plugin.h
index 74d1573d0f..3cbf5ff68d 100644
--- a/tools/editor/plugins/tile_map_editor_plugin.h
+++ b/tools/editor/plugins/tile_map_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/plugins/tile_set_editor_plugin.cpp b/tools/editor/plugins/tile_set_editor_plugin.cpp
index 09115472a8..06046b226a 100644
--- a/tools/editor/plugins/tile_set_editor_plugin.cpp
+++ b/tools/editor/plugins/tile_set_editor_plugin.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -145,10 +145,6 @@ void TileSetEditor::_menu_confirm() {
switch(option) {
- case MENU_OPTION_REMOVE_ITEM: {
-
- tileset->remove_tile(to_erase);
- } break;
case MENU_OPTION_MERGE_FROM_SCENE:
case MENU_OPTION_CREATE_FROM_SCENE: {
@@ -165,6 +161,27 @@ void TileSetEditor::_menu_confirm() {
}
}
+void TileSetEditor::_name_dialog_confirm(const String& name) {
+
+ switch (option) {
+
+ case MENU_OPTION_REMOVE_ITEM: {
+
+ int id=tileset->find_tile_by_name(name);
+
+ if (id<0 && name.is_valid_integer())
+ id=name.to_int();
+
+ if (tileset->has_tile(id)) {
+ tileset->remove_tile(id);
+ } else {
+ err_dialog->set_text("Could not find tile: " + name);
+ err_dialog->popup_centered(Size2(300, 60));
+ }
+ } break;
+ }
+}
+
void TileSetEditor::_menu_cbk(int p_option) {
option=p_option;
@@ -176,13 +193,9 @@ void TileSetEditor::_menu_cbk(int p_option) {
} break;
case MENU_OPTION_REMOVE_ITEM: {
- String p = editor->get_property_editor()->get_selected_path();
- if (p.begins_with("/TileSet") && p.get_slice_count("/")>=2) {
-
- to_erase = p.get_slice("/",2).to_int();
- cd->set_text("Remove Item "+itos(to_erase)+"?");
- cd->popup_centered(Size2(300,60));
- }
+ nd->set_title("Remove Item");
+ nd->set_text("Item name or ID:");
+ nd->popup_centered(Size2(300, 95));
} break;
case MENU_OPTION_CREATE_FROM_SCENE: {
@@ -210,6 +223,7 @@ void TileSetEditor::_bind_methods() {
ObjectTypeDB::bind_method("_menu_cbk",&TileSetEditor::_menu_cbk);
ObjectTypeDB::bind_method("_menu_confirm",&TileSetEditor::_menu_confirm);
+ ObjectTypeDB::bind_method("_name_dialog_confirm",&TileSetEditor::_name_dialog_confirm);
}
TileSetEditor::TileSetEditor(EditorNode *p_editor) {
@@ -222,7 +236,7 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) {
options->set_pos(Point2(1,1));
options->set_text("Theme");
options->get_popup()->add_item("Add Item",MENU_OPTION_ADD_ITEM);
- options->get_popup()->add_item("Remove Selected Item",MENU_OPTION_REMOVE_ITEM);
+ options->get_popup()->add_item("Remove Item",MENU_OPTION_REMOVE_ITEM);
options->get_popup()->add_separator();
options->get_popup()->add_item("Create from Scene",MENU_OPTION_CREATE_FROM_SCENE);
options->get_popup()->add_item("Merge from Scene",MENU_OPTION_MERGE_FROM_SCENE);
@@ -232,6 +246,15 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) {
add_child(cd);
cd->get_ok()->connect("pressed", this,"_menu_confirm");
+ nd = memnew(EditorNameDialog);
+ add_child(nd);
+ nd->set_hide_on_ok(true);
+ nd->get_line_edit()->set_margin(MARGIN_TOP,28);
+ nd->connect("name_confirmed", this,"_name_dialog_confirm");
+
+ err_dialog = memnew(AcceptDialog);
+ add_child(err_dialog);
+ err_dialog->set_title("Error");
}
void TileSetEditorPlugin::edit(Object *p_node) {
diff --git a/tools/editor/plugins/tile_set_editor_plugin.h b/tools/editor/plugins/tile_set_editor_plugin.h
index df82df6993..3f47520e2a 100644
--- a/tools/editor/plugins/tile_set_editor_plugin.h
+++ b/tools/editor/plugins/tile_set_editor_plugin.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,6 +33,7 @@
#include "scene/resources/tile_set.h"
#include "tools/editor/editor_node.h"
+#include "tools/editor/editor_name_dialog.h"
class TileSetEditor : public Control {
@@ -44,7 +45,8 @@ class TileSetEditor : public Control {
EditorNode *editor;
MenuButton *menu;
ConfirmationDialog *cd;
- int to_erase;
+ EditorNameDialog *nd;
+ AcceptDialog *err_dialog;
enum {
@@ -56,7 +58,8 @@ class TileSetEditor : public Control {
int option;
void _menu_cbk(int p_option);
- void _menu_confirm();
+ void _menu_confirm();
+ void _name_dialog_confirm(const String& name);
static void _import_scene(Node *p_scene, Ref<TileSet> p_library, bool p_merge);
diff --git a/tools/editor/progress_dialog.cpp b/tools/editor/progress_dialog.cpp
index c8b87486c0..d072ce7f83 100644
--- a/tools/editor/progress_dialog.cpp
+++ b/tools/editor/progress_dialog.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,7 +29,7 @@
#include "progress_dialog.h"
#include "main/main.h"
#include "message_queue.h"
-
+#include "os/os.h"
void BackgroundProgress::_add_task(const String& p_task,const String& p_label, int p_steps) {
@@ -191,10 +191,16 @@ void ProgressDialog::add_task(const String& p_task,const String& p_label,int p_s
}
-void ProgressDialog::task_step(const String& p_task, const String& p_state, int p_step){
+void ProgressDialog::task_step(const String& p_task, const String& p_state, int p_step,bool p_force_redraw){
ERR_FAIL_COND(!tasks.has(p_task));
+ if (!p_force_redraw) {
+ uint64_t tus = OS::get_singleton()->get_ticks_usec();
+ if (tus-last_progress_tick < 50000) //50ms
+ return;
+ }
+
Task &t=tasks[p_task];
if (p_step<0)
t.progress->set_val(t.progress->get_val()+1);
@@ -202,6 +208,7 @@ void ProgressDialog::task_step(const String& p_task, const String& p_state, int
t.progress->set_val(p_step);
t.state->set_text(p_state);
+ last_progress_tick=OS::get_singleton()->get_ticks_usec();
Main::iteration(); // this will not work on a lot of platforms, so it's only meant for the editor
}
@@ -229,4 +236,5 @@ ProgressDialog::ProgressDialog() {
add_child(main);
main->set_area_as_parent_rect();
set_exclusive(true);
+ last_progress_tick=0;
}
diff --git a/tools/editor/progress_dialog.h b/tools/editor/progress_dialog.h
index 7f1cc4cb2d..539eaa8737 100644
--- a/tools/editor/progress_dialog.h
+++ b/tools/editor/progress_dialog.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -84,6 +84,7 @@ class ProgressDialog : public Popup {
Map<String,Task> tasks;
VBoxContainer *main;
+ uint64_t last_progress_tick;
void _popup();
protected:
@@ -92,7 +93,7 @@ protected:
public:
void add_task(const String& p_task,const String& p_label, int p_steps);
- void task_step(const String& p_task,const String& p_state, int p_step=-1);
+ void task_step(const String& p_task, const String& p_state, int p_step=-1, bool p_force_redraw=true);
void end_task(const String& p_task);
diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp
index 3464b3c9bb..7690d31e7b 100644
--- a/tools/editor/project_export.cpp
+++ b/tools/editor/project_export.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -258,6 +258,7 @@ void ProjectExportDialog::_sample_convert_edited(int what) {
EditorImportExport::get_singleton()->sample_set_action( EditorImportExport::SampleAction(sample_mode->get_selected()));
EditorImportExport::get_singleton()->sample_set_max_hz( sample_max_hz->get_val() );
EditorImportExport::get_singleton()->sample_set_trim( sample_trim->is_pressed() );
+ _save_export_cfg();
}
@@ -297,6 +298,7 @@ void ProjectExportDialog::_notification(int p_what) {
// _rescan();
_update_platform();
export_mode->select( EditorImportExport::get_singleton()->get_export_filter() );
+ convert_text_scenes->set_pressed( EditorImportExport::get_singleton()->get_convert_text_scenes() );
filters->set_text( EditorImportExport::get_singleton()->get_export_custom_filter() );
if (EditorImportExport::get_singleton()->get_export_filter()!=EditorImportExport::EXPORT_SELECTED)
tree_vb->hide();
@@ -420,6 +422,8 @@ void ProjectExportDialog::_export_mode_changed(int p_idx) {
else
tree_vb->show();
+ EditorImportExport::get_singleton()->set_convert_text_scenes( convert_text_scenes->is_pressed() );
+
_save_export_cfg();
}
@@ -468,20 +472,32 @@ void ProjectExportDialog::_export_action_pck(const String& p_file) {
ERR_PRINT("Invalid platform for export of PCK");
return;
}
- FileAccess *f = FileAccess::open(p_file,FileAccess::WRITE);
- if (!f) {
- error->set_text("Error exporting project PCK! Can't write");
- error->popup_centered_minsize();
- }
- ERR_FAIL_COND(!f);
- Error err = exporter->save_pack(f,false);
- memdelete(f);
+ if (p_file.ends_with(".pck")) {
+ FileAccess *f = FileAccess::open(p_file,FileAccess::WRITE);
+ if (!f) {
+ error->set_text("Error exporting project PCK! Can't write");
+ error->popup_centered_minsize();
+ }
+ ERR_FAIL_COND(!f);
- if (err!=OK) {
- error->set_text("Error exporting project!");
- error->popup_centered_minsize();
- return;
+ Error err = exporter->save_pack(f,false);
+ memdelete(f);
+
+ if (err!=OK) {
+ error->set_text("Error exporting project!");
+ error->popup_centered_minsize();
+ return;
+ }
+ } else if (p_file.ends_with(".zip")) {
+
+ Error err = exporter->save_zip(p_file,false);
+
+ if (err!=OK) {
+ error->set_text("Error exporting project!");
+ error->popup_centered_minsize();
+ return;
+ }
}
}
@@ -1137,6 +1153,7 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) {
vb = memnew( VBoxContainer );
vb->set_name("Resources");
sections->add_child(vb);
+
export_mode = memnew( OptionButton );
export_mode->add_item("Export selected resources (including dependencies).");
export_mode->add_item("Export all resources in the project.");
@@ -1145,6 +1162,8 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) {
vb->add_margin_child("Export Mode:",export_mode);
+
+
tree_vb = memnew( VBoxContainer );
vb->add_child(tree_vb);
tree_vb->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -1165,6 +1184,10 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) {
vb->add_margin_child("Filters to export non-resource files (Comma Separated, ie: *.json, *.txt):",filters);
filters->connect("text_changed",this,"_filters_edited");
+ convert_text_scenes = memnew( CheckButton );
+ convert_text_scenes->set_text("Convert text scenes to binary on export");
+ vb->add_child(convert_text_scenes);
+ convert_text_scenes->connect("toggled",this,"_export_mode_changed");
image_vb = memnew( VBoxContainer );
image_vb->set_name("Images");
@@ -1385,7 +1408,7 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) {
add_child(confirm);
confirm->connect("confirmed",this,"_confirmed");
- get_ok()->set_text("Export PCK");
+ get_ok()->set_text("Export PCK/Zip");
expopt="--,Export,Bundle";
@@ -1415,6 +1438,7 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) {
pck_export->set_title("Export Project PCK");
pck_export->connect("file_selected", this,"_export_action_pck");
pck_export->add_filter("*.pck ; Data Pack");
+ pck_export->add_filter("*.zip ; Zip");
add_child(pck_export);
button_export = add_button("Export..",!OS::get_singleton()->get_swap_ok_cancel(),"export_pck");
diff --git a/tools/editor/project_export.h b/tools/editor/project_export.h
index 2f824e5ff7..5a42a58e58 100644
--- a/tools/editor/project_export.h
+++ b/tools/editor/project_export.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -108,6 +108,7 @@ private:
PropertyEditor *platform_options;
OptionButton *export_mode;
+ CheckButton *convert_text_scenes;
VBoxContainer *tree_vb;
VBoxContainer *image_vb;
diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp
index 04705017d2..589d9d3d99 100644
--- a/tools/editor/project_manager.cpp
+++ b/tools/editor/project_manager.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -348,6 +348,13 @@ struct ProjectItem {
_FORCE_INLINE_ bool operator ==(const ProjectItem& l) const { return project==l.project; }
};
+void ProjectManager::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ get_tree()->set_editor_hint(true);
+ }
+}
void ProjectManager::_panel_draw(Node *p_hb) {
@@ -825,6 +832,19 @@ ProjectManager::ProjectManager() {
FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files"));
set_area_as_parent_rect();
+
+ Ref<Theme> theme = Ref<Theme>( memnew( Theme ) );
+ set_theme(theme);
+ editor_register_icons(theme);
+
+ String global_font = EditorSettings::get_singleton()->get("global/font");
+ if (global_font!="") {
+ Ref<Font> fnt = ResourceLoader::load(global_font);
+ if (fnt.is_valid()) {
+ theme->set_default_theme_font(fnt);
+ }
+ }
+
Panel *panel = memnew( Panel );
add_child(panel);
panel->set_area_as_parent_rect();
@@ -944,7 +964,7 @@ ProjectManager::ProjectManager() {
String cp;
cp.push_back(0xA9);
cp.push_back(0);
- l->set_text(cp+" 2008-2015 Juan Linietsky, Ariel Manzur.");
+ l->set_text(cp+" 2008-2016 Juan Linietsky, Ariel Manzur.");
l->set_align(Label::ALIGN_CENTER);
vb->add_child(l);
@@ -972,10 +992,6 @@ ProjectManager::ProjectManager() {
npdialog = memnew( NewProjectDialog );
add_child(npdialog);
- Ref<Theme> theme = memnew( Theme );
- editor_register_icons(theme);
- set_theme(theme);
-
npdialog->connect("project_created", this,"_load_recent_projects");
_load_recent_projects();
diff --git a/tools/editor/project_manager.h b/tools/editor/project_manager.h
index 1e6ea9c1c9..80c34690f8 100644
--- a/tools/editor/project_manager.h
+++ b/tools/editor/project_manager.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -85,6 +85,7 @@ class ProjectManager : public Control {
protected:
+ void _notification(int p_what);
static void _bind_methods();
public:
ProjectManager();
diff --git a/tools/editor/project_settings.cpp b/tools/editor/project_settings.cpp
index 2fd8b37753..6c5e18ec9a 100644
--- a/tools/editor/project_settings.cpp
+++ b/tools/editor/project_settings.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,6 +33,7 @@
#include "editor_node.h"
#include "scene/gui/margin_container.h"
#include "translation.h"
+#include "global_constants.h"
ProjectSettings *ProjectSettings::singleton=NULL;
@@ -106,6 +107,8 @@ void ProjectSettings::_action_persist_toggle() {
String name="input/"+ti->get_text(0);
bool prev = Globals::get_singleton()->is_persisting(name);
+ print_line("prev persist: "+itos(prev));
+ print_line("new persist: "+itos(ti->is_checked(0)));
if (prev==ti->is_checked(0))
return;
@@ -155,12 +158,14 @@ void ProjectSettings::_device_input_add() {
} break;
case InputEvent::JOYSTICK_MOTION: {
- ie.joy_motion.axis = device_index->get_selected();
+ ie.joy_motion.axis = device_index->get_selected()>>1;
+ ie.joy_motion.axis_value = device_index->get_selected()&1?1:-1;
+
for(int i=0;i<arr.size();i++) {
InputEvent aie=arr[i];
- if (aie.device == ie.device && aie.type==InputEvent::JOYSTICK_MOTION && aie.joy_motion.axis==ie.joy_motion.axis) {
+ if (aie.device == ie.device && aie.type==InputEvent::JOYSTICK_MOTION && aie.joy_motion.axis==ie.joy_motion.axis && aie.joy_motion.axis_value==ie.joy_motion.axis_value) {
return;
}
}
@@ -294,9 +299,10 @@ void ProjectSettings::_add_item(int p_item){
device_id->set_val(0);
device_index_label->set_text("Joy Button Axis:");
device_index->clear();
- for(int i=0;i<8;i++) {
+ for(int i=0;i<24;i++) {
+
- device_index->add_item("Axis "+itos(i));
+ device_index->add_item("Axis "+itos(i/2)+" "+(i&1?"+":"-"));
}
device_input->popup_centered(Size2(350,95));
@@ -338,6 +344,15 @@ void ProjectSettings::_action_button_pressed(Object* p_obj, int p_column,int p_i
add_at="input/"+ti->get_text(0);
} else if (p_id==2) {
+ //rename
+
+ add_at="input/"+ti->get_text(0);
+ rename_action->popup_centered();
+ rename_action->get_line_edit()->set_text(ti->get_text(0));
+ rename_action->get_line_edit()->set_cursor_pos(ti->get_text(0).length());
+ rename_action->get_line_edit()->select_all();
+
+ } else if (p_id==3) {
//remove
if (ti->get_parent()==input_editor->get_root()) {
@@ -415,13 +430,16 @@ void ProjectSettings::_update_actions() {
continue;
TreeItem *item=input_editor->create_item(root);
- item->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ //item->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
item->set_text(0,name);
item->add_button(0,get_icon("Add","EditorIcons"),1);
- item->add_button(0,get_icon("Remove","EditorIcons"),2);
+ if (!Globals::get_singleton()->get_input_presets().find(pi.name)) {
+ item->add_button(0,get_icon("Rename","EditorIcons"),2);
+ item->add_button(0,get_icon("Remove","EditorIcons"),3);
+ }
item->set_custom_bg_color(0,get_color("prop_subsection","Editor"));
item->set_editable(0,true);
- item->set_checked(0,pi.usage&PROPERTY_USAGE_CHECKED);
+ //item->set_checked(0,pi.usage&PROPERTY_USAGE_CHECKED);
@@ -481,12 +499,12 @@ void ProjectSettings::_update_actions() {
} break;
case InputEvent::JOYSTICK_MOTION: {
- String str = "Device "+itos(ie.device)+", Axis "+itos(ie.joy_motion.axis)+".";
+ String str = "Device "+itos(ie.device)+", Axis "+itos(ie.joy_motion.axis)+" "+(ie.joy_motion.axis_value<0?"-.":"+.");
action->set_text(0,str);
action->set_icon(0,get_icon("JoyAxis","EditorIcons"));
} break;
}
- action->add_button(0,get_icon("Remove","EditorIcons"),2);
+ action->add_button(0,get_icon("Remove","EditorIcons"),3);
action->set_metadata(0,i);
}
}
@@ -507,12 +525,12 @@ void ProjectSettings::popup_project_settings() {
void ProjectSettings::_item_selected() {
- TreeItem *ti = globals_editor->get_scene_tree()->get_selected();
+ TreeItem *ti = globals_editor->get_property_editor()->get_scene_tree()->get_selected();
if (!ti)
return;
if (!ti->get_parent())
return;
- category->set_text(ti->get_parent()->get_text(0));
+ category->set_text(globals_editor->get_current_section());
property->set_text(ti->get_text(0));
popup_platform->set_disabled(false);
@@ -551,7 +569,8 @@ void ProjectSettings::_item_add() {
String name = catname+"/"+propname;
Globals::get_singleton()->set(name,value);
- globals_editor->update_tree();
+ globals_editor->edit(NULL);
+ globals_editor->edit(Globals::get_singleton());
}
void ProjectSettings::_item_del() {
@@ -563,7 +582,7 @@ void ProjectSettings::_item_del() {
String name = catname+"/"+propname;
Globals::get_singleton()->set(name,Variant());
- globals_editor->update_tree();
+ globals_editor->get_property_editor()->update_tree();
}
@@ -616,14 +635,57 @@ void ProjectSettings::_action_add() {
}
+void ProjectSettings::_action_rename(const String &p_name) {
+
+
+ if (p_name.find("/")!=-1 || p_name.find(":")!=-1 || p_name=="") {
+ message->set_text("Invalid Action (Anything goes but / or :).");
+ message->popup_centered(Size2(300,100));
+ return;
+ }
+
+ String new_name = "input/"+p_name;
+
+ if (Globals::get_singleton()->has(new_name)) {
+ message->set_text("Action '"+p_name+"' already exists!.");
+ message->popup_centered(Size2(300,100));
+ return;
+ }
+
+ int order = Globals::get_singleton()->get_order(add_at);
+ Array va = Globals::get_singleton()->get(add_at);
+ bool persisting = Globals::get_singleton()->is_persisting(add_at);
+
+ undo_redo->create_action("Rename Input Action Event");
+ undo_redo->add_do_method(Globals::get_singleton(),"clear",add_at);
+ undo_redo->add_do_method(Globals::get_singleton(),"set",new_name,va);
+ undo_redo->add_do_method(Globals::get_singleton(),"set_persisting",new_name,persisting);
+ undo_redo->add_do_method(Globals::get_singleton(),"set_order",new_name,order);
+ undo_redo->add_undo_method(Globals::get_singleton(),"clear",new_name);
+ undo_redo->add_undo_method(Globals::get_singleton(),"set",add_at,va);
+ undo_redo->add_undo_method(Globals::get_singleton(),"set_persisting",add_at,persisting);
+ undo_redo->add_undo_method(Globals::get_singleton(),"set_order",add_at,order);
+ undo_redo->add_do_method(this,"_update_actions");
+ undo_redo->add_undo_method(this,"_update_actions");
+ undo_redo->add_do_method(this,"_settings_changed");
+ undo_redo->add_undo_method(this,"_settings_changed");
+ undo_redo->commit_action();
+
+ rename_action->hide();
+}
+
void ProjectSettings::_item_checked(const String& p_item, bool p_check) {
undo_redo->create_action("Toggle Persisting");
- undo_redo->add_do_method(Globals::get_singleton(),"set_persisting",p_item,p_check);
- undo_redo->add_undo_method(Globals::get_singleton(),"set_persisting",p_item,!p_check);
+ String full_item = globals_editor->get_full_item_path(p_item);
+
+ undo_redo->add_do_method(Globals::get_singleton(),"set_persisting",full_item,p_check);
+ undo_redo->add_undo_method(Globals::get_singleton(),"set_persisting",full_item,!p_check);
undo_redo->add_do_method(this,"_settings_changed");
undo_redo->add_undo_method(this,"_settings_changed");
+ undo_redo->add_do_method(globals_editor->get_property_editor(),"update_tree");
+ undo_redo->add_undo_method(globals_editor->get_property_editor(),"update_tree");
undo_redo->commit_action();
}
@@ -640,11 +702,22 @@ void ProjectSettings::_save() {
void ProjectSettings::_settings_prop_edited(const String& p_name) {
- if (!Globals::get_singleton()->is_persisting(p_name)) {
+ String full_item = globals_editor->get_full_item_path(p_name);
+
+ if (!Globals::get_singleton()->is_persisting(full_item)) {
+ Globals::get_singleton()->set_persisting(full_item,true);
+
+ {
+ //small usability workaround, if anything related to resolution scaling or size is modified, change all of them together
+ if (full_item=="display/width" || full_item=="display/height" || full_item=="display/stretch_mode") {
+ Globals::get_singleton()->set_persisting("display/height",true);
+ Globals::get_singleton()->set_persisting("display/width",true);
+ }
+ }
+
- Globals::get_singleton()->set_persisting(p_name,true);
// globals_editor->update_property(p_name);
- globals_editor->update_tree();
+ globals_editor->get_property_editor()->update_tree();
}
_settings_changed();
}
@@ -679,7 +752,7 @@ void ProjectSettings::_copy_to_platform(int p_which) {
name = catname+"/"+propname;
Globals::get_singleton()->set(name,value);
- globals_editor->update_tree();
+ globals_editor->get_property_editor()->update_tree();
}
@@ -722,6 +795,11 @@ void ProjectSettings::_translation_file_open() {
void ProjectSettings::_autoload_file_callback(const String& p_path) {
autoload_add_path->set_text(p_path);
+ //if (autoload_add_name->get_text().strip_edges()==String()) {
+
+ autoload_add_name->set_text( p_path.get_file().basename() );
+ //}
+
//_translation_add(p_translation);
}
@@ -730,6 +808,40 @@ void ProjectSettings::_autoload_file_open() {
autoload_file_open->popup_centered_ratio();
}
+void ProjectSettings::_autoload_edited() {
+
+ if (updating_autoload)
+ return;
+
+ TreeItem *ti = autoload_list->get_edited();
+ if (!ti || autoload_list->get_edited_column()!=2)
+ return;
+
+ updating_autoload=true;
+ bool checked=ti->is_checked(2);
+
+ String base="autoload/"+ti->get_text(0);
+
+ String path = Globals::get_singleton()->get(base);
+
+ if (path.begins_with("*"))
+ path=path.substr(1,path.length());
+
+ if (checked)
+ path="*"+path;
+
+ undo_redo->create_action("Toggle Autoload GlobalVar");
+ undo_redo->add_do_property(Globals::get_singleton(),base,path);
+ undo_redo->add_undo_property(Globals::get_singleton(),base,Globals::get_singleton()->get(base));
+ undo_redo->add_do_method(this,"_update_autoload");
+ undo_redo->add_undo_method(this,"_update_autoload");
+ undo_redo->add_do_method(this,"_settings_changed");
+ undo_redo->add_undo_method(this,"_settings_changed");
+ undo_redo->commit_action();
+ updating_autoload=false;
+
+}
+
void ProjectSettings::_autoload_add() {
String name = autoload_add_name->get_text();
@@ -740,6 +852,35 @@ void ProjectSettings::_autoload_add() {
}
+ if (ObjectTypeDB::type_exists(name)) {
+
+ message->set_text("Invalid Name.Must not collide with an existing engine class name.");
+ message->popup_centered(Size2(300,100));
+ return;
+
+ }
+
+ for(int i=0;i<Variant::VARIANT_MAX;i++) {
+ if (Variant::get_type_name(Variant::Type(i))==name) {
+
+ message->set_text("Invalid Name.Must not collide with an existing buit-in type name.");
+ message->popup_centered(Size2(300,100));
+ return;
+
+ }
+ }
+
+ for(int i=0;i<GlobalConstants::get_global_constant_count();i++) {
+
+ if (GlobalConstants::get_global_constant_name(i)==name) {
+
+ message->set_text("Invalid Name.Must not collide with an existing global constant name.");
+ message->popup_centered(Size2(300,100));
+ return;
+ }
+
+ }
+
String path = autoload_add_path->get_text();
if (!FileAccess::exists(path)) {
message->set_text("Invalid Path.\nFile does not exist.");
@@ -756,7 +897,7 @@ void ProjectSettings::_autoload_add() {
undo_redo->create_action("Add Autoload");
name = "autoload/"+name;
- undo_redo->add_do_property(Globals::get_singleton(),name,path);
+ undo_redo->add_do_property(Globals::get_singleton(),name,"*"+path);
if (Globals::get_singleton()->has(name))
undo_redo->add_undo_property(Globals::get_singleton(),name,Globals::get_singleton()->get(name));
else
@@ -769,6 +910,9 @@ void ProjectSettings::_autoload_add() {
undo_redo->add_undo_method(this,"_settings_changed");
undo_redo->commit_action();
+ autoload_add_path->set_text("");
+ autoload_add_name->set_text("");
+
//autoload_file_open->popup_centered_ratio();
}
@@ -803,11 +947,14 @@ void ProjectSettings::_autoload_delete(Object *p_item,int p_column, int p_button
String swap_name= "autoload/"+swap->get_text(0);
+ int order = Globals::get_singleton()->get_order(name);
+ int swap_order = Globals::get_singleton()->get_order(swap_name);
+
undo_redo->create_action("Move Autoload");
- undo_redo->add_do_method(Globals::get_singleton(),"set_order",swap_name,Globals::get_singleton()->get_order(name));
- undo_redo->add_do_method(Globals::get_singleton(),"set_order",name,Globals::get_singleton()->get_order(swap_name));
- undo_redo->add_undo_method(Globals::get_singleton(),"set_order",swap_name,Globals::get_singleton()->get_order(swap_name));
- undo_redo->add_undo_method(Globals::get_singleton(),"set_order",name,Globals::get_singleton()->get_order(name));
+ undo_redo->add_do_method(Globals::get_singleton(),"set_order",swap_name,order);
+ undo_redo->add_do_method(Globals::get_singleton(),"set_order",name,swap_order);
+ undo_redo->add_undo_method(Globals::get_singleton(),"set_order",swap_name,swap_order);
+ undo_redo->add_undo_method(Globals::get_singleton(),"set_order",name,order);
undo_redo->add_do_method(this,"_update_autoload");
undo_redo->add_undo_method(this,"_update_autoload");
undo_redo->add_do_method(this,"_settings_changed");
@@ -1146,6 +1293,11 @@ void ProjectSettings::_update_translations() {
void ProjectSettings::_update_autoload() {
+ if (updating_autoload)
+ return;
+
+ updating_autoload=true;
+
autoload_list->clear();
TreeItem *root = autoload_list->create_item();
autoload_list->set_hide_root(true);
@@ -1160,23 +1312,36 @@ void ProjectSettings::_update_autoload() {
continue;
String name = pi.name.get_slice("/",1);
+ String path = Globals::get_singleton()->get(pi.name);
+
if (name=="")
continue;
-
+ bool global=false;
+ if (path.begins_with("*")) {
+ path=path.substr(1,path.length());
+ global=true;
+ }
TreeItem *t = autoload_list->create_item(root);
t->set_text(0,name);
- t->set_text(1,Globals::get_singleton()->get(pi.name));
- t->add_button(1,get_icon("MoveUp","EditorIcons"),1);
- t->add_button(1,get_icon("MoveDown","EditorIcons"),2);
- t->add_button(1,get_icon("Del","EditorIcons"),0);
+ t->set_text(1,path);
+ t->set_cell_mode(2,TreeItem::CELL_MODE_CHECK);
+ t->set_editable(2,true);
+ t->set_text(2,"Enable");
+ t->set_checked(2,global);
+ t->add_button(3,get_icon("MoveUp","EditorIcons"),1);
+ t->add_button(3,get_icon("MoveDown","EditorIcons"),2);
+ t->add_button(3,get_icon("Del","EditorIcons"),0);
+
}
+ updating_autoload=false;
+
}
void ProjectSettings::_toggle_search_bar(bool p_pressed) {
- globals_editor->set_use_filter(p_pressed);
+ globals_editor->get_property_editor()->set_use_filter(p_pressed);
if (p_pressed) {
@@ -1197,7 +1362,7 @@ void ProjectSettings::_clear_search_box() {
return;
search_box->clear();
- globals_editor->update_tree();
+ globals_editor->get_property_editor()->update_tree();
}
void ProjectSettings::_bind_methods() {
@@ -1212,6 +1377,7 @@ void ProjectSettings::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_action_adds"),&ProjectSettings::_action_adds);
ObjectTypeDB::bind_method(_MD("_action_persist_toggle"),&ProjectSettings::_action_persist_toggle);
ObjectTypeDB::bind_method(_MD("_action_button_pressed"),&ProjectSettings::_action_button_pressed);
+ ObjectTypeDB::bind_method(_MD("_action_rename"),&ProjectSettings::_action_rename);
ObjectTypeDB::bind_method(_MD("_update_actions"),&ProjectSettings::_update_actions);
ObjectTypeDB::bind_method(_MD("_wait_for_key"),&ProjectSettings::_wait_for_key);
ObjectTypeDB::bind_method(_MD("_add_item"),&ProjectSettings::_add_item);
@@ -1239,6 +1405,7 @@ void ProjectSettings::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_autoload_file_callback"),&ProjectSettings::_autoload_file_callback);
ObjectTypeDB::bind_method(_MD("_update_autoload"),&ProjectSettings::_update_autoload);
ObjectTypeDB::bind_method(_MD("_autoload_delete"),&ProjectSettings::_autoload_delete);
+ ObjectTypeDB::bind_method(_MD("_autoload_edited"),&ProjectSettings::_autoload_edited);
ObjectTypeDB::bind_method(_MD("_clear_search_box"),&ProjectSettings::_clear_search_box);
ObjectTypeDB::bind_method(_MD("_toggle_search_bar"),&ProjectSettings::_toggle_search_bar);
@@ -1339,15 +1506,15 @@ ProjectSettings::ProjectSettings(EditorData *p_data) {
search_bar->add_child(clear_button);
clear_button->connect("pressed",this,"_clear_search_box");
- globals_editor = memnew( PropertyEditor );
+ globals_editor = memnew( SectionedPropertyEditor );
props_base->add_child(globals_editor);
- globals_editor->hide_top_label();
+ //globals_editor->hide_top_label();
globals_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- globals_editor->register_text_enter(search_box);
- globals_editor->set_capitalize_paths(false);
- globals_editor->get_scene_tree()->connect("cell_selected",this,"_item_selected");
- globals_editor->connect("property_toggled",this,"_item_checked");
- globals_editor->connect("property_edited",this,"_settings_prop_edited");
+ globals_editor->get_property_editor()->register_text_enter(search_box);
+ globals_editor->get_property_editor()->set_capitalize_paths(false);
+ globals_editor->get_property_editor()->get_scene_tree()->connect("cell_selected",this,"_item_selected");
+ globals_editor->get_property_editor()->connect("property_toggled",this,"_item_checked",varray(),CONNECT_DEFERRED);
+ globals_editor->get_property_editor()->connect("property_edited",this,"_settings_prop_edited");
/*
Button *save = memnew( Button );
@@ -1431,12 +1598,17 @@ ProjectSettings::ProjectSettings(EditorData *p_data) {
add_child(popup_add);
popup_add->connect("item_pressed",this,"_add_item");
+ rename_action = memnew( EditorNameDialog );
+ add_child(rename_action);
+ rename_action->set_hide_on_ok(false);
+ rename_action->set_size(Size2(200, 70));
+ rename_action->set_title("Rename Input Action");
+ rename_action->connect("name_confirmed", this,"_action_rename");
+
press_a_key = memnew( ConfirmationDialog );
press_a_key->set_focus_mode(FOCUS_ALL);
add_child(press_a_key);
-
-
l = memnew( Label );
l->set_text("Press a Key..");
l->set_area_as_parent_rect();
@@ -1589,11 +1761,6 @@ ProjectSettings::ProjectSettings(EditorData *p_data) {
HBoxContainer *ahb = memnew( HBoxContainer);
avb->add_child(ahb);
- VBoxContainer *avb_name = memnew( VBoxContainer );
- avb_name->set_h_size_flags(SIZE_EXPAND_FILL);
- autoload_add_name = memnew(LineEdit);
- avb_name->add_margin_child("Node Name:",autoload_add_name);
- ahb->add_child(avb_name);
VBoxContainer *avb_path = memnew( VBoxContainer );
avb_path->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -1604,13 +1771,24 @@ ProjectSettings::ProjectSettings(EditorData *p_data) {
Button *browseaa = memnew( Button("..") );
ahb_path->add_child(browseaa);
browseaa->connect("pressed",this,"_autoload_file_open");
- Button *addaa = memnew( Button("Add") );
- ahb_path->add_child(addaa);
- addaa->connect("pressed",this,"_autoload_add");
avb_path->add_margin_child("Path:",ahb_path);
ahb->add_child(avb_path);
+ VBoxContainer *avb_name = memnew( VBoxContainer );
+ avb_name->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ HBoxContainer *ahb_name = memnew( HBoxContainer );
+ autoload_add_name = memnew(LineEdit);
+ autoload_add_name->set_h_size_flags(SIZE_EXPAND_FILL);
+ ahb_name->add_child(autoload_add_name);
+ avb_name->add_margin_child("Node Name:",ahb_name);
+ Button *addaa = memnew( Button("Add") );
+ ahb_name->add_child(addaa);
+ addaa->connect("pressed",this,"_autoload_add");
+
+ ahb->add_child(avb_name);
+
autoload_list = memnew( Tree );
autoload_list->set_v_size_flags(SIZE_EXPAND_FILL);
avb->add_margin_child("List:",autoload_list,true);
@@ -1620,11 +1798,24 @@ ProjectSettings::ProjectSettings(EditorData *p_data) {
autoload_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
autoload_file_open->connect("file_selected",this,"_autoload_file_callback");
- autoload_list->set_columns(2);
+ autoload_list->set_columns(4);
autoload_list->set_column_titles_visible(true);
- autoload_list->set_column_title(0,"name");
- autoload_list->set_column_title(1,"path");
+ autoload_list->set_column_title(0,"Name");
+ autoload_list->set_column_expand(0,true);
+ autoload_list->set_column_min_width(0,100);
+ autoload_list->set_column_title(1,"Path");
+ autoload_list->set_column_expand(1,true);
+ autoload_list->set_column_min_width(1,100);
+ autoload_list->set_column_title(2,"Singleton");
+ autoload_list->set_column_expand(2,false);
+ autoload_list->set_column_min_width(2,80);
+ autoload_list->set_column_expand(3,false);
+ autoload_list->set_column_min_width(3,80);
+
autoload_list->connect("button_pressed",this,"_autoload_delete");
+ autoload_list->connect("item_edited",this,"_autoload_edited");
+
+ updating_autoload=false;
}
diff --git a/tools/editor/project_settings.h b/tools/editor/project_settings.h
index b122609e52..b689340fdf 100644
--- a/tools/editor/project_settings.h
+++ b/tools/editor/project_settings.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,6 +34,7 @@
#include "optimized_save_dialog.h"
#include "undo_redo.h"
#include "editor_data.h"
+#include "editor_name_dialog.h"
//#include "project_export_settings.h"
class ProjectSettings : public AcceptDialog {
@@ -45,7 +46,7 @@ class ProjectSettings : public AcceptDialog {
EditorData *data;
UndoRedo *undo_redo;
- PropertyEditor *globals_editor;
+ SectionedPropertyEditor *globals_editor;
HBoxContainer *search_bar;
ToolButton *search_button;
@@ -66,6 +67,8 @@ class ProjectSettings : public AcceptDialog {
Label *device_index_label;
MenuButton *popup_platform;
+ EditorNameDialog *rename_action;
+
LineEdit *action_name;
Tree *input_editor;
bool setting;
@@ -92,8 +95,10 @@ class ProjectSettings : public AcceptDialog {
void _update_autoload();
void _autoload_file_callback(const String& p_path);
void _autoload_add();
+ void _autoload_edited();
void _autoload_file_open();
void _autoload_delete(Object *p_item,int p_column, int p_button);
+ bool updating_autoload;
void _item_selected();
@@ -106,6 +111,7 @@ class ProjectSettings : public AcceptDialog {
void _action_adds(String);
void _action_add();
+ void _action_rename(const String& p_name);
void _device_input_add();
void _item_checked(const String& p_item, bool p_check);
diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp
index 0fe3dee2ea..4b1b93ea6e 100644
--- a/tools/editor/property_editor.cpp
+++ b/tools/editor/property_editor.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -89,13 +89,23 @@ void CustomPropertyEditor::_menu_option(int p_which) {
case OBJ_MENU_LOAD: {
file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- List<String> extensions;
String type=(hint==PROPERTY_HINT_RESOURCE_TYPE)?hint_text:String();
- ResourceLoader::get_recognized_extensions_for_type(type,&extensions);
- file->clear_filters();
+ List<String> extensions;
+ for (int i=0;i<type.get_slice_count(",");i++) {
+
+ ResourceLoader::get_recognized_extensions_for_type(type.get_slice(",",i),&extensions);
+ }
+
+ Set<String> valid_extensions;
for (List<String>::Element *E=extensions.front();E;E=E->next()) {
+ valid_extensions.insert(E->get());
+ }
+
+ file->clear_filters();
+ for (Set<String>::Element *E=valid_extensions.front();E;E=E->next()) {
+
file->add_filter("*."+E->get()+" ; "+E->get().to_upper() );
}
@@ -585,7 +595,7 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty
color_picker->show();
color_picker->set_edit_alpha(hint!=PROPERTY_HINT_COLOR_NO_ALPHA);
color_picker->set_color(v);
- set_size( Size2(350, color_picker->get_combined_minimum_size().height+10));
+ set_size( Size2(300, color_picker->get_combined_minimum_size().height+10));
/*
int ofs=80;
int m=10;
@@ -717,7 +727,17 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty
RES cb=EditorSettings::get_singleton()->get_resource_clipboard();
- bool paste_valid=cb.is_valid() && (hint_text=="" || ObjectTypeDB::is_type(cb->get_type(),hint_text));
+ bool paste_valid=false;
+ if (cb.is_valid()) {
+ if (hint_text=="")
+ paste_valid=true;
+ else
+ for (int i = 0; i < hint_text.get_slice_count(",");i++)
+ if (ObjectTypeDB::is_type(cb->get_type(),hint_text.get_slice(",",i))) {
+ paste_valid=true;
+ break;
+ }
+ }
if (!RES(v).is_null() || paste_valid) {
menu->add_separator();
@@ -905,19 +925,31 @@ void CustomPropertyEditor::_color_changed(const Color& p_color) {
void CustomPropertyEditor::_node_path_selected(NodePath p_path) {
- if (owner && owner->is_type("Node")) {
+ if (owner) {
+
+ Node *node=NULL;
+
+ if (owner->is_type("Node"))
+ node = owner->cast_to<Node>();
+ else if (owner->is_type("ArrayPropertyEdit"))
+ node = owner->cast_to<ArrayPropertyEdit>()->get_node();
+
+ if (!node) {
+ v=p_path;
+ emit_signal("variant_changed");
+ call_deferred("hide"); //to not mess with dialogs
+ return;
+ }
- Node *node = owner->cast_to<Node>();
Node *tonode=node->get_node(p_path);
if (tonode) {
-
p_path=node->get_path_to(tonode);
}
-
}
v=p_path;
emit_signal("variant_changed");
+ call_deferred("hide"); //to not mess with dialogs
}
@@ -1020,6 +1052,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
v=NodePath();
emit_signal("variant_changed");
+ hide();
}
} break;
case Variant::OBJECT: {
@@ -2012,7 +2045,7 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p
if (img.empty())
p_item->set_text(1,"[Image (empty)]");
else
- p_item->set_text(1,"[Image "+itos(img.get_width())+"x"+itos(img.get_height())+"]");
+ p_item->set_text(1,"[Image "+itos(img.get_width())+"x"+itos(img.get_height())+"-"+String(Image::get_format_name(img.get_format()))+"]");
} break;
case Variant::NODE_PATH: {
@@ -2090,6 +2123,65 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p
}
+void PropertyEditor::_check_reload_status(const String&p_name, TreeItem* item) {
+
+ bool has_reload=false;
+ int found=-1;
+
+ for(int i=0;i<item->get_button_count(1);i++) {
+
+ if (item->get_button_id(1,i)==3) {
+ found=i;
+ break;
+ }
+ }
+
+ if (_might_be_in_instance()) {
+
+
+ Variant vorig;
+ Dictionary d=item->get_metadata(0);
+ int usage = d.has("usage")?int(int(d["usage"])&(PROPERTY_USAGE_STORE_IF_NONONE|PROPERTY_USAGE_STORE_IF_NONZERO)):0;
+
+
+ if (_get_instanced_node_original_property(p_name,vorig) || usage) {
+ Variant v = obj->get(p_name);
+
+ bool changed = _is_property_different(v,vorig,usage);
+
+ if ((found!=-1)!=changed) {
+
+ if (changed) {
+
+ has_reload=true;
+ } else {
+
+ }
+
+ }
+
+ }
+
+
+
+ }
+
+ if (!has_reload && !obj->get_script().is_null()) {
+ Ref<Script> scr = obj->get_script();
+ Variant orig_value;
+ if (scr->get_property_default_value(p_name,orig_value)) {
+ if (orig_value!=obj->get(p_name)) {
+ has_reload=true;
+ }
+ }
+ }
+
+ if (found!=-1 && !has_reload) {
+ item->erase_button(1,found);
+ } else if (found==-1 && has_reload) {
+ item->add_button(1,get_icon("Reload","EditorIcons"),3);
+ }
+}
void PropertyEditor::_notification(int p_what) {
@@ -2131,43 +2223,8 @@ void PropertyEditor::_notification(int p_what) {
if (!item)
continue;
- if (_might_be_in_instance()) {
-
-
- Variant vorig;
- Dictionary d=item->get_metadata(0);
- int usage = d.has("usage")?int(int(d["usage"])&(PROPERTY_USAGE_STORE_IF_NONONE|PROPERTY_USAGE_STORE_IF_NONZERO)):0;
-
-
- if (_get_instanced_node_original_property(*k,vorig) || usage) {
- Variant v = obj->get(*k);
-
- int found=-1;
- for(int i=0;i<item->get_button_count(1);i++) {
-
- if (item->get_button_id(1,i)==3) {
- found=i;
- break;
- }
- }
-
- bool changed = _is_property_different(v,vorig,usage);
-
- if ((found!=-1)!=changed) {
-
- if (changed) {
+ _check_reload_status(*k,item);
- item->add_button(1,get_icon("Reload","EditorIcons"),3);
- } else {
-
- item->erase_button(1,found);
- }
-
- }
-
- }
-
- }
Dictionary d=item->get_metadata(0);
set_item_text(item,d["type"],d["name"],d["hint"],d["hint_text"]);
}
@@ -2207,9 +2264,9 @@ TreeItem *PropertyEditor::get_parent_node(String p_path,HashMap<String,TreeItem*
}
item->set_editable(0,false);
- item->set_selectable(0,false);
+ item->set_selectable(0,subsection_selectable);
item->set_editable(1,false);
- item->set_selectable(1,false);
+ item->set_selectable(1,subsection_selectable);
if (item->get_parent()==root) {
@@ -2234,23 +2291,30 @@ void PropertyEditor::_refresh_item(TreeItem *p_item) {
if (name!=String()) {
+
+ _check_reload_status(name,p_item);
+#if 0
+ bool has_reload=false;
+
+ int found=-1;
+ for(int i=0;i<p_item->get_button_count(1);i++) {
+
+ if (p_item->get_button_id(1,i)==3) {
+ found=i;
+ break;
+ }
+ }
+
if (_might_be_in_instance()) {
Variant vorig;
Dictionary d=p_item->get_metadata(0);
int usage = d.has("usage")?int(int(d["usage"])&(PROPERTY_USAGE_STORE_IF_NONONE|PROPERTY_USAGE_STORE_IF_NONZERO)):0;
+
if (_get_instanced_node_original_property(name,vorig) || usage) {
Variant v = obj->get(name);
- int found=-1;
- for(int i=0;i<p_item->get_button_count(1);i++) {
-
- if (p_item->get_button_id(1,i)==3) {
- found=i;
- break;
- }
- }
bool changed = _is_property_different(v,vorig,usage);
@@ -2258,10 +2322,11 @@ void PropertyEditor::_refresh_item(TreeItem *p_item) {
if (changed) {
- p_item->add_button(1,get_icon("Reload","EditorIcons"),3);
+ has_reload=true;
+
} else {
- p_item->erase_button(1,found);
+ //p_item->erase_button(1,found);
}
}
@@ -2270,6 +2335,22 @@ void PropertyEditor::_refresh_item(TreeItem *p_item) {
}
+ if (!has_reload && !obj->get_script().is_null()) {
+ Ref<Script> scr = obj->get_script();
+ Variant orig_value;
+ if (scr->get_property_default_value(name,orig_value)) {
+ if (orig_value!=obj->get(name)) {
+ has_reload=true;
+ }
+ }
+ }
+
+ if (!has_reload && found!=-1) {
+ p_item->erase_button(1,found);
+ } else if (has_reload && found==-1) {
+ p_item->add_button(1,get_icon("Reload","EditorIcons"),3);
+ }
+#endif
Dictionary d=p_item->get_metadata(0);
set_item_text(p_item,d["type"],d["name"],d["hint"],d["hint_text"]);
}
@@ -2549,7 +2630,8 @@ void PropertyEditor::update_tree() {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CHECK );
item->set_text(1,"On");
item->set_checked( 1, obj->get( p.name ) );
- item->set_icon( 0, get_icon("Bool","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("Bool","EditorIcons") );
item->set_editable(1,!read_only);
} break;
@@ -2561,7 +2643,8 @@ void PropertyEditor::update_tree() {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->set_text(1, String::num(obj->get( p.name ),2) );
item->set_editable(1,!read_only);
- item->set_icon( 0, get_icon("Curve","EditorIcons"));
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("Curve","EditorIcons"));
break;
@@ -2631,7 +2714,8 @@ void PropertyEditor::update_tree() {
// int c = p.hint_string.get_slice_count(",");
item->set_text(1,p.hint_string);
- item->set_icon( 0,get_icon("Enum","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Enum","EditorIcons") );
item->set_range(1, obj->get( p.name ) );
item->set_editable(1,!read_only);
break;
@@ -2647,11 +2731,13 @@ void PropertyEditor::update_tree() {
};
if (p.type==Variant::REAL) {
- item->set_icon( 0, get_icon("Real","EditorIcons"));
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("Real","EditorIcons"));
item->set_range(1, obj->get( p.name ) );
} else {
- item->set_icon( 0,get_icon("Integer","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Integer","EditorIcons") );
item->set_range(1, obj->get( p.name ) );
}
@@ -2671,7 +2757,8 @@ void PropertyEditor::update_tree() {
item->set_cell_mode( 1, TreeItem::CELL_MODE_STRING );
item->set_editable(1,!read_only);
- item->set_icon( 0, get_icon("File","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("File","EditorIcons") );
item->set_text(1,obj->get(p.name));
item->add_button(1,get_icon("Folder","EditorIcons"));
@@ -2691,7 +2778,8 @@ void PropertyEditor::update_tree() {
item->set_text(1, p.hint_string);
item->set_range(1,idx);
item->set_editable( 1, !read_only );
- item->set_icon( 0,get_icon("Enum","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Enum","EditorIcons") );
} break;
@@ -2699,7 +2787,8 @@ void PropertyEditor::update_tree() {
item->set_cell_mode( 1, TreeItem::CELL_MODE_STRING );
item->set_editable(1,!read_only);
- item->set_icon( 0, get_icon("String","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("String","EditorIcons") );
item->set_text(1,obj->get(p.name));
if (p.hint==PROPERTY_HINT_MULTILINE_TEXT)
item->add_button(1,get_icon("MultiLine","EditorIcons") );
@@ -2719,7 +2808,8 @@ void PropertyEditor::update_tree() {
item->set_text(1,"Array["+itos(v.call("size"))+"]");
else
item->set_text(1,"Array[]");
- item->set_icon( 0, get_icon("ArrayData","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("ArrayData","EditorIcons") );
} break;
@@ -2734,7 +2824,8 @@ void PropertyEditor::update_tree() {
item->set_text(1,"IntArray["+itos(v.call("size"))+"]");
else
item->set_text(1,"IntArray[]");
- item->set_icon( 0, get_icon("ArrayInt","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("ArrayInt","EditorIcons") );
} break;
@@ -2748,7 +2839,8 @@ void PropertyEditor::update_tree() {
item->set_text(1,"FloatArray["+itos(v.call("size"))+"]");
else
item->set_text(1,"FloatArray[]");
- item->set_icon( 0, get_icon("ArrayReal","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("ArrayReal","EditorIcons") );
} break;
@@ -2762,7 +2854,8 @@ void PropertyEditor::update_tree() {
item->set_text(1,"String["+itos(v.call("size"))+"]");
else
item->set_text(1,"String[]");
- item->set_icon( 0, get_icon("ArrayString","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("ArrayString","EditorIcons") );
} break;
@@ -2776,7 +2869,8 @@ void PropertyEditor::update_tree() {
item->set_text(1,"Byte["+itos(v.call("size"))+"]");
else
item->set_text(1,"Byte[]");
- item->set_icon( 0, get_icon("ArrayData","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("ArrayData","EditorIcons") );
} break;
@@ -2790,7 +2884,8 @@ void PropertyEditor::update_tree() {
item->set_text(1,"Vector2["+itos(v.call("size"))+"]");
else
item->set_text(1,"Vector2[]");
- item->set_icon( 0, get_icon("Vector2","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("Vector2","EditorIcons") );
} break;
@@ -2804,7 +2899,8 @@ void PropertyEditor::update_tree() {
item->set_text(1,"Vector3["+itos(v.call("size"))+"]");
else
item->set_text(1,"Vector3[]");
- item->set_icon( 0, get_icon("Vector","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("Vector","EditorIcons") );
} break;
@@ -2818,7 +2914,8 @@ void PropertyEditor::update_tree() {
item->set_text(1,"Color["+itos(v.call("size"))+"]");
else
item->set_text(1,"Color[]");
- item->set_icon( 0, get_icon("Color","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("Color","EditorIcons") );
} break;
@@ -2827,7 +2924,8 @@ void PropertyEditor::update_tree() {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->set_editable( 1, true );
item->set_text(1,obj->get(p.name));
- item->set_icon( 0,get_icon("Vector2","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Vector2","EditorIcons") );
} break;
case Variant::RECT2: {
@@ -2835,7 +2933,8 @@ void PropertyEditor::update_tree() {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->set_editable( 1, true );
item->set_text(1,obj->get(p.name));
- item->set_icon( 0,get_icon("Rect2","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Rect2","EditorIcons") );
} break;
case Variant::VECTOR3: {
@@ -2843,7 +2942,8 @@ void PropertyEditor::update_tree() {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->set_editable( 1, true );
item->set_text(1,obj->get(p.name));
- item->set_icon( 0,get_icon("Vector","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Vector","EditorIcons") );
} break;
case Variant::MATRIX32:
@@ -2858,7 +2958,8 @@ void PropertyEditor::update_tree() {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->set_editable( 1, true );
item->set_text(1,obj->get(p.name));
- item->set_icon( 0,get_icon("Matrix","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Matrix","EditorIcons") );
} break;
case Variant::PLANE: {
@@ -2866,7 +2967,8 @@ void PropertyEditor::update_tree() {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->set_editable( 1, true );
item->set_text(1,obj->get(p.name));
- item->set_icon( 0,get_icon("Plane","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Plane","EditorIcons") );
} break;
case Variant::_AABB: {
@@ -2874,7 +2976,8 @@ void PropertyEditor::update_tree() {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->set_editable( 1, true );
item->set_text(1,"AABB");
- item->set_icon( 0,get_icon("Rect3","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Rect3","EditorIcons") );
} break;
case Variant::QUAT: {
@@ -2882,7 +2985,8 @@ void PropertyEditor::update_tree() {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->set_editable( 1, true );
item->set_text(1,obj->get(p.name));
- item->set_icon( 0,get_icon("Quat","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Quat","EditorIcons") );
} break;
case Variant::COLOR: {
@@ -2891,7 +2995,8 @@ void PropertyEditor::update_tree() {
item->set_editable( 1, !read_only );
// item->set_text(1,obj->get(p.name));
item->set_custom_bg_color(1,obj->get(p.name));
- item->set_icon( 0,get_icon("Color","EditorIcons") );
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Color","EditorIcons") );
} break;
case Variant::IMAGE: {
@@ -2902,8 +3007,9 @@ void PropertyEditor::update_tree() {
if (img.empty())
item->set_text(1,"[Image (empty)]");
else
- item->set_text(1,"[Image "+itos(img.get_width())+"x"+itos(img.get_height())+"]");
- item->set_icon( 0,get_icon("Image","EditorIcons") );
+ item->set_text(1,"[Image "+itos(img.get_width())+"x"+itos(img.get_height())+"-"+String(Image::get_format_name(img.get_format()))+"]");
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Image","EditorIcons") );
} break;
case Variant::NODE_PATH: {
@@ -2985,6 +3091,7 @@ void PropertyEditor::update_tree() {
}
}
+ bool has_reload=false;
if (_might_be_in_instance()) {
Variant vorig;
@@ -2992,16 +3099,29 @@ void PropertyEditor::update_tree() {
int usage = d.has("usage")?int(int(d["usage"])&(PROPERTY_USAGE_STORE_IF_NONONE|PROPERTY_USAGE_STORE_IF_NONZERO)):0;
if (_get_instanced_node_original_property(p.name,vorig) || usage) {
Variant v = obj->get(p.name);
-
+
if (_is_property_different(v,vorig,usage)) {
//print_line("FOR "+String(p.name)+" RELOAD WITH: "+String(v)+"("+Variant::get_type_name(v.get_type())+")=="+String(vorig)+"("+Variant::get_type_name(vorig.get_type())+")");
item->add_button(1,get_icon("Reload","EditorIcons"),3);
+ has_reload=true;
}
}
}
+ if (!has_reload && !obj->get_script().is_null()) {
+ Ref<Script> scr = obj->get_script();
+ Variant orig_value;
+ if (scr->get_property_default_value(p.name,orig_value)) {
+ if (orig_value!=obj->get(p.name)) {
+ item->add_button(1,get_icon("Reload","EditorIcons"),3);
+ }
+ }
+ }
+
+
+
}
}
@@ -3292,8 +3412,6 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) {
call_deferred("_set_range_def",ti,prop,ti->get_range(p_column)+1.0);
} else if (p_button==3) {
- if (!_might_be_in_instance())
- return;
if (!d.has("name"))
return;
@@ -3301,11 +3419,21 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) {
Variant vorig;
- if (_get_instanced_node_original_property(prop,vorig)) {
+ if (_might_be_in_instance() && _get_instanced_node_original_property(prop,vorig)) {
_edit_set(prop,vorig);
+ return;
}
+ if (!obj->get_script().is_null()) {
+ Ref<Script> scr = obj->get_script();
+ Variant orig_value;
+ if (scr->get_property_default_value(prop,orig_value)) {
+ _edit_set(prop,orig_value);
+ }
+ }
+
+
} else {
Dictionary d = ti->get_metadata(0);
@@ -3441,6 +3569,7 @@ void PropertyEditor::_bind_methods() {
ObjectTypeDB::bind_method( "_draw_flags",&PropertyEditor::_draw_flags);
ObjectTypeDB::bind_method( "_set_range_def",&PropertyEditor::_set_range_def);
ObjectTypeDB::bind_method( "_filter_changed",&PropertyEditor::_filter_changed);
+ ObjectTypeDB::bind_method( "update_tree",&PropertyEditor::update_tree);
ADD_SIGNAL( MethodInfo("property_toggled",PropertyInfo( Variant::STRING, "property"),PropertyInfo( Variant::BOOL, "value")));
ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) );
@@ -3511,7 +3640,15 @@ void PropertyEditor::register_text_enter(Node* p_line_edit) {
if (search_box)
search_box->connect("text_changed",this,"_filter_changed");
+}
+
+void PropertyEditor::set_subsection_selectable(bool p_selectable) {
+
+ if (p_selectable==subsection_selectable)
+ return;
+ subsection_selectable=p_selectable;
+ update_tree();
}
PropertyEditor::PropertyEditor() {
@@ -3573,8 +3710,9 @@ PropertyEditor::PropertyEditor() {
show_categories=false;
refresh_countdown=0;
use_doc_hints=false;
-
use_filter=false;
+ subsection_selectable=false;
+ show_type_icons=EDITOR_DEF("inspector/show_type_icons",false);
}
@@ -3584,3 +3722,201 @@ PropertyEditor::~PropertyEditor()
}
+/////////////////////////////
+
+
+
+
+
+class SectionedPropertyEditorFilter : public Object {
+
+ OBJ_TYPE( SectionedPropertyEditorFilter, Object );
+
+ Object *edited;
+ String section;
+
+ bool _set(const StringName& p_name, const Variant& p_value) {
+
+ if (!edited)
+ return false;
+
+ String name=p_name;
+ if (section!="") {
+ name=section+"/"+name;
+ }
+
+ bool valid;
+ edited->set(name,p_value,&valid);
+ return valid;
+ }
+
+ bool _get(const StringName& p_name,Variant &r_ret) const{
+
+ if (!edited)
+ return false;
+
+ String name=p_name;
+ if (section!="") {
+ name=section+"/"+name;
+ }
+
+ bool valid=false;
+
+ r_ret=edited->get(name,&valid);
+ return valid;
+
+
+ }
+ void _get_property_list(List<PropertyInfo> *p_list) const{
+
+ if (!edited)
+ return;
+
+ List<PropertyInfo> pinfo;
+ edited->get_property_list(&pinfo);
+ for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+
+ PropertyInfo pi=E->get();
+ int sp = pi.name.find("/");
+ if (sp!=-1) {
+ String ss = pi.name.substr(0,sp);
+
+ if (ss==section) {
+ pi.name=pi.name.substr(sp+1,pi.name.length());
+ p_list->push_back(pi);
+ }
+ } else {
+ if (section=="")
+ p_list->push_back(pi);
+ }
+ }
+
+ }
+public:
+
+ void set_section(const String& p_section) {
+
+ section=p_section;
+ _change_notify();
+ }
+
+ void set_edited(Object* p_edited) {
+ edited=p_edited;
+ _change_notify();
+ }
+
+ SectionedPropertyEditorFilter() {
+ edited=NULL;
+ }
+
+};
+
+
+void SectionedPropertyEditor::_bind_methods() {
+
+ ObjectTypeDB::bind_method("_section_selected",&SectionedPropertyEditor::_section_selected);
+}
+
+void SectionedPropertyEditor::_section_selected(int p_which) {
+
+ filter->set_section( sections->get_item_metadata(p_which) );
+}
+
+String SectionedPropertyEditor::get_current_section() const {
+
+ return sections->get_item_metadata( sections->get_current() );
+}
+
+String SectionedPropertyEditor::get_full_item_path(const String& p_item) {
+
+ String base = sections->get_item_metadata( sections->get_current() );
+ if (base!="")
+ return base+"/"+p_item;
+ else
+ return p_item;
+}
+
+void SectionedPropertyEditor::edit(Object* p_object) {
+
+ List<PropertyInfo> pinfo;
+ if (p_object)
+ p_object->get_property_list(&pinfo);
+ sections->clear();
+
+ Set<String> existing_sections;
+ for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+
+ PropertyInfo pi=E->get();
+ if (pi.usage&PROPERTY_USAGE_CATEGORY)
+ continue;
+ if (pi.name.find(":")!=-1 || pi.name=="script/script")
+ continue;
+ int sp = pi.name.find("/");
+ if (sp!=-1) {
+ String sname=pi.name.substr(0,sp);
+ if (!existing_sections.has(sname)) {
+ existing_sections.insert(sname);
+ sections->add_item(sname.capitalize());
+ sections->set_item_metadata(sections->get_item_count()-1,sname);
+ }
+
+ } else {
+ if (!existing_sections.has("")) {
+ existing_sections.insert("");
+ sections->add_item("Global");
+ sections->set_item_metadata(sections->get_item_count()-1,"");
+ }
+ }
+
+
+ }
+
+ //sections->sort_items_by_text();
+
+
+ filter->set_edited(p_object);
+ editor->edit(filter);
+
+ sections->select(0);
+ _section_selected(0);
+
+}
+
+PropertyEditor *SectionedPropertyEditor::get_property_editor() {
+
+ return editor;
+}
+
+SectionedPropertyEditor::SectionedPropertyEditor() {
+
+ VBoxContainer *left_vb = memnew( VBoxContainer);
+ left_vb->set_custom_minimum_size(Size2(160,0));
+ add_child(left_vb);
+
+ sections = memnew( ItemList );
+ sections->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ left_vb->add_margin_child("Sections:",sections,true);
+
+ VBoxContainer *right_vb = memnew( VBoxContainer);
+ right_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+ add_child(right_vb);
+
+ filter = memnew( SectionedPropertyEditorFilter );
+ editor = memnew( PropertyEditor );
+ editor->set_v_size_flags(SIZE_EXPAND_FILL);
+ right_vb->add_margin_child("Properties:",editor,true);
+
+ editor->get_scene_tree()->set_column_titles_visible(false);
+
+
+ editor->hide_top_label();
+
+ sections->connect("item_selected",this,"_section_selected");
+
+}
+
+SectionedPropertyEditor::~SectionedPropertyEditor() {
+
+ memdelete(filter);
+}
diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h
index 5fb8386b1b..63ad090901 100644
--- a/tools/editor/property_editor.h
+++ b/tools/editor/property_editor.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -39,6 +39,7 @@
#include "scene/gui/texture_frame.h"
#include "scene/gui/text_edit.h"
#include "scene/gui/check_button.h"
+#include "scene/gui/split_container.h"
#include "scene_tree_editor.h"
/**
@@ -113,6 +114,7 @@ class CustomPropertyEditor : public Popup {
void _action_pressed(int p_which);
void _type_create_selected(int p_idx);
+
void _color_changed(const Color& p_color);
void _draw_easing();
void _menu_option(int p_which);
@@ -161,10 +163,11 @@ class PropertyEditor : public Control {
bool keying;
bool read_only;
bool show_categories;
+ bool show_type_icons;
float refresh_countdown;
bool use_doc_hints;
-
bool use_filter;
+ bool subsection_selectable;
HashMap<String,String> pending;
String selected_property;
@@ -190,6 +193,7 @@ class PropertyEditor : public Control {
virtual void _changed_callback(Object *p_changed,const char * p_what);
virtual void _changed_callbacks(Object *p_changed,const String& p_callback);
+ void _check_reload_status(const String&p_name,TreeItem* item);
void _edit_button(Object *p_item, int p_column, int p_button);
@@ -239,9 +243,37 @@ public:
void set_use_filter(bool p_use);
void register_text_enter(Node *p_line_edit);
+ void set_subsection_selectable(bool p_selectable);
+
PropertyEditor();
~PropertyEditor();
};
+
+class SectionedPropertyEditorFilter;
+
+class SectionedPropertyEditor : public HBoxContainer {
+
+
+ OBJ_TYPE(SectionedPropertyEditor,HBoxContainer);
+ ItemList *sections;
+ SectionedPropertyEditorFilter *filter;
+ PropertyEditor *editor;
+
+
+ static void _bind_methods();
+ void _section_selected(int p_which);
+
+public:
+
+ PropertyEditor *get_property_editor();
+ void edit(Object* p_object);
+ String get_full_item_path(const String& p_item);
+ String get_current_section() const;
+
+ SectionedPropertyEditor();
+ ~SectionedPropertyEditor();
+};
+
#endif
diff --git a/tools/editor/pvrtc_compress.cpp b/tools/editor/pvrtc_compress.cpp
index a2f98adbe0..c30aedc1dc 100644
--- a/tools/editor/pvrtc_compress.cpp
+++ b/tools/editor/pvrtc_compress.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/pvrtc_compress.h b/tools/editor/pvrtc_compress.h
index c4fb0bacb5..129faee080 100644
--- a/tools/editor/pvrtc_compress.h
+++ b/tools/editor/pvrtc_compress.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/quick_open.cpp b/tools/editor/quick_open.cpp
index 6135a4ab64..828275340b 100644
--- a/tools/editor/quick_open.cpp
+++ b/tools/editor/quick_open.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,7 +30,7 @@
#include "os/keyboard.h"
-void EditorQuickOpen::popup(const StringName &p_base, bool p_dontclear, bool p_add_dirs) {
+void EditorQuickOpen::popup(const StringName &p_base, bool p_enable_multi, bool p_add_dirs, bool p_dontclear) {
add_directories=p_add_dirs;
popup_centered_ratio(0.6);
@@ -38,13 +38,38 @@ void EditorQuickOpen::popup(const StringName &p_base, bool p_dontclear, bool p_a
search_box->select_all();
else
search_box->clear();
+ if (p_enable_multi)
+ search_options->set_select_mode(Tree::SELECT_MULTI);
+ else
+ search_options->set_select_mode(Tree::SELECT_SINGLE);
search_box->grab_focus();
base_type=p_base;
_update_search();
+}
+
+String EditorQuickOpen::get_selected() const {
+ TreeItem *ti = search_options->get_selected();
+ if (!ti)
+ return String();
+ return "res://" + ti->get_text(0);
}
+Vector<String> EditorQuickOpen::get_selected_files() const {
+
+ Vector<String> files;
+
+ TreeItem* item = search_options->get_next_selected(search_options->get_root());
+ while (item) {
+
+ files.push_back("res://"+item->get_text(0));
+
+ item = search_options->get_next_selected(item);
+ }
+
+ return files;
+}
void EditorQuickOpen::_text_changed(const String& p_newtext) {
@@ -53,14 +78,33 @@ void EditorQuickOpen::_text_changed(const String& p_newtext) {
void EditorQuickOpen::_sbox_input(const InputEvent& p_ie) {
- if (p_ie.type==InputEvent::KEY && (
- p_ie.key.scancode == KEY_UP ||
- p_ie.key.scancode == KEY_DOWN ||
- p_ie.key.scancode == KEY_PAGEUP ||
- p_ie.key.scancode == KEY_PAGEDOWN ) ) {
+ if (p_ie.type==InputEvent::KEY) {
- search_options->call("_input_event",p_ie);
- search_box->accept_event();
+ switch(p_ie.key.scancode) {
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_PAGEUP:
+ case KEY_PAGEDOWN: {
+
+ search_options->call("_input_event", p_ie);
+ search_box->accept_event();
+
+ TreeItem *root = search_options->get_root();
+ if (!root->get_children())
+ break;
+
+ TreeItem *current = search_options->get_selected();
+
+ TreeItem *item = search_options->get_next_selected(root);
+ while (item) {
+ item->deselect(0);
+ item = search_options->get_next_selected(item);
+ }
+
+ current->select(0);
+
+ } break;
+ }
}
}
@@ -100,9 +144,6 @@ void EditorQuickOpen::_parse_fs(EditorFileSystemDirectory *efsd) {
ti->set_text(0,file);
Ref<Texture> icon = get_icon( (has_icon(efsd->get_file_type(i),ei)?efsd->get_file_type(i):ot),ei);
ti->set_icon(0,icon);
- if (root->get_children()==ti)
- ti->select(0);
-
}
}
@@ -123,6 +164,13 @@ void EditorQuickOpen::_update_search() {
TreeItem *root = search_options->create_item();
_parse_fs(EditorFileSystem::get_singleton()->get_filesystem());
+ if (root->get_children()) {
+ TreeItem *ti = root->get_children();
+
+ ti->select(0);
+ ti->set_as_cursor(0);
+ }
+
get_ok()->set_disabled(root->get_children()==NULL);
}
@@ -132,7 +180,7 @@ void EditorQuickOpen::_confirmed() {
TreeItem *ti = search_options->get_selected();
if (!ti)
return;
- emit_signal("quick_open","res://"+ti->get_text(0));
+ emit_signal("quick_open");
hide();
}
@@ -156,7 +204,7 @@ void EditorQuickOpen::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_confirmed"),&EditorQuickOpen::_confirmed);
ObjectTypeDB::bind_method(_MD("_sbox_input"),&EditorQuickOpen::_sbox_input);
- ADD_SIGNAL(MethodInfo("quick_open",PropertyInfo(Variant::STRING,"respath")));
+ ADD_SIGNAL(MethodInfo("quick_open"));
}
diff --git a/tools/editor/quick_open.h b/tools/editor/quick_open.h
index 8b38256d39..520f7e569d 100644
--- a/tools/editor/quick_open.h
+++ b/tools/editor/quick_open.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -61,7 +61,10 @@ public:
StringName get_base_type() const;
- void popup(const StringName& p_base,bool p_dontclear=false,bool p_add_dirs=false);
+ String get_selected() const;
+ Vector<String> get_selected_files() const;
+
+ void popup(const StringName& p_base,bool p_enable_multi=false,bool p_add_dirs=false,bool p_dontclear=false);
EditorQuickOpen();
};
diff --git a/tools/editor/register_exporters.h b/tools/editor/register_exporters.h
index 0e1ad2ca46..364ad5efc9 100644
--- a/tools/editor/register_exporters.h
+++ b/tools/editor/register_exporters.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/reparent_dialog.cpp b/tools/editor/reparent_dialog.cpp
index 78ba47d54b..97b27603b2 100644
--- a/tools/editor/reparent_dialog.cpp
+++ b/tools/editor/reparent_dialog.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,12 +36,12 @@
void ReparentDialog::_notification(int p_what) {
- if (p_what==NOTIFICATION_ENTER_TREE) {
+ if (p_what==NOTIFICATION_ENTER_TREE) {
connect("confirmed", this,"_reparent");
}
- if (p_what==NOTIFICATION_EXIT_TREE) {
+ if (p_what==NOTIFICATION_EXIT_TREE) {
disconnect("confirmed", this,"_reparent");
}
@@ -62,7 +62,7 @@ void ReparentDialog::_reparent() {
if (tree->get_selected()) {
- emit_signal("reparent",tree->get_selected()->get_path(),node_only->is_pressed());
+ emit_signal("reparent",tree->get_selected()->get_path(),keep_transform->is_pressed());
hide();
}
}
@@ -78,38 +78,41 @@ void ReparentDialog::_bind_methods() {
ObjectTypeDB::bind_method("_reparent",&ReparentDialog::_reparent);
ObjectTypeDB::bind_method("_cancel",&ReparentDialog::_cancel);
- ADD_SIGNAL( MethodInfo("reparent",PropertyInfo(Variant::NODE_PATH,"path"),PropertyInfo(Variant::BOOL,"only_node")));
+ ADD_SIGNAL( MethodInfo("reparent",PropertyInfo(Variant::NODE_PATH,"path"),PropertyInfo(Variant::BOOL,"keep_global_xform")));
}
ReparentDialog::ReparentDialog() {
-
set_title("Reparent Node");
+
VBoxContainer *vbc = memnew( VBoxContainer );
add_child(vbc);
set_child_rect(vbc);
tree = memnew( SceneTreeEditor(false) );
-
+ tree->set_show_enabled_subscene(true);
vbc->add_margin_child("Reparent Location (Select new Parent):",tree,true);
-
+
+ tree->get_scene_tree()->connect("item_activated",this,"_reparent");
+
//Label *label = memnew( Label );
//label->set_pos( Point2( 15,8) );
//label->set_text("Reparent Location (Select new Parent):");
-
- node_only = memnew( CheckButton );
- add_child(node_only);
- node_only->hide();
- tree->set_show_enabled_subscene(true);
+ keep_transform = memnew( CheckBox );
+ keep_transform->set_text("Keep Global Transform");
+ keep_transform->set_pressed(true);
+ vbc->add_child(keep_transform);
+
+
//vbc->add_margin_child("Options:",node_only);;
-
//cancel->connect("pressed", this,"_cancel");
get_ok()->set_text("Reparent");
+
}
diff --git a/tools/editor/reparent_dialog.h b/tools/editor/reparent_dialog.h
index 78c0df9285..296102e4b9 100644
--- a/tools/editor/reparent_dialog.h
+++ b/tools/editor/reparent_dialog.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,6 +32,7 @@
#include "scene/gui/dialogs.h"
#include "scene/gui/button.h"
#include "scene/gui/check_button.h"
+#include "scene/gui/check_box.h"
#include "tools/editor/scene_tree_editor.h"
#include "scene/gui/line_edit.h"
/**
@@ -42,12 +43,14 @@ class ReparentDialog : public ConfirmationDialog {
OBJ_TYPE( ReparentDialog, ConfirmationDialog );
SceneTreeEditor *tree;
- CheckButton *node_only;
+ CheckBox *keep_transform;
+
void update_tree();
void _reparent();
void _cancel();
-
+
+
protected:
void _notification(int p_what);
diff --git a/tools/editor/resources_dock.cpp b/tools/editor/resources_dock.cpp
index b69eec4a51..5e44162c93 100644
--- a/tools/editor/resources_dock.cpp
+++ b/tools/editor/resources_dock.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/resources_dock.h b/tools/editor/resources_dock.h
index 933b457b29..978291fc3f 100644
--- a/tools/editor/resources_dock.h
+++ b/tools/editor/resources_dock.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/run_settings_dialog.cpp b/tools/editor/run_settings_dialog.cpp
index e883c69939..e8c509d79d 100644
--- a/tools/editor/run_settings_dialog.cpp
+++ b/tools/editor/run_settings_dialog.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/run_settings_dialog.h b/tools/editor/run_settings_dialog.h
index fdb8857f6b..09319702f3 100644
--- a/tools/editor/run_settings_dialog.h
+++ b/tools/editor/run_settings_dialog.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp
index 8b5bf8c1e1..5877ce1a43 100644
--- a/tools/editor/scene_tree_dock.cpp
+++ b/tools/editor/scene_tree_dock.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,7 +35,10 @@
#include "tools/editor/plugins/canvas_item_editor_plugin.h"
#include "script_editor_debugger.h"
#include "tools/editor/plugins/script_editor_plugin.h"
+#include "core/io/resource_saver.h"
#include "multi_node_edit.h"
+#include "tools/editor/plugins/animation_player_editor_plugin.h"
+#include "animation_editor.h"
void SceneTreeDock::_unhandled_key_input(InputEvent p_event) {
@@ -291,7 +294,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
for (int i = 0; i < selection.size(); i++) {
Node *top_node = selection[i];
Node *bottom_node = selection[selection.size() - 1 - i];
-
+
ERR_FAIL_COND(!top_node->get_parent());
ERR_FAIL_COND(!bottom_node->get_parent());
@@ -397,7 +400,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
editor_data->get_undo_redo().add_do_method(d,"set_owner",node->get_owner());
}
editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",dup);
- editor_data->get_undo_redo().add_undo_method(parent,"remove_child",dup);
+ editor_data->get_undo_redo().add_undo_method(parent,"remove_child",dup);
editor_data->get_undo_redo().add_do_reference(dup);
ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
@@ -485,7 +488,54 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
delete_dialog->popup_centered_minsize();
}
+ } break;
+ case TOOL_NEW_SCENE_FROM: {
+
+ Node *scene = editor_data->get_edited_scene_root();
+
+ if (!scene) {
+ accept->get_ok()->set_text("I see..");
+ accept->set_text("This operation can't be done without a scene.");
+ accept->popup_centered_minsize();
+ break;
+ }
+
+ List<Node*> selection = editor_selection->get_selected_node_list();
+
+ if (selection.size()!=1) {
+ accept->get_ok()->set_text("I see..");
+ accept->set_text("This operation requires a single selected node.");
+ accept->popup_centered_minsize();
+ break;
+ }
+
+ Node *tocopy = selection.front()->get();
+
+ if (tocopy!=editor_data->get_edited_scene_root() && tocopy->get_filename()!="") {
+ accept->get_ok()->set_text("I see..");
+ accept->set_text("This operation can't be done on instanced scenes.");
+ accept->popup_centered_minsize();
+ break;
+ }
+
+ new_scene_from_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+
+ List<String> extensions;
+ Ref<PackedScene> sd = memnew( PackedScene );
+ ResourceSaver::get_recognized_extensions(sd,&extensions);
+ new_scene_from_dialog->clear_filters();
+ for(int i=0;i<extensions.size();i++) {
+ new_scene_from_dialog->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
+ }
+
+ String existing;
+ if (extensions.size()) {
+ existing="new_scene."+extensions.front()->get().to_lower();
+ }
+ new_scene_from_dialog->set_current_path(existing);
+ new_scene_from_dialog->popup_centered_ratio();
+ new_scene_from_dialog->set_title("Save New Scene As..");
} break;
@@ -520,6 +570,7 @@ void SceneTreeDock::_notification(int p_what) {
"MoveDown",
"Duplicate",
"Reparent",
+ "CreateNewSceneFrom",
"MultiNodeEdit",
"Remove",
};
@@ -875,7 +926,7 @@ bool SceneTreeDock::_validate_no_foreign() {
}
- if (edited_scene->get_scene_inherited_state().is_valid() && edited_scene->get_scene_inherited_state()->find_node_by_path(edited_scene->get_path_to(E->get()))>=0) {
+ if (edited_scene->get_scene_inherited_state().is_valid() && edited_scene->get_scene_inherited_state()->find_node_by_path(edited_scene->get_path_to(E->get()))>=0) {
accept->get_ok()->set_text("Makes Sense!");
accept->set_text("Can't operate on nodes the current scene inherits from!");
@@ -889,7 +940,7 @@ bool SceneTreeDock::_validate_no_foreign() {
return true;
}
-void SceneTreeDock::_node_reparent(NodePath p_path,bool p_node_only) {
+void SceneTreeDock::_node_reparent(NodePath p_path,bool p_keep_global_xform) {
Node *node = scene_tree->get_selected();
@@ -948,11 +999,28 @@ void SceneTreeDock::_node_reparent(NodePath p_path,bool p_node_only) {
editor_data->get_undo_redo().add_do_method(sed,"live_debug_reparent_node",edited_scene->get_path_to(node),edited_scene->get_path_to(new_parent),new_name,-1);
editor_data->get_undo_redo().add_undo_method(sed,"live_debug_reparent_node",NodePath(String(edited_scene->get_path_to(new_parent))+"/"+new_name),edited_scene->get_path_to(node->get_parent()),node->get_name(),node->get_index());
+ if (p_keep_global_xform) {
+ if (node->cast_to<Node2D>())
+ editor_data->get_undo_redo().add_do_method(node,"set_global_transform",node->cast_to<Node2D>()->get_global_transform());
+ if (node->cast_to<Spatial>())
+ editor_data->get_undo_redo().add_do_method(node,"set_global_transform",node->cast_to<Spatial>()->get_global_transform());
+ if (node->cast_to<Control>()) {
+ bool can_do_it=false;
+ Control *c=node->cast_to<Control>();
+ if (c->get_parent()->cast_to<Container>())
+ can_do_it=false;
+ for(int i=0;i<4;i++) {
+ if (c->get_anchor(Margin(i))!=ANCHOR_BEGIN)
+ can_do_it=false;
+ }
+ editor_data->get_undo_redo().add_do_method(node,"set_global_pos",node->cast_to<Control>()->get_global_pos());
+ }
+ }
editor_data->get_undo_redo().add_do_method(this,"_set_owners",edited_scene,owners);
- if (editor->get_animation_editor()->get_root()==node)
- editor_data->get_undo_redo().add_do_method(editor->get_animation_editor(),"set_root",node);
+ if (AnimationPlayerEditor::singleton->get_key_editor()->get_root()==node)
+ editor_data->get_undo_redo().add_do_method(AnimationPlayerEditor::singleton->get_key_editor(),"set_root",node);
editor_data->get_undo_redo().add_undo_method(new_parent,"remove_child",node);
@@ -979,8 +1047,28 @@ void SceneTreeDock::_node_reparent(NodePath p_path,bool p_node_only) {
editor_data->get_undo_redo().add_undo_method(node->get_parent(),"add_child",node);
editor_data->get_undo_redo().add_undo_method(node->get_parent(),"move_child",node,child_pos);
editor_data->get_undo_redo().add_undo_method(this,"_set_owners",edited_scene,owners);
- if (editor->get_animation_editor()->get_root()==node)
- editor_data->get_undo_redo().add_undo_method(editor->get_animation_editor(),"set_root",node);
+ if (AnimationPlayerEditor::singleton->get_key_editor()->get_root()==node)
+ editor_data->get_undo_redo().add_undo_method(AnimationPlayerEditor::singleton->get_key_editor(),"set_root",node);
+
+ if (p_keep_global_xform) {
+ if (node->cast_to<Node2D>())
+ editor_data->get_undo_redo().add_undo_method(node,"set_transform",node->cast_to<Node2D>()->get_transform());
+ if (node->cast_to<Spatial>())
+ editor_data->get_undo_redo().add_undo_method(node,"set_transform",node->cast_to<Spatial>()->get_transform());
+ if (node->cast_to<Control>()) {
+ bool can_do_it=false;
+ Control *c=node->cast_to<Control>();
+ if (c->get_parent()->cast_to<Container>())
+ can_do_it=false;
+ for(int i=0;i<4;i++) {
+ if (c->get_anchor(Margin(i))!=ANCHOR_BEGIN)
+ can_do_it=false;
+ }
+ editor_data->get_undo_redo().add_undo_method(node,"set_pos",node->cast_to<Control>()->get_pos());
+ }
+ }
+
+
}
@@ -1066,8 +1154,8 @@ void SceneTreeDock::_delete_confirm() {
editor_data->get_undo_redo().add_do_method(n->get_parent(),"remove_child",n);
editor_data->get_undo_redo().add_undo_method(n->get_parent(),"add_child",n);
editor_data->get_undo_redo().add_undo_method(n->get_parent(),"move_child",n,n->get_index());
- if (editor->get_animation_editor()->get_root()==n)
- editor_data->get_undo_redo().add_undo_method(editor->get_animation_editor(),"set_root",n);
+ if (AnimationPlayerEditor::singleton->get_key_editor()->get_root()==n)
+ editor_data->get_undo_redo().add_undo_method(AnimationPlayerEditor::singleton->get_key_editor(),"set_root",n);
editor_data->get_undo_redo().add_undo_method(this,"_set_owners",edited_scene,owners);
//editor_data->get_undo_redo().add_undo_method(n,"set_owner",n->get_owner());
editor_data->get_undo_redo().add_undo_reference(n);
@@ -1103,6 +1191,7 @@ void SceneTreeDock::_update_tool_buttons() {
tool_buttons[TOOL_DUPLICATE]->set_disabled(disable_root);
tool_buttons[TOOL_REPARENT]->set_disabled(disable_root);
tool_buttons[TOOL_ERASE]->set_disabled(disable);
+ tool_buttons[TOOL_NEW_SCENE_FROM]->set_disabled(disable_root);
tool_buttons[TOOL_MULTI_EDIT]->set_disabled(EditorNode::get_singleton()->get_editor_selection()->get_selection().size()<2);
@@ -1231,13 +1320,18 @@ void SceneTreeDock::_create() {
editor->set_edited_scene(newnode);
}
+ //small hack to make collisionshapes and other kind of nodes to work
+ for(int i=0;i<newnode->get_child_count();i++) {
+ Node *c=newnode->get_child(i);
+ c->call("set_transform", c->call("get_transform") );
+ }
editor_data->get_undo_redo().clear_history();
newnode->set_name(newname);
editor->push_item(newnode);
memdelete(n);
-
+
_update_tool_buttons();
}
@@ -1284,6 +1378,59 @@ void SceneTreeDock::_import_subscene() {
*/
}
+void SceneTreeDock::_new_scene_from(String p_file) {
+
+ List<Node*> selection = editor_selection->get_selected_node_list();
+
+ if (selection.size()!=1) {
+ accept->get_ok()->set_text("I see..");
+ accept->set_text("This operation requires a single selected node.");
+ accept->popup_centered_minsize();
+ return;
+ }
+
+ Node *base = selection.front()->get();
+
+ Map<Node*,Node*> reown;
+ reown[editor_data->get_edited_scene_root()]=base;
+ Node *copy = base->duplicate_and_reown(reown);
+ if (copy) {
+
+ Ref<PackedScene> sdata = memnew( PackedScene );
+ Error err = sdata->pack(copy);
+ memdelete(copy);
+
+ if (err!=OK) {
+ accept->get_ok()->set_text("I see..");
+ accept->set_text("Couldn't save new scene. Likely dependencies (instances) couldn't be satisfied.");
+ accept->popup_centered_minsize();
+ return;
+ }
+
+ int flg=0;
+ if (EditorSettings::get_singleton()->get("on_save/compress_binary_resources"))
+ flg|=ResourceSaver::FLAG_COMPRESS;
+ if (EditorSettings::get_singleton()->get("on_save/save_paths_as_relative"))
+ flg|=ResourceSaver::FLAG_RELATIVE_PATHS;
+
+
+ err = ResourceSaver::save(p_file,sdata,flg);
+ if (err!=OK) {
+ accept->get_ok()->set_text("I see..");
+ accept->set_text("Error saving scene.");
+ accept->popup_centered_minsize();
+ return;
+ }
+
+ } else {
+ accept->get_ok()->set_text("I see..");
+ accept->set_text("Error duplicating scene to save it.");
+ accept->popup_centered_minsize();
+ return;
+ }
+
+}
+
void SceneTreeDock::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_tool_selected"),&SceneTreeDock::_tool_selected);
@@ -1301,6 +1448,7 @@ void SceneTreeDock::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_node_prerenamed"),&SceneTreeDock::_node_prerenamed);
ObjectTypeDB::bind_method(_MD("_import_subscene"),&SceneTreeDock::_import_subscene);
ObjectTypeDB::bind_method(_MD("_selection_changed"),&SceneTreeDock::_selection_changed);
+ ObjectTypeDB::bind_method(_MD("_new_scene_from"),&SceneTreeDock::_new_scene_from);
ObjectTypeDB::bind_method(_MD("instance"),&SceneTreeDock::instance);
}
@@ -1373,9 +1521,10 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec
scene_tree->set_undo_redo(&editor_data->get_undo_redo());
scene_tree->set_editor_selection(editor_selection);
+
HBoxContainer *hbc_bottom = memnew( HBoxContainer );
vbc->add_child(hbc_bottom);
-
+ hbc_bottom->add_constant_override("separation", 0);
tb = memnew( ToolButton );
tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_MOVE_UP, false));
@@ -1404,6 +1553,12 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec
hbc_bottom->add_spacer();
tb = memnew( ToolButton );
+ tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_NEW_SCENE_FROM, false));
+ tb->set_tooltip("Create New Scene From Node(s)");
+ hbc_bottom->add_child(tb);
+ tool_buttons[TOOL_NEW_SCENE_FROM]=tb;
+
+ tb = memnew( ToolButton );
tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_MULTI_EDIT, false));
tb->set_tooltip("Multi-Edit Selected Nodes");
hbc_bottom->add_child(tb);
@@ -1423,12 +1578,15 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec
groups_editor = memnew( GroupsEditor );
add_child(groups_editor);
groups_editor->set_undo_redo(&editor_data->get_undo_redo());
+
connect_dialog = memnew( ConnectionsDialog(p_editor) );
add_child(connect_dialog);
connect_dialog->set_undoredo(&editor_data->get_undo_redo());
+
script_create_dialog = memnew( ScriptCreateDialog );
add_child(script_create_dialog);
script_create_dialog->connect("script_created",this,"_script_created");
+
reparent_dialog = memnew( ReparentDialog );
add_child(reparent_dialog);
reparent_dialog->connect("reparent",this,"_node_reparent");
@@ -1444,10 +1602,16 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec
delete_dialog = memnew( ConfirmationDialog );
add_child(delete_dialog);
delete_dialog->connect("confirmed",this,"_delete_confirm");
+
import_subscene_dialog = memnew( EditorSubScene );
add_child(import_subscene_dialog);
import_subscene_dialog->connect("subscene_selected",this,"_import_subscene");
+ new_scene_from_dialog = memnew( EditorFileDialog );
+ new_scene_from_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ add_child(new_scene_from_dialog);
+ new_scene_from_dialog->connect("file_selected",this,"_new_scene_from");
+
first_enter=true;
diff --git a/tools/editor/scene_tree_dock.h b/tools/editor/scene_tree_dock.h
index b1c53d2ff9..114e2c5c97 100644
--- a/tools/editor/scene_tree_dock.h
+++ b/tools/editor/scene_tree_dock.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -62,6 +62,7 @@ class SceneTreeDock : public VBoxContainer {
TOOL_MOVE_DOWN,
TOOL_DUPLICATE,
TOOL_REPARENT,
+ TOOL_NEW_SCENE_FROM,
TOOL_MULTI_EDIT,
TOOL_ERASE,
TOOL_BUTTON_MAX
@@ -90,6 +91,7 @@ class SceneTreeDock : public VBoxContainer {
ReparentDialog *reparent_dialog;
EditorFileDialog *file;
EditorSubScene *import_subscene_dialog;
+ EditorFileDialog *new_scene_from_dialog;
bool first_enter;
@@ -99,7 +101,7 @@ class SceneTreeDock : public VBoxContainer {
EditorNode *editor;
Node *_duplicate(Node *p_node, Map<Node*,Node*> &duplimap);
- void _node_reparent(NodePath p_path,bool p_node_only);
+ void _node_reparent(NodePath p_path, bool p_keep_global_xform);
void _set_owners(Node *p_owner, const Array& p_nodes);
void _load_request(const String& p_path);
void _script_open_request(const Ref<Script>& p_script);
@@ -119,6 +121,8 @@ class SceneTreeDock : public VBoxContainer {
void _import_subscene();
+ void _new_scene_from(String p_file);
+
bool _validate_no_foreign();
void _selection_changed();
diff --git a/tools/editor/scene_tree_editor.cpp b/tools/editor/scene_tree_editor.cpp
index 6575603073..0260457c81 100644
--- a/tools/editor/scene_tree_editor.cpp
+++ b/tools/editor/scene_tree_editor.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -39,12 +39,8 @@
Node *SceneTreeEditor::get_scene_node() {
ERR_FAIL_COND_V(!is_inside_tree(),NULL);
- if (get_tree()->get_root()->get_child_count() && get_tree()->get_root()->get_child(0)->cast_to<EditorNode>())
- return get_tree()->get_root()->get_child(0)->cast_to<EditorNode>()->get_edited_scene();
- else
- return get_tree()->get_root();
- return NULL;
+ return get_tree()->get_edited_scene_root();
}
@@ -725,6 +721,9 @@ void SceneTreeEditor::_update_selection(TreeItem *item) {
NodePath np = item->get_metadata(0);
+ if (!has_node(np))
+ return;
+
Node *n=get_node(np);
if (!n)
@@ -928,7 +927,7 @@ void SceneTreeDialog::_cancel() {
void SceneTreeDialog::_select() {
if (tree->get_selected()) {
- emit_signal("selected",tree->get_selected()->get_path());
+ emit_signal("selected",tree->get_selected()->get_path());
hide();
}
}
@@ -939,7 +938,6 @@ void SceneTreeDialog::_bind_methods() {
ObjectTypeDB::bind_method("_cancel",&SceneTreeDialog::_cancel);
ADD_SIGNAL( MethodInfo("selected",PropertyInfo(Variant::NODE_PATH,"path")));
-
}
@@ -951,7 +949,7 @@ SceneTreeDialog::SceneTreeDialog() {
add_child(tree);
set_child_rect(tree);
-
+ tree->get_scene_tree()->connect("item_activated",this,"_select");
}
diff --git a/tools/editor/scene_tree_editor.h b/tools/editor/scene_tree_editor.h
index 50cca4e24b..334debc148 100644
--- a/tools/editor/scene_tree_editor.h
+++ b/tools/editor/scene_tree_editor.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/scenes.cpp b/tools/editor/scenes.cpp
index ada5751b5a..e6569c98a9 100644
--- a/tools/editor/scenes.cpp
+++ b/tools/editor/scenes.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/scenes.h b/tools/editor/scenes.h
index 463c3b5e18..bae9ef65f0 100644
--- a/tools/editor/scenes.h
+++ b/tools/editor/scenes.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/scenes_dock.cpp b/tools/editor/scenes_dock.cpp
index c9b376ebec..5abc4992df 100644
--- a/tools/editor/scenes_dock.cpp
+++ b/tools/editor/scenes_dock.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -195,7 +195,12 @@ void ScenesDock::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: {
} break;
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+ display_mode->set_pressed(int(EditorSettings::get_singleton()->get("file_dialog/display_mode"))==EditorFileDialog::DISPLAY_LIST);
+
+ _change_file_display();
+ } break;
}
}
@@ -1063,6 +1068,11 @@ void ScenesDock::open(const String& p_path) {
}
+void ScenesDock::set_use_thumbnails(bool p_use) {
+
+ display_mode->set_pressed(!p_use);
+}
+
void ScenesDock::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_update_tree"),&ScenesDock::_update_tree);
@@ -1244,6 +1254,8 @@ ScenesDock::ScenesDock(EditorNode *p_editor) {
history_pos=0;
tree_mode=true;
+ path="res://";
+
}
diff --git a/tools/editor/scenes_dock.h b/tools/editor/scenes_dock.h
index d045124bf7..a1978a3ca4 100644
--- a/tools/editor/scenes_dock.h
+++ b/tools/editor/scenes_dock.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -153,6 +153,7 @@ public:
void fix_dependencies(const String& p_for_file);
+ void set_use_thumbnails(bool p_use);
ScenesDock(EditorNode *p_editor);
~ScenesDock();
diff --git a/tools/editor/script_create_dialog.cpp b/tools/editor/script_create_dialog.cpp
index 622150ab68..409e8be870 100644
--- a/tools/editor/script_create_dialog.cpp
+++ b/tools/editor/script_create_dialog.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/script_create_dialog.h b/tools/editor/script_create_dialog.h
index 59fde8fbd5..181989402e 100644
--- a/tools/editor/script_create_dialog.h
+++ b/tools/editor/script_create_dialog.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/editor/script_editor_debugger.cpp b/tools/editor/script_editor_debugger.cpp
index 60f2afa2c2..e727668c49 100644
--- a/tools/editor/script_editor_debugger.cpp
+++ b/tools/editor/script_editor_debugger.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -210,6 +210,8 @@ void ScriptEditorDebugger::_parse_message(const String& p_msg,const Array& p_dat
OS::get_singleton()->move_window_to_foreground();
tabs->set_current_tab(0);
+ EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
+
} else if (p_msg=="debug_exit") {
breaked=false;
@@ -358,7 +360,7 @@ void ScriptEditorDebugger::_parse_message(const String& p_msg,const Array& p_dat
if (EditorNode::get_log()->is_hidden()) {
log_forced_visible=true;
- EditorNode::get_log()->show();
+ EditorNode::get_singleton()->make_bottom_panel_item_visible(EditorNode::get_log());
}
EditorNode::get_log()->add_message(t);
@@ -528,6 +530,8 @@ void ScriptEditorDebugger::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
+ inspector->edit(variables);
+
step->set_icon( get_icon("DebugStep","EditorIcons"));
next->set_icon( get_icon("DebugNext","EditorIcons"));
back->set_icon( get_icon("Back","EditorIcons"));
@@ -551,8 +555,14 @@ void ScriptEditorDebugger::_notification(int p_what) {
if (error_count==0) {
error_split->set_name("Errors");
+ debugger_button->set_text("Debugger");
+ debugger_button->set_icon(Ref<Texture>());
+ tabs->set_tab_icon(error_split->get_index(),Ref<Texture>());
} else {
error_split->set_name("Errors ("+itos(error_count)+")");
+ debugger_button->set_text("Debugger ("+itos(error_count)+")");
+ debugger_button->set_icon(get_icon("Error","EditorIcons"));
+ tabs->set_tab_icon(error_split->get_index(),get_icon("Error","EditorIcons"));
}
last_error_count=error_count;
}
@@ -569,12 +579,12 @@ void ScriptEditorDebugger::_notification(int p_what) {
ppeer->set_stream_peer(connection);
+ //EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
+ //emit_signal("show_debugger",true);
- show();
dobreak->set_disabled(false);
tabs->set_current_tab(0);
- emit_signal("show_debugger",true);
reason->set_text("Child Process Connected");
reason->set_tooltip("Child Process Connected");
scene_tree->clear();
@@ -727,7 +737,9 @@ void ScriptEditorDebugger::stop(){
message.clear();
if (log_forced_visible) {
- EditorNode::get_log()->hide();
+ //EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
+ if (EditorNode::get_log()->is_visible())
+ EditorNode::get_singleton()->hide_bottom_panel();
log_forced_visible=false;
}
@@ -737,8 +749,11 @@ void ScriptEditorDebugger::stop(){
le_set->set_disabled(true);
- hide();
- emit_signal("show_debugger",false);
+ if (hide_on_stop) {
+ if (is_visible())
+ EditorNode::get_singleton()->hide_bottom_panel();
+ emit_signal("show_debugger",false);
+ }
}
@@ -768,9 +783,9 @@ void ScriptEditorDebugger::_stack_dump_frame_selected() {
void ScriptEditorDebugger::_hide_request() {
- hide();
+ if (EditorNode::get_log()->is_visible())
+ EditorNode::get_singleton()->hide_bottom_panel();
emit_signal("show_debugger",false);
-
}
void ScriptEditorDebugger::_output_clear() {
@@ -1160,6 +1175,10 @@ void ScriptEditorDebugger:: _error_stack_selected(int p_idx){
}
+void ScriptEditorDebugger::set_hide_on_stop(bool p_hide) {
+
+ hide_on_stop=p_hide;
+}
void ScriptEditorDebugger::_bind_methods() {
@@ -1222,12 +1241,13 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor){
vbc->add_child(hbc);
- reason = memnew( Label );
+ reason = memnew( LineEdit );
reason->set_text("");
+ reason->set_editable(false);
hbc->add_child(reason);
reason->add_color_override("font_color",Color(1,0.4,0.0,0.8));
reason->set_h_size_flags(SIZE_EXPAND_FILL);
- reason->set_clip_text(true);
+ //reason->set_clip_text(true);
hbc->add_child( memnew( VSeparator) );
@@ -1290,7 +1310,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor){
pending_in_queue=0;
variables = memnew( ScriptEditorDebuggerVariables );
- inspector->edit(variables);
+
breaked=false;
tabs->add_child(dbg);
@@ -1454,7 +1474,6 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor){
msgdialog = memnew( AcceptDialog );
add_child(msgdialog);
- hide();
log_forced_visible=false;
p_editor->get_undo_redo()->set_method_notify_callback(_method_changeds,this);
@@ -1462,6 +1481,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor){
live_debug=false;
last_path_id=false;
error_count=0;
+ hide_on_stop=true;
last_error_count=0;
diff --git a/tools/editor/script_editor_debugger.h b/tools/editor/script_editor_debugger.h
index 6b66a62dd5..0be311a990 100644
--- a/tools/editor/script_editor_debugger.h
+++ b/tools/editor/script_editor_debugger.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -54,6 +54,7 @@ class ScriptEditorDebugger : public Control {
AcceptDialog *msgdialog;
+ Button *debugger_button;
LineEdit *clicked_ctrl;
LineEdit *clicked_ctrl_type;
@@ -71,6 +72,8 @@ class ScriptEditorDebugger : public Control {
int error_count;
int last_error_count;
+ bool hide_on_stop;
+
TextureButton *tb;
@@ -78,7 +81,7 @@ class ScriptEditorDebugger : public Control {
TabContainer *tabs;
- Label *reason;
+ LineEdit *reason;
bool log_forced_visible;
ScriptEditorDebuggerVariables *variables;
@@ -182,6 +185,9 @@ public:
void update_live_edit_root();
+ void set_hide_on_stop(bool p_hide);
+
+ void set_tool_button(Button *p_tb) { debugger_button=p_tb; }
virtual Size2 get_minimum_size() const;
ScriptEditorDebugger(EditorNode *p_editor=NULL);
diff --git a/tools/editor/settings_config_dialog.cpp b/tools/editor/settings_config_dialog.cpp
index 6d8f849427..ebbc488ff2 100644
--- a/tools/editor/settings_config_dialog.cpp
+++ b/tools/editor/settings_config_dialog.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -71,7 +71,7 @@ void EditorSettingsDialog::popup_edit_settings() {
return;
property_editor->edit(EditorSettings::get_singleton());
- property_editor->update_tree();
+ property_editor->get_property_editor()->update_tree();
search_box->select_all();
search_box->grab_focus();
@@ -254,7 +254,7 @@ void EditorSettingsDialog::_clear_search_box() {
return;
search_box->clear();
- property_editor->update_tree();
+ property_editor->get_property_editor()->update_tree();
}
void EditorSettingsDialog::_notification(int p_what) {
@@ -306,10 +306,10 @@ EditorSettingsDialog::EditorSettingsDialog() {
hbc->add_child(clear_button);
clear_button->connect("pressed",this,"_clear_search_box");
- property_editor = memnew( PropertyEditor );
- property_editor->hide_top_label();
- property_editor->set_use_filter(true);
- property_editor->register_text_enter(search_box);
+ property_editor = memnew( SectionedPropertyEditor );
+ //property_editor->hide_top_label();
+ property_editor->get_property_editor()->set_use_filter(true);
+ property_editor->get_property_editor()->register_text_enter(search_box);
property_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
vbc->add_child(property_editor);
diff --git a/tools/editor/settings_config_dialog.h b/tools/editor/settings_config_dialog.h
index 50159cf488..e1c3238a64 100644
--- a/tools/editor/settings_config_dialog.h
+++ b/tools/editor/settings_config_dialog.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -53,7 +53,7 @@ class EditorSettingsDialog : public AcceptDialog {
Tree *plugins;
LineEdit *search_box;
ToolButton *clear_button;
- PropertyEditor *property_editor;
+ SectionedPropertyEditor *property_editor;
Timer *timer;
diff --git a/tools/editor/spatial_editor_gizmos.cpp b/tools/editor/spatial_editor_gizmos.cpp
index 5efca44c7d..320b0c3a70 100644
--- a/tools/editor/spatial_editor_gizmos.cpp
+++ b/tools/editor/spatial_editor_gizmos.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -2283,6 +2283,8 @@ void NavigationMeshSpatialGizmo::redraw() {
}
}
+ if (faces.empty())
+ return;
Map<_EdgeKey,bool> edge_map;
DVector<Vector3> tmeshfaces;
@@ -2330,7 +2332,7 @@ void NavigationMeshSpatialGizmo::redraw() {
}
}
- Ref<TriangleMesh> tmesh = memnew( TriangleMesh);
+ Ref<TriangleMesh> tmesh = memnew( TriangleMesh );
tmesh->create(tmeshfaces);
if (lines.size())
diff --git a/tools/editor/spatial_editor_gizmos.h b/tools/editor/spatial_editor_gizmos.h
index bc7e8ad21d..669d3e2380 100644
--- a/tools/editor/spatial_editor_gizmos.h
+++ b/tools/editor/spatial_editor_gizmos.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/export/blender25/io_scene_dae/export_dae.py b/tools/export/blender25/io_scene_dae/export_dae.py
index b846f0e2d8..7ee0e179b8 100644
--- a/tools/export/blender25/io_scene_dae/export_dae.py
+++ b/tools/export/blender25/io_scene_dae/export_dae.py
@@ -921,7 +921,7 @@ class DaeExporter:
if (node.parent.type=="ARMATURE"):
armature=node.parent
if (armcount>1):
- self.operator.report({'WARNING'},'Object "'+node.name+'" refers to more than one armature! This is unsopported.')
+ self.operator.report({'WARNING'},'Object "'+node.name+'" refers to more than one armature! This is unsupported.')
if (armcount==0):
self.operator.report({'WARNING'},'Object "'+node.name+'" is child of an armature, but has no armature modifier.')
diff --git a/tools/html_fs/godot.html b/tools/html_fs/godot.html
index 36761deb90..c354826e1f 100644
--- a/tools/html_fs/godot.html
+++ b/tools/html_fs/godot.html
@@ -1,1317 +1,374 @@
-<!doctype html>
-<html lang="en-us">
- <head>
- <meta charset="utf-8">
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <title>Emscripten-Generated Code</title>
- <style>
- body {
- font-family: arial;
- margin: 0;
- padding: none;
- }
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
+<head>
+ <meta charset="utf-8" />
+ <title>$GODOT_HEAD_TITLE</title>
+ $GODOT_HEAD_INCLUDE
+ <style type="text/css">
+ body {
+ margin: 0;
+ border: 0 none;
+ padding: 0;
+ text-align: center;
+ background-color: black;
+ font-family: $GODOT_STYLE_FONT_FAMILY;
+ }
- .emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
- div.emscripten { text-align: center; }
- div.emscripten_border { border: 1px solid black; }
- /* the canvas *must not* have any border or padding, or mouse coords will be wrong */
- canvas.emscripten { border: 0px none; }
- #emscripten_logo {
- display: inline-block;
- margin: 0;
- }
+ /* Godot Engine default theme style
+ * ================================ */
- .spinner {
- height: 30px;
- width: 30px;
- margin: 0;
- margin-top: 20px;
- margin-left: 20px;
- display: inline-block;
- vertical-align: top;
+ .godot {
+ color: #e0e0e0;
+ background-color: #3b3943;
+ background-image: linear-gradient(to bottom, #403e48, #35333c);
+ border: 1px solid #45434e;
+ box-shadow: 0 0 1px 1px #2f2d35;
+ }
- -webkit-animation: rotation .8s linear infinite;
- -moz-animation: rotation .8s linear infinite;
- -o-animation: rotation .8s linear infinite;
- animation: rotation 0.8s linear infinite;
+ button.godot {
+ font-family: $GODOT_STYLE_FONT_FAMILY; /* override user agent style */
+ padding: 1px 5px;
+ background-color: #37353f;
+ background-image: linear-gradient(to bottom, #413e49, #3a3842);
+ border: 1px solid #514f5d;
+ border-radius: 1px;
+ box-shadow: 0 0 1px 1px #2a2930;
+ }
- border-left: 5px solid rgb(235, 235, 235);
- border-right: 5px solid rgb(235, 235, 235);
- border-bottom: 5px solid rgb(235, 235, 235);
- border-top: 5px solid rgb(120, 120, 120);
-
- border-radius: 100%;
- background-color: rgb(189, 215, 46);
- }
+ button.godot:hover {
+ color: #f0f0f0;
+ background-color: #44414e;
+ background-image: linear-gradient(to bottom, #494652, #423f4c);
+ border: 1px solid #5a5667;
+ box-shadow: 0 0 1px 1px #26252b;
+ }
- @-webkit-keyframes rotation {
- from {-webkit-transform: rotate(0deg);}
- to {-webkit-transform: rotate(360deg);}
- }
- @-moz-keyframes rotation {
- from {-moz-transform: rotate(0deg);}
- to {-moz-transform: rotate(360deg);}
- }
- @-o-keyframes rotation {
- from {-o-transform: rotate(0deg);}
- to {-o-transform: rotate(360deg);}
- }
- @keyframes rotation {
- from {transform: rotate(0deg);}
- to {transform: rotate(360deg);}
- }
+ button.godot:active {
+ color: #fff;
+ background-color: #3e3b46;
+ background-image: linear-gradient(to bottom, #36343d, #413e49);
+ border: 1px solid #4f4c59;
+ box-shadow: 0 0 1px 1px #26252b;
+ }
- #status {
- display: inline-block;
- vertical-align: top;
- margin-top: 30px;
- margin-left: 20px;
- font-weight: bold;
- color: rgb(120, 120, 120);
- }
+ button.godot:disabled {
+ color: rgba(230, 230, 230, 0.2);
+ background-color: #3d3d3d;
+ background-image: linear-gradient(to bottom, #434343, #393939);
+ border: 1px solid #474747;
+ box-shadow: 0 0 1px 1px #2d2b33;
+ }
- #progress {
- height: 20px;
- width: 30px;
- }
- #controls {
- display: inline-block;
- float: right;
- vertical-align: top;
- margin-top: 30px;
- margin-right: 20px;
- }
+ /* Canvas / wrapper
+ * ================ */
- #output {
- width: 100%;
- height: 200px;
- margin: 0 auto;
- margin-top: 10px;
- display: block;
- background-color: black;
- color: white;
- font-family: 'Lucida Console', Monaco, monospace;
- outline: none;
- }
- </style>
- </head>
- <body>
- <a href="http://emscripten.org">
- <?xml version="1.0" encoding="UTF-8" standalone="no"?><svg
- version="1.1"
- id="Layer_1"
- x="0px"
- y="0px"
- width="296px"
- height="78px"
- viewBox="420 120 100 170"
- enable-background="new 0 0 900 400"
- xml:space="preserve"
- inkscape:version="0.48.4 r9939"
- sodipodi:docname="emscripten_powered_by_logo.svg"><metadata
- id="metadata345"><rdf:RDF><cc:Work
- rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
- id="defs343"><linearGradient
- y2="247.6265"
- x2="225.1929"
- y1="152.499"
- x1="225.1929"
- gradientUnits="userSpaceOnUse"
- id="linearGradient5104"><stop
- id="stop5106"
- style="stop-color:#C1D72F"
- offset="0.3227531" /><stop
- id="stop5108"
- style="stop-color:#BCD631"
- offset="0.45119295" /><stop
- id="stop5110"
- style="stop-color:#AFD136"
- offset="0.64491969" /><stop
- id="stop5112"
- style="stop-color:#ABD037"
- offset="1" /><a:midPointStop
- style="stop-color:#C1D72F"
- offset="0.0123" /><a:midPointStop
- style="stop-color:#C1D72F"
- offset="0.3086" /><a:midPointStop
- style="stop-color:#ABD037"
- offset="1" /></linearGradient><linearGradient
- inkscape:collect="always"
- xlink:href="#SVGID_2_"
- id="linearGradient5120"
- x1="397.56918"
- y1="128.12726"
- x2="397.56918"
- y2="166.25996"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.103059,0,0,1.103059,-38.997823,3.1312145)" /><filter
- inkscape:collect="always"
- id="filter5126"><feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.56377237"
- id="feGaussianBlur5128" /></filter><linearGradient
- inkscape:collect="always"
- xlink:href="#SVGID_2_"
- id="linearGradient5134"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.103059,0,0,1.103059,-38.997823,3.1312145)"
- x1="397.56918"
- y1="128.12726"
- x2="397.56918"
- y2="166.25996" /></defs><sodipodi:namedview
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1"
- objecttolerance="10"
- gridtolerance="10"
- guidetolerance="10"
- inkscape:pageopacity="0"
- inkscape:pageshadow="2"
- inkscape:window-width="1440"
- inkscape:window-height="838"
- id="namedview341"
- showgrid="false"
- inkscape:zoom="0.63555556"
- inkscape:cx="224.82424"
- inkscape:cy="-52.085109"
- inkscape:window-x="-8"
- inkscape:window-y="-8"
- inkscape:window-maximized="1"
- inkscape:current-layer="Layer_1" /><g
- id="g5130"
- transform="matrix(0.91591318,0,0,0.91591318,28.176953,14.143571)"><path
- transform="matrix(1.103059,0,0,1.103059,-35.073492,-16.03923)"
- id="path5122"
- style="fill:#383838;fill-opacity:0.34705882;stroke:none;filter:url(#filter5126)"
- d="m 494.39333,173.6323 c 0.57407,0.28703 1.87073,1.00226 2.89426,1.02855 0.55732,0.0143 1.14006,-0.1672 1.60262,-0.4784 1.20466,-0.81046 2.23561,-2.03031 2.72683,-3.39661 0.19424,-0.54027 0.0238,-1.72222 0.0238,-1.72222 l -3.82713,-14.06478 -1.98533,0 0.50231,-2.67891 6.36261,0 2.55939,12.22285 4.78392,-9.68746 -2.00924,0 0,-2.65498 7.19979,0 -11.00301,22.38875 -1.69829,1.91358 -2.29628,1.3395 -2.46371,0.26312 -2.29628,-0.21528 -2.79859,-1.36342 z m -12.0637,-14.56445 c -0.93698,1.88565 -1.70261,4.35262 -0.81842,6.26333 0.36549,0.78976 1.35098,1.19428 2.192,1.41737 0.60934,0.16133 1.29167,0.0999 1.88775,-0.10468 0.48126,-0.1655 0.8829,-0.5224 1.255,-0.8697 0.40341,-0.3768 0.77723,-0.80461 1.03505,-1.29262 0.21864,-0.41395 0.40236,-0.84786 0.49325,-1.30698 0.20667,-1.0485 0.35879,-2.1079 0.33583,-3.17631 -0.0184,-0.87403 -0.0789,-1.87107 -0.47711,-2.64959 -0.26344,-0.51379 -0.77017,-0.71849 -1.33113,-0.85633 -0.42395,-0.10479 -0.81432,-0.0626 -1.21773,0.10517 -0.65479,0.27273 -1.2544,0.5311 -1.82112,0.95764 -0.57331,0.4317 -1.21403,0.86959 -1.53337,1.5127 z m 0.65588,-4.31208 c 0,0 2.19341,-1.80738 3.45549,-2.27082 0.71718,-0.26365 3.45363,-0.65258 4.15,-0.3378 1.47292,0.66633 2.26103,1.57529 2.7222,2.60001 0.46118,1.02472 0.69944,2.59956 0.79701,3.73627 0.13278,1.55027 -0.13682,3.77629 -0.53404,5.74843 -0.30079,1.49256 -1.01883,2.74423 -1.83478,3.92156 -1.06526,1.5373 -1.82382,2.15116 -3.66756,2.46594 -0.98864,0.16889 -1.93845,0.46787 -3.25466,0.0928 -1.4384,-0.40963 -2.35273,-0.81244 -3.39599,-1.63337 -0.72524,-0.57054 -1.16043,-1.54043 -1.16043,-1.54043 l 0,2.82636 -4.8903,0 3.39872,-23.01602 -1.92242,-0.85888 0.0403,-2.38127 7.25847,0.0534 z m -23.77803,2.20447 c 0.29175,1.49273 0.0813,4.83252 -0.86111,6.69751 -0.3062,0.60617 -0.94813,1.32967 -1.55479,1.6983 -1.01515,0.61713 -2.21688,1.21322 -3.3966,1.07639 -0.47944,-0.0541 -0.97036,-0.34348 -1.24383,-0.74151 -0.47686,-0.69328 -0.43621,-1.55032 -0.45448,-2.39198 -0.024,-1.06873 0.13137,-2.23775 0.38272,-3.277 0.18705,-0.7744 0.4229,-1.58254 0.86111,-2.24844 0.39037,-0.59323 0.92628,-1.12617 1.55478,-1.45909 0.54854,-0.29014 1.19695,-0.38467 1.81791,-0.40664 0.63637,-0.0231 1.3031,0.0385 1.88966,0.28704 0.3875,0.16453 0.92361,0.3524 1.00463,0.76542 z m 1.29312,-9.69052 -0.64254,6.12262 c 0,0 -1.68393,-0.96858 -2.605,-1.25148 -0.73032,-0.22434 -1.50312,-0.36654 -2.26624,-0.33838 -0.97069,0.0345 -1.91182,0.22099 -2.81751,0.57088 -0.9185,0.35497 -1.78344,0.94565 -2.49338,1.62792 -0.88025,0.84538 -1.51404,1.90455 -2.02977,3.0106 -0.39653,0.84993 -0.69517,1.75284 -0.87975,2.67232 -0.22875,1.14241 -0.44415,2.38719 -0.43937,3.55197 0.01,1.44865 0.0623,2.89489 0.54092,4.26214 0.25525,0.72907 0.71643,1.40578 1.28572,1.9283 0.56835,0.52207 1.29566,0.87604 2.02935,1.11621 0.41072,0.13491 0.85346,0.17274 1.28579,0.16935 1.00285,-0.01 2.03715,-0.0883 2.97671,-0.43999 0.66497,-0.2489 1.21759,-0.73399 1.79298,-1.1502 0.75304,-0.54475 2.16476,-1.86006 2.16476,-1.86006 l 0,1.62374 -0.5751,0 0,1.48807 6.86709,0 0,-2.84135 -1.92841,0 3.21374,-23.57782 -7.37422,0 0,2.33412 z m -93.60062,7.55781 2.33363,15.57933 6.23084,0 4.04243,-11.34169 1.62654,11.34169 5.88425,0 7.05633,-16.38872 0,-2.0141 -6.1713,0 0,2.82349 1.88966,0 -4.04243,10.16973 -0.74151,0 -1.29167,-12.55773 -5.38194,0 -4.7361,12.50989 -1.55478,-12.94538 -6.86496,0 0,2.82349 z m -12.15,0.72146 c -0.56264,0.0892 -1.03524,0.17358 -1.53086,0.45447 -0.737,0.41808 -1.46132,0.95771 -1.91357,1.67437 -0.44123,0.70048 -0.53204,1.57581 -0.66975,2.39196 -0.1751,1.04003 -0.20064,2.10306 -0.19136,3.15741 0.01,0.81614 -0.0138,1.66577 0.35879,2.39197 0.1904,0.37315 0.52874,0.80945 0.88503,1.02855 0.56015,0.34453 1.06632,0.55494 1.72222,0.598 0.72597,0.0483 1.48801,-0.18852 2.10493,-0.57408 0.59422,-0.37072 1.03334,-0.97401 1.38735,-1.5787 0.46117,-0.78744 0.70905,-1.69257 0.90895,-2.58334 0.20377,-0.90704 0.33579,-1.84565 0.28703,-2.77468 -0.0491,-0.92714 -0.18211,-1.88434 -0.57407,-2.72684 -0.2728,-0.58681 -0.70954,-1.00753 -1.29166,-1.29165 -0.44403,-0.21628 -0.99455,-0.24402 -1.48303,-0.16744 z m -6.62442,-0.73581 c 0.65404,-0.6664 1.4072,-1.25479 2.23273,-1.69161 1.0305,-0.54505 2.16429,-0.92749 3.31518,-1.11604 1.51307,-0.24806 3.09342,-0.2847 4.60036,0 0.88055,0.16632 1.78322,0.44742 2.50307,0.98113 0.77409,0.57312 1.35279,1.40936 1.79291,2.26639 0.42901,0.83457 0.6828,1.77223 0.77798,2.70605 0.16564,1.61985 0.024,3.29135 -0.37201,4.87103 -0.33328,1.33759 -0.88436,2.64754 -1.65745,3.78889 -0.67549,0.99679 -1.52894,1.91262 -2.53721,2.5709 -0.89957,0.58746 -1.9718,0.87641 -3.01035,1.15006 -0.87153,0.22963 -1.77166,0.4095 -2.67235,0.40576 -1.21068,-0.01 -2.47998,-0.0817 -3.58589,-0.57511 -1.09854,-0.48896 -1.89728,-1.32739 -2.60455,-2.30013 -0.61123,-0.83995 -1.02561,-1.59975 -1.31932,-2.87516 -0.2125,-0.9233 -0.40006,-2.19912 -0.37215,-3.14592 0.0335,-1.16537 0.3568,-2.74121 0.83416,-3.80434 0.52547,-1.17098 1.17609,-2.3161 2.07489,-3.2319 z m 94.95184,13.82318 c -2.20516,1.01761 -4.61429,1.69636 -7.02343,1.69636 -5.32726,0 -7.22678,-3.12145 -7.22678,-7.22678 0,-7.1251 4.54685,-11.19645 10.0772,-11.19645 3.7324,0 5.56453,1.69625 5.56453,4.47856 0,4.85189 -5.12329,6.27735 -10.41633,6.82001 0.10168,1.73076 0.81446,3.32485 3.3592,3.32485 1.2218,0 2.88401,-0.37315 4.91982,-1.22099 z m -3.22292,-11.77374 c 0,-0.81423 -0.57695,-1.28891 -1.62876,-1.28891 -1.89988,0 -3.46041,1.66212 -3.96978,4.34287 1.45897,-0.20368 5.59854,-0.91613 5.59854,-3.05396 z m -30.33408,11.77374 c -2.2054,1.01761 -4.61457,1.69636 -7.02371,1.69636 -5.32653,0 -7.22671,-3.12145 -7.22671,-7.22678 0,-7.1251 4.54679,-11.19645 10.07785,-11.19645 3.73175,0 5.56382,1.69625 5.56382,4.47856 0,4.85189 -5.12273,6.27735 -10.41568,6.82001 0.10142,1.73076 0.81422,3.32485 3.35884,3.32485 1.22158,0 2.8842,-0.37315 4.91994,-1.22099 z m -3.22305,-11.77374 c 0,-0.81423 -0.57638,-1.28891 -1.62883,-1.28891 -1.89959,0 -3.46023,1.66212 -3.96971,4.34287 1.4591,-0.20368 5.59854,-0.91613 5.59854,-3.05396 z m -82.36051,20.5268 -0.0679,-0.13571 0.98406,-5.66614 2.10303,-15.16698 c 0.0687,-0.40664 -0.0332,-0.61046 -0.30522,-0.71214 l -1.66259,-0.61111 0.37379,-2.57855 6.78556,0 -0.40663,2.71427 0.10142,0.0335 c 2.0016,-1.86631 4.10566,-3.08743 6.24306,-3.08743 2.91821,0 4.95366,1.86577 4.95366,6.78561 0,4.68241 -1.83206,11.6379 -8.14271,11.6379 -2.20534,0 -3.42694,-0.84825 -4.68256,-1.73039 l -0.74621,5.08917 c -0.0341,0.37361 0.0326,0.50898 0.47457,0.54273 l 3.42697,0.33969 -0.37385,2.5447 -9.0589,0 z m 6.78613,-12.04485 c 0.84787,0.71258 1.96788,1.32305 3.22348,1.32305 2.74798,0 3.76601,-3.86811 3.76601,-6.85368 0,-2.002 -0.47476,-3.32542 -1.76432,-3.32542 -1.35696,0 -3.08763,1.4591 -4.30913,2.54506 z m 81.08934,4.85147 0.33969,-2.54464 1.56064,-0.2038 c 0.47498,-0.0683 0.5429,-0.1695 0.61084,-0.67837 l 1.42466,-10.34864 c 0.0335,-0.37315 -0.0335,-0.61046 -0.33914,-0.71214 l -1.69691,-0.61111 0.37365,-2.57855 6.71797,0 -0.44097,3.05395 0.10191,0.0679 c 1.32326,-1.89982 3.22359,-3.46042 5.39485,-3.46042 0.7463,0 2.0359,0.13582 2.61295,0.30538 l -0.84863,6.17508 -3.96972,-0.13582 -0.10157,-1.76443 c -0.0335,-0.30537 -0.10223,-0.40701 -0.37391,-0.40701 -0.64452,0 -1.69636,0.78027 -2.64651,1.76455 l -1.18674,8.61817 c -0.0687,0.54303 -0.0334,0.64474 0.47477,0.67874 l 3.22351,0.27142 -0.37384,2.51081 -10.8575,0 z"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cssscccccccccccccccccssssssssccssscssssscsssccccccccsssssssssccsccsssssssssscsscccccccccccccccccccccccccccccccsssscsssssscscsssssssscsssssssssscsssscsccsscscsssscsccsscsccccccccccsssccccccccssscccccccccccccsccccsccccccc" /><path
- sodipodi:nodetypes="cssscccccccccccccccccssssssssccssscssssscsssccccccccsssssssssccsccsssssssssscsscccccccccccccccccccccccccccccccsssscsssssscscsssssssscsssssssssscsssscsccsscscsssscsccsscsccccccccccsssccccccccssscccccccccccccsccccsccccccc"
- inkscape:connector-curvature="0"
- d="m 509.55935,174.26011 c 0.63327,0.31663 2.06355,1.10555 3.19256,1.13455 0.61476,0.0158 1.25757,-0.18443 1.76781,-0.5277 1.3288,-0.89397 2.46618,-2.23946 3.00784,-3.74661 0.21419,-0.59598 0.0258,-1.89972 0.0258,-1.89972 l -4.22153,-15.51428 -2.18993,0 0.55406,-2.95501 7.01835,0 2.82313,13.48255 5.27696,-10.68586 -2.21631,0 0,-2.92858 7.94179,0 -12.13698,24.69605 -1.87332,2.11078 -2.5329,1.4776 -2.71762,0.29022 -2.53295,-0.23748 -3.08699,-1.50392 z m -13.30698,-16.06545 c -1.0335,2.08005 -1.87803,4.80122 -0.90274,6.90883 0.4032,0.87116 1.49018,1.31738 2.4179,1.56347 0.67214,0.17793 1.42477,0.1102 2.08233,-0.11548 0.53084,-0.1826 0.97383,-0.5762 1.38432,-0.9593 0.44502,-0.4157 0.85733,-0.8875 1.14176,-1.42582 0.24113,-0.45665 0.44375,-0.93526 0.54404,-1.44168 0.22797,-1.1566 0.3958,-2.3252 0.37043,-3.50371 -0.0204,-0.96413 -0.0869,-2.06387 -0.52631,-2.92259 -0.29054,-0.56679 -0.84946,-0.79259 -1.46826,-0.94463 -0.46761,-0.11559 -0.89829,-0.0686 -1.34322,0.11597 -0.72226,0.30083 -1.38368,0.5859 -2.00879,1.05634 -0.63242,0.4762 -1.33915,0.9593 -1.69146,1.6686 z m 0.72346,-4.75648 c 0,0 2.41951,-1.99358 3.81169,-2.50482 0.79109,-0.29085 3.80953,-0.71977 4.57766,-0.3726 1.6247,0.73503 2.49408,1.73759 3.00274,2.86791 0.50868,1.13043 0.77154,2.86756 0.87911,4.12137 0.14648,1.71007 -0.15092,4.16549 -0.58904,6.34083 -0.33179,1.64636 -1.12383,3.02703 -2.02388,4.32576 -1.17506,1.6957 -2.01178,2.37286 -4.04556,2.72004 -1.09051,0.18629 -2.13814,0.51607 -3.59006,0.10268 -1.5866,-0.45183 -2.59522,-0.89615 -3.74599,-1.8017 -0.79994,-0.62933 -1.28003,-1.6992 -1.28003,-1.6992 l 0,3.11766 -5.39426,0 3.74898,-25.38802 -2.12052,-0.94738 0.0443,-2.62669 8.00657,0.0587 z m -26.22853,2.43167 c 0.32185,1.64663 0.0893,5.33062 -0.9498,7.38781 -0.33781,0.66857 -1.04588,1.46667 -1.7151,1.8733 -1.11975,0.68073 -2.44527,1.33822 -3.7466,1.18729 -0.52883,-0.0601 -1.07036,-0.37888 -1.37203,-0.81791 -0.52601,-0.76478 -0.48121,-1.71012 -0.50128,-2.63848 -0.0263,-1.17893 0.14487,-2.46835 0.42212,-3.6147 0.20635,-0.8543 0.4665,-1.74564 0.94981,-2.48024 0.43067,-0.65433 1.02178,-1.24217 1.71508,-1.60939 0.60504,-0.32004 1.32025,-0.42437 2.00521,-0.44854 0.70197,-0.0251 1.4374,0.0425 2.08446,0.31654 0.4274,0.18153 1.01882,0.3888 1.10813,0.84432 z m 1.42642,-10.68922 -0.70874,6.75362 c 0,0 -1.85753,-1.06838 -2.8735,-1.38048 -0.80562,-0.24744 -1.65802,-0.40424 -2.49984,-0.37318 -1.07069,0.0382 -2.10882,0.24369 -3.1078,0.62968 -1.01321,0.39157 -1.96724,1.04315 -2.75039,1.79572 -0.97095,0.93248 -1.67003,2.10085 -2.23897,3.3208 -0.43738,0.93753 -0.76677,1.93354 -0.9704,2.94777 -0.2523,1.26016 -0.4899,2.63324 -0.48461,3.91802 0.011,1.59795 0.0683,3.19329 0.59661,4.70144 0.28155,0.80417 0.79028,1.55058 1.41822,2.127 0.62695,0.57587 1.4292,0.96634 2.23856,1.23121 0.45301,0.14881 0.94135,0.19054 1.41828,0.18685 1.10615,-0.011 2.24705,-0.0973 3.28346,-0.48539 0.73352,-0.2745 1.34304,-0.80959 1.97773,-1.2687 0.83064,-0.60085 2.38786,-2.05176 2.38786,-2.05176 l 0,1.79104 -0.63429,0 0,1.64147 7.57478,0 0,-3.13415 -2.12721,0 3.54494,-26.00772 -8.13411,0 0,2.57462 z m -103.24702,8.33671 2.57413,17.18493 6.87304,0 4.45903,-12.51049 1.79414,12.51049 6.49065,0 7.78353,-18.07772 0,-2.2217 -6.8073,0 0,3.11449 2.08446,0 -4.45903,11.21783 -0.8179,0 -1.42488,-13.85193 -5.93654,0 -5.2242,13.79919 -1.71497,-14.27958 -7.57246,0 0,3.11449 z m -13.4021,0.79586 c -0.62064,0.0982 -1.14194,0.19148 -1.68866,0.50127 -0.813,0.46118 -1.61192,1.05641 -2.11077,1.84697 -0.48673,0.77268 -0.58683,1.73821 -0.73875,2.63846 -0.1932,1.14723 -0.22134,2.31976 -0.21116,3.48281 0.011,0.90024 -0.0148,1.83747 0.39579,2.63847 0.21,0.41165 0.58324,0.89285 0.97623,1.13455 0.61796,0.38003 1.17622,0.61214 1.89972,0.6596 0.80077,0.0533 1.64141,-0.20792 2.32189,-0.63318 0.65546,-0.40892 1.13978,-1.07441 1.53029,-1.7414 0.50878,-0.86864 0.78215,-1.86707 1.00265,-2.84964 0.22477,-1.00044 0.37039,-2.03585 0.31663,-3.06058 -0.0541,-1.02274 -0.20091,-2.07854 -0.63327,-3.00784 -0.3009,-0.64731 -0.78264,-1.11143 -1.42476,-1.42485 -0.48983,-0.23858 -1.09705,-0.26912 -1.63583,-0.18464 z m -7.30711,-0.81171 c 0.72143,-0.735 1.55219,-1.38409 2.46282,-1.86591 1.1367,-0.60125 2.38729,-1.02309 3.65678,-1.23104 1.66908,-0.27366 3.41222,-0.314 5.07446,0 0.97135,0.18342 1.96702,0.49352 2.76107,1.08223 0.85389,0.63222 1.49219,1.55466 1.97771,2.49999 0.47321,0.92057 0.7531,1.95483 0.85808,2.98495 0.18274,1.78675 0.0263,3.63055 -0.41031,5.37303 -0.36757,1.47539 -0.97545,2.92034 -1.82825,4.17929 -0.74509,1.09959 -1.68654,2.10982 -2.79871,2.8359 -0.99227,0.64796 -2.175,0.96671 -3.32055,1.26856 -0.96139,0.25333 -1.95426,0.4517 -2.94774,0.44756 -1.33549,-0.011 -2.73559,-0.0897 -3.9555,-0.63431 -1.21174,-0.53936 -2.09278,-1.46419 -2.87295,-2.53723 -0.67423,-0.92645 -1.13131,-1.76457 -1.45532,-3.17146 -0.2344,-1.0184 -0.44126,-2.42572 -0.41044,-3.47012 0.0365,-1.28547 0.39349,-3.02371 0.92005,-4.19644 0.57967,-1.29168 1.29729,-2.5548 2.2888,-3.565 z m 104.73744,15.24778 c -2.43247,1.12251 -5.0899,1.87126 -7.74734,1.87126 -5.87626,0 -7.97147,-3.44315 -7.97147,-7.97158 0,-7.8594 5.0154,-12.35035 11.11569,-12.35035 4.11711,0 6.13803,1.87105 6.13803,4.94016 0,5.35189 -5.65129,6.92425 -11.48983,7.52281 0.11219,1.90916 0.89836,3.66755 3.7054,3.66755 1.3477,0 3.18121,-0.41165 5.42682,-1.34689 z m -3.55513,-12.98704 c 0,-0.89823 -0.63635,-1.42181 -1.79655,-1.42181 -2.09568,0 -3.81712,1.83342 -4.37899,4.79047 1.60937,-0.22468 6.17554,-1.01053 6.17554,-3.36866 z m -33.46028,12.98704 c -2.4327,1.12251 -5.09006,1.87126 -7.74751,1.87126 -5.87553,0 -7.97151,-3.44315 -7.97151,-7.97158 0,-7.8594 5.01539,-12.35035 11.11645,-12.35035 4.11635,0 6.13722,1.87105 6.13722,4.94016 0,5.35189 -5.65062,6.92425 -11.48908,7.52281 0.11182,1.90916 0.89812,3.66755 3.70494,3.66755 1.34748,0 3.1815,-0.41165 5.42704,-1.34689 z m -3.55514,-12.98704 c 0,-0.89823 -0.63578,-1.42181 -1.79674,-1.42181 -2.09539,0 -3.81683,1.83342 -4.37881,4.79047 1.60951,-0.22468 6.17555,-1.01053 6.17555,-3.36866 z m -90.84852,22.6422 -0.0749,-0.14971 1.08546,-6.25004 2.31984,-16.73008 c 0.0757,-0.44854 -0.0367,-0.67336 -0.33673,-0.78554 l -1.83388,-0.67411 0.41228,-2.84425 7.48486,0 -0.44853,2.99397 0.11182,0.0371 c 2.2079,-2.05871 4.52887,-3.40563 6.88646,-3.40563 3.21901,0 5.46427,2.05807 5.46427,7.48491 0,5.16501 -2.02094,12.8373 -8.98192,12.8373 -2.43264,0 -3.78014,-0.93565 -5.16516,-1.90869 l -0.82311,5.61357 c -0.0376,0.41212 0.0356,0.56148 0.52347,0.59873 l 3.78017,0.37469 -0.41234,2.8069 -9.9925,0 z m 7.48553,-13.28615 c 0.93528,0.78598 2.17068,1.45946 3.55568,1.45946 3.03118,0 4.15411,-4.26682 4.15411,-7.56009 0,-2.2083 -0.52366,-3.66812 -1.94612,-3.66812 -1.49686,0 -3.40583,1.6095 -4.75323,2.80736 z m 89.44624,5.35147 0.37469,-2.80694 1.72154,-0.2248 c 0.52388,-0.0753 0.5988,-0.1869 0.67374,-0.74827 l 1.57152,-11.41514 c 0.0365,-0.41155 -0.0368,-0.67336 -0.3741,-0.78554 l -1.87181,-0.67411 0.41215,-2.84425 7.41037,0 -0.48647,3.36865 0.11241,0.0749 c 1.45966,-2.09562 3.55581,-3.81702 5.95085,-3.81702 0.8232,0 2.2457,0.14982 2.88225,0.33688 l -0.93613,6.81148 -4.37882,-0.14982 -0.11196,-1.94633 c -0.0371,-0.33677 -0.11284,-0.44891 -0.41252,-0.44891 -0.71092,0 -1.87116,0.86067 -2.91921,1.94635 l -1.30904,9.50637 c -0.0757,0.59903 -0.0368,0.71124 0.52367,0.74874 l 3.55571,0.29932 -0.41234,2.76961 -11.9765,0 z"
- style="fill:url(#linearGradient5134);fill-opacity:1;stroke:none"
- id="path5080" /></g><path
- fill="#E2E2E2"
- d="M256.023,135.437H196.36c-16.432,0-29.8,13.368-29.8,29.8v73.527c0,16.432,13.368,29.8,29.8,29.8h59.663 c16.433,0,29.801-13.368,29.801-29.8v-73.527C285.824,148.805,272.456,135.437,256.023,135.437z M191.561,165.236 c0-2.646,2.153-4.8,4.8-4.8h59.663c2.647,0,4.801,2.153,4.801,4.8v73.527c0,2.646-2.153,4.8-4.801,4.8H196.36 c-2.646,0-4.8-2.153-4.8-4.8V165.236z"
- id="path3" /><path
- d="m 531.664,250.155 h 18.498 l -2.809,18.064 h 5.59 37.586 l 2.6,-17.718 c 4.98,-1.091 9.133,-3.455 12.512,-6.693 3.084,4.075 8.566,7.37 18.252,7.37 6.338,0 12.775,-1.807 17.174,-3.687 4.254,2.399 9.463,3.687 15.459,3.687 3.088,0 6.236,-0.355 9.426,-1.023 h 67.135 l 3.354,-24.827 -5.445,-0.764 1.879,-13.356 c 0.371,-2.386 0.449,-4.66 0.449,-6.156 l -0.008,-0.375 c -0.457,-12.191 -8.139,-19.765 -20.045,-19.765 -2.404,0 -4.623,0.314 -6.676,0.852 h -34.189 l -0.035,0.244 c -2.527,-0.701 -5.41,-1.096 -8.686,-1.096 -3.801,0 -7.406,0.555 -10.76,1.598 l 0.105,-0.746 h -12.467 l 1.826,-12.951 H 615.08 l -1.846,7.658 c -1.373,5.704 -2.213,5.793 -4.453,6.03 l -4.508,0.477 c -3.049,-1.424 -6.357,-2.065 -9.602,-2.065 -2.135,0 -4.275,0.284 -6.416,0.852 h -19.291 c 0.502,-1.772 0.775,-3.674 0.775,-5.678 0,-9.601 -6.846,-16.305 -16.646,-16.305 -11.055,0 -18.775,7.721 -18.775,18.776 0,0.951 0.082,1.869 0.219,2.764 -2.135,-0.288 -4.277,-0.409 -5.553,-0.409 -2.053,0 -4.072,0.288 -6.045,0.852 h -31.342 c -2.74,-0.553 -5.641,-0.852 -8.537,-0.852 -7.138,0 -13.492,1.674 -18.808,4.723 l -3.451,-1.461 c -3.711,-1.571 -11.232,-3.262 -18.979,-3.262 -8.933,0 -16.383,2.56 -21.576,7.016 -3.265,-4.473 -8.523,-7.016 -15.228,-7.016 -4.822,0 -9.021,1.477 -12.572,3.44 -2.996,-2.204 -6.796,-3.44 -11.115,-3.44 -2.327,0 -4.48,0.315 -6.476,0.852 h -33.963 l -0.035,0.245 c -2.526,-0.702 -5.41,-1.097 -8.687,-1.097 -20.458,0 -35.307,16.031 -35.307,38.117 0,17.363 10.785,28.149 28.148,28.149 3.087,0 6.236,-0.356 9.426,-1.023 h 88.816 c 3.706,0.676 7.669,1.023 11.154,1.023 8.907,0 16.278,-2.375 21.51,-6.593 4.872,4.252 11.585,6.593 19.728,6.593 3.053,0 6.206,-0.368 9.286,-1.023 h 44.664 2.069 z"
- id="path5"
- inkscape:connector-curvature="0"
- style="fill:#e2e2e2" /><path
- fill="#F5F5F5"
- d="M255.023,133.437H195.36c-16.432,0-29.8,13.368-29.8,29.8v73.527c0,16.432,13.368,29.8,29.8,29.8h59.663 c16.433,0,29.801-13.368,29.801-29.8v-73.527C284.824,146.805,271.456,133.437,255.023,133.437z M190.561,163.236 c0-2.646,2.153-4.8,4.8-4.8h59.663c2.647,0,4.801,2.153,4.801,4.8v73.527c0,2.646-2.153,4.8-4.801,4.8H195.36 c-2.646,0-4.8-2.153-4.8-4.8V163.236z"
- id="path7" /><g
- id="g9"><g
- id="g11"><path
- fill="#FBFDF8"
- d="M195.361,251.626c-8.161,0-14.8-6.64-14.8-14.8v-73.527c0-8.161,6.639-14.8,14.8-14.8h59.663 c8.161,0,14.8,6.639,14.8,14.8v73.527c0,8.16-6.639,14.8-14.8,14.8H195.361z"
- id="path13" /><path
- fill="#F0F4E1"
- d="M255.024,152.499c5.964,0,10.8,4.835,10.8,10.8v73.527c0,5.965-4.835,10.8-10.8,10.8h-59.663 c-5.964,0-10.8-4.835-10.8-10.8v-73.527c0-5.964,4.835-10.8,10.8-10.8H255.024 M255.024,144.499h-59.663 c-10.366,0-18.8,8.434-18.8,18.8v73.527c0,10.366,8.434,18.8,18.8,18.8h59.663c10.366,0,18.8-8.434,18.8-18.8v-73.527 C273.824,152.933,265.391,144.499,255.024,144.499L255.024,144.499z"
- id="path15" /></g><defs
- id="defs17"><filter
- id="Adobe_OpacityMaskFilter"
- filterUnits="userSpaceOnUse"
- x="176.562"
- y="144.499"
- width="97.263"
- height="111.127"><feColorMatrix
- type="matrix"
- values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
- color-interpolation-filters="sRGB"
- result="source"
- id="feColorMatrix20" /></filter></defs><mask
- maskUnits="userSpaceOnUse"
- x="176.562"
- y="144.499"
- width="97.263"
- height="111.127"
- id="SVGID_1_"><g
- filter="url(#Adobe_OpacityMaskFilter)"
- id="g23"><image
- overflow="visible"
- width="422"
- height="480"
- xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEBLAEsAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA EAMCAwYAAAg2AAAQ4QAAF1b/2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIAeMBqQMBIgACEQEDEQH/ xACjAAEAAgMBAQAAAAAAAAAAAAAABQYBAwQHAgEBAQAAAAAAAAAAAAAAAAAAAAEQAAEDAQQKAwAC AwEAAAAAAAABAwQCMRMUBRBQEjMVJQYWNgcgESEwI5AiMkARAAEBAwsEAQIFAwUBAAAAAAABMQID EFAycqOz0wQ0RaURIXGRIEFRMGEiExRAgRKh0SMzQxUSAQAAAAAAAAAAAAAAAAAAAJD/2gAMAwEA AhEDEQAAANUJsrZYFfFgV8WBXxYEL0ki5fo6GjJuaRuaRuaRuaRuaRuaRuaRuaRuaRuaRuaRuaRu aRuaMHQ5dR3ojnJ9XxYFfFgV8WD0jxf2AodbslbAD6mDhlpLvI/qkuiovZL7CGzNfRCJwQacEGnB Bp0QSdEEnRBJ0QSdEEnRBJ3BBpwQacEHidwQXzPfBA6bBqK5w2nlKVH3iJitt+gAeweP+wFDrdkr Y+vmaN02k6+e3d2Gjo6N0c2zoyaM7xozuGluGluGluGluGluGluGluGluGluGluGluGnG8c/z1YO PVIfJF80xoIGPsfBVVrl6hIrD7+B7B4/7AUOt2StnXaYyxHTJ6ZKvrqb4x9MgAAAAAAAAAAAAAAA DGR8692Dh4pbkIKJscTVNiLdVY1+weP+wFDgJ+JLJORs3XbIc3dGz6ZAAAAAAAAAAAAAAAAAAAPn R0ayMi5uLqv1S51eIT2Dx/2AofB38Ra5uIm6kOzm6o+gAAAAAAAAAAAAAAAAAAAPj7+TkjJWNIOt 2et1WfYPH/YIofH2cZcJyEnKkenn6IyAAAAAAAAAAAAAAAAAAABjODmjZONIWt2WtVWPYPH/AGCK Hx9nIXGcg5ypLfo3xkAAAAAAAAAAAAAAAAAAADGcHPGyUaQ1astaqseweP8AsEUPk6+QuM7BTtSW 7TujIAAAAAAAAAAAAAAAAAAAGM4OeOkY4hqzZqzVY9g8f9gih8nXyFxnYKdqS3ad0ZAAAAAAAAAA AAAAAAAAAAxnBzx0jHENWbNWarHsHj/sEUPk6+QuM7BTtSW7TujIAAAAAAAAAAAAAAAAAAAGM4Oe OkY4hqzZqzVY9g8f9gih8nXyFxnYKdqS3ad0ZAAAAAAAAAAAAAAAAAAAAxnBzx0jHENWbNWarHsH j/sEUPk6+QuM7BTtSW7TujIAAAAAAAAAAAAAAAAAAAGM4OeOkY4hqzZqzVY9g8f9gih8nXyFxnYK dqS3ad0ZAAAAAAAAAAAAAAAAAAAAxnBzx0jHENWbNWarHsHj/sEUPk6+QuM7BTtSW7TujIAAAAAA AAAAAAAAAAAAAGM4OeOkY4hqzZqzVY9g8f8AYIofJ18hcZ2Cnakt2ndGQAAAAAAAAAAAAAAAAAAA MZwc8dIxxDVmzVmqx7B4/wCwRQ+Tr5C4zsFO1JbtO6MgAAAAAAAAAAAAAAAAAAAYzg546RjiGrNm rNVj2Dx/2CKHydfIXGdgp2pLdp3RkAAAAAAAAAAAAAAAAAAADGcHPHSMcQ1Zs1ZqseweP+wRQ+Tr 5C4zsFO1JbtO6MgAAAAAAAAAAAAAAAAAAAYzg546RjiGrNmrNVj2Dx/2CKHydfIXGdgp2pLdp3Rk AAAAAAAAAAAAAAAAAAADGcHPHSMcQ1Zs1ZqseweP+wRQ+Tr5C4zsFO1JbtO6MgAAAAAAAAAAAAAA AAAAAYzg546RjiGrNmrNVj2Dx/2CKHydfIXGdgp2pLdp3RkAAAAAAAAAAAAAAAAAAADGcHPHSMcQ 1Zs1ZqseweP+wRQ+Tr4y5TkHOVJb9G+MgAAAAAAAAAAAAAAAAAAAYzg542SjSGrVlrVVj2Dx/wBg ih8fZxlxnIKcqT6ObpjIAAAAAAAAAAAAAAAAAAAGM4OeNkY0h61Za1VY9g8f9gih8Xbwlxm4GbqW 6uLrj7AAAAAAAAAAAAAAAAAAAA+fr5OaNkI0ia1Y61Vb9g8f9gihxknCl1m65N1OdsZ3x0ZxkAAA AAAAAAAAAAAAAAAAx8fek5ozui6jazYKsRPsHj/sEUOu2Ktlqn6XZ6scjBSRLbOPpjYxkAAAAAAA AAAAAAAAAAYfJjm+uM0xXVE1xVOZr0Y9g8f9gKHW7JWz7s1W6i9SdYlasXXB9pLbI7fHY5/s3NeT 7fGT6fI+nyPp8j6fI+nyPp8j6fI+nyPp8j6fI+nyPp8D7x8fJtxp1m7Tp5jbw/MfWIjbXTk5SHsH j/sBQ63ZK2AdthqO8vXbUZWrJ0V/oJ7ZB7Sa+ofJMIkS6IySyJRLIkSyJEsiRLIkSyJEsiRLIkSy JVLYiRLYicEr8xfwSemN0kjy8PIdkfxQp0xWEAPYPH/YCh1uyVsAAz08ome2si37qZkumaULspIu 2aRkuyki7KSLspIuyki7KSLspIuyki7KSLtilC6qSLtilC6fNNFu5qz8k7wcI+vkAAHsHj/sBWoQ AAAAAAAAAAAAAAAAAAAAAAAAAHpAf//aAAgBAgABBQD/ACi//9oACAEDAAEFAP8AKL//2gAIAQEA AQUA6w6rz/LM+776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++qzvv qs776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++qz vvqs776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++ qzvvqs776rMfLPYHlHyRFUbivuDeUv1FOSVKJkRwE4CcAOAHADgBwA4AcAOAHADgBwA4AcAOAHAD gBwA4AcAOAHADgBwA4AcAOAnARciFyRUK8ndQcgyGxaaqf4fYHlHwRFUjZe68RsqbpGoKIUQkKYY kISEYJDAmBMCYEwJgTAmBMCYEwJgTAmBMCYEwJgTAmBMCYEwJgTAmCQWELCKoSFcNByEhIyxusk5 VVQV0VUL8vYHlGltupyqDlaIMREQaijcUoilMUSKgkZDDIYZDDIYZDDIYZDDIYZDDIYZDDIYZDDI YZDDIYZDDIYZDDIYZDDIYZDDIYZDDIYZDDILGQWKVRSuKORR2KPRCZltDiSYrjFXx9geUaG26nKs vy9KEjxhmONRxuOUMFLAjIjJdF0XRdIXSF0hdF0XRdF0XRdF0XRdF0XRdF0XRdIXSF0hdIXRdCsi sisFTBXHHY49GH4xMhU10y4tTFfw9geUCJ9rlcL6SNHGGBlgbZKGilsShDZQ+kPr/wBX0fSGygtC CtoVNDjI6wPsElgzCGjlLrdTden2B5QZfGvnYbCIkdkYZGmihsSn61ItJXQOtD7JIZJTBm0X6+Hs DyhP1cpjbLcVojtDLY3QIn1qZU+yugebJDRKaJ7CVUvtq27o9geURaLx6C19JFbI7Y1QU0/WqFQd oH6CS2TG/wAzZrZd0ewPKMqo2n4VH5FoGKBunVTifj9JJpJdBnVH+mj2B5RkqfdcOki0jFJQn5qm pPx5CTSS6TOKf6tHsDyjI0/2hIRU/GUKbNU1DyfklCWhm6f06PYHlGRf9QkIqfjKCWapWx4kkszj daPYHlGQ2wrItjImqlseJJMM43Wj2B5RkNsEjWNarUeJJMM43Oj2B5RkNsEjWNarUeJJMM43Oj2B 5RkNsGyLY1qtR6ySTDONzo9geUZDbBsi2NarUesk2TDON1o9geUZDbBsjWNarUesk2TDON1o9geU ZDbBsjWNarUeskkwzjdaPYHlGQ2wbI1jWq1HrJJMM43Wj2B5RkNsGyNY1qtR6ySTDON1o9geUZDb BsjWNarUeskkwzjdaPYHlGQ2wbI1jWq1HrJJMM43Wj2B5RkNsGyNY1qtR6ySTDON1o9geUZDbBsj WNarUeskkwzjdaPYHlGQ2wbI1jWq1HrJJMM43Wj2B5RkNsGyNY1qtR6ySTDON1o9geUZDbBsjWNa rUeskkwzjdaPYHlGQ2wbI1jWq1HrJJMM43Wj2B5RkNsGyNY1qtR6ySTDON1o9geUZDbBsjWNarUe skkwzjdaPYHlGQ2wbI1jWq1HrJJMM43Wj2B5RkNsGyNY1qtR6ySTDON1o9geUZDbBsjWNarUeskk wzjdaPYHlGQ2wbI1jWq1HrJJMM43Wj2B5RkNsGyNY1qtR6ySTDON1o9geUZDbBsjWNarUeskkwzj daPYHlGQ2wbI1jWq1HrJJMM43Wj2B5RkNsGyNY1qtR6ySTDON1o9geUZDbBsjWNarUeskkwzjdaP YHlGQ2wbI1jWq1HrJNkwzjdaPYHlGQ2wbItjWq1HrJNkwzjdaPYHlGQ2wbItjWq1HrJJMM43Oj2B 5RkNsGyNY1qtR4kkwzjc6PYHlGQ2wSNY1qtR4kkwzjc6PYHlGQ2wrItjImqlseJJMM43Wj2B5RkV sJSKv4yolmqVseJJLM43Wj2B5Rkf/UJSKv4ypTZqmoeX8kqS1M43Oj2B5Rki/wC0Koi1DKlC/mqa h5SSpLUzdf6tHsDyjJ6/p2HURaxiobX81TWv4/USaiXUZy59N6PYHlGXubEiE5+RaxisaqEXVCjl Q/WSayXX+Zy59ro9geUUVbNeXPpVRFdI7gzWUVfeqK6h2skOElwmu/ST3bx/R7A8oMpk/SxHiM8M OjThTX9iLqWqr6HHB50kOkp4zSVsUVKqro9geUDLit15fLSumM+MPjTw26UuCVH2moPsWoqcK3R1 4feJD5MkIiTpKvO6fYHlGiFLViuHLSpGJAzIGnyh8peKXRHEEcQ20NtDbQ2kNpDaQ2kNpDaQ2kNp DaQ2kNpDaQ2kNpDaQ2kNpDaQ2kNpDaQ20NtDbQVxBXEFdKnit8cfHpA/IJMn6TMp+0vw9geUaYU+ pmqJNprRmUNSRuSUSSmQgkgSQI+X5fl+X5fl+X5fl+X5fl+X5fl+X5fl+X5fl+X5fl+X4r4sgWQV SCuSOSR2SPSiRLREzDMlUVVVfh7A8o+EeW4wsTNKKxmYijcsollMspliSxJZjDGIYxDGIYxDGIYx DGIYxDGIYxDGIYxDGIYxDGIYxDGIYxDGIYxDGIYxDGIYxBZYssqllUsrljksdmISsxooSVmLjyqq r8vYHlHxRVRWZ77QznNI3mzSlGZUKU5hSJmKHEUOIocRQ4jScRQ4ihxFDiKHEUOIocRQ4ihxFDiK HEUOIocRQ4ihxFDiKHEUOIocRpOIocRQ4ihxFBcxQXMEKsxpHM1aQezmhB/M3nCquqtfn7A8o/hS utC9dL50vnS/eL94v3i/eL94v3i/eL94v3i/eL94v3i/eL94v3i/eL94v3i/eL94v3i/eL94v3i/ eL50vnS9dLytT7X+PrDhvHuTHJjkxyY5McmOTHJjkxyY5McmOTHJjkxyY5McmOTHJjkxyY5McmOT HJjkxyY5McmOTHJjkxyY5McmOTHJjkxyY5McmOTHJjkxyY5McmOTHJjkxyY/pP/aAAgBAgIGPwBR f//aAAgBAwIGPwBRf//aAAgBAQEGPwCPk8jmv2su47DV1z9uE90V5xHl7vuKrTXWMHDNdYwcM11j BwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHD NdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11 jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMH DNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDP+z/AEd/2MzUhXbvz7H6XVO/ Y7vFJSkpSUpKUlKSlJSkpSUpKUlKSlJSkpSUpKUlKSlJSkpSUpKUlKSlJSkpSUpKUlKSlJSkp+le p3d6ndOn4OZqQrt349EOqp0QT9PVfzGDBgwYMGDBgwYMGDBgwYMGDBgwYMGDBgwYMGDBgwYMGC9X RVh9/wAjo8nRfnmakK7d+H+LqdVEefTqonYYMGDBgwYMGDBgwYMGDBgwYMGDBgwYMGDBgwYMGDBg wYMGDBeqd/uKip2+/wAszUhXbsqOutURVT9SidhgwYMlZ/XsGDBgvYVFQVOnb6fHM1IV27J0QR95 O6idhOwyaWC9hU6d/oK6v0+GZqQrt2RFVOyCdhBJrUU/cRO6N+GZqQrt06CL07qIJNiijydGjzsu ZqQrt0dd/MRBBJsUUU/y+8uZqQrt06/YQQSbFFFOv2WXM1IV26KIJNyij0uZqQrt0e8iCTcoo/Lm akK7dHvIggk2KKKPy5mpCu3R7yIJNyij8uZqQrt0e8iCTcoo/LmakK7dHvIgk3KKPy5mpCu3R7yI JNyij8uZqQrt0e8iCTaooo/LmakK7dHvIgk3KKPy5mpCu3R7yIJNyij8uZqQrt0e8iCCTaoo/Lma kK7dHvIggk2qKPy5mpCu3R7yIIJNqij8uZqQrt0e8iCCTaoo/LmakK7dHvIggk2qKPy5mpCu3R7y IIJNqij8uZqQrt0e8iCCTaoo/LmakK7dHvIggk2qKPy5mpCu3R7yIIJNqij8uZqQrt0e8iCCTaoo /LmakK7dHvIggk2qKPy5mpCu3R7yIIJNqij8uZqQrt0e8iCCTaoo/LmakK7dHvIggk2qKPy5mpCu 3R7yIIJNqij8uZqQrt0e8iCCTaoo/LmakK7dHvIggk2qKPy5mpCu3R7yIIJNqij8uZqQrt0e8iCC Taoo/LmakK7dHvIggk2qKPy5mpCu3R7yIIJNqij8uZqQrt0e8iCTcoo/LmakK7dHvIgk2qKKPy5m pCu3R7yIJNyij8uZqQrt0e8iCTcoo/LmakK7dHvIgk3KKPy5mpCu3R7yIJNyij8uZqQrt0e8iCCT aoo/LmakK7dHvIgk3KKPy5mpCu3R4QSblFHpczUhXboqfcQQSbVFFT7y5mpCu3RPzEEEmxRRRHZc zUhXbojyfRR1RBJsUUUX7JLmakK7dk/bVfAgk2KKL37qwVV+suZqQrt2RHk+giook2L3F7i9GJ8M zUhXbsqItFRFRRO40aNmVo0aL3FhuL5+OZqQrt34I69REVFGjRo0aNGjf6po0aNGjRo0XuK5DXv9 zqrV+OZqQrt349UXt9hEVeijRo0aNGjRo0aNGjRo0aNGjRo0aNGjRo0aNGjRo0aNGjRo0Xq9/YVH V6OnVflmakK7d+XVOw3qh0e7FM7PJ7KQ0aNGjRo0aNGjRo0aNGjRo0aNGjRo0aNGjRpSKaH6V6nR 3sh1eXr+BmakK7d/C7KqFJfZTX2U19lNfZTX2U19lN72U3vZTe9lN72U3vZTe9lN72U3vZTe9lN7 2U3vZTe9lN72U3vZTe9lN72U3vZTe9lN72U19lNfZTX2U19lNfZSX2d3l/Ej/wAj/wCf+7/jD6/y f5/7tBOnX+L/AMfr+5tPKm08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptPK m08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptP Km08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptPKn/jan//Z"
- transform="matrix(0.24 0 0 0.24 174.5615 142.499)"
- id="image25"></image></g></mask><g
- opacity="0.09"
- mask="url(#SVGID_1_)"
- a:adobe-blending-mode="multiply"
- a:adobe-opacity-share="1"
- id="g27"><path
- fill="#1D2915"
- a:adobe-blending-mode="normal"
- a:adobe-opacity-share="0"
- d="M195.361,251.626 c-8.161,0-14.8-6.64-14.8-14.8v-73.527c0-8.161,6.639-14.8,14.8-14.8h59.663c8.161,0,14.8,6.639,14.8,14.8v73.527 c0,8.16-6.639,14.8-14.8,14.8H195.361z"
- id="path29" /><path
- fill="#1D2915"
- a:adobe-blending-mode="normal"
- a:adobe-opacity-share="0"
- d="M255.024,152.499 c5.964,0,10.8,4.835,10.8,10.8v73.527c0,5.965-4.835,10.8-10.8,10.8h-59.663c-5.964,0-10.8-4.835-10.8-10.8v-73.527 c0-5.964,4.835-10.8,10.8-10.8H255.024 M255.024,144.499h-59.663c-10.366,0-18.8,8.434-18.8,18.8v73.527 c0,10.366,8.434,18.8,18.8,18.8h59.663c10.366,0,18.8-8.434,18.8-18.8v-73.527C273.824,152.933,265.391,144.499,255.024,144.499 L255.024,144.499z"
- id="path31" /></g></g><g
- id="g33"><g
- id="g35"><linearGradient
- id="SVGID_2_"
- gradientUnits="userSpaceOnUse"
- x1="225.1929"
- y1="152.499"
- x2="225.1929"
- y2="247.6265"><stop
- offset="0.0123"
- style="stop-color:#C1D72F"
- id="stop38" /><stop
- offset="0.1394"
- style="stop-color:#BCD631"
- id="stop40" /><stop
- offset="0.5859"
- style="stop-color:#AFD136"
- id="stop42" /><stop
- offset="1"
- style="stop-color:#ABD037"
- id="stop44" /><a:midPointStop
- offset="0.0123"
- style="stop-color:#C1D72F" /><a:midPointStop
- offset="0.3086"
- style="stop-color:#C1D72F" /><a:midPointStop
- offset="1"
- style="stop-color:#ABD037" /></linearGradient><path
- d="M184.562,236.826c0,5.965,4.835,10.8,10.8,10.8h59.663c5.964,0,10.8-4.835,10.8-10.8v-73.527 c0-5.964-4.835-10.8-10.8-10.8h-59.663c-5.964,0-10.8,4.835-10.8,10.8V236.826z"
- id="path46"
- fill="url(#SVGID_2_)" /></g><defs
- id="defs48"><filter
- id="Adobe_OpacityMaskFilter_1_"
- filterUnits="userSpaceOnUse"
- x="184.562"
- y="152.499"
- width="81.263"
- height="95.127"><feColorMatrix
- type="matrix"
- values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
- color-interpolation-filters="sRGB"
- result="source"
- id="feColorMatrix51" /></filter></defs><mask
- maskUnits="userSpaceOnUse"
- x="184.562"
- y="152.499"
- width="81.263"
- height="95.127"
- id="SVGID_3_"><g
- filter="url(#Adobe_OpacityMaskFilter_1_)"
- id="g54"><image
- overflow="visible"
- width="356"
- height="414"
- xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEBLAEsAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA EAMCAwYAAAXBAAALIQAAEOP/2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIAaEBawMBIgACEQEDEQH/ xACYAAEAAgMBAQAAAAAAAAAAAAAABAcBBQYDAgEBAAAAAAAAAAAAAAAAAAAAABAAAAMIAwEAAgMB AAAAAAAAAAIGATIDBBQFFjZQMwcRECKQMRMSEQABAgQEBgEBBwQDAQAAAAAAAQIxcgMEEFCRsyGC M6PTNBFBIGFxEiIyE1GB0UKhscFiEgEAAAAAAAAAAAAAAAAAAACQ/9oADAMBAAIRAxEAAADy0npz Z0Dnx0DS7Q9kr0IKcIKeICeICeICeICeICeICeICeICeICeICeICeICfggp2CElQD1aXxOgc+O1s um7kKj5vpObG6d2Q9zspRA9JmSGmCHmWIiWIiWIiWIiWIiWIiWIiWIiWIiWIiWIiWIaYIeJo1sPe 4OK5C2tCVS3OmN5clN3IVHod9EOv6zWb0zkAAAAAAAAAAAAAAAAAMRJnwcVXltVuetyU3chUfp5+ 5YexhTgAAAAAAAAAAAAAAAAABjODUVxZNbnjclN3IVHIjyCx5sKaAAAAAAAAAAAAAAAAAAMZwaut rJrY8bkpu5Co5EeQWPNhTQAAAAAAAAAAAAAAAAABjODV1tZNbHjclN3IVHIjyCx5sKaAAAAAAAAA AAAAAAAAAMZwautrJrY8bkpu5Co5EeQWPNhTQAAAAAAAAAAAAAAAAABjODV1tZNbHjclN3IVHIjy Cx5sKaAAAAAAAAAAAAAAAAAAMZwautrJrY8bkpu5Co5EeQWPNhTQAAAAAAAAAAAAAAAAABjODV1t ZNbHjclN3IVHIjyCx5sKaAAAAAAAAAAAAAAAAAAMZwautrJrY8bkpu5Co5EeQWPNhTQAAAAAAAAA AAAAAAAABjODV1tZNbHjclN3IVHIjyCx5sKaAAAAAAAAAAAAAAAAAAMZwautrJrY8bkpu5Co5EeQ WPNhTQAAAAAAAAAAAAAAAAABjODV1tZNbHjclN3IVHIjyCx5sKaAAAAAAAAAAAAAAAAAAMZwautr JrY8bkpu5Co5EeQWPNhTQAAAAAAAAAAAAAAAAABjODV1tZNbHjclN3IVHIjyCx5sKaAAAAAAAAAA AAAAAAAAMZwautrJrY8bkpu5Co5EeQWPNhTQAAAAAAAAAAAAAAAAABjODV1tZNbHjclN3IVHIjyC x5sKaAAAAAAAAAAAAAAAAAAMZwautrJrY8bkpu5Co5EeQWPNhTQAAAAAAAAAAAAAAAAABjODV1tZ NbHjclN3IVHIjyCx5sKaAAAAAAAAAAAAAAAAAAMZwautrJrY8bkpu5Co5EeQWPNhTQAAAAAAAAAA AAAAAAABjODV1tZNbHjclN3IVH7+HqWTO1uxMgAAAAAAAAAAAAAAAAAYzg1Vb2NXB5XJTdyFRx5G jLc3XG9SS2MgAAAAAAAAAAAAAAAAD4+ohqq47GvTa3JTdyFR830nNm/7qp+gLVk8fuDcZgehLRBL RBLRBLRBLRBLRBLRBLRBLRBLRBLRBLRBLRBLRBLRBKQohP0MbkT40OcG8uSm7kKj5vpObAJm45sd n98SO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3xxI7PX84JcQAN5 clN3IAAAAAAAAAAAAAAAAAAAAAAAf//aAAgBAgABBQD+G3//2gAIAQMAAQUA/ht//9oACAEBAAEF AFgq7/bL9narGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxn arGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qx narGdqsZ2qxnarCYVyhn78PQNo/MCUmJhssm48QEScNrGJGEMQgjEIIxCCMQgjEIIxCCMQgjEIIx CCMQgjEIIxCCMQgjEIIxCCMQgjEIIxCCMQgjEIIxCCMQgjEIIxCCMQgjEIIxCCMQgjEIQakYQOlI bGTCajw2R5SPLm/KK2gegbR+LVYzzDZGzFKyBaysYS3FYGSBBQkFCQUJBQkFCQUJBQkFCQUJBQkF CQUJBQkFCQUJBQkFCQUJBQkFCQUJBQkFCQUJBQkFCQUJBQkFCQNkCA9uK0R7WVrJ+ykMy6WI8BrW NY0IraB6BtAsdqbMHtttYxkvKFKxhCs4JpCtExKFMy5W5jWX22NgRAitoHoG0SsBsePZZFhSSkuw peFm5dhi3qRKYk1BbAjoraB6BtCcl/8ASYtUBjCkL8Lwp2fS3WCxpVDA/wA5lFbQPQNoShGNLbif CcM3+roX9VQz4ZFbQPQNoSLP0t7P04e5uql5FbQPQNoSPXIOcPc3VU8itoHoG0JHrkHOHubqqeRW 0D0DaEj1yDnD3N1VPIraB6BtCR65Bzh7m6qnkVtA9A2hI9cg5w9zdVTyK2gegbQkeuQc4e5uqp5F bQPQNoSPXIOcPc3VU8itoHoG0JHrkHOHubqqeRW0D0DaEj1yDnD3N1VPIraB6BtCR65Bzh7m6qnk VtA9A2hI9cg5w9zdVTyK2gegbQkeuQc4e5uqp5FbQPQNoSPXIOcPc3VU8itoHoG0JHrkHOHubqqe RW0D0DaEj1yDnD3N1VPIraB6BtCR65Bzh7m6qnkVtA9A2hI9cg5w9zdVTyK2gegbQkeuQc4e5uqp 5FbQPQNoSPXIOcPc3VU8itoHoG0JHrkHOHubqqeRW0D0DaEj1yDnD3N1VPIraB6BtCR65Bzh7m6q nkVtA9A2hI9cg5w9zdVTyK2gegbQkeuQc4e5uqp5FbQPQNoSPXIOcPc3VU8itoHoG0JHrkHOHubq qeRW0D0DaEj1yDnD3N1VPIraB6BtCR65Bzh7m6qnkVtA9A2hI9cg5w9zdVTyK2gegbQkeuQc4e5u qp5FbQPQNoSPXIOcPc3VU8itoHoG0JHrkHOHubqqeRW0D0DaEj1yDnD3N1VPIraB6BtCR65Bzh7m 6qnkVtA9A2hI9cg5w9zdVTyK2gegbQkeuQc4e5uqp5FbQPQNoSLlvb+nD3N1UvIraB6BtCTN8Jbj /ScM3+rob9VQ36ZFbQPQNoTUx/xGtcdjSlb9ZwsRvwt1jMYVRR/+5hFbQPQNokZinmbPOsaWVjsM XhZuOwpbxOsYWcjtjzCK2gegbQLDdv8ANtuuDGsgTJTMYZjeCaZjBHmSlZcbgxjL9dGxDBFbQPQN oDGtK2z31pBJXYrWQLmVrCz5Whk8QVpBWkFaQVpBWkFaQVpBWkFaQVpBWkFaQVpBWkFaQVpBWkFa QVpBWkFaQVpBWkFaQVpBWkFaQVpBWkDZ4gNPkYI9zKxk7dysZdr80zTGaZoRW0D0DaPzK3Oalmyy oYwEVEv8yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXGV S4yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXB1RL/JlUMMyauU1Mt/KK2gegbRxaK2jj/wD/ 2gAIAQICBj8AG3//2gAIAQMCBj8AG3//2gAIAQEBBj8Ar2djdfxW7G01az+Ok74VzEcvF7FWJ73Z o+M97s0fGe92aPjPe7NHxnvdmj4z3uzR8Z73Zo+M97s0fGe92aPjPe7NHxnvdmj4z3uzR8Z73Zo+ M97s0fGe92aPjPe7NHxnvdmj4z3uzR8Z73Zo+M97s0fGe92aPjPe7NHxnvdmj4z3uzR8Z73Zo+M9 7s0fGe92aPjPe7NHxnvdmj4z3uzR8Z73Zo+M97s0fGe92aPjPe7NHxnvdmj4z3uzR8Z73Zo+M97s 0fGe92aPjPe7NHxnvdmj4z3uzR8Z73Zo+Ms7O7u/5Leq5yVGfx0m/KIxzotYixTC5kpbbfsfFJir 9/0EWo74+5qHH8y/3IO1Ug7VSDtVIO1Ug7VSDtVIO1Ug7VSDtVIO1Ug7VSDtVIO1Ug7VSDtVIO1U g7VSDtVIO1Ug7VSDtVIO1Ug7VSDtVIO1Ug7VSDtVIO1Ug7VSDtVIO1U4fmT+5803fP3Kn+D4qsVP v+n2LCd22/C5kpbbcUqVkX4+jf8AIiI34QTgQIECBAgQIECBAgQIECBAgQIECBAgQIECBAgQIEBe AqK1FRfuFqUE/SkWf4PhY4WE7tt+FzJS224JWqJw+f0ov/YnATgcMi4i8BeAtdifpX9yf+4WE7tt +FzJS22jKSfVeP4DUROCCcMmXgORU4KPpL/qvD8CwndtvwuZKW20dUVIcEE4Hxkyi8BHon7uC/2L Cd22/C5kpbbT5/8AoTKFG/iWE7tt+FzJS22nMomUKNmLCd22/C5kpbbTmUTKFGzFhO7bfhcyUttp zKJlCjZiwndtvwuZKW205lEyhRsxYTu234XMlLbacyiZQo2YsJ3bb8LmSlttOZRMoUbMWE7tt+Fz JS22nMomUKNmLCd22/C5kpbbTmUTKFGzFhO7bfhcyUttpzKJlCjZiwndtvwuZKW205lEyhRsxYTu 234XMlLbacyiZQo2YsJ3bb8LmSlttOZRMoUbMWE7tt+FzJS22nMomUKNmLCd22/C5kpbbTmUTKFG zFhO7bfhcyUttpzKJlCjZiwndtvwuZKW205lEyhRsxYTu234XMlLbacyiZQo2YsJ3bb8LmSlttOZ RMoUbMWE7tt+FzJS22nMomUKNmLCd22/C5kpbbTmUTKFGzFhO7bfhcyUttpzKJlCjZiwndtvwuZK W205lEyhRsxYTu234XMlLbacyiZQo2YsJ3bb8LmSlttOZRMoUbMWE7tt+FzJS22nMomUKNmLCd22 /C5kpbbTmUTKFGzFhO7bfhcyUttpzKJlCjZiwndtvwuZKW205lEyhRsxYTu234XMlLbacyiZQo2Y sJ3bb8LmSlttOZRMoUbMWE7tt+FzJS22nMomUKNmLCd22/C5kpbbTmUTKFGzFhO7bfhcyUttpzKJ lCjZiwndtvwuZKW205lEyhRsxYTu234XMlLbacyiZQo2YsJ3bb8LmSlttOZRMoUbMWE7tt+FzJS2 2nMomUKNmLCd22/C5kpbbTmUTKFGzFhO7bfhcyUttpzCZQo38SwndtvwuZKW20dTVfvQQ+cmUXiI xFhxUsJ3bb8LmSlttGVPp8/C/go1fkTjky8RyqsB9T6KvD8CwndtvwuZKW23BKNR3wqftX+qCcRO JwyLiLxF4i0Ka8V/cuFhO7bfhcyUttuCKi/CpBRtOs74cnBF/qJ+oiRIkSJEiRIkSJEiRIkSJEiR IkSJEiRIkSJEiRIkReIv6hadFfl31d9EFc5flViuFhO7bfhcyUttv2ERrvzNT/VT4qIrf+TqIdVD qodVDqpqdVNTqpqdVNTqpqdVNTqpqdVNTqpqdVNTqpqdVNTqpqdVNTqpqdVNTqpqdVNTqpqdVNTq pqdVNTqpqdVNTqpqdVDqodVDqC/xorl0F/O74av+qfYsJ3bb8LmSlttyywndtvzD/9k="
- transform="matrix(0.24 0 0 0.24 182.5615 150.499)"
- id="image56"></image></g></mask><g
- opacity="0.35"
- mask="url(#SVGID_3_)"
- a:adobe-opacity-share="1"
- id="g58"><path
- a:adobe-opacity-share="0"
- d="M184.562,236.826c0,5.965,4.835,10.8,10.8,10.8h59.663 c5.964,0,10.8-4.835,10.8-10.8v-73.527c0-5.964-4.835-10.8-10.8-10.8h-59.663c-5.964,0-10.8,4.835-10.8,10.8V236.826z"
- id="path60"
- fill="#1D2915" /></g></g><linearGradient
- id="SVGID_4_"
- gradientUnits="userSpaceOnUse"
- x1="226.1924"
- y1="159.7139"
- x2="226.1924"
- y2="200"><stop
- offset="0.0123"
- style="stop-color:#FFFFFF"
- id="stop63" /><stop
- offset="0.3788"
- style="stop-color:#F8FBF3"
- id="stop65" /><stop
- offset="1"
- style="stop-color:#F2F7E8"
- id="stop67" /><a:midPointStop
- offset="0.0123"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="0.4383"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="1"
- style="stop-color:#F2F7E8" /></linearGradient><polygon
- fill="url(#SVGID_4_)"
- points="221.189,159.714 214.142,180.951 224.048,180.951 214.142,200 238.243,173.61 227.655,173.61 236.978,159.714 "
- id="polygon69" /><g
- id="g71"><g
- id="g73"><g
- id="g75"><image
- overflow="visible"
- opacity="0.75"
- a:adobe-blending-mode="multiply"
- a:adobe-opacity-share="1"
- width="392"
- height="242"
- xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYwAAAD2CAYAAADF97BZAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAHohJREFUeNrsnYlu40gSBZMU5Z75 /4+dbUsiFwtY2JrqvIqHSEoRACFZPtqk3BV8WVcvAAAACXouAQAAIAwAAEAYAADwWgYuwSp0XAKA wzJxCRAGIgCANf8fIxaE8RIxIBaA8yeMDokgjLkNfLfyzwOAfWTRNX49EkEY5h9N6+sIAuC8/++n mXKZjJ/5UfIYPuyPRXut9WOEAXDuxOGJYEqKZPpEebyjMOYKoTO+BmEAfIYwSjG0JJFaHm8rjncS RkYE2uutwkAgAO8liezzTPqY3jl1vIMwooa+fi0SRvQzshIBgHMKYwpez5Su3jJ1nFUYLWWlznne KpHW5AEAx5fF5Aijfi0jDy91nFocZxRGJgnUMvDkkf3arDiQCMD+YshIwxKE93xy5CGJ1HFqcZxJ GEsE4b0WHa3JA2EAHEcYU8PjlJREdESp47TiOIMwIlG0yqEPPl4iDmQBcCxpZMtOmWNs+Fy2n6M7 kzSOLIy5oogk0SsfZwWCNADeSxhZMYzGYy2I8uslIY5TpY2jCiMzsikjCO2xDz4fiaNFGggDYD9h LJGF9uh9rq8+7hxxWLI4vDiOJozsKCdPFJoc5ry2JG0gDYDzJouxOrTXLJHUsuiKz4uROurS1GHL VEcShpcqNGFoZSZLBBfla6zXO0MeGXGQMgCOkyyyopgCMfzveDifs44yRdQlLKtEdei0cRRhaLKI UkXZoFtCeH7uUn3dJfF9UV8HwgA4tzDG6nktjYfy/OF8zhJLZ0hjEns01SHTxt7C8EpQmdKTlhQu lSguxmu1TLSfNac8hTQAji+MMZEsahHUx6g8743v1aQxOudzSGnsKYyoBOUlCk0StQQGRRrW4aUO bWRVpj8DYQDsI4xaFJEwPFk8FGHcDYGUR1/Jon7uzf84bIlqL2FkS1BWP8XFSRKDIozBEclgiMPq CJ8rDSQCsI0cWmWRTRaWDO7BYy2OXhFH2SE+BudymLSxhzAsWbSkCk8S3vNBkUdGGJE06pTUIgTE AbCOKLRylCYNqxyVTRV347gYX9sr4nhUotDKVPXw292l8WphtMrCSxWeEOrjqghDE0hUlrKkYaUL ZACwj1S8lBGli1oYWpL433Eznl8qWdxFL2trfRsiev/GIaTxSmFkJ99po5+0RBHJoXy8Bt+j9WmU /743qU/E7vxGGgD7JBBrCRCvs9sqRd2NZHErRDEY4iiTxV1p72ppiPx/IqDVr7GbNF4ljBZZaKnC E0UtBu3jq5E0PGFcgpJUH8gCcQDsJworXWQTRiSMWyWM5/Oheu3ZltzFLmk/lPbhkCOoXiEMreHM 9FVYsrhWz8vjS3lNE8dglKiyHd9ewqAsBbB/KcoThjbvwhpCG6WL8vgu2pRb0XbdnGpFKY26vbCG 3u4mja2Fkemz8EpQZWOulZq+gkdNIlFZaq4wBGkAHFYWIm2d3lG6uFeiKNPFt9Ku3ESfEOyJY3TS xi7S2FIYc2ThpQpLFF/Bx6U4auFckiWpFlkgCoBjiCPb8T01Jow6WVx/JHEtZPEt+oCaaD6XRUYa b1OSapXFEJSdsodVporKUZlRUpEsEAbAcaWhpYx6WK02lPamSKOWxVBIo1UY3QJpbC6PrYTROhLK SxW1LH5VUvhlvG5JQ0sXWv/FReYNp0UaAPvKYq4wxoQwvIQRlbojYayRNDaVxhbCaFmKXJNFPcrp q5LFL0UUGWlE6UJ7Y7MT9hAGwDmFEaUMb/5F3X/hjb70hulnZVFL4/Sd3l2iLNUHsrBKUL+M48v4 2EoX0ZvqlaIEYQCcWhalNKwNkrz5GPeftuRWtCk30ed8aUsYzU0WdZoo25ZaHJsJZMuSVMs8i6iv opbEX4FAnt+jdXZnZaEtby6IAuBtUsac/oxaGoPy6A2mWZoupiJldK8uTa0pjLmlKK2DOxLFX8br WllKG5Lbsn4UO+0BII1B/uzLqG9Av+XPKQHZNsU7H22IcF2e0qRx2ISRkYU1g3sISlB/KY9/OUlD 67vIyOKSKEO1JAzEAbCfKFqF4c0CL1PGUKSNm9hr1LXchHYJWYjoy4RYZSnZQhxbz8OIRDEYwvhl SOIvQxh/KenC6+hu7eSOpIEwAM4hjCXSuBRp47lW1F1p16wtoFvShSYLa++MUV7Un7GGMFpKUV66 qPssaln8bUijFoY1u9vbOGnp8NkucX0A4LWyEGmbCT6KvnzIWMjiUcgjsyGbdQOa+V0nyW/p2r2i NLVmSWqJLLR0Ycnib6ck5U3S85JFy8KCSzq5kQfA9pJokUX52AdJo6/EkVmwdM6ci2nG0TmyWE0c S4URDaPN9ltkZPG3U5bS5l1kFhecu2w55SeAfcl0FncJgXh9G30hivqxXIE2Gl3ZO6KIymPZo0xI m/VjrFWSmjsqanBkYfVd/K2kC6uj25JFZ7yxraJAEADHF8pUvTYFjbZUd+5T0UY8hfEQfapAZnRl lCpG0eeHaB/XKcOS5CriGFZ6Qyx5aPMuhiBZ/FJkoaUMTRblMNpoFvfS3fOQBcB55DEp/3e9DuJa GE9ZWO1bpvRkNeZWp7u1Z0emNDUp579YGsOCNyBKF9HIqEFp7K1U4Q2lteZcWOu4tM6xoAQF8H7S EKN0Uz9qd/B90Xh3ku+r6IxUMTpHuWWsdvRGacrr09g9YWTnW7RM0rPKU9oyIN7CgpYs1twxD3EA HJcp+f9UuxPvFGnMFUUXpANLGJ5Qyu+t/+1Ddnp3iXKUNu/iy0gYvyQ/Qa8cGaUt+5FJFiJtI5+Q A8D50kVGIpNy0zgtkIYY/0b5PLOnuHZcqpTRK0nIK0+9TBjZLVfnzOrOJI0vQxbafAuvzyJbfmK4 LMB7JAzv/+zU8H+9lEZL2zApopgMcURHVJrqRO+72a0Pw0oX0YZIVsKIylDWkuVav0UpK2upj7mi QA4A504YnkCmoLpQfm/r3hbWarmRHJ5rV3kpwytNaalqljiGhRc+U4qKNkb6ctJFnSa0uRaaLC7J ZEEZCgCBRCOoLHFMxd19JuVEndyeMLIpo98yZcwtSWWXL5/bf/El9kioL7H3tYhmW1rpYm4pCgDe RyCt4pCigRaxZ297w2fHIFWU6aJ8HOTf61uVbd5mKWOYcVFb08Wc/bm1RQTrVFH3WViy6INUgSgA oEUcWn9HL7kFEOtS1BiIojy+5P97cdSlqUfVDnspYzZLh9Vq+3Rn5mBcE6KwtlgtReEli16YiAcA 64vDayt65XszQ2ejhFFu3FTuxfFQksYo+kitXfowOrFHSnmlqGgLVi9daEt9ZCbmibAzHgBsK46u kIFUlY3pp416CmNIlqNulShuRVtYbuB0r26aR6MsNYm/d8aqwpi7DEhm74urU36K9rTQ1p23Fg9E FgCwpjjqmeFdlTK8ctS1eNT2DP+qZPFVSOMm+grcUV/G4s7v1j6MOcuYe3MwNGl8KV8b7cFd/w4i /pR8RAEAc8QRSUOqlPH8+jpljEVJqZbGl5Iq6qPc7e9eScPry5AlKWONeRjeUNpLUI7SEsUg9sxt bwZ3L/RVAMBr04bXCT5Wpam6XF+WpK7y7z6Ka5EqynQxiL2DaC/xaKnNJ+5Fayi1jpQagtKTNXN7 SKSLaClhZAEAa6cNSxrlXX5fpYyxaNdqadyVdnBuyli187ufeaG0foJMyhgMMdSlp0wZykoXIu3b qAIAzE0b2nNtBGl2YdbBaRsHJ2W0rMg9q23sGy5My2S9PnExhsTFyG6BmHkDAQBeLRFNGpeqNOXt RJppG7Wb6i6Qxiz6hpP3RNIHCSNj0swF6WaUopAFALwyZWRvri1xXIL2sWVqQbR67qrCaEkaLUNr 6wtxCWRh7ZVryQFJAMAe0ojazWe7dWlsI6/JhKG1l6KUoma1lf3Ci2RdiGyyuIg+CspbRLA3TD7n jQQA2EIe0Y21Nw1hUB6z0sgkDC8dLRZGNlVkR0hZpSdLFpfkBVhkTgCADVJGZoM5qyLjyaN1o7hV +jH6mTHL2gcjugjWBfHKUN1WJw8AsFG6iGSRLeNn2spoFOlqbWXfeDG6IHK1ysI76cyOeaQLADhr maqfIY2L5Pt5rQ7vzYfVZspUfXC0CsLq5LbGEgMAnC1laP0Z1giqls7ubBl/k07vaOiYtp6TdjKa JKJJJ9n5FqQLADhj2vCG20Y33NlSVNfwu62SMLqkNb2E0SviyMzgXrUOBwDw4pThrY6R6QPOVmo2 7fvNTNzrgs9F9bhIHH3ihC07C+kCAE4mE00ctUCiakymhN+vfZPdz4gm2fHFXSALK0V409pFWPID AM6XNrwUklnANSpZzRlS29x+zllLqiVpZBKHNwoqE6OQBgAcXRTeIoCd0x564siW8K2RUs0MMy9E 9tBOwNv4KFtjQxwA8C5C8drOLlmlya4h5a21Fy513q948llbdo48okglQn8FAJxLCt68Ma1Bt9pD 7fW1O7q7LYQRxausLaPaGivPAsC7yyTbZnZiTznIyENk4UipfuZJtp68VXLyxJGZoEfaAIAzSaJl TtuaCWOVdrJ18UHrJCNZRFErU3ZCCgDwjglDa+u6GQkjszjr5sLIJI2oA8dLGtKYMBAHAJxVDJ4s Mmv1ZWURlaNeKgxJnmBmT9kueZFFKEEBwGdJJjui9CU7j/YrnJTX6Gcn3m1SbwMAOEnyyDT4SxNF tGrtLGF4nc3euN7MbMKsGDIlKMQCAO8kjeyNdIs0Vm0vt+jDiGQS2TVbtgIAOKMkoopMa5uaEc4q 9C+8EF4UmyMpAIB3Tx4tfcGb32T3G52sVzN7iQkBAA4ogJYbbetjbxe9zFp8s8v8/Y4XCQAAkeiN uwSJQiQ3qbn1Jn/zhNHNuDCR5RAKAHyKLDKfjxJG9t/YpdNbpH1/7ZY4BgDw6TKJSvWtW0Espt/g ROes/eQtxYtQAAAOsJFc/6KTmxPJAADAF8RL29F+5xMHAEAGfz5fvHfFFu1tf8ILCgDwbrLIrAi+ xs/+CGEAACCX/FpTm9x4IwwAgPMkka2+/jDCoJwEAPAGbSoJAwDgwxr+owuDlAEAcHJIGAAAgDAA AD6At5jpDQAAJAwAAPikdIEwAAAAYQAAAMIAAACEAQAACAMAABAGAAAgDAAAAIQBAAAIAwAAEAYA ACAMAABAGAAAgDAAAABhAAAAIAwAAEAYAACAMAAAAGEAAADCAAAAhAEAAAgDAAAAYQAAAMIAAACE AQAACAMAABAGAAAgDAAAQBgAAAAIAwAAEAYAACAMAABAGAAAgDAAAABhAAAAwgAAAEAYAACAMAAA AGEAAADCAAAAhAEAAAgDAAAQBgAAAMIAAACEAQDwMUwIAwAASBgAAHDOlIEwAADgUMKYuNQAAOdu F0kYAABwGGGQLgAA1mtHd2tTSRgAAOeThvX58vhYYZBSAOBTJDAl0sXU0EauJhESBgDA/tKoG/U1 GvnVk0a/08UhNQAArJtENqff4KQydbTpyBcFAODA0titA7xf+MtPM09YuwDT1nEKAOCEaSLqw5he 1Wb2K51c5hedErYkUQDAJ0ohalen4KZ9esXN9h4zvefIBQDgE6QxSVyJmSRXllq9xN9vdBEiM2ai FwDAp0hjMm6sWxKGN9oqandTbW+/0clnkkXr8DFkAgBnl8KcG+dJ/AFFU9DGZqUQ3uT3G1yUKGJ5 1pyEkVIA8BkCySSOKHVMiTZ2tfazn3liU/IEopPPXBhkAQDvKIu5N9JTcGx2o903xpLopDIXyJNB JIgp+XsCAJxBHNkb6czN+ZT8Ppl7Q96vcNItJxHZUoKTRBAA8K4CiYbIPp+PDW1t5qb+ZcKQwIxZ C3oJA2kAwLumi0w7OiqSGKWtI3yV9rNPntyc2KQdkRk9cQAAvIscJidZWG3mqHy89IZ804SR6Zix RDFWJzlK23Axz4zIBQDOJBCRuDQ/OqLItKOrDx5asw/DkoRmxFH5mlH8OhzDbQHg3WQRtZuZhDE6 clky9201YURlqDFIGGODGT0rAwCcVRxRKX9MtJ8tJarF7WffcIJZY3mmtKJVFK+s+AYAcBYxRJ+L Sk5jcMzp12iq2myVMFpO0CpXtdoRgQDAGSQSdW5bCePRII1R8h3tL1lLaq4kyhN/SNwhHtkaUQDA UdOFVRXxkoUmh0fQfmZK/SILy/t94mS9dUsiI3on6J209jNF4o5w5AEAZxFHNM/iURxLZbFKGT+7 ltSUSBjRCKjoRB/BBaQjHADOKAmvKqP1UTyM9jFqQz2BaL/D6sJoPenROdHoKC+EVdfLCAJ5AMCR xJGpzHg32I9EW9pSltosYXiiECNWRXW4R0PUmrOoFgDAEdOFJpEoSTyPe/U4VxpzfvdFCSNKGi1W fF6Au7T1a7SsagsAsHe6EMmVo7yb63tSFF5ZalHq6Gc2utnRUZEkshdgSpw8ogCAI6YLWUEUd+fj pQkj3W6uMXEvEkdWEnfR63abxSsAgBeki7k32Hfj0BJH3W5uMlqqbzh5TyCtUSpzEVpKU6QMADhi uvCE8VBuqj1R3IMb72iY7WLmrlabnXuRsWXGng/xZ4KTMgDgiOlCGiowLdKIOr6jzetm7ZGx1bDa TN/F87glLkhLR44IczQAYL90kZnYbI2EqtvEW4M8Mqt/L2of+4YLEfVfaOb0TvJWXIybcWE8e86Z owEAsJUsrOkGmVLUXZFG1D5mb7BXm4vRz7worQkjEsVNsanVqROtzLjYogAAM2URdXA/GtrIW0Ic L524Nyy4UJm+jEdwEerj+vM4/DxeiuN/P6P7kdz487z7ed4rF6P7ea0rfueOv3EA2KAMJZLbEygr iqjNbE0X2u/YfEM9JC9MV/3gLlGWsmpz1vH98/uUx70QRl8cXXFIJY5IGoI4AGBFWbR0cFtTDeo2 8ltpH7W+jUyHt7fH92YJY3JEkZFFfVG+fxLFd5EsbkXCGKqEEQmjThmlLOp0QdoAgLVkUYujbrSt AUC3QBLWa9mEYW0V8fKSVH1xygbbGjJWlppuijQG5Yhk0SmJoa+k4EmDtAEAS0RRPnorz1ojoer2 sD40aUQDgzJbts5KGUPDxeoco0bjiy9KuhgUWVyLz1+MhOEJoyt+v1H5Gk0SpA0AyIoiksUYVFse jizqR00ac6YeTMnzWj1haHfpVsdOb0SwoUgadbK4FsmiTBnZhNFVKUNDEwdpAwCyohCZtyzSwyhD 1cdvI2lEKcOTxSpTEJb0YZSNb1mailLGUxpRGWqoRKHJonMa+k7aO8ERBwCiiEShVVesEaLlTbM1 2Oe3IwpLGLdkyvDKaZsnDE0cXSGLTMrISKNMFhdHFpYwpkIWnZM4InEgDwBEYcnCWnVWW+LDE0Ut jUgcmc7uVdeQWiIMcS5iJmXcqpLTt/w5IqpFFlGjXs/b6BrEQeoAQBTRpLxphiwsUXji8EpSWv+F yEqd3XOFMTl34V7KuFelpUtwaGWovlEW5UXqg5SRKU1NhmQA4NyCyIpCjGShDZ3V5lV8B3L4bXzu OyhFeSOkWs5/s4RhDVEt7+QfRUNfSqNMGV6qqKXRBymjlsTFKFPV3zsVH7eUpqagzAUAxxRDNmFk k8XDSBfaCKhaCv/5OTxpRB3eXt/FquvtrdGHUd+p18t2PIqGXytNXZTk4U3Sy7zxtTiespjEHmk1 JctVmWQDAOcSibXQamYDJGvobCmL34njP+L3YWRLUasOpS25zPy+srPZKhFpX+Md3pDZqA+j5Y9k 6UXrFn4eAPZPGNnyU3borCaLm1KG+k+VLLzDG17rSWOTdLFEGCJ+B7IllEgCEryWbaCjWZlrxVlE AXA+cSyRxST6sFlNFjdHFnU5yhPGb0cW1gipTSofwwpvRl3S0dZ+19JEn0waljCiIW7Px6EqS12K z2n9IyL+pEBGTQGcUxaZ5T2iDm5v8yNtUp7VZ/FPQ7Lw9gpqWdJ8t+XNPVlIUhqZklSXSBGj2JNn roU0xh9ZjIU4ns9HRxzWo9dBjlAAjlOGmgJJiCzbz8KSxbfofRSRLH47Zaho7oXIhpvKrTUPo1N+ wbFoOLPSyAgjMw66vJClLMpjlD9HYdXikMSjJocu+SYhFYBlMmhJFa2y0EZCZWRxE33IbC2Hf6rH WhatI6M230RurZKUNcy2FkerNLw33lvw6/mmXos3tlyj6iH6aKw+WRaLZIEgAPYTSKs0rEUEvdFQ 1uZH2qQ8r5/iH4k7uVtGRmlltdVYM2FYb9RYNbgZaXiNq/amWtseatJ4iD9JcKk0WjrnAWB7aXhr QXk3oJP4o6G0mdzakh9WZ/c/Ys/DiFanrTdM8q7BoUpSUWmqbOSz0rB+flSGeiSkcRF7rw1vhrlI bhgx0gDYVxhT0GjWd+FjsmJxF31TuGg2dzSk9rdRjlpj7+7DJYxsaapMG1oDG02Es5ZR90RRvsHP pdOfW79mpZFdUh1hABxfGN5EvKws6r6Let8Kq/8imt3tLWWe2fNis1LUFgnDeyNHpeF8JGThJYxo 8kx5J3AtJHFVUoa1LIkmjH6mMJAFwPbCyHZyjzOqFlay0Pa1aJnR7Y2KinbV82SxujS2Kklpo4Qm RRwtPzsShZUqvooL/0wX9QZN1gq5njhE2kZSIQ2A7WQxNT5qZai6P3SU3G559RIgVsqwEoW1wGA0 jFacEtQpEoYnjXLOQ7bxzAyh9UYtfBXiuMq/d/UbnKShiWOuNJAFwHGkYQnj0ZAublU5yts5L1qy /DuQRVSCispzpyhJlfLwImGLLKw+DC8yluIYKnFo0uiN8hTSAHgfYYwSz+HKlqIyW61qaULbqzsq Q2X7LTaTx7DRm9gF4sjKQpKi8IRx/XkjalnUfRmeNCxhRP0ZCAPgGMLwZDGJP4imlsXdKEdF+3Pf xO+rqDu4DyWLLRNG1J8RScMaAjc69UUrXVyrhOGVpYbGlIEwAM6TLsZkwshULW4N0rgpj9oM7nr4 bKss3qIkNVcaIvl16LWRUc9SVJkwhiphWH0ZLSlj7dngANAuCi1R1M+z6WIUe85FnTK+FWnclBRR J4rspLwWWWwujuGFb3KLNDL9F1Z0/DJKUbUwWstSnjSQBcDxpRHJIprRHaWMmyEIL1FEqSLb0X36 Tu9SFFlpTOKvSZ8dVntVRKEJo+78tvYWvyQSBsIAOFZJKhKG1p6MTtXCGimlPY9E8RB9BvdDkdok L1qN9ggJo0Ua2T0vvIRxlT/7MKwSVDS8NprINzdlIA6AdUQRJYy6HOUtLGi1KZnSlCWSjChaS1C7 yGKPklQkDS1teEnjUr3JQ/H4nKh3q4RxUaRxCRJGZngtHd8Ax0oYmXJUZq+LaB0p77WHxP0UD4nX htqlz2IvYWSkMUnbHhhjII5aCjcjTXjlqOxcjEgaiAJge3FkN0NqmYORKU9ZcmhJFNYM7sPI4tXC mFue0t703hFH+ca2pIkoXWRkkU0ZHogFoK1BbNk9L+rH8OZ5ZYRgPc+Iwis/7S6LPYThSUOTxyh/ 7hNei6N+oy/y7z0v7skk4fVdZIWxRBaIAmC+OLKyyHZ+eyth3wOpRENkWzc/OoQs9hJGNmlMSmNc v+F9lTZ6+fduehdFHPXn+oQoMsIQsffKQAwA24ukRRqZlOF1hkevWf0To1IWkzPIYk9hlCffGc8l SBudkjaejXmdNHrjMRLEnHSBMAD2k4WIP2CmRRqePEbxl/Cw0kRUftp1nsWRhdFaotI6xbW00RWl qmfi0NJDS5pAGADnF4ZIbk0pSxjWx1lJjOL3URwyVRxNGFrasGRRp43668dKFmVD/0gKwtqiNdrn m/kXAPsJQyS3rPmkNN7185bDks00s/R0WFkcSRiiJAxLIJNxh1+nkzFICr3zemY01JzlzZEGwD7C kERpKtv4j4mUUm9L3ZImpqNe+OHAfwzRwoWROLoqcXTiL1MepYmlu+0hCoDXlaZapZFJHlMghslJ FJnf7dCyOKoworSREYcYAukqeWTkQKoAeO+kIQl5eK+PkptDccpUcRZhiPgjqTKd4p2TRGSGIJYI A2kAbC+LrDBE8qOpWo45SWI6y0UfTvbHEZWp6mSSafQzH4vkJ+chDIB9hRHdxWdGKUWL/0Wd2G8l irMJQ5OBKOnDk4bX6GdSw1qLCyINgNcKo0UakUhE5o1yOrUozioMcWTRkjqyKSGbJOjgBjiuSLyG u6V/YU5fxFuI4szC0N6MOaljmiGDTOkJUQAcM31MM59PC37GW4jiXYShiUMkP7JK+16SBMBnp45s w9/6McI48B9GlDrq2eNTQjgIA+D9hLH11yCME6cOCdJHy89AGADnFEbm89PCr0UYb5A6ZIFAsn8o SATguIJo+fppxX8HYZz8D6n75DcfAGE0ff3HtxEDf1ipdNDyh9LxhwVwOmkgB4Sx6h9Kxx8aAGJB GLDmHxb9FwCIAGEAf6gA8Ln0XAIAAEAYAACAMAAAAGEAAADCAACAs/JfAQYAL3iXmIlSiu4AAAAA SUVORK5CYII="
- transform="matrix(0.24 0 0 0.24 179.2061 198.1514)"
- id="image77"></image><g
- id="g79"><radialGradient
- id="SVGID_5_"
- cx="225.1929"
- cy="226.1387"
- r="30.8299"
- gradientTransform="matrix(1 0 0 0.75 0 56.5347)"
- gradientUnits="userSpaceOnUse"><stop
- offset="0.0123"
- style="stop-color:#FFFFFF"
- id="stop82" /><stop
- offset="0.4828"
- style="stop-color:#FDFEFB"
- id="stop84" /><stop
- offset="0.7611"
- style="stop-color:#F8FBF3"
- id="stop86" /><stop
- offset="0.989"
- style="stop-color:#F2F8E8"
- id="stop88" /><stop
- offset="1"
- style="stop-color:#F2F7E8"
- id="stop90" /><a:midPointStop
- offset="0.0123"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="0.8025"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="1"
- style="stop-color:#F2F7E8" /></radialGradient><path
- fill="url(#SVGID_5_)"
- d="M186.706,235.825c0,5.965,4.835,10.801,10.799,10.801h55.374c5.965,0,10.801-4.836,10.801-10.801 v-19.373c0-5.965-4.836-10.801-10.801-10.801h-55.374c-5.964,0-10.799,4.836-10.799,10.801V235.825z"
- id="path92" /><path
- fill="none"
- stroke="#EDF5E5"
- stroke-width="5"
- stroke-miterlimit="10"
- d="M186.706,235.825 c0,5.965,4.835,10.801,10.799,10.801h55.374c5.965,0,10.801-4.836,10.801-10.801v-19.373c0-5.965-4.836-10.801-10.801-10.801 h-55.374c-5.964,0-10.799,4.836-10.799,10.801V235.825z"
- id="path94" /></g></g><path
- opacity="0.74"
- fill="#FFFFFF"
- a:adobe-blending-mode="lighten"
- d="M263.623,229.595c0.037-0.364,0.057-0.734,0.057-1.107 v-13.375c0-5.965-4.836-10.799-10.801-10.799h-55.374c-5.964,0-10.799,4.834-10.799,10.799v7.324 c7.545-1.012,15.699-1.566,24.213-1.566C231.959,220.87,250.812,224.252,263.623,229.595z"
- id="path96" /><linearGradient
- id="SVGID_6_"
- gradientUnits="userSpaceOnUse"
- x1="225.1929"
- y1="204.3135"
- x2="225.1929"
- y2="246.626"><stop
- offset="0.0123"
- style="stop-color:#FFFFFF;stop-opacity:0"
- id="stop99" /><stop
- offset="0.0141"
- style="stop-color:#FDFDFC;stop-opacity:2.231669e-04"
- id="stop101" /><stop
- offset="0.1344"
- style="stop-color:#BEBEAF;stop-opacity:0.0148"
- id="stop103" /><stop
- offset="0.2565"
- style="stop-color:#94957C;stop-opacity:0.0297"
- id="stop105" /><stop
- offset="0.3796"
- style="stop-color:#747759;stop-opacity:0.0446"
- id="stop107" /><stop
- offset="0.5029"
- style="stop-color:#5D633F;stop-opacity:0.0596"
- id="stop109" /><stop
- offset="0.6263"
- style="stop-color:#4D552E;stop-opacity:0.0746"
- id="stop111" /><stop
- offset="0.75"
- style="stop-color:#414B23;stop-opacity:0.0896"
- id="stop113" /><stop
- offset="0.8742"
- style="stop-color:#3B461E;stop-opacity:0.1047"
- id="stop115" /><stop
- offset="1"
- style="stop-color:#38441C;stop-opacity:0.12"
- id="stop117" /><a:midPointStop
- offset="0.0123"
- style="stop-color:#FFFFFF;stop-opacity:0" /><a:midPointStop
- offset="0.2901"
- style="stop-color:#FFFFFF;stop-opacity:0" /><a:midPointStop
- offset="1"
- style="stop-color:#38441C;stop-opacity:0.12" /></linearGradient><path
- fill="url(#SVGID_6_)"
- a:adobe-blending-mode="darken"
- d="M263.68,221.954v13.871c0,5.965-4.836,10.801-10.801,10.801 h-55.374c-5.964,0-10.799-4.836-10.799-10.801v-13.871l0.038-7.704c0,0,0.923-9.937,11.173-9.937h54.962 c0,0,10.063,0.328,10.801,10.799V221.954z"
- id="path119" /></g><g
- id="g121"><g
- id="g123"><image
- overflow="visible"
- opacity="0.25"
- a:adobe-blending-mode="multiply"
- a:adobe-opacity-share="1"
- width="30"
- height="30"
- xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAhCAYAAABX5MJvAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAuJJREFUeNrsl9trE0EUxjO7m5vW tKFN1RqLCmqlIvjgkz5I/cOFIqLggw9KsRHxUo1IdEtactG9+A1+A8dxNrsxK/rgwI9lt5ueb875 ZuZspfJ//Bhqjvc0AfCIHClIQEzSMkUoBqyCJbAKWrxXQoBmBL6AQzChmGQREWbmNQY/DS6Aa6AL mtZvdcDPoEcOQEgxUV5mVMYzH5wCZ8FFcJ0CLoN1UHeIGII34AV4BvbBW4qbzsqKctzruq+ALXAL 3ABXwAafNyjS9sQ3cAwG4BXYA0/AU/AejLOE+I4MtME22AH3wE2wyedNivSFQT3eB/y79kwHnGE2 v4IjinCaNrBEtJiBu2SLs686VkRWGRt8/wTL5jFwxIxMbSGB+Ac1qtcluEMBbWslFDV7QBFdlmBE bwxZtthVDn1dpgF3WIIOhakF9iCf2ajQK32W5hcRJgvnmYHb9ECzQAnyhif8o7PxkWImsiQeRSyJ fWCjJAGy5G2usKtgzc6wx5dWxT6wYhm2jKNBm/UcV90m/aLsdLVoonX+QJV8RvmcXNflNVOOKktQ Fz4p+6AMrBg/GUeeFWUHd51HyuXevz7+GRELNSRzjMwYnmhI5Laa/gEBYxEjskVE7Ih67AeOi3ZE BYc55j+xxzjgpBMpImZL1mNDMuDxm5aYBT2x1+wx+vZJ6lt94kl2Ux1uWl4JWZhy9g/AQ/DOPjt8 q0ULuLebhiRYYO8wPUTIdm+X1zDrKE/FKjH95TL3eP83MiIF7FHAY2ZkYpfadxhoRE80WJ66EKIK BE9YAiPgPkW8dPUSFUfDGnMpHVmKvQJCEoofcsamBLs0fOgSUMnomo2QQ66UAbMTi4+hmOk2mGZW B39OE+rgj5iBcNb3h5qxk9boDb1SLrEh2c75+NlnCfT1A4OP8nZiVeAT0IhZY0Ni+gHP8oEpQ59Z HHP2uRtfkeUnxTj7AWHqMU0ZiRVX2ld5kZ4jnSewHN8FGACSOOKkAlOGAAAAAABJRU5ErkJggg=="
- transform="matrix(0.24 0 0 0.24 199.0298 216.5547)"
- id="image125"></image><g
- id="g127"><radialGradient
- id="SVGID_7_"
- cx="202.6289"
- cy="219.7041"
- r="2.9995"
- gradientTransform="matrix(1 0 0 0.75 0 54.926)"
- gradientUnits="userSpaceOnUse"><stop
- offset="0.0123"
- style="stop-color:#FFFFFF"
- id="stop130" /><stop
- offset="0.4235"
- style="stop-color:#FAFCF6"
- id="stop132" /><stop
- offset="1"
- style="stop-color:#F2F7E8"
- id="stop134" /><a:midPointStop
- offset="0.0123"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="0.6235"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="1"
- style="stop-color:#F2F7E8" /></radialGradient><circle
- fill="url(#SVGID_7_)"
- cx="202.629"
- cy="219.704"
- r="2.999"
- id="circle136" /></g></g><g
- id="g138"><image
- overflow="visible"
- opacity="0.25"
- a:adobe-blending-mode="multiply"
- a:adobe-opacity-share="1"
- width="30"
- height="30"
- xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAhCAYAAAC1ONkWAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAtFJREFUeNrsmP1LFEEYx292Ts3V 9ujFrCiwFyPShH4I+imoiPqbhYKIoKigN0W8SulNIrOU63S921u/A9+BYdm9mbndg4IGPiynuzOf eea52WeuVvvf/Joo8VwA6rxm+0lBD3R5TYctpu6XYBRE4DiYzMhpqRbYBDtgHyQ+gsIzQmMUOg3O gzkwzciZTUXqO1gCH8E3CsauERSOUiOgAc6AC2ABXAYXwZECsV/gPVgBb8AH8AVsg45NTjhKTYGr 4Aa4AmYZqYjLmpdj+4ySilwTLIOn4C34YZOTjlLXwH1wC8xzKSMureQym0g+O85ITxP1uU3hPS6r t5j63zFK3QM3uYwNQ0g45KUSPMSJNLjsLS71blHUZJ9Ox5lDSuo2k32SHYsBvslKcAIc5jJvUK7r I1ZntK6Du8yryBJhW9P73hi3jg2ym7ek0hKtO0z4E5xx2RYYOany7DPYyotaUPCwyoVL3KemKpLS TX+h5jhGI88jT0x9/U9yrzoHwoL7ykQtZN8LHGvURUxy05xhntWH8I7WOTzDsaSLmOAMQl6DIYgF mTGEi5iWEyWqD9dtpHCMoPaXtn9KrHSR59CsYxSJ6SKv1e9FW6L1MmM4iXWMIu8ri7u04mjF7HuJ Y3VcxLqciaqfVlnYJRWKJexzlWNs5r2SZMGMNOp1cRYc5atEVBCtPVazD8AzHzHdQUKZUyzywoIT kY9Uh9XrC4o1WTimPmI9ouv9iAXfIHKm1GtKvSyKlq2C1Una5sMTLBRHPN4MOvIxpV6BRfCEJU/s W8Ganf4xzoaCf5dGaS36JHnMKnWNUg/BY35uD1rza7ku5bY4658cMDHkEt6nUZP4TQG1dI/Ic/CJ /SVVHHglS2J94pnluXLecuB9x3Nlk5+3jUlV9hOBMAQjCpn1lMikgFrCdQrtGEKp62CDlCtaMLQc eNu+QmV/7XGp2cyN2rsdCDAAoyXZx8WJpTUAAAAASUVORK5CYII="
- transform="matrix(0.24 0 0 0.24 213.9448 216.5547)"
- id="image140"></image><g
- id="g142"><radialGradient
- id="SVGID_8_"
- cx="217.5439"
- cy="219.7041"
- r="2.9995"
- gradientTransform="matrix(1 0 0 0.75 0 54.926)"
- gradientUnits="userSpaceOnUse"><stop
- offset="0.0123"
- style="stop-color:#FFFFFF"
- id="stop145" /><stop
- offset="0.4235"
- style="stop-color:#FAFCF6"
- id="stop147" /><stop
- offset="1"
- style="stop-color:#F2F7E8"
- id="stop149" /><a:midPointStop
- offset="0.0123"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="0.6235"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="1"
- style="stop-color:#F2F7E8" /></radialGradient><circle
- fill="url(#SVGID_8_)"
- cx="217.544"
- cy="219.704"
- r="2.999"
- id="circle151" /></g></g><g
- id="g153"><image
- overflow="visible"
- opacity="0.25"
- a:adobe-blending-mode="multiply"
- a:adobe-opacity-share="1"
- width="30"
- height="30"
- xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAhCAYAAAC1ONkWAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAttJREFUeNrsmO9r00Acxptc1m6d Fn9M125sU4RVpyjiSwXB/9wXulciiE4dhpUMpwzFUa02XdP4HDwHR7hcLk0mCh58WOnI9548973k uTYa/0e54c15nQ8E8TJ1UpKQ2Z8QJgUtgDa4CC6AliZOiYrBCfgGfoLTsgK9OQStgE2wDa6DDv+v hhQwBAdgH0TgS1mBLsIEBV0F18BNcJvC1sCyQdgIHFHYG/AODMAxBSZVhQXgHJ15AO5T2Aa4TMHC 0GMJBXwFhxT2Erygkz/AtGhim1NS1A3wCDwGO+AKBS3QKS+nrlp6eQProKe5G4LvNucCS0+1uXQP wRNwj6JaFkH6SgitNxeJ0BwNueSzMsIC3ulduiX/roJmpp9cWkVQ1CrrqB17ws+TPGdM3y3Rftnk fTpVVlS2ZpN1+qy7znl8V2HSrUvcdbKnutryVRk+63RZd5vzBC7ClFvyMXALbHEDiJreNGpDbbH+ Wp5rJmEd7sQ+n13NCq8uU881WbfPeTquwtq0u1ezW1nXepyn7SJM9dgSCc4oPBTO4Rus9jKJwatZ lGeZy+rYXzH+GWEpXxEq5Kl8VecwBcnURVjMgCcZn5GwsTZH7CJMD3khL5zWLGzKuiHnGZpe5CZh I6bO9wx7v+bN7YYxY70j1o/yEoZpKSdMmntMoMq1tIYlVG7ts/4x50tddmXCEDfgxRETZ1JRWMI6 EesObGFRWCyfaa+oDl8jQd4DscApJUr21S54Dj7wu1JBUW2Ct1rybDDRntditUtPnWor8Aw8Zd2h rXdFQdGYd6WfbPTYnOeeEiSv/cTDyC5FvbL1luspSSXPFUYUmaHu8KS0yfjdMpySYp6QIop6TZdC njEnRTvdpVc8Lt0yBW4wS+04HHj3+Fg4pKARnUxdJnVNBL7hSNal4OxPBFLAZ/CRzumn8NR1wrKR xdfy1KLlwDvmw3RaRlDVX3s8h8dGWiUE/BZgAMf82R9IYLF+AAAAAElFTkSuQmCC"
- transform="matrix(0.24 0 0 0.24 228.8599 216.5547)"
- id="image155"></image><g
- id="g157"><radialGradient
- id="SVGID_9_"
- cx="232.459"
- cy="219.7041"
- r="2.9995"
- gradientTransform="matrix(1 0 0 0.75 0 54.926)"
- gradientUnits="userSpaceOnUse"><stop
- offset="0.0123"
- style="stop-color:#FFFFFF"
- id="stop160" /><stop
- offset="0.4235"
- style="stop-color:#FAFCF6"
- id="stop162" /><stop
- offset="1"
- style="stop-color:#F2F7E8"
- id="stop164" /><a:midPointStop
- offset="0.0123"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="0.6235"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="1"
- style="stop-color:#F2F7E8" /></radialGradient><circle
- fill="url(#SVGID_9_)"
- cx="232.459"
- cy="219.704"
- r="2.999"
- id="circle166" /></g></g><g
- id="g168"><image
- overflow="visible"
- opacity="0.25"
- a:adobe-blending-mode="multiply"
- a:adobe-opacity-share="1"
- width="30"
- height="30"
- xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAhCAYAAABX5MJvAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAt9JREFUeNrsl91rE0EUxTOzm69a 05YmVWsUFdRKRfDBJ32Q+ocLRUTBBx+UYiOitlqRaEos2UT3w3P1jIzrbHZNVuiDAz9CNru5Z+69 M3O2Uvk/fg414zOCDzSxRwJiEJGkTBGKAatgEayCFr8rS4AwAp/BIRhTTDyPCDPzGoOfAhfANdAF zdT/SMBPoEf2wYBiQldmVAEBHjgJzoCL4DoFXAZroO4QMQRvwAvwDOyCtxQ3SWdF5QiQui+DDXAL 3ABXwDqvNygy3RPfwBHog1dgBzwBT8E7ENhCvJwMrIBNsAXugZvgPK83KdKzGlTzu8/fpWc64DSz +RV8oYhfTetPEdFiBu6SDc6+6lgRWZNo8P4Flk0zcMiMSGkSP+MPalQvJbhDASuplVB0RfkU0WUJ RuyNIcsWucoh15bYgFssQYfC1Bz7kcdsVNgrByzNHyJMFs4xA7fZA80CJcgb2uofycYHihlrh4hF ax9YL0mAGT7LKivsKmjLpLXjplVrH1ie0ryzlkWa9SxXnWR5QTv6ocUmWuMDqlLu8Di5ruk1Vzmq LEGdD5QtQln7yI8YespZUXbwzBi6cgzGsRTx14ZkxvFbDJeI9Laa/AMBgRUjTIsI6Yh69ANH0xzR DMMc8x/pMcTwjNIiIlqyHg1Jn8dvUmIWZGKv6THk/Jh4GWqFE3RTHW5auoQsTDj7B+Ah2JOzI8vU RNxQ2pYh8efYO4yHGNDubfNzkHWUJ9YqMf5yiZ7AmyEjtoAdCnjMjIj5TbycBhqxJxosT90SogoE j1kCI+A+Rbw0XmKaxzQlCXjz2GpOXUBITPFDztiUYJsNPzAC8kQklpBDrpQ+sxNZL0MR020wZlaC P2cTSvBHzMAg/f6hCu6qNfaGrJRLNCSbOS8/uyyBfL5n8JFrJy7a7Solpk1DYrynTvWBKcMBsxhw 9nEZL8S2GNtzuJo6YFOG1oor7a28iOdI8gLb47sAAwCDFN6m03jgxgAAAABJRU5ErkJggg=="
- transform="matrix(0.24 0 0 0.24 243.7749 216.5547)"
- id="image170"></image><g
- id="g172"><radialGradient
- id="SVGID_10_"
- cx="247.374"
- cy="219.7041"
- r="2.9995"
- gradientTransform="matrix(1 0 0 0.75 0 54.926)"
- gradientUnits="userSpaceOnUse"><stop
- offset="0.0123"
- style="stop-color:#FFFFFF"
- id="stop175" /><stop
- offset="0.4235"
- style="stop-color:#FAFCF6"
- id="stop177" /><stop
- offset="1"
- style="stop-color:#F2F7E8"
- id="stop179" /><a:midPointStop
- offset="0.0123"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="0.6235"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="1"
- style="stop-color:#F2F7E8" /></radialGradient><circle
- fill="url(#SVGID_10_)"
- cx="247.374"
- cy="219.704"
- r="2.999"
- id="circle181" /></g></g><g
- id="g183"><image
- overflow="visible"
- opacity="0.25"
- a:adobe-blending-mode="multiply"
- a:adobe-opacity-share="1"
- width="30"
- height="30"
- xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAhCAYAAABX5MJvAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAn9JREFUeNrsl+lrE0EYxvdKjSZW YxEPxBsVrNdHQTxA/KMFBRGPDwoVVIpoq3jUeJUG25qk2fVZ+A28WTabxG4lHzrwgxw78z7zzMw7 73reBDR/jOcCUREhn21LRCy6osfn0kT4BN0h9oiDoiGmTN8Efoum+CHWEBRvRoSbeZXgR8QZcVEc F7syfTcI/kq8Fgviu1jlv3hcET627xXHxFlxWZwXJ8RMxgmPIKkTn8UbMSdeinfiq1hnmUYS4QTs F5fENQSc4rfUgahgT7TFivgk5sVj8VQs4kqukGiAgCviDiKOijr/BUOWL7t/9uGaVyTEighYggsI uI79NQYfdY9FPF8x/WL2xiJLk9hOoelcJehtcYslqI8hYNDGrvP9G5t1PbtRQ+NIg/W/KWaxNNpk DnK5JZ35TzbuCq70ibAu3BBXxWHW1i8hGbpc0+akNLNuBDAtTopz4kBJAuxEC8cPzIlI88BpOoQl Xw1TuDtLsqvZkxbwUA2FjZxEVJYbdROj4mWOpVuzCMoWYGPlxggm4SrfFmFFJOTzDUi2KFY8KIYT sUoSWRadLRDSM0XPMgVPn4guOT0tSN6KVtHd/w8tYWJfqDHeM+m+jBkTeIEaoEmKTUp0oXD80Kjt kU4PkVSqJWTOhIDpFf5APBFLOOPliYhxZgYR00MKmVEEuKWeQ8Q8ruRe5Xb3po7s5CqvDSjnxhVw XzzjFu3k5XTbuuziNYLvZolCk+KHBU8n8QcBL8Rd8VB8yCto8kTEDNBCTIdBg4wQvyD4L6rsdOb3 xKNhhW44IKm4wZaghSAnoIdrHWhz/m3wlOfiI86OXPJPzMvPxLwG/tcX4u3m2l8BBgBQ/dU5d1Za tAAAAABJRU5ErkJggg=="
- transform="matrix(0.24 0 0 0.24 199.0298 230.2217)"
- id="image185"></image><g
- id="g187"><radialGradient
- id="SVGID_11_"
- cx="202.6289"
- cy="233.3711"
- r="2.999"
- gradientTransform="matrix(1 0 0 0.75 0 58.3428)"
- gradientUnits="userSpaceOnUse"><stop
- offset="0.0123"
- style="stop-color:#FFFFFF"
- id="stop190" /><stop
- offset="0.4235"
- style="stop-color:#FAFCF6"
- id="stop192" /><stop
- offset="1"
- style="stop-color:#F2F7E8"
- id="stop194" /><a:midPointStop
- offset="0.0123"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="0.6235"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="1"
- style="stop-color:#F2F7E8" /></radialGradient><circle
- fill="url(#SVGID_11_)"
- cx="202.629"
- cy="233.37"
- r="2.999"
- id="circle196" /></g></g><g
- id="g198"><image
- overflow="visible"
- opacity="0.25"
- a:adobe-blending-mode="multiply"
- a:adobe-opacity-share="1"
- width="30"
- height="30"
- xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAhCAYAAAC1ONkWAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNrsmM9r1EAUx3cz2XW1 il2wLLagIh5aeilUBC967EX/XA/1It5aUaiC2JNY/EWp0lZkG3c3id+Bz0AIaXayibKHDnzIJfPm s29eZl/Sas3paNeYZ0SHaz5OKmIx5pr+azF7fyh6oi+WxXURZGJZiUScim/iWERiUkWwXTFDlxG6 I1bFBnKd3P1jpPbEvviE4JlvBtueUl1xQ9wVa2ITsdtkzOTmxGTsALE34oP4KH6I0TS5tofUJXFT PBCPxToZ67OlZTUWkSmbsffipXglvos/ZXLGI1N2qx6Kp+KRuFcgVYRh/oJYEgNxle08EUNqsbJY SDAnZa8r1FlYoQzc02sFF5n/W/wskzMlAReopydkaoVtDWocL1bqGtv8Bblx0YSgJFt9xNbJXLfG uZctjQEx11gj9M2YDXCFiVviflmAGeQCYtlt/MxTOvbJmEFkFZqSyu9GNr7xEXNP4gbnVK/mFhZl rUdsd0B3fcQCDs3lcw7PJobJrRH4iE37g24qa6VrBK05HRdiTYjVbvI8xtQ1isSyTd4pE5secW6N xEdslGnyDmhd0oazFRF7j7VGPmIxPdQ+HNMWNzUmBfFj3+7C1YDtMG7RT3UaONMS+jErtC1e05tV EksyPdkAyToHbsqW2e51R7ygs42qNooJaU/oPF2TF8wgl2SkdsVz8Y5sJVXFUvryX6TfNXld5HwE U37cWUbqGdfDsto1njVxQjscQ8jc8+SckO25jqipHTK1i+Ro1peR7FM6pKH7StAhC7uam7CQI+J+ J7RNTb0lU7Vf3+b6hXeuPxH8948qF6Pq+CvAAGGezDColMK7AAAAAElFTkSuQmCC"
- transform="matrix(0.24 0 0 0.24 213.9448 230.2217)"
- id="image200"></image><g
- id="g202"><radialGradient
- id="SVGID_12_"
- cx="217.5439"
- cy="233.3711"
- r="2.999"
- gradientTransform="matrix(1 0 0 0.75 0 58.3428)"
- gradientUnits="userSpaceOnUse"><stop
- offset="0.0123"
- style="stop-color:#FFFFFF"
- id="stop205" /><stop
- offset="0.4235"
- style="stop-color:#FAFCF6"
- id="stop207" /><stop
- offset="1"
- style="stop-color:#F2F7E8"
- id="stop209" /><a:midPointStop
- offset="0.0123"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="0.6235"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="1"
- style="stop-color:#F2F7E8" /></radialGradient><circle
- fill="url(#SVGID_12_)"
- cx="217.544"
- cy="233.37"
- r="2.999"
- id="circle211" /></g></g><g
- id="g213"><image
- overflow="visible"
- opacity="0.25"
- a:adobe-blending-mode="multiply"
- a:adobe-opacity-share="1"
- width="30"
- height="30"
- xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAhCAYAAAC1ONkWAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAlRJREFUeNrsmM9LG0EUx5PdjTTW otDYWmoOQm2M/YGXnrxI/3IvnnoRW7TagocotqjQtLYp5pffgc/CECc7u+uGpuDAB2Y32Tff9+bN 7Jstlaa0lXM+E4gIAsd/BqIHpj+cpLBY0Ix4JBbhwYg4I+SvOIdf4jqrwHIOQUvihXgtVsWCQ9gP 8UV8El/Ft6wCyyl+DxH0XLwUb8UbxD0V1RE7ZtCO+I6oj2JPHIlTBPZ94sqe3yIi0hCb4h1Reibm iOK4HDPRuRJnRO+D2BGHRLSXJC7yRGpeNMV7sYXAeQSFCU6FRHIGB56IGveMI/uIGxu5JGFzTN0W wpqIijIsmpDFYZ55hah4xRpxP7MIM4NWWHEbTGGDKY1ybi8VKyVM/l2wYjtM+S1xrvww9x6KulgX K0QqvOOeGafGCnbrjOPScOtmnPA1Hm7Sr+TcjF2Rq2F3nb4zNVzCZsWyWMOr2XFe5WgB9urYX+ba KywkF1bJh8d4WWSrYLdhbdBhmohVrddNtYApLOUZI0jxgp6EMO8YQWlK272wuwobFlHkeVqqMVzC OlaR15mQMO8Yo8L6VpFnypNL0S1YWBe7h4wTVxneiP0RJ+KzaHE9KEjUAHst7J9wnWoqe7z9TVly QL9bwJQOsXOB3X36vbTVhfHqN16Zh49F2xXujK2PnWPsthhnkLYeiz0ziblrVZ55CkV7Ftrk1Q52 z5NmIkowdsUBIrIqz7SltR2la0vUNhxhP3PNP7RCf4CouPIs4jDS9p2U/svj21QfeKf6E8E/+ahy 37K2GwEGAJb/2mQI89WQAAAAAElFTkSuQmCC"
- transform="matrix(0.24 0 0 0.24 228.8599 230.2217)"
- id="image215"></image><g
- id="g217"><radialGradient
- id="SVGID_13_"
- cx="232.459"
- cy="233.3711"
- r="2.999"
- gradientTransform="matrix(1 0 0 0.75 0 58.3428)"
- gradientUnits="userSpaceOnUse"><stop
- offset="0.0123"
- style="stop-color:#FFFFFF"
- id="stop220" /><stop
- offset="0.4235"
- style="stop-color:#FAFCF6"
- id="stop222" /><stop
- offset="1"
- style="stop-color:#F2F7E8"
- id="stop224" /><a:midPointStop
- offset="0.0123"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="0.6235"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="1"
- style="stop-color:#F2F7E8" /></radialGradient><circle
- fill="url(#SVGID_13_)"
- cx="232.459"
- cy="233.37"
- r="2.999"
- id="circle226" /></g></g><g
- id="g228"><image
- overflow="visible"
- opacity="0.25"
- a:adobe-blending-mode="multiply"
- a:adobe-opacity-share="1"
- width="30"
- height="30"
- xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAhCAYAAABX5MJvAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAnpJREFUeNrsl2lrE1EUhmdLjSZ2 sYgL4lqsYN0+CuIC4o8WFERcPii0YEsQtYpL3cVgW7PMjO+F55ZhmMlMzATyoRceSDKZc957zplz zzjOBCz3P+/xRE34fE6uWESiJ0I+VybCxekeMSMOizkxlbATwx/xRXwXWwiKRhFhd17H+TFxVlwU J8W+lJ0+zlfFmngjvolNrkXDinAJ+6w4IRbFZXFenBLzqUg4ODGR+CheimXxQrwWn8U2aSolwgo4 KC6Jawg4w28mAsGAmuiI3+KDaInH4qlYJyo7QoISAq6IO4g4Lppc8wrSl66fA0TNSQvJE+GRggsI uE74GxgvW8gB/68l7ouojXVSE/s5N9dxelvcIgXNIQTkFXaT718pViMiyjIa8OiZ/N8US4Q0GLEf 2d5iauYHhWtqpu8PiMINcVUcJbduBY3R9poOT4rpJdteRi1Mi9PinDhUkQC7/Cz7aRH2iTB9YIEb /IqPiSmiu0Sza3gZf2qgcC6jEVUVjWbCR83LOR8CqFpAMu07PrxJOMp3ReSJiOnnfYjH5DdK+sgS sUkT+SW6YxASJoYe46OXFtGjp5uB5JVop8/+EVfMxj4xY7w1m/YywtRmGmqhtlNhNMIs+36O2pB2 fYSmUq+gc8ZsyBzhD8QTsWEikyciomjnETFdMMiUEWBTvYyIFlGJ/ILqNRHZy1HeyBnnhhVwXzzj FO06BSHuUcVbON9Piuy7hlvCudnEXwSsiLvioXhnB5oiEREG2ojpYtRLCXEHOP/JlG12fk88yhp0 /RJNxRrbgDaCrICQqHWhw/OfdG54Lt4T2dIj/8S8/EzMa+DYX4h3l13/BBgABM7SO70ZkkMAAAAA SUVORK5CYII="
- transform="matrix(0.24 0 0 0.24 243.7749 230.2217)"
- id="image230"></image><g
- id="g232"><radialGradient
- id="SVGID_14_"
- cx="247.374"
- cy="233.3711"
- r="2.999"
- gradientTransform="matrix(1 0 0 0.75 0 58.3428)"
- gradientUnits="userSpaceOnUse"><stop
- offset="0.0123"
- style="stop-color:#FFFFFF"
- id="stop235" /><stop
- offset="0.4235"
- style="stop-color:#FAFCF6"
- id="stop237" /><stop
- offset="1"
- style="stop-color:#F2F7E8"
- id="stop239" /><a:midPointStop
- offset="0.0123"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="0.6235"
- style="stop-color:#FFFFFF" /><a:midPointStop
- offset="1"
- style="stop-color:#F2F7E8" /></radialGradient><circle
- fill="url(#SVGID_14_)"
- cx="247.374"
- cy="233.37"
- r="2.999"
- id="circle241" /></g></g></g></g><path
- d="m 529.664,248.155 h 18.498 l -2.809,18.064 h 5.59 37.586 l 2.6,-17.718 c 4.98,-1.091 9.133,-3.455 12.512,-6.693 3.084,4.075 8.566,7.37 18.252,7.37 6.338,0 12.775,-1.807 17.174,-3.687 4.254,2.399 9.463,3.687 15.459,3.687 3.088,0 6.236,-0.355 9.426,-1.023 h 67.135 l 3.354,-24.827 -5.445,-0.764 1.879,-13.356 c 0.371,-2.386 0.449,-4.66 0.449,-6.156 l -0.008,-0.375 c -0.457,-12.191 -8.139,-19.765 -20.045,-19.765 -2.404,0 -4.623,0.314 -6.676,0.852 h -34.189 l -0.035,0.244 c -2.527,-0.701 -5.41,-1.096 -8.686,-1.096 -3.801,0 -7.406,0.555 -10.76,1.598 l 0.105,-0.746 h -12.467 l 1.826,-12.951 H 613.08 l -1.846,7.658 c -1.373,5.704 -2.213,5.793 -4.453,6.03 l -4.508,0.477 c -3.049,-1.424 -6.357,-2.065 -9.602,-2.065 -2.135,0 -4.275,0.284 -6.416,0.852 h -19.291 c 0.502,-1.772 0.775,-3.674 0.775,-5.678 0,-9.601 -6.846,-16.305 -16.646,-16.305 -11.055,0 -18.775,7.721 -18.775,18.776 0,0.951 0.082,1.869 0.219,2.764 -2.135,-0.288 -4.277,-0.409 -5.553,-0.409 -2.053,0 -4.072,0.288 -6.045,0.852 h -31.342 c -2.74,-0.553 -5.641,-0.852 -8.537,-0.852 -7.138,0 -13.492,1.674 -18.808,4.723 l -3.451,-1.461 c -3.711,-1.571 -11.232,-3.262 -18.979,-3.262 -8.933,0 -16.383,2.56 -21.576,7.016 -3.265,-4.473 -8.523,-7.016 -15.228,-7.016 -4.822,0 -9.021,1.477 -12.572,3.44 -2.996,-2.204 -6.796,-3.44 -11.115,-3.44 -2.327,0 -4.48,0.315 -6.476,0.852 h -33.963 l -0.035,0.245 c -2.526,-0.702 -5.41,-1.097 -8.687,-1.097 -20.458,0 -35.307,16.031 -35.307,38.117 0,17.363 10.785,28.149 28.148,28.149 3.087,0 6.236,-0.356 9.426,-1.023 h 88.816 c 3.706,0.676 7.669,1.023 11.154,1.023 8.907,0 16.278,-2.375 21.51,-6.593 4.872,4.252 11.585,6.593 19.728,6.593 3.053,0 6.206,-0.368 9.286,-1.023 h 44.664 2.069 z"
- id="path243"
- inkscape:connector-curvature="0"
- style="fill:#f5f5f5" /><g
- id="g245"
- transform="translate(0,16)"><g
- id="g247"><path
- d="m 340.308,218.463 c -5.538,2.556 -11.588,4.26 -17.638,4.26 -13.377,0 -18.148,-7.839 -18.148,-18.148 0,-17.893 11.418,-28.117 25.307,-28.117 9.372,0 13.973,4.26 13.973,11.247 0,12.184 -12.865,15.763 -26.157,17.126 0.255,4.346 2.045,8.35 8.435,8.35 3.068,0 7.243,-0.937 12.355,-3.067 l 1.873,8.349 z m -8.095,-29.567 c 0,-2.045 -1.448,-3.237 -4.09,-3.237 -4.771,0 -8.69,4.175 -9.969,10.906 3.664,-0.511 14.059,-2.3 14.059,-7.669 z"
- id="path249"
- inkscape:connector-curvature="0"
- style="fill:#383838" /><path
- d="m 394.07,221.7 -0.171,-0.255 1.789,-10.055 2.642,-18.063 c 0.512,-3.749 0.341,-5.623 -1.96,-5.623 -2.642,0 -5.794,2.727 -9.372,5.879 l -2.727,19.512 c -0.171,1.363 -0.171,1.534 1.022,1.704 l 4.26,0.597 -0.852,6.305 h -18.404 l -0.171,-0.341 1.875,-10.82 2.471,-17.212 c 0.512,-3.237 0.682,-5.453 -1.789,-5.453 -3.238,0 -7.413,3.664 -9.714,5.709 l -2.642,19.512 c -0.17,1.363 -0.17,1.534 1.108,1.704 l 4.26,0.597 -0.852,6.305 h -23.347 l 0.853,-6.39 3.749,-0.512 c 1.107,-0.17 1.363,-0.426 1.533,-1.704 l 3.579,-25.987 c 0.17,-0.938 0,-1.534 -0.767,-1.789 l -4.176,-1.534 0.938,-6.476 h 16.871 l -0.938,6.987 0.256,0.085 c 4.43,-3.749 9.116,-7.924 15.592,-7.924 4.687,0 7.839,2.641 8.18,7.753 l 0.256,0.086 c 4.175,-3.664 9.202,-7.839 15.252,-7.839 6.22,0 8.775,3.152 8.946,9.202 0,1.618 -0.171,3.493 -0.426,5.538 l -3.067,21.897 c -0.171,1.363 -0.171,1.534 1.107,1.704 l 4.175,0.597 -0.852,6.305 H 394.07 z"
- id="path251"
- inkscape:connector-curvature="0"
- style="fill:#383838" /><path
- d="m 443.995,190.771 -0.17,-4.431 c 0,-0.682 -0.085,-1.108 -1.022,-1.363 -1.022,-0.256 -2.642,-0.427 -4.771,-0.427 -3.579,0 -6.391,1.108 -6.391,4.09 0,2.727 2.982,3.749 6.731,5.027 6.05,2.045 13.888,4.431 13.888,13.463 0,11.076 -9.372,15.592 -20.193,15.592 -8.009,0 -14.91,-1.959 -16.273,-2.981 l 1.618,-12.355 8.691,0.512 0.255,4.941 c 0,0.597 0.171,1.108 0.938,1.363 1.278,0.427 3.238,0.768 6.05,0.768 4.687,0 7.327,-1.79 7.327,-4.687 0,-3.408 -3.152,-4.175 -8.009,-5.624 -6.135,-1.874 -12.78,-4.26 -12.78,-13.206 0,-10.48 9.116,-14.996 19.597,-14.996 6.646,0 12.866,1.533 15.081,2.471 l -1.704,12.354 -8.863,-0.511 z"
- id="path253"
- inkscape:connector-curvature="0"
- style="fill:#383838" /><path
- d="m 489.748,218.548 c -4.175,2.386 -10.395,4.175 -16.444,4.175 -13.036,0 -18.575,-7.583 -18.575,-18.574 0,-18.83 11.588,-27.691 25.988,-27.691 6.475,0 11.843,1.874 14.229,3.578 l -1.874,13.377 -8.691,-0.426 -0.255,-5.794 c 0,-0.597 -0.086,-0.938 -0.597,-1.192 -1.022,-0.427 -2.557,-0.597 -4.175,-0.597 -5.624,0 -11.418,4.601 -11.418,17.382 0,7.839 3.493,10.395 8.436,10.395 4.346,0 8.436,-1.448 11.247,-2.556 l 2.129,7.923 z"
- id="path255"
- inkscape:connector-curvature="0"
- style="fill:#383838" /><path
- d="m 491.364,221.7 0.853,-6.39 3.919,-0.512 c 1.193,-0.17 1.363,-0.426 1.534,-1.704 l 3.578,-25.987 c 0.086,-0.938 -0.085,-1.534 -0.852,-1.789 l -4.261,-1.534 0.938,-6.476 h 16.87 l -1.107,7.669 0.256,0.17 c 3.323,-4.771 8.095,-8.69 13.548,-8.69 1.874,0 5.112,0.341 6.561,0.767 l -2.13,15.507 -9.969,-0.341 -0.256,-4.431 c -0.086,-0.767 -0.256,-1.022 -0.938,-1.022 -1.619,0 -4.26,1.96 -6.646,4.431 l -2.981,21.643 c -0.171,1.363 -0.085,1.619 1.192,1.704 l 8.095,0.682 -0.938,6.305 h -27.266 z"
- id="path257"
- inkscape:connector-curvature="0"
- style="fill:#383838" /><path
- d="m 536.094,221.7 -0.17,-0.426 2.045,-11.503 3.152,-22.749 c 0.17,-0.938 -0.086,-1.534 -0.853,-1.79 l -4.175,-1.448 0.852,-6.476 h 18.149 l -5.027,35.786 c -0.171,1.363 -0.085,1.534 1.192,1.704 l 4.09,0.597 -0.852,6.305 h -18.403 z m 5.879,-57.598 c 0,-5.453 3.238,-8.775 8.776,-8.775 4.175,0 6.646,2.215 6.646,6.305 0,5.368 -3.322,8.861 -8.861,8.861 -4.176,-0.001 -6.561,-2.387 -6.561,-6.391 z"
- id="path259"
- inkscape:connector-curvature="0"
- style="fill:#383838" /><path
- d="m 556.796,239.764 -0.17,-0.341 2.471,-14.229 5.282,-38.087 c 0.171,-1.022 -0.085,-1.534 -0.767,-1.789 l -4.175,-1.534 0.938,-6.476 h 17.041 l -1.022,6.816 0.255,0.085 c 5.027,-4.686 10.311,-7.753 15.678,-7.753 7.328,0 12.44,4.686 12.44,17.041 0,11.758 -4.601,29.225 -20.449,29.225 -5.538,0 -8.605,-2.13 -11.759,-4.345 l -1.874,12.78 c -0.085,0.938 0.085,1.278 1.192,1.363 l 8.606,0.853 -0.938,6.39 h -22.749 z m 17.041,-30.247 c 2.13,1.789 4.942,3.322 8.095,3.322 6.901,0 9.458,-9.713 9.458,-17.211 0,-5.027 -1.193,-8.351 -4.431,-8.351 -3.408,0 -7.754,3.664 -10.821,6.391 l -2.301,15.849 z"
- id="path261"
- inkscape:connector-curvature="0"
- style="fill:#383838" /><path
- d="m 635.777,219.4 c -3.749,1.789 -9.458,3.322 -14.229,3.322 -8.521,0 -12.099,-2.981 -12.099,-9.969 0,-1.107 0.085,-2.386 0.256,-3.749 l 3.066,-22.323 c 0.086,-0.512 0.086,-0.853 -0.511,-0.853 h -5.879 l 1.107,-7.839 c 7.242,-0.767 10.906,-4.431 13.122,-13.633 h 7.924 l -1.704,12.1 c -0.085,0.596 -0.085,0.852 0.597,0.852 h 11.758 l -1.193,8.521 h -12.439 l -2.812,20.364 c -0.171,1.107 -0.256,1.96 -0.256,2.727 0,2.982 1.278,4.26 4.942,4.26 2.385,0 4.771,-0.596 6.816,-1.363 l 1.534,7.583 z"
- id="path263"
- inkscape:connector-curvature="0"
- style="fill:#383838" /><path
- d="m 671.817,218.463 c -5.538,2.556 -11.588,4.26 -17.638,4.26 -13.377,0 -18.148,-7.839 -18.148,-18.148 0,-17.893 11.418,-28.117 25.307,-28.117 9.372,0 13.973,4.26 13.973,11.247 0,12.184 -12.865,15.763 -26.157,17.126 0.255,4.346 2.045,8.35 8.435,8.35 3.068,0 7.243,-0.937 12.355,-3.067 l 1.873,8.349 z m -8.094,-29.567 c 0,-2.045 -1.448,-3.237 -4.09,-3.237 -4.771,0 -8.69,4.175 -9.969,10.906 3.664,-0.511 14.059,-2.3 14.059,-7.669 z"
- id="path265"
- inkscape:connector-curvature="0"
- style="fill:#383838" /><path
- d="m 703.596,221.7 -0.17,-0.255 1.874,-10.396 2.471,-17.723 c 0.512,-3.578 0.341,-5.879 -2.215,-5.879 -3.664,0 -8.18,3.578 -11.077,6.135 l -2.641,19.512 c -0.171,1.363 -0.171,1.534 1.107,1.704 l 4.26,0.597 -0.852,6.305 h -23.347 l 0.853,-6.39 3.749,-0.512 c 1.107,-0.17 1.363,-0.426 1.533,-1.704 l 3.579,-25.987 c 0.17,-0.938 0,-1.534 -0.768,-1.789 l -4.175,-1.534 0.938,-6.476 h 16.87 l -0.937,6.987 0.255,0.085 c 4.771,-4.09 9.373,-7.924 16.02,-7.924 6.475,0 9.798,3.322 10.054,10.139 0,1.363 -0.085,3.067 -0.341,4.687 l -3.067,21.812 c -0.171,1.363 -0.171,1.534 1.022,1.704 l 4.26,0.597 L 722,221.7 h -18.404 z"
- id="path267"
- inkscape:connector-curvature="0"
- style="fill:#383838" /></g><g
- id="g269"><linearGradient
- id="SVGID_15_"
- gradientUnits="userSpaceOnUse"
- x1="324.1611"
- y1="239.7637"
- x2="324.1611"
- y2="155.3275"><stop
- offset="0"
- style="stop-color:#000000"
- id="stop272" /><stop
- offset="1"
- style="stop-color:#000000;stop-opacity:0"
- id="stop274" /><a:midPointStop
- offset="0"
- style="stop-color:#000000" /><a:midPointStop
- offset="0.6933"
- style="stop-color:#000000" /><a:midPointStop
- offset="1"
- style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
- d="m 340.308,218.463 c -5.538,2.556 -11.588,4.26 -17.638,4.26 -13.377,0 -18.148,-7.839 -18.148,-18.148 0,-17.893 11.418,-28.117 25.307,-28.117 9.372,0 13.973,4.26 13.973,11.247 0,12.184 -12.865,15.763 -26.157,17.126 0.255,4.346 2.045,8.35 8.435,8.35 3.068,0 7.243,-0.937 12.355,-3.067 l 1.873,8.349 z m -8.095,-29.567 c 0,-2.045 -1.448,-3.237 -4.09,-3.237 -4.771,0 -8.69,4.175 -9.969,10.906 3.664,-0.511 14.059,-2.3 14.059,-7.669 z"
- id="path276"
- style="fill:url(#SVGID_15_)"
- inkscape:connector-curvature="0" /><linearGradient
- id="SVGID_16_"
- gradientUnits="userSpaceOnUse"
- x1="377.45459"
- y1="239.7637"
- x2="377.45459"
- y2="155.3277"><stop
- offset="0"
- style="stop-color:#000000"
- id="stop279" /><stop
- offset="1"
- style="stop-color:#000000;stop-opacity:0"
- id="stop281" /><a:midPointStop
- offset="0"
- style="stop-color:#000000" /><a:midPointStop
- offset="0.6933"
- style="stop-color:#000000" /><a:midPointStop
- offset="1"
- style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
- d="m 394.07,221.7 -0.171,-0.255 1.789,-10.055 2.642,-18.063 c 0.512,-3.749 0.341,-5.623 -1.96,-5.623 -2.642,0 -5.794,2.727 -9.372,5.879 l -2.727,19.512 c -0.171,1.363 -0.171,1.534 1.022,1.704 l 4.26,0.597 -0.852,6.305 h -18.404 l -0.171,-0.341 1.875,-10.82 2.471,-17.212 c 0.512,-3.237 0.682,-5.453 -1.789,-5.453 -3.238,0 -7.413,3.664 -9.714,5.709 l -2.642,19.512 c -0.17,1.363 -0.17,1.534 1.108,1.704 l 4.26,0.597 -0.852,6.305 h -23.347 l 0.853,-6.39 3.749,-0.512 c 1.107,-0.17 1.363,-0.426 1.533,-1.704 l 3.579,-25.987 c 0.17,-0.938 0,-1.534 -0.767,-1.789 l -4.176,-1.534 0.938,-6.476 h 16.871 l -0.938,6.987 0.256,0.085 c 4.43,-3.749 9.116,-7.924 15.592,-7.924 4.687,0 7.839,2.641 8.18,7.753 l 0.256,0.086 c 4.175,-3.664 9.202,-7.839 15.252,-7.839 6.22,0 8.775,3.152 8.946,9.202 0,1.618 -0.171,3.493 -0.426,5.538 l -3.067,21.897 c -0.171,1.363 -0.171,1.534 1.107,1.704 l 4.175,0.597 -0.852,6.305 H 394.07 z"
- id="path283"
- style="fill:url(#SVGID_16_)"
- inkscape:connector-curvature="0" /><linearGradient
- id="SVGID_17_"
- gradientUnits="userSpaceOnUse"
- x1="435.17719"
- y1="239.7637"
- x2="435.17719"
- y2="155.3275"><stop
- offset="0"
- style="stop-color:#000000"
- id="stop286" /><stop
- offset="1"
- style="stop-color:#000000;stop-opacity:0"
- id="stop288" /><a:midPointStop
- offset="0"
- style="stop-color:#000000" /><a:midPointStop
- offset="0.6933"
- style="stop-color:#000000" /><a:midPointStop
- offset="1"
- style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
- d="m 443.995,190.771 -0.17,-4.431 c 0,-0.682 -0.085,-1.108 -1.022,-1.363 -1.022,-0.256 -2.642,-0.427 -4.771,-0.427 -3.579,0 -6.391,1.108 -6.391,4.09 0,2.727 2.982,3.749 6.731,5.027 6.05,2.045 13.888,4.431 13.888,13.463 0,11.076 -9.372,15.592 -20.193,15.592 -8.009,0 -14.91,-1.959 -16.273,-2.981 l 1.618,-12.355 8.691,0.512 0.255,4.941 c 0,0.597 0.171,1.108 0.938,1.363 1.278,0.427 3.238,0.768 6.05,0.768 4.687,0 7.327,-1.79 7.327,-4.687 0,-3.408 -3.152,-4.175 -8.009,-5.624 -6.135,-1.874 -12.78,-4.26 -12.78,-13.206 0,-10.48 9.116,-14.996 19.597,-14.996 6.646,0 12.866,1.533 15.081,2.471 l -1.704,12.354 -8.863,-0.511 z"
- id="path290"
- style="fill:url(#SVGID_17_)"
- inkscape:connector-curvature="0" /><linearGradient
- id="SVGID_18_"
- gradientUnits="userSpaceOnUse"
- x1="474.83691"
- y1="239.7637"
- x2="474.83691"
- y2="155.3275"><stop
- offset="0"
- style="stop-color:#000000"
- id="stop293" /><stop
- offset="1"
- style="stop-color:#000000;stop-opacity:0"
- id="stop295" /><a:midPointStop
- offset="0"
- style="stop-color:#000000" /><a:midPointStop
- offset="0.6933"
- style="stop-color:#000000" /><a:midPointStop
- offset="1"
- style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
- d="m 489.748,218.548 c -4.175,2.386 -10.395,4.175 -16.444,4.175 -13.036,0 -18.575,-7.583 -18.575,-18.574 0,-18.83 11.588,-27.691 25.988,-27.691 6.475,0 11.843,1.874 14.229,3.578 l -1.874,13.377 -8.691,-0.426 -0.255,-5.794 c 0,-0.597 -0.086,-0.938 -0.597,-1.192 -1.022,-0.427 -2.557,-0.597 -4.175,-0.597 -5.624,0 -11.418,4.601 -11.418,17.382 0,7.839 3.493,10.395 8.436,10.395 4.346,0 8.436,-1.448 11.247,-2.556 l 2.129,7.923 z"
- id="path297"
- style="fill:url(#SVGID_18_)"
- inkscape:connector-curvature="0" /><linearGradient
- id="SVGID_19_"
- gradientUnits="userSpaceOnUse"
- x1="512.28223"
- y1="239.7637"
- x2="512.28223"
- y2="155.3277"><stop
- offset="0"
- style="stop-color:#000000"
- id="stop300" /><stop
- offset="1"
- style="stop-color:#000000;stop-opacity:0"
- id="stop302" /><a:midPointStop
- offset="0"
- style="stop-color:#000000" /><a:midPointStop
- offset="0.6933"
- style="stop-color:#000000" /><a:midPointStop
- offset="1"
- style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
- d="m 491.364,221.7 0.853,-6.39 3.919,-0.512 c 1.193,-0.17 1.363,-0.426 1.534,-1.704 l 3.578,-25.987 c 0.086,-0.938 -0.085,-1.534 -0.852,-1.789 l -4.261,-1.534 0.938,-6.476 h 16.87 l -1.107,7.669 0.256,0.17 c 3.323,-4.771 8.095,-8.69 13.548,-8.69 1.874,0 5.112,0.341 6.561,0.767 l -2.13,15.507 -9.969,-0.341 -0.256,-4.431 c -0.086,-0.767 -0.256,-1.022 -0.938,-1.022 -1.619,0 -4.26,1.96 -6.646,4.431 l -2.981,21.643 c -0.171,1.363 -0.085,1.619 1.192,1.704 l 8.095,0.682 -0.938,6.305 h -27.266 z"
- id="path304"
- style="fill:url(#SVGID_19_)"
- inkscape:connector-curvature="0" /><linearGradient
- id="SVGID_20_"
- gradientUnits="userSpaceOnUse"
- x1="546.65918"
- y1="239.7637"
- x2="546.65918"
- y2="155.32719"><stop
- offset="0"
- style="stop-color:#000000"
- id="stop307" /><stop
- offset="1"
- style="stop-color:#000000;stop-opacity:0"
- id="stop309" /><a:midPointStop
- offset="0"
- style="stop-color:#000000" /><a:midPointStop
- offset="0.6933"
- style="stop-color:#000000" /><a:midPointStop
- offset="1"
- style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
- d="m 536.094,221.7 -0.17,-0.426 2.045,-11.503 3.152,-22.749 c 0.17,-0.938 -0.086,-1.534 -0.853,-1.79 l -4.175,-1.448 0.852,-6.476 h 18.149 l -5.027,35.786 c -0.171,1.363 -0.085,1.534 1.192,1.704 l 4.09,0.597 -0.852,6.305 h -18.403 z m 5.879,-57.598 c 0,-5.453 3.238,-8.775 8.776,-8.775 4.175,0 6.646,2.215 6.646,6.305 0,5.368 -3.322,8.861 -8.861,8.861 -4.176,-0.001 -6.561,-2.387 -6.561,-6.391 z"
- id="path311"
- style="fill:url(#SVGID_20_)"
- inkscape:connector-curvature="0" /><linearGradient
- id="SVGID_21_"
- gradientUnits="userSpaceOnUse"
- x1="580.69629"
- y1="239.7637"
- x2="580.69629"
- y2="155.32719"><stop
- offset="0"
- style="stop-color:#000000"
- id="stop314" /><stop
- offset="1"
- style="stop-color:#000000;stop-opacity:0"
- id="stop316" /><a:midPointStop
- offset="0"
- style="stop-color:#000000" /><a:midPointStop
- offset="0.6933"
- style="stop-color:#000000" /><a:midPointStop
- offset="1"
- style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
- d="m 556.796,239.764 -0.17,-0.341 2.471,-14.229 5.282,-38.087 c 0.171,-1.022 -0.085,-1.534 -0.767,-1.789 l -4.175,-1.534 0.938,-6.476 h 17.041 l -1.022,6.816 0.255,0.085 c 5.027,-4.686 10.311,-7.753 15.678,-7.753 7.328,0 12.44,4.686 12.44,17.041 0,11.758 -4.601,29.225 -20.449,29.225 -5.538,0 -8.605,-2.13 -11.759,-4.345 l -1.874,12.78 c -0.085,0.938 0.085,1.278 1.192,1.363 l 8.606,0.853 -0.938,6.39 h -22.749 z m 17.041,-30.247 c 2.13,1.789 4.942,3.322 8.095,3.322 6.901,0 9.458,-9.713 9.458,-17.211 0,-5.027 -1.193,-8.351 -4.431,-8.351 -3.408,0 -7.754,3.664 -10.821,6.391 l -2.301,15.849 z"
- id="path318"
- style="fill:url(#SVGID_21_)"
- inkscape:connector-curvature="0" /><linearGradient
- id="SVGID_22_"
- gradientUnits="userSpaceOnUse"
- x1="622.7832"
- y1="239.7637"
- x2="622.7832"
- y2="155.3268"><stop
- offset="0"
- style="stop-color:#000000"
- id="stop321" /><stop
- offset="1"
- style="stop-color:#000000;stop-opacity:0"
- id="stop323" /><a:midPointStop
- offset="0"
- style="stop-color:#000000" /><a:midPointStop
- offset="0.6933"
- style="stop-color:#000000" /><a:midPointStop
- offset="1"
- style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
- d="m 635.777,219.4 c -3.749,1.789 -9.458,3.322 -14.229,3.322 -8.521,0 -12.099,-2.981 -12.099,-9.969 0,-1.107 0.085,-2.386 0.256,-3.749 l 3.066,-22.323 c 0.086,-0.512 0.086,-0.853 -0.511,-0.853 h -5.879 l 1.107,-7.839 c 7.242,-0.767 10.906,-4.431 13.122,-13.633 h 7.924 l -1.704,12.1 c -0.085,0.596 -0.085,0.852 0.597,0.852 h 11.758 l -1.193,8.521 h -12.439 l -2.812,20.364 c -0.171,1.107 -0.256,1.96 -0.256,2.727 0,2.982 1.278,4.26 4.942,4.26 2.385,0 4.771,-0.596 6.816,-1.363 l 1.534,7.583 z"
- id="path325"
- style="fill:url(#SVGID_22_)"
- inkscape:connector-curvature="0" /><linearGradient
- id="SVGID_23_"
- gradientUnits="userSpaceOnUse"
- x1="655.6709"
- y1="239.7637"
- x2="655.6709"
- y2="155.3275"><stop
- offset="0"
- style="stop-color:#000000"
- id="stop328" /><stop
- offset="1"
- style="stop-color:#000000;stop-opacity:0"
- id="stop330" /><a:midPointStop
- offset="0"
- style="stop-color:#000000" /><a:midPointStop
- offset="0.6933"
- style="stop-color:#000000" /><a:midPointStop
- offset="1"
- style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
- d="m 671.817,218.463 c -5.538,2.556 -11.588,4.26 -17.638,4.26 -13.377,0 -18.148,-7.839 -18.148,-18.148 0,-17.893 11.418,-28.117 25.307,-28.117 9.372,0 13.973,4.26 13.973,11.247 0,12.184 -12.865,15.763 -26.157,17.126 0.255,4.346 2.045,8.35 8.435,8.35 3.068,0 7.243,-0.937 12.355,-3.067 l 1.873,8.349 z m -8.094,-29.567 c 0,-2.045 -1.448,-3.237 -4.09,-3.237 -4.771,0 -8.69,4.175 -9.969,10.906 3.664,-0.511 14.059,-2.3 14.059,-7.669 z"
- id="path332"
- style="fill:url(#SVGID_23_)"
- inkscape:connector-curvature="0" /><linearGradient
- id="SVGID_24_"
- gradientUnits="userSpaceOnUse"
- x1="697.92969"
- y1="239.7637"
- x2="697.92969"
- y2="155.3277"><stop
- offset="0"
- style="stop-color:#000000"
- id="stop335" /><stop
- offset="1"
- style="stop-color:#000000;stop-opacity:0"
- id="stop337" /><a:midPointStop
- offset="0"
- style="stop-color:#000000" /><a:midPointStop
- offset="0.6933"
- style="stop-color:#000000" /><a:midPointStop
- offset="1"
- style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
- d="m 703.596,221.7 -0.17,-0.255 1.874,-10.396 2.471,-17.723 c 0.512,-3.578 0.341,-5.879 -2.215,-5.879 -3.664,0 -8.18,3.578 -11.077,6.135 l -2.641,19.512 c -0.171,1.363 -0.171,1.534 1.107,1.704 l 4.26,0.597 -0.852,6.305 h -23.347 l 0.853,-6.39 3.749,-0.512 c 1.107,-0.17 1.363,-0.426 1.533,-1.704 l 3.579,-25.987 c 0.17,-0.938 0,-1.534 -0.768,-1.789 l -4.175,-1.534 0.938,-6.476 h 16.87 l -0.937,6.987 0.255,0.085 c 4.771,-4.09 9.373,-7.924 16.02,-7.924 6.475,0 9.798,3.322 10.054,10.139 0,1.363 -0.085,3.067 -0.341,4.687 l -3.067,21.812 c -0.171,1.363 -0.171,1.534 1.022,1.704 l 4.26,0.597 L 722,221.7 h -18.404 z"
- id="path339"
- style="fill:url(#SVGID_24_)"
- inkscape:connector-curvature="0" /></g></g><g
- id="g4141"
- transform="matrix(0.81856441,0,0,0.81856441,79.234731,-94.128741)"><g
- id="g4143"></g><g
- id="g4165"><linearGradient
- y2="155.3275"
- x2="324.1611"
- y1="239.7637"
- x1="324.1611"
- gradientUnits="userSpaceOnUse"
- id="linearGradient4167"><stop
- id="stop4169"
- style="stop-color:#000000"
- offset="0" /><stop
- id="stop4171"
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /><a:midPointStop
- style="stop-color:#000000"
- offset="0" /><a:midPointStop
- style="stop-color:#000000"
- offset="0.6933" /><a:midPointStop
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /></linearGradient><linearGradient
- y2="155.3277"
- x2="377.45459"
- y1="239.7637"
- x1="377.45459"
- gradientUnits="userSpaceOnUse"
- id="linearGradient4175"><stop
- id="stop4177"
- style="stop-color:#000000"
- offset="0" /><stop
- id="stop4179"
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /><a:midPointStop
- style="stop-color:#000000"
- offset="0" /><a:midPointStop
- style="stop-color:#000000"
- offset="0.6933" /><a:midPointStop
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /></linearGradient><linearGradient
- y2="155.3275"
- x2="435.17719"
- y1="239.7637"
- x1="435.17719"
- gradientUnits="userSpaceOnUse"
- id="linearGradient4183"><stop
- id="stop4185"
- style="stop-color:#000000"
- offset="0" /><stop
- id="stop4187"
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /><a:midPointStop
- style="stop-color:#000000"
- offset="0" /><a:midPointStop
- style="stop-color:#000000"
- offset="0.6933" /><a:midPointStop
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /></linearGradient><linearGradient
- y2="155.3275"
- x2="474.83691"
- y1="239.7637"
- x1="474.83691"
- gradientUnits="userSpaceOnUse"
- id="linearGradient4191"><stop
- id="stop4193"
- style="stop-color:#000000"
- offset="0" /><stop
- id="stop4195"
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /><a:midPointStop
- style="stop-color:#000000"
- offset="0" /><a:midPointStop
- style="stop-color:#000000"
- offset="0.6933" /><a:midPointStop
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /></linearGradient><linearGradient
- y2="155.3277"
- x2="512.28223"
- y1="239.7637"
- x1="512.28223"
- gradientUnits="userSpaceOnUse"
- id="linearGradient4199"><stop
- id="stop4201"
- style="stop-color:#000000"
- offset="0" /><stop
- id="stop4203"
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /><a:midPointStop
- style="stop-color:#000000"
- offset="0" /><a:midPointStop
- style="stop-color:#000000"
- offset="0.6933" /><a:midPointStop
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /></linearGradient><linearGradient
- y2="155.32719"
- x2="546.65918"
- y1="239.7637"
- x1="546.65918"
- gradientUnits="userSpaceOnUse"
- id="linearGradient4207"><stop
- id="stop4209"
- style="stop-color:#000000"
- offset="0" /><stop
- id="stop4211"
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /><a:midPointStop
- style="stop-color:#000000"
- offset="0" /><a:midPointStop
- style="stop-color:#000000"
- offset="0.6933" /><a:midPointStop
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /></linearGradient><linearGradient
- y2="155.32719"
- x2="580.69629"
- y1="239.7637"
- x1="580.69629"
- gradientUnits="userSpaceOnUse"
- id="linearGradient4215"><stop
- id="stop4217"
- style="stop-color:#000000"
- offset="0" /><stop
- id="stop4219"
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /><a:midPointStop
- style="stop-color:#000000"
- offset="0" /><a:midPointStop
- style="stop-color:#000000"
- offset="0.6933" /><a:midPointStop
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /></linearGradient><linearGradient
- y2="155.3268"
- x2="622.7832"
- y1="239.7637"
- x1="622.7832"
- gradientUnits="userSpaceOnUse"
- id="linearGradient4223"><stop
- id="stop4225"
- style="stop-color:#000000"
- offset="0" /><stop
- id="stop4227"
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /><a:midPointStop
- style="stop-color:#000000"
- offset="0" /><a:midPointStop
- style="stop-color:#000000"
- offset="0.6933" /><a:midPointStop
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /></linearGradient><linearGradient
- y2="155.3275"
- x2="655.6709"
- y1="239.7637"
- x1="655.6709"
- gradientUnits="userSpaceOnUse"
- id="linearGradient4231"><stop
- id="stop4233"
- style="stop-color:#000000"
- offset="0" /><stop
- id="stop4235"
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /><a:midPointStop
- style="stop-color:#000000"
- offset="0" /><a:midPointStop
- style="stop-color:#000000"
- offset="0.6933" /><a:midPointStop
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /></linearGradient><linearGradient
- y2="155.3277"
- x2="697.92969"
- y1="239.7637"
- x1="697.92969"
- gradientUnits="userSpaceOnUse"
- id="linearGradient4239"><stop
- id="stop4241"
- style="stop-color:#000000"
- offset="0" /><stop
- id="stop4243"
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /><a:midPointStop
- style="stop-color:#000000"
- offset="0" /><a:midPointStop
- style="stop-color:#000000"
- offset="0.6933" /><a:midPointStop
- style="stop-color:#000000;stop-opacity:0"
- offset="1" /></linearGradient></g></g></svg>
- </a>
+ #container {
+ display: inline-block; /* scale with canvas */
+ vertical-align: top; /* prevent extra height */
+ position: relative; /* root for absolutely positioned overlay */
+ margin: 0;
+ border: 0 none;
+ padding: 0;
+ background-color: #111;
+ }
- <div class="spinner" id='spinner'></div>
- <div class="emscripten" id="status">Downloading...</div>
+ #canvas {
+ display: block;
+ margin: 0 auto;
+ /* canvas must have border and padding set to zero to
+ * calculate cursor coordinates correctly */
+ border: 0 none;
+ padding: 0;
+ }
-<span id='controls'>
- <span><input type="checkbox" id="resize">Resize canvas</span>
- <span><input type="checkbox" id="pointerLock" checked>Lock/hide mouse pointer &nbsp;&nbsp;&nbsp;</span>
- <span><input type="button" value="Fullscreen" onclick="Module.requestFullScreen(document.getElementById('pointerLock').checked,
- document.getElementById('resize').checked)">
- </span>
-</span>
- <div class="emscripten">
- <progress value="0" max="100" id="progress" hidden=1></progress>
- </div>
+ /* Status display
+ * ============== */
-
- <div class="emscripten_border">
- <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
- </div>
- <textarea id="output" rows="8"></textarea>
+ #status-container {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ /* don't consume click events - make children visible explicitly */
+ visibility: hidden;
+ }
- <script type='text/javascript'>
- var statusElement = document.getElementById('status');
- var progressElement = document.getElementById('progress');
- var spinnerElement = document.getElementById('spinner');
+ #status {
+ visibility: visible;
+ padding: 4px 6px;
+ }
- var Module = {
- TOTAL_MEMORY: $GODOTTMEM,
- preRun: [],
- postRun: [],
- print: (function() {
- var element = document.getElementById('output');
- if (element) element.value = ''; // clear browser cache
- return function(text) {
- if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
- // These replacements are necessary if you render to raw HTML
- //text = text.replace(/&/g, "&amp;");
- //text = text.replace(/</g, "&lt;");
- //text = text.replace(/>/g, "&gt;");
- //text = text.replace('\n', '<br>', 'g');
- console.log(text);
- if (element) {
- element.value += text + "\n";
- element.scrollTop = element.scrollHeight; // focus on bottom
- }
- };
- })(),
- printErr: function(text) {
- if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
- if (0) { // XXX disabled for safety typeof dump == 'function') {
- dump(text + '\n'); // fast, straight to the real console
- } else {
- console.error(text);
- }
- },
- canvas: (function() {
- var canvas = document.getElementById('canvas');
- // As a default initial behavior, pop up an alert when webgl context is lost. To make your
- // application robust, you may want to override this behavior before shipping!
- // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
- canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
+ /* On-hover controls
+ * ================= */
- return canvas;
- })(),
- setStatus: function(text) {
- if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
- if (text === Module.setStatus.text) return;
- var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
- var now = Date.now();
- if (m && now - Date.now() < 30) return; // if this is a progress update, skip it if too soon
- if (m) {
- text = m[1];
- progressElement.value = parseInt(m[2])*100;
- progressElement.max = parseInt(m[4])*100;
- progressElement.hidden = false;
- spinnerElement.hidden = false;
- } else {
- progressElement.value = null;
- progressElement.max = null;
- progressElement.hidden = true;
- if (!text) spinnerElement.style.display = 'none';
- }
- statusElement.innerHTML = text;
- },
- totalDependencies: 0,
- monitorRunDependencies: function(left) {
- this.totalDependencies = Math.max(this.totalDependencies, left);
- Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
- }
- };
- Module.setStatus('Downloading...');
- window.onerror = function(event) {
- // TODO: do not warn on ok events like simulating an infinite loop or exitStatus
- Module.setStatus('Exception thrown, see JavaScript console');
- spinnerElement.style.display = 'none';
- Module.setStatus = function(text) {
- if (text) Module.printErr('[post-exception status] ' + text);
- };
- };
- </script>
- <script type="text/javascript" src="$GODOTFS"></script>
- <script>
+ #controls {
+ visibility: hidden;
+ opacity: 0.0;
+ transition: opacity 500ms ease-in-out 200ms;
+ position: absolute;
+ right: 16px;
+ top: 16px;
+ padding: 3px 5px;
+ font-size: small;
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ }
- (function() {
- var memoryInitializer = '$GODOTMEM';
- if (typeof Module['locateFile'] === 'function') {
- memoryInitializer = Module['locateFile'](memoryInitializer);
- } else if (Module['memoryInitializerPrefixURL']) {
- memoryInitializer = Module['memoryInitializerPrefixURL'] + memoryInitializer;
- }
- var xhr = Module['memoryInitializerRequest'] = new XMLHttpRequest();
- xhr.open('GET', memoryInitializer, true);
- xhr.responseType = 'arraybuffer';
- xhr.send(null);
- })();
+ #container:hover > #controls {
+ opacity: 1.0;
+ transition: opacity 60ms ease-in-out;
+ }
- var script = document.createElement('script');
- script.src = "$GODOTJS";
- document.body.appendChild(script);
+ #controls > button,
+ #controls > label {
+ vertical-align: middle;
+ margin-left: 2px;
+ margin-right: 2px;
+ }
-</script>
- </body>
+ #controls > label > input[type="checkbox"] {
+ /* override user agent style */
+ margin-left: 0;
+ }
+
+ label > input {
+ vertical-align: middle;
+ }
+
+ #display-output { display: none; }
+
+
+ /* Debug output
+ * ============ */
+
+ #output {
+ display: none;
+ margin: 6px auto;
+ border: 2px groove grey;
+ padding: 4px;
+ outline: none;
+ text-align: left;
+ white-space: pre-wrap;
+ font-size: small;
+ color: #eee;
+ background-color: black;
+ font-family: "Lucida Console", Monaco, monospace;
+ }
+
+
+ /* Export style include
+ * ==================== */
+
+ $GODOT_STYLE_INCLUDE
+ </style>
+</head>
+<body>
+ <div id="container">
+ <canvas id="canvas" width="$GODOT_CANVAS_WIDTH" height="$GODOT_CANVAS_HEIGHT" onclick="canvas.ownerDocument.defaultView.focus();" oncontextmenu="event.preventDefault();">
+ HTML5 canvas appears to be unsupported in the current browser.<br />Please try updating or use a different browser.
+ </canvas>
+ <div id="status-container">
+ <span id="status" class="godot" onclick="this.style.visibility='hidden';">Loading page...</span>
+ </div>
+ <div id="controls" class="godot">
+ <label id="display-output"><input id="output-toggle" type="checkbox" autocomplete="off" onchange="Presentation.setOutputVisible(this.checked);" />display output</label>
+ <!-- hidden until implemented
+ <label><input id="lock-cursor" type="checkbox" autocomplete="off" />lock cursor</label>
+ <label><input id="resize-canvas" type="checkbox" autocomplete="off" />resize canvas</label>
+ -->
+ <button id="fullscreen" class="godot" type="button" disabled="disabled" autocomplete="off" onclick="Presentation.goFullscreen();">fullscreen</button>
+ </div>
+ </div>
+ <!-- Firefox adds extra space to textarea, but shouldn't matter too much https://bugzilla.mozilla.org/show_bug.cgi?id=33654 -->
+ <textarea id="output" rows="10" cols="100" readonly="readonly" style="resize:none"></textarea>
+
+ <script type="text/javascript">//<![CDATA[
+ var Presentation = (function() {
+ var statusElement = document.getElementById("status");
+ var outputElement = document.getElementById("output");
+ var doneLoading = false;
+
+ function onLoaded() {
+ doneLoading = true;
+ var fullscreenButtonElement = document.getElementById("fullscreen");
+ fullscreenButtonElement.disabled = false;
+ }
+
+ var presentation = {
+ statusElement: statusElement,
+ outputElement: outputElement,
+ setOutputVisible: function setOutputVisible(visible) {
+ outputElement.style.display = (visible?"block":"none");
+ },
+ setStatusVisible: function setStatusVisible(visible) {
+ statusElement.style.visibility = (visible?"visible":"hidden");
+ },
+ setStatus: function setStatus(text) {
+ if (!text || text.length === 0) {
+ Presentation.setStatusVisible(false);
+ onLoaded();
+ } else {
+ Presentation.setStatusVisible(true);
+ statusElement.innerHTML = text;
+ }
+ },
+ goFullscreen: function goFullscreen() {
+ if (doneLoading) Module.requestFullScreen(false, false);
+ }
+ };
+
+ if ($GODOT_CONTROLS_ENABLED) { // controls enabled
+ (function() {
+ var controlsElement = document.getElementById("controls");
+ controlsElement.style.visibility="visible";
+ })();
+ }
+
+ if ($GODOT_DEBUG_ENABLED) { // debugging enabled
+ (function() {
+ var outputToggleLabel = document.getElementById("display-output");
+ var outputToggle = document.getElementById("output-toggle");
+
+ outputElement.value = ""; // clear browser cache
+ outputElement.style.display = "block";
+ outputToggle.checked = true;
+ outputToggleLabel.style.display = "inline";
+
+ presentation.print = function print(text) {
+ if (outputElement.value.length !== 0)
+ outputElement.value += "\n";
+ outputElement.value += text;
+ outputElement.scrollTop = outputElement.scrollHeight; // focus on bottom
+ };
+ })();
+ }
+
+ return presentation;
+ })();
+
+ // Emscripten interface
+ var Module = (function() {
+ var print = (function() {
+ if (typeof Presentation.print === "function") {
+ return function print(text) {
+ if (arguments.length > 1)
+ text = Array.prototype.slice.call(arguments).join(" ");
+ console.log(text);
+ Presentation.print(text);
+ };
+ } else {
+ return function print(text) {
+ if (arguments.length > 1)
+ text = Array.prototype.slice.call(arguments).join(" ");
+ console.log(text);
+ };
+ }
+ })();
+
+ var canvas = (function() {
+ var canvasElement = document.getElementById("canvas");
+
+ // As a default initial behavior, pop up an alert when WebGL context is lost. To make your
+ // application robust, you may want to override this behavior before shipping!
+ // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
+ canvasElement.addEventListener("webglcontextlost", function(e) { alert("WebGL context lost. Plase reload the page."); e.preventDefault(); }, false);
+
+ return canvasElement;
+ })();
+
+ var setStatus = (function() {
+ if (typeof Presentation.setStatus === "function")
+ return function setStatus(text) {
+ if (!Module.setStatus.last)
+ Module.setStatus.last = { time: Date.now(), text: "" };
+ if (text === Module.setStatus.text)
+ return;
+ var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
+ var now = Date.now();
+ if (m) {
+ if (now - Date.now() < 30) // if this is a progress update, skip it if too soon
+ return;
+ text = m[1];
+ }
+ Presentation.setStatus(text);
+ };
+ else
+ return function setStatus(text) {
+ if (!Module.setStatus.last)
+ Module.setStatus.last = { time: Date.now(), text: "" };
+ if (text === Module.setStatus.text)
+ return;
+ var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
+ var now = Date.now();
+ if (m) {
+ if (now - Date.now() < 30) // if this is a progress update, skip it if too soon
+ return;
+ text = m[1];
+ }
+ };
+ })();
+
+ return {
+ TOTAL_MEMORY: 268435456,
+ preRun: [],
+ postRun: [],
+ print: print,
+ printErr: function printErr(text) {
+ if (arguments.length > 1)
+ text = Array.prototype.slice.call(arguments).join(" ");
+ if (0) { // XXX disabled for safety `if (typeof dump == "function")`
+ dump(text + "\n"); // fast, straight to the real console
+ } else {
+ console.error(text);
+ }
+ },
+ canvas: canvas,
+ setStatus: setStatus,
+ totalDependencies: 0,
+ monitorRunDependencies: function monitorRunDependencies(left) {
+ this.totalDependencies = Math.max(this.totalDependencies, left);
+ Module.setStatus(left ? "Preparing... (" + (this.totalDependencies-left) + "/" + this.totalDependencies + ")" : "All downloads complete.");
+ }
+ };
+ })();
+
+ Presentation.setStatus("Downloading...");
+
+ window.onerror = function(event) {
+ // TODO: do not warn on ok events like simulating an infinite loop or exitStatus
+ Module.setStatus("Exception thrown, see JavaScript console");
+ Module.setStatus = function(text) {
+ if (text) Module.printErr("[post-exception status] " + text);
+ };
+ };
+ //]]></script>
+ <script type="text/javascript" src="$GODOT_FS"></script>
+ <script>
+ (function() {
+ var memoryInitializer = "$GODOT_MEM";
+ if (typeof Module.locateFile === "function") {
+ memoryInitializer = Module.locateFile(memoryInitializer);
+ } else if (Module.memoryInitializerPrefixURL) {
+ memoryInitializer = Module.memoryInitializerPrefixURL + memoryInitializer;
+ }
+ var xhr = Module.memoryInitializerRequest = new XMLHttpRequest();
+ xhr.open("GET", memoryInitializer, true);
+ xhr.responseType = "arraybuffer";
+ xhr.send(null);
+ })();
+
+ var script = document.createElement("script");
+ script.src = "$GODOT_JS";
+ document.body.appendChild(script);
+ </script>
+</body>
</html>
diff --git a/tools/ios_xcode_template/godot_ios/main.m b/tools/ios_xcode_template/godot_ios/main.m
index 6bb6bc2188..3e4ea5e129 100644
--- a/tools/ios_xcode_template/godot_ios/main.m
+++ b/tools/ios_xcode_template/godot_ios/main.m
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/ios_xcode_template/godot_iosTests/godot_iosTests.m b/tools/ios_xcode_template/godot_iosTests/godot_iosTests.m
index 75e44659e0..d9fac0a250 100644
--- a/tools/ios_xcode_template/godot_iosTests/godot_iosTests.m
+++ b/tools/ios_xcode_template/godot_iosTests/godot_iosTests.m
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/tools/pck/pck_packer.cpp b/tools/pck/pck_packer.cpp
index d398fefb5f..228d37df7c 100644
--- a/tools/pck/pck_packer.cpp
+++ b/tools/pck/pck_packer.cpp
@@ -26,7 +26,7 @@ void PCKPacker::_bind_methods() {
ObjectTypeDB::bind_method(_MD("pck_start","pck_name","alignment"),&PCKPacker::pck_start);
ObjectTypeDB::bind_method(_MD("add_file","pck_path","source_path"),&PCKPacker::add_file);
- ObjectTypeDB::bind_method(_MD("flush"),&PCKPacker::flush);
+ ObjectTypeDB::bind_method(_MD("flush","verbose"),&PCKPacker::flush);
};